-
NAND to Tetris - 1장: 조합 게이트 실습만들면서 배우기/Nand to Tetris 2021. 8. 1. 01:39
지난 글에서 정의한 게이트 인터페이스들을 하나씩 직접 구현해보자.
Not
Not 게이트는 Nand 게이트 하나만으로 구현할 수 있다. x Nand x는 Not (x And x)이고, x And x는 x와 같으므로 x Nand x는 Not x와 같다.
CHIP Not { IN in; OUT out; PARTS: Nand(a=in, b=in, out=out); }
And
And 게이트는 단순히 Nand 게이트의 결과를 뒤집으면 된다. Not 게이트는 위에서 만든 것을 가져다 쓴다.
CHIP And { IN a, b; OUT out; PARTS: Nand(a=a, b=b, out=aNandb); Not(in=aNandb, out=out); }
Or
드 모르간의 법칙: A Or B = Not (Not A And Not B)을 이용한다. Not과 And 게이트를 이미 만들었으니 Or 게이트도 구현할 수 있다.
CHIP Or { IN a, b; OUT out; PARTS: Not(in=a, out=nota); Not(in=b, out=notb); And(a=nota, b=notb, out=notaandnotb); Not(in=notaandnotb, out=out); }
Xor
Xor 게이트를 정준 표현으로 나타내면 (Not x And y) Or (x And Not y)이다. Not, And, Or 게이트를 모두 만들었으니 Xor 게이트도 만들 수 있다.
CHIP Xor { IN a, b; OUT out; PARTS: Not(in=a, out=nota); Not(in=b, out=notb); And(a=nota, b=b, out=notaandb); And(a=a, b=notb, out=aandnotb); Or(a=notaandb, b=aandnotb, out=out); }
Mux
Mux 는 out이 1이 되는 4개의 행을 Or로 합치는 정준 표현으로도 나타낼 수 있지만, 이것보다 더 간단한 방법으로 구현해보겠다.
(Not sel And x) Or (sel And y)는 sel이 0인 경우엔 오른쪽 항은 항상 0이 되어 무시되고 왼쪽 항은 x가 1일 때 1, 0일 때 0을 반환하므로, 즉 x와 값이 같아진다. 반대로 sel이 1인 경우엔 왼쪽 항은 항상 0이 되어 무시되고 오른쪽 항은 y가 1일 때 1, 0일 때 0을 반환하므로, 즉 y와 값이 같아진다.
CHIP Mux { IN a, b, sel; OUT out; PARTS: Not(in=sel, out=notsel); And(a=a, b=notsel, out=sela); And(a=b, b=sel, out=selb); Or(a=sela, b=selb, out=out); }
Dmux
Dmux는 정준 표현으로 깔끔하게 구현할 수 있다. 출력선 a의 반환 값이 1이 되는 경우는 (Not sel And in)이고, 출력선 b의 반환 값이 1이 되는 경우는 (sel And in)이다.
CHIP DMux { IN in, sel; OUT a, b; PARTS: Not(in=sel, out=notsel); And(a=in, b=notsel, out=a); And(a=in, b=sel, out=b); }
Not16, And16, Or16, Mux16
이 게이트들은 단순히 0번부터 15번 비트까지 총 16개의 1비트 게이트를 구성하면 된다. 코드가 단순하고 길기 때문에 생략하겠다.
Or8Way
두 비트씩 Or 게이트를 만들어 나가면 된다.
CHIP Or8Way { IN in[8]; OUT out; PARTS: Or(a=in[0], b=in[1], out=out1); Or(a=out1, b=in[2], out=out2); Or(a=out2, b=in[3], out=out3); Or(a=out3, b=in[4], out=out4); Or(a=out4, b=in[5], out=out5); Or(a=out5, b=in[6], out=out6); Or(a=out6, b=in[7], out=out); }
Mux4Way16
우선은 (a, b, sel[0])와 (c, d, sel[0]) 쌍에 대해서 각각 Mux16을 계산하여 out1, out2으로 반환해보자. sel[0]의 값에 따라 out1과 out2는 각각 a 또는 b, c 또는 d의 값을 가진다. (sel[0]이 0이라면 out1 = a, out2 = c, sel[0]이 1이라면 out1 = b, out2 = d) 그리고 (out1, out2, sel[1])에 대해 다시 Mux16을 계산하여 out으로 반환한다. 그러면 sel[1]의 값에 따라 out1과 out2 중에 적절한 값이 반환될 것이다. (sel[1]이 0이면 out = out1, sel[1]이 1이라면 out = out2)
CHIP Mux4Way16 { IN a[16], b[16], c[16], d[16], sel[2]; OUT out[16]; PARTS: Mux16(a=a, b=b, sel=sel[0], out=out0); Mux16(a=c, b=d, sel=sel[0], out=out1); Mux16(a=out0, b=out1, sel=sel[1], out=out); }
Mux8Way16
Mux16으로 Mux4Way16을 만들었던 것 처럼 Mux4Way16 으로 만들 수 있다.
CHIP Mux8Way16 { IN a[16], b[16], c[16], d[16], e[16], f[16], g[16], h[16], sel[3]; OUT out[16]; PARTS: Mux4Way16(a=a, b=b, c=c, d=d, sel=sel[0..1], out=out0); Mux4Way16(a=e, b=f, c=g, d=h, sel=sel[0..1], out=out1); Mux16(a=out0, b=out1, sel=sel[2], out=out); }
DMux4Way
DMux4Way 구현은 Mux4Way16의 구현과 반대 순서이다.
CHIP DMux4Way { IN in, sel[2]; OUT a, b, c, d; PARTS: // sel[1]이 0이면 in1 = in, in2 = 0 이고 // sel[1]이 1이면 in1 = 0, in2 = in DMux(in=in, sel=sel[1], a=in1, b=in2); // sel[0] 값에 따라 다시 DMux DMux(in=in1, sel=sel[0], a=a, b=b); DMux(in=in2, sel=sel[0], a=c, b=d); }
DMux8Way
DMux로 DMux4Way를 만들었던 것 처럼 DMux4Way로 만들 수 있다.
CHIP DMux8Way { IN in, sel[3]; OUT a, b, c, d, e, f, g, h; PARTS: DMux(in=in, sel=sel[2], a=in1, b=in2); DMux4Way(in=in1, sel=sel[0..1], a=a, b=b, c=c, d=d); DMux4Way(in=in2, sel=sel[0..1], a=e, b=f, c=g, d=h); }
마무리
1비트 Nand 게이트 하나에서 시작하여 총 15개의 조합 회로를 직접 구현해봤다. 아직까지는 간단한 불 연산밖에 안되지만, 이번에 만든 것들을 사용하여 다음 장에서는 이진 덧셈을 하는 회로를 만들 예정이다.
'만들면서 배우기 > Nand to Tetris' 카테고리의 다른 글
NAND to Tetris - 3장: 순차 게이트 (1) 2021.08.04 NAND to Tetris - 2장: Adder, Inc, ALU 실습 (0) 2021.08.03 NAND to Tetris - 2장: Adder, Inc, ALU (0) 2021.08.03 NAND to Tetris - 1장: 조합 게이트 (0) 2021.07.31 NAND to Tetris - 서론 (0) 2021.07.31