mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-22 04:47:25 -04:00
[rtl] multdiv_slow general tidy-up
- Correct some typos and fix various lint / style guide issues - No functional changes Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
This commit is contained in:
parent
10bc77ddcc
commit
0ba0ad5a43
2 changed files with 113 additions and 86 deletions
|
@ -147,7 +147,7 @@ module ibex_ex_block #(
|
|||
.op_b_i ( multdiv_operand_b_i ),
|
||||
.alu_adder_ext_i ( alu_adder_result_ext ),
|
||||
.alu_adder_i ( alu_adder_result_ex_o ),
|
||||
.equal_to_zero ( alu_is_equal_result ),
|
||||
.equal_to_zero_i ( alu_is_equal_result ),
|
||||
.valid_o ( multdiv_valid ),
|
||||
.alu_operand_a_o ( multdiv_alu_operand_a ),
|
||||
.alu_operand_b_o ( multdiv_alu_operand_b ),
|
||||
|
|
|
@ -25,7 +25,7 @@ module ibex_multdiv_slow
|
|||
input logic [31:0] op_b_i,
|
||||
input logic [33:0] alu_adder_ext_i,
|
||||
input logic [31:0] alu_adder_i,
|
||||
input logic equal_to_zero,
|
||||
input logic equal_to_zero_i,
|
||||
|
||||
output logic [32:0] alu_operand_a_o,
|
||||
output logic [32:0] alu_operand_b_o,
|
||||
|
@ -43,17 +43,18 @@ module ibex_multdiv_slow
|
|||
|
||||
import ibex_pkg::*;
|
||||
|
||||
logic [ 4:0] multdiv_state_q, multdiv_state_d, multdiv_state_m1;
|
||||
typedef enum logic [2:0] {
|
||||
MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH
|
||||
} md_fsm_e;
|
||||
md_fsm_e md_state_q, md_state_d;
|
||||
|
||||
logic [32:0] accum_window_q, accum_window_d;
|
||||
logic unused_imd_val;
|
||||
|
||||
logic [32:0] res_adder_l;
|
||||
logic [32:0] res_adder_h;
|
||||
|
||||
logic [ 4:0] multdiv_count_q, multdiv_count_d;
|
||||
logic [32:0] op_b_shift_q, op_b_shift_d;
|
||||
logic [32:0] op_a_shift_q, op_a_shift_d;
|
||||
logic [32:0] op_a_ext, op_b_ext;
|
||||
|
@ -61,120 +62,109 @@ module ibex_multdiv_slow
|
|||
logic [32:0] op_a_bw_pp, op_a_bw_last_pp;
|
||||
logic [31:0] b_0;
|
||||
logic sign_a, sign_b;
|
||||
logic [32:0] next_reminder, next_quotient;
|
||||
logic [32:0] op_remainder;
|
||||
logic [32:0] next_quotient;
|
||||
logic [31:0] next_remainder;
|
||||
logic [31:0] op_numerator_q, op_numerator_d;
|
||||
logic is_greater_equal;
|
||||
logic div_change_sign, rem_change_sign;
|
||||
logic multdiv_hold;
|
||||
logic multdiv_en;
|
||||
|
||||
// (accum_window_q + op_a_shift_q)
|
||||
assign res_adder_l = alu_adder_ext_i[32:0];
|
||||
assign res_adder_l = alu_adder_ext_i[32:0];
|
||||
// (accum_window_q + op_a_shift_q)>>1
|
||||
assign res_adder_h = alu_adder_ext_i[33:1];
|
||||
assign res_adder_h = alu_adder_ext_i[33:1];
|
||||
|
||||
/////////////////////
|
||||
// ALU Operand MUX //
|
||||
/////////////////////
|
||||
|
||||
// Use shared intermediate value register in id_stage for accum_window
|
||||
assign imd_val_d_o = accum_window_d;
|
||||
assign imd_val_d_o = {1'b0,accum_window_d};
|
||||
assign imd_val_we_o = ~multdiv_hold;
|
||||
assign accum_window_q = imd_val_q_i;
|
||||
assign accum_window_q = imd_val_q_i[32:0];
|
||||
assign unused_imd_val = imd_val_q_i[33];
|
||||
|
||||
always_comb begin
|
||||
alu_operand_a_o = accum_window_q;
|
||||
multdiv_result_o = div_sel_i ? accum_window_q[31:0] : res_adder_l;
|
||||
alu_operand_a_o = accum_window_q;
|
||||
|
||||
unique case(operator_i)
|
||||
|
||||
MD_OP_MULL: begin
|
||||
alu_operand_b_o = op_a_bw_pp;
|
||||
alu_operand_b_o = op_a_bw_pp;
|
||||
end
|
||||
|
||||
MD_OP_MULH: begin
|
||||
alu_operand_b_o = (md_state_q == MD_LAST) ? op_a_bw_last_pp : op_a_bw_pp;
|
||||
end
|
||||
|
||||
default: begin
|
||||
MD_OP_DIV,
|
||||
MD_OP_REM: begin
|
||||
unique case(md_state_q)
|
||||
MD_IDLE: begin
|
||||
// 0 - B = 0 iff B == 0
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~op_b_i, 1'b1};
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~op_b_i, 1'b1};
|
||||
end
|
||||
MD_ABS_A: begin
|
||||
// ABS(A) = 0 - A
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~op_a_i, 1'b1};
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~op_a_i, 1'b1};
|
||||
end
|
||||
MD_ABS_B: begin
|
||||
// ABS(B) = 0 - B
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~op_b_i, 1'b1};
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~op_b_i, 1'b1};
|
||||
end
|
||||
MD_CHANGE_SIGN: begin
|
||||
// ABS(Quotient) = 0 - Quotient (or Reminder)
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~accum_window_q[31:0], 1'b1};
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~accum_window_q[31:0], 1'b1};
|
||||
end
|
||||
default: begin
|
||||
// Division
|
||||
alu_operand_a_o = {accum_window_q[31:0], 1'b1}; // it contains the reminder
|
||||
alu_operand_b_o = {~op_b_shift_q[31:0], 1'b1}; // -denominator two's compliment
|
||||
alu_operand_a_o = {accum_window_q[31:0], 1'b1}; // it contains the remainder
|
||||
alu_operand_b_o = {~op_b_shift_q[31:0], 1'b1}; // -denominator two's compliment
|
||||
end
|
||||
endcase
|
||||
end
|
||||
default: begin
|
||||
alu_operand_a_o = accum_window_q;
|
||||
alu_operand_b_o = {~op_b_shift_q[31:0], 1'b1};
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
// The adder in the ALU computes alu_operand_a_o + alu_operand_b_o which means
|
||||
// Reminder - Divisor. If Reminder - Divisor >= 0, is_greater_equal is equal to 1,
|
||||
// the next Reminder is Reminder - Divisor contained in res_adder_h and the
|
||||
// Quotient multdiv_state_q-th bit is set to 1 using the shift register op_b_shift_q.
|
||||
assign is_greater_equal = ((accum_window_q[31] ^ op_b_shift_q[31]) == 1'b0) ?
|
||||
(res_adder_h[31] == 1'b0) : accum_window_q[31];
|
||||
|
||||
assign one_shift = {32'b0, 1'b1} << multdiv_state_q;
|
||||
|
||||
assign next_reminder = is_greater_equal ? res_adder_h : op_remainder;
|
||||
assign next_quotient = is_greater_equal ? op_a_shift_q | one_shift : op_a_shift_q;
|
||||
|
||||
// Multiplier partial product calculation
|
||||
assign b_0 = {32{op_b_shift_q[0]}};
|
||||
assign op_a_bw_pp = { ~(op_a_shift_q[32] & op_b_shift_q[0]), (op_a_shift_q[31:0] & b_0) };
|
||||
assign op_a_bw_last_pp = { (op_a_shift_q[32] & op_b_shift_q[0]), ~(op_a_shift_q[31:0] & b_0) };
|
||||
|
||||
// build the partial product
|
||||
assign op_a_bw_pp = { ~(op_a_shift_q[32] & op_b_shift_q[0]), (op_a_shift_q[31:0] & b_0) };
|
||||
assign op_a_bw_last_pp = { (op_a_shift_q[32] & op_b_shift_q[0]), ~(op_a_shift_q[31:0] & b_0) };
|
||||
|
||||
// Sign extend the input operands
|
||||
assign sign_a = op_a_i[31] & signed_mode_i[0];
|
||||
assign sign_b = op_b_i[31] & signed_mode_i[1];
|
||||
|
||||
assign op_a_ext = {sign_a, op_a_i};
|
||||
assign op_b_ext = {sign_b, op_b_i};
|
||||
|
||||
// division
|
||||
assign op_remainder = accum_window_q[32:0];
|
||||
// Divider calculations
|
||||
|
||||
// The adder in the ALU computes Remainder - Divisor. If Remainder - Divisor >= 0,
|
||||
// is_greater_equal is true, the next Remainder is the subtraction result and the Quotient
|
||||
// multdiv_count_q-th bit is set to 1.
|
||||
assign is_greater_equal = (accum_window_q[31] == op_b_shift_q[31]) ?
|
||||
~res_adder_h[31] : accum_window_q[31];
|
||||
|
||||
assign one_shift = {32'b0, 1'b1} << multdiv_count_q;
|
||||
|
||||
assign next_remainder = is_greater_equal ? res_adder_h[31:0] : accum_window_q[31:0];
|
||||
assign next_quotient = is_greater_equal ? op_a_shift_q | one_shift : op_a_shift_q;
|
||||
|
||||
assign multdiv_state_m1 = multdiv_state_q - 5'h1;
|
||||
assign div_change_sign = sign_a ^ sign_b;
|
||||
assign rem_change_sign = sign_a;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : proc_multdiv_state_q
|
||||
if (!rst_ni) begin
|
||||
multdiv_state_q <= 5'h0;
|
||||
op_b_shift_q <= 33'h0;
|
||||
op_a_shift_q <= 33'h0;
|
||||
op_numerator_q <= 32'h0;
|
||||
md_state_q <= MD_IDLE;
|
||||
end else begin
|
||||
if ((mult_en_i || div_en_i) && !multdiv_hold) begin
|
||||
multdiv_state_q <= multdiv_state_d;
|
||||
op_b_shift_q <= op_b_shift_d;
|
||||
op_a_shift_q <= op_a_shift_d;
|
||||
op_numerator_q <= op_numerator_d;
|
||||
md_state_q <= md_state_d;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
multdiv_state_d = multdiv_state_q;
|
||||
multdiv_count_d = multdiv_count_q;
|
||||
accum_window_d = accum_window_q;
|
||||
op_b_shift_d = op_b_shift_q;
|
||||
op_a_shift_d = op_a_shift_q;
|
||||
|
@ -190,7 +180,7 @@ module ibex_multdiv_slow
|
|||
accum_window_d = { ~(op_a_ext[32] & op_b_i[0]),
|
||||
op_a_ext[31:0] & {32{op_b_i[0]}} };
|
||||
op_b_shift_d = op_b_ext >> 1;
|
||||
md_state_d = !(op_b_ext >> 1) ? MD_LAST : MD_COMP;
|
||||
md_state_d = ((op_b_ext >> 1) == 0) ? MD_LAST : MD_COMP;
|
||||
end
|
||||
MD_OP_MULH: begin
|
||||
op_a_shift_d = op_a_ext;
|
||||
|
@ -200,19 +190,20 @@ module ibex_multdiv_slow
|
|||
md_state_d = MD_COMP;
|
||||
end
|
||||
MD_OP_DIV: begin
|
||||
// Check if the Denominator is 0
|
||||
// Check if the denominator is 0
|
||||
// quotient for division by 0
|
||||
accum_window_d = {33{1'b1}};
|
||||
md_state_d = equal_to_zero ? MD_FINISH : MD_ABS_A;
|
||||
md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A;
|
||||
end
|
||||
default: begin
|
||||
// Check if the Denominator is 0
|
||||
// reminder for division by 0
|
||||
MD_OP_REM: begin
|
||||
// Check if the denominator is 0
|
||||
// remainder for division by 0
|
||||
accum_window_d = op_a_ext;
|
||||
md_state_d = equal_to_zero ? MD_FINISH : MD_ABS_A;
|
||||
md_state_d = equal_to_zero_i ? MD_FINISH : MD_ABS_A;
|
||||
end
|
||||
default:;
|
||||
endcase
|
||||
multdiv_state_d = 5'd31;
|
||||
multdiv_count_d = 5'd31;
|
||||
end
|
||||
|
||||
MD_ABS_A: begin
|
||||
|
@ -224,33 +215,35 @@ module ibex_multdiv_slow
|
|||
end
|
||||
|
||||
MD_ABS_B: begin
|
||||
// reminder
|
||||
accum_window_d = { 32'h0, op_numerator_q[31]};
|
||||
// remainder
|
||||
accum_window_d = {32'h0,op_numerator_q[31]};
|
||||
// B abs value
|
||||
op_b_shift_d = sign_b ? alu_adder_i : op_b_i;
|
||||
op_b_shift_d = sign_b ? {1'b0,alu_adder_i} : {1'b0,op_b_i};
|
||||
md_state_d = MD_COMP;
|
||||
end
|
||||
|
||||
MD_COMP: begin
|
||||
multdiv_state_d = multdiv_state_m1;
|
||||
multdiv_count_d = multdiv_count_q - 5'h1;
|
||||
unique case(operator_i)
|
||||
MD_OP_MULL: begin
|
||||
accum_window_d = res_adder_l;
|
||||
op_a_shift_d = op_a_shift_q << 1;
|
||||
op_b_shift_d = op_b_shift_q >> 1;
|
||||
md_state_d = !(op_b_shift_q >> 1) ? MD_LAST : MD_COMP;
|
||||
md_state_d = ((op_b_shift_q >> 1) == 0) ? MD_LAST : MD_COMP;
|
||||
end
|
||||
MD_OP_MULH: begin
|
||||
accum_window_d = res_adder_h;
|
||||
op_a_shift_d = op_a_shift_q;
|
||||
op_b_shift_d = op_b_shift_q >> 1;
|
||||
md_state_d = (multdiv_state_q == 5'd1) ? MD_LAST : MD_COMP;
|
||||
md_state_d = (multdiv_count_q == 5'd1) ? MD_LAST : MD_COMP;
|
||||
end
|
||||
default: begin
|
||||
accum_window_d = {next_reminder[31:0], op_numerator_q[multdiv_state_m1]};
|
||||
MD_OP_DIV,
|
||||
MD_OP_REM: begin
|
||||
accum_window_d = {next_remainder[31:0], op_numerator_q[multdiv_count_d]};
|
||||
op_a_shift_d = next_quotient;
|
||||
md_state_d = (multdiv_state_q == 5'd1) ? MD_LAST : MD_COMP;
|
||||
md_state_d = (multdiv_count_q == 5'd1) ? MD_LAST : MD_COMP;
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -273,15 +266,16 @@ module ibex_multdiv_slow
|
|||
end
|
||||
MD_OP_DIV: begin
|
||||
// this time we save the quotient in accum_window_q since we do not need anymore the
|
||||
// reminder
|
||||
// remainder
|
||||
accum_window_d = next_quotient;
|
||||
md_state_d = MD_CHANGE_SIGN;
|
||||
end
|
||||
default: begin
|
||||
// this time we do not save the quotient anymore since we need only the reminder
|
||||
accum_window_d = {1'b0, next_reminder[31:0]};
|
||||
MD_OP_REM: begin
|
||||
// this time we do not save the quotient anymore since we need only the remainder
|
||||
accum_window_d = {1'b0, next_remainder[31:0]};
|
||||
md_state_d = MD_CHANGE_SIGN;
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -289,9 +283,10 @@ module ibex_multdiv_slow
|
|||
md_state_d = MD_FINISH;
|
||||
unique case(operator_i)
|
||||
MD_OP_DIV:
|
||||
accum_window_d = (div_change_sign) ? alu_adder_i : accum_window_q;
|
||||
default:
|
||||
accum_window_d = (rem_change_sign) ? alu_adder_i : accum_window_q;
|
||||
accum_window_d = div_change_sign ? {1'b0,alu_adder_i} : accum_window_q;
|
||||
MD_OP_REM:
|
||||
accum_window_d = rem_change_sign ? {1'b0,alu_adder_i} : accum_window_q;
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -308,14 +303,46 @@ module ibex_multdiv_slow
|
|||
end // (mult_sel_i || div_sel_i)
|
||||
end
|
||||
|
||||
//////////////////////////////////////////
|
||||
// Mutliplier / Divider state registers //
|
||||
//////////////////////////////////////////
|
||||
|
||||
assign multdiv_en = (mult_en_i | div_en_i) & ~multdiv_hold;
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
multdiv_count_q <= 5'h0;
|
||||
op_b_shift_q <= 33'h0;
|
||||
op_a_shift_q <= 33'h0;
|
||||
op_numerator_q <= 32'h0;
|
||||
md_state_q <= MD_IDLE;
|
||||
end else if (multdiv_en) begin
|
||||
multdiv_count_q <= multdiv_count_d;
|
||||
op_b_shift_q <= op_b_shift_d;
|
||||
op_a_shift_q <= op_a_shift_d;
|
||||
op_numerator_q <= op_numerator_d;
|
||||
md_state_q <= md_state_d;
|
||||
end
|
||||
end
|
||||
|
||||
/////////////
|
||||
// Outputs //
|
||||
/////////////
|
||||
|
||||
assign valid_o = (md_state_q == MD_FINISH) |
|
||||
(md_state_q == MD_LAST &
|
||||
(operator_i == MD_OP_MULL |
|
||||
operator_i == MD_OP_MULH));
|
||||
|
||||
assign multdiv_result_o = div_en_i ? accum_window_q[31:0] : res_adder_l[31:0];
|
||||
|
||||
////////////////
|
||||
// Assertions //
|
||||
////////////////
|
||||
|
||||
// State must be valid.
|
||||
`ASSERT(IbexMultDivStateValid, md_state_q inside {
|
||||
MD_IDLE, MD_ABS_A, MD_ABS_B, MD_COMP, MD_LAST, MD_CHANGE_SIGN, MD_FINISH
|
||||
}, clk_i, !rst_ni)
|
||||
|
||||
endmodule // ibex_mult
|
||||
endmodule
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue