// 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/05/CPU.hdl /** * The Hack CPU (Central Processing unit), consisting of an ALU, * two registers named A and D, and a program counter named PC. * The CPU is designed to fetch and execute instructions written in * the Hack machine language. In particular, functions as follows: * Executes the inputted instruction according to the Hack machine * language specification. The D and A in the language specification * refer to CPU-resident registers, while M refers to the external * memory location addressed by A, i.e. to Memory[A]. The inM input * holds the value of this location. If the current instruction needs * to write a value to M, the value is placed in outM, the address * of the target location is placed in the addressM output, and the * writeM control bit is asserted. (When writeM==0, any value may * appear in outM). The outM and writeM outputs are combinational: * they are affected instantaneously by the execution of the current * instruction. The addressM and pc outputs are clocked: although they * are affected by the execution of the current instruction, they commit * to their new values only in the next time step. If reset==1 then the * CPU jumps to address 0 (i.e. pc is set to 0 in next time step) rather * than to the address resulting from executing the current instruction. */ 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: Mux16(a=instruction ,b=ALUout ,sel=instruction[15] ,out=outToAreg ); ARegister(in=outToAreg ,load=loadAreg ,out=outAreg,out[0..14]=addressM ); DRegister(in=ALUout ,load=loadDreg ,out=outDreg ); Mux16(a=outAreg ,b=inM ,sel=instruction[12] ,out=outToALU ); ALU(x=outDreg ,y=outToALU ,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 ); And(a=instruction[3],b=instruction[15],out=writeM); //when to load A reg Not(in=instruction[5],out=notd5); Nand(a=instruction[15],b=notd5,out=loadAreg); Not(in=ng,out=notNg); Not(in=zr,out=notZr); //when to load D reg And(a=instruction[4],b=instruction[15],out=loadDreg); //checking if instruction is a or c before jump decision is made And(a=instruction[2],b=instruction[15],out=J1); And(a=instruction[1],b=instruction[15],out=J2); And(a=instruction[0],b=instruction[15],out=J3); //NULL Nand(a=J1,b=J2,out=NandJ1J2); Nand(a=NandJ1J2,b=J3,out=NoJump); //JGT And(a=J3,b=J3,out=AndJ3J3); Or(a=zr,b=ng,out=orZrNg); Not(in=orZrNg,out=NorZrNg); And(a=AndJ3J3,b=NorZrNg,out=JGT); //JEQ And(a=J2,b=J2,out=AndJ2J2); And(a=zr,b=zr,out=AndZrZr); And(a=AndZrZr,b=AndJ2J2,out=JEQ); //JGE And(a=J3,b=J2,out=AndJ3J2); Or(a=zr,b=notNg,out=AndZrNotNg); And(a=AndZrNotNg,b=AndJ3J2,out=JGE); //JLT And(a=J1,b=J1,out=AndJ1J1); And(a=ng,b=ng,out=AndNgNg); And(a=AndJ1J1,b=AndNgNg,out=JLT); //JNE And(a=J3,b=J1,out=AndJ3J1); And(a=notZr,b=notZr,out=AndNotZrNotZr); And(a=AndNotZrNotZr,b=AndJ3J1,out=JNE); //JLE And(a=J2,b=J1,out=AndJ2J1); And(a=AndJ2J1,b=orZrNg,out=JLE); //JMP And(a=AndJ3J1,b=J2,out=JMP); Not(in=outToLoad,out=outToLoad1); // once needted to know when to increes but also needed to not it so it dosent load the reg when J1J2J3=000 //4wayMux one Mux(a=JMP,b=JGT,sel=instruction[0] ,out=out1); Mux(a=JEQ,b=JGE,sel=instruction[0] ,out=out2); Mux(a=out1,b=out2, sel=instruction[1] ,out=out5); //4wayMux two Mux(a=JLT,b=JNE,sel=instruction[0] ,out=out3); Mux(a=JLE,b=JMP,sel=instruction[0] ,out=out4); Mux(a=out3,b=out4,sel=instruction[1] ,out=out6); //2wayMux Mux(a=out5,b=out6,sel= instruction[2],out=outToLoad); PC(in=outAreg ,load=outToLoad ,inc=outToLoad1 ,reset=reset ,out[0..14]=pc); }