mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 21:07:34 -04:00
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:
parent
d64eaad817
commit
1174603e76
3 changed files with 247 additions and 198 deletions
|
@ -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 ),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue