[rtl] Rework generation and use of mult/div_sel/en

Signed-off-by: Pirmin Vogel <vogelpi@lowrisc.org>
This commit is contained in:
Pirmin Vogel 2020-04-24 09:06:04 +02:00
parent 511c59db18
commit 3922b2582f
6 changed files with 108 additions and 78 deletions

View file

@ -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 ),

View file

@ -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;

View file

@ -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 ),

View file

@ -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;

View file

@ -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.

View file

@ -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) |