diff --git a/rtl/ibex_core.sv b/rtl/ibex_core.sv index 335e8a4f..d71a75bb 100644 --- a/rtl/ibex_core.sv +++ b/rtl/ibex_core.sv @@ -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 ), diff --git a/rtl/ibex_decoder.sv b/rtl/ibex_decoder.sv index 6499b9d1..23680a4d 100644 --- a/rtl/ibex_decoder.sv +++ b/rtl/ibex_decoder.sv @@ -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 diff --git a/rtl/ibex_id_stage.sv b/rtl/ibex_id_stage.sv index eade6ca9..e3aeef49 100644 --- a/rtl/ibex_id_stage.sv +++ b/rtl/ibex_id_stage.sv @@ -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 (