// This file is part of www.nand2tetris.org // and the book "The Elements of Computing Systems" // by Nisan and Schocken, MIT Press. // File name: projects/5/CPU.hdl /** * The Hack Central Processing unit (CPU). * Parses the binary code in the instruction input and executes it according to the * Hack machine language specification. In the case of a C-instruction, computes the * function specified by the instruction. If the instruction specifies to read a memory * value, the inM input is expected to contain this value. If the instruction specifies * to write a value to the memory, sets the outM output to this value, sets the addressM * output to the target address, and asserts the writeM output (when writeM = 0, any * value may appear in outM). * If the reset input is 0, computes the address of the next instruction and sets the * pc output to that value. If the reset input is 1, sets pc to 0. * Note: The outM and writeM outputs are combinational: they are affected by the * instruction's execution during the current cycle. The addressM and pc outputs are * clocked: although they are affected by the instruction's execution, they commit to * their new values only in the next cycle. */ CHIP CPU { IN inM[16], // M value input (M = contents of RAM[A]) instruction[16], // Instruction for execution reset; // Signals whether to re-start the current // program (reset==1) or continue executing // the current program (reset==0). OUT outM[16], // M value output writeM, // Write to M? addressM[15], // Address in data memory (of M) pc[15]; // address of next instruction PARTS: // Instructions. // Decode the instruction bit. // i xx a cccccc ddd jjj // For C-Instruction the byte is stored as i(opcode) xx(notUsed) a cccccc(a/c = comp) ddd(destination) jjj(jump) // i xxxxxxxxxxxxxxx // For A-Instruction the i(opcode) is 0 and the rest is the 16(15)-bit value that is stored there. // Decode Instruction Not(in=instruction[15], out=isAInstruction); // Flip it and if 1 it's an A Instruction And(a=instruction[15], b=true, out=isCInstruction); // Check it with an And static true to check if both 1 then it's C instruction. // Don't need decoding for the rest when A instruction. // Just use instruction because instruction[15] will always be 0 // Decode C & Create Wires // 1xA And(a=instruction[12], b=true , out=a1); // 6xC And(a=instruction[11], b=true , out=c1); And(a=instruction[10], b=true , out=c2); And(a=instruction[9], b=true , out=c3); And(a=instruction[8], b=true , out=c4); And(a=instruction[7], b=true , out=c5); And(a=instruction[6], b=true , out=c6); // 3xD And(a=instruction[5], b=true , out=d1); And(a=instruction[4], b=true , out=d2); And(a=instruction[3], b=true , out=d3); // 3xJ And(a=instruction[2], b=true , out=j1); And(a=instruction[1], b=true , out=j2); And(a=instruction[0], b=true , out=j3); // aluOut is not made yet // A Register // Should Load from ALU if And(a=isCInstruction, b=d1, out=loadAFromALU); Mux16(a=instruction, b=aluOut, sel=loadAFromALU,out=aRegIn); Or(a=isAInstruction, b=loadAFromALU, out=loadA); Register(in=aRegIn, load=loadA, out=aRegOut); // D Register And(a=isCInstruction, b=d2, out=loadD); Register(in=aluOut, load=loadD, out=dRegOut); // a - instruction12 - a1 // a=0 → use A register // a=1 → use M (inM from memory) // ALU Mux16(a=aRegOut, b=inM , sel=a1 , out=aluYin); ALU(x=dRegOut, y=aluYin, zx=c1, nx=c2, zy=c3, ny=c4 , f=c5 , no=c6 , out=aluOut , zr=aluZrOut , ng=aluNgOut ); }