Commit 4ad34eca authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

rtl: passes RV32IM test suite

parent 7630ec3a
...@@ -14,6 +14,7 @@ files = [ "rv_cpu.v", ...@@ -14,6 +14,7 @@ files = [ "rv_cpu.v",
"rv_writeback.v", "rv_writeback.v",
"rv_shifter.v", "rv_shifter.v",
"rv_multiply.v", "rv_multiply.v",
"rv_divide.v",
"rv_csr.v", "rv_csr.v",
"rv_timer.v", "rv_timer.v",
"rv_exceptions.v", "rv_exceptions.v",
......
...@@ -100,6 +100,9 @@ module rv_cpu ...@@ -100,6 +100,9 @@ module rv_cpu
wire [4:0] d2x_opcode; wire [4:0] d2x_opcode;
wire d2x_shifter_sign; wire d2x_shifter_sign;
wire d2x_is_load, d2x_is_store, d2x_is_undef;
wire [31:0] d2x_imm; wire [31:0] d2x_imm;
wire d2x_is_signed_compare; wire d2x_is_signed_compare;
wire d2x_is_signed_alu_op; wire d2x_is_signed_alu_op;
...@@ -210,6 +213,10 @@ module rv_cpu ...@@ -210,6 +213,10 @@ module rv_cpu
.x_is_signed_alu_op_o(d2x_is_signed_alu_op), .x_is_signed_alu_op_o(d2x_is_signed_alu_op),
.x_is_add_o(d2x_is_add), .x_is_add_o(d2x_is_add),
.x_is_shift_o(d2x_is_shift), .x_is_shift_o(d2x_is_shift),
.x_is_load_o(d2x_is_load),
.x_is_store_o(d2x_is_store),
.x_is_undef_o(d2x_is_undef),
.x_rd_source_o(d2x_rd_source), .x_rd_source_o(d2x_rd_source),
.x_rd_write_o(d2x_rd_write), .x_rd_write_o(d2x_rd_write),
...@@ -240,9 +247,10 @@ module rv_cpu ...@@ -240,9 +247,10 @@ module rv_cpu
wire rf_rd_write; wire rf_rd_write;
wire x2w_valid;
wire [31:0] rf_bypass_rd_value = x2w_rd_value; wire [31:0] rf_bypass_rd_value = x2w_rd_value;
wire rf_bypass_rd_write = rf_rd_write && !x2w_load; wire rf_bypass_rd_write = rf_rd_write && !x2w_load; // multiply/shift too?
rv_regfile regfile rv_regfile regfile
( (
...@@ -284,7 +292,6 @@ module rv_cpu ...@@ -284,7 +292,6 @@ module rv_cpu
.irq_i ( irq_i ), .irq_i ( irq_i ),
.x_stall_req_o(x_stall_req), .x_stall_req_o(x_stall_req),
.w_stall_req_i(w_stall_req),
.d_valid_i(d2x_valid), .d_valid_i(d2x_valid),
...@@ -302,6 +309,10 @@ module rv_cpu ...@@ -302,6 +309,10 @@ module rv_cpu
.d_is_signed_alu_op_i(d2x_is_signed_alu_op), .d_is_signed_alu_op_i(d2x_is_signed_alu_op),
.d_is_add_i(d2x_is_add), .d_is_add_i(d2x_is_add),
.d_is_shift_i(d2x_is_shift), .d_is_shift_i(d2x_is_shift),
.d_is_load_i(d2x_is_load),
.d_is_store_i(d2x_is_store),
.d_is_undef_i(d2x_is_undef),
.d_rd_source_i(d2x_rd_source), .d_rd_source_i(d2x_rd_source),
.d_rd_write_i(d2x_rd_write), .d_rd_write_i(d2x_rd_write),
...@@ -321,7 +332,7 @@ module rv_cpu ...@@ -321,7 +332,7 @@ module rv_cpu
.w_fun_o(x2w_fun), .w_fun_o(x2w_fun),
.w_load_o(x2w_load), .w_load_o(x2w_load),
.w_store_o(x2w_store), .w_store_o(x2w_store),
.w_valid_o(x2w_valid),
.w_dm_addr_o(x2w_dm_addr), .w_dm_addr_o(x2w_dm_addr),
.w_rd_o(x2w_rd), .w_rd_o(x2w_rd),
.w_rd_value_o(x2w_rd_value), .w_rd_value_o(x2w_rd_value),
...@@ -358,7 +369,8 @@ module rv_cpu ...@@ -358,7 +369,8 @@ module rv_cpu
.x_load_i(x2w_load), .x_load_i(x2w_load),
.x_load_hazard_i(x2w_load_hazard), .x_load_hazard_i(x2w_load_hazard),
.x_store_i(x2w_store), .x_store_i(x2w_store),
.x_valid_i(x2w_valid),
.x_rd_i(x2w_rd), .x_rd_i(x2w_rd),
.x_rd_source_i(x2w_rd_source), .x_rd_source_i(x2w_rd_source),
.x_rd_value_i(x2w_rd_value), .x_rd_value_i(x2w_rd_value),
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
`define OPC_LOAD 5'b00000 `define OPC_LOAD 5'b00000
`define OPC_STORE 5'b01000 `define OPC_STORE 5'b01000
`define OPC_SYSTEM 5'b11100 `define OPC_SYSTEM 5'b11100
`define OPC_MULDIV 5'b
`define BRA_EQ 3'b000 `define BRA_EQ 3'b000
`define BRA_NEQ 3'b001 `define BRA_NEQ 3'b001
...@@ -56,6 +57,11 @@ ...@@ -56,6 +57,11 @@
`define FUNC_MULHSU 3'b010 `define FUNC_MULHSU 3'b010
`define FUNC_MULHU 3'b011 `define FUNC_MULHU 3'b011
`define FUNC_DIV 3'b100
`define FUNC_DIVU 3'b101
`define FUNC_REM 3'b110
`define FUNC_REMU 3'b111
`define RD_SOURCE_ALU 3'b000 `define RD_SOURCE_ALU 3'b000
`define RD_SOURCE_SHIFTER 3'b010 `define RD_SOURCE_SHIFTER 3'b010
`define RD_SOURCE_MULTIPLY 3'b001 `define RD_SOURCE_MULTIPLY 3'b001
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library. License along with this library.
*/ */
`include "rv_defs.v" `include "rv_defs.v"
...@@ -29,14 +29,14 @@ module rv_exceptions ...@@ -29,14 +29,14 @@ module rv_exceptions
input x_stall_i, input x_stall_i,
input x_kill_i, input x_kill_i,
input d_is_csr_i, input d_is_csr_i,
input d_is_eret_i, input d_is_eret_i,
input [2:0] d_fun_i, input [2:0] d_fun_i,
input [4:0] d_csr_imm_i, input [4:0] d_csr_imm_i,
input [11:0] d_csr_sel_i, input [11:0] d_csr_sel_i,
input exp_irq_i, input exp_irq_i,
input exp_tick_i, input exp_tick_i,
input exp_breakpoint_i, input exp_breakpoint_i,
...@@ -45,38 +45,40 @@ module rv_exceptions ...@@ -45,38 +45,40 @@ module rv_exceptions
input exp_invalid_insn_i, input exp_invalid_insn_i,
input [31:0] x_csr_write_value_i, input [31:0] x_csr_write_value_i,
output x_exception_o, output x_exception_o,
input [31:0] x_exception_pc_i, input [31:0] x_exception_pc_i,
output [31:0] x_exception_pc_o, output [31:0] x_exception_pc_o,
output [31:0] x_exception_vector_o,
output [31:0] csr_mstatus_o, output [31:0] csr_mstatus_o,
output [31:0] csr_mip_o, output [31:0] csr_mip_o,
output [31:0] csr_mie_o, output [31:0] csr_mie_o,
output [31:0] csr_mepc_o, output [31:0] csr_mepc_o,
output [31:0] csr_mcause_o output [31:0] csr_mcause_o
); );
reg [31:0] csr_mepc; reg [31:0] csr_mepc;
reg [31:0] csr_mie; reg [31:0] csr_mie;
reg csr_ie; reg csr_ie;
reg exception; reg [3:0] csr_mcause;
reg [3:0] cause;
reg exception;
reg [3:0] cause;
reg [5:0] except_vec_masked; reg [5:0] except_vec_masked;
assign csr_mcause_o = 0; assign csr_mcause_o = {28'h0, csr_mcause};
assign csr_mepc_o = csr_mepc; assign csr_mepc_o = csr_mepc;
assign csr_mie_o = csr_mie; assign csr_mie_o = csr_mie;
assign csr_mstatus_o[0] = csr_ie; assign csr_mstatus_o[0] = csr_ie;
assign csr_mstatus_o[31:1] = 0; assign csr_mstatus_o[31:1] = 0;
reg [31:0] csr_mip; reg [31:0] csr_mip;
always@* always@*
begin begin
...@@ -92,7 +94,7 @@ module rv_exceptions ...@@ -92,7 +94,7 @@ module rv_exceptions
assign csr_mip_o = csr_mip; assign csr_mip_o = csr_mip;
always@(posedge clk_i) always@(posedge clk_i)
if (rst_i) if (rst_i)
...@@ -107,31 +109,45 @@ module rv_exceptions ...@@ -107,31 +109,45 @@ module rv_exceptions
except_vec_masked[5] <= x_csr_write_value_i [`EXCEPT_IRQ]; except_vec_masked[5] <= x_csr_write_value_i [`EXCEPT_IRQ];
end else begin end else begin
if ( exp_invalid_insn_i ) if ( exp_invalid_insn_i )
except_vec_masked[0] <= csr_mie[`EXCEPT_ILLEGAL_INSN]; except_vec_masked[0] <= 1'b1;
if ( exp_breakpoint_i ) if ( exp_breakpoint_i )
except_vec_masked[1] <= csr_mie[`EXCEPT_BREAKPOINT]; except_vec_masked[1] <= 1'b1;
if ( exp_unaligned_load_i ) if ( exp_unaligned_load_i )
except_vec_masked[2] <= csr_mie[`EXCEPT_UNALIGNED_LOAD]; except_vec_masked[2] <= 1'b1;
if ( exp_unaligned_store_i ) if ( exp_unaligned_store_i )
except_vec_masked[3] <= csr_mie[`EXCEPT_UNALIGNED_STORE]; except_vec_masked[3] <= 1'b1;
if ( exp_tick_i ) if ( exp_tick_i )
except_vec_masked[4] <= csr_mie[`EXCEPT_TIMER]; except_vec_masked[4] <= csr_mie[`EXCEPT_TIMER] & csr_ie;
if( exp_irq_i ) if( exp_irq_i )
except_vec_masked[5] <= csr_mie[`EXCEPT_IRQ]; except_vec_masked[5] <= csr_mie[`EXCEPT_IRQ] & csr_ie;
end // else: !if(!x_stall_i && !x_kill_i && d_is_csr_i && d_csr_sel_i == `CSR_ID_MIP) end // else: !if(!x_stall_i && !x_kill_i && d_is_csr_i && d_csr_sel_i == `CSR_ID_MIP)
end // else: !if(rst_i) end // else: !if(rst_i)
always@* always@*
exception <= |except_vec_masked; exception <= |except_vec_masked | exp_invalid_insn_i;
reg exception_pending; reg exception_pending;
assign x_exception_vector_o = 'h8;
always@*
if(exp_invalid_insn_i || except_vec_masked[0])
cause <= `EXCEPT_ILLEGAL_INSN;
else if (except_vec_masked[1])
cause <= `EXCEPT_BREAKPOINT;
else if (except_vec_masked[2])
cause <= `EXCEPT_UNALIGNED_LOAD;
else if (except_vec_masked[3])
cause <= `EXCEPT_UNALIGNED_STORE;
else if (except_vec_masked[4])
cause <= `EXCEPT_TIMER;
else
cause <= `EXCEPT_IRQ;
always@(posedge clk_i) always@(posedge clk_i)
if(rst_i) if(rst_i)
...@@ -145,9 +161,10 @@ module rv_exceptions ...@@ -145,9 +161,10 @@ module rv_exceptions
if ( d_is_eret_i ) if ( d_is_eret_i )
exception_pending <= 0; exception_pending <= 0;
if ( !exception_pending && exception && csr_ie ) if ( !exception_pending && exception )
begin begin
csr_mepc <= x_exception_pc_i; csr_mepc <= x_exception_pc_i;
csr_mcause <= cause;
exception_pending <= 1; exception_pending <= 1;
end end
...@@ -159,10 +176,10 @@ module rv_exceptions ...@@ -159,10 +176,10 @@ module rv_exceptions
csr_mepc <= x_csr_write_value_i; csr_mepc <= x_csr_write_value_i;
`CSR_ID_MIE: `CSR_ID_MIE:
begin begin
csr_mie[`EXCEPT_ILLEGAL_INSN] <= x_csr_write_value_i [`EXCEPT_ILLEGAL_INSN]; csr_mie[`EXCEPT_ILLEGAL_INSN] <= 1;
csr_mie[`EXCEPT_BREAKPOINT] <= x_csr_write_value_i [`EXCEPT_BREAKPOINT]; csr_mie[`EXCEPT_BREAKPOINT] <= 1;
csr_mie[`EXCEPT_UNALIGNED_LOAD] <= x_csr_write_value_i [`EXCEPT_UNALIGNED_LOAD]; csr_mie[`EXCEPT_UNALIGNED_LOAD] <= 1;
csr_mie[`EXCEPT_UNALIGNED_STORE] <= x_csr_write_value_i [`EXCEPT_UNALIGNED_STORE]; csr_mie[`EXCEPT_UNALIGNED_STORE] <= 1;
csr_mie[`EXCEPT_TIMER] <= x_csr_write_value_i [`EXCEPT_TIMER]; csr_mie[`EXCEPT_TIMER] <= x_csr_write_value_i [`EXCEPT_TIMER];
csr_mie[`EXCEPT_IRQ] <= x_csr_write_value_i [`EXCEPT_IRQ]; csr_mie[`EXCEPT_IRQ] <= x_csr_write_value_i [`EXCEPT_IRQ];
end end
...@@ -172,10 +189,10 @@ module rv_exceptions ...@@ -172,10 +189,10 @@ module rv_exceptions
end // if (!x_stall_i && !x_kill_i) end // if (!x_stall_i && !x_kill_i)
assign x_exception_pc_o = csr_mepc; assign x_exception_pc_o = csr_mepc;
assign x_exception_o = exception & csr_ie & !exception_pending; assign x_exception_o = exception & !exception_pending;
endmodule // rv_exceptions endmodule // rv_exceptions
...@@ -30,7 +30,6 @@ module rv_exec ...@@ -30,7 +30,6 @@ module rv_exec
input x_stall_i, input x_stall_i,
input x_kill_i, input x_kill_i,
output reg x_stall_req_o, output reg x_stall_req_o,
input w_stall_req_i,
input [31:0] d_pc_i, input [31:0] d_pc_i,
...@@ -59,6 +58,12 @@ module rv_exec ...@@ -59,6 +58,12 @@ module rv_exec
input d_is_signed_alu_op_i, input d_is_signed_alu_op_i,
input d_is_add_i, input d_is_add_i,
input d_is_shift_i, input d_is_shift_i,
input d_is_load_i,
input d_is_store_i,
input d_is_divide_i,
input d_is_undef_i,
input [2:0] d_rd_source_i, input [2:0] d_rd_source_i,
input d_rd_write_i, input d_rd_write_i,
...@@ -73,7 +78,8 @@ module rv_exec ...@@ -73,7 +78,8 @@ module rv_exec
output reg [2:0 ] w_fun_o, output reg [2:0 ] w_fun_o,
output reg w_load_o, output reg w_load_o,
output reg w_store_o, output reg w_store_o,
output reg w_valid_o,
output reg [4:0] w_rd_o, output reg [4:0] w_rd_o,
output reg [31:0] w_rd_value_o, output reg [31:0] w_rd_value_o,
output reg w_rd_write_o, output reg w_rd_write_o,
...@@ -97,8 +103,6 @@ module rv_exec ...@@ -97,8 +103,6 @@ module rv_exec
); );
parameter g_exception_vector = 'h40;
wire [31:0] rs1, rs2; wire [31:0] rs1, rs2;
assign rs1 = rf_rs1_value_i; assign rs1 = rf_rs1_value_i;
...@@ -124,10 +128,6 @@ module rv_exec ...@@ -124,10 +128,6 @@ module rv_exec
reg f_branch_take; reg f_branch_take;
wire x_stall_req_shifter = 0;
wire x_stall_req_multiply = 0;
wire x_stall_req_divide = 0;
wire [31:0] rd_shifter; wire [31:0] rd_shifter;
wire [31:0] rd_csr; wire [31:0] rd_csr;
wire [31:0] rd_mul; wire [31:0] rd_mul;
...@@ -136,7 +136,7 @@ module rv_exec ...@@ -136,7 +136,7 @@ module rv_exec
wire exception; wire exception;
wire [31:0] csr_mie, csr_mip, csr_mepc, csr_mstatus,csr_mcause; wire [31:0] csr_mie, csr_mip, csr_mepc, csr_mstatus,csr_mcause;
wire [31:0] csr_write_value; wire [31:0] csr_write_value;
wire [31:0] exception_address; wire [31:0] exception_address, exception_vector;
rv_csr csr_regs rv_csr csr_regs
...@@ -165,7 +165,7 @@ module rv_exec ...@@ -165,7 +165,7 @@ module rv_exec
.csr_mip_i(csr_mip), .csr_mip_i(csr_mip),
.csr_mie_i(csr_mie), .csr_mie_i(csr_mie),
.csr_mepc_i(csr_mepc), .csr_mepc_i(csr_mepc),
.csr_mcause_i(csr_mmause) .csr_mcause_i(csr_mcause)
); );
rv_exceptions exception_unit rv_exceptions exception_unit
...@@ -188,12 +188,12 @@ module rv_exec ...@@ -188,12 +188,12 @@ module rv_exec
.exp_breakpoint_i(1'b0), .exp_breakpoint_i(1'b0),
.exp_unaligned_load_i(1'b0), .exp_unaligned_load_i(1'b0),
.exp_unaligned_store_i(1'b0), .exp_unaligned_store_i(1'b0),
.exp_invalid_insn_i(1'b0), .exp_invalid_insn_i(d_is_undef_i && !x_stall_i && !x_kill_i && d_valid_i),
.x_exception_o(exception), .x_exception_o(exception),
.x_exception_pc_i(d_pc_i), .x_exception_pc_i(d_pc_i),
.x_exception_pc_o(exception_address), .x_exception_pc_o(exception_address),
.x_exception_vector_o(exception_vector),
.csr_mstatus_o(csr_mstatus), .csr_mstatus_o(csr_mstatus),
.csr_mip_o(csr_mip), .csr_mip_o(csr_mip),
...@@ -220,7 +220,7 @@ module rv_exec ...@@ -220,7 +220,7 @@ module rv_exec
if(d_is_eret_i ) if(d_is_eret_i )
branch_target <= exception_address; branch_target <= exception_address;
else if ( exception ) else if ( exception )
branch_target <= g_exception_vector; branch_target <= exception_vector;
else case (d_opcode_i) else case (d_opcode_i)
`OPC_JAL: branch_target <= d_pc_i + d_imm_i; `OPC_JAL: branch_target <= d_pc_i + d_imm_i;
`OPC_JALR: branch_target <= rs1 + d_imm_i; `OPC_JALR: branch_target <= rs1 + d_imm_i;
...@@ -300,7 +300,9 @@ module rv_exec ...@@ -300,7 +300,9 @@ module rv_exec
.d_is_shift_i(d_is_shift_i), .d_is_shift_i(d_is_shift_i),
.w_rd_o(w_rd_shifter_o) .w_rd_o(w_rd_shifter_o)
); );
wire divider_stall_req = 0;
rv_multiply multiplier rv_multiply multiplier
( (
...@@ -314,10 +316,35 @@ module rv_exec ...@@ -314,10 +316,35 @@ module rv_exec
.w_rd_o (w_rd_multiply_o) .w_rd_o (w_rd_multiply_o)
); );
/* wire divider_stall_req;
wire [31:0] rd_divide;
rv_divide divider
(
.clk_i(clk_i),
.rst_i(rst_i),
.x_stall_i(x_stall_i),
.x_kill_i(x_kill_i),
.x_stall_req_o(divider_stall_req),
.d_valid_i(d_valid_i),
.d_is_divide_i(d_is_divide_i),
.d_rs1_i(rs1),
.d_rs2_i(rs2),
.d_fun_i(d_fun_i),
.x_rd_o(rd_divide)
);
-----/\----- EXCLUDED -----/\----- */
always@* always@*
case (d_rd_source_i) case (d_rd_source_i)
`RD_SOURCE_ALU: rd_value <= alu_result; `RD_SOURCE_ALU: rd_value <= alu_result;
`RD_SOURCE_CSR: rd_value <= rd_csr; `RD_SOURCE_CSR: rd_value <= rd_csr;
// `RD_SOURCE_DIVIDE: rd_value <= rd_divide;
default: rd_value <= 32'hx; default: rd_value <= 32'hx;
endcase // case (x_rd_source_i) endcase // case (x_rd_source_i)
...@@ -406,16 +433,19 @@ module rv_exec ...@@ -406,16 +433,19 @@ module rv_exec
assign dm_data_s_o = dm_data_s; assign dm_data_s_o = dm_data_s;
assign dm_data_select_o = dm_select_s; assign dm_data_select_o = dm_select_s;
/* -----\/----- EXCLUDED -----\/-----
wire is_load = (d_opcode_i == `OPC_LOAD ? 1: 0) && d_valid_i && !x_kill_i; wire is_load = (d_opcode_i == `OPC_LOAD ? 1: 0) && d_valid_i && !x_kill_i;
wire is_store = (d_opcode_i == `OPC_STORE ? 1: 0) && d_valid_i && !x_kill_i; wire is_store = (d_opcode_i == `OPC_STORE ? 1: 0) && d_valid_i && !x_kill_i;
-----/\----- EXCLUDED -----/\----- */
assign dm_load_o = is_load && !x_stall_i; assign dm_load_o = d_is_load_i & d_valid_i & !x_kill_i & !x_stall_i & !exception;
assign dm_store_o = is_store && !x_stall_i; assign dm_store_o = d_is_store_i & d_valid_i & !x_kill_i & !x_stall_i & !exception;
/* -----\/----- EXCLUDED -----\/-----
wire trig_ent = (d_pc_i == 'h264 && !x_kill_i); wire trig_ent = (d_pc_i == 'h264 && !x_kill_i);
wire trig_ret = (d_pc_i == 'h2bc && !x_kill_i); wire trig_ret = (d_pc_i == 'h2bc && !x_kill_i);
wire trig_wr = (dm_addr == 'hf368 && is_store && !x_stall_i); wire trig_wr = (dm_addr == 'hf368 && is_store && !x_stall_i);
-----/\----- EXCLUDED -----/\----- */
always@(posedge clk_i) always@(posedge clk_i)
...@@ -429,8 +459,7 @@ module rv_exec ...@@ -429,8 +459,7 @@ module rv_exec
w_store_o <= 0; w_store_o <= 0;
w_dm_addr_o <= 0; w_dm_addr_o <= 0;
w_rd_source_o <= 0; w_rd_source_o <= 0;
w_valid_o <= 0;
end else if (!x_stall_i) begin end else if (!x_stall_i) begin
f_branch_target_o <= branch_target; f_branch_target_o <= branch_target;
...@@ -438,32 +467,30 @@ module rv_exec ...@@ -438,32 +467,30 @@ module rv_exec
w_rd_o <= d_rd_i; w_rd_o <= d_rd_i;
// if(!shifter_stall_req)
w_rd_value_o <= rd_value; w_rd_value_o <= rd_value;
w_rd_write_o <= d_rd_write_i && !x_kill_i && d_valid_i && !exception; w_rd_write_o <= d_rd_write_i && !x_kill_i && !exception;
w_rd_source_o <= d_rd_source_i; w_rd_source_o <= d_rd_source_i;
w_fun_o <= d_fun_i; w_fun_o <= d_fun_i;
w_load_o <= is_load && !exception; w_load_o <= d_is_load_i & d_valid_i && !x_kill_i && !exception;
w_store_o <= is_store && !exception; w_store_o <= d_is_store_i & d_valid_i && !x_kill_i && !exception;
if ( (is_load || is_store) && !exception && unaligned_addr) /* -----\/----- EXCLUDED -----\/-----
if ( (d_is_load_i || is_store) && !exception && unaligned_addr)
begin begin
$error("Unaligned address!"); $error("Unaligned address!");
$stop; $stop;
end end
-----/\----- EXCLUDED -----/\----- */
w_dm_addr_o <= dm_addr; w_dm_addr_o <= dm_addr;
w_valid_o <= d_valid_i && !x_kill_i && !exception;
end else begin // if (!x_stall_i) end else begin // if (!x_stall_i)
// f_branch_take <= 0; w_valid_o <= 0;
w_rd_write_o <= 0; end // else: !if(rst_i)
w_load_o <= 0;
w_store_o <= 0;
end // else: !if(rst_i)
assign f_branch_take_o = f_branch_take; assign f_branch_take_o = f_branch_take;
...@@ -471,9 +498,9 @@ end // else: !if(rst_i) ...@@ -471,9 +498,9 @@ end // else: !if(rst_i)
always@* always@*
if(f_branch_take) if(f_branch_take)
x_stall_req_o <= 0; x_stall_req_o <= 0;
else if (x_stall_req_shifter || x_stall_req_multiply || x_stall_req_divide) else if(divider_stall_req)
x_stall_req_o <= 1; x_stall_req_o <= 1;
else if ((is_store || is_load) && !dm_ready_i) else if ((d_is_load_i || d_is_store_i) && d_valid_i && !x_kill_i && !dm_ready_i)
x_stall_req_o <= 1; x_stall_req_o <= 1;
else else
x_stall_req_o <= 0; x_stall_req_o <= 0;
......
...@@ -15,28 +15,30 @@ module rv_multiply ...@@ -15,28 +15,30 @@ module rv_multiply
output reg [31:0] w_rd_o output reg [31:0] w_rd_o
); );
wire sign_a = ( d_fun_i == `FUNC_MUL || d_fun_i == `FUNC_MULHSU ) ? d_rs1_i[31] : 1'b0; reg [31:0] yl_xl, yl_xh, yh_xl;
wire sign_b = ( d_fun_i == `FUNC_MUL ) ? d_rs2_i[31] : 1'b0;
wire [32:0] a = { sign_a, d_rs1_i };
wire [32:0] b = { sign_b, d_rs2_i };
reg [65:0] stage0, stage1;
reg [2:0] s2_fun;
wire[17:0] xl = d_rs1_i[17:0];
wire[13:0] xh = d_rs1_i[31:18];
wire[17:0] yl = d_rs2_i[17:0];
wire[13:0] yh = d_rs2_i[31:18];
always@(posedge clk_i) always@(posedge clk_i)
if(!x_stall_i) if(!x_stall_i)
begin begin
stage0 <= $signed(a) * $signed(b); yh_xl <= $signed(yh) * $signed(xl);
s2_fun <= d_fun_i; yl_xh <= $signed(yl) * $signed(xh);
yl_xl <= $unsigned(yl) * $unsigned(xl);
end end
// stage0 <= $signed(d_rs1_i) * $signed(d_rs2_i);
always@* always@*
if( s2_fun != `FUNC_MUL ) w_rd_o <= yl_xl + {yl_xh[13:0], 18'h0} + {yh_xl[13:0], 18'h0};
w_rd_o <= stage0[63:32];
else
w_rd_o <= stage0[31:0];
endmodule // rv_multiply endmodule // rv_multiply
......
...@@ -39,7 +39,7 @@ module rv_decode ...@@ -39,7 +39,7 @@ module rv_decode
input [31:0] f_pc_i, input [31:0] f_pc_i,
input f_valid_i, input f_valid_i,
output x_valid_o, output x_valid_o,
output reg [31:0] x_pc_o, output reg [31:0] x_pc_o,
...@@ -62,8 +62,13 @@ module rv_decode ...@@ -62,8 +62,13 @@ module rv_decode
output reg x_is_signed_alu_op_o, output reg x_is_signed_alu_op_o,
output reg x_is_add_o, output reg x_is_add_o,
output x_is_shift_o, output x_is_shift_o,
output reg x_is_load_o,
output reg x_is_store_o,
output reg x_is_undef_o,
output reg [2:0] x_rd_source_o, output reg [2:0] x_rd_source_o,
output reg x_rd_write_o, output x_rd_write_o,
output reg [11:0] x_csr_sel_o, output reg [11:0] x_csr_sel_o,
output reg [4:0] x_csr_imm_o, output reg [4:0] x_csr_imm_o,
...@@ -75,13 +80,14 @@ module rv_decode ...@@ -75,13 +80,14 @@ module rv_decode
wire [4:0] f_rs1 = f_ir_i[19:15]; wire [4:0] f_rs1 = f_ir_i[19:15];
wire [4:0] f_rs2 = f_ir_i[24:20]; wire [4:0] f_rs2 = f_ir_i[24:20];
reg [4:0] x_rs1; reg [4:0] x_rs1;
reg [4:0] x_rs2; reg [4:0] x_rs2;
reg [4:0] x_rd; reg [4:0] x_rd;
reg [4:0] x_opcode; reg [4:0] x_opcode;
reg x_valid; reg x_valid;
reg x_is_shift; reg x_is_shift;
reg x_rd_write;
assign x_rs1_o = x_rs1; assign x_rs1_o = x_rs1;
...@@ -126,13 +132,19 @@ module rv_decode ...@@ -126,13 +132,19 @@ module rv_decode
wire d_is_shift = (d_fun == `FUNC_SL || d_fun == `FUNC_SR) && wire d_is_shift = (d_fun == `FUNC_SL || d_fun == `FUNC_SR) &&
(d_opcode == `OPC_OP || d_opcode == `OPC_OP_IMM ); (d_opcode == `OPC_OP || d_opcode == `OPC_OP_IMM );
reg x_is_mul;
wire d_is_mul = (f_ir_i[25] && d_fun == 3'b000);
always@* always@*
if (x_valid && f_valid_i && ( (f_rs1 == x_rd) || (f_rs2 == x_rd) ) && (!d_kill_i) ) if (x_valid && f_valid_i && ( (f_rs1 == x_rd) || (f_rs2 == x_rd) ) && (!d_kill_i) )
begin begin
case (x_opcode) case (x_opcode)
`OPC_LOAD: `OPC_LOAD:
load_hazard <= 1; load_hazard <= 1;
`OPC_OP, `OPC_OP:
load_hazard <= x_is_shift | x_is_mul;
`OPC_OP_IMM: `OPC_OP_IMM:
load_hazard <= x_is_shift; load_hazard <= x_is_shift;
default: default:
...@@ -141,8 +153,6 @@ module rv_decode ...@@ -141,8 +153,6 @@ module rv_decode
end else end else
load_hazard <= 0; load_hazard <= 0;
//wire load_hazard = x_valid && f_valid_i && ( (f_rs1 == x_rd) || (f_rs2 == x_rd) ) && (!d_kill_i) && (x_opcode == `OPC_LOAD);
reg inserting_nop = 0; reg inserting_nop = 0;
always@(posedge clk_i) always@(posedge clk_i)
...@@ -165,8 +175,8 @@ module rv_decode ...@@ -165,8 +175,8 @@ module rv_decode
begin begin
x_rs1 <= f_rs1; x_rs1 <= f_rs1;
x_rs2 <= f_rs2; x_rs2 <= f_rs2;
x_rd <= load_hazard ? 0 : f_ir_i [11:7]; x_rd <= (load_hazard && !inserting_nop) ? 0 : f_ir_i [11:7];
x_opcode <= load_hazard ? `OPC_OP : d_opcode; x_opcode <= (load_hazard && !inserting_nop) ? `OPC_OP : d_opcode;
load_hazard_d <= load_hazard; load_hazard_d <= load_hazard;
x_shamt_o <= f_ir_i[24:20]; x_shamt_o <= f_ir_i[24:20];
end end
...@@ -219,11 +229,15 @@ module rv_decode ...@@ -219,11 +229,15 @@ module rv_decode
if(!d_stall_i) if(!d_stall_i)
begin begin
x_is_shift <= d_is_shift; x_is_shift <= d_is_shift;
x_is_load_o <= ( d_opcode == `OPC_LOAD && !load_hazard) ? 1'b1 : 1'b0;
x_is_store_o <= ( d_opcode == `OPC_STORE && !load_hazard) ? 1'b1 : 1'b0;
x_is_signed_compare_o <= ( ( d_opcode == `OPC_BRANCH) && ( ( d_fun == `BRA_GE )|| (d_fun == `BRA_LT ) ) ) x_is_signed_compare_o <= ( ( d_opcode == `OPC_BRANCH) && ( ( d_fun == `BRA_GE )|| (d_fun == `BRA_LT ) ) )
|| ( ( (d_opcode == `OPC_OP) || (d_opcode == `OPC_OP_IMM) ) && (d_fun == `FUNC_SLT ) ); || ( ( (d_opcode == `OPC_OP) || (d_opcode == `OPC_OP_IMM) ) && (d_fun == `FUNC_SLT ) );
x_is_mul <= d_is_mul;
x_is_add_o <= (d_opcode == `OPC_AUIPC) || (d_opcode == `OPC_JAL) || x_is_add_o <= (d_opcode == `OPC_AUIPC) || (d_opcode == `OPC_JAL) ||
...@@ -232,6 +246,8 @@ module rv_decode ...@@ -232,6 +246,8 @@ module rv_decode
x_is_signed_alu_op_o <= (d_fun == `FUNC_SLT); x_is_signed_alu_op_o <= (d_fun == `FUNC_SLT);
// all multiply/divide instructions except MUL
x_is_undef_o <= (d_opcode == `OPC_OP && f_ir_i[25] && d_fun != 3'b000);
if(d_is_shift) if(d_is_shift)
x_rd_source_o <= `RD_SOURCE_SHIFTER; x_rd_source_o <= `RD_SOURCE_SHIFTER;
...@@ -247,11 +263,11 @@ module rv_decode ...@@ -247,11 +263,11 @@ module rv_decode
// rdest write value // rdest write value
case (d_opcode) case (d_opcode)
`OPC_OP_IMM, `OPC_OP, `OPC_JAL, `OPC_JALR, `OPC_LUI, `OPC_AUIPC: `OPC_OP_IMM, `OPC_OP, `OPC_JAL, `OPC_JALR, `OPC_LUI, `OPC_AUIPC:
x_rd_write_o <= 1; x_rd_write <= 1;
`OPC_SYSTEM: `OPC_SYSTEM:
x_rd_write_o <= (d_fun != 0); // CSR instructions write to RD x_rd_write <= (d_fun != 0); // CSR instructions write to RD
default: default:
x_rd_write_o <= 0; x_rd_write <= 0;
endcase // case (d_opcode) endcase // case (d_opcode)
end // if (!d_stall_i) end // if (!d_stall_i)
...@@ -271,6 +287,7 @@ module rv_decode ...@@ -271,6 +287,7 @@ module rv_decode
end end
assign x_is_shift_o = x_is_shift; assign x_is_shift_o = x_is_shift;
assign x_rd_write_o = x_rd_write;
......
...@@ -24,36 +24,38 @@ ...@@ -24,36 +24,38 @@
module rv_writeback module rv_writeback
( (
input clk_i, input clk_i,
input rst_i, input rst_i,
input w_stall_i, input w_stall_i,
output w_stall_req_o, output w_stall_req_o,
input [2:0] x_fun_i, input [2:0] x_fun_i,
input x_load_i, input x_load_i,
input x_store_i, input x_store_i,
input x_load_hazard_i, input x_load_hazard_i,
input [31:0] x_dm_addr_i, input [31:0] x_dm_addr_i,
input [4:0] x_rd_i, input [4:0] x_rd_i,
input [31:0] x_rd_value_i, input [31:0] x_rd_value_i,
input x_rd_write_i, input x_rd_write_i,
input x_valid_i,
input [31:0] x_shifter_rd_value_i,
input [31:0] x_multiply_rd_value_i,
input [1:0] x_rd_source_i,
input [31:0] dm_data_l_i,
input dm_load_done_i, input [31:0] x_shifter_rd_value_i,
input dm_store_done_i, input [31:0] x_multiply_rd_value_i,
input [1:0] x_rd_source_i,
input [31:0] dm_data_l_i,
input dm_load_done_i,
input dm_store_done_i,
output reg [31:0] rf_rd_value_o, output reg [31:0] rf_rd_value_o,
output [4:0] rf_rd_o, output [4:0] rf_rd_o,
output reg rf_rd_write_o, output reg rf_rd_write_o,
output [31:0] TRIG2 output [31:0] TRIG2
); );
reg [31:0] load_value; reg [31:0] load_value;
...@@ -102,31 +104,8 @@ module rv_writeback ...@@ -102,31 +104,8 @@ module rv_writeback
endcase // case (d_fun_i) endcase // case (d_fun_i)
end // always@ * end // always@ *
reg pending_load, pending_store;
always@(posedge clk_i)
if(rst_i) begin
pending_load <= 0;
pending_store <= 0;
end else begin
if(x_load_i && !dm_load_done_i) begin
pending_load <= 1;
end else if (dm_load_done_i) begin
pending_load <= 0;
end
if(x_store_i && !dm_store_done_i)
pending_store <= 1;
else if (dm_store_done_i)
pending_store <= 0;
end
always@* always@*
if( x_load_i || pending_load ) if( x_load_i )
rf_rd_value_o <= load_value; rf_rd_value_o <= load_value;
else if ( x_rd_source_i == `RD_SOURCE_SHIFTER ) else if ( x_rd_source_i == `RD_SOURCE_SHIFTER )
rf_rd_value_o <= x_shifter_rd_value_i; rf_rd_value_o <= x_shifter_rd_value_i;
...@@ -135,28 +114,20 @@ module rv_writeback ...@@ -135,28 +114,20 @@ module rv_writeback
else else
rf_rd_value_o <= x_rd_value_i; rf_rd_value_o <= x_rd_value_i;
always@* always@*
if (w_stall_i) if (w_stall_i)
rf_rd_write_o <= 0; rf_rd_write_o <= 0;
else if ( (x_load_i || pending_load) && dm_load_done_i) else if (x_load_i && dm_load_done_i)
rf_rd_write_o <= 1; rf_rd_write_o <= 1;
else else
rf_rd_write_o <= x_rd_write_i; rf_rd_write_o <= x_rd_write_i & x_valid_i;
// assign rf_rd_value_o = (x_load_i || pending_load ? load_value : x_rd_value_i );
assign rf_rd_o = (x_rd_i); assign rf_rd_o = (x_rd_i);
assign w_stall_req_o = (x_load_i && !dm_load_done_i) || (x_store_i && !dm_store_done_i);
assign w_stall_req_o = ((x_load_i || pending_load) && !dm_load_done_i) || ((x_store_i || pending_store) && !dm_store_done_i);
assign TRIG2[6] = x_load_i; assign TRIG2[6] = x_load_i;
assign TRIG2[7] = pending_load;
assign TRIG2[8] = dm_load_done_i; assign TRIG2[8] = dm_load_done_i;
assign TRIG2[9] = x_store_i; assign TRIG2[9] = x_store_i;
assign TRIG2[10] = pending_store;
assign TRIG2[11] = dm_store_done_i; assign TRIG2[11] = dm_store_done_i;
assign TRIG2[15] = w_stall_req_o; assign TRIG2[15] = w_stall_req_o;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment