본문 바로가기

[Chapter 1] projects 01 : 논리 게이트 구현

(밑바닥부터 만드는 컴퓨팅 시스템 2판,  인사이트(insight), 2023)을 학습하고 개인 학습용으로 정리한 내용입니다.

 

 

 

 

 

1. 목표 : nand2tetris/project/01에 있는 모든 칩(*.hdl)을 구현하고 시뮬레이션 해본다.

 

2. 일반적인 구현 팁

  • 게이트마다 여려가지 방식으로 구현 가능하다. 구현은 단순할수록 좋다. 가능한 한 적은 수의 칩 파트를 사용하도록 노력해보자.
  • 각 칩은 Nand 게이트만으로 구현할 수 있지만, 이미 구현된 조합 게이트를 활용하기를 추천한다.
  • 이 장에서 나온 순서대로 칩을 구현하자
  • Nand 게이트는 기본으로 제공된다고 가정한다. 즉, 별도 구현없이 hdl에서 바로 사용할 수 있다. (HDL 참조)

A B Nand(A, B)
0 0 1
0 1 1
1 0 1
1 1 0

 

 

 

3. 논리 게이트 구현

  • Not.hdl

A Not(A)
0 1
1 0

 

 

Nand 게이트의 입력값이 동일할 때, Not이 된다. (참조 : [Chapter 1] Nand의 표현력, 보조 정리 3)

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Not.hdl
 /**
 * Not gate:
 * out = ((in == 0), 1, 0)
 */
CHIP Not {
    IN in;
    OUT out;

    PARTS:
    Nand(a=in, b=in, out=out);
}

 

  • And.hdl

A B And(A, B)
0 0 0
0 1 0
1 0 0
1 1 1

Nand 게이트의 입력값이 동일할 때, Not을 더하면 And가 된다. (참조 : [Chapter 1] Nand의 표현력, 보조 정리 3)

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/And.hdl
/**
 * And gate:
 * out = (((a == 1) && (b == 1))), 1, 0) 
 */
CHIP And {
    IN a, b;
    OUT out;
    
    PARTS:
    Nand(a=a, b=b, out=v);
    Not(in=v, out=out);
}

 

  • Or.hdl

A B Or(A, B)
0 0 0
0 1 1
1 0 1
1 1 1

Or는 And 와 Not으로 표현할 수 있다. (참조 : [Chapter 1] Nand의 표현력, 보조 정리 2)

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Or.hdl
/**
 * Or gate:
 * out = (((a == 1) || (b == 1))), 1, 0) 
 */
CHIP Or {
    IN a, b;
    OUT out;

    PARTS:
    Not(in=a, out=va);
    Not(in=b, out=vb);
    And(a=va, b=vb, out=ab);
    Not(in=ab, out=out);
}

 

  • Xor.hdl

A B Xor(A, B)
0 0 0
0 1 1
1 0 1
1 1 0

모든 불 함수는 And, Or, Not만으로 표현이 가능하다.  (참조 : [Chapter 1] Nand의 표현력, 보조 정리 1)

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Xor.hdl
/**
 * Exclusive-or gate:
 * out = (((a == 0) & (b = 1)) | ((a == 1) & (b = 0)), 1, 0)
 */
CHIP Xor {
    IN a, b;
    OUT out;

    PARTS:
    Not(in=a, out=va);
    And(a=va, b=b, out=v1);
    Not(in=b, out=vb);
    And(a=a, b=vb, out=v2);
    Or(a=v1, b=v2, out=out);
}

 

  • Mux.hdl

a b sel out
0 0 0 0
0 1 0 0
1 0 0 1
1 1 0 1
0 0 1 0
0 1 1 1
1 0 1 0
1 1 1 1

 

sel out
0 a
1 b

 

 

 

 

 

 

 

모든 불 함수는 And, Or, Not만으로 표현이 가능하다.  (참조 : [Chapter 1] Nand의 표현력, 보조 정리 1)

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Mux.hdl
/** 
 * Multiplexor:
 * out = ((sel == 0), a, b)
 */
CHIP Mux {
    IN a, b, sel;
    OUT out;

    PARTS:
    Not(in=sel, out=ns);
    And(a=a, b=ns, out=v1);
    And(a=sel, b=b, out=v2);
    Or(a=v1, b=v2, out=out);
}

 

  • DMux.hdl

sel (a, b)
0 (in, 0)
1 (0, in)

 

 

 

 

sel이 0일 때, 입력 값을 출력 a로 연결(out=a)하는 게이트와

sel이 1일 때, 입력 값을 출력 b로 연결(out=b)하는 게이트가 있어야 한다.

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/DMux.hdl
/**
 * Demultiplexor:
 * [a, b] = ((sel == 0), [in, 0], [0, in])
 */
CHIP DMux {
    IN in, sel;
    OUT a, b;

    PARTS:
    Not(in=sel, out=ns);
    And(a=in, b=ns, out=a);
    And(a=sel, b=in, out=b);
}

 

  • Not16.hdl
더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Not16.hdl
/**
 * 16-bit Not gate:
 * out[i] = ((in[i] == 0), 1, 0) for i = 0..15 
 */
CHIP Not16 {
    IN in[16];
    OUT out[16];

    PARTS:
    Nand(a=in[0], b=in[0], out=out[0]);
    Nand(a=in[1], b=in[1], out=out[1]);
    Nand(a=in[2], b=in[2], out=out[2]);
    Nand(a=in[3], b=in[3], out=out[3]);
    Nand(a=in[4], b=in[4], out=out[4]);
    Nand(a=in[5], b=in[5], out=out[5]);
    Nand(a=in[6], b=in[6], out=out[6]);
    Nand(a=in[7], b=in[7], out=out[7]);
    Nand(a=in[8], b=in[8], out=out[8]);
    Nand(a=in[9], b=in[9], out=out[9]);
    Nand(a=in[10], b=in[10], out=out[10]);
    Nand(a=in[11], b=in[11], out=out[11]);
    Nand(a=in[12], b=in[12], out=out[12]);
    Nand(a=in[13], b=in[13], out=out[13]);
    Nand(a=in[14], b=in[14], out=out[14]);
    Nand(a=in[15], b=in[15], out=out[15]);
}

 

  • And16.hdl
더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/And16.hdl
/**
 * 16-bit bitwise And gate:
 * out[i] = And(a[i],b[i]) for i = 0..15 
 */
CHIP And16 {
    IN a[16], b[16];
    OUT out[16];

    PARTS:
    Nand(a=a[0], b=b[0], out=v0);
    Not(in=v0, out=out[0]);
    Nand(a=a[1], b=b[1], out=v1);
    Not(in=v1, out=out[1]);
    Nand(a=a[2], b=b[2], out=v2);
    Not(in=v2, out=out[2]);
    Nand(a=a[3], b=b[3], out=v3);
    Not(in=v3, out=out[3]);
    Nand(a=a[4], b=b[4], out=v4);
    Not(in=v4, out=out[4]);
    Nand(a=a[5], b=b[5], out=v5);
    Not(in=v5, out=out[5]);
    Nand(a=a[6], b=b[6], out=v6);
    Not(in=v6, out=out[6]);
    Nand(a=a[7], b=b[7], out=v7);
    Not(in=v7, out=out[7]);
    Nand(a=a[8], b=b[8], out=v8);
    Not(in=v8, out=out[8]);
    Nand(a=a[9], b=b[9], out=v9);
    Not(in=v9, out=out[9]);
    Nand(a=a[10], b=b[10], out=v10);
    Not(in=v10, out=out[10]);
    Nand(a=a[11], b=b[11], out=v11);
    Not(in=v11, out=out[11]);
    Nand(a=a[12], b=b[12], out=v12);
    Not(in=v12, out=out[12]);
    Nand(a=a[13], b=b[13], out=v13);
    Not(in=v13, out=out[13]);
    Nand(a=a[14], b=b[14], out=v14);
    Not(in=v14, out=out[14]);
    Nand(a=a[15], b=b[15], out=v15);
    Not(in=v15, out=out[15]);
}

 

  • Or16.hdl

