ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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개의 조합 회로를 직접 구현해봤다. 아직까지는 간단한 불 연산밖에 안되지만, 이번에 만든 것들을 사용하여 다음 장에서는 이진 덧셈을 하는 회로를 만들 예정이다. 

    댓글

Designed by Tistory.