Rework ID stage and decoder

This commit moves logic directly related to the decoder from the ID
stage into the decoder. This logic includes:
- Generation of immediates and decoder-based mux selectors
- Generation of register file addresses
- CSR operand check and manipulation depending on value in `rs1`
- Register file address check for RV32E (still disabled)

The muxes themselves stay in the ID stage as their control signals also
depend also on other, non-decoder-based signals (LSU, EX, WB FSM).
This commit is contained in:
Pirmin Vogel 2019-07-03 11:33:35 +01:00
parent d64eaad817
commit 1174603e76
3 changed files with 247 additions and 198 deletions

View file

@ -765,7 +765,7 @@ module ibex_core #(
.cluster_id_i ( cluster_id_i ),
.pc_i ( id_stage_i.pc_id_i ),
.instr_i ( id_stage_i.instr ),
.instr_i ( id_stage_i.instr_rdata_i ),
.compressed_i ( id_stage_i.instr_is_compressed_i ),
.id_valid_i ( id_stage_i.id_valid_o ),
.is_decoding_i ( id_stage_i.is_decoding_o ),
@ -782,9 +782,9 @@ module ibex_core #(
.lsu_value_i ( data_wdata_ex ),
.ex_reg_addr_i ( id_stage_i.regfile_waddr_id ),
.ex_reg_addr_i ( id_stage_i.regfile_waddr ),
.ex_reg_we_i ( id_stage_i.regfile_we ),
.ex_reg_wdata_i ( id_stage_i.regfile_wdata_id ),
.ex_reg_wdata_i ( id_stage_i.regfile_wdata ),
.data_valid_lsu_i ( data_valid_lsu ),
.ex_data_addr_i ( data_addr_o ),
.ex_data_req_i ( data_req_o ),

View file

@ -21,13 +21,19 @@
// //
////////////////////////////////////////////////////////////////////////////////
// Source/Destination register instruction index
`define REG_S1 19:15
`define REG_S2 24:20
`define REG_D 11:07
/**
* Instruction decoder
*/
module ibex_decoder #(
parameter bit RV32M = 1
parameter bit RV32E = 0,
parameter bit RV32M = 1
) (
// singals running to/from controller
// to/from controller
output logic illegal_insn_o, // illegal instr encountered
output logic ebrk_insn_o, // trap instr encountered
output logic mret_insn_o, // return from exception instr
@ -37,38 +43,48 @@ module ibex_decoder #(
output logic pipe_flush_o, // pipeline flush is requested
output logic jump_set_o, // jump taken set signal
// from IF/ID pipeline
// from IF-ID pipeline register
input logic instr_new_i, // instruction read is new
input logic [31:0] instr_rdata_i, // instruction read from memory/cache
input logic illegal_c_insn_i, // compressed instruction decode failed
// ALU signals
// immediates
output ibex_defines::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a
output ibex_defines::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b
output logic [31:0] imm_i_type_o,
output logic [31:0] imm_s_type_o,
output logic [31:0] imm_b_type_o,
output logic [31:0] imm_u_type_o,
output logic [31:0] imm_j_type_o,
output logic [31:0] zimm_rs1_type_o,
// register file
output ibex_defines::rf_wd_sel_e regfile_wdata_sel_o, // RF write data selection
output logic regfile_we_o, // write enable for regfile
output logic [4:0] regfile_raddr_a_o,
output logic [4:0] regfile_raddr_b_o,
output logic [4:0] regfile_waddr_o,
// ALU
output ibex_defines::alu_op_e alu_operator_o, // ALU operation selection
output ibex_defines::op_a_sel_e alu_op_a_mux_sel_o, // operand a selection: reg value, PC,
// immediate or zero
output ibex_defines::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or
// immediate
output ibex_defines::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a
output ibex_defines::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b
// MUL, DIV related control signals
// MULT & DIV
output logic mult_en_o, // perform integer multiplication
output logic div_en_o, // perform integer division or
// remainder
output ibex_defines::md_op_e multdiv_operator_o,
output logic [1:0] multdiv_signed_mode_o,
// register file related signals
output ibex_defines::rf_wd_sel_e regfile_wdata_sel_o, // RF write data selection
output logic regfile_we_o, // write enable for regfile
// CSR manipulation
// CSRs
output logic csr_access_o, // access to CSR
output ibex_defines::csr_op_e csr_op_o, // operation to perform on CSR
output logic csr_status_o, // access to xstatus CSR
// LSU signals
// LSU
output logic data_req_o, // start transaction to data memory
output logic data_we_o, // write enable
output logic [1:0] data_type_o, // size of transaction: byte, half
@ -84,9 +100,60 @@ module ibex_decoder #(
import ibex_defines::*;
logic csr_illegal;
logic illegal_reg_rv32e;
logic csr_illegal;
logic [31:0] instr;
opcode_e opcode;
csr_op_e csr_op;
opcode_e opcode;
assign instr = instr_rdata_i;
//////////////////////////////////////
// Register and immediate selection //
//////////////////////////////////////
// immediate extraction and sign extension
assign imm_i_type_o = { {20{instr[31]}}, instr[31:20] };
assign imm_s_type_o = { {20{instr[31]}}, instr[31:25], instr[11:7] };
assign imm_b_type_o = { {19{instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0 };
assign imm_u_type_o = { instr[31:12], 12'b0 };
assign imm_j_type_o = { {12{instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 };
// immediate for CSR manipulation (zero extended)
assign zimm_rs1_type_o = { 27'b0, instr[`REG_S1] }; // rs1
// source registers
assign regfile_raddr_a_o = instr[`REG_S1]; // rs1
assign regfile_raddr_b_o = instr[`REG_S2]; // rs2
// destination register
assign regfile_waddr_o = instr[`REG_D]; // rd
////////////////////
// Register check //
////////////////////
//if (RV32E)
// assign illegal_reg_rv32e = (regfile_raddr_a_o[4] |
// regfile_raddr_b_o[4] |
// regfile_waddr_o[4]);
//else
assign illegal_reg_rv32e = 1'b0;
///////////////////////
// CSR operand check //
///////////////////////
always_comb begin : csr_operand_check
csr_op_o = csr_op;
// CSRRSI/CSRRCI must not write 0 to CSRs (uimm[4:0]=='0)
// CSRRS/CSRRC must not write from x0 to CSRs (rs1=='0)
if ((csr_op == CSR_OP_SET || csr_op == CSR_OP_CLEAR) &&
instr[`REG_S1] == '0) begin
csr_op_o = CSR_OP_READ;
end
end
/////////////
// Decoder //
@ -114,7 +181,7 @@ module ibex_decoder #(
csr_access_o = 1'b0;
csr_status_o = 1'b0;
csr_illegal = 1'b0;
csr_op_o = CSR_OP_READ;
csr_op = CSR_OP_READ;
data_we_o = 1'b0;
data_type_o = 2'b00;
@ -129,7 +196,7 @@ module ibex_decoder #(
ecall_insn_o = 1'b0;
pipe_flush_o = 1'b0;
opcode = opcode_e'(instr_rdata_i[6:0]);
opcode = opcode_e'(instr[6:0]);
unique case (opcode)
@ -174,7 +241,7 @@ module ibex_decoder #(
alu_operator_o = ALU_ADD;
regfile_we_o = 1'b1;
end
if (instr_rdata_i[14:12] != 3'b0) begin
if (instr[14:12] != 3'b0) begin
illegal_insn_o = 1'b1;
end
end
@ -182,7 +249,7 @@ module ibex_decoder #(
OPCODE_BRANCH: begin // Branch
branch_in_dec_o = 1'b1;
if (instr_new_i) begin
unique case (instr_rdata_i[14:12])
unique case (instr[14:12])
3'b000: alu_operator_o = ALU_EQ;
3'b001: alu_operator_o = ALU_NE;
3'b100: alu_operator_o = ALU_LT;
@ -210,7 +277,7 @@ module ibex_decoder #(
data_we_o = 1'b1;
alu_operator_o = ALU_ADD;
if (!instr_rdata_i[14]) begin
if (!instr[14]) begin
// offset from immediate
imm_b_mux_sel_o = IMM_B_S;
alu_op_b_mux_sel_o = OP_B_IMM;
@ -220,7 +287,7 @@ module ibex_decoder #(
end
// store size
unique case (instr_rdata_i[13:12])
unique case (instr[13:12])
2'b00: data_type_o = 2'b10; // SB
2'b01: data_type_o = 2'b01; // SH
2'b10: data_type_o = 2'b00; // SW
@ -242,10 +309,10 @@ module ibex_decoder #(
imm_b_mux_sel_o = IMM_B_I;
// sign/zero extension
data_sign_extension_o = ~instr_rdata_i[14];
data_sign_extension_o = ~instr[14];
// load size
unique case (instr_rdata_i[13:12])
unique case (instr[13:12])
2'b00: data_type_o = 2'b10; // LB
2'b01: data_type_o = 2'b01; // LH
2'b10: data_type_o = 2'b00; // LW
@ -253,15 +320,15 @@ module ibex_decoder #(
endcase
// reg-reg load (different encoding)
if (instr_rdata_i[14:12] == 3'b111) begin
if (instr[14:12] == 3'b111) begin
// offset from RS2
alu_op_b_mux_sel_o = OP_B_REG_B;
// sign/zero extension
data_sign_extension_o = ~instr_rdata_i[30];
data_sign_extension_o = ~instr[30];
// load size
unique case (instr_rdata_i[31:25])
unique case (instr[31:25])
7'b0000_000,
7'b0100_000: data_type_o = 2'b10; // LB, LBU
7'b0001_000,
@ -273,7 +340,7 @@ module ibex_decoder #(
endcase
end
if (instr_rdata_i[14:12] == 3'b011) begin
if (instr[14:12] == 3'b011) begin
// LD -> RV64 only
illegal_insn_o = 1'b1;
end
@ -305,7 +372,7 @@ module ibex_decoder #(
imm_b_mux_sel_o = IMM_B_I;
regfile_we_o = 1'b1;
unique case (instr_rdata_i[14:12])
unique case (instr[14:12])
3'b000: alu_operator_o = ALU_ADD; // Add Immediate
3'b010: alu_operator_o = ALU_SLT; // Set to one if Lower Than Immediate
3'b011: alu_operator_o = ALU_SLTU; // Set to one if Lower Than Immediate Unsigned
@ -315,15 +382,15 @@ module ibex_decoder #(
3'b001: begin
alu_operator_o = ALU_SLL; // Shift Left Logical by Immediate
if (instr_rdata_i[31:25] != 7'b0) begin
if (instr[31:25] != 7'b0) begin
illegal_insn_o = 1'b1;
end
end
3'b101: begin
if (instr_rdata_i[31:25] == 7'b0) begin
if (instr[31:25] == 7'b0) begin
alu_operator_o = ALU_SRL; // Shift Right Logical by Immediate
end else if (instr_rdata_i[31:25] == 7'b010_0000) begin
end else if (instr[31:25] == 7'b010_0000) begin
alu_operator_o = ALU_SRA; // Shift Right Arithmetically by Immediate
end else begin
illegal_insn_o = 1'b1;
@ -339,10 +406,10 @@ module ibex_decoder #(
OPCODE_OP: begin // Register-Register ALU operation
regfile_we_o = 1'b1;
if (instr_rdata_i[31]) begin
if (instr[31]) begin
illegal_insn_o = 1'b1;
end else if (!instr_rdata_i[28]) begin // non bit-manipulation instructions
unique case ({instr_rdata_i[30:25], instr_rdata_i[14:12]})
end else if (!instr[28]) begin // non bit-manipulation instructions
unique case ({instr[30:25], instr[14:12]})
// RV32I ALU operations
{6'b00_0000, 3'b000}: alu_operator_o = ALU_ADD; // Add
{6'b10_0000, 3'b000}: alu_operator_o = ALU_SUB; // Sub
@ -430,7 +497,7 @@ module ibex_decoder #(
// fence.i (funct3 == 001) was moved to a separate Zifencei extension
// in the RISC-V ISA spec proposed for ratification, so we treat it as
// an illegal instruction.
if (instr_rdata_i[14:12] == 3'b000) begin
if (instr[14:12] == 3'b000) begin
alu_operator_o = ALU_ADD; // nop
regfile_we_o = 1'b0;
end else begin
@ -439,9 +506,9 @@ module ibex_decoder #(
end
OPCODE_SYSTEM: begin
if (instr_rdata_i[14:12] == 3'b000) begin
if (instr[14:12] == 3'b000) begin
// non CSR related SYSTEM instructions
unique case (instr_rdata_i[31:20])
unique case (instr[31:20])
12'h000: // ECALL
// environment (system) call
ecall_insn_o = 1'b1;
@ -472,27 +539,27 @@ module ibex_decoder #(
imm_a_mux_sel_o = IMM_A_Z;
imm_b_mux_sel_o = IMM_B_I; // CSR address is encoded in I imm
if (instr_rdata_i[14]) begin
if (instr[14]) begin
// rs1 field is used as immediate
alu_op_a_mux_sel_o = OP_A_IMM;
end else begin
alu_op_a_mux_sel_o = OP_A_REG_A;
end
unique case (instr_rdata_i[13:12])
2'b01: csr_op_o = CSR_OP_WRITE;
2'b10: csr_op_o = CSR_OP_SET;
2'b11: csr_op_o = CSR_OP_CLEAR;
unique case (instr[13:12])
2'b01: csr_op = CSR_OP_WRITE;
2'b10: csr_op = CSR_OP_SET;
2'b11: csr_op = CSR_OP_CLEAR;
default: csr_illegal = 1'b1;
endcase
if (!csr_illegal) begin
// flush pipeline on access to mstatus or debug CSRs
if (csr_num_e'(instr_rdata_i[31:20]) == CSR_MSTATUS ||
csr_num_e'(instr_rdata_i[31:20]) == CSR_DCSR ||
csr_num_e'(instr_rdata_i[31:20]) == CSR_DPC ||
csr_num_e'(instr_rdata_i[31:20]) == CSR_DSCRATCH0 ||
csr_num_e'(instr_rdata_i[31:20]) == CSR_DSCRATCH1) begin
if (csr_num_e'(instr[31:20]) == CSR_MSTATUS ||
csr_num_e'(instr[31:20]) == CSR_DCSR ||
csr_num_e'(instr[31:20]) == CSR_DPC ||
csr_num_e'(instr[31:20]) == CSR_DSCRATCH0 ||
csr_num_e'(instr[31:20]) == CSR_DSCRATCH1) begin
csr_status_o = 1'b1;
end
end
@ -511,6 +578,12 @@ module ibex_decoder #(
illegal_insn_o = 1'b1;
end
// make sure instructions accessing non-available registers in RV32E cause illegal
// instruction exceptions
if (illegal_reg_rv32e) begin
illegal_insn_o = 1'b1;
end
// make sure illegal instructions detected in the decoder do not propagate from decoder
// into register file, LSU, EX, WB, CSRs
// NOTE: instructions can also be detected to be illegal inside the CSRs (upon accesses with

View file

@ -21,15 +21,10 @@
// //
////////////////////////////////////////////////////////////////////////////////
// Source/Destination register instruction index
`define REG_S1 19:15
`define REG_S2 24:20
`define REG_D 11:07
`ifdef RISCV_FORMAL
`define RVFI
`endif
/**
* Instruction Decode Stage
*
@ -155,13 +150,10 @@ module ibex_id_stage #(
import ibex_defines::*;
logic [31:0] instr;
// Decoder/Controller ID stage internal signals
logic deassert_we;
logic illegal_insn_dec;
logic illegal_reg_rv32e;
logic ebrk_insn;
logic mret_insn_dec;
logic dret_insn_dec;
@ -198,15 +190,15 @@ module ibex_id_stage #(
logic exc_ack, exc_kill;// handshake
// Register file interface
logic [4:0] regfile_addr_ra_id;
logic [4:0] regfile_addr_rb_id;
logic [4:0] regfile_raddr_a;
logic [4:0] regfile_raddr_b;
logic [4:0] regfile_waddr_id;
logic [4:0] regfile_waddr;
logic regfile_we_id, regfile_we_dec;
logic [31:0] regfile_data_ra_id;
logic [31:0] regfile_data_rb_id;
logic [31:0] regfile_wdata_id;
logic [31:0] regfile_rdata_a;
logic [31:0] regfile_rdata_b;
logic [31:0] regfile_wdata;
rf_wd_sel_e regfile_wdata_sel;
logic regfile_we;
@ -245,36 +237,6 @@ module ibex_id_stage #(
logic [31:0] alu_operand_a;
logic [31:0] alu_operand_b;
assign instr = instr_rdata_i;
// immediate extraction and sign extension
assign imm_i_type = { {20 {instr[31]}}, instr[31:20] };
assign imm_s_type = { {20 {instr[31]}}, instr[31:25], instr[11:7] };
assign imm_b_type = { {19 {instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0 };
assign imm_u_type = { instr[31:12], 12'b0 };
assign imm_j_type = { {12 {instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 };
// immediate for CSR manipulatin (zero extended)
assign zimm_rs1_type = { 27'b0, instr[`REG_S1] };
///////////////////////////////
// Source register selection //
///////////////////////////////
assign regfile_addr_ra_id = instr[`REG_S1];
assign regfile_addr_rb_id = instr[`REG_S2];
///////////////////////////
// Destination registers //
///////////////////////////
assign regfile_waddr_id = instr[`REG_D];
//if (RV32E)
// assign illegal_reg_rv32e = (regfile_addr_ra_id[4] |
// regfile_addr_rb_id[4] |
// regfile_waddr_id[4]);
//else
assign illegal_reg_rv32e = 1'b0;
/////////////
// LSU Mux //
/////////////
@ -287,28 +249,29 @@ module ibex_id_stage #(
// do not write back the second address since the first calculated address was the correct one
assign regfile_we_id = data_misaligned_i ? 1'b0 : regfile_we_dec & ~deassert_we;
///////////////
// Operand A //
///////////////
///////////////////
// Operand A MUX //
///////////////////
// ALU_Op_a Mux
// Immediate MUX for Operand A
assign imm_a = (imm_a_mux_sel == IMM_A_Z) ? zimm_rs1_type : '0;
// ALU MUX for Operand A
always_comb begin : alu_operand_a_mux
unique case (alu_op_a_mux_sel)
OP_A_REG_A: alu_operand_a = regfile_data_ra_id;
OP_A_FWD: alu_operand_a = lsu_addr_last_i;
OP_A_CURRPC: alu_operand_a = pc_id_i;
OP_A_IMM: alu_operand_a = imm_a;
default: alu_operand_a = 'X;
OP_A_REG_A: alu_operand_a = regfile_rdata_a;
OP_A_FWD: alu_operand_a = lsu_addr_last_i;
OP_A_CURRPC: alu_operand_a = pc_id_i;
OP_A_IMM: alu_operand_a = imm_a;
default: alu_operand_a = 'X;
endcase
end
assign imm_a = (imm_a_mux_sel == IMM_A_Z) ? zimm_rs1_type : '0;
///////////////////
// Operand B MUX //
///////////////////
///////////////
// Operand B //
///////////////
// Immediate Mux for operand B
// Immediate MUX for Operand B
always_comb begin : immediate_b_mux
unique case (imm_b_mux_sel)
IMM_B_I: imm_b = imm_i_type;
@ -318,59 +281,63 @@ module ibex_id_stage #(
IMM_B_J: imm_b = imm_j_type;
IMM_B_INCR_PC: imm_b = instr_is_compressed_i ? 32'h2 : 32'h4;
IMM_B_INCR_ADDR: imm_b = 32'h4;
default: imm_b = imm_i_type;
default: imm_b = 'X;
endcase
end
// ALU_Op_b Mux
assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : regfile_data_rb_id;
// ALU MUX for Operand B
assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : regfile_rdata_b;
// Signals used by tracer
assign operand_a_fw_id = data_misaligned_i ? lsu_addr_last_i : regfile_data_ra_id;
assign operand_b_fw_id = regfile_data_rb_id;
assign operand_a_fw_id = data_misaligned_i ? lsu_addr_last_i : regfile_rdata_a;
assign operand_b_fw_id = regfile_rdata_b;
assign unused_operand_a_fw_id = operand_a_fw_id;
assign unused_operand_b_fw_id = operand_b_fw_id;
///////////////
// Registers //
///////////////
///////////////////////
// Register File MUX //
///////////////////////
// Register file write data mux
always_comb begin : regfile_wdata_mux
unique case (regfile_wdata_sel)
RF_WD_EX: regfile_wdata_id = regfile_wdata_ex_i;
RF_WD_LSU: regfile_wdata_id = regfile_wdata_lsu_i;
RF_WD_CSR: regfile_wdata_id = csr_rdata_i;
default: regfile_wdata_id = regfile_wdata_ex_i;
RF_WD_EX: regfile_wdata = regfile_wdata_ex_i;
RF_WD_LSU: regfile_wdata = regfile_wdata_lsu_i;
RF_WD_CSR: regfile_wdata = csr_rdata_i;
default: regfile_wdata = 'X;
endcase;
end
ibex_register_file #( .RV32E ( RV32E ) ) registers_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
///////////////////
// Register File //
///////////////////
.test_en_i ( test_en_i ),
ibex_register_file #( .RV32E ( RV32E ) ) registers_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.test_en_i ( test_en_i ),
// Read port a
.raddr_a_i ( regfile_addr_ra_id ),
.rdata_a_o ( regfile_data_ra_id ),
.raddr_a_i ( regfile_raddr_a ),
.rdata_a_o ( regfile_rdata_a ),
// Read port b
.raddr_b_i ( regfile_addr_rb_id ),
.rdata_b_o ( regfile_data_rb_id ),
.raddr_b_i ( regfile_raddr_b ),
.rdata_b_o ( regfile_rdata_b ),
// write port
.waddr_a_i ( regfile_waddr_id ),
.wdata_a_i ( regfile_wdata_id ),
.we_a_i ( regfile_we )
.waddr_a_i ( regfile_waddr ),
.wdata_a_i ( regfile_wdata ),
.we_a_i ( regfile_we )
);
`ifdef RVFI
assign rfvi_reg_raddr_ra_o = regfile_addr_ra_id;
assign rfvi_reg_rdata_ra_o = regfile_data_ra_id;
assign rfvi_reg_raddr_rb_o = regfile_addr_rb_id;
assign rfvi_reg_rdata_rb_o = regfile_data_rb_id;
assign rfvi_reg_waddr_rd_o = regfile_waddr_id;
assign rfvi_reg_wdata_rd_o = regfile_wdata_id;
assign rfvi_reg_raddr_ra_o = regfile_raddr_a;
assign rfvi_reg_rdata_ra_o = regfile_rdata_a;
assign rfvi_reg_raddr_rb_o = regfile_raddr_b;
assign rfvi_reg_rdata_rb_o = regfile_rdata_b;
assign rfvi_reg_waddr_rd_o = regfile_waddr;
assign rfvi_reg_wdata_rd_o = regfile_wdata;
assign rfvi_reg_we_o = regfile_we;
`endif
@ -378,74 +345,76 @@ module ibex_id_stage #(
// Decoder //
/////////////
ibex_decoder #( .RV32M ( RV32M ) ) decoder_i (
// controller related signals
.illegal_insn_o ( illegal_insn_dec ),
.ebrk_insn_o ( ebrk_insn ),
.mret_insn_o ( mret_insn_dec ),
.dret_insn_o ( dret_insn_dec ),
.ecall_insn_o ( ecall_insn_dec ),
.pipe_flush_o ( pipe_flush_dec ),
.jump_set_o ( jump_set ),
ibex_decoder #(
.RV32E ( RV32E ),
.RV32M ( RV32M )
) decoder_i (
// controller
.illegal_insn_o ( illegal_insn_dec ),
.ebrk_insn_o ( ebrk_insn ),
.mret_insn_o ( mret_insn_dec ),
.dret_insn_o ( dret_insn_dec ),
.ecall_insn_o ( ecall_insn_dec ),
.pipe_flush_o ( pipe_flush_dec ),
.jump_set_o ( jump_set ),
// from IF/ID pipeline
.instr_new_i ( instr_new_i ),
.instr_rdata_i ( instr ),
.illegal_c_insn_i ( illegal_c_insn_i ),
// from IF-ID pipeline register
.instr_new_i ( instr_new_i ),
.instr_rdata_i ( instr_rdata_i ),
.illegal_c_insn_i ( illegal_c_insn_i ),
// ALU signals
.alu_operator_o ( alu_operator ),
.alu_op_a_mux_sel_o ( alu_op_a_mux_sel_dec ),
.alu_op_b_mux_sel_o ( alu_op_b_mux_sel_dec ),
// immediates
.imm_a_mux_sel_o ( imm_a_mux_sel ),
.imm_b_mux_sel_o ( imm_b_mux_sel_dec ),
.imm_a_mux_sel_o ( imm_a_mux_sel ),
.imm_b_mux_sel_o ( imm_b_mux_sel_dec ),
.imm_i_type_o ( imm_i_type ),
.imm_s_type_o ( imm_s_type ),
.imm_b_type_o ( imm_b_type ),
.imm_u_type_o ( imm_u_type ),
.imm_j_type_o ( imm_j_type ),
.zimm_rs1_type_o ( zimm_rs1_type ),
.mult_en_o ( mult_en_dec ),
.div_en_o ( div_en_dec ),
.multdiv_operator_o ( multdiv_operator ),
.multdiv_signed_mode_o ( multdiv_signed_mode ),
// register file
.regfile_wdata_sel_o ( regfile_wdata_sel ),
.regfile_we_o ( regfile_we_dec ),
// register file control signals
.regfile_wdata_sel_o ( regfile_wdata_sel ),
.regfile_we_o ( regfile_we_dec ),
.regfile_raddr_a_o ( regfile_raddr_a ),
.regfile_raddr_b_o ( regfile_raddr_b ),
.regfile_waddr_o ( regfile_waddr ),
// CSR control signals
.csr_access_o ( csr_access ),
.csr_op_o ( csr_op ),
.csr_status_o ( csr_status ),
// ALU
.alu_operator_o ( alu_operator ),
.alu_op_a_mux_sel_o ( alu_op_a_mux_sel_dec ),
.alu_op_b_mux_sel_o ( alu_op_b_mux_sel_dec ),
// Data bus interface
.data_req_o ( data_req_dec ),
.data_we_o ( data_we_id ),
.data_type_o ( data_type_id ),
.data_sign_extension_o ( data_sign_ext_id ),
.data_reg_offset_o ( data_reg_offset_id ),
// MULT & DIV
.mult_en_o ( mult_en_dec ),
.div_en_o ( div_en_dec ),
.multdiv_operator_o ( multdiv_operator ),
.multdiv_signed_mode_o ( multdiv_signed_mode ),
// CSRs
.csr_access_o ( csr_access ),
.csr_op_o ( csr_op ),
.csr_status_o ( csr_status ),
// LSU
.data_req_o ( data_req_dec ),
.data_we_o ( data_we_id ),
.data_type_o ( data_type_id ),
.data_sign_extension_o ( data_sign_ext_id ),
.data_reg_offset_o ( data_reg_offset_id ),
// jump/branches
.jump_in_dec_o ( jump_in_dec ),
.branch_in_dec_o ( branch_in_dec )
.jump_in_dec_o ( jump_in_dec ),
.branch_in_dec_o ( branch_in_dec )
);
///////////////////////
// CSR operand check //
///////////////////////
always_comb begin : csr_operand_check
csr_op_ex_o = csr_op;
// CSRRSI/CSRRCI must not write 0 to CSRs (uimm[4:0]=='0)
// CSRRS/CSRRC must not write from x0 to CSRs (rs1=='0)
if ((csr_op == CSR_OP_SET || csr_op == CSR_OP_CLEAR) &&
instr[`REG_S1] == '0) begin
csr_op_ex_o = CSR_OP_READ;
end
end
////////////////
// Controller //
////////////////
assign illegal_insn_o = illegal_insn_dec | illegal_reg_rv32e | illegal_csr_insn_i;
assign illegal_insn_o = illegal_insn_dec | illegal_csr_insn_i;
ibex_controller controller_i (
.clk_i ( clk_i ),
@ -468,7 +437,7 @@ module ibex_id_stage #(
// from IF-ID pipeline
.instr_valid_i ( instr_valid_i ),
.instr_i ( instr ),
.instr_i ( instr_rdata_i ),
.instr_compressed_i ( instr_rdata_c_i ),
.instr_is_compressed_i ( instr_is_compressed_i ),
@ -563,6 +532,7 @@ module ibex_id_stage #(
//////////////
// ID-EX/WB //
//////////////
// Forward decoder output to EX, WB and controller only if current instr is still
// being executed. This is the case if the current instr is either:
// - a new instr (not yet done)
@ -580,7 +550,7 @@ module ibex_id_stage #(
assign data_we_ex_o = data_we_id;
assign data_type_ex_o = data_type_id;
assign data_sign_ext_ex_o = data_sign_ext_id;
assign data_wdata_ex_o = regfile_data_rb_id;
assign data_wdata_ex_o = regfile_rdata_b;
assign data_reg_offset_ex_o = data_reg_offset_id;
assign alu_operator_ex_o = alu_operator;
@ -588,14 +558,15 @@ module ibex_id_stage #(
assign alu_operand_b_ex_o = alu_operand_b;
assign csr_access_ex_o = csr_access;
assign csr_op_ex_o = csr_op;
assign mult_en_ex_o = mult_en_id;
assign div_en_ex_o = div_en_id;
assign multdiv_operator_ex_o = multdiv_operator;
assign multdiv_signed_mode_ex_o = multdiv_signed_mode;
assign multdiv_operand_a_ex_o = regfile_data_ra_id;
assign multdiv_operand_b_ex_o = regfile_data_rb_id;
assign multdiv_operand_a_ex_o = regfile_rdata_a;
assign multdiv_operand_b_ex_o = regfile_rdata_b;
typedef enum logic { IDLE, WAIT_MULTICYCLE } id_fsm_e;
id_fsm_e id_wb_fsm_cs, id_wb_fsm_ns;
@ -603,6 +574,7 @@ module ibex_id_stage #(
////////////////////////////////
// ID-EX/WB Pipeline Register //
////////////////////////////////
always_ff @(posedge clk_i or negedge rst_ni) begin : id_wb_pipeline_reg
if (!rst_ni) begin
id_wb_fsm_cs <= IDLE;
@ -618,6 +590,7 @@ module ibex_id_stage #(
//////////////////
// ID-EX/WB FSM //
//////////////////
assign multdiv_en_dec = mult_en_dec | div_en_dec;
always_comb begin : id_wb_fsm
@ -690,13 +663,16 @@ module ibex_id_stage #(
end
end
default:;
default: begin
id_wb_fsm_ns = id_fsm_e'(1'bX);
end
endcase
end
////////////////
// Assertions //
////////////////
`ifndef VERILATOR
// make sure that branch decision is valid when jumping
assert property (