mirror of
https://github.com/openhwgroup/cva5.git
synced 2025-04-23 21:47:15 -04:00
div algorithms pruned and div unit input buffering reduced
This commit is contained in:
parent
4919cac19c
commit
27caeb5514
17 changed files with 37 additions and 1580 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue