はじめに
これは、「コンピュータシステムの理論と実装」(以下「Nand2Tetris」という)の第5章 コンピュータアーキテクチャのプロジェクトに対するレポートである。
Qiitaでは、画像の利用に制約があるため、論理回路図など掲載することは省いている。
プロジェクトに対するレポート
目標
- 1章から3章で作成した論理回路を使い、Hackコンピュータの論理回路を作成する。
材料
- Nand2Tetrisで定義しているHDL言語
- ハードウェアエミュレータ
実装
Memory
Hackの最終的なメモリ回路である。DMux8Wayを使うだけの分岐がないためDMuxで分岐している。
キーボードとの分岐をアドレスの13ビットのみで行うとRAM16Kでも不具合が出たため、14ビット目とAndをとっている。
// Put your code here:
DMux(in=load, sel=address[14], a=w1, b=w2);
And(a=address[14], b=address[13], out=w3);
DMux(in=w2, sel=w3, a=w4, b=w5);
RAM16K(in=in, load=w1, address=address[0..13], out=w6);
Screen(in=in, load=w4, address=address[0..12], out=w7);
Keyboard(out=w8); //w5
Mux16(a=w7, b=w8, sel=w3, out=w9);
Mux16(a=w6, b=w9, sel=address[14], out=out);
ハードウェアエミュレータを使い、Memory.Tstスクリプトを動作させると、途中キー入力を行った後、Comparison ended successfullyと表示された。
CPU
HackのCPU回路である。CPUの回路図はすでに与えられているため、それをベースに作成する。
デコードフェーズは、CPUの回路図中のcのところに入るフラグの振り分けについて必要なものを解読している。
実行フェーズは、CPUの回路図のとおりに組み立てている。
フェッチフェーズは、JMP命令のときのALU出力フラグとのAndチェックを行う。大なりのフラグはないため、ALU出力フラグがともにゼロのときとする。
// Put your code here:
//decode
DMux(in=true, sel=instruction[15], a=w1, b=w2); //i bit w1: A_Inst w2: C_I\
nst
And(a=w2, b=instruction[12], out=w3);
And(a=w2, b=instruction[11], out=w4); //zx
And(a=w2, b=instruction[10], out=w5); //nx
And(a=w2, b=instruction[9], out=w6); //zy
And(a=w2, b=instruction[8], out=w7); //ny
And(a=w2, b=instruction[7], out=w8); //f
And(a=w2, b=instruction[6], out=w9); //no
And(a=w2, b=instruction[5], out=w10);
Or(a=w1, b=w10, out=w11); // load ARegister
And(a=w2, b=instruction[4], out=w12); //load DRegister
And(a=w2, b=instruction[3], out=writeM); //writeM
And(a=w2, b=instruction[2], out=w13); // out < 0
And(a=w2, b=instruction[1], out=w14); // out = 0
And(a=w2, b=instruction[0], out=w15); // out > 0
//execute
DRegister(in=w20, load=w12, out=w16);
Mux16(a=instruction, b=w20, sel=instruction[15], out=w17);
ARegister(in=w17, load=w11 ,out=w18, out[0..14]=addressM);
Mux16(a=w18, b=inM, sel=w3, out=w19);
ALU(x=w16, y=w19, zx=w4, nx=w5, zy=w6, ny=w7, f=w8, no=w9, out=w20, zr=w21\
, ng=w22, out=outM);
//fetch
DMux4Way(in=true, sel[0]=w21, sel[1]=w22, a=w23, b=w24, c=w25, d=w26);
And(a=w15, b=w23, out=w27); // out > 0
And(a=w14, b=w24, out=w28);// out = 0
And(a=w13, b=w25, out=w29);// out < 0
Or(a=w27, b=w28, out=w30);
Or(a=w29, b=w30, out=w31);
PC(in=w18, inc=true , load=w31, reset=reset , out[0..14]=pc);
ハードウェアエミュレータを使い、CPU.Tstスクリプトを動作させると、Comparison ended successfullyと表示された。
Computer
最後に、メモリとCPUを接続しコンピュータを作成する。
// Put your code here:
ROM32K(address=w5 ,out=w1);
CPU(inM=w6, instruction=w1, reset=reset, outM=w2, writeM=w3, addressM=w4, \
pc=w5);
Memory(in=w2, load=w3, address=w4, out=w6);
ハードウェアエミュレータを使い、各スクリプトを動作させると、Comparison ended successfullyと表示された。実行時間は以下の通りである。
第4章で作成したプログラムは、アセンブラ作成後確認する。
スクリプト名 | 実行時間 |
---|---|
ComputerAdd | 13 |
ComputerMax | 25 |
ComputerRect | 63 |