101 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			101 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|  | // 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: | ||
|  |     // Put your code here: | ||
|  | 
 | ||
|  |     // load A Register if it's an A instruction | ||
|  |     // load A Register if it's a  C instruction with d1 bit set | ||
|  |     // AC d1 Nand Nand | ||
|  |     // 0  0  1    1 | ||
|  |     // 0  1  1    1 | ||
|  |     // 1  0  1    0 | ||
|  |     // 1  1  0    1 | ||
|  |     Nand(a=instruction[15], b=instruction[5], out=instructionAC); | ||
|  |     Nand(a=instruction[15], b=instructionAC, out=loadA); | ||
|  | 
 | ||
|  |     // load A Register with either an A instruction or ALU output | ||
|  |     Mux16(a=instruction, b=fromALU, sel=instruction[15], out=toARegister); | ||
|  |     ARegister(in=toARegister, load=loadA, out=fromARegister, out[0..14]=addressM); | ||
|  | 
 | ||
|  |     // load D Register if it's a C instruction with d2 bit set | ||
|  |     And(a=instruction[15], b=instruction[4], out=loadD); | ||
|  |     DRegister(in=fromALU, load=loadD, out=fromDRegister); | ||
|  | 
 | ||
|  |     // load R[addressM] if it's a C instruction with d3 bit set | ||
|  |     And(a=instruction[15], b=instruction[3], out=writeM); | ||
|  | 
 | ||
|  |     Mux16(a=fromARegister, b=inM, sel=instruction[12], out=fromARegisterOrRAM); | ||
|  | 
 | ||
|  |     ALU( | ||
|  |         x=fromDRegister, | ||
|  |         y=fromARegisterOrRAM, | ||
|  |         zx=instruction[11], | ||
|  |         nx=instruction[10], | ||
|  |         zy=instruction[9], | ||
|  |         ny=instruction[8], | ||
|  |          f=instruction[7], | ||
|  |         no=instruction[6], | ||
|  |         out=fromALU, | ||
|  |         out=outM, | ||
|  |         zr=zr, | ||
|  |         ng=ng); | ||
|  | 
 | ||
|  |     // jump if j1 bit set and ng bit set | ||
|  |     // jump if j2 bit set and zr bit set | ||
|  |     // jump if j2 bit set and zr, ng bit not set | ||
|  |     Or(a=zr, b=ng, out=nz); | ||
|  |     Not(in=nz, out=NZ); | ||
|  | 
 | ||
|  |     And(a=instruction[2], b=ng,  out=J1); | ||
|  |     And(a=instruction[1], b=zr,  out=J2); | ||
|  |     And(a=instruction[0], b=NZ, out=J3); | ||
|  | 
 | ||
|  |     Or(a=J1, b=J2, out=L1); | ||
|  |     Or(a=J3, b=L1, out=L2); | ||
|  | 
 | ||
|  |     // only jump if it's a C instruction | ||
|  |     // inc & load are mutually exclusive | ||
|  |     And(a=instruction[15], b=L2, out=load); | ||
|  |     Not(in=load, out=inc); | ||
|  | 
 | ||
|  |     PC(in=fromARegister, load=load, inc=inc, reset=reset, out[0..14]=pc); | ||
|  | } |