게이트 순서는 편집하기 편한 순서로 나열했다.

16비트 게이트를 작성해보니, Or 게이트 기본 설계가 비효율적인가? 의구심이 든다.

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Or16.hdl
/**
 * 16-bit bitwise Or gate:
 * out[i] = (a[i] Or b[i]) for i = 0..15 
 */
CHIP Or16 {
    IN a[16], b[16];
    OUT out[16];
    
    PARTS:
    Not(in=a[0], out=a0);
    Not(in=a[1], out=a1);
    Not(in=a[2], out=a2);
    Not(in=a[3], out=a3);
    Not(in=a[4], out=a4);
    Not(in=a[5], out=a5);
    Not(in=a[6], out=a6);
    Not(in=a[7], out=a7);
    Not(in=a[8], out=a8);
    Not(in=a[9], out=a9);
    Not(in=a[10], out=a10);
    Not(in=a[11], out=a11);
    Not(in=a[12], out=a12);
    Not(in=a[13], out=a13);
    Not(in=a[14], out=a14);
    Not(in=a[15], out=a15);
    
    Not(in=b[0], out=b0);
    Not(in=b[1], out=b1);
    Not(in=b[2], out=b2);
    Not(in=b[3], out=b3);
    Not(in=b[4], out=b4);
    Not(in=b[5], out=b5);
    Not(in=b[6], out=b6);
    Not(in=b[7], out=b7);
    Not(in=b[8], out=b8);
    Not(in=b[9], out=b9);
    Not(in=b[10], out=b10);
    Not(in=b[11], out=b11);
    Not(in=b[12], out=b12);
    Not(in=b[13], out=b13);
    Not(in=b[14], out=b14);
    Not(in=b[15], out=b15);
       
    And(a=a0, b=b0, out=ab0);
    And(a=a1, b=b1, out=ab1);
    And(a=a2, b=b2, out=ab2);
    And(a=a3, b=b3, out=ab3);
    And(a=a4, b=b4, out=ab4);
    And(a=a5, b=b5, out=ab5);
    And(a=a6, b=b6, out=ab6);
    And(a=a7, b=b7, out=ab7);
    And(a=a8, b=b8, out=ab8);
    And(a=a9, b=b9, out=ab9);
    And(a=a10, b=b10, out=ab10);
    And(a=a11, b=b11, out=ab11);
    And(a=a12, b=b12, out=ab12);
    And(a=a13, b=b13, out=ab13);
    And(a=a14, b=b14, out=ab14);
    And(a=a15, b=b15, out=ab15);
    
    Not(in=ab0, out=out[0]);
    Not(in=ab1, out=out[1]);
    Not(in=ab2, out=out[2]);
    Not(in=ab3, out=out[3]);
    Not(in=ab4, out=out[4]);
    Not(in=ab5, out=out[5]);
    Not(in=ab6, out=out[6]);
    Not(in=ab7, out=out[7]);
    Not(in=ab8, out=out[8]);
    Not(in=ab9, out=out[9]);
    Not(in=ab10, out=out[10]);
    Not(in=ab11, out=out[11]);
    Not(in=ab12, out=out[12]);
    Not(in=ab13, out=out[13]);
    Not(in=ab14, out=out[14]);
    Not(in=ab15, out=out[15]);
}

 

  • Mux16.hdl
더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Mux16.hdl
/**
 * 16-bit multiplexor: 
 * out[i] = ((sel == 0), a[i], b[i]) for i = 0..15
 */
CHIP Mux16 {
    IN a[16], b[16], sel;
    OUT out[16];
    
    PARTS:
    Not(in=sel, out=ns);
    
    And(a=a[0], b=ns, out=a0);
    And(a=a[1], b=ns, out=a1);
    And(a=a[2], b=ns, out=a2);
    And(a=a[3], b=ns, out=a3);
    And(a=a[4], b=ns, out=a4);
    And(a=a[5], b=ns, out=a5);
    And(a=a[6], b=ns, out=a6);
    And(a=a[7], b=ns, out=a7);
    And(a=a[8], b=ns, out=a8);
    And(a=a[9], b=ns, out=a9);
    And(a=a[10], b=ns, out=a10);
    And(a=a[11], b=ns, out=a11);
    And(a=a[12], b=ns, out=a12);
    And(a=a[13], b=ns, out=a13);
    And(a=a[14], b=ns, out=a14);
    And(a=a[15], b=ns, out=a15);
    
    And(a=sel, b=b[0], out=b0);
    And(a=sel, b=b[1], out=b1);
    And(a=sel, b=b[2], out=b2);
    And(a=sel, b=b[3], out=b3);
    And(a=sel, b=b[4], out=b4);
    And(a=sel, b=b[5], out=b5);
    And(a=sel, b=b[6], out=b6);
    And(a=sel, b=b[7], out=b7);
    And(a=sel, b=b[8], out=b8);
    And(a=sel, b=b[9], out=b9);
    And(a=sel, b=b[10], out=b10);
    And(a=sel, b=b[11], out=b11);
    And(a=sel, b=b[12], out=b12);
    And(a=sel, b=b[13], out=b13);
    And(a=sel, b=b[14], out=b14);
    And(a=sel, b=b[15], out=b15);
    
    Or(a=a0, b=b0, out=out[0]);
    Or(a=a1, b=b1, out=out[1]);
    Or(a=a2, b=b2, out=out[2]);
    Or(a=a3, b=b3, out=out[3]);
    Or(a=a4, b=b4, out=out[4]);
    Or(a=a5, b=b5, out=out[5]);
    Or(a=a6, b=b6, out=out[6]);
    Or(a=a7, b=b7, out=out[7]);
    Or(a=a8, b=b8, out=out[8]);
    Or(a=a9, b=b9, out=out[9]);
    Or(a=a10, b=b10, out=out[10]);
    Or(a=a11, b=b11, out=out[11]);
    Or(a=a12, b=b12, out=out[12]);
    Or(a=a13, b=b13, out=out[13]);
    Or(a=a14, b=b14, out=out[14]);
    Or(a=a15, b=b15, out=out[15]);
}

 

  • Or8Way.hdl

8입력, 1-bit 출력

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Or8Way.hdl
/**
 * 8-way Or gate: 
 * out = in[0] Or in[1] Or ... Or in[7]
 */
CHIP Or8Way {
    IN in[8];
    OUT out;
    
    PARTS:
    Or(a=in[0], b=in[1], out=v1);
    Or(a=v1, b=in[2], out=v2);
    Or(a=v2, b=in[3], out=v3);
    Or(a=v3, b=in[4], out=v4);
    Or(a=v4, b=in[5], out=v5);
    Or(a=v5, b=in[7], out=out);
}

 

  • Mux4Way16.hdl

sel[1] sel[0] out
0 0 a
0 1 b
1 0 c
1 1 d

 

 

 

4-입력, 16-bit 출력

Mux16을 이용해야 한다.

sel-bit 진리표에서 규칙을 찾아야 한다.

'00 → a'도 규칙이지만, 이것은 out이 a,b,c,d로 각각 결정되는 너무 세부적인 규칙이다. ab, cd와 같이 두개 이상씩 묶을 수 있는 규칙을 찾아보자.

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Mux4Way16.hdl
/**
 * 4-way 16-bit multiplexor:
 * out = a if sel == 00
 *       b if sel == 01
 *       c if sel == 10
 *       d if sel == 11
 */
CHIP Mux4Way16 {
    IN a[16], b[16], c[16], d[16], sel[2];
    OUT out[16];
    
    PARTS:
    Mux16(a=a, b=c, sel=sel[1], out=r1);
    Mux16(a=b, b=d, sel=sel[1], out=r2);
    Mux16(a=r1, b=r2, sel=sel[0], out=out);
}

 

  • Mux8Way16.hdl
sel[2] sel[1] sel[0] out
0 0 0 a
0 0 1 b
0 1 0 c
0 1 1 d
1 0 0 e
1 0 1 f
1 1 0 g
1 1 1 h

Mux4Way16 때와 같이, 크게 묶을 수 있는 규칙을 찾아야 한다.

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/Mux8Way16.hdl
/**
 * 8-way 16-bit multiplexor:
 * out = a if sel == 000
 *       b if sel == 001
 *       ...
 *       h if sel == 111
 */
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:
    Mux16(a=a, b=c, sel=sel[1], out=ac);
    Mux16(a=b, b=d, sel=sel[1], out=bd);
    Mux16(a=e, b=g, sel=sel[1], out=eg);
    Mux16(a=f, b=h, sel=sel[1], out=fh);
    Mux16(a=ac, b=bd, sel=sel[0], out=r1);
    Mux16(a=eg, b=fh, sel=sel[0], out=r2);
    Mux16(a=r1, b=r2, sel=sel[2], out=out);
}

 

  • DMux4Way.hdl

Mux4Way16, Mux8Way16 때와 같이, 크게 묶을 수 있는 규칙을 찾아야 한다.

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/DMux4Way.hdl
/**
 * 4-way demultiplexor:
 * [a, b, c, d] = [in, 0, 0, 0] if sel == 00
 *                [0, in, 0, 0] if sel == 01
 *                [0, 0, in, 0] if sel == 10
 *                [0, 0, 0, in] if sel == 11
 */
CHIP DMux4Way {
    IN in, sel[2];
    OUT a, b, c, d;

    PARTS:
    DMux(in=in, sel=sel[1], a=ab, b=cd);
    DMux(in=ab, sel=sel[0], a=a, b=b);
    DMux(in=cd, sel=sel[0], a=c, b=d);
}

 

  • DMux8Way.hdl
sel[2] sel[1] sel[0] out
0 0 0 a
0 0 1 b
0 1 0 c
0 1 1 d
1 0 0 e
1 0 1 f
1 1 0 g
1 1 1 h

Mux4Way16, Mux8Way16, DMux4Way 때와 같이, 크게 묶을 수 있는 규칙을 찾아야 한다.

더보기

// This file is part of http://www.nand2tetris.org
// and the book "The Elements of Computing Systems"
// by Nisan and Schocken, MIT Press.
// File name: projects/01/DMux8Way.hdl
/**
 * 8-way demultiplexor:
 * [a, b, c, d, e, f, g, h] = [in, 0, 0, 0, 0, 0, 0, 0] if sel == 000
 *                            [0, in, 0, 0, 0, 0, 0, 0] if sel == 001
 *                            ...
 *                            [0, 0, 0, 0, 0, 0, 0, in] if sel == 111
 */
CHIP DMux8Way {
    IN in, sel[3];
    OUT a, b, c, d, e, f, g, h;
    
    PARTS:
    DMux(in=in, sel=sel[2], a=abcd, b=efgh);
    DMux(in=abcd, sel=sel[1], a=ab, b=cd);
    DMux(in=efgh, sel=sel[1], a=ef, b=gh);
    DMux(in=ab, sel=sel[0], a=a, b=b);
    DMux(in=cd, sel=sel[0], a=c, b=d);
    DMux(in=ef, sel=sel[0], a=e, b=f);
    DMux(in=gh, sel=sel[0], a=g, b=h);
}