Skip to content
1 change: 1 addition & 0 deletions src/ControlFSM.sv
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ module ControlFSM(
pc_src <= 1'b0;
PCUpdate <= 1'b0;
IRWrite <= 1'b0;
MemWrite <= 1'b0;

FSMState <= current_state;

Expand Down
14 changes: 7 additions & 7 deletions src/Instruction_Decode/RegisterFile.v
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@ 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

);

//declare 32 registers in Register File, with 32 bits each
//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
Comment thread
TheDeepestSpace marked this conversation as resolved.

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
Expand Down
17 changes: 12 additions & 5 deletions src/top.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -152,5 +154,10 @@ module top ( input wire clk
default: result = 32'hxxxxxxxx;
endcase
end

always @(posedge clk) begin
dataA <= rd1;
dataB <= rd2;
end
Comment on lines +157 to +161

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So i think figured out what was the issue with the sw -- it was not really related to the PC using the single clock cycle stuff; the real problem was that the dataA and dataB registers here, because they technically already existed in the RF implementation (i.e. the reads were "clocked"); so this was adding another clock cycle basically.

Both approaches are correct, but i think your implementation is probably more inline with how the diagram is layed out -- the sync register is outside of RF and the reads are combinational ; i pushed the update to your PR along with the test bench fixes and it should be good to go now


endmodule
endmodule
109 changes: 109 additions & 0 deletions test/sw_tb.sv
Original file line number Diff line number Diff line change
@@ -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