[05/CPU] Implements most of the CPU
This includes: - Handling of data i/o (for A/D/M) - Handling the ALU properly (all 28 computations) - Basic incremental PC (i/o) - PC reset - read/write to M What's missing: - Handling jumps
This commit is contained in:
parent
69a32190dc
commit
e7d72b1020
|
@ -6,23 +6,23 @@
|
|||
/**
|
||||
* 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 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
|
||||
* 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.
|
||||
* 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 {
|
||||
|
@ -34,10 +34,85 @@ CHIP CPU {
|
|||
// the current program (reset==0).
|
||||
|
||||
OUT outM[16], // M value output
|
||||
writeM, // Write to M?
|
||||
writeM, // Write to M?
|
||||
addressM[15], // Address in data memory (of M)
|
||||
pc[15]; // address of next instruction
|
||||
|
||||
PARTS:
|
||||
// Put your code here:
|
||||
}
|
||||
// instructions[15] = instructionC
|
||||
|
||||
// Specifically, when C instruction
|
||||
// instruction[14] = 1
|
||||
// instruction[13] = 1
|
||||
|
||||
// instruction[12] = a
|
||||
|
||||
// instruction[11] = c1
|
||||
// instruction[10] = c2
|
||||
// instruction[9] = c3
|
||||
|
||||
// instruction[8] = c4
|
||||
// instruction[7] = c5
|
||||
// instruction[6] = c6
|
||||
|
||||
// instruction[5] = d1
|
||||
// instruction[4] = d2
|
||||
// instruction[3] = d3
|
||||
// instruction[2] = j1
|
||||
// instruction[1] = j2
|
||||
// instruction[0] = j3
|
||||
|
||||
// we write to A based on the following truth table
|
||||
// i[15] = true = instruction =C
|
||||
// i[5] = true = d1 = true = write ALU output to register A
|
||||
// i[15] | i[5] | write?| t1
|
||||
// 0 | 0 | 1 | 1
|
||||
// 0 | 1 | 1 | 1
|
||||
// 1 | 0 | 0 | 1
|
||||
// 1 | 1 | 1 | 0
|
||||
Nand(a=instruction[15], b=instruction[5], out=t1);
|
||||
Nand(a=t1, b=instruction[15], out=writeA);
|
||||
|
||||
// But the input to registerA is picked b/w instruction[0..14] | aluoutput
|
||||
// depending on instructionA
|
||||
// registerAInput = {
|
||||
// [0, instruction[0..14]] if instruction[15] = 0
|
||||
// aluoutput if instruction[15] = 1
|
||||
// }
|
||||
Mux16(a[15]=false,
|
||||
a[0..14]=instruction[0..14],
|
||||
b=aluoutput,
|
||||
sel=instruction[15],
|
||||
out=registerAInput);
|
||||
|
||||
// Register A
|
||||
ARegister(in=registerAInput,
|
||||
load=writeA,
|
||||
out=registerA, out[0..14]=addressM);
|
||||
|
||||
// Register D (instruction[4] = d2)
|
||||
DRegister(in=aluoutput, load=instruction[4], out=registerD);
|
||||
|
||||
// TODO: support jumps
|
||||
PC(in=registerA, load=false, inc=true, reset=reset, out[0..14]=pc);
|
||||
|
||||
// the "a" bit = instruction[12] decides whether Y = registerA | inM
|
||||
Mux16(a=registerA, b=inM, sel=instruction[12], out=y);
|
||||
|
||||
ALU(x=registerD,
|
||||
y=y,
|
||||
// control bits start
|
||||
zx=instruction[11],
|
||||
nx=instruction[10],
|
||||
zy=instruction[9],
|
||||
ny=instruction[8],
|
||||
f=instruction[7],
|
||||
no=instruction[6],
|
||||
// control bits end
|
||||
out=aluoutput,
|
||||
out=outM,
|
||||
zr=zr, ng=ng);
|
||||
|
||||
// if we are on instruction C, and d3 is true
|
||||
And(a=instruction[3], b=instruction[15], out=writeM);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
|time| inM | instruction |reset| outM |writeM |addre| pc |DRegiste|
|
||||
|0+ | 0|0011000000111001| 0 | 0| 0 | 0| 0| 0 |
|
||||
|1 | 0|0011000000111001| 0 | 0| 0 |12345| 1| 0 |
|
||||
|1+ | 0|1110110000010000| 0 | 12345| 0 |12345| 1| 12345 |
|
||||
|2 | 0|1110110000010000| 0 | 12345| 0 |12345| 2| 12345 |
|
||||
|2+ | 0|0101101110100000| 0 | -1| 0 |12345| 2| 12345 |
|
||||
|3 | 0|0101101110100000| 0 | -1| 0 |23456| 3| 12345 |
|
||||
|3+ | 0|1110000111010000| 0 | 11111| 0 |23456| 3| 11111 |
|
||||
|4 | 0|1110000111010000| 0 | 12345| 0 |23456| 4| 11111 |
|
||||
|4+ | 0|0000001111101000| 0 | -11111| 0 |23456| 4| 11111 |
|
||||
|5 | 0|0000001111101000| 0 | -11111| 0 | 1000| 5| 11111 |
|
||||
|5+ | 0|1110001100001000| 0 | 11111| 1 | 1000| 5| 11111 |
|
||||
|6 | 0|1110001100001000| 0 | 11111| 1 | 1000| 6| 11111 |
|
||||
|6+ | 0|0000001111101001| 0 | -11111| 0 | 1000| 6| 11111 |
|
||||
|7 | 0|0000001111101001| 0 | -11111| 0 | 1001| 7| 11111 |
|
||||
|7+ | 0|1110001110011000| 0 | 11110| 1 | 1001| 7| 11110 |
|
||||
|8 | 0|1110001110011000| 0 | 11109| 1 | 1001| 8| 11110 |
|
||||
|8+ | 0|0000001111101000| 0 | -11110| 0 | 1001| 8| 11110 |
|
||||
|9 | 0|0000001111101000| 0 | -11110| 0 | 1000| 9| 11110 |
|
||||
|9+ | 11111|1111010011010000| 0 | -1| 0 | 1000| 9| -1 |
|
||||
|10 | 11111|1111010011010000| 0 | -11112| 0 | 1000| 10| -1 |
|
||||
|10+ | 11111|0000000000001110| 0 | 1000| 0 | 1000| 10| -1 |
|
||||
|11 | 11111|0000000000001110| 0 | 14| 0 | 14| 11| -1 |
|
||||
|11+ | 11111|1110001100000100| 0 | -1| 0 | 14| 11| -1 |
|
||||
|12 | 11111|1110001100000100| 0 | -1| 0 | 14| 12| -1 |
|
Loading…
Reference in New Issue