add verilog files for project one through five

This commit is contained in:
2024-10-17 14:36:58 -04:00
parent b16bfcfd43
commit 792efa70cd
37 changed files with 871 additions and 275 deletions

View File

@@ -1,40 +1,106 @@
/**
* 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.
*/
`default_nettype none
module CPU(
input clk,
input [15:0] inM, // M value input (M = contents of RAM[A])
input [15:0] instruction, // Instruction for execution
input reset, // Signals whether to re-start the current
// program (reset==1) or continue executing
// the current program (reset==0).
input clk,
input [15:0] inM, // M value input (M = contents of RAM[A])
input [15:0] instruction, // Instruction for execution
input reset, // Signals whether to re-start the current
// program (reset==1) or continue executing
// the current program (reset==0).
output [15:0] outM, // M value output
output writeM, // Write to M?
output [15:0] addressM, // Address in data memory (of M) to read
output [15:0] pc // address of next instruction
output [15:0] outM, // M value output
output writeM, // Write to M?
output [15:0] addressM, // Address in data memory (of M) to read
output [15:0] pc // address of next instruction
);
// Put your code here:
// Put your code here:
wire loadA;
wire loadD;
wire is_A;
wire is_C;
wire zr;
wire ng;
wire inc;
wire load;
wire jump;
wire [15:0] toA;
wire [15:0] toD;
wire [15:0] toPC;
wire [15:0] fromA;
wire [15:0] fromD;
wire [15:0] fromPC;
wire [15:0] fromAorM;
wire [15:0] fromALU;
reg [15:0] tempM;
reg [15:0] tempPC;
assign is_C = instruction[15] & instruction[14] & instruction[13];
assign is_A = ~is_C;
assign loadD = is_C & instruction[4];
assign loadA = (is_C & instruction[5]) || is_A;
assign fromAorM = instruction[12] ? inM : fromA;
assign toA = is_A ? instruction : outM;
// jump if j1 bit set and ng bit set
// jump if j2 bit set and zr bit set
// jump if j3 bit set and zr, ng bit not set
assign jump = is_C
& ((instruction[2] & ng)
|| (instruction[1] & zr)
|| (instruction[0] & ~(zr | ng)));
assign inc = ~jump;
assign outM = fromALU;
//assign toPC = jump? fromA : pc;
//xxxx xxxx xxxx xxxx
Register RegA(clk, toA, loadA, fromA);
Register RegD(clk, fromALU, loadD, fromD);
PC PC(clk, fromA, jump, inc, reset, pc);
ALU ALU(
fromD,
fromAorM,
instruction[11],
instruction[10],
instruction[9],
instruction[8],
instruction[7],
instruction[6],
fromALU,
zr,
ng
);
assign addressM = fromA;
assign writeM = is_C & instruction[3];
endmodule

View File

@@ -4,12 +4,24 @@
* a reset signal of approx. 20us length
*/
`default_nettype none
module Clock25_Reset20(
input CLK, // external clock 100 MHz
output clk, // internal clock 25 Mhz
output reset // reset signal approx. 20us
module Clock25_Reset20(
input CLK, // external clock 100 MHz
output reg clk, // internal clock 25 Mhz
output reg reset // reset signal approx. 20us
);
// Put your code here:
// Put your code here:
reg boot=1;
reg [3:0] ccount=0;
reg [12:0] rcount=0;
always @(posedge CLK) begin
if (boot == 1) begin
boot <= (rcount == 4095) ? 0 : 1;
rcount <= (rcount == 4095) ? 0 : rcount + 1;
reset <= (rcount >= 2048) ? 0 : 1;
end
ccount <= (ccount == 3) ? 0 : ccount + 1;
clk <= (ccount >= 2) ? 1 : 0;
end
endmodule

View File

@@ -8,12 +8,89 @@
*/
`default_nettype none
module HACK(
input CLK, // external clock 100 MHz
input [1:0] BUT, // user button (0 if pressed, 1 if released)
output [1:0] LED // leds (0 off, 1 on)
module HACK(
input CLK, // external clock 100 MHz
input [1:0] BUT, // user button (0 if pressed, 1 if released)
output [1:0] LED // leds (0 off, 1 on)
);
// Put your code here:
wire loadRAM;
wire loadIO0;
wire loadIO1;
wire loadIO2;
wire loadIO3;
wire loadIO4;
wire loadIO5;
wire loadIO6;
wire loadIO7;
wire loadIO8;
wire loadIO9;
wire loadIOA;
wire loadIOB;
wire loadIOC;
wire loadIOD;
wire loadIOE;
wire loadIOF;
wire [15:0] inRAM;
wire [15:0] inIO0;
wire [15:0] inIO1;
wire [15:0] inIO2=0;
wire [15:0] inIO3=0;
wire [15:0] inIO4=0;
wire [15:0] inIO5=0;
wire [15:0] inIO6=0;
wire [15:0] inIO7=0;
wire [15:0] inIO8=0;
wire [15:0] inIO9=0;
wire [15:0] inIOA=0;
wire [15:0] inIOB;
wire [15:0] inIOC;
wire [15:0] inIOD;
wire [15:0] inIOE;
wire [15:0] inIOF;
wire writeM;
wire [15:0] inM;
wire [15:0] instruction;
wire [15:0] outM;
wire [15:0] addressM;
wire [15:0] pc;
wire clk, reset;
wire [15:0] outDEBUG0;
wire [15:0] outDEBUG1;
wire [15:0] outDEBUG2;
wire loadDEBUG0;
wire loadDEBUG1;
wire loadDEBUG2;
// Put your code here:
assign LED[1:0] = inIO0[1:0];
assign outDEBUG0 = inIOB;
assign outDEBUG1 = inIOC;
assign outDEBUG2 = inIOD;
assign loadDEBUG0 = loadIOB;
assign loadDEBUG1 = loadIOC;
assign loadDEBUG2 = loadIOD;
Clock25_Reset20 CLKR(CLK, clk, reset);
CPU CPU(clk, inM, instruction, reset, outM, writeM, addressM, pc);
Memory Memory(addressM, writeM, inM, loadRAM,
loadIO0, loadIO1, loadIO2, loadIO3, loadIO4, loadIO5, loadIO6, loadIO7,
loadIO8, loadIO9, loadIOA, loadIOB, loadIOC, loadIOD, loadIOE, loadIOF,
inRAM, inIO0, inIO1, inIO2, inIO3, inIO4, inIO5, inIO6, inIO7,
inIO8, inIO9, inIOA, inIOB, inIOC, inIOD, inIOE, inIOF);
ROM ROM(pc, instruction);
RAM3840 RAM(clk, addressM[11:0], outM, loadRAM, inRAM);
Register LED12(clk, outM, loadIO0, inIO0);
Register BUT12(clk, {14'b0, BUT[1:0]}, 1'b1, inIO1);
Register DEBUG0(clk, outM, loadIOB, inIOB);
Register DEBUG1(clk, outM, loadIOC, inIOC);
Register DEBUG2(clk, outM, loadIOD, inIOD);
Register DEBUG3(clk, outM, loadIOE, inIOE);
Register DEBUG4(clk, outM, loadIOF, inIOF);
endmodule

View File

@@ -1,12 +1,12 @@
/**
* The complete address space of the Hack computer's memory,
* including RAM and memory-mapped I/O.
* including RAM and memory-mapped I/O.
* The chip facilitates read and write operations, as follows:
* Read: out(t) = Memory[address(t)](t)
* Write: if load(t-1) then Memory[address(t-1)](t) = in(t-1)
* In words: the chip always outputs the value stored at the memory
* location specified by address. If load==1, the in value is loaded
* into the memory location specified by address. This value becomes
* In words: the chip always outputs the value stored at the memory
* location specified by address. If load==1, the in value is loaded
* into the memory location specified by address. This value becomes
* available through the out output from the next time step onward.
* Address space rules:
* RAM 0x0000 - 0x0EFF (3840 words)
@@ -16,45 +16,80 @@
`default_nettype none
module Memory(
input [15:0] address,
input load,
output [15:0] out,
output loadRAM,
output loadIO0,
output loadIO1,
output loadIO2,
output loadIO3,
output loadIO4,
output loadIO5,
output loadIO6,
output loadIO7,
output loadIO8,
output loadIO9,
output loadIOA,
output loadIOB,
output loadIOC,
output loadIOD,
output loadIOE,
output loadIOF,
input [15:0] inRAM,
input [15:0] inIO0,
input [15:0] inIO1,
input [15:0] inIO2,
input [15:0] inIO3,
input [15:0] inIO4,
input [15:0] inIO5,
input [15:0] inIO6,
input [15:0] inIO7,
input [15:0] inIO8,
input [15:0] inIO9,
input [15:0] inIOA,
input [15:0] inIOB,
input [15:0] inIOC,
input [15:0] inIOD,
input [15:0] inIOE,
input [15:0] inIOF
input [15:0] address,
input load,
output [15:0] out,
output loadRAM,
output loadIO0,
output loadIO1,
output loadIO2,
output loadIO3,
output loadIO4,
output loadIO5,
output loadIO6,
output loadIO7,
output loadIO8,
output loadIO9,
output loadIOA,
output loadIOB,
output loadIOC,
output loadIOD,
output loadIOE,
output loadIOF,
input [15:0] inRAM,
input [15:0] inIO0,
input [15:0] inIO1,
input [15:0] inIO2,
input [15:0] inIO3,
input [15:0] inIO4,
input [15:0] inIO5,
input [15:0] inIO6,
input [15:0] inIO7,
input [15:0] inIO8,
input [15:0] inIO9,
input [15:0] inIOA,
input [15:0] inIOB,
input [15:0] inIOC,
input [15:0] inIOD,
input [15:0] inIOE,
input [15:0] inIOF
);
// Put your code here:
// Put your code here:
wire selA;
wire selB;
wire loadA;
wire loadB;
wire [15:0] outA;
wire [15:0] outB;
wire [15:0] outAB;
DMux DMUX(address[12], address[3], selA, selB);
And ANDA(selA,load,loadA);
And ANDB(selB,load,loadB);
And ANDR(~address[12], load, loadRAM);
DMux8Way DMUXLOADA(loadA, address[2:0],
loadIO0, loadIO1, loadIO2, loadIO3,
loadIO4, loadIO5, loadIO6, loadIO7);
DMux8Way DMUXLOADB(loadB, address[2:0],
loadIO8, loadIO9, loadIOA, loadIOB,
loadIOC, loadIOD, loadIOE, loadIOF);
Mux8Way16 Mux8Way16A(
inIO0[15:0], inIO1[15:0], inIO2[15:0], inIO3[15:0],
inIO4[15:0], inIO5[15:0], inIO6[15:0], inIO7[15:0],
address[2:0], outA[15:0]
);
Mux8Way16 Mux8Way16B(
inIO8[15:0], inIO9[15:0], inIOA[15:0], inIOB[15:0],
inIOC[15:0], inIOD[15:0], inIOE[15:0], inIOF[15:0],
address[2:0], outB[15:0]
);
Mux16 MUX16AB(outA[15:0], outB[15:0], address[3], outAB[15:0]);
Mux16 MUX16ABR(inRAM[15:0], outAB[15:0], address[12], out[15:0]);
endmodule