div algorithms pruned and div unit input buffering reduced

This commit is contained in:
Eric Matthews 2020-06-07 18:31:11 -07:00
parent 4919cac19c
commit 27caeb5514
17 changed files with 37 additions and 1580 deletions

View file

@ -34,19 +34,7 @@ module div_algorithm
generate
case(DIV_ALGORITHM)
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

@ -31,6 +31,7 @@ module div_quick_clz
logic running;
logic terminate;
logic [div.DATA_WIDTH-1:0] divisor_r;
logic [div.DATA_WIDTH-1:0] normalized_divisor;
@ -79,13 +80,16 @@ module div_quick_clz
div.done <= (running & terminate) | (div.start & divisor_is_zero_first_cycle);
end
assign terminate = div.remainder < div.divisor;
assign terminate = div.remainder < divisor_r;
////////////////////////////////////////////////////
//Divisor Pre-processing
always_ff @ (posedge clk) begin
divisor_CLZ_r <= divisor_CLZ;
normalized_divisor <= div.divisor << divisor_CLZ;
if (div.start) begin
divisor_r <= div.divisor;
divisor_CLZ_r <= divisor_CLZ;
normalized_divisor <= div.divisor << divisor_CLZ;
end
end
////////////////////////////////////////////////////

View file

@ -1,138 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_quick_clz_mk2
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic running;
logic terminate;
logic [div.DATA_WIDTH:0] A0;
logic [div.DATA_WIDTH:0] A1;
logic [div.DATA_WIDTH-1:0] A2;
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 [div.DATA_WIDTH-1:0] Q_bit1;
logic [div.DATA_WIDTH-1:0] Q_bit2;
logic [div.DATA_WIDTH-1:0] B1;
logic [div.DATA_WIDTH-1:0] B2;
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 divisor_is_zero_first_cycle;
logic [div.DATA_WIDTH-1:0] shiftedB;
//////////////////////////////////////////
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
B_CLZ_r <= B_CLZ;
shiftedB <= div.divisor << 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[div.DATA_WIDTH-1:1]};
always_comb begin
if (A1[div.DATA_WIDTH])
new_Q_bit = Q_bit2;
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 = div.remainder - B1;
assign B2 = {1'b0, B1[div.DATA_WIDTH-1:1]};
assign A2 = div.remainder - B2;
assign A0 = div.remainder - (B1 + B2);
always_comb begin
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[div.DATA_WIDTH-1:0];
end
assign divisor_is_zero_first_cycle = (B_CLZ == 5'b11111 && ~div.divisor[0]);
always @ (posedge clk) begin
if (div.start)
div.divisor_is_zero <= divisor_is_zero_first_cycle;
end
always_ff @ (posedge clk) begin
if (rst)
running <= 0;
else if (div.start & ~divisor_is_zero_first_cycle)
running <= 1;
else if (terminate)
running <= 0;
end
always_ff @ (posedge clk) begin
div.done <= (running & terminate) | (div.start & divisor_is_zero_first_cycle);
end
assign terminate = div.remainder < div.divisor;
always_ff @ (posedge clk) begin
if (div.start)
div.quotient <= '0;
else if (~terminate & running)
div.quotient <= div.quotient | new_Q_bit;
end
initial begin
div.remainder = 0;
end
always @ (posedge clk) begin
if (div.start)
div.remainder <= div.dividend;
else if (~terminate & running)
div.remainder <= new_R;
end
endmodule

View file

@ -1,110 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_quick_naive
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic running;
logic terminate;
logic [div.DATA_WIDTH:0] A1;
logic [div.DATA_WIDTH-1:0] A2;
logic [div.DATA_WIDTH-1:0] new_R;
logic [div.DATA_WIDTH-1:0] new_Q_bit;
logic [div.DATA_WIDTH-1:0] Q_bit1;
logic [div.DATA_WIDTH-1:0] Q_bit2;
logic [div.DATA_WIDTH-1:0] B1;
logic [div.DATA_WIDTH-1:0] B2;
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;
logic divisor_is_zero_first_cycle;
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[div.DATA_WIDTH-1:1]};
assign new_Q_bit = div.quotient | (A1[div.DATA_WIDTH] ? Q_bit2 : Q_bit1);
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[div.DATA_WIDTH] ? A2 : A1[div.DATA_WIDTH-1:0];
assign divisor_is_zero_first_cycle = (B_MSB == 0 && ~div.divisor[0]);
always @ (posedge clk) begin
if (div.start)
div.divisor_is_zero <= divisor_is_zero_first_cycle;
end
always_ff @ (posedge clk) begin
if (rst)
running <= 0;
else if (div.start & ~divisor_is_zero_first_cycle)
running <= 1;
else if (terminate)
running <= 0;
end
always_ff @ (posedge clk) begin
if (rst)
div.done <= 0;
else if (div.done)
div.done <= 0;
else if ((running & terminate) | (div.start & divisor_is_zero_first_cycle))
div.done <= 1;
end
assign terminate = (div.remainder < div.divisor);
always_ff @ (posedge clk) begin
B_MSB_r <= B_MSB;
if (div.start) begin
div.quotient <= 0;
div.remainder <= div.dividend;
end
else if (~terminate & running) begin
div.quotient <= new_Q_bit;
div.remainder <= new_R;
end
end
endmodule

View file

@ -1,196 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_quick_radix_4
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic terminate;
logic [div.DATA_WIDTH/2-1:0] shift_count;
logic [div.DATA_WIDTH+1:0] PR;
logic [2:0] new_PR_sign;
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 [div.DATA_WIDTH-1:0] AR_r;
logic [div.DATA_WIDTH-1:0] Q_temp;
logic [5:0] shift_num_R;
logic [6:0] shift_num_R_normalized;
logic [5:0] shift_num_Q;
logic [div.DATA_WIDTH*2+1:0] combined;
logic [div.DATA_WIDTH*2+1:0] combined_normalized;
logic terminate_early;
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;
logic [CLZ_W-1:0] B_CLZ_r;
logic [CLZ_W-1:0] CLZ_delta;
logic firstCycle;
logic greaterDivisor;
logic [div.DATA_WIDTH-1:0] A_shifted;
logic [div.DATA_WIDTH-1:0] B_shifted;
logic [div.DATA_WIDTH-1:0] R_shifted;
logic [div.DATA_WIDTH-1:0] B_shifted_r;
//implementation
////////////////////////////////////////////////////
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
if (rst) begin
firstCycle <= 0;
A_CLZ_r <= 0;
B_CLZ_r <= 0;
A_shifted <= 0;
B_shifted <= 0;
end else begin
if (div.start) begin
firstCycle <= 1;
A_CLZ_r <= A_CLZ;
B_CLZ_r <= B_CLZ;
greaterDivisor <= div.divisor > div.dividend;
A_shifted <= div.dividend << A_CLZ;
B_shifted <= div.divisor << A_CLZ;
end else begin
firstCycle <= 0;
end
end
end
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[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 (rst) begin
shift_count <= 0;
end else if (firstCycle) begin
shift_count <= 1;
end else if (terminate) begin
shift_count <= 0;
end else begin
shift_count <= {shift_count[14:0], firstCycle};
end
end
always_ff @ (posedge clk) begin
if (firstCycle) begin
shift_num_R <= 2;
shift_num_R_normalized <= 2 + {2'b0, A_CLZ_r};
shift_num_Q <= 32;
end
else if (~terminate & ~terminate_early) begin
shift_num_R <= shift_num_R + 2;
shift_num_R_normalized <= shift_num_R_normalized + 2;
shift_num_Q <= shift_num_Q - 2;
end
end
assign combined_normalized = {PR, AR_r} >> shift_num_R_normalized;
assign div.remainder = combined_normalized[div.DATA_WIDTH-1:0];
assign combined = {PR, AR_r} >> shift_num_R;
assign R_shifted = combined[div.DATA_WIDTH-1:0];
assign terminate_early = ~firstCycle & ((B_shifted_r > R_shifted) | greaterDivisor);
assign div.quotient = terminate_early ? (Q_temp << shift_num_Q) : Q_temp;
always_ff @ (posedge clk) begin
if (firstCycle) begin
PR <= {{(div.DATA_WIDTH){1'b0}}, A_shifted[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= '0;
AR_r <= {A_shifted[div.DATA_WIDTH-3:0], 2'b00};
B_shifted_r <= B_shifted;
B_1 <= {2'b0, B_shifted}; //1xB
B_2 <= {1'b0, B_shifted, 1'b0}; //2xB
B_3 <= {1'b0, B_shifted, 1'b0} + {2'b0, B_shifted}; //3xB
end else if (~terminate & ~terminate_early) begin
AR_r <= {AR_r[div.DATA_WIDTH-3:0], 2'b00};
case (new_PR_sign)
3'b111 : begin
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[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[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
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
endcase
end
end
always_ff @ (posedge clk) begin
if (div.start)
div.divisor_is_zero <= ~(|div.divisor);
else if (~terminate & ~terminate_early)
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (firstCycle)
terminate <= 0;
else if (shift_count[15] | terminate_early)
terminate <= 1;
end
end
always_ff @ (posedge clk) begin
if (rst)
div.done <= 0;
else begin
if (firstCycle)
div.done <= 0;
else if ((shift_count[15] | terminate_early) & ~div.done & ~terminate)
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end
endmodule

View file

@ -1,146 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix16
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic terminate;
logic [div.DATA_WIDTH-1:0] shift_count;
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 [div.DATA_WIDTH+4:0] new_PR_8;
logic [div.DATA_WIDTH+4:0] new_PR [6:0];
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] <= div.start;
shift_count[31:1] <= shift_count[30:0];
end
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][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[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][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][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[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][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][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 (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 <= {{(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
case (new_PR_8[div.DATA_WIDTH+4])
1'b1 : begin
PR <= PR_lower;
div.quotient <= Q_lower;
end
1'b0 : begin
PR <= PR_upper;
div.quotient <= Q_upper;
end
endcase
end
end
assign div.remainder = PR[div.DATA_WIDTH+3:4];
always_ff @ (posedge clk) begin
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (div.start)
terminate <= 0;
if (shift_count[7])
terminate <= 1;
end
end
always_ff @ (posedge clk) begin
if (rst)
div.done <= 0;
else begin
if (shift_count[7])
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end
endmodule

View file

@ -31,6 +31,7 @@ module div_radix2
logic terminate;
logic [div.DATA_WIDTH-1:0] divisor_r;
logic [div.DATA_WIDTH:0] new_PR;
logic [div.DATA_WIDTH:0] PR;
logic [div.DATA_WIDTH-1:0] shift_count;
@ -38,7 +39,7 @@ module div_radix2
//implementation
////////////////////////////////////////////////////
assign new_PR = PR - {1'b0, div.divisor};
assign new_PR = PR - {1'b0, divisor_r};
assign negative_sub_rst = new_PR[div.DATA_WIDTH];
//Shift reg for
@ -48,6 +49,7 @@ module div_radix2
always_ff @ (posedge clk) begin
if (div.start) begin
divisor_r <= div.divisor;
PR <= {(div.DATA_WIDTH)'(1'b0), div.dividend[div.DATA_WIDTH-1]};
div.quotient <= {div.dividend[div.DATA_WIDTH-2:0], 1'b0};
end

View file

@ -1,104 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix2_ET
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic terminate;
logic terminate_early;
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, div.divisor};
assign negative_sub_rst = new_PR[div.DATA_WIDTH];
always_ff @ (posedge clk) begin
shift_count <= {shift_count[30:0], div.start & ~terminate_early};
end
assign terminate_early = div.divisor > div.dividend;
always_ff @ (posedge clk) begin
if (div.start) begin
if (terminate_early) begin
PR <= {div.dividend, 1'b0};
div.quotient <= '0;
end else 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
end else if (~terminate) begin
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 div.remainder = PR[div.DATA_WIDTH:1];
always_ff @ (posedge clk) begin
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
div.divisor_is_zero <= div.divisor_is_zero & ~negative_sub_rst;
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (div.start) begin
if (terminate_early) begin
terminate <= 1;
end else begin
terminate <= 0;
end
end
if (shift_count[31])
terminate <= 1;
end
end
always_ff @ (posedge clk) begin
if (rst)
div.done <= 0;
else begin
if (div.done)
div.done <= 0;
else if ((~div.start & (shift_count[31])) | (div.start & terminate_early))
div.done <= 1;
end
end
endmodule

View file

@ -1,123 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix2_ET_full
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic terminate;
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;
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 [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, div.divisor};
assign negative_sub_rst = new_PR[div.DATA_WIDTH];
always_ff @ (posedge clk) begin
if (div.start)
shift_count <= 32'd1;
else
shift_count <= {shift_count[30:0], div.start};
end
always_ff @ (posedge clk) begin
if (div.start) begin
shift_num_R <= 1;
shift_num_Q <= 32;
end
else if (~terminate & ~terminate_early) begin
shift_num_R <= shift_num_R + 1;
shift_num_Q <= shift_num_Q - 1;
end
end
assign combined = {PR, AR_r} >> shift_num_R;
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 (div.start) begin
PR <= {(div.DATA_WIDTH)'(1'b0), div.dividend[div.DATA_WIDTH-1]};
Q_temp <= '0;
AR_r <= {div.dividend[div.DATA_WIDTH-2:0], 1'b0};
end
else if (~terminate & ~terminate_early) begin
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 (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
div.divisor_is_zero <= div.divisor_is_zero & ~negative_sub_rst;
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (div.start)
terminate <= 0;
//if (shift_count[31])
else if (shift_count[31] | terminate_early)
terminate <= 1;
end
end
always_ff @ (posedge clk) begin
if (rst)
div.done <= 0;
else begin
// if (shift_count[31])
if (~div.start & (shift_count[31] | terminate_early) & ~div.done & ~terminate)
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end
endmodule

View file

@ -1,117 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix4
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic terminate;
logic [div.DATA_WIDTH/2-1:0] shift_count;
logic [div.DATA_WIDTH+1:0] PR;
logic [2:0] new_PR_sign;
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[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], div.start};
end
always_ff @ (posedge clk) begin
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, 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
case (new_PR_sign)
3'b111 : begin
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[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[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
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 div.remainder = PR[div.DATA_WIDTH+1:2];
always_ff @ (posedge clk) begin
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (div.start)
terminate <= 0;
if (shift_count[15])
terminate <= 1;
end
end
always_ff @ (posedge clk) begin
if (rst)
div.done <= 0;
else begin
if (shift_count[15])
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end
endmodule

View file

@ -1,130 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix4_ET
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic terminate;
logic terminate_early;
logic [div.DATA_WIDTH/2-1:0] shift_count;
logic [div.DATA_WIDTH+1:0] PR;
logic [2:0] new_PR_sign;
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[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], div.start & ~terminate_early};
end
assign terminate_early = div.divisor > div.dividend;
always_ff @ (posedge clk) begin
if (div.start) begin
if (terminate_early) begin
PR <= {div.dividend, 2'b00};
div.quotient <= '0;
end
else 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};
end
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
case (new_PR_sign)
3'b111 : begin
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[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[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
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 div.remainder = PR[div.DATA_WIDTH+1:2];
always_ff @ (posedge clk) begin
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (div.start)
if (terminate_early) begin
terminate <= 1;
end else begin
terminate <= 0;
end
if (shift_count[15])
terminate <= 1;
end
end
always_ff @ (posedge clk) begin
if (rst)
div.done <= 0;
else begin
if (div.done)
div.done <= 0;
else if ((~div.start & (shift_count[15])) | (div.start & terminate_early))
div.done <= 1;
end
end
endmodule

View file

@ -1,144 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix4_ET_full
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic terminate;
logic [div.DATA_WIDTH/2-1:0] shift_count;
logic [div.DATA_WIDTH+1:0] PR;
logic [2:0] new_PR_sign;
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 [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 [div.DATA_WIDTH*2:0] combined;
logic terminate_early;
//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[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 (div.start)
shift_count <= 1;
else
shift_count <= {shift_count[14:0], div.start};
end
always_ff @ (posedge clk) begin
if (div.start) begin
shift_num_R <= 2;
shift_num_Q <= 32;
end
else if (~terminate & ~terminate_early) begin
shift_num_R <= shift_num_R + 2;
shift_num_Q <= shift_num_Q - 2;
end
end
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 (div.start) begin
PR <= {{(div.DATA_WIDTH){1'b0}}, div.dividend[div.DATA_WIDTH-1:div.DATA_WIDTH-2]};
Q_temp <= '0;
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[div.DATA_WIDTH-3:0], 2'b00};
case (new_PR_sign)
3'b111 : begin
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[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[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
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
endcase
end
end
always_ff @ (posedge clk) begin
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (div.start)
terminate <= 0;
else if (shift_count[15] | terminate_early)
terminate <= 1;
end
end
always_ff @ (posedge clk) begin
if (rst)
div.done <= 0;
else begin
if (~div.start & (shift_count[15] | terminate_early) & ~div.done & ~terminate)
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end
endmodule

View file

@ -1,162 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix8
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic terminate;
logic [10:0] shift_count;
logic [div.DATA_WIDTH+2:0] PR;
logic [div.DATA_WIDTH:0] Q_33;
logic [6:0] new_PR_sign;
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} - 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;
assign new_PR_4 = {1'b0, PR} - B_4;
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[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], div.start};
end
always_ff @ (posedge clk) begin
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, 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
case (new_PR_sign)
7'b1111111 : begin
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[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[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[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[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[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[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
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 div.remainder = PR[div.DATA_WIDTH+2:3];
assign div.quotient = Q_33[div.DATA_WIDTH-1:0];
always_ff @ (posedge clk) begin
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (div.start)
terminate <= 0;
if (shift_count[10])
terminate <= 1;
end
end
always_ff @ (posedge clk) begin
if (rst)
div.done <= 0;
else begin
if (shift_count[10])
div.done <= 1;
else if (div.done)
div.done <= 0;
end
end
endmodule

View file

@ -1,152 +0,0 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial code developed under the supervision of Dr. Lesley Shannon,
* Reconfigurable Computing Lab, Simon Fraser University.
*
* Author(s):
* Eric Matthews <ematthew@sfu.ca>
* Alec Lu <alec_lu@sfu.ca>
*/
module div_radix8_ET
(
input logic clk,
input logic rst,
unsigned_division_interface.divider div
);
logic terminate;
logic terminate_early;
logic [10:0] shift_count;
logic [div.DATA_WIDTH+2:0] PR;
logic [div.DATA_WIDTH:0] Q_33;
logic [6:0] new_PR_sign;
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} - {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], div.start & ~terminate_early};
end
assign terminate_early = div.divisor > div.dividend;
always_ff @ (posedge clk) begin
if (div.start) begin
if (terminate_early) begin
PR <= {div.dividend, 3'b000};
Q_33 <= '0;
end else 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};
end
end
else if (~terminate) begin
case (new_PR_sign)
7'b1111111 : begin
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[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[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[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[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[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[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
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 div.remainder = PR[div.DATA_WIDTH+2:3];
assign div.quotient = Q_33[div.DATA_WIDTH-1:0];
always_ff @ (posedge clk) begin
if (div.start)
div.divisor_is_zero <= ~div.divisor[0];
else if (~terminate)
div.divisor_is_zero <= div.divisor_is_zero & ~(|new_PR_sign);
end
always_ff @ (posedge clk) begin
if (rst)
terminate <= 0;
else begin
if (div.start)
if (terminate_early) begin
terminate <= 1;
end else begin
terminate <= 0;
end
if (shift_count[10])
terminate <= 1;
end
end
always_ff @ (posedge clk) begin
if (rst)
div.done <= 0;
else begin
if (div.done)
div.done <= 0;
else if ((~div.start & (shift_count[10])) | (div.start & terminate_early))
div.done <= 1;
end
end
endmodule

View file

@ -47,17 +47,22 @@ module div_unit
logic remainder_op;
typedef struct packed{
logic [XLEN-1:0] unsigned_dividend;
logic [XLEN-1:0] unsigned_divisor;
logic remainder_op;
logic negate_quotient;
logic negate_remainder;
logic reuse_result;
id_t id;
} div_attributes_t;
typedef struct packed{
logic [XLEN-1:0] unsigned_dividend;
logic [XLEN-1:0] unsigned_divisor;
div_attributes_t attr;
} div_fifo_inputs_t;
div_fifo_inputs_t fifo_inputs;
div_fifo_inputs_t div_op;
div_attributes_t in_progress_attr;
unsigned_division_interface #(.DATA_WIDTH(32)) div_core();
@ -90,36 +95,40 @@ module div_unit
assign fifo_inputs.unsigned_dividend = unsigned_dividend;
assign fifo_inputs.unsigned_divisor = unsigned_divisor;
assign fifo_inputs.remainder_op = div_inputs.op[1];
assign fifo_inputs.negate_quotient = negate_quotient;
assign fifo_inputs.negate_remainder = negate_remainder;
assign fifo_inputs.reuse_result = div_inputs.reuse_result;
assign fifo_inputs.id = issue.id;
assign fifo_inputs.attr.remainder_op = div_inputs.op[1];
assign fifo_inputs.attr.negate_quotient = negate_quotient;
assign fifo_inputs.attr.negate_remainder = negate_remainder;
assign fifo_inputs.attr.reuse_result = div_inputs.reuse_result;
assign fifo_inputs.attr.id = issue.id;
////////////////////////////////////////////////////
//Input FIFO
taiga_fifo #(.DATA_WIDTH($bits(div_fifo_inputs_t)), .FIFO_DEPTH(MAX_IDS))
taiga_fifo #(.DATA_WIDTH($bits(div_fifo_inputs_t)), .FIFO_DEPTH(1))
div_input_fifo (.fifo(input_fifo), .*);
assign input_fifo.data_in = fifo_inputs;
assign input_fifo.push = issue.new_request;
assign input_fifo.potential_push = issue.possible_issue;
assign issue.ready = 1; //As FIFO depth is the same as MAX_INFLIGHT_COUNT
assign input_fifo.pop = wb.done & wb.ack;
assign issue.ready = ~input_fifo.full | input_fifo.pop; //As FIFO depth is the same as MAX_INFLIGHT_COUNT
assign input_fifo.pop = input_fifo.valid & (~in_progress);//wb.done & wb.ack;
assign div_op = input_fifo.data_out;
////////////////////////////////////////////////////
//Control Signals
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);
assign div_core.start = input_fifo.valid & (~in_progress) & ~div_op.attr.reuse_result;
assign div_done = div_core.done | (in_progress & in_progress_attr.reuse_result);
//If more than one cycle, set in_progress so that multiple div.start signals are not sent to the div unit.
set_clr_reg_with_rst #(.SET_OVER_CLR(1), .WIDTH(1), .RST_VALUE('0)) in_progress_m (
.clk, .rst,
.set(div_core.start),
.set(input_fifo.valid & (~in_progress)),
.clr(wb.ack),
.result(in_progress)
);
always_ff @ (posedge clk) begin
if (input_fifo.pop)
in_progress_attr <= div_op.attr;
end
////////////////////////////////////////////////////
//Div core
@ -130,8 +139,8 @@ module div_unit
////////////////////////////////////////////////////
//Output
logic done_r;
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 : ({32{div_core.divisor_is_zero}} | div_core.quotient), negate_result);
assign negate_result = in_progress_attr.remainder_op ? in_progress_attr.negate_remainder : (~div_core.divisor_is_zero & in_progress_attr.negate_quotient);
assign wb.rd = negate_if (in_progress_attr.remainder_op ? div_core.remainder : ({32{div_core.divisor_is_zero}} | div_core.quotient), negate_result);
always_ff @ (posedge clk) begin
if (wb.ack)
@ -140,7 +149,7 @@ module div_unit
done_r <= 1;
end
assign wb.done = div_done | done_r;
assign wb.id = div_op.id;
assign wb.id = in_progress_attr.id;
////////////////////////////////////////////////////
//Assertions

View file

@ -51,19 +51,8 @@ package taiga_config;
//Division algorithm selection
typedef enum {
RADIX_2,
RADIX_2_EARLY_TERMINATE,
RADIX_2_EARLY_TERMINATE_FULL,
RADIX_4,
RADIX_4_EARLY_TERMINATE,
RADIX_4_EARLY_TERMINATE_FULL,
RADIX_8,
RADIX_8_EARLY_TERMINATE,
RADIX_16,
QUICK_NAIVE,
QUICK_CLZ,
QUICK_CLZ_MK2,
QUICK_RADIX_4
RADIX_2,//Smallest
QUICK_CLZ//Highest performance and best performance per LUT
} div_type;
parameter div_type DIV_ALGORITHM = QUICK_CLZ;

View file

@ -62,21 +62,8 @@
../core/div_algorithms/div_radix2.sv
../core/div_algorithms/div_radix2_ET.sv
../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
../core/msb.sv
../core/msb_naive.sv
../core/clz.sv
../core/div_algorithms/div_quick_clz_mk2.sv
../core/div_algorithms/div_quick_clz.sv
../core/div_algorithms/div_quick_radix4.sv
../core/div_algorithms/div_quick_naive.sv
../core/div_algorithms/div_algorithm.sv
../core/div_unit.sv