본문 바로가기

[Chapter 2] project 02

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

 

 

 

 

 

1. 목표 : 반가산기, 전가산기, 가산기, 증분기, ALU 구현

 

2. 구현 팁

  • 1장에서 설명한 게이트들을 활용하면 만들 수 있다.
  • project 01을 성공적으로 구현했더라도, 내장형 칩 사용을 권장한다. (내장형 칩을 사용하기 위해서는 project/02 경로에, project 01에서 만든 *.hdl 파일을 넣지 않으면 된다.)
  • 이 장에서 나온 순서대로 구현한다. (반가신기 → 전가산기 → 가산기 → 증분기 → ALU)

3. 구현

  • 반가산기 HalfAdder.hdl

in out
a b carry sum
0 0 0 0
0 1 0 1
1 0 0 1
1 1 1 0

 

sum(a,b)와 carry(a,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/02/HalfAdder.hdl
/**
 * Computes the sum of two bits.
 */
CHIP HalfAdder {
    IN a, b;    // 1-bit inputs
    OUT sum,    // Right bit of a + b 
        carry;  // Left bit of a + b
    
    PARTS:
    And(a=a, b=b, out=carry);
    Xor(a=a, b=b, out=sum);
}

 

 

 

  • 전가산기 FullAdder.hdl

a b c carry sum
0 0 0 0 0
0 0 1 0 1
0 1 0 0 1
0 1 1 1 0
1 0 0 0 1
1 0 1 1 0
1 1 0 1 0
1 1 1 1 1

 

반가산기 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/02/FullAdder.hdl
/**
 * Computes the sum of three bits.
 */
CHIP FullAdder {
    IN a, b, c;  // 1-bit inputs
    OUT sum,     // Right bit of a + b + c
        carry;   // Left bit of a + b + c
    
    PARTS:
    HalfAdder(a=a, b=b, carry=c1, sum=s1);
    HalfAdder(a=c, b=s1, carry=c2, sum=sum);
    Or(a=c1, b=c2, out=carry);
}

 

 

 

  • 가산기 Add.hdl

  0 1 0    
  1 0 1 1 a
... 0 0 1 0 b
... 1 1 0 1 out

 

 

더보기

// 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/02/Adder16.hdl
/**
 * 16-bit adder: Adds two 16-bit two's complement values.
 * The most significant carry bit is ignored.
 */
CHIP Add16 {
    IN a[16], b[16];
    OUT out[16];
    
    PARTS:
    HalfAdder(a=a[0], b=b[0], carry=c0, sum=out[0]);
    FullAdder(a=a[1], b=b[1], c=c0, carry=c1, sum=out[1]);
    FullAdder(a=a[2], b=b[2], c=c1, carry=c2, sum=out[2]);
    FullAdder(a=a[3], b=b[3], c=c2, carry=c3, sum=out[3]);
    FullAdder(a=a[4], b=b[4], c=c3, carry=c4, sum=out[4]);
    FullAdder(a=a[5], b=b[5], c=c4, carry=c5, sum=out[5]);
    FullAdder(a=a[6], b=b[6], c=c5, carry=c6, sum=out[6]);
    FullAdder(a=a[7], b=b[7], c=c6, carry=c7, sum=out[7]);
    FullAdder(a=a[8], b=b[8], c=c7, carry=c8, sum=out[8]);
    FullAdder(a=a[9], b=b[9], c=c8, carry=c9, sum=out[9]);
    FullAdder(a=a[10], b=b[10], c=c9, carry=c10, sum=out[10]);
    FullAdder(a=a[11], b=b[11], c=c10, carry=c11, sum=out[11]);
    FullAdder(a=a[12], b=b[12], c=c11, carry=c12, sum=out[12]);
    FullAdder(a=a[13], b=b[13], c=c12, carry=c13, sum=out[13]);
    FullAdder(a=a[14], b=b[14], c=c13, carry=c14, sum=out[14]);
    FullAdder(a=a[15], b=b[15], c=c14, carry=c15, sum=out[15]);
}

 

 

 

  • 증분기 inc16.hdl

+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/02/Inc16.hdl
/**
 * 16-bit incrementer:
 * out = in + 1
 */
CHIP Inc16 {
    IN in[16];
    OUT out[16];
    
    PARTS:
    Not(in=in[0], out=n0);
    Or(a=in[0], b=n0, out=p1);
    HalfAdder(a=in[0], b=p1, sum=out[0], carry=c0);
    FullAdder(a=in[1], b=c0, sum=out[1], carry=c1);
    FullAdder(a=in[2], b=c1, sum=out[2], carry=c2);
    FullAdder(a=in[3], b=c2, sum=out[3], carry=c3);
    FullAdder(a=in[4], b=c3, sum=out[4], carry=c4);
    FullAdder(a=in[5], b=c4, sum=out[5], carry=c5);
    FullAdder(a=in[6], b=c5, sum=out[6], carry=c6);
    FullAdder(a=in[7], b=c6, sum=out[7], carry=c7);
    FullAdder(a=in[8], b=c7, sum=out[8], carry=c8);
    FullAdder(a=in[9], b=c8, sum=out[9], carry=c9);
    FullAdder(a=in[10], b=c9, sum=out[10], carry=c10);
    FullAdder(a=in[11], b=c10, sum=out[11], carry=c11);
    FullAdder(a=in[12], b=c11, sum=out[12], carry=c12);
    FullAdder(a=in[13], b=c12, sum=out[13], carry=c13);
    FullAdder(a=in[14], b=c13, sum=out[14], carry=c14);
    FullAdder(a=in[15], b=c14, sum=out[15], carry=c15);
}

 

 

 

  • 산술 논리 장치 ALU.hdl

  

왼쪽에서 오른쪽으로 연산을 수행한다. zx → nx → zy → ny → f → no → out (결과출력)
x 입력이 미리 설정됨 y 입력이 미리 설정됨 + 또는 &, 계산 출력이
나중에
설정됨
ALU
출력 결과
if zx then x=0 if nx then x=!x if zy then y=0 if ny then y=!y if f then
out=x+y
else out=x&y
if no then
out=!out
out(x, y) =
zx nx zy ny f no out
1 0 1 0 1 0 0
1 1 1 1 1 1 1
1 1 1 0 1 0 -1
0 0 1 1 0 0 x
1 1 0 0 0 0 y
0 0 1 1 0 1 !x
1 1 0 0 0 1 !y
0 0 1 1 1 1 -x
1 1 0 0 1 1 -y
0 1 1 1 1 1 x+1
1 1 0 1 1 1 y+1
0 0 1 1 1 0 x-1
1 1 0 0 1 0 y-1
0 0 0 0 1 0 x+y
0 1 0 0 1 1 x-y
0 0 0 1 1 1 y-x
0 0 0 0 0 0 x&y
0 1 0 1 0 1 x|y

 

기본 논리 게이트를 이용해서 제어 비트 동작을 구현한다.

제어 비트는 순서대로 구현한다. ( zx → nx → zy → ny → f → no → out → zr/ng)

더보기

// 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/02/ALU.hdl
/**
 * ALU (Arithmetic Logic Unit):
 * Computes out = one of the following functions:
 *                0, 1, -1,
 *                x, y, !x, !y, -x, -y,
 *                x + 1, y + 1, x - 1, y - 1,
 *                x + y, x - y, y - x,
 *                x & y, x | y
 * on the 16-bit inputs x, y,
 * according to the input bits zx, nx, zy, ny, f, no.
 * In addition, computes the output bits:
 * zr = (out == 0, 1, 0)
 * ng = (out < 0,  1, 0)
 */
// Implementation: Manipulates the x and y inputs
// and operates on the resulting values, as follows:
// if (zx == 1) sets x = 0        // 16-bit constant
// if (nx == 1) sets x = !x       // bitwise not
// if (zy == 1) sets y = 0        // 16-bit constant
// if (ny == 1) sets y = !y       // bitwise not
// if (f == 1)  sets out = x + y  // integer 2's complement addition
// if (f == 0)  sets out = x & y  // bitwise and
// if (no == 1) sets out = !out   // bitwise not
CHIP ALU {
    IN  
        x[16], y[16],  // 16-bit inputs        
        zx, // zero the x input?
        nx, // negate the x input?
        zy, // zero the y input?
        ny, // negate the y input?
        f,  // compute (out = x + y) or (out = x & y)?
        no; // negate the out output?
    OUT 
        out[16], // 16-bit output
        zr,      // (out == 0, 1, 0)
        ng;      // (out < 0,  1, 0)
    
    PARTS:
    
    //process zx
    Mux16(a=x, b[0..15]=false, sel=zx, out=rzx);
    
    //process nx
    Not16(in=rzx, out=nrzx);
    Mux16(a=rzx, b=nrzx, sel=nx, out=rx);
    
    //process zy
    Mux16(a=y, b[0..15]=false, sel=zy, out=rzy);
    
    //process ny
    Not16(in=rzy, out=nrzy);
    Mux16(a=rzy, b=nrzy, sel=ny, out=ry);
    
    //process f
    Add16(a=rx, b=ry, out=xplusy);
    And16(a=rx, b=ry, out=xny);
    Mux16(a=xny, b=xplusy, sel=f, out=rf);
    
    //process no
    Not16(in=rf, out=nrf);
    Mux16(a=rf, b=nrf, sel=no, out=out, out[15]=msb, out[0..7]=lo, out[8..15]=ho);
    
    //for zr
    Or8Way(in=lo, out=rlo);
    Or8Way(in=ho, out=rho);
    Or(a=rlo, b=rho, out=ro);
    Mux(a=true, b=false, sel=ro, out=zr);
    
    //for ng
    Mux(a=false, b=true, sel=msb, out=ng);
}