div interface refactor

This commit is contained in:
Eric Matthews 2019-11-19 18:06:20 -08:00
parent 7dba36573c
commit 0558c63557
22 changed files with 675 additions and 821 deletions

View file

@ -64,6 +64,7 @@ module decode(
output logic tr_branch_operand_stall,
output logic tr_alu_operand_stall,
output logic tr_ls_operand_stall,
output logic tr_div_operand_stall,
output logic tr_instruction_issued_dec,
output logic [31:0] tr_instruction_pc_dec,
@ -374,7 +375,6 @@ module decode(
assign div_inputs.rs2 = rf_decode.rs2_data;
assign div_inputs.op = fn3[1:0];
assign div_inputs.reuse_result = prev_div_result_valid_r & current_op_resuses_rs1_rs2;
assign div_inputs.instruction_id = ti.issue_id;
end
endgenerate
@ -426,6 +426,7 @@ module decode(
assign tr_branch_operand_stall = tr_operand_stall & new_request[BRANCH_UNIT_ID];
assign tr_alu_operand_stall = tr_operand_stall & new_request[ALU_UNIT_WB_ID] & ~new_request[BRANCH_UNIT_ID];
assign tr_ls_operand_stall = tr_operand_stall & new_request[LS_UNIT_WB_ID];
assign tr_div_operand_stall = tr_operand_stall & new_request[DIV_UNIT_WB_ID];
assign tr_instruction_issued_dec = instruction_issued;
assign tr_instruction_pc_dec = fb.pc;

View file

@ -25,37 +25,27 @@ import taiga_config::*;
import taiga_types::*;
module div_algorithm
#(
parameter C_WIDTH = 32
)
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
unsigned_division_interface.divider div
);
generate
case(DIV_ALGORITHM)
RADIX_2 : div_radix2 #(XLEN) div (.*);
RADIX_2_EARLY_TERMINATE : div_radix2_ET #(XLEN) div (.*);
RADIX_2_EARLY_TERMINATE_FULL : div_radix2_ET_full #(XLEN) div (.*);
RADIX_4 : div_radix4 #(XLEN) div (.*);
RADIX_4_EARLY_TERMINATE : div_radix4_ET #(XLEN) div (.*);
RADIX_4_EARLY_TERMINATE_FULL: div_radix4_ET_full #(XLEN) div (.*);
RADIX_8 : div_radix8 #(XLEN) div (.*);
RADIX_8_EARLY_TERMINATE : div_radix8_ET #(XLEN) div (.*);
RADIX_16 : div_radix16 #(XLEN) div (.*);
QUICK_NAIVE : div_quick_naive #(XLEN) div (.*);
QUICK_CLZ : div_quick_clz #(XLEN) div (.*);
QUICK_CLZ_MK2 : div_quick_clz_mk2 #(XLEN) div (.*);
QUICK_RADIX_4 : div_quick_radix_4 #(XLEN) div (.*);
RADIX_2 : div_radix2 div_block (.*);
RADIX_2_EARLY_TERMINATE : div_radix2_ET div_block (.*);
RADIX_2_EARLY_TERMINATE_FULL : div_radix2_ET_full div_block (.*);
RADIX_4 : div_radix4 div_block (.*);
RADIX_4_EARLY_TERMINATE : div_radix4_ET div_block (.*);
RADIX_4_EARLY_TERMINATE_FULL: div_radix4_ET_full div_block (.*);
RADIX_8 : div_radix8 div_block (.*);
RADIX_8_EARLY_TERMINATE : div_radix8_ET div_block (.*);
RADIX_16 : div_radix16 div_block (.*);
QUICK_NAIVE : div_quick_naive div_block (.*);
QUICK_CLZ : div_quick_clz div_block (.*);
QUICK_CLZ_MK2 : div_quick_clz_mk2 div_block (.*);
QUICK_RADIX_4 : div_quick_radix_4 div_block (.*);
default : $error("invalid div selection");
endcase
endgenerate

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -23,104 +23,106 @@
module div_quick_clz
#(
parameter C_WIDTH = 32
)(
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
unsigned_division_interface.divider div
);
logic running;
logic terminate;
logic [C_WIDTH-1:0] A_r;
logic [C_WIDTH:0] A1;
logic [C_WIDTH-1:0] A2;
logic [div.DATA_WIDTH-1:0] normalized_divisor;
logic [C_WIDTH-1:0] new_R;
logic [C_WIDTH-1:0] new_Q_bit;
logic overflow;
logic [div.DATA_WIDTH-1:0] subtraction1;
logic [div.DATA_WIDTH-1:0] subtraction2;
logic [C_WIDTH-1:0] Q_bit1;
logic [C_WIDTH-1:0] Q_bit2;
logic [div.DATA_WIDTH-1:0] new_remainder;
logic [div.DATA_WIDTH-1:0] new_quotient;
logic [C_WIDTH-1:0] B1;
logic [C_WIDTH-1:0] B2;
logic [C_WIDTH-1:0] B_r;
logic [div.DATA_WIDTH-1:0] new_Q_bit1;
logic [div.DATA_WIDTH-1:0] new_Q_bit2;
localparam CLZ_W = $clog2(C_WIDTH);
logic [CLZ_W-1:0] R_CLZ;
logic [CLZ_W-1:0] B_CLZ;
logic [CLZ_W-1:0] B_CLZ_r;
logic [div.DATA_WIDTH-1:0] test_multiple1;
logic [div.DATA_WIDTH-1:0] test_multiple2;
localparam CLZ_W = $clog2(div.DATA_WIDTH);
logic [CLZ_W-1:0] remainder_CLZ;
logic [CLZ_W-1:0] divisor_CLZ;
logic [CLZ_W-1:0] divisor_CLZ_r;
logic [CLZ_W-1:0] CLZ_delta;
////////////////////////////////////////////////////
//Implementation
clz remainder_clz_block (.clz_input(div.remainder), .clz(remainder_CLZ));
clz divisor_clz_block (.clz_input(div.divisor), .clz(divisor_CLZ));
logic firstCycle;
logic [C_WIDTH-1:0] shiftedB;
//////////////////////////////////////////
clz clz_r (.clz_input(R), .clz(R_CLZ));
clz clz_b (.clz_input(B), .clz(B_CLZ));
always_ff @ (posedge clk) begin
B_CLZ_r <= B_CLZ;
shiftedB <= B << B_CLZ;
end
assign CLZ_delta = B_CLZ_r - R_CLZ;
always_comb begin
Q_bit1 = 0;
Q_bit1[CLZ_delta] = 1;
end
assign Q_bit2 = {1'b0, Q_bit1[C_WIDTH-1:1]};
assign new_Q_bit = Q | (A1[C_WIDTH] ? Q_bit2 : Q_bit1);
assign B1 = shiftedB >> R_CLZ;
assign A1 = R - B1;
assign B2 = {1'b0, B1[C_WIDTH-1:1]};
assign A2 = R - B2;
assign new_R = A1[C_WIDTH] ? A2[C_WIDTH-1:0] : A1[C_WIDTH-1:0];
assign B_is_zero = (&B_CLZ) & ~B[0];
////////////////////////////////////////////////////
//Control Signals
assign div.divisor_is_zero = (&divisor_CLZ) & ~div.divisor[0];
always_ff @ (posedge clk) begin
if (rst)
running <= 0;
else if (start & ~B_is_zero)
else if (div.start & ~div.divisor_is_zero)
running <= 1;
else if (terminate)
running <= 0;
end
always_ff @ (posedge clk) begin
complete <= (running & terminate) | (start & B_is_zero);
div.done <= (running & terminate) | (div.start & div.divisor_is_zero);
end
assign terminate = R < B;
assign terminate = div.remainder < div.divisor;
////////////////////////////////////////////////////
//Divisor Pre-processing
always_ff @ (posedge clk) begin
if (start)
Q <= B_is_zero ? '1 : '0;
else if (~terminate & running)
Q <= new_Q_bit;
divisor_CLZ_r <= divisor_CLZ;
normalized_divisor <= div.divisor << divisor_CLZ;
end
////////////////////////////////////////////////////
//Remainder Determination
assign test_multiple1 = normalized_divisor >> remainder_CLZ;
assign {overflow, subtraction1} = div.remainder - test_multiple1;
assign test_multiple2 = test_multiple1 >> 1;
assign subtraction2 = div.remainder - test_multiple2;
assign new_remainder = overflow ? subtraction2 : subtraction1;
initial begin
R = 0;
div.remainder = 0;
end
always @ (posedge clk) begin
if (start)
R <= A;
if (div.start)
div.remainder <= div.dividend;
else if (~terminate & running)
R <= new_R;
div.remainder <= new_remainder;
end
////////////////////////////////////////////////////
//Quotient Determination
assign CLZ_delta = divisor_CLZ_r - remainder_CLZ;
always_comb begin
new_Q_bit1 = 0;
new_Q_bit1[CLZ_delta] = 1;
end
assign new_Q_bit2 = new_Q_bit1 >> 1;
assign new_quotient = div.quotient | (overflow ? new_Q_bit2 : new_Q_bit1);
always_ff @ (posedge clk) begin
if (div.start)
div.quotient <= div.divisor_is_zero ? '1 : '0;
else if (~terminate & running)
div.quotient <= new_quotient;
end
////////////////////////////////////////////////////
//End of Implementation
////////////////////////////////////////////////////
////////////////////////////////////////////////////
//Assertions
endmodule

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,64 +18,49 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
Alec Lu <alec_lu@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_quick_clz_mk2
#(
parameter C_WIDTH = 32
)(
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
unsigned_division_interface.divider div
);
logic running;
logic terminate;
logic [C_WIDTH-1:0] A_r;
logic [C_WIDTH:0] A0;
logic [C_WIDTH:0] A1;
logic [C_WIDTH-1:0] A2;
logic [div.DATA_WIDTH:0] A0;
logic [div.DATA_WIDTH:0] A1;
logic [div.DATA_WIDTH-1:0] A2;
logic [C_WIDTH-1:0] new_R;
logic [C_WIDTH-1:0] new_Q_bit;
logic [C_WIDTH-1:0] new_R2;
logic [div.DATA_WIDTH-1:0] new_R;
logic [div.DATA_WIDTH-1:0] new_Q_bit;
logic [div.DATA_WIDTH-1:0] new_R2;
logic [C_WIDTH-1:0] Q_bit1;
logic [C_WIDTH-1:0] Q_bit2;
logic [div.DATA_WIDTH-1:0] Q_bit1;
logic [div.DATA_WIDTH-1:0] Q_bit2;
logic [C_WIDTH-1:0] B1;
logic [C_WIDTH-1:0] B2;
logic [C_WIDTH-1:0] B_r;
logic [div.DATA_WIDTH-1:0] B1;
logic [div.DATA_WIDTH-1:0] B2;
localparam CLZ_W = $clog2(C_WIDTH);
localparam CLZ_W = $clog2(div.DATA_WIDTH);
logic [CLZ_W-1:0] R_CLZ;
logic [CLZ_W-1:0] B_CLZ;
logic [CLZ_W-1:0] B_CLZ_r;
logic [CLZ_W-1:0] CLZ_delta;
logic firstCycle;
logic [C_WIDTH-1:0] shiftedB;
logic [div.DATA_WIDTH-1:0] shiftedB;
//////////////////////////////////////////
clz clz_r (.clz_input(R), .clz(R_CLZ));
clz clz_b (.clz_input(B), .clz(B_CLZ));
clz clz_r (.clz_input(div.remainder), .clz(R_CLZ));
clz clz_b (.clz_input(div.divisor), .clz(B_CLZ));
always_ff @ (posedge clk) begin
firstCycle <= start;
B_CLZ_r <= B_CLZ;
A_r <= A;
B_r <= B;
shiftedB <= B_r << B_CLZ_r;
shiftedB <= div.divisor << B_CLZ;
end
assign CLZ_delta = B_CLZ_r - R_CLZ;
@ -84,70 +69,65 @@ module div_quick_clz_mk2
Q_bit1 = 0;
Q_bit1[CLZ_delta] = 1;
end
assign Q_bit2 = {1'b0, Q_bit1[C_WIDTH-1:1]};
assign Q_bit2 = {1'b0, Q_bit1[div.DATA_WIDTH-1:1]};
always_comb begin
if (A1[C_WIDTH])
if (A1[div.DATA_WIDTH])
new_Q_bit = Q_bit2;
else if (A0[C_WIDTH] || CLZ_delta == 0)
else if (A0[div.DATA_WIDTH] || CLZ_delta == 0)
new_Q_bit = Q_bit1;
else
new_Q_bit = (Q_bit1 | Q_bit2);
end
assign B1 = shiftedB >> R_CLZ;
assign A1 = R - B1;
assign B2 = {1'b0, B1[C_WIDTH-1:1]};
assign A2 = R - B2;
assign A1 = div.remainder - B1;
assign B2 = {1'b0, B1[div.DATA_WIDTH-1:1]};
assign A2 = div.remainder - B2;
assign A0 = R - (B1 + B2);
assign A0 = div.remainder - (B1 + B2);
always_comb begin
if (A1[C_WIDTH])
new_R = A2[C_WIDTH-1:0];
else if (A0[C_WIDTH] || CLZ_delta == 0)
new_R = A1[C_WIDTH-1:0];
if (A1[div.DATA_WIDTH])
new_R = A2[div.DATA_WIDTH-1:0];
else if (A0[div.DATA_WIDTH] || CLZ_delta == 0)
new_R = A1[div.DATA_WIDTH-1:0];
else
new_R = A0[C_WIDTH-1:0];
new_R = A0[div.DATA_WIDTH-1:0];
end
assign B_is_zero = (B_CLZ_r == 5'b11111 && ~B_r[0]);
assign div.divisor_is_zero = (B_CLZ == 5'b11111 && ~div.divisor[0]);
always_ff @ (posedge clk) begin
if (rst)
running <= 0;
else if (firstCycle & ~B_is_zero)
else if (div.start & ~div.divisor_is_zero)
running <= 1;
else if (terminate)
running <= 0;
end
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
else if (ack)
complete <= 0;
else if ((running & terminate) | (firstCycle & B_is_zero))
complete <= 1;
div.done <= (running & terminate) | (div.start & div.divisor_is_zero);
end
assign terminate = ({firstCycle, R} < {1'b0, B_r});
assign terminate = div.remainder < div.divisor;
always_ff @ (posedge clk) begin
if (firstCycle)
Q <= B_is_zero ? '1 : '0;
if (div.start)
div.quotient <= div.divisor_is_zero ? '1 : '0;
else if (~terminate & running)
Q <= Q | new_Q_bit;
div.quotient <= div.quotient | new_Q_bit;
end
initial begin
R = 0;
div.remainder = 0;
end
always @ (posedge clk) begin
if (firstCycle)
R <= A_r;
if (div.start)
div.remainder <= div.dividend;
else if (~terminate & running)
R <= new_R;
div.remainder <= new_R;
end
endmodule

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,75 +18,63 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
Alec Lu <alec_lu@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_quick_naive
#(
parameter C_WIDTH = 32
)
(
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
);
unsigned_division_interface.divider div
);
logic running;
logic terminate;
logic [C_WIDTH:0] A1;
logic [C_WIDTH-1:0] A2;
logic [div.DATA_WIDTH:0] A1;
logic [div.DATA_WIDTH-1:0] A2;
logic [C_WIDTH-1:0] new_R;
logic [C_WIDTH-1:0] new_Q_bit;
logic [div.DATA_WIDTH-1:0] new_R;
logic [div.DATA_WIDTH-1:0] new_Q_bit;
logic [C_WIDTH-1:0] Q_bit1;
logic [C_WIDTH-1:0] Q_bit2;
logic [div.DATA_WIDTH-1:0] Q_bit1;
logic [div.DATA_WIDTH-1:0] Q_bit2;
logic [C_WIDTH-1:0] B1;
logic [C_WIDTH-1:0] B2;
logic [C_WIDTH-1:0] B_r;
logic [div.DATA_WIDTH-1:0] B1;
logic [div.DATA_WIDTH-1:0] B2;
localparam MSB_W = $clog2(C_WIDTH);
localparam MSB_W = $clog2(div.DATA_WIDTH);
logic [MSB_W-1:0] R_MSB;
logic [MSB_W-1:0] B_MSB;
logic [MSB_W-1:0] B_MSB_r;
logic [MSB_W-1:0] MSB_delta;
msb_naive msb_r (.msb_input(R), .msb(R_MSB));
msb_naive msb_b (.msb_input(B), .msb(B_MSB));
// msb msb_r (.msb_input(R), .msb(R_MSB));
// msb msb_b (.msb_input(B_r), .msb(B_MSB));
msb_naive msb_r (.msb_input(div.remainder), .msb(R_MSB));
msb_naive msb_b (.msb_input(div.divisor), .msb(B_MSB));
// msb msb_r (.msb_input(div.remainder), .msb(R_MSB));
// msb msb_b (.msb_input(div.divisor), .msb(B_MSB));
assign MSB_delta = R_MSB - B_MSB_r;
assign Q_bit1 = 2**MSB_delta;
assign Q_bit2 = {1'b0, Q_bit1[C_WIDTH-1:1]};
assign new_Q_bit = Q | (A1[C_WIDTH] ? Q_bit2 : Q_bit1);
assign Q_bit2 = {1'b0, Q_bit1[div.DATA_WIDTH-1:1]};
assign new_Q_bit = div.quotient | (A1[div.DATA_WIDTH] ? Q_bit2 : Q_bit1);
assign B1 = B_r << MSB_delta;
assign A1 = R - B1;
assign B2 = {1'b0,B1[C_WIDTH-1:1]};
assign A2 = R - B2;
assign B1 = div.divisor << MSB_delta;
assign A1 = div.remainder - B1;
assign B2 = {1'b0,B1[div.DATA_WIDTH-1:1]};
assign A2 = div.remainder - B2;
assign new_R = A1[C_WIDTH] ? A2 : A1[C_WIDTH-1:0];
assign new_R = A1[div.DATA_WIDTH] ? A2 : A1[div.DATA_WIDTH-1:0];
assign B_is_zero = (B_MSB == 0 && ~B[0]);
assign div.divisor_is_zero = (B_MSB == 0 && ~div.divisor[0]);
always_ff @ (posedge clk) begin
if (rst)
running <= 0;
else if (start & ~B_is_zero)
else if (div.start & ~div.divisor_is_zero)
running <= 1;
else if (terminate)
running <= 0;
@ -94,25 +82,24 @@ module div_quick_naive
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
else if (ack)
complete <= 0;
else if ((running & terminate) | (start & B_is_zero))
complete <= 1;
div.done <= 0;
else if (div.done)
div.done <= 0;
else if ((running & terminate) | (div.start & div.divisor_is_zero))
div.done <= 1;
end
assign terminate = (R < B_r);
assign terminate = (div.remainder < div.divisor);
always_ff @ (posedge clk) begin
B_r <= B;
B_MSB_r <= B_MSB;
if (start) begin
Q <= B_is_zero ? '1 : 0;
R <= A;
if (div.start) begin
div.quotient <= div.divisor_is_zero ? '1 : 0;
div.remainder <= div.dividend;
end
else if (~terminate & running) begin
Q <= new_Q_bit;
R <= new_R;
div.quotient <= new_Q_bit;
div.remainder <= new_R;
end
end

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,48 +18,40 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_quick_radix_4
#(
parameter C_WIDTH = 32
)(
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
unsigned_division_interface.divider div
);
logic terminate;
logic [C_WIDTH/2-1:0] shift_count;
logic [div.DATA_WIDTH/2-1:0] shift_count;
logic [C_WIDTH+1:0] PR;
logic [div.DATA_WIDTH+1:0] PR;
logic [2:0] new_PR_sign;
logic [C_WIDTH+2:0] new_PR_1;
logic [C_WIDTH+2:0] new_PR_2;
logic [C_WIDTH+2:0] new_PR_3;
logic [C_WIDTH+1:0] B_1;
logic [C_WIDTH+1:0] B_2;
logic [C_WIDTH+1:0] B_3;
logic [div.DATA_WIDTH+2:0] new_PR_1;
logic [div.DATA_WIDTH+2:0] new_PR_2;
logic [div.DATA_WIDTH+2:0] new_PR_3;
logic [div.DATA_WIDTH+1:0] B_1;
logic [div.DATA_WIDTH+1:0] B_2;
logic [div.DATA_WIDTH+1:0] B_3;
logic [C_WIDTH-1:0] A_r;
logic [C_WIDTH-1:0] B_r;
logic [C_WIDTH-1:0] AR_r;
logic [C_WIDTH-1:0] Q_temp;
logic [div.DATA_WIDTH-1:0] A_r;
logic [div.DATA_WIDTH-1:0] B_r;
logic [div.DATA_WIDTH-1:0] AR_r;
logic [div.DATA_WIDTH-1:0] Q_temp;
logic [5:0] shift_num_R;
logic [5:0] shift_num_Q;
logic [C_WIDTH*2:0] combined;
logic [C_WIDTH*2:0] combined_normalized;
logic [div.DATA_WIDTH*2+1:0] combined;
logic [div.DATA_WIDTH*2+1:0] combined_normalized;
logic terminate_early;
localparam CLZ_W = $clog2(C_WIDTH);
localparam CLZ_W = $clog2(div.DATA_WIDTH);
logic [CLZ_W-1:0] A_CLZ;
logic [CLZ_W-1:0] B_CLZ;
logic [CLZ_W-1:0] A_CLZ_r;
@ -68,21 +60,21 @@ module div_quick_radix_4
logic firstCycle;
logic greaterDivisor;
logic [C_WIDTH-1:0] A_shifted;
logic [C_WIDTH-1:0] B_shifted;
logic [C_WIDTH-1:0] R_shifted;
logic [div.DATA_WIDTH-1:0] A_shifted;
logic [div.DATA_WIDTH-1:0] B_shifted;
logic [div.DATA_WIDTH-1:0] R_shifted;
//implementation
////////////////////////////////////////////////////
clz clz_r (.clz_input(A), .clz(A_CLZ));
clz clz_b (.clz_input(B), .clz(B_CLZ));
clz clz_r (.clz_input(div.dividend), .clz(A_CLZ));
clz clz_b (.clz_input(div.divisor), .clz(B_CLZ));
always_ff @ (posedge clk) begin
firstCycle <= start;
firstCycle <= div.start;
A_CLZ_r <= A_CLZ;
B_CLZ_r <= B_CLZ;
A_r <= A;
B_r <= B;
A_r <= div.dividend;
B_r <= div.divisor;
end
assign A_shifted = A_r << A_CLZ_r;
assign B_shifted = B_r << A_CLZ_r;
@ -90,12 +82,12 @@ module div_quick_radix_4
assign new_PR_1 = {1'b0, PR} - {1'b0, B_1};
assign new_PR_2 = {1'b0, PR} - {1'b0, B_2};
assign new_PR_3 = {1'b0, PR} - {1'b0, B_3};
assign new_PR_sign = {new_PR_3[C_WIDTH+2], new_PR_2[C_WIDTH+2], new_PR_1[C_WIDTH+2]};
assign new_PR_sign = {new_PR_3[div.DATA_WIDTH+2], new_PR_2[div.DATA_WIDTH+2], new_PR_1[div.DATA_WIDTH+2]};
//Shift reg for
always_ff @ (posedge clk) begin
if (firstCycle)
shift_count <= 32'd1;
shift_count <= 1;
else
shift_count <= {shift_count[14:0], firstCycle};
end
@ -112,57 +104,53 @@ module div_quick_radix_4
end
assign combined_normalized = {PR, AR_r} >> (shift_num_R + A_CLZ_r);
assign R = combined_normalized[C_WIDTH-1:0];
assign div.remainder = combined_normalized[div.DATA_WIDTH-1:0];
assign combined = {PR, AR_r} >> shift_num_R;
assign R_shifted = combined[C_WIDTH-1:0];
assign R_shifted = combined[div.DATA_WIDTH-1:0];
assign terminate_early = (B_shifted > R_shifted) | greaterDivisor;
assign Q = terminate_early ? (Q_temp << shift_num_Q) : Q_temp;
assign div.quotient = terminate_early ? (Q_temp << shift_num_Q) : Q_temp;
always_ff @ (posedge clk) begin
if (firstCycle) begin
PR <= {{(C_WIDTH-1){1'b0}}, A_shifted[C_WIDTH-1:C_WIDTH-2]};
Q_temp <= B_is_zero ? '1 : '0;
AR_r <= {A_shifted[C_WIDTH-3:0], 2'b00};
PR <= {{(div.DATA_WIDTH){1'b0}}, A_shifted[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= div.divisor_is_zero ? '1 : '0;
AR_r <= {A_shifted[div.DATA_WIDTH-3:0], 2'b00};
greaterDivisor <= B_r > A_r;
B_1 <= {2'b0, B_shifted}; //1xB
B_2 <= {1'b0, B_shifted, 1'b0}; //2xB
B_3 <= {1'b0, B_shifted, 1'b0} + B_shifted; //3xB
B_3 <= {1'b0, B_shifted, 1'b0} + {2'b0, B_shifted}; //3xB
end else if (~terminate & ~terminate_early) begin
AR_r <= {AR_r[C_WIDTH-3:0], 2'b00};
casex (new_PR_sign)
AR_r <= {AR_r[div.DATA_WIDTH-3:0], 2'b00};
case (new_PR_sign)
3'b111 : begin
PR <= {PR[C_WIDTH-1:0], AR_r[C_WIDTH-1:C_WIDTH-2]};
Q_temp <= {Q[C_WIDTH-3:0], 2'b00};
PR <= {PR[div.DATA_WIDTH-1:0], AR_r[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= {div.quotient[div.DATA_WIDTH-3:0], 2'b00};
end
3'b110 : begin
PR <= {new_PR_1[C_WIDTH-1:0], AR_r[C_WIDTH-1:C_WIDTH-2]};
Q_temp <= {Q[C_WIDTH-3:0], 2'b01};
PR <= {new_PR_1[div.DATA_WIDTH-1:0], AR_r[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= {div.quotient[div.DATA_WIDTH-3:0], 2'b01};
end
3'b100 : begin
PR <= {new_PR_2[C_WIDTH-1:0], AR_r[C_WIDTH-1:C_WIDTH-2]};
Q_temp <= {Q[C_WIDTH-3:0], 2'b10};
PR <= {new_PR_2[div.DATA_WIDTH-1:0], AR_r[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= {div.quotient[div.DATA_WIDTH-3:0], 2'b10};
end
3'b000 : begin
PR <= {new_PR_3[C_WIDTH-1:0], AR_r[C_WIDTH-1:C_WIDTH-2]};
Q_temp <= {Q[C_WIDTH-3:0], 2'b11};
default : begin //3'b000 : begin
PR <= {new_PR_3[div.DATA_WIDTH-1:0], AR_r[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= {div.quotient[div.DATA_WIDTH-3:0], 2'b11};
end
default begin
PR <= 'x;
Q_temp <= 'x;
end
endcase
end
end
// always_ff @ (posedge clk) begin
// if (firstCycle)
// B_is_zero <= ~B_r[0];
// div.divisor_is_zero <= ~B_r[0];
// else if (~terminate)
// B_is_zero <= B_is_zero & ~(|new_PR_sign);
// div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
// end
assign B_is_zero = (&B_CLZ_r) & ~B_r[0];
assign div.divisor_is_zero = (&B_CLZ_r) & ~B_r[0];
always_ff @ (posedge clk) begin
if (rst)
@ -177,13 +165,13 @@ module div_quick_radix_4
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
div.done <= 0;
else begin
if ((~firstCycle & (shift_count[15] | terminate_early) & ~complete & ~terminate) | (firstCycle & B_is_zero))
complete <= 1;
else if (ack)
complete <= 0;
if ((~firstCycle & (shift_count[15] | terminate_early) & ~div.done & ~terminate) | (firstCycle & div.divisor_is_zero))
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end
endmodule
endmodule

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,126 +18,114 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
Alec Lu <alec_lu@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix16
#(
parameter C_WIDTH = 32
)(
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
);
unsigned_division_interface.divider div
);
logic terminate;
logic [C_WIDTH-1:0] shift_count;
logic [div.DATA_WIDTH-1:0] shift_count;
logic [C_WIDTH+3:0] PR;
logic [C_WIDTH+3:0] PR_lower;
logic [C_WIDTH+3:0] PR_upper;
logic [C_WIDTH-1:0] Q_lower;
logic [C_WIDTH-1:0] Q_upper;
logic [div.DATA_WIDTH+3:0] PR;
logic [div.DATA_WIDTH+3:0] PR_lower;
logic [div.DATA_WIDTH+3:0] PR_upper;
logic [div.DATA_WIDTH-1:0] Q_lower;
logic [div.DATA_WIDTH-1:0] Q_upper;
logic [6:0] new_PR_sign;
logic [C_WIDTH+4:0] new_PR_8;
logic [C_WIDTH+4:0] new_PR [6:0];
logic [div.DATA_WIDTH+4:0] new_PR_8;
logic [div.DATA_WIDTH+4:0] new_PR [6:0];
logic [C_WIDTH+3:0] B_6;
logic [C_WIDTH+3:0] B_10;
logic [C_WIDTH+3:0] B_12;
logic [C_WIDTH+3:0] B_14;
logic [div.DATA_WIDTH+3:0] B_6;
logic [div.DATA_WIDTH+3:0] B_10;
logic [div.DATA_WIDTH+3:0] B_12;
logic [div.DATA_WIDTH+3:0] B_14;
//Shift reg for
always_ff @ (posedge clk) begin
shift_count[0] <= start;
shift_count[0] <= div.start;
shift_count[31:1] <= shift_count[30:0];
end
assign new_PR_8 = {1'b0, PR} - {1'b0, {1'b0, B, 3'b000}};
assign new_PR[0] = new_PR_8[C_WIDTH+4] ? {1'b0, PR} - {1'b0, {4'b0000, B}} : {1'b0, PR} - {1'b0, {1'b0, B, 3'b000}} - {4'b0000, B};
assign new_PR[1] = new_PR_8[C_WIDTH+4] ? {1'b0, PR} - {1'b0, {3'b000, B, 1'b0}} : {1'b0, PR} - {1'b0, B_10};
assign new_PR[2] = new_PR_8[C_WIDTH+4] ? {1'b0, PR} - {1'b0, {3'b000, B, 1'b0}} - {4'b0000, B} : {1'b0, PR} - {1'b0, B_10} - {4'b0000, B};
assign new_PR[3] = new_PR_8[C_WIDTH+4] ? {1'b0, PR} - {1'b0, {2'b00, B, 2'b00}} : {1'b0, PR} - {1'b0, B_12};
assign new_PR[4] = new_PR_8[C_WIDTH+4] ? {1'b0, PR} - {1'b0, {2'b00, B, 2'b00}} - {4'b0000, B} : {1'b0, PR} - {1'b0, B_12} - {4'b0000, B};
assign new_PR[5] = new_PR_8[C_WIDTH+4] ? {1'b0, PR} - {1'b0, B_6} : {1'b0, PR} - {1'b0, B_14};
assign new_PR[6] = new_PR_8[C_WIDTH+4] ? {1'b0, PR} - {1'b0, B_6} - {4'b0000, B} : {1'b0, PR} - {1'b0, B_14} - {4'b0000, B};
assign new_PR_8 = {1'b0, PR} - {1'b0, {1'b0, div.divisor, 3'b000}};
assign new_PR[0] = new_PR_8[div.DATA_WIDTH+4] ? {1'b0, PR} - {1'b0, {4'b0000, div.divisor}} : {1'b0, PR} - {1'b0, {1'b0, div.divisor, 3'b000}} - {4'b0000, div.divisor};
assign new_PR[1] = new_PR_8[div.DATA_WIDTH+4] ? {1'b0, PR} - {1'b0, {3'b000, div.divisor, 1'b0}} : {1'b0, PR} - {1'b0, B_10};
assign new_PR[2] = new_PR_8[div.DATA_WIDTH+4] ? {1'b0, PR} - {1'b0, {3'b000, div.divisor, 1'b0}} - {4'b0000, div.divisor} : {1'b0, PR} - {1'b0, B_10} - {4'b0000, div.divisor};
assign new_PR[3] = new_PR_8[div.DATA_WIDTH+4] ? {1'b0, PR} - {1'b0, {2'b00, div.divisor, 2'b00}} : {1'b0, PR} - {1'b0, B_12};
assign new_PR[4] = new_PR_8[div.DATA_WIDTH+4] ? {1'b0, PR} - {1'b0, {2'b00, div.divisor, 2'b00}} - {4'b0000, div.divisor} : {1'b0, PR} - {1'b0, B_12} - {4'b0000, div.divisor};
assign new_PR[5] = new_PR_8[div.DATA_WIDTH+4] ? {1'b0, PR} - {1'b0, B_6} : {1'b0, PR} - {1'b0, B_14};
assign new_PR[6] = new_PR_8[div.DATA_WIDTH+4] ? {1'b0, PR} - {1'b0, B_6} - {4'b0000, div.divisor} : {1'b0, PR} - {1'b0, B_14} - {4'b0000, div.divisor};
assign new_PR_sign = {new_PR[6][C_WIDTH+4], new_PR[5][C_WIDTH+4], new_PR[4][C_WIDTH+4],
new_PR[3][C_WIDTH+4], new_PR[2][C_WIDTH+4], new_PR[1][C_WIDTH+4],
new_PR[0][C_WIDTH+4]};
assign new_PR_sign = {new_PR[6][div.DATA_WIDTH+4], new_PR[5][div.DATA_WIDTH+4], new_PR[4][div.DATA_WIDTH+4],
new_PR[3][div.DATA_WIDTH+4], new_PR[2][div.DATA_WIDTH+4], new_PR[1][div.DATA_WIDTH+4],
new_PR[0][div.DATA_WIDTH+4]};
always_comb begin
PR_lower = ({PR[C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-4]} & {(C_WIDTH+4){(new_PR_sign[0])}});
Q_lower = ({Q[C_WIDTH-5:0], 4'b0000} & {C_WIDTH{(new_PR_sign[0])}});
PR_lower = ({PR[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-4]} & {(div.DATA_WIDTH+4){(new_PR_sign[0])}});
Q_lower = ({div.quotient[div.DATA_WIDTH-5:0], 4'b0000} & {div.DATA_WIDTH{(new_PR_sign[0])}});
for (int i = 1; i < 7; i = i+1) begin
PR_lower = PR_lower | ({new_PR[i-1][C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-4]} & {(C_WIDTH+4){(~new_PR_sign[i-1] & new_PR_sign[i])}});
Q_lower = Q_lower | ({Q[C_WIDTH-5:0], i[3:0]} & {C_WIDTH{(~new_PR_sign[i-1] & new_PR_sign[i])}});
PR_lower = PR_lower | ({new_PR[i-1][div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-4]} & {(div.DATA_WIDTH+4){(~new_PR_sign[i-1] & new_PR_sign[i])}});
Q_lower = Q_lower | ({div.quotient[div.DATA_WIDTH-5:0], i[3:0]} & {div.DATA_WIDTH{(~new_PR_sign[i-1] & new_PR_sign[i])}});
end
PR_lower = PR_lower | ({new_PR[6][C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-4]} & {(C_WIDTH+4){(~new_PR_sign[6])}});
Q_lower = Q_lower | ({Q[C_WIDTH-5:0], 4'b0111} & {C_WIDTH{(~new_PR_sign[6])}});
PR_lower = PR_lower | ({new_PR[6][div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-4]} & {(div.DATA_WIDTH+4){(~new_PR_sign[6])}});
Q_lower = Q_lower | ({div.quotient[div.DATA_WIDTH-5:0], 4'b0111} & {div.DATA_WIDTH{(~new_PR_sign[6])}});
PR_upper = {new_PR_8[C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-4]} & {(C_WIDTH+4){new_PR_sign[0]}};
Q_upper = {Q[C_WIDTH-5:0], 4'b1000} & {C_WIDTH{new_PR_sign[0]}};
PR_upper = {new_PR_8[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-4]} & {(div.DATA_WIDTH+4){new_PR_sign[0]}};
Q_upper = {div.quotient[div.DATA_WIDTH-5:0], 4'b1000} & {div.DATA_WIDTH{new_PR_sign[0]}};
for (int i = 1; i < 7; i = i+1) begin
PR_upper = PR_upper | ({new_PR[i-1][C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-4]} & {(C_WIDTH+4){(~new_PR_sign[i-1] & new_PR_sign[i])}});
Q_upper = Q_upper | ({Q[C_WIDTH-5:0], (i[3:0] | 4'b1000)} & {C_WIDTH{(~new_PR_sign[i-1] & new_PR_sign[i])}});
PR_upper = PR_upper | ({new_PR[i-1][div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-4]} & {(div.DATA_WIDTH+4){(~new_PR_sign[i-1] & new_PR_sign[i])}});
Q_upper = Q_upper | ({div.quotient[div.DATA_WIDTH-5:0], (i[3:0] | 4'b1000)} & {div.DATA_WIDTH{(~new_PR_sign[i-1] & new_PR_sign[i])}});
end
PR_upper = PR_upper | ({new_PR[6][C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-4]} & {(C_WIDTH+4){(~new_PR_sign[6])}});
Q_upper = Q_upper | ({Q[C_WIDTH-5:0], 4'b1111} & {C_WIDTH{(~new_PR_sign[6])}});
PR_upper = PR_upper | ({new_PR[6][div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-4]} & {(div.DATA_WIDTH+4){(~new_PR_sign[6])}});
Q_upper = Q_upper | ({div.quotient[div.DATA_WIDTH-5:0], 4'b1111} & {div.DATA_WIDTH{(~new_PR_sign[6])}});
end
always_ff @ (posedge clk) begin
if (start) begin
B_6 <= {2'b00, B, 2'b00} + {3'b000, B, 1'b0};
B_10 <= {1'b0, B, 3'b000} + {3'b000, B, 1'b0};
B_12 <= {1'b0, B, 3'b000} + {2'b00, B, 2'b00};
B_14 <= {1'b0, B, 3'b000} + {2'b00, B, 2'b00} + {3'b000, B, 1'b0};
if (div.start) begin
B_6 <= {2'b00, div.divisor, 2'b00} + {3'b000, div.divisor, 1'b0};
B_10 <= {1'b0, div.divisor, 3'b000} + {3'b000, div.divisor, 1'b0};
B_12 <= {1'b0, div.divisor, 3'b000} + {2'b00, div.divisor, 2'b00};
B_14 <= {1'b0, div.divisor, 3'b000} + {2'b00, div.divisor, 2'b00} + {3'b000, div.divisor, 1'b0};
PR <= {{(C_WIDTH){1'b0}}, A[C_WIDTH-1:C_WIDTH-4]};
Q <= {A[C_WIDTH-5:0], 4'b0000};
PR <= {{(div.DATA_WIDTH){1'b0}}, div.dividend[div.DATA_WIDTH-1:div.DATA_WIDTH-4]};
div.quotient <= {div.dividend[div.DATA_WIDTH-5:0], 4'b0000};
end
else if (~terminate) begin
casez (new_PR_8[C_WIDTH+4])
case (new_PR_8[div.DATA_WIDTH+4])
1'b1 : begin
PR <= PR_lower;
Q <= Q_lower;
div.quotient <= Q_lower;
end
1'b0 : begin
PR <= PR_upper;
Q <= Q_upper;
end
default : begin
PR <= 'x;
Q <= 'x;
div.quotient <= Q_upper;
end
endcase
end
end
assign R = PR[C_WIDTH+3:4];
assign div.remainder = PR[div.DATA_WIDTH+3:4];
always_ff @ (posedge clk) begin
if (start)
B_is_zero <= ~B[0];
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
B_is_zero <= B_is_zero & ~(|new_PR_sign);
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (start)
if (div.start)
terminate <= 0;
if (shift_count[7])
terminate <= 1;
@ -146,12 +134,12 @@ module div_radix16
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
div.done <= 0;
else begin
if (shift_count[7])
complete <= 1;
else if (ack)
complete <= 0;
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,71 +18,59 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix2
#(
parameter C_WIDTH = 32
)(
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
unsigned_division_interface.divider div
);
logic terminate;
logic [C_WIDTH:0] new_PR;
logic [C_WIDTH:0] PR;
logic [C_WIDTH-1:0] shift_count;
logic [C_WIDTH-1:0] B_r;
logic [div.DATA_WIDTH:0] new_PR;
logic [div.DATA_WIDTH:0] PR;
logic [div.DATA_WIDTH-1:0] shift_count;
logic negative_sub_rst;
//implementation
////////////////////////////////////////////////////
assign new_PR = PR - {1'b0, B_r};
assign negative_sub_rst = new_PR[C_WIDTH];
assign new_PR = PR - {1'b0, div.divisor};
assign negative_sub_rst = new_PR[div.DATA_WIDTH];
//Shift reg for
always_ff @ (posedge clk) begin
shift_count <= {shift_count[30:0], start};
shift_count <= {shift_count[30:0], div.start};
end
always_ff @ (posedge clk) begin
if (start) begin
PR <= {{(C_WIDTH){1'b0}}, A[C_WIDTH-1]};
Q <= {A[C_WIDTH-2:0], 1'b0};
B_r <= B;
if (div.start) begin
PR <= {(div.DATA_WIDTH)'(1'b0), div.dividend[div.DATA_WIDTH-1]};
div.quotient <= {div.dividend[div.DATA_WIDTH-2:0], 1'b0};
end
else if (~terminate) begin
PR <= negative_sub_rst ? {PR[C_WIDTH-1:0], Q[C_WIDTH-1]} : {new_PR[C_WIDTH-1:0], Q[C_WIDTH-1]};
Q <= {Q[C_WIDTH-2:0], ~negative_sub_rst};
PR <= negative_sub_rst ? {PR[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1]} : {new_PR[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1]};
div.quotient <= {div.quotient[div.DATA_WIDTH-2:0], ~negative_sub_rst};
end
end
assign R = PR[C_WIDTH:1];
assign div.remainder = PR[div.DATA_WIDTH:1];
always_ff @ (posedge clk) begin
if (start)
B_is_zero <= ~B[0];
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
B_is_zero <= B_is_zero & ~negative_sub_rst;
div.divisor_is_zero <= div.divisor_is_zero & ~negative_sub_rst;
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (start)
if (div.start)
terminate <= 0;
if (shift_count[31])
terminate <= 1;
@ -91,12 +79,12 @@ module div_radix2
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
div.done <= 0;
else begin
if (shift_count[31])
complete <= 1;
else if (ack)
complete <= 0;
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,78 +18,67 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
Alec Lu <alec_lu@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix2_ET
#(
parameter C_WIDTH = 32
)(
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
);
unsigned_division_interface.divider div
);
logic terminate;
logic terminate_early;
logic [C_WIDTH:0] new_PR;
logic [C_WIDTH:0] PR;
logic [div.DATA_WIDTH:0] new_PR;
logic [div.DATA_WIDTH:0] PR;
logic [C_WIDTH-1:0] shift_count;
logic [div.DATA_WIDTH-1:0] shift_count;
logic [C_WIDTH-1:0] B_r;
logic negative_sub_rst;
//implementation
////////////////////////////////////////////////////
assign new_PR = PR - {1'b0, B_r};
assign negative_sub_rst = new_PR[C_WIDTH];
assign new_PR = PR - {1'b0, div.divisor};
assign negative_sub_rst = new_PR[div.DATA_WIDTH];
always_ff @ (posedge clk) begin
shift_count <= {shift_count[30:0], start & ~terminate_early};
shift_count <= {shift_count[30:0], div.start & ~terminate_early};
end
assign terminate_early = B > A;
assign terminate_early = div.divisor > div.dividend;
always_ff @ (posedge clk) begin
if (start) begin
if (div.start) begin
if (terminate_early) begin
PR <= {A, 1'b0};
Q <= '0;
PR <= {div.dividend, 1'b0};
div.quotient <= '0;
end else begin
PR <= {{(C_WIDTH-2){1'b0}}, A[C_WIDTH-1]};
Q <= {A[C_WIDTH-2:0], 1'b0};
PR <= {(div.DATA_WIDTH)'(1'b0), div.dividend[div.DATA_WIDTH-1]};
div.quotient <= {div.dividend[div.DATA_WIDTH-2:0], 1'b0};
end
B_r <= B;
end else if (~terminate) begin
PR <= negative_sub_rst ? {PR[C_WIDTH-1:0], Q[C_WIDTH-1]} : {new_PR[C_WIDTH-1:0], Q[C_WIDTH-1]};
Q <= {Q[C_WIDTH-2:0], ~negative_sub_rst};
PR <= negative_sub_rst ? {PR[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1]} : {new_PR[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1]};
div.quotient <= {div.quotient[div.DATA_WIDTH-2:0], ~negative_sub_rst};
end
end
assign R = PR[C_WIDTH:1];
assign div.remainder = PR[div.DATA_WIDTH:1];
always_ff @ (posedge clk) begin
if (start)
B_is_zero <= ~B[0];
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
B_is_zero <= B_is_zero & ~negative_sub_rst;
div.divisor_is_zero <= div.divisor_is_zero & ~negative_sub_rst;
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (start) begin
if (div.start) begin
if (terminate_early) begin
terminate <= 1;
end else begin
@ -103,12 +92,12 @@ module div_radix2_ET
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
div.done <= 0;
else begin
if (ack)
complete <= 0;
else if ((~start & (shift_count[31])) | (start & terminate_early))
complete <= 1;
if (div.done)
div.done <= 0;
else if ((~div.start & (shift_count[31])) | (div.start & terminate_early))
div.done <= 1;
end
end

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,58 +18,48 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
Alec Lu <alec_lu@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix2_ET_full
#(
parameter C_WIDTH = 32
)(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
);
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic terminate;
logic [C_WIDTH:0] new_PR;
logic [C_WIDTH:0] PR;
logic [div.DATA_WIDTH:0] new_PR;
logic [div.DATA_WIDTH:0] PR;
logic [C_WIDTH-1:0] shift_count;
logic [div.DATA_WIDTH-1:0] shift_count;
logic negative_sub_rst;
logic [C_WIDTH-1:0] B_r;
logic [C_WIDTH-1:0] AR_r;
logic [C_WIDTH-1:0] Q_temp;
logic [div.DATA_WIDTH-1:0] AR_r;
logic [div.DATA_WIDTH-1:0] Q_temp;
logic [5:0] shift_num_R;
logic [5:0] shift_num_Q;
logic [C_WIDTH*2:0] combined;
logic [C_WIDTH*2:0] combined_r;
logic [div.DATA_WIDTH*2:0] combined;
logic [div.DATA_WIDTH*2:0] combined_r;
logic terminate_early;
logic terminate_early_r;
//implementation
////////////////////////////////////////////////////
assign new_PR = PR - {1'b0, B_r};
assign negative_sub_rst = new_PR[C_WIDTH];
assign new_PR = PR - {1'b0, div.divisor};
assign negative_sub_rst = new_PR[div.DATA_WIDTH];
always_ff @ (posedge clk) begin
if (start)
if (div.start)
shift_count <= 32'd1;
else
shift_count <= {shift_count[30:0], start};
shift_count <= {shift_count[30:0], div.start};
end
always_ff @ (posedge clk) begin
if (start) begin
if (div.start) begin
shift_num_R <= 1;
shift_num_Q <= 32;
end
@ -81,37 +71,36 @@ module div_radix2_ET_full
assign combined = {PR, AR_r} >> shift_num_R;
assign R = combined[C_WIDTH-1:0];
assign terminate_early = B_r > R;
assign Q = terminate_early ? (Q_temp << shift_num_Q) : Q_temp;
assign div.remainder = combined[div.DATA_WIDTH-1:0];
assign terminate_early = div.divisor > div.remainder;
assign div.quotient = terminate_early ? (Q_temp << shift_num_Q) : Q_temp;
always_ff @ (posedge clk) begin
if (start) begin
PR <= {{(C_WIDTH-2){1'b0}}, A[C_WIDTH-1]};
if (div.start) begin
PR <= {(div.DATA_WIDTH)'(1'b0), div.dividend[div.DATA_WIDTH-1]};
Q_temp <= '0;
AR_r <= {A[C_WIDTH-2:0], 1'b0};
B_r <= B;
AR_r <= {div.dividend[div.DATA_WIDTH-2:0], 1'b0};
end
else if (~terminate & ~terminate_early) begin
PR <= negative_sub_rst ? {PR[C_WIDTH-1:0], AR_r[C_WIDTH-1]} :
{new_PR[C_WIDTH-1:0], AR_r[C_WIDTH-1]};
Q_temp <= {Q_temp[C_WIDTH-2:0], ~negative_sub_rst};
AR_r <= {AR_r[C_WIDTH-2:0], 1'b0};
PR <= negative_sub_rst ? {PR[div.DATA_WIDTH-1:0], AR_r[div.DATA_WIDTH-1]} :
{new_PR[div.DATA_WIDTH-1:0], AR_r[div.DATA_WIDTH-1]};
Q_temp <= {Q_temp[div.DATA_WIDTH-2:0], ~negative_sub_rst};
AR_r <= {AR_r[div.DATA_WIDTH-2:0], 1'b0};
end
end
always_ff @ (posedge clk) begin
if (start)
B_is_zero <= ~B[0];
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
B_is_zero <= B_is_zero & ~negative_sub_rst;
div.divisor_is_zero <= div.divisor_is_zero & ~negative_sub_rst;
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (start)
if (div.start)
terminate <= 0;
//if (shift_count[31])
else if (shift_count[31] | terminate_early)
@ -121,14 +110,14 @@ module div_radix2_ET_full
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
div.done <= 0;
else begin
// if (shift_count[31])
if (~start & (shift_count[31] | terminate_early) & ~complete & ~terminate)
complete <= 1;
else if (ack)
complete <= 0;
if (~div.start & (shift_count[31] | terminate_early) & ~div.done & ~terminate)
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end
endmodule
endmodule

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,97 +18,85 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix4
#(
parameter C_WIDTH = 32
)(
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
);
unsigned_division_interface.divider div
);
logic terminate;
logic [C_WIDTH/2-1:0] shift_count;
logic [div.DATA_WIDTH/2-1:0] shift_count;
logic [C_WIDTH+1:0] PR;
logic [div.DATA_WIDTH+1:0] PR;
logic [2:0] new_PR_sign;
logic [C_WIDTH+2:0] new_PR_1;
logic [C_WIDTH+2:0] new_PR_2;
logic [C_WIDTH+2:0] new_PR_3;
logic [C_WIDTH+1:0] B_1;
logic [C_WIDTH+1:0] B_2;
logic [C_WIDTH+1:0] B_3;
logic [div.DATA_WIDTH+2:0] new_PR_1;
logic [div.DATA_WIDTH+2:0] new_PR_2;
logic [div.DATA_WIDTH+2:0] new_PR_3;
logic [div.DATA_WIDTH+1:0] B_1;
logic [div.DATA_WIDTH+1:0] B_2;
logic [div.DATA_WIDTH+1:0] B_3;
//implementation
////////////////////////////////////////////////////
assign new_PR_1 = {1'b0, PR} - {1'b0, B_1};
assign new_PR_2 = {1'b0, PR} - {1'b0, B_2};
assign new_PR_3 = {1'b0, PR} - {1'b0, B_3};
assign new_PR_sign = {new_PR_3[C_WIDTH+2], new_PR_2[C_WIDTH+2], new_PR_1[C_WIDTH+2]};
assign new_PR_sign = {new_PR_3[div.DATA_WIDTH+2], new_PR_2[div.DATA_WIDTH+2], new_PR_1[div.DATA_WIDTH+2]};
//Shift reg for
always_ff @ (posedge clk) begin
shift_count <= {shift_count[14:0], start};
shift_count <= {shift_count[14:0], div.start};
end
always_ff @ (posedge clk) begin
if (start) begin
PR <= {{(C_WIDTH-1){1'b0}}, A[C_WIDTH-1:C_WIDTH-2]};
Q <= {A[C_WIDTH-3:0], 2'b00};
if (div.start) begin
PR <= {{(div.DATA_WIDTH){1'b0}}, div.dividend[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
div.quotient <= {div.dividend[div.DATA_WIDTH-3:0], 2'b00};
B_1 <= {2'b0, B}; //1xB
B_2 <= {1'b0, B, 1'b0}; //2xB
B_3 <= {1'b0, B, 1'b0} + B; //3xB
B_1 <= {2'b0, div.divisor}; //1xB
B_2 <= {1'b0, div.divisor, 1'b0}; //2xB
B_3 <= {1'b0, div.divisor, 1'b0} + {2'b0, div.divisor}; //3xB
end else if (~terminate) begin
casex (new_PR_sign)
case (new_PR_sign)
3'b111 : begin
PR <= {PR[C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-2]};
Q <= {Q[C_WIDTH-3:0], 2'b00};
PR <= {PR[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
div.quotient <= {div.quotient[div.DATA_WIDTH-3:0], 2'b00};
end
3'b110 : begin
PR <= {new_PR_1[C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-2]};
Q <= {Q[C_WIDTH-3:0], 2'b01};
PR <= {new_PR_1[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
div.quotient <= {div.quotient[div.DATA_WIDTH-3:0], 2'b01};
end
3'b100 : begin
PR <= {new_PR_2[C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-2]};
Q <= {Q[C_WIDTH-3:0], 2'b10};
PR <= {new_PR_2[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
div.quotient <= {div.quotient[div.DATA_WIDTH-3:0], 2'b10};
end
3'b000 : begin
PR <= {new_PR_3[C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-2]};
Q <= {Q[C_WIDTH-3:0], 2'b11};
default: begin //3'b000 : begin
PR <= {new_PR_3[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
div.quotient <= {div.quotient[div.DATA_WIDTH-3:0], 2'b11};
end
default begin
PR <= 'x;
Q <= 'x;
end
endcase
end
end
assign R = PR[C_WIDTH+1:2];
assign div.remainder = PR[div.DATA_WIDTH+1:2];
always_ff @ (posedge clk) begin
if (start)
B_is_zero <= ~B[0];
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
B_is_zero <= B_is_zero & ~(|new_PR_sign);
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (start)
if (div.start)
terminate <= 0;
if (shift_count[15])
terminate <= 1;
@ -117,13 +105,13 @@ module div_radix4
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
div.done <= 0;
else begin
if (shift_count[15])
complete <= 1;
else if (ack)
complete <= 0;
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end
endmodule
endmodule

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,107 +18,94 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix4_ET
#(
parameter C_WIDTH = 32
)(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic terminate;
logic terminate_early;
logic [C_WIDTH/2-1:0] shift_count;
logic [div.DATA_WIDTH/2-1:0] shift_count;
logic [C_WIDTH+1:0] PR;
logic [div.DATA_WIDTH+1:0] PR;
logic [2:0] new_PR_sign;
logic [C_WIDTH+2:0] new_PR_1;
logic [C_WIDTH+2:0] new_PR_2;
logic [C_WIDTH+2:0] new_PR_3;
logic [C_WIDTH+1:0] B_1;
logic [C_WIDTH+1:0] B_2;
logic [C_WIDTH+1:0] B_3;
logic [div.DATA_WIDTH+2:0] new_PR_1;
logic [div.DATA_WIDTH+2:0] new_PR_2;
logic [div.DATA_WIDTH+2:0] new_PR_3;
logic [div.DATA_WIDTH+1:0] B_1;
logic [div.DATA_WIDTH+1:0] B_2;
logic [div.DATA_WIDTH+1:0] B_3;
//implementation
////////////////////////////////////////////////////
assign new_PR_1 = {1'b0, PR} - {1'b0, B_1};
assign new_PR_2 = {1'b0, PR} - {1'b0, B_2};
assign new_PR_3 = {1'b0, PR} - {1'b0, B_3};
assign new_PR_sign = {new_PR_3[C_WIDTH+2], new_PR_2[C_WIDTH+2], new_PR_1[C_WIDTH+2]};
assign new_PR_sign = {new_PR_3[div.DATA_WIDTH+2], new_PR_2[div.DATA_WIDTH+2], new_PR_1[div.DATA_WIDTH+2]};
//Shift reg for
always_ff @ (posedge clk) begin
shift_count <= {shift_count[14:0], start & ~terminate_early};
shift_count <= {shift_count[14:0], div.start & ~terminate_early};
end
assign terminate_early = B > A;
assign terminate_early = div.divisor > div.dividend;
always_ff @ (posedge clk) begin
if (start) begin
if (div.start) begin
if (terminate_early) begin
PR <= {A, 2'b00};
Q <= '0;
PR <= {div.dividend, 2'b00};
div.quotient <= '0;
end
else begin
PR <= {{(C_WIDTH-1){1'b0}}, A[C_WIDTH-1:C_WIDTH-2]};
Q <= {A[C_WIDTH-3:0], 2'b00};
PR <= {{(div.DATA_WIDTH){1'b0}}, div.dividend[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
div.quotient <= {div.dividend[div.DATA_WIDTH-3:0], 2'b00};
end
B_1 <= {2'b0, B}; //1xB
B_2 <= {1'b0, B, 1'b0}; //2xB
B_3 <= {1'b0, B, 1'b0} + B; //3xB
B_1 <= {2'b0, div.divisor}; //1xB
B_2 <= {1'b0, div.divisor, 1'b0}; //2xB
B_3 <= {1'b0, div.divisor, 1'b0} + {2'b0, div.divisor}; //3xB
end
else if (~terminate) begin
casex (new_PR_sign)
case (new_PR_sign)
3'b111 : begin
PR <= {PR[C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-2]};
Q <= {Q[C_WIDTH-3:0], 2'b00};
PR <= {PR[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
div.quotient <= {div.quotient[div.DATA_WIDTH-3:0], 2'b00};
end
3'b110 : begin
PR <= {new_PR_1[C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-2]};
Q <= {Q[C_WIDTH-3:0], 2'b01};
PR <= {new_PR_1[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
div.quotient <= {div.quotient[div.DATA_WIDTH-3:0], 2'b01};
end
3'b100 : begin
PR <= {new_PR_2[C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-2]};
Q <= {Q[C_WIDTH-3:0], 2'b10};
PR <= {new_PR_2[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
div.quotient <= {div.quotient[div.DATA_WIDTH-3:0], 2'b10};
end
3'b000 : begin
PR <= {new_PR_3[C_WIDTH-1:0], Q[C_WIDTH-1:C_WIDTH-2]};
Q <= {Q[C_WIDTH-3:0], 2'b11};
end
default begin
PR <= 'x;
Q <= 'x;
default: begin //3'b000 : begin
PR <= {new_PR_3[div.DATA_WIDTH-1:0], div.quotient[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
div.quotient <= {div.quotient[div.DATA_WIDTH-3:0], 2'b11};
end
endcase
end
end
assign R = PR[C_WIDTH+1:2];
assign div.remainder = PR[div.DATA_WIDTH+1:2];
always_ff @ (posedge clk) begin
if (start)
B_is_zero <= ~B[0];
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
B_is_zero <= B_is_zero & ~(|new_PR_sign);
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (start)
if (div.start)
if (terminate_early) begin
terminate <= 1;
end else begin
@ -131,12 +118,12 @@ module div_radix4_ET
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
div.done <= 0;
else begin
if (ack)
complete <= 0;
else if ((~start & (shift_count[15])) | (start & terminate_early))
complete <= 1;
if (div.done)
div.done <= 0;
else if ((~div.start & (shift_count[15])) | (div.start & terminate_early))
div.done <= 1;
end
end

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,44 +18,35 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix4_ET_full
#(
parameter C_WIDTH = 32
)(
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
);
unsigned_division_interface.divider div
);
logic terminate;
logic [C_WIDTH/2-1:0] shift_count;
logic [div.DATA_WIDTH/2-1:0] shift_count;
logic [C_WIDTH+1:0] PR;
logic [div.DATA_WIDTH+1:0] PR;
logic [2:0] new_PR_sign;
logic [C_WIDTH+2:0] new_PR_1;
logic [C_WIDTH+2:0] new_PR_2;
logic [C_WIDTH+2:0] new_PR_3;
logic [C_WIDTH+1:0] B_1;
logic [C_WIDTH+1:0] B_2;
logic [C_WIDTH+1:0] B_3;
logic [div.DATA_WIDTH+2:0] new_PR_1;
logic [div.DATA_WIDTH+2:0] new_PR_2;
logic [div.DATA_WIDTH+2:0] new_PR_3;
logic [div.DATA_WIDTH+1:0] B_1;
logic [div.DATA_WIDTH+1:0] B_2;
logic [div.DATA_WIDTH+1:0] B_3;
logic [C_WIDTH-1:0] B_r;
logic [C_WIDTH-1:0] AR_r;
logic [C_WIDTH-1:0] Q_temp;
logic [div.DATA_WIDTH-1:0] B_r;
logic [div.DATA_WIDTH-1:0] AR_r;
logic [div.DATA_WIDTH-1:0] Q_temp;
logic [5:0] shift_num_R;
logic [5:0] shift_num_Q;
logic [C_WIDTH*2:0] combined;
logic [div.DATA_WIDTH*2:0] combined;
logic terminate_early;
//implementation
@ -63,18 +54,18 @@ module div_radix4_ET_full
assign new_PR_1 = {1'b0, PR} - {1'b0, B_1};
assign new_PR_2 = {1'b0, PR} - {1'b0, B_2};
assign new_PR_3 = {1'b0, PR} - {1'b0, B_3};
assign new_PR_sign = {new_PR_3[C_WIDTH+2], new_PR_2[C_WIDTH+2], new_PR_1[C_WIDTH+2]};
assign new_PR_sign = {new_PR_3[div.DATA_WIDTH+2], new_PR_2[div.DATA_WIDTH+2], new_PR_1[div.DATA_WIDTH+2]};
//Shift reg for
always_ff @ (posedge clk) begin
if (start)
shift_count <= 32'd1;
if (div.start)
shift_count <= 1;
else
shift_count <= {shift_count[14:0], start};
shift_count <= {shift_count[14:0], div.start};
end
always_ff @ (posedge clk) begin
if (start) begin
if (div.start) begin
shift_num_R <= 2;
shift_num_Q <= 32;
end
@ -84,59 +75,55 @@ module div_radix4_ET_full
end
end
assign combined = {PR, AR_r} >> shift_num_R;
assign R = combined[C_WIDTH-1:0];
assign terminate_early = B_r > R;
assign Q = terminate_early ? (Q_temp << shift_num_Q) : Q_temp;
assign combined = {PR[div.DATA_WIDTH:0], AR_r} >> shift_num_R;
assign div.remainder = combined[div.DATA_WIDTH-1:0];
assign terminate_early = B_r > div.remainder;
assign div.quotient = terminate_early ? (Q_temp << shift_num_Q) : Q_temp;
always_ff @ (posedge clk) begin
if (start) begin
PR <= {{(C_WIDTH-1){1'b0}}, A[C_WIDTH-1:C_WIDTH-2]};
if (div.start) begin
PR <= {{(div.DATA_WIDTH){1'b0}}, div.dividend[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= '0;
AR_r <= {A[C_WIDTH-3:0], 2'b00};
B_r <= B;
B_1 <= {2'b0, B}; //1xB
B_2 <= {1'b0, B, 1'b0}; //2xB
B_3 <= {1'b0, B, 1'b0} + B; //3xB
AR_r <= {div.dividend[div.DATA_WIDTH-3:0], 2'b00};
B_r <= div.divisor;
B_1 <= {2'b0, div.divisor}; //1xB
B_2 <= {1'b0, div.divisor, 1'b0}; //2xB
B_3 <= {1'b0, div.divisor, 1'b0} + {2'b0, div.divisor}; //3xB
end else if (~terminate & ~terminate_early) begin
AR_r <= {AR_r[C_WIDTH-3:0], 2'b00};
casex (new_PR_sign)
AR_r <= {AR_r[div.DATA_WIDTH-3:0], 2'b00};
case (new_PR_sign)
3'b111 : begin
PR <= {PR[C_WIDTH-1:0], AR_r[C_WIDTH-1:C_WIDTH-2]};
Q_temp <= {Q[C_WIDTH-3:0], 2'b00};
PR <= {PR[div.DATA_WIDTH-1:0], AR_r[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= {div.quotient[div.DATA_WIDTH-3:0], 2'b00};
end
3'b110 : begin
PR <= {new_PR_1[C_WIDTH-1:0], AR_r[C_WIDTH-1:C_WIDTH-2]};
Q_temp <= {Q[C_WIDTH-3:0], 2'b01};
PR <= {new_PR_1[div.DATA_WIDTH-1:0], AR_r[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= {div.quotient[div.DATA_WIDTH-3:0], 2'b01};
end
3'b100 : begin
PR <= {new_PR_2[C_WIDTH-1:0], AR_r[C_WIDTH-1:C_WIDTH-2]};
Q_temp <= {Q[C_WIDTH-3:0], 2'b10};
PR <= {new_PR_2[div.DATA_WIDTH-1:0], AR_r[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= {div.quotient[div.DATA_WIDTH-3:0], 2'b10};
end
3'b000 : begin
PR <= {new_PR_3[C_WIDTH-1:0], AR_r[C_WIDTH-1:C_WIDTH-2]};
Q_temp <= {Q[C_WIDTH-3:0], 2'b11};
default: begin //3'b000 : begin
PR <= {new_PR_3[div.DATA_WIDTH-1:0], AR_r[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= {div.quotient[div.DATA_WIDTH-3:0], 2'b11};
end
default begin
PR <= 'x;
Q_temp <= 'x;
end
endcase
end
end
always_ff @ (posedge clk) begin
if (start)
B_is_zero <= ~B[0];
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
B_is_zero <= B_is_zero & ~(|new_PR_sign);
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (start)
if (div.start)
terminate <= 0;
else if (shift_count[15] | terminate_early)
terminate <= 1;
@ -145,13 +132,13 @@ module div_radix4_ET_full
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
div.done <= 0;
else begin
if (~start & (shift_count[15] | terminate_early) & ~complete & ~terminate)
complete <= 1;
else if (ack)
complete <= 0;
if (~div.start & (shift_count[15] | terminate_early) & ~div.done & ~terminate)
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end
endmodule
endmodule

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,56 +18,48 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix8
#(
parameter C_WIDTH = 32
)(
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
);
unsigned_division_interface.divider div
);
logic terminate;
logic [10:0] shift_count;
logic [C_WIDTH+2:0] PR;
logic [C_WIDTH:0] Q_33;
logic [div.DATA_WIDTH+2:0] PR;
logic [div.DATA_WIDTH:0] Q_33;
logic [6:0] new_PR_sign;
logic [C_WIDTH+3:0] new_PR_1;
logic [C_WIDTH+3:0] new_PR_2;
logic [C_WIDTH+3:0] new_PR_3;
logic [C_WIDTH+3:0] new_PR_4;
logic [C_WIDTH+3:0] new_PR_5;
logic [C_WIDTH+3:0] new_PR_6;
logic [C_WIDTH+3:0] new_PR_7;
logic [C_WIDTH+2:0] B_1;
logic [C_WIDTH+2:0] B_2;
logic [C_WIDTH+2:0] B_3;
logic [C_WIDTH+2:0] B_4;
logic [C_WIDTH+2:0] B_5;
logic [C_WIDTH+2:0] B_6;
logic [C_WIDTH+2:0] B_7;
logic [div.DATA_WIDTH+3:0] new_PR_1;
logic [div.DATA_WIDTH+3:0] new_PR_2;
logic [div.DATA_WIDTH+3:0] new_PR_3;
logic [div.DATA_WIDTH+3:0] new_PR_4;
logic [div.DATA_WIDTH+3:0] new_PR_5;
logic [div.DATA_WIDTH+3:0] new_PR_6;
logic [div.DATA_WIDTH+3:0] new_PR_7;
logic [div.DATA_WIDTH+2:0] B_1;
logic [div.DATA_WIDTH+2:0] B_2;
logic [div.DATA_WIDTH+2:0] B_3;
logic [div.DATA_WIDTH+2:0] B_4;
logic [div.DATA_WIDTH+2:0] B_5;
logic [div.DATA_WIDTH+2:0] B_6;
logic [div.DATA_WIDTH+2:0] B_7;
//implementation
////////////////////////////////////////////////////
// assign new_PR_1 = {1'b0, PR} - B;
// assign new_PR_2 = {1'b0, PR} - {B, 1'b0};
// assign new_PR_3 = {1'b0, PR} - {B, 1'b0} - B;
// assign new_PR_4 = {1'b0, PR} - {B, 2'b0};
// assign new_PR_5 = {1'b0, PR} - {B, 2'b0} - B;
// assign new_PR_6 = {1'b0, PR} - {B, 2'b0} - {B, 1'b0};
// assign new_PR_7 = {1'b0, PR} - {B, 2'b0} - {B, 1'b0} - B;
// assign new_PR_1 = {1'b0, PR} - div.divisor;
// assign new_PR_2 = {1'b0, PR} - {div.divisor, 1'b0};
// assign new_PR_3 = {1'b0, PR} - {div.divisor, 1'b0} - div.divisor;
// assign new_PR_4 = {1'b0, PR} - {div.divisor, 2'b0};
// assign new_PR_5 = {1'b0, PR} - {div.divisor, 2'b0} - div.divisor;
// assign new_PR_6 = {1'b0, PR} - {div.divisor, 2'b0} - {div.divisor, 1'b0};
// assign new_PR_7 = {1'b0, PR} - {div.divisor, 2'b0} - {div.divisor, 1'b0} - div.divisor;
assign new_PR_1 = {1'b0, PR} - B_1;
assign new_PR_2 = {1'b0, PR} - B_2;
assign new_PR_3 = {1'b0, PR} - B_3;
@ -75,85 +67,81 @@ module div_radix8
assign new_PR_5 = {1'b0, PR} - B_5;
assign new_PR_6 = {1'b0, PR} - B_6;
assign new_PR_7 = {1'b0, PR} - B_7;
assign new_PR_sign = {new_PR_7[C_WIDTH+3], new_PR_6[C_WIDTH+3], new_PR_5[C_WIDTH+3],
new_PR_4[C_WIDTH+3], new_PR_3[C_WIDTH+3], new_PR_2[C_WIDTH+3],
new_PR_1[C_WIDTH+3]};
assign new_PR_sign = {new_PR_7[div.DATA_WIDTH+3], new_PR_6[div.DATA_WIDTH+3], new_PR_5[div.DATA_WIDTH+3],
new_PR_4[div.DATA_WIDTH+3], new_PR_3[div.DATA_WIDTH+3], new_PR_2[div.DATA_WIDTH+3],
new_PR_1[div.DATA_WIDTH+3]};
//Shift reg for
always_ff @ (posedge clk) begin
shift_count <= {shift_count[9:0], start};
shift_count <= {shift_count[9:0], div.start};
end
always_ff @ (posedge clk) begin
if (start) begin
PR <= {{(C_WIDTH){1'b0}}, 1'b0, A[C_WIDTH-1:C_WIDTH-2]};
Q_33 <= {A[C_WIDTH-3:0], 3'b000};
if (div.start) begin
PR <= {{(div.DATA_WIDTH){1'b0}}, 1'b0, div.dividend[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_33 <= {div.dividend[div.DATA_WIDTH-3:0], 3'b000};
B_1 <= {3'b000, B};
B_2 <= {2'b00, B, 1'b0};
B_3 <= {2'b00, B, 1'b0} + B;
B_4 <= {1'b0, B, 2'b00};
B_5 <= {1'b0, B, 2'b00} + B;
B_6 <= {1'b0, B, 2'b00} + {2'b00, B, 1'b0};
B_7 <= {1'b0, B, 2'b00} + {2'b00, B, 1'b0} + B;
B_1 <= {3'b000, div.divisor};
B_2 <= {2'b00, div.divisor, 1'b0};
B_3 <= {2'b00, div.divisor, 1'b0} + {3'b0, div.divisor};
B_4 <= {1'b0, div.divisor, 2'b00};
B_5 <= {1'b0, div.divisor, 2'b00} + {3'b0, div.divisor};
B_6 <= {1'b0, div.divisor, 2'b00} + {2'b00, div.divisor, 1'b0};
B_7 <= {1'b0, div.divisor, 2'b00} + {2'b00, div.divisor, 1'b0} + {3'b0, div.divisor};
end
else if (~terminate) begin
casex (new_PR_sign)
case (new_PR_sign)
7'b1111111 : begin
PR <= {PR[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b000};
PR <= {PR[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b000};
end
7'b1111110 : begin
PR <= {new_PR_1[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b001};
PR <= {new_PR_1[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b001};
end
7'b1111100 : begin
PR <= {new_PR_2[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b010};
PR <= {new_PR_2[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b010};
end
7'b1111000 : begin
PR <= {new_PR_3[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b011};
PR <= {new_PR_3[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b011};
end
7'b1110000 : begin
PR <= {new_PR_4[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b100};
PR <= {new_PR_4[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b100};
end
7'b1100000 : begin
PR <= {new_PR_5[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b101};
PR <= {new_PR_5[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b101};
end
7'b1000000 : begin
PR <= {new_PR_6[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b110};
PR <= {new_PR_6[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b110};
end
7'b0000000 : begin
PR <= {new_PR_7[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b111};
end
default begin
PR <= 'x;
Q_33 <= 'x;
default: begin //7'b0000000 : begin
PR <= {new_PR_7[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b111};
end
endcase
end
end
assign R = PR[C_WIDTH+2:3];
assign Q = Q_33[C_WIDTH-1:0];
assign div.remainder = PR[div.DATA_WIDTH+2:3];
assign div.quotient = Q_33[div.DATA_WIDTH-1:0];
always_ff @ (posedge clk) begin
if (start)
B_is_zero <= ~B[0];
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
B_is_zero <= B_is_zero & ~(|new_PR_sign);
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (start)
if (div.start)
terminate <= 0;
if (shift_count[10])
terminate <= 1;
@ -162,13 +150,13 @@ module div_radix8
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
div.done <= 0;
else begin
if (shift_count[10])
complete <= 1;
else if (ack)
complete <= 0;
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end
endmodule
endmodule

View file

@ -1,5 +1,5 @@
/*
* Copyright © 2017 Eric Matthews, Lesley Shannon
* Copyright © 2017-2019 Eric Matthews, Lesley Shannon
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -18,128 +18,116 @@
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix8_ET
#(
parameter C_WIDTH = 32
)(
(
input logic clk,
input logic rst,
input logic start,
input logic ack,
input logic [C_WIDTH-1:0] A,
input logic [C_WIDTH-1:0] B,
output logic [C_WIDTH-1:0] Q,
output logic [C_WIDTH-1:0] R,
output logic complete,
output logic B_is_zero
);
unsigned_division_interface.divider div
);
logic terminate;
logic terminate_early;
logic [10:0] shift_count;
logic [C_WIDTH+2:0] PR;
logic [C_WIDTH:0] Q_33;
logic [div.DATA_WIDTH+2:0] PR;
logic [div.DATA_WIDTH:0] Q_33;
logic [6:0] new_PR_sign;
logic [C_WIDTH+3:0] new_PR_1;
logic [C_WIDTH+3:0] new_PR_2;
logic [C_WIDTH+3:0] new_PR_3;
logic [C_WIDTH+3:0] new_PR_4;
logic [C_WIDTH+3:0] new_PR_5;
logic [C_WIDTH+3:0] new_PR_6;
logic [C_WIDTH+3:0] new_PR_7;
logic [div.DATA_WIDTH+3:0] new_PR_1;
logic [div.DATA_WIDTH+3:0] new_PR_2;
logic [div.DATA_WIDTH+3:0] new_PR_3;
logic [div.DATA_WIDTH+3:0] new_PR_4;
logic [div.DATA_WIDTH+3:0] new_PR_5;
logic [div.DATA_WIDTH+3:0] new_PR_6;
logic [div.DATA_WIDTH+3:0] new_PR_7;
//implementation
////////////////////////////////////////////////////
assign new_PR_1 = {1'b0, PR} - B;
assign new_PR_2 = {1'b0, PR} - {B, 1'b0};
assign new_PR_3 = {1'b0, PR} - {B, 1'b0} - B;
assign new_PR_4 = {1'b0, PR} - {B, 2'b0};
assign new_PR_5 = {1'b0, PR} - {B, 2'b0} - B;
assign new_PR_6 = {1'b0, PR} - {B, 2'b0} - {B, 1'b0};
assign new_PR_7 = {1'b0, PR} - {B, 2'b0} - {B, 1'b0} - B;
assign new_PR_sign = {new_PR_7[C_WIDTH+3], new_PR_6[C_WIDTH+3], new_PR_5[C_WIDTH+3],
new_PR_4[C_WIDTH+3], new_PR_3[C_WIDTH+3], new_PR_2[C_WIDTH+3],
new_PR_1[C_WIDTH+3]};
assign new_PR_1 = {1'b0, PR} - {4'b0, div.divisor};
assign new_PR_2 = {1'b0, PR} - {3'b0, div.divisor, 1'b0};
assign new_PR_3 = {1'b0, PR} - {3'b0, div.divisor, 1'b0} - {4'b0, div.divisor};
assign new_PR_4 = {1'b0, PR} - {2'b0, div.divisor, 2'b0};
assign new_PR_5 = {1'b0, PR} - {2'b0, div.divisor, 2'b0} - {4'b0, div.divisor};
assign new_PR_6 = {1'b0, PR} - {2'b0, div.divisor, 2'b0} - {3'b0, div.divisor, 1'b0};
assign new_PR_7 = {1'b0, PR} - {2'b0, div.divisor, 2'b0} - {3'b0, div.divisor, 1'b0} - {4'b0, div.divisor};
assign new_PR_sign = {new_PR_7[div.DATA_WIDTH+3], new_PR_6[div.DATA_WIDTH+3], new_PR_5[div.DATA_WIDTH+3],
new_PR_4[div.DATA_WIDTH+3], new_PR_3[div.DATA_WIDTH+3], new_PR_2[div.DATA_WIDTH+3],
new_PR_1[div.DATA_WIDTH+3]};
//Shift reg for
always_ff @ (posedge clk) begin
shift_count <= {shift_count[9:0], start & ~terminate_early};
shift_count <= {shift_count[9:0], div.start & ~terminate_early};
end
assign terminate_early = B > A;
assign terminate_early = div.divisor > div.dividend;
always_ff @ (posedge clk) begin
if (start) begin
if (div.start) begin
if (terminate_early) begin
PR <= {A, 3'b000};
PR <= {div.dividend, 3'b000};
Q_33 <= '0;
end else begin
PR <= {{(C_WIDTH){1'b0}}, 1'b0, A[C_WIDTH-1:C_WIDTH-2]};
Q_33 <= {A[C_WIDTH-3:0], 3'b000};
PR <= {{(div.DATA_WIDTH){1'b0}}, 1'b0, div.dividend[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_33 <= {div.dividend[div.DATA_WIDTH-3:0], 3'b000};
end
end
else if (~terminate) begin
casex (new_PR_sign)
case (new_PR_sign)
7'b1111111 : begin
PR <= {PR[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b000};
PR <= {PR[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b000};
end
7'b1111110 : begin
PR <= {new_PR_1[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b001};
PR <= {new_PR_1[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b001};
end
7'b1111100 : begin
PR <= {new_PR_2[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b010};
PR <= {new_PR_2[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b010};
end
7'b1111000 : begin
PR <= {new_PR_3[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b011};
PR <= {new_PR_3[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b011};
end
7'b1110000 : begin
PR <= {new_PR_4[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b100};
PR <= {new_PR_4[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b100};
end
7'b1100000 : begin
PR <= {new_PR_5[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b101};
PR <= {new_PR_5[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b101};
end
7'b1000000 : begin
PR <= {new_PR_6[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b110};
PR <= {new_PR_6[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b110};
end
7'b0000000 : begin
PR <= {new_PR_7[C_WIDTH-1:0], Q_33[C_WIDTH:C_WIDTH-2]};
Q_33 <= {Q_33[C_WIDTH-3:0], 3'b111};
end
default begin
PR <= 'x;
Q_33 <= 'x;
default: begin //7'b0000000 : begin
PR <= {new_PR_7[div.DATA_WIDTH-1:0], Q_33[div.DATA_WIDTH:div.DATA_WIDTH-2]};
Q_33 <= {Q_33[div.DATA_WIDTH-3:0], 3'b111};
end
endcase
end
end
assign R = PR[C_WIDTH+2:3];
assign Q = Q_33[C_WIDTH-1:0];
assign div.remainder = PR[div.DATA_WIDTH+2:3];
assign div.quotient = Q_33[div.DATA_WIDTH-1:0];
always_ff @ (posedge clk) begin
if (start)
B_is_zero <= ~B[0];
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
B_is_zero <= B_is_zero & ~(|new_PR_sign);
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (start)
if (div.start)
if (terminate_early) begin
terminate <= 1;
end else begin
@ -152,13 +140,13 @@ module div_radix8_ET
always_ff @ (posedge clk) begin
if (rst)
complete <= 0;
div.done <= 0;
else begin
if (ack)
complete <= 0;
else if ((~start & (shift_count[10])) | (start & terminate_early))
complete <= 1;
if (div.done)
div.done <= 0;
else if ((~div.start & (shift_count[10])) | (div.start & terminate_early))
div.done <= 1;
end
end
endmodule
endmodule

View file

@ -58,15 +58,10 @@ module div_unit
div_fifo_inputs_t fifo_inputs;
div_fifo_inputs_t div_op;
logic start_algorithm;
unsigned_division_interface #(.DATA_WIDTH(32)) div_core();
logic in_progress;
logic computation_complete;
logic div_done;
logic [31:0] unsigned_quotient;
logic [31:0] unsigned_remainder;
logic divisor_zero;
logic negate_result;
fifo_interface #(.DATA_WIDTH($bits(div_fifo_inputs_t))) input_fifo();
@ -114,27 +109,29 @@ module div_unit
////////////////////////////////////////////////////
//Control Signals
assign start_algorithm = input_fifo.valid & (~in_progress) & ~div_op.reuse_result;
assign div_done = computation_complete | (input_fifo.valid & div_op.reuse_result);
assign div_core.start = input_fifo.valid & (~in_progress) & ~div_op.reuse_result;
assign div_done = div_core.done | (input_fifo.valid & div_op.reuse_result);
//If more than one cycle, set in_progress so that multiple start_algorithm signals are not sent to the div unit.
//If more than one cycle, set in_progress so that multiple div.start signals are not sent to the div unit.
always_ff @(posedge clk) begin
if (rst)
in_progress <= 0;
else if (start_algorithm)
else if (div_core.start)
in_progress <= 1;
else if (computation_complete)
else if (div_core.done)
in_progress <= 0;
end
////////////////////////////////////////////////////
//Div core
div_algorithm #(XLEN) div (.*, .start(start_algorithm), .A(div_op.unsigned_dividend), .B(div_op.unsigned_divisor), .Q(unsigned_quotient), .R(unsigned_remainder), .complete(computation_complete), .ack(computation_complete), .B_is_zero(divisor_zero));
assign div_core.dividend = div_op.unsigned_dividend;
assign div_core.divisor = div_op.unsigned_divisor;
div_algorithm divider_block (.*, .div(div_core));
////////////////////////////////////////////////////
//Output
assign negate_result = div_op.remainder_op ? div_op.negate_remainder : (~divisor_zero & div_op.negate_quotient);
assign wb.rd = negate_if (div_op.remainder_op ? unsigned_remainder : unsigned_quotient, negate_result);
assign negate_result = div_op.remainder_op ? div_op.negate_remainder : (~div_core.divisor_is_zero & div_op.negate_quotient);
assign wb.rd = negate_if (div_op.remainder_op ? div_core.remainder : div_core.quotient, negate_result);
assign wb.done = div_done;
assign wb.id = div_op.instruction_id;
////////////////////////////////////////////////////

View file

@ -239,6 +239,19 @@ interface fetch_sub_unit_interface;
endinterface
//start and done are cycle cycle pulses
interface unsigned_division_interface #(parameter DATA_WIDTH = 32);
logic start;
logic [DATA_WIDTH-1:0] dividend;
logic [DATA_WIDTH-1:0] divisor;
logic [DATA_WIDTH-1:0] remainder;
logic [DATA_WIDTH-1:0] quotient;
logic done;
logic divisor_is_zero;
modport requester (input remainder, quotient, done, divisor_is_zero, output dividend, divisor, start);
modport divider (output remainder, quotient, done, divisor_is_zero, input dividend, divisor, start);
endinterface
//request and ack are single cycle pulses
//request should be high when the instruction is issued
//data_valid is held high until an ack is received

View file

@ -128,6 +128,7 @@ module taiga (
logic tr_branch_operand_stall;
logic tr_alu_operand_stall;
logic tr_ls_operand_stall;
logic tr_div_operand_stall;
logic tr_instruction_issued_dec;
logic [31:0] tr_instruction_pc_dec;
@ -227,6 +228,7 @@ module taiga (
tr.events.branch_operand_stall <= tr_branch_operand_stall;
tr.events.alu_operand_stall <= tr_alu_operand_stall;
tr.events.ls_operand_stall <= tr_ls_operand_stall;
tr.events.div_operand_stall <= tr_div_operand_stall;
tr.events.branch_correct <= tr_branch_correct;
tr.events.branch_misspredict <= tr_branch_misspredict;
tr.events.return_misspredict <= tr_return_misspredict;

View file

@ -64,7 +64,7 @@ package taiga_config;
QUICK_CLZ_MK2,
QUICK_RADIX_4
} div_type;
parameter div_type DIV_ALGORITHM = QUICK_CLZ;
parameter div_type DIV_ALGORITHM = RADIX_2;
//Enable Atomic extension (cache operations only)
parameter USE_AMO = 0;

View file

@ -394,7 +394,6 @@ package taiga_types;
logic [XLEN-1:0] rs2;
logic [1:0] op;
logic reuse_result;
instruction_id_t instruction_id;
} div_inputs_t;
typedef struct packed{
@ -454,6 +453,7 @@ package taiga_types;
logic branch_operand_stall;
logic alu_operand_stall;
logic ls_operand_stall;
logic div_operand_stall;
//Branch Unit
logic branch_correct;

View file

@ -46,6 +46,7 @@ static const char * const eventNames[] = {
"branch_operand_stall",
"alu_operand_stall",
"ls_operand_stall",
"div_operand_stall",
"branch_correct",
"branch_misspredict",
"return_misspredict",

View file

@ -62,6 +62,7 @@
../core/div_algorithms/div_radix2_ET_full.sv
../core/div_algorithms/div_radix4.sv
../core/div_algorithms/div_radix8.sv
../core/div_algorithms/div_radix8_ET.sv
../core/div_algorithms/div_radix4_ET.sv
../core/div_algorithms/div_radix4_ET_full.sv
../core/div_algorithms/div_radix16.sv