Skip to content

Instantly share code, notes, and snippets.

@meikj
Created August 21, 2013 19:26
Show Gist options
  • Save meikj/6299021 to your computer and use it in GitHub Desktop.
Save meikj/6299021 to your computer and use it in GitHub Desktop.
/**
* The Central Processing unit (CPU).
* Consists of an ALU and a set of registers, 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 unit. If reset=1 then the
* CPU jumps to address 0 (i.e. sets pc=0 in next time unit) 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 into M?
addressM[15], // Address in data memory (of M)
pc[15]; // address of next instruction
PARTS:
//
// Decode instruction:
// i = [15]
//
// a_Addr = [0..14]
//
// c_Jump = [0..2] (jjj)
// c_Dest = [3..5] (ddd)
// c_Cond = [6..12] (acccccc)
//
// zx = [11]
// nx = [10]
// zy = [9]
// ny = [8]
// f = [7]
// no = [6]
//
// store A = [5]
// store D = [4]
// store M = [3]
//
// Determine register A load flag
Not(in=instruction[15], out=noti);
Or(a=noti, b=instruction[5], out=aFlag);
// In the case of A-inst, load address input, otherwise load ALU output
Mux16(a=instruction, b=aluOut, sel=instruction[15], out=addr);
ARegister(in=addr, load=aFlag, out=regA, out[0..14]=addressM);
// Determine input to ALU - use A or M
Mux16(a=regA, b=inM, sel=instruction[12], out=aluIn);
ALU(
x=regD, y=aluIn,
zx=instruction[11], nx=instruction[10], zy=instruction[9],
ny=instruction[8], f=instruction[7], no=instruction[6],
out=outM, out=aluOut, zr=zr, ng=ng
);
// Store ALU result in D if store D == 1
And(a=instruction[4], b=instruction[15], out=loadD); // C-inst ONLY
DRegister(in=aluOut, load=loadD, out=regD);
// Determine writeM output
And(a=instruction[15], b=instruction[3], out=writeM); // C-inst ONLY
// Determine jump values
Or(a=zr, b=ng, out=zrorng);
Not(in=zrorng, out=ps); // positive flag
And(a=instruction[0], b=ps, out=jgt); // positive jump
And(a=instruction[1], b=zr, out=jeq); // zero jump
And(a=instruction[2], b=ng, out=jlt); // negative jump
Or(a=jgt, b=jeq, out=jge); // greater than or equal jump
Or(a=jgt, b=jlt, out=jne); // not equal jump
Or(a=jlt, b=jeq, out=jle); // less than or equal jump
And(a=instruction[0], b=instruction[1], out=j3andj2);
And(a=j3andj2, b=instruction[2], out=jmp); // standard jump/goto
// Handle program counter
Or8Way(
in[0]=jmp, in[1]=jgt, in[2]=jeq, in[3]=jlt,
in[4]=jge, in[5]=jne, in[6]=jle, in[7]=jmp,
out=orjumps
);
And(a=orjumps, b=instruction[15], out=loadPC); // load flag
Not(in=loadPC, out=inc); // inc flag
PC(in=regA, load=loadPC, inc=inc, reset=reset, out[0..14]=pc);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment