Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion bhv/cv32e40x_wrapper.sv
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
`include "cv32e40x_rvfi_sva.sv"
`include "cv32e40x_sequencer_sva.sv"
`include "cv32e40x_clic_int_controller_sva.sv"
`include "cv32e40x_register_file_sva.sv"
`endif

`include "cv32e40x_wrapper.vh"
Expand Down Expand Up @@ -166,7 +167,7 @@ module cv32e40x_wrapper
);

bind cv32e40x_id_stage:
core_i.id_stage_i cv32e40x_id_stage_sva id_stage_sva
core_i.id_stage_i cv32e40x_id_stage_sva #(.RV32(RV32)) id_stage_sva
(
.jmp_taken_id_ctrl_i (core_i.controller_i.controller_fsm_i.jump_taken_id),
.*
Expand Down Expand Up @@ -196,6 +197,11 @@ module cv32e40x_wrapper
.illegal_insn (core_i.id_stage_i.illegal_insn ),
.*);

bind cv32e40x_register_file:
core_i.register_file_wrapper_i.register_file_i cv32e40x_register_file_sva #(.RV32(RV32))
register_file_sva
(.*);

generate
if(M_EXT != M_NONE) begin: mul_sva
bind cv32e40x_mult:
Expand Down
8 changes: 6 additions & 2 deletions rtl/cv32e40x_core.sv
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
module cv32e40x_core import cv32e40x_pkg::*;
#(
parameter LIB = 0,
parameter rv32_e RV32 = RV32I, // todo: Add support for RV32E
parameter rv32_e RV32 = RV32I,
parameter bit A_EXT = 0,
parameter b_ext_e B_EXT = B_NONE,
parameter m_ext_e M_EXT = M,
Expand Down Expand Up @@ -414,6 +414,7 @@ module cv32e40x_core import cv32e40x_pkg::*;

cv32e40x_if_stage
#(
.RV32 ( RV32 ),
.A_EXT ( A_EXT ),
.B_EXT ( B_EXT ),
.X_EXT ( X_EXT ),
Expand Down Expand Up @@ -478,6 +479,7 @@ module cv32e40x_core import cv32e40x_pkg::*;

cv32e40x_id_stage
#(
.RV32 ( RV32 ),
.A_EXT ( A_EXT ),
.B_EXT ( B_EXT ),
.M_EXT ( M_EXT ),
Expand Down Expand Up @@ -716,6 +718,7 @@ module cv32e40x_core import cv32e40x_pkg::*;

cv32e40x_cs_registers
#(
.RV32 ( RV32 ),
.A_EXT ( A_EXT ),
.M_EXT ( M_EXT ),
.X_EXT ( X_EXT ),
Expand Down Expand Up @@ -1014,7 +1017,8 @@ module cv32e40x_core import cv32e40x_pkg::*;

cv32e40x_register_file_wrapper
#(
.REGFILE_NUM_READ_PORTS ( REGFILE_NUM_READ_PORTS )
.REGFILE_NUM_READ_PORTS ( REGFILE_NUM_READ_PORTS ),
.RV32 ( RV32 )
)
register_file_wrapper_i
(
Expand Down
16 changes: 9 additions & 7 deletions rtl/cv32e40x_cs_registers.sv
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

module cv32e40x_cs_registers import cv32e40x_pkg::*;
#(
parameter rv32_e RV32 = RV32I,
parameter bit A_EXT = 0,
parameter m_ext_e M_EXT = M,
parameter bit X_EXT = 0,
Expand Down Expand Up @@ -106,13 +107,14 @@ module cv32e40x_cs_registers import cv32e40x_pkg::*;
);

localparam logic [31:0] CORE_MISA =
(32'(A_EXT) << 0) | // A - Atomic Instructions extension
(32'(1) << 2) | // C - Compressed extension
(32'(1) << 8) | // I - RV32I/64I/128I base ISA
(32'(M_EXT == M) << 12) | // M - Integer Multiply/Divide extension
(32'(0) << 20) | // U - User mode implemented
(32'(1) << 23) | // X - Non-standard extensions present
(32'(MXL) << 30); // M-XLEN
(32'(A_EXT) << 0) | // A - Atomic Instructions extension
(32'(1) << 2) | // C - Compressed extension
(32'(RV32 == RV32E) << 4) | // E - RV32E/64E base ISA
(32'(RV32 == RV32I) << 8) | // I - RV32I/64I/128I base ISA
(32'(M_EXT == M) << 12) | // M - Integer Multiply/Divide extension
(32'(0) << 20) | // U - User mode implemented
(32'(1) << 23) | // X - Non-standard extensions present
(32'(MXL) << 30); // M-XLEN

localparam logic [31:0] MISA_VALUE = CORE_MISA | (X_EXT ? X_MISA : 32'h0000_0000);

Expand Down
109 changes: 81 additions & 28 deletions rtl/cv32e40x_decoder.sv
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

module cv32e40x_decoder import cv32e40x_pkg::*;
#(
parameter rv32_e RV32 = RV32I,
parameter int unsigned REGFILE_NUM_READ_PORTS = 2,
parameter bit A_EXT = 0,
parameter b_ext_e B_EXT = B_NONE,
parameter m_ext_e M_EXT = M,
Expand Down Expand Up @@ -84,6 +86,10 @@ module cv32e40x_decoder import cv32e40x_pkg::*;
output logic rf_we_o, // Write enable for register file
output logic [1:0] rf_re_o,

input rf_addr_t rf_raddr_i[REGFILE_NUM_READ_PORTS],
input rf_addr_t rf_waddr_i,
output logic [REGFILE_NUM_READ_PORTS-1:0] rf_illegal_raddr_o,

// Mux selects
output op_c_mux_e op_c_mux_sel_o, // Operand c selection: reg value or jump target
output imm_a_mux_e imm_a_mux_sel_o, // Immediate selection for operand a
Expand All @@ -108,15 +114,30 @@ module cv32e40x_decoder import cv32e40x_pkg::*;

logic [31:0] instr_rdata;

decoder_ctrl_t decoder_i_ctrl;
decoder_ctrl_t decoder_m_ctrl;
decoder_ctrl_t decoder_a_ctrl;
decoder_ctrl_t decoder_b_ctrl;
decoder_ctrl_t decoder_ctrl_mux_subdec;
logic dec_i_rf_illegal_addr;
logic dec_a_rf_illegal_addr;
logic dec_b_rf_illegal_addr;
logic dec_m_rf_illegal_addr;
logic rf_illegal_waddr;

decoder_ctrl_t decoder_i_ctrl, decoder_i_ctrl_int;
decoder_ctrl_t decoder_m_ctrl, decoder_m_ctrl_int;
decoder_ctrl_t decoder_a_ctrl, decoder_a_ctrl_int;
decoder_ctrl_t decoder_b_ctrl, decoder_b_ctrl_int;
decoder_ctrl_t decoder_ctrl_mux;

assign instr_rdata = if_id_pipe_i.instr.bus_resp.rdata;

// Check for illegal GPR address if using RV32E
genvar rf_rport_idx;
generate
for (rf_rport_idx = 0; rf_rport_idx < REGFILE_NUM_READ_PORTS; rf_rport_idx++) begin: gen_rf_raddr_illegal
assign rf_illegal_raddr_o[rf_rport_idx] = (RV32 == RV32I) ? 1'b0 : rf_raddr_i[rf_rport_idx][4];
end
endgenerate

assign rf_illegal_waddr = (RV32 == RV32I) ? 1'b0 : rf_waddr_i[4];

// RV32I Base instruction set decoder
cv32e40x_i_decoder
#(
Expand All @@ -125,20 +146,40 @@ module cv32e40x_decoder import cv32e40x_pkg::*;
)
i_decoder_i
(
.instr_rdata_i ( instr_rdata ),
.ctrl_fsm_i ( ctrl_fsm_i ),
.decoder_ctrl_o ( decoder_i_ctrl )
.instr_rdata_i ( instr_rdata ),
.ctrl_fsm_i ( ctrl_fsm_i ),
.decoder_ctrl_o ( decoder_i_ctrl_int )
);

assign dec_i_rf_illegal_addr = (decoder_i_ctrl_int.rf_re[0] && rf_illegal_raddr_o[0]) ||
(decoder_i_ctrl_int.rf_re[1] && rf_illegal_raddr_o[1]) ||
(decoder_i_ctrl_int.rf_we && rf_illegal_waddr);

// Take illegal compressed instruction and illegal RV32E GPR address into account
assign decoder_i_ctrl = (dec_i_rf_illegal_addr || if_id_pipe_i.illegal_c_insn) ?
DECODER_CTRL_ILLEGAL_INSN :
decoder_i_ctrl_int;

generate
if (A_EXT) begin: a_decoder
// RV32A extension decoder
cv32e40x_a_decoder a_decoder_i
(
.instr_rdata_i ( instr_rdata ),
.decoder_ctrl_o ( decoder_a_ctrl )
.instr_rdata_i ( instr_rdata ),
.decoder_ctrl_o ( decoder_a_ctrl_int )
);

assign dec_a_rf_illegal_addr = (decoder_a_ctrl_int.rf_re[0] && rf_illegal_raddr_o[0]) ||
Copy link
Contributor

Choose a reason for hiding this comment

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

Assign this signal to 1'b0 in 'else' part of generate statement so that we do net get floating signals (even though they are not used). Same remark for other similar signals.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

(decoder_a_ctrl_int.rf_re[1] && rf_illegal_raddr_o[1]) ||
(decoder_a_ctrl_int.rf_we && rf_illegal_waddr);

// Take illegal compressed instruction and illegal RV32E GPR address into account
assign decoder_a_ctrl = (dec_a_rf_illegal_addr || if_id_pipe_i.illegal_c_insn) ?
DECODER_CTRL_ILLEGAL_INSN :
decoder_a_ctrl_int;

end else begin: no_a_decoder
assign dec_a_rf_illegal_addr = 1'b0;
assign decoder_a_ctrl = DECODER_CTRL_ILLEGAL_INSN;
end

Expand All @@ -151,9 +192,20 @@ module cv32e40x_decoder import cv32e40x_pkg::*;
b_decoder_i
(
.instr_rdata_i ( instr_rdata ),
.decoder_ctrl_o ( decoder_b_ctrl )
.decoder_ctrl_o ( decoder_b_ctrl_int )
);

assign dec_b_rf_illegal_addr = (decoder_b_ctrl_int.rf_re[0] && rf_illegal_raddr_o[0]) ||
(decoder_b_ctrl_int.rf_re[1] && rf_illegal_raddr_o[1]) ||
(decoder_b_ctrl_int.rf_we && rf_illegal_waddr);

// Take illegal compressed instruction and illegal RV32E GPR address into account
assign decoder_b_ctrl = (dec_b_rf_illegal_addr || if_id_pipe_i.illegal_c_insn) ?
DECODER_CTRL_ILLEGAL_INSN :
decoder_b_ctrl_int;

end else begin: no_b_decoder
assign dec_b_rf_illegal_addr = 1'b0;
assign decoder_b_ctrl = DECODER_CTRL_ILLEGAL_INSN;
end

Expand All @@ -165,10 +217,21 @@ module cv32e40x_decoder import cv32e40x_pkg::*;
)
m_decoder_i
(
.instr_rdata_i ( instr_rdata ),
.decoder_ctrl_o ( decoder_m_ctrl )
.instr_rdata_i ( instr_rdata ),
.decoder_ctrl_o ( decoder_m_ctrl_int )
);

assign dec_m_rf_illegal_addr = (decoder_m_ctrl_int.rf_re[0] && rf_illegal_raddr_o[0]) ||
(decoder_m_ctrl_int.rf_re[1] && rf_illegal_raddr_o[1]) ||
(decoder_m_ctrl_int.rf_we && rf_illegal_waddr);

// Take illegal compressed instruction and illegal RV32E GPR address into account
assign decoder_m_ctrl = (dec_m_rf_illegal_addr || if_id_pipe_i.illegal_c_insn) ?
DECODER_CTRL_ILLEGAL_INSN :
decoder_m_ctrl_int;

end else begin: no_m_decoder
assign dec_m_rf_illegal_addr = 1'b0;
assign decoder_m_ctrl = DECODER_CTRL_ILLEGAL_INSN;
end

Expand All @@ -178,24 +241,14 @@ module cv32e40x_decoder import cv32e40x_pkg::*;
always_comb
begin
unique case (1'b1)
!decoder_m_ctrl.illegal_insn : decoder_ctrl_mux_subdec = decoder_m_ctrl; // M decoder got a match
!decoder_a_ctrl.illegal_insn : decoder_ctrl_mux_subdec = decoder_a_ctrl; // A decoder got a match
!decoder_i_ctrl.illegal_insn : decoder_ctrl_mux_subdec = decoder_i_ctrl; // I decoder got a match
!decoder_b_ctrl.illegal_insn : decoder_ctrl_mux_subdec = decoder_b_ctrl; // B decoder got a match
default : decoder_ctrl_mux_subdec = DECODER_CTRL_ILLEGAL_INSN; // No match from decoders, illegal instruction
!decoder_m_ctrl.illegal_insn : decoder_ctrl_mux = decoder_m_ctrl; // M decoder got a match
!decoder_a_ctrl.illegal_insn : decoder_ctrl_mux = decoder_a_ctrl; // A decoder got a match
!decoder_i_ctrl.illegal_insn : decoder_ctrl_mux = decoder_i_ctrl; // I decoder got a match
!decoder_b_ctrl.illegal_insn : decoder_ctrl_mux = decoder_b_ctrl; // B decoder got a match
default : decoder_ctrl_mux = DECODER_CTRL_ILLEGAL_INSN; // No match from decoders, illegal instruction
endcase
end

// Take illegal compressed instruction into account
always_comb begin
if (if_id_pipe_i.illegal_c_insn) begin
decoder_ctrl_mux = DECODER_CTRL_ILLEGAL_INSN;
end
else begin
decoder_ctrl_mux = decoder_ctrl_mux_subdec;
end
end

assign alu_en = decoder_ctrl_mux.alu_en;
assign alu_bch_o = decoder_i_ctrl.alu_bch; // Only I decoder handles branches/jumps
assign alu_jmp_o = decoder_i_ctrl.alu_jmp; // Only I decoder handles branches/jumps
Expand Down
13 changes: 10 additions & 3 deletions rtl/cv32e40x_id_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

module cv32e40x_id_stage import cv32e40x_pkg::*;
#(
parameter rv32_e RV32 = RV32I,
parameter bit A_EXT = 0,
parameter b_ext_e B_EXT = B_NONE,
parameter m_ext_e M_EXT = M,
Expand Down Expand Up @@ -119,6 +120,7 @@ module cv32e40x_id_stage import cv32e40x_pkg::*;
logic rf_we;
logic rf_we_dec;
rf_addr_t rf_waddr;
logic [REGFILE_NUM_READ_PORTS-1:0] rf_illegal_raddr;

// ALU Control
logic alu_en;
Expand Down Expand Up @@ -404,6 +406,8 @@ module cv32e40x_id_stage import cv32e40x_pkg::*;

cv32e40x_decoder
#(
.RV32 ( RV32 ),
.REGFILE_NUM_READ_PORTS ( REGFILE_NUM_READ_PORTS ),
.A_EXT ( A_EXT ),
.B_EXT ( B_EXT ),
.M_EXT ( M_EXT ),
Expand Down Expand Up @@ -462,6 +466,9 @@ module cv32e40x_id_stage import cv32e40x_pkg::*;
// Register file control signals
.rf_re_o ( rf_re ),
.rf_we_o ( rf_we_dec ),
.rf_raddr_i ( rf_raddr_o ),
.rf_waddr_i ( rf_waddr ),
.rf_illegal_raddr_o ( rf_illegal_raddr ),

// Mux selects
.imm_a_mux_sel_o ( imm_a_mux_sel ),
Expand Down Expand Up @@ -739,16 +746,16 @@ module cv32e40x_id_stage import cv32e40x_pkg::*;
xif_issue_if.issue_req.rs_valid = '0;
if (xif_issue_if.X_NUM_RS > 0) begin
xif_issue_if.issue_req.rs [0] = operand_a_fw;
xif_issue_if.issue_req.rs_valid[0] = 1'b1;
xif_issue_if.issue_req.rs_valid[0] = !rf_illegal_raddr[0];
end
if (xif_issue_if.X_NUM_RS > 1) begin
xif_issue_if.issue_req.rs [1] = operand_b_fw;
xif_issue_if.issue_req.rs_valid[1] = 1'b1;
xif_issue_if.issue_req.rs_valid[1] = !rf_illegal_raddr[1];
end
// TODO: implement forwarding for other operands than rs1 and rs2
for (integer i = 2; i < xif_issue_if.X_NUM_RS && i < REGFILE_NUM_READ_PORTS; i++) begin
xif_issue_if.issue_req.rs [i] = rf_rdata_i[i];
xif_issue_if.issue_req.rs_valid[i] = 1'b1;
xif_issue_if.issue_req.rs_valid[i] = !rf_illegal_raddr[i];
end
end

Expand Down
2 changes: 2 additions & 0 deletions rtl/cv32e40x_if_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

module cv32e40x_if_stage import cv32e40x_pkg::*;
#(
parameter rv32_e RV32 = RV32I,
parameter bit A_EXT = 0,
parameter b_ext_e B_EXT = B_NONE,
parameter bit X_EXT = 0,
Expand Down Expand Up @@ -424,6 +425,7 @@ module cv32e40x_if_stage import cv32e40x_pkg::*;
generate
if (ZC_EXT) begin : gen_seq
cv32e40x_sequencer
#(.RV32(RV32))
sequencer_i
(
.clk ( clk ),
Expand Down
9 changes: 7 additions & 2 deletions rtl/cv32e40x_register_file.sv
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@

module cv32e40x_register_file import cv32e40x_pkg::*;
#(
parameter int unsigned REGFILE_NUM_READ_PORTS = 2
parameter int unsigned REGFILE_NUM_READ_PORTS = 2,
parameter rv32_e RV32 = RV32I
)
(
// Clock and Reset
Expand All @@ -45,6 +46,10 @@ module cv32e40x_register_file import cv32e40x_pkg::*;
input logic we_i [REGFILE_NUM_WRITE_PORTS]
);

// Number of regfile integer registers
localparam REGFILE_NUM_WORDS = (RV32 == RV32I) ? 32 : 16;
localparam REGFILE_IMPL_ADDR_WIDTH = $clog2(REGFILE_NUM_WORDS);

// integer register file
logic [REGFILE_WORD_WIDTH-1:0] mem [REGFILE_NUM_WORDS];

Expand All @@ -57,7 +62,7 @@ module cv32e40x_register_file import cv32e40x_pkg::*;
genvar ridx;
generate
for (ridx=0; ridx<REGFILE_NUM_READ_PORTS; ridx++) begin : gen_regfile_rdata
assign rdata_o[ridx] = mem[raddr_i[ridx]];
assign rdata_o[ridx] = mem[raddr_i[ridx][REGFILE_IMPL_ADDR_WIDTH-1:0]];
end
endgenerate

Expand Down
Loading