Nand2Tetris — 第2章
ブール算術とALU
//1ビット半加算器 (Half Adder)
//入力:a、b(1ビット)
//出力: sum (a+bのLSB)、carry (a+bのMSB)
//動作: sum = a XOR b, carry = a AND b
CHIP HalfAdder {
IN a, b;
OUT sum, // Right bit of a + b
carry; // Left bit of a + b
PARTS:
Xor(a=a, b=b, out=sum);
And(a=a, b=b, out=carry);
}
//1ビット全加算器 (Full Adder)
//入力:a、b、c(1ビット入力+桁上げ)
//出力: sum (a+b+cのLSB)、carry (a+b+cのMSB)
//アクション:(a + b)を最初に計算した後、結果にcを加える
CHIP FullAdder {
IN a, b, c;
OUT sum, // Right bit of a + b + c
carry; // Left bit of a + b + c
PARTS:
//最初の HalfAdder: a + b 計算
HalfAdder(a=a, b=b, sum=sum1, carry=carry1);
//2番目のHalfAdder:sum1 + cの計算
HalfAdder(a=sum1, b=c, sum=sum, carry=carry2);
//最終キャリー:carry1 OR carry2
Or(a=carry1, b=carry2, out=carry);
}
//16-bit加算器(リップルキャリー方式)
//入力: a[16], b[16] (16 ビット数, 2 の補数表現)
//出力: out[16] (a + b の結果、最上位キャリーは無視)
//動作:0番目はHalfAdder、1~15番目はFullAdderを使用
CHIP Add16 {
IN a[16], b[16];
OUT out[16];
PARTS:
//ビット0:入力キャリーなし
HalfAdder(a=a[0], b=b[0],
sum=out[0], carry=carry1);
//ビット1〜15:前のステップのキャリー入力を受信
FullAdder(a=a[1], b=b[1], c=carry1,
sum=out[1], carry=carry2);
FullAdder(a=a[2], b=b[2], c=carry2,
sum=out[2], carry=carry3);
FullAdder(a=a[3], b=b[3], c=carry3,
sum=out[3], carry=carry4);
FullAdder(a=a[4], b=b[4], c=carry4,
sum=out[4], carry=carry5);
FullAdder(a=a[5], b=b[5], c=carry5,
sum=out[5], carry=carry6);
FullAdder(a=a[6], b=b[6], c=carry6,
sum=out[6], carry=carry7);
FullAdder(a=a[7], b=b[7], c=carry7,
sum=out[7], carry=carry8);
FullAdder(a=a[8], b=b[8], c=carry8,
sum=out[8], carry=carry9);
FullAdder(a=a[9], b=b[9], c=carry9,
sum=out[9], carry=carry10);
FullAdder(a=a[10], b=b[10], c=carry10,
sum=out[10], carry=carry11);
FullAdder(a=a[11], b=b[11], c=carry11,
sum=out[11], carry=carry12);
FullAdder(a=a[12], b=b[12], c=carry12,
sum=out[12], carry=carry13);
FullAdder(a=a[13], b=b[13], c=carry13,
sum=out[13], carry=carry14);
FullAdder(a=a[14], b=b[14], c=carry14,
sum=out[14], carry=carry15);
FullAdder(a=a[15], b=b[15], c=carry15,
sum=out[15]);
}
//16ビットインクリメント
//入力: in[16]
//出力:in + 1の結果
//アクション:Add16を使用してinに1を追加する
CHIP Inc16 {
IN in[16];
OUT out[16];
PARTS:
//in + 1計算(1を2進数として:b [0] = 1、残り= 0)
Add16(a=in,
b[0]=true, b[1]=false, b[2]=false, b[3]=false,
b[4]=false, b[5]=false, b[6]=false, b[7]=false,
b[8]=false, b[9]=false, b[10]=false, b[11]=false,
b[12]=false, b[13]=false, b[14]=false, b[15]=false,
out=out);
}
//ALU(算術論理演算装置 - Arithmetic Logic Unit)
//入力: x[16], y[16] (16 ビット入力)
//zx、nx、zy、ny、f、no(制御信号)
//出力: out[16] (演算結果)
//zr(out==0の場合は1、または0)
//ng(out <0の場合1、または0)
//
//動作フロー:
//ステップ1:zx = 1の場合x = 0、nx = 1の場合x = NOT(x)
//ステップ2:zy = 1の場合y = 0、ny = 1の場合y = NOT(y)
//ステップ3:f = 1の場合はout = x + y(Add 16)、f = 0の場合はout = x&y(And 16)
//ステップ4:no = 1の場合はout = NOT(out)
//ステップ5:zrとngフラグを計算する
CHIP ALU {
IN
x[16], y[16], // 16-bit inputs
zx, // zero x?
nx, // negate x?
zy, // zero y?
ny, // negate y?
f, // (x+y) or (x&y)?
no; // negate output?
OUT
out[16], // 16-bit output
zr, // is out == 0?
ng; // is out < 0?
PARTS:
//ステップ1:x前処理(zero、negate)
Mux16(a=x, b=false, sel=zx, out=xZero);
Not16(in=xZero, out=xNot);
Mux16(a=xZero, b=xNot, sel=nx, out=xProc);
//ステップ2:y前処理(zero、negate)
Mux16(a=y, b=false, sel=zy, out=yZero);
Not16(in=yZero, out=yNot);
Mux16(a=yZero, b=yNot, sel=ny, out=yProc);
//ステップ3:演算を選択する(ADD or AND)
Add16(a=xProc, b=yProc, out=addRes);
And16(a=xProc, b=yProc, out=andRes);
Mux16(a=andRes, b=addRes, sel=f, out=fRes);
//ステップ4:出力後処理(negate)+フラグ
Not16(in=fRes, out=fNot);
Mux16(a=fRes, b=fNot, sel=no,
out=out, out[15]=ng, out[0..7]=outLow, out[8..15]=outHigh);
//ステップ5:zrフラグを計算する(すべてのビットのOR、その後NOT)
Or8Way(in=outLow, out=orLow);
Or8Way(in=outHigh, out=orHigh);
Or(a=orLow, b=orHigh, out=orFinal);
Not(in=orFinal, out=zr);
}