diff --git a/src/ControlFSM.sv b/src/ControlFSM.sv index de2e4670..73e09133 100644 --- a/src/ControlFSM.sv +++ b/src/ControlFSM.sv @@ -102,6 +102,7 @@ module ControlFSM( pc_src <= 1'b0; PCUpdate <= 1'b0; IRWrite <= 1'b0; + MemWrite <= 1'b0; FSMState <= current_state; diff --git a/src/Instruction_Decode/RegisterFile.v b/src/Instruction_Decode/RegisterFile.v index 4b674b24..c43b6c47 100644 --- a/src/Instruction_Decode/RegisterFile.v +++ b/src/Instruction_Decode/RegisterFile.v @@ -17,8 +17,8 @@ input clk, input regWrite, input [31:0] dataIn, input reset, -output reg [31:0] baseAddr, //data read line #1 - from first source register -output reg [31:0] writeData //data read line #2 - from second source register +output wire [31:0] baseAddr, //data read line #1 - from first source register +output wire [31:0] writeData //data read line #2 - from second source register ); @@ -26,14 +26,14 @@ output reg [31:0] writeData //data read line #2 - from second source register //32 bits deep (32 addresses) and 32 bits wide (32 bits at each register) //note that RFMem[0:31] means there are 32 elements (with addr for each element), each of which are 32-bit regs reg [31:0] RFMem [0:31] /* synthesis ramstyle = M10K*/; - + + assign baseAddr = RFMem[Addr1]; //read out 32-bit contents of rs1 register + assign writeData = RFMem[Addr2]; //read out 32-bit contents of rs2 register + always@(posedge clk) begin if (reset) RFMem[0] <= 0; //register r0 should always remain at 0 - - baseAddr <= RFMem[Addr1]; //read out 32-bit contents of rs1 register - writeData <= RFMem[Addr2]; //read out 32-bit contents of rs2 register - + if(regWrite && Addr3 != 0) begin RFMem[Addr3] <= dataIn; //write into destination register if RegWrite = 1 diff --git a/src/top.v b/src/top.v index 94488ccb..00f2b061 100644 --- a/src/top.v +++ b/src/top.v @@ -41,6 +41,8 @@ module top ( input wire clk wire [3:0] __tmp_ALUControl; wire [1:0] __tmp_ResultSrc; wire [3:0] __tmp_FSMState; + logic [31:0] dataA + ,dataB; ControlFSM control_fsm ( .opcode ( opcode ) @@ -83,8 +85,8 @@ module top ( input wire clk MA memory // instructions and data ( .A ( memory_address ) - , .WD ( 32'hxxxxxxxx ) - , .WE ( `FALSE ) + , .WD ( dataB ) + , .WE ( __tmp_MemWrite ) , .CLK ( clk ) // outputs @@ -130,14 +132,14 @@ module top ( input wire clk case (__tmp_ALUSrcA) ALU_SRC_A__PC: alu_input_a = pc_cur; ALU_SRC_A__OLD_PC: alu_input_a = pc_old; - ALU_SRC_A__RD1: alu_input_a = rd1; + ALU_SRC_A__RD1: alu_input_a = dataA; default: alu_input_a = 32'hxxxxxxxx; endcase end always @(*) begin case (__tmp_ALUSrcB) - ALU_SRC_B__RD2: alu_input_b = rd2; + ALU_SRC_B__RD2: alu_input_b = dataB; ALU_SRC_B__IMM_EXT: alu_input_b = imm_ext; ALU_SRC_B__4: alu_input_b = 32'd4; default: alu_input_b = 32'hxxxxxxxx; @@ -152,5 +154,10 @@ module top ( input wire clk default: result = 32'hxxxxxxxx; endcase end + + always @(posedge clk) begin + dataA <= rd1; + dataB <= rd2; + end -endmodule +endmodule diff --git a/test/addi_tb.sv b/test/addi_tb.sv new file mode 100644 index 00000000..d9f83505 --- /dev/null +++ b/test/addi_tb.sv @@ -0,0 +1,93 @@ +`timescale 1ns/1ps + +`include "test/utils.svh" + +module addi_tb; + + reg clk; + reg reset; + + top uut + ( .clk ( clk ) + , .reset ( reset ) + ); + + initial begin + clk = 0; + forever #5 clk = ~clk; + end + + task wait_till_next_cfsm_state(input [5:0] expected_state); + @(posedge clk); #1; + `assert_equal(uut.control_fsm.current_state, expected_state) + endtask + + initial begin + reset <= `TRUE; + + // Set up instruction memory + uut.memory.M[ 0] = 32'h00010093; // addi x1, x2, 0 + uut.memory.M[ 1] = 32'h00410093; // addi x1, x2, 4 + uut.memory.M[ 2] = 32'hff810093; // addi x1, x2, -8 + + // Set up register file + uut.instruction_decode.instanceRegFile.RFMem[1] = 0; // x1 = 0 + uut.instruction_decode.instanceRegFile.RFMem[2] = 42; // x2 = 42 + + wait_till_next_cfsm_state(uut.control_fsm.FETCH); + + reset <= `FALSE; + + // --- Instruction 1: addi x1, x2, 0 --- + wait_till_next_cfsm_state(uut.control_fsm.DECODE); + `assert_equal(uut.opcode, 7'b0010011) + `assert_equal(uut.instruction_decode.rs1, 2) + `assert_equal(uut.instruction_decode.rd, 1) + `assert_equal(uut.instruction_decode.imm_ext, 0) + + wait_till_next_cfsm_state(uut.control_fsm.EXECUTEI); + `assert_equal(uut.alu.a, 42) + `assert_equal(uut.alu.b, 0) + `assert_equal(uut.alu.out, 42) + + wait_till_next_cfsm_state(uut.control_fsm.ALUWB); + + wait_till_next_cfsm_state(uut.control_fsm.FETCH); + `assert_equal(uut.instruction_decode.instanceRegFile.RFMem[1], 42) + `assert_equal(uut.fetch.pc_cur, 4) + + // --- Instruction 2: addi x1, x2, 4 --- + wait_till_next_cfsm_state(uut.control_fsm.DECODE); + `assert_equal(uut.instruction_decode.imm_ext, 4) + + wait_till_next_cfsm_state(uut.control_fsm.EXECUTEI); + `assert_equal(uut.alu.out, 46) + + wait_till_next_cfsm_state(uut.control_fsm.ALUWB); + + wait_till_next_cfsm_state(uut.control_fsm.FETCH); + `assert_equal(uut.instruction_decode.instanceRegFile.RFMem[1], 46) + `assert_equal(uut.fetch.pc_cur, 8) + + // --- Instruction 3: addi x1, x2, -8 --- + wait_till_next_cfsm_state(uut.control_fsm.DECODE); + `assert_equal(uut.instruction_decode.imm_ext, -8) + + wait_till_next_cfsm_state(uut.control_fsm.EXECUTEI); + `assert_equal(uut.alu.out, 34) + + wait_till_next_cfsm_state(uut.control_fsm.ALUWB); + + wait_till_next_cfsm_state(uut.control_fsm.FETCH); + `assert_equal(uut.instruction_decode.instanceRegFile.RFMem[1], 34) + + // Final assertions + `assert_equal(uut.instruction_decode.instanceRegFile.RFMem[2], 42) + `assert_equal(uut.instruction_decode.instanceRegFile.RFMem[1], 34) + + $finish; + end + + `SETUP_VCD_DUMP(addi_tb) + +endmodule diff --git a/test/sw_tb.sv b/test/sw_tb.sv new file mode 100644 index 00000000..d58fce4e --- /dev/null +++ b/test/sw_tb.sv @@ -0,0 +1,109 @@ +`timescale 1ns/1ps + +`include "test/utils.svh" + +module sw_tb; + + reg clk; + reg reset; + + top uut + ( .clk ( clk ) + , .reset ( reset ) + ); + + initial begin + clk = 0; + forever #5 clk = ~clk; + end + + task wait_till_next_cfsm_state(input [5:0] expected_state); + @(posedge clk); #1; + `assert_equal(uut.control_fsm.current_state, expected_state) + endtask + + initial begin + reset <= `TRUE; + + // set up instructions and data memory + uut.memory.M[ 0] = 32'h00532023; // sw x5, 0(x6) + uut.memory.M[ 1] = 32'h00532223; // sw x5, 4(x6) + uut.memory.M[ 2] = 32'h00532423; // sw x5, 8(x6) + uut.memory.M[10] = 32'hbadab00f; // initial value + uut.memory.M[11] = 32'hdeadbeef; // initial value + uut.memory.M[12] = 32'hcafebabe; // initial value + uut.memory.M[13] = 32'h00000000; // will be written by sw x5, 8(x6) + + // set up register file + uut.instruction_decode.instanceRegFile.RFMem[6] = 44; // x6 = 44 + uut.instruction_decode.instanceRegFile.RFMem[5] = 256; // x5 = 256 + + wait_till_next_cfsm_state(uut.control_fsm.FETCH); + + reset <= `FALSE; + + // --- Instruction 1: sw x5, 0(x6) --- + wait_till_next_cfsm_state(uut.control_fsm.DECODE); + `assert_equal(uut.opcode, 7'b0100011) + `assert_equal(uut.instruction_decode.rs1, 6) + `assert_equal(uut.instruction_decode.rs2, 5) + `assert_equal(uut.instruction_decode.imm_ext, 0) + + wait_till_next_cfsm_state(uut.control_fsm.MEMADR); + `assert_equal(uut.alu.out, 44) + + wait_till_next_cfsm_state(uut.control_fsm.MEMWRITE); + `assert_equal(uut.memory_address, 44) + + wait_till_next_cfsm_state(uut.control_fsm.FETCH); + + `assert_equal(uut.memory.M[11], 256) + `assert_equal(uut.fetch.pc_cur, 4) + + // --- Instruction 2: sw x5, 4(x6) --- + wait_till_next_cfsm_state(uut.control_fsm.DECODE); + + `assert_equal(uut.instruction_decode.imm_ext, 4) + + wait_till_next_cfsm_state(uut.control_fsm.MEMADR); + + `assert_equal(uut.alu.out, 48) + + wait_till_next_cfsm_state(uut.control_fsm.MEMWRITE); + + wait_till_next_cfsm_state(uut.control_fsm.FETCH); + + `assert_equal(uut.memory.M[12], 256) + `assert_equal(uut.fetch.pc_cur, 8) + + // --- Instruction 3: sw x5, 8(x6) --- + wait_till_next_cfsm_state(uut.control_fsm.DECODE); + + `assert_equal(uut.opcode, 7'b0100011) + `assert_equal(uut.instruction_decode.rs1, 6) + `assert_equal(uut.instruction_decode.rs2, 5) + `assert_equal(uut.instruction_decode.imm_ext, 8) + + wait_till_next_cfsm_state(uut.control_fsm.MEMADR); + + `assert_equal(uut.alu.out, 52) + + wait_till_next_cfsm_state(uut.control_fsm.MEMWRITE); + + wait_till_next_cfsm_state(uut.control_fsm.FETCH); + + `assert_equal(uut.memory.M[13], 256) + + // Final assertions + `assert_equal(uut.memory.M[11], 256) + `assert_equal(uut.memory.M[12], 256) + `assert_equal(uut.memory.M[13], 256) + `assert_equal(uut.instruction_decode.instanceRegFile.RFMem[5], 256) + `assert_equal(uut.instruction_decode.instanceRegFile.RFMem[6], 44) + + $finish; + end + + `SETUP_VCD_DUMP(sw_tb) + +endmodule