Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a682347f0
|
||
|
|
559ff01d69
|
||
|
|
92a0cb17da
|
||
|
|
65be2c2d61
|
||
|
|
878f949e5f
|
||
|
|
0ea3e0fa12
|
||
|
|
12ae58ad86
|
||
|
|
4c7e2ff085
|
No files matched your search
@@ -0,0 +1,18 @@
|
||||
01084023
|
||||
25090007
|
||||
ad090000
|
||||
8d0a0000
|
||||
012a5821
|
||||
012b6022
|
||||
212d0003
|
||||
018d7020
|
||||
012d8024
|
||||
012d8825
|
||||
012d9026
|
||||
012d9827
|
||||
018ea02a
|
||||
018ea82b
|
||||
25080001
|
||||
010db02b
|
||||
12d4fffd
|
||||
12d6ffff
|
||||
+14
-12
@@ -15,26 +15,28 @@ module alu #(parameter width=2)(input logic [3:0] op,
|
||||
logic [2**width-1:0] asu_out;
|
||||
logic [2:0] asu_flags;
|
||||
|
||||
asu #(width) adder_unit(asu_op[op[1]], A, B, asu_out, asu_flags[0], asu_flags[1]);
|
||||
assign asu_op = op[1];
|
||||
asu #(width) adder_unit(asu_op, A, B, asu_out, asu_flags[0], asu_flags[1]);
|
||||
|
||||
logic [2**width-1:0] lu_out;
|
||||
lu #(width) logic_unit(op[1:0], A, B, lu_out);
|
||||
|
||||
always_comb begin
|
||||
case (op)
|
||||
4'b0000: begin OUT_1 = asu_out; flags = asu_flags; end
|
||||
4'b0001: begin OUT_1 = asu_out; flags = asu_flags; end
|
||||
4'b0010: begin OUT_1 = asu_out; flags = asu_flags; end
|
||||
4'b0011: begin OUT_1 = asu_out; flags = asu_flags; end
|
||||
4'b0100: begin OUT_1 = lu_out; flags = asu_flags; end
|
||||
4'b0101: begin OUT_1 = lu_out; flags = asu_flags; end
|
||||
4'b0110: begin OUT_1 = lu_out; flags = asu_flags; end
|
||||
4'b0111: begin OUT_1 = lu_out; flags = asu_flags; end
|
||||
4'b1010: begin OUT_1 = (asu_out[2**width-1] ^ asu_flags[1]) & {{(width-1){1'b0}}, 1'b1}; flags = asu_flags; end
|
||||
4'b1011: begin OUT_1 = ~asu_flags[0] & {{(width-1){1'b0}}, 1'b1}; flags = asu_flags; end
|
||||
default: begin OUT_1 = {(2**width){1'b0}}; flags = asu_flags; end
|
||||
4'b0000: begin OUT_1 = asu_out; end
|
||||
4'b0001: begin OUT_1 = asu_out; end
|
||||
4'b0010: begin OUT_1 = asu_out; end
|
||||
4'b0011: begin OUT_1 = asu_out; end
|
||||
4'b0100: begin OUT_1 = lu_out; end
|
||||
4'b0101: begin OUT_1 = lu_out; end
|
||||
4'b0110: begin OUT_1 = lu_out; end
|
||||
4'b0111: begin OUT_1 = lu_out; end
|
||||
4'b1010: begin OUT_1 = (asu_out[2**width-1] ^ asu_flags[1]) & {{(width-1){1'b0}}, 1'b1}; end
|
||||
4'b1011: begin OUT_1 = ~asu_flags[0] & {{(width-1){1'b0}}, 1'b1}; end
|
||||
default: begin OUT_1 = {(2**width){1'b0}}; end
|
||||
endcase
|
||||
asu_flags[2] = OUT_1 == 0;
|
||||
flags = asu_flags;
|
||||
end
|
||||
endmodule
|
||||
`endif
|
||||
+13
-15
@@ -30,8 +30,8 @@ module assignment2 #(width=5, romsz=10) (
|
||||
logic[15:0] PC_Reg_Display;
|
||||
|
||||
// Program / Instruction Counter Intermediates
|
||||
logic [romsz-1:0] pc_addr;
|
||||
logic [romsz-1:0] pc_addr_write;
|
||||
logic [2**width-1:0] pc_addr;
|
||||
logic [2**width-1:0] pc_addr_write;
|
||||
logic [0:0] pc_we;
|
||||
logic [2**width-1:0] instruction;
|
||||
|
||||
@@ -58,10 +58,10 @@ module assignment2 #(width=5, romsz=10) (
|
||||
|
||||
instruction_counter #(width) PC (clk, pc_we, pc_addr_write, pc_addr);
|
||||
|
||||
rom #(romsz, 2**width) ROM (pc_addr, instruction);
|
||||
rom #(romsz, width) ROM (pc_addr, instruction);
|
||||
|
||||
logic [2**width-1:0] rd_mem;
|
||||
ram #(width) RAM (clk, rd_alu, M2W, rt, rd_mem);
|
||||
ram #(ramsz, width) RAM (clk, rd_alu, M2W, rt, rd_mem);
|
||||
|
||||
control_unit CONTROL_UNIT (instruction[31:26], instruction[5:0],
|
||||
M2R, M2W, B, ALU_FN, ALU_SRC, RDST, RW
|
||||
@@ -70,29 +70,27 @@ module assignment2 #(width=5, romsz=10) (
|
||||
|
||||
register_file #(width, 5) REGS (
|
||||
clk, rd_we,
|
||||
instruction[20:16], rd,
|
||||
(RDST) ? instruction[15:11] : instruction[20:16], rt,
|
||||
instruction[25:21], rs,
|
||||
(RDST) ? instruction[15:11] : instruction[20:16], rd,
|
||||
instruction[25:21], rs,
|
||||
instruction[20:16], rt,
|
||||
regs_out
|
||||
);
|
||||
// Always use sign-extension
|
||||
logic [2**width-1:0] rt_imm;
|
||||
sign_extender #(4, width) SIGNEXT(1'b1, instruction[15:0], rt_imm);
|
||||
// TODO:
|
||||
// - ALU srcB
|
||||
// - PCBranch (rel jump of 4-byte words)
|
||||
|
||||
|
||||
alu #(width) ALU (ALU_FN, rs, rt_alu, rd_alu, flags[1:0]);
|
||||
logic [2**width-1:0] rd_alu;
|
||||
logic [2**width-1:0] rt_alu;
|
||||
alu #(width) ALU (ALU_FN, rs, rt_alu, rd_alu, flags);
|
||||
assign rt_alu = (ALU_SRC) ? (rt_imm) : (rt);
|
||||
|
||||
assign pc_we = B & flags[2];
|
||||
assign pc_addr_write = (rt_imm << 2) + pc_addr;
|
||||
assign rd_we = RW;
|
||||
assign rd = (M2R) ? rd_alu : rd_mem;
|
||||
|
||||
assign rd = (M2R) ? rd_mem : rd_alu;
|
||||
|
||||
|
||||
`ifdef QUARTUS_SYNTH
|
||||
// Temporary Test output
|
||||
// assign PC_Reg_Display = 16'hC342;
|
||||
|
||||
@@ -105,6 +103,6 @@ module assignment2 #(width=5, romsz=10) (
|
||||
.segments2(out_seg_2),
|
||||
.segments3(out_seg_3)
|
||||
);
|
||||
|
||||
`endif
|
||||
endmodule
|
||||
`endif
|
||||
@@ -23,13 +23,13 @@ module control_unit (
|
||||
instruction_classifier CLASSIFIER (op, TYPE_R, TYPE_B1, TYPE_J, TYPE_B2, TYPE_I, TYPE_F, TYPE_M);
|
||||
|
||||
always_comb begin
|
||||
M2R = TYPE_M & op[3];
|
||||
M2W = TYPE_M & ~op[3];
|
||||
M2R = TYPE_M & ~((op & 6'b001000) >> 3);
|
||||
M2W = TYPE_M & ((op & 6'b001000) >> 3);
|
||||
B = TYPE_B1 | TYPE_B2 | TYPE_J;
|
||||
ALU_FN = (func & {(6){TYPE_R}}) | ( {4'b0000, op[1:0]} & {(6){TYPE_I}});
|
||||
ALU_SRC = TYPE_B1 | TYPE_B2 | TYPE_I | TYPE_M;
|
||||
RDST = TYPE_I; // Imm ops store back into rt
|
||||
RW = TYPE_R | TYPE_I | (TYPE_M & op[3]); // All ALU R-type ops, Addi/Addiu ops, and memory loads
|
||||
ALU_FN = (func & {(4){TYPE_R}}) | ( {2'b00, (op & 6'b000011)} & {(4){TYPE_I}}) | (4'b0010 & {4{TYPE_B1 | TYPE_B2}});
|
||||
ALU_SRC = TYPE_I | TYPE_M;
|
||||
RDST = TYPE_R; // Imm ops store back into rt
|
||||
RW = TYPE_R | TYPE_I | M2R;
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
@@ -8,6 +8,11 @@ module instruction_counter #(parameter width=5)(
|
||||
);
|
||||
|
||||
logic [2**width-1:0] pc;
|
||||
|
||||
initial begin
|
||||
pc = {(2**width){1'b0}};
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
if (we) begin
|
||||
pc <= W;
|
||||
|
||||
+6
-6
@@ -1,12 +1,12 @@
|
||||
`ifndef RAM_H
|
||||
`define RAM_H
|
||||
|
||||
module ram #(datawidth=5)(
|
||||
input logic [0:0] clk,
|
||||
input logic [2**datawidth-1:0] addr,
|
||||
input logic [0:0] we,
|
||||
input logic [datawidth-1:0] data_in,
|
||||
output logic [datawidth-1:0] data_out
|
||||
module ram #(addrwidth=9, datawidth=5)(
|
||||
input logic [0:0] clk,
|
||||
input logic [addrwidth-1:0] addr,
|
||||
input logic [0:0] we,
|
||||
input logic [datawidth-1:0] data_in,
|
||||
output logic [datawidth-1:0] data_out
|
||||
);
|
||||
|
||||
// TODO: Make this byte-sized, NOT word-sized!
|
||||
|
||||
@@ -12,7 +12,8 @@ module register_file #(parameter width=5, parameter nregs=5)(
|
||||
logic [2**width-1:0] regs[2**nregs];
|
||||
|
||||
initial begin
|
||||
regs[0] = {(2**width){1'b0}};
|
||||
for (integer N = 0; N < (2**nregs); ++N)
|
||||
regs[N] = 32'd0;
|
||||
end
|
||||
|
||||
always_ff @(posedge clk) begin
|
||||
|
||||
+5
-5
@@ -3,19 +3,19 @@
|
||||
|
||||
module rom #(parameter m=7,p=4) (
|
||||
input logic [m-1:0] Ad,
|
||||
output logic [p-1:0] Dout
|
||||
output logic [2**p-1:0] Dout
|
||||
);
|
||||
|
||||
logic [p-1:0] mem[2**m-1:0];
|
||||
assign Dout = mem[Ad];
|
||||
logic [2**p-1:0] mem[2**m];
|
||||
assign Dout = mem[Ad>>2]; // Because word-size versus byte size hack
|
||||
|
||||
//Load the program in memory
|
||||
// The machine code stored in text file program.dat written in Hex format
|
||||
initial begin
|
||||
`ifdef QUARTUS_SYNTH
|
||||
$readmemh("../../asm/bin/ELEC4720-2026s2-Ass-02-Demo.txt",mem); //$readmemb for binary
|
||||
$readmemh("../../asm/bin/ELEC4720-2026s2-Ass-02-Demo.hex", mem, 0, 2**m-1); //$readmemb for binary
|
||||
`else
|
||||
$readmemh("./asm/bin/ELEC4720-2026s2-Ass-02-Demo.txt",mem); //$readmemb for binary
|
||||
$readmemh("./asm/bin/ELEC4720-2026s2-Ass-02-Demo.hex", mem, 0, 2**m-1); //$readmemb for binary
|
||||
`endif
|
||||
end
|
||||
endmodule // end rom module
|
||||
|
||||
@@ -6,9 +6,11 @@ module sign_extender #(in_width=4, out_width=5)(
|
||||
input logic [2**in_width-1:0] val,
|
||||
output logic [2**out_width-1:0] ext_val
|
||||
);
|
||||
logic [0:0] msb;
|
||||
assign msb = (val & {1'b1, {(in_width-1){1'b0}}}) >> (in_width-1);
|
||||
always_comb begin
|
||||
if (op) begin
|
||||
ext_val = { {(2**(out_width-in_width)){val[2**in_width-1]}}, val};
|
||||
ext_val = { {(2**(out_width-in_width)){msb}}, val};
|
||||
end else begin
|
||||
ext_val = ({{(2**(out_width-in_width)){1'b0}}, val});
|
||||
end
|
||||
|
||||
+41
-26
@@ -1,76 +1,88 @@
|
||||
`include "assignment2.sv"
|
||||
|
||||
`timescale 1us/10ns
|
||||
|
||||
`define PRINT_REGISTERS(regs)\
|
||||
$display("\tt0-t8: \t0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x\n\ts0-s8: \t0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x 0x%0x\n",\
|
||||
regs[8], regs[9], regs[10], regs[11], regs[12], regs[13], regs[14], regs[15], \
|
||||
regs[16], regs[17], regs[18], regs[19], regs[20], regs[21], regs[22], regs[23] \
|
||||
);
|
||||
`define TEST_CHECK(cond) if (cond) begin end else begin \
|
||||
$display("Check %s failed\n", `"cond`"); \
|
||||
$display("Check %s failed", `"cond`"); \
|
||||
`PRINT_REGISTERS(CPU.REGS.regs); \
|
||||
num_errors += 1; \
|
||||
end
|
||||
|
||||
module mips_tb(input logic [0:0] clk);
|
||||
module mips_tb();
|
||||
logic [0:0] clk;
|
||||
assignment2 #(5) CPU (clk);
|
||||
|
||||
initial clk = 0;
|
||||
always #1 clk = ~clk;
|
||||
|
||||
integer num_errors = 0;
|
||||
initial begin
|
||||
$dumpfile("output.vcd");
|
||||
$dumpvars(0, clk);
|
||||
$dumpvars(1, CPU.REGS);
|
||||
$dumpvars(2, CPU.ROM);
|
||||
$dumpvars(3, CPU.PC);
|
||||
$dumpvars(4, CPU.pc_addr);
|
||||
$dumpvars(5, CPU.CONTROL_UNIT);
|
||||
$dumpvars(5, CPU.instruction);
|
||||
$dumpvars(5, CPU.ALU);
|
||||
|
||||
// Zero out lower registers
|
||||
$display("Beginning MIPS tests");
|
||||
assign num_errors = 0;
|
||||
|
||||
for (integer N = 1; N < 32; ++N)
|
||||
CPU.REGS.regs[N] = 32'd0;
|
||||
|
||||
// Check R-type / initialise
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[8] == 32'd0);
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[9] == (CPU.REGS.regs[8] + 32'd7));
|
||||
|
||||
// Check load-store
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.RAM.mem[0] == CPU.REGS.regs[9]);
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[10] == CPU.RAM.mem[0]);
|
||||
|
||||
// Check arithmetic
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[11] == (CPU.REGS.regs[9] + CPU.REGS.regs[10]));
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[12] == (CPU.REGS.regs[9] - CPU.REGS.regs[11]));
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[13] == (CPU.REGS.regs[9] + 3));
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[14] == (CPU.REGS.regs[12] + CPU.REGS.regs[13]));
|
||||
|
||||
// Check logic instructions
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[16] == (CPU.REGS.regs[9] & CPU.REGS.regs[13]));
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[17] == (CPU.REGS.regs[9] | CPU.REGS.regs[13]));
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[18] == (CPU.REGS.regs[9] ^ CPU.REGS.regs[13]));
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[19] == ( ~(CPU.REGS.regs[9] | CPU.REGS.regs[13]) ));
|
||||
|
||||
// Check SLT instructions
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[20] == $signed(CPU.REGS.regs[12]) < $signed(CPU.REGS.regs[14]));
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[21] == $unsigned(CPU.REGS.regs[12]) < $unsigned(CPU.REGS.regs[14]));
|
||||
|
||||
// Check loop branching
|
||||
for (integer N = 1; N < 11; ++N) begin
|
||||
#1;
|
||||
`TEST_CHECK(CPU.REGS.regs[0] == 32'(N));
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[8] == 32'(N));
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[22] == $unsigned(CPU.REGS.regs[8]) < $unsigned(CPU.REGS.regs[13]));
|
||||
end
|
||||
|
||||
// Final state check
|
||||
#1;
|
||||
#2;
|
||||
`TEST_CHECK(CPU.REGS.regs[8] == 32'd10);
|
||||
`TEST_CHECK(CPU.REGS.regs[9] == 32'd7);
|
||||
`TEST_CHECK(CPU.REGS.regs[10] == 32'd7);
|
||||
@@ -89,7 +101,10 @@ module mips_tb(input logic [0:0] clk);
|
||||
`TEST_CHECK(CPU.REGS.regs[22] == 32'd0);
|
||||
`TEST_CHECK(CPU.REGS.regs[23] == 32'd0);
|
||||
|
||||
if (num_errors == 0) $display("\x1b[38;5;10mAll MIPS tests passing\x1b[m");
|
||||
else $display("\x1b[38;5;9m%0d MIPS test(s) failing\x1b[m", num_errors);
|
||||
if (num_errors == 0) begin $display("\x1b[38;5;10mAll MIPS tests passing\x1b[m");
|
||||
end else begin $display("\x1b[38;5;9m%0d MIPS test(s) failing\x1b[m", num_errors); end
|
||||
|
||||
$dumpflush;
|
||||
$finish;
|
||||
end
|
||||
endmodule
|
||||
Reference in new issue
Block a user