// 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 out=aRegOut, out[0..14]=addressM ); // 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 , zr=aluZrOut, ng=aluNgOut, // Out out=aluOut, out=outM ); // IN in[16], reset, load, inc; // OUT out[16]; // inc almost all the time. // only when not load. load = jump // JGT // not negative and not zero Not(in=aluNgOut, out=notAluNgOut); Not(in=aluZrOut, out=notAluZrOut); And(a=notAluZrOut, b=notAluNgOut , out=isPositive); And(a=isPositive, b=j3, out=shouldJumpJGT); // JEQ // Jump if zero can be checked it zr And(a=aluZrOut, b=j2 , out=shouldJumpJEQ); // JLT // Jump if less than 0 And(a=aluNgOut, b=j1, out=shouldJumpJLT); // Should Jump Or(a=shouldJumpJGT, b=shouldJumpJEQ , out=shouldJumpJGTJEQ); Or(a=shouldJumpJGTJEQ , b= shouldJumpJLT, out=hasJumpInstruction ); // And C instruction And(a=hasJumpInstruction, b=isCInstruction , out=shouldJump); //Inc Not(in=shouldJump, out=shouldIncrement); PC(in=aRegOut, load=shouldJump, inc=shouldIncrement, reset=reset , out[0..14]=pc); // Out And(a=isCInstruction, b=d3 , out=writeM); }