Nand2Tetris — Chapter 5
Hack Computer Architecture
// Memory
//Input: in[16], load, address[15]
//output: out[16]
//movement:
// address[0..13] : RAM16K
//address[14]=0: RAM area
// address[14]=1, address[13]=0 : Screen
// address[14]=1, address[13]=1 : Keyboard
//Keyboard is read-only, so no load is attached.
CHIP Memory {
IN in[16], load, address[15];
OUT out[16];
PARTS:
DMux4Way(in=load, sel=address[13..14],
a=loadRamA, b=loadRamB, c=loadScreen, d=ignore);
Or(a=loadRamA, b=loadRamB, out=loadRam);
RAM16K(in=in, load=loadRam, address=address[0..13], out=ramOut);
Screen(in=in, load=loadScreen, address=address[0..12], out=screenOut);
Keyboard(out=keyboardOut);
Mux4Way16(a=ramOut, b=ramOut, c=screenOut, d=keyboardOut,
sel=address[13..14], out=out);
}
// CPU
//Input: inM[16], instruction[16], reset
//output of power:
//outM[16]: Value to write to memory
//writeM: Whether to write value to M
//addressM: Memory address to access (A register)
//pc: next instruction address
//movement:
//If it is an A-instruction, the instruction value is stored in the A register.
//If it is a C-instruction, the ALU and registers are controlled according to the comp, dest, and jump fields.
CHIP CPU {
IN inM[16], instruction[16], reset;
OUT outM[16], writeM, addressM[15], pc[15];
PARTS:
//Command type determination
Not(in=instruction[15], out=isA);
And(a=instruction[15], b=true, out=isC);
//A register input selection
Mux16(a=instruction, b=aluOut, sel=isC, out=aInput);
And(a=isC, b=instruction[5], out=loadAFromC);
Or(a=isA, b=loadAFromC, out=loadA);
ARegister(in=aInput, load=loadA, out=aOut, out[0..14]=addressM);
//D register
And(a=isC, b=instruction[4], out=loadD);
DRegister(in=aluOut, load=loadD, out=dOut);
//Selection of y input of ALU: A if a-bit is 0, M if a-bit is 1
Mux16(a=aOut, b=inM, sel=instruction[12], out=aluY);
ALU(x=dOut, y=aluY,
zx=instruction[11],
nx=instruction[10],
zy=instruction[9],
ny=instruction[8],
f=instruction[7],
no=instruction[6],
out=aluOut,
out=outM,
zr=zr,
ng=ng);
//M bit of dest
And(a=isC, b=instruction[3], out=writeM);
//jump calculation
Not(in=zr, out=notZr);
Not(in=ng, out=notNg);
And(a=notZr, b=notNg, out=positive);
And(a=instruction[0], b=positive, out=jgt);
And(a=instruction[1], b=zr, out=jeq);
And(a=instruction[2], b=ng, out=jlt);
Or(a=jgt, b=jeq, out=jump1);
Or(a=jump1, b=jlt, out=jumpCond);
And(a=isC, b=jumpCond, out=pcLoad);
PC(in=aOut, load=pcLoad, inc=true, reset=reset, out[0..14]=pc);
}
// Computer
//Input: reset
//Output: None
//movement:
//Read instructions from ROM32K,
//CPU reads and writes memory,
//PC determines next instruction address
CHIP Computer {
IN reset;
PARTS:
ROM32K(address=pc, out=instruction);
CPU(inM=memOut, instruction=instruction, reset=reset,
outM=outM, writeM=writeM, addressM=addressM, pc=pc);
Memory(in=outM, load=writeM, address=addressM, out=memOut);
}