diff --git a/rtl/ibex_core.sv b/rtl/ibex_core.sv index 144b4809..707eb5c5 100644 --- a/rtl/ibex_core.sv +++ b/rtl/ibex_core.sv @@ -186,7 +186,8 @@ module ibex_core #( // Multiplier Control logic mult_en_ex; logic div_en_ex; - logic multdiv_sel_ex; + logic mult_sel_ex; + logic div_sel_ex; md_op_e multdiv_operator_ex; logic [1:0] multdiv_signed_mode_ex; logic [31:0] multdiv_operand_a_ex; @@ -493,7 +494,8 @@ module ibex_core #( .mult_en_ex_o ( mult_en_ex ), .div_en_ex_o ( div_en_ex ), - .multdiv_sel_ex_o ( multdiv_sel_ex ), + .mult_sel_ex_o ( mult_sel_ex ), + .div_sel_ex_o ( div_sel_ex ), .multdiv_operator_ex_o ( multdiv_operator_ex ), .multdiv_signed_mode_ex_o ( multdiv_signed_mode_ex ), .multdiv_operand_a_ex_o ( multdiv_operand_a_ex ), @@ -606,7 +608,8 @@ module ibex_core #( .multdiv_operator_i ( multdiv_operator_ex ), .mult_en_i ( mult_en_ex ), .div_en_i ( div_en_ex ), - .multdiv_sel_i ( multdiv_sel_ex ), + .mult_sel_i ( mult_sel_ex ), + .div_sel_i ( div_sel_ex ), .multdiv_signed_mode_i ( multdiv_signed_mode_ex ), .multdiv_operand_a_i ( multdiv_operand_a_ex ), .multdiv_operand_b_i ( multdiv_operand_b_ex ), diff --git a/rtl/ibex_decoder.sv b/rtl/ibex_decoder.sv index 92908409..80e6d546 100644 --- a/rtl/ibex_decoder.sv +++ b/rtl/ibex_decoder.sv @@ -78,9 +78,9 @@ module ibex_decoder #( // MULT & DIV output logic mult_en_o, // perform integer multiplication - output logic div_en_o, // perform integer division or - // remainder - output logic multdiv_sel_o, + output logic div_en_o, // perform integer division or remainder + output logic mult_sel_o, // as above but static, for data muxes + output logic div_sel_o, // as above but static, for data muxes output ibex_pkg::md_op_e multdiv_operator_o, output logic [1:0] multdiv_signed_mode_o, @@ -176,38 +176,36 @@ module ibex_decoder #( ///////////// always_comb begin - jump_in_dec_o = 1'b0; - jump_set_o = 1'b0; - branch_in_dec_o = 1'b0; - icache_inval_o = 1'b0; + jump_in_dec_o = 1'b0; + jump_set_o = 1'b0; + branch_in_dec_o = 1'b0; + icache_inval_o = 1'b0; - mult_en_o = 1'b0; - div_en_o = 1'b0; - multdiv_operator_o = MD_OP_MULL; - multdiv_signed_mode_o = 2'b00; + multdiv_operator_o = MD_OP_MULL; + multdiv_signed_mode_o = 2'b00; - rf_wdata_sel_o = RF_WD_EX; - rf_we = 1'b0; - rf_ren_a_o = 1'b0; - rf_ren_b_o = 1'b0; + rf_wdata_sel_o = RF_WD_EX; + rf_we = 1'b0; + rf_ren_a_o = 1'b0; + rf_ren_b_o = 1'b0; - csr_access_o = 1'b0; - csr_illegal = 1'b0; - csr_op = CSR_OP_READ; + csr_access_o = 1'b0; + csr_illegal = 1'b0; + csr_op = CSR_OP_READ; - data_we_o = 1'b0; - data_type_o = 2'b00; - data_sign_extension_o = 1'b0; - data_req_o = 1'b0; + data_we_o = 1'b0; + data_type_o = 2'b00; + data_sign_extension_o = 1'b0; + data_req_o = 1'b0; - illegal_insn = 1'b0; - ebrk_insn_o = 1'b0; - mret_insn_o = 1'b0; - dret_insn_o = 1'b0; - ecall_insn_o = 1'b0; - wfi_insn_o = 1'b0; + illegal_insn = 1'b0; + ebrk_insn_o = 1'b0; + mret_insn_o = 1'b0; + dret_insn_o = 1'b0; + ecall_insn_o = 1'b0; + wfi_insn_o = 1'b0; - opcode = opcode_e'(instr[6:0]); + opcode = opcode_e'(instr[6:0]); unique case (opcode) @@ -432,52 +430,44 @@ module ibex_decoder #( {7'b000_0100, 3'b001}, // shfl {7'b000_0100, 3'b101}: illegal_insn = RV32B ? 1'b0 : 1'b1; // unshfl - // supported RV32M instructions + // RV32M instructions {7'b000_0001, 3'b000}: begin // mul multdiv_operator_o = MD_OP_MULL; - mult_en_o = RV32M ? 1'b1 : 1'b0; multdiv_signed_mode_o = 2'b00; illegal_insn = RV32M ? 1'b0 : 1'b1; end {7'b000_0001, 3'b001}: begin // mulh multdiv_operator_o = MD_OP_MULH; - mult_en_o = RV32M ? 1'b1 : 1'b0; multdiv_signed_mode_o = 2'b11; illegal_insn = RV32M ? 1'b0 : 1'b1; end {7'b000_0001, 3'b010}: begin // mulhsu multdiv_operator_o = MD_OP_MULH; - mult_en_o = RV32M ? 1'b1 : 1'b0; multdiv_signed_mode_o = 2'b01; illegal_insn = RV32M ? 1'b0 : 1'b1; end {7'b000_0001, 3'b011}: begin // mulhu multdiv_operator_o = MD_OP_MULH; - mult_en_o = RV32M ? 1'b1 : 1'b0; multdiv_signed_mode_o = 2'b00; illegal_insn = RV32M ? 1'b0 : 1'b1; end {7'b000_0001, 3'b100}: begin // div multdiv_operator_o = MD_OP_DIV; - div_en_o = RV32M ? 1'b1 : 1'b0; multdiv_signed_mode_o = 2'b11; illegal_insn = RV32M ? 1'b0 : 1'b1; end {7'b000_0001, 3'b101}: begin // divu multdiv_operator_o = MD_OP_DIV; - div_en_o = RV32M ? 1'b1 : 1'b0; multdiv_signed_mode_o = 2'b00; illegal_insn = RV32M ? 1'b0 : 1'b1; end {7'b000_0001, 3'b110}: begin // rem multdiv_operator_o = MD_OP_REM; - div_en_o = RV32M ? 1'b1 : 1'b0; multdiv_signed_mode_o = 2'b11; illegal_insn = RV32M ? 1'b0 : 1'b1; end {7'b000_0001, 3'b111}: begin // remu multdiv_operator_o = MD_OP_REM; - div_en_o = RV32M ? 1'b1 : 1'b0; multdiv_signed_mode_o = 2'b00; illegal_insn = RV32M ? 1'b0 : 1'b1; end @@ -589,8 +579,6 @@ module ibex_decoder #( rf_we = 1'b0; data_req_o = 1'b0; data_we_o = 1'b0; - mult_en_o = 1'b0; - div_en_o = 1'b0; jump_in_dec_o = 1'b0; jump_set_o = 1'b0; branch_in_dec_o = 1'b0; @@ -613,12 +601,13 @@ module ibex_decoder #( bt_a_mux_sel_o = OP_A_CURRPC; bt_b_mux_sel_o = IMM_B_I; - multdiv_sel_o = 1'b0; opcode_alu = opcode_e'(instr_alu[6:0]); use_rs3 = 1'b0; alu_multicycle_o = 1'b0; + mult_sel_o = 1'b0; + div_sel_o = 1'b0; unique case (opcode_alu) @@ -928,17 +917,38 @@ module ibex_decoder #( {7'b011_0100, 3'b001}: if (RV32B) alu_operator_o = ALU_SBINV; // sbinv {7'b010_0100, 3'b101}: if (RV32B) alu_operator_o = ALU_SBEXT; // sbext - // supported RV32M instructions, all use the same ALU operation - {7'b000_0001, 3'b000}, // mul - {7'b000_0001, 3'b001}, // mulh - {7'b000_0001, 3'b010}, // mulhsu - {7'b000_0001, 3'b011}, // mulhu - {7'b000_0001, 3'b100}, // div - {7'b000_0001, 3'b101}, // divu - {7'b000_0001, 3'b110}, // rem + // RV32M instructions, all use the same ALU operation + {7'b000_0001, 3'b000}: begin // mul + alu_operator_o = ALU_ADD; + mult_sel_o = RV32M ? 1'b1 : 1'b0; + end + {7'b000_0001, 3'b001}: begin // mulh + alu_operator_o = ALU_ADD; + mult_sel_o = RV32M ? 1'b1 : 1'b0; + end + {7'b000_0001, 3'b010}: begin // mulhsu + alu_operator_o = ALU_ADD; + mult_sel_o = RV32M ? 1'b1 : 1'b0; + end + {7'b000_0001, 3'b011}: begin // mulhu + alu_operator_o = ALU_ADD; + mult_sel_o = RV32M ? 1'b1 : 1'b0; + end + {7'b000_0001, 3'b100}: begin // div + alu_operator_o = ALU_ADD; + div_sel_o = RV32M ? 1'b1 : 1'b0; + end + {7'b000_0001, 3'b101}: begin // divu + alu_operator_o = ALU_ADD; + div_sel_o = RV32M ? 1'b1 : 1'b0; + end + {7'b000_0001, 3'b110}: begin // rem + alu_operator_o = ALU_ADD; + div_sel_o = RV32M ? 1'b1 : 1'b0; + end {7'b000_0001, 3'b111}: begin // remu - multdiv_sel_o = 1'b1; - alu_operator_o = ALU_ADD; + alu_operator_o = ALU_ADD; + div_sel_o = RV32M ? 1'b1 : 1'b0; end default: ; @@ -999,6 +1009,10 @@ module ibex_decoder #( endcase end + // do not enable multdiv in case of illegal instruction exceptions + assign mult_en_o = illegal_insn ? 1'b0 : mult_sel_o; + assign div_en_o = illegal_insn ? 1'b0 : div_sel_o; + // make sure instructions accessing non-available registers in RV32E cause illegal // instruction exceptions assign illegal_insn_o = illegal_insn | illegal_reg_rv32e; diff --git a/rtl/ibex_ex_block.sv b/rtl/ibex_ex_block.sv index feb151fa..b8e31100 100644 --- a/rtl/ibex_ex_block.sv +++ b/rtl/ibex_ex_block.sv @@ -30,9 +30,10 @@ module ibex_ex_block #( // Multiplier/Divider input ibex_pkg::md_op_e multdiv_operator_i, - input logic mult_en_i, - input logic div_en_i, - input logic multdiv_sel_i, + input logic mult_en_i, // dynamic enable signal, for FSM control + input logic div_en_i, // dynamic enable signal, for FSM control + input logic mult_sel_i, // static decoder output, for data muxes + input logic div_sel_i, // static decoder output, for data muxes input logic [1:0] multdiv_signed_mode_i, input logic [31:0] multdiv_operand_a_i, input logic [31:0] multdiv_operand_b_i, @@ -66,22 +67,22 @@ module ibex_ex_block #( logic [33:0] multdiv_imd_val_d; logic multdiv_imd_val_we; - // Intermediate Value Register Mux - assign imd_val_d_o = multdiv_sel_i ? multdiv_imd_val_d : {2'b0, alu_imd_val_d}; - assign imd_val_we_o = multdiv_sel_i ? multdiv_imd_val_we : alu_imd_val_we; - /* The multdiv_i output is never selected if RV32M=0 At synthesis time, all the combinational and sequential logic from the multdiv_i module are eliminated */ if (RV32M) begin : gen_multdiv_m - assign multdiv_sel = multdiv_sel_i; + assign multdiv_sel = mult_sel_i | div_sel_i; end else begin : gen_multdiv_no_m assign multdiv_sel = 1'b0; end - assign result_ex_o = multdiv_sel ? multdiv_result : alu_result; + // Intermediate Value Register Mux + assign imd_val_d_o = multdiv_sel ? multdiv_imd_val_d : {2'b0, alu_imd_val_d}; + assign imd_val_we_o = multdiv_sel ? multdiv_imd_val_we : alu_imd_val_we; + + assign result_ex_o = multdiv_sel ? multdiv_result : alu_result; // branch handling assign branch_decision_o = alu_cmp_result; @@ -120,7 +121,7 @@ module ibex_ex_block #( .imd_val_d_o ( alu_imd_val_d ), .multdiv_operand_a_i ( multdiv_alu_operand_a ), .multdiv_operand_b_i ( multdiv_alu_operand_b ), - .multdiv_sel_i ( multdiv_sel_i ), + .multdiv_sel_i ( multdiv_sel ), .adder_result_o ( alu_adder_result_ex_o ), .adder_result_ext_o ( alu_adder_result_ext ), .result_o ( alu_result ), @@ -138,6 +139,8 @@ module ibex_ex_block #( .rst_ni ( rst_ni ), .mult_en_i ( mult_en_i ), .div_en_i ( div_en_i ), + .mult_sel_i ( mult_sel_i ), + .div_sel_i ( div_sel_i ), .operator_i ( multdiv_operator_i ), .signed_mode_i ( multdiv_signed_mode_i ), .op_a_i ( multdiv_operand_a_i ), @@ -162,6 +165,8 @@ module ibex_ex_block #( .rst_ni ( rst_ni ), .mult_en_i ( mult_en_i ), .div_en_i ( div_en_i ), + .mult_sel_i ( mult_sel_i ), + .div_sel_i ( div_sel_i ), .operator_i ( multdiv_operator_i ), .signed_mode_i ( multdiv_signed_mode_i ), .op_a_i ( multdiv_operand_a_i ), @@ -186,6 +191,8 @@ module ibex_ex_block #( .rst_ni ( rst_ni ), .mult_en_i ( mult_en_i ), .div_en_i ( div_en_i ), + .mult_sel_i ( mult_sel_i ), + .div_sel_i ( div_sel_i ), .operator_i ( multdiv_operator_i ), .signed_mode_i ( multdiv_signed_mode_i ), .op_a_i ( multdiv_operand_a_i ), diff --git a/rtl/ibex_id_stage.sv b/rtl/ibex_id_stage.sv index 57ba3067..0f229613 100644 --- a/rtl/ibex_id_stage.sv +++ b/rtl/ibex_id_stage.sv @@ -80,7 +80,8 @@ module ibex_id_stage #( // MUL, DIV output logic mult_en_ex_o, output logic div_en_ex_o, - output logic multdiv_sel_ex_o, + output logic mult_sel_ex_o, + output logic div_sel_ex_o, output ibex_pkg::md_op_e multdiv_operator_ex_o, output logic [1:0] multdiv_signed_mode_ex_o, output logic [31:0] multdiv_operand_a_ex_o, @@ -246,7 +247,6 @@ module ibex_id_stage #( // Multiplier Control logic mult_en_id, mult_en_dec; // use integer multiplier logic div_en_id, div_en_dec; // use integer division or reminder - logic multdiv_sel_dec; logic multdiv_en_dec; md_op_e multdiv_operator; logic [1:0] multdiv_signed_mode; @@ -442,7 +442,8 @@ module ibex_id_stage #( // MULT & DIV .mult_en_o ( mult_en_dec ), .div_en_o ( div_en_dec ), - .multdiv_sel_o ( multdiv_sel_dec ), + .mult_sel_o ( mult_sel_ex_o ), + .div_sel_o ( div_sel_ex_o ), .multdiv_operator_o ( multdiv_operator ), .multdiv_signed_mode_o ( multdiv_signed_mode ), @@ -603,7 +604,6 @@ module ibex_id_stage #( assign mult_en_ex_o = mult_en_id; assign div_en_ex_o = div_en_id; - assign multdiv_sel_ex_o = multdiv_sel_dec; assign multdiv_operator_ex_o = multdiv_operator; assign multdiv_signed_mode_ex_o = multdiv_signed_mode; diff --git a/rtl/ibex_multdiv_fast.sv b/rtl/ibex_multdiv_fast.sv index 424c6dae..efee4a4a 100644 --- a/rtl/ibex_multdiv_fast.sv +++ b/rtl/ibex_multdiv_fast.sv @@ -19,8 +19,10 @@ module ibex_multdiv_fast #( ) ( input logic clk_i, input logic rst_ni, - input logic mult_en_i, - input logic div_en_i, + input logic mult_en_i, // dynamic enable signal, for FSM control + input logic div_en_i, // dynamic enable signal, for FSM control + input logic mult_sel_i, // static decoder output, for data muxes + input logic div_sel_i, // static decoder output, for data muxes input ibex_pkg::md_op_e operator_i, input logic [1:0] signed_mode_i, input logic [31:0] op_a_i, @@ -85,6 +87,8 @@ module ibex_multdiv_fast #( } md_fsm_e; md_fsm_e md_state_q, md_state_d; + logic unused_mult_sel_i; + assign unused_mult_sel_i = mult_sel_i; assign mult_en_internal = mult_en_i & ~mult_hold; assign div_en_internal = div_en_i & ~div_hold; @@ -112,11 +116,11 @@ module ibex_multdiv_fast #( assign multdiv_en = mult_en_internal | div_en_internal; - assign imd_val_d_o = div_en_i ? op_remainder_d : mac_res_d; + assign imd_val_d_o = div_sel_i ? op_remainder_d : mac_res_d; assign imd_val_we_o = multdiv_en; assign signed_mult = (signed_mode_i != 2'b00); - assign multdiv_result_o = div_en_i ? imd_val_q_i[31:0] : mac_res_d[31:0]; + assign multdiv_result_o = div_sel_i ? imd_val_q_i[31:0] : mac_res_d[31:0]; // The single cycle multiplier uses three 17 bit multipliers to compute MUL instructions in a // single cycle and MULH instructions in two cycles. diff --git a/rtl/ibex_multdiv_slow.sv b/rtl/ibex_multdiv_slow.sv index 0c2d3280..7be2446b 100644 --- a/rtl/ibex_multdiv_slow.sv +++ b/rtl/ibex_multdiv_slow.sv @@ -15,8 +15,10 @@ module ibex_multdiv_slow ( input logic clk_i, input logic rst_ni, - input logic mult_en_i, - input logic div_en_i, + input logic mult_en_i, // dynamic enable signal, for FSM control + input logic div_en_i, // dynamic enable signal, for FSM control + input logic mult_sel_i, // static decoder output, for data muxes + input logic div_sel_i, // static decoder output, for data muxes input ibex_pkg::md_op_e operator_i, input logic [1:0] signed_mode_i, input logic [31:0] op_a_i, @@ -78,7 +80,7 @@ module ibex_multdiv_slow always_comb begin alu_operand_a_o = accum_window_q; - multdiv_result_o = div_en_i ? accum_window_q[31:0] : res_adder_l; + multdiv_result_o = div_sel_i ? accum_window_q[31:0] : res_adder_l; unique case(operator_i) @@ -179,7 +181,7 @@ module ibex_multdiv_slow op_numerator_d = op_numerator_q; md_state_d = md_state_q; multdiv_hold = 1'b0; - if (mult_en_i || div_en_i) begin + if (mult_sel_i || div_sel_i) begin unique case(md_state_q) MD_IDLE: begin unique case(operator_i) @@ -302,8 +304,8 @@ module ibex_multdiv_slow default: begin md_state_d = MD_IDLE; end - endcase // md_state_q - end + endcase // md_state_q + end // (mult_sel_i || div_sel_i) end assign valid_o = (md_state_q == MD_FINISH) |