URL
https://opencores.org/ocsvn/double_fpu/double_fpu/trunk
Subversion Repositories double_fpu
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 11 to Rev 12
- ↔ Reverse comparison
Rev 11 → Rev 12
/tags/arelease/fpu_div.v
0,0 → 1,412
///////////////////////////////////////////////////////////////////// |
//// //// |
//// FPU //// |
//// Floating Point Unit (Double precision) //// |
//// //// |
//// Author: David Lundgren //// |
//// davidklun@gmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 David Lundgren //// |
//// davidklun@gmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
|
`timescale 1ns / 100ps |
|
module fpu_div( clk, rst, enable, opa, opb, sign, mantissa_7, |
exponent_out); |
input clk; |
input rst; |
input enable; |
input [63:0] opa; |
input [63:0] opb; |
output sign; |
output [55:0] mantissa_7; |
output [11:0] exponent_out; |
|
parameter preset = 53; |
|
reg [53:0] dividend_reg; |
reg [53:0] divisor_reg; |
reg enable_reg; |
reg enable_reg_2; |
reg enable_reg_a; |
reg enable_reg_b; |
reg enable_reg_c; |
reg enable_reg_d; |
reg enable_reg_e; |
reg [5:0] dividend_shift; |
reg [5:0] dividend_shift_2; |
reg [5:0] divisor_shift; |
reg [5:0] divisor_shift_2; |
reg [5:0] count_out; |
reg [11:0] exponent_out; |
|
|
wire sign = opa[63] ^ opb[63]; |
reg [51:0] mantissa_a; |
reg [51:0] mantissa_b; |
wire [10:0] expon_a = opa[62:52]; |
wire [10:0] expon_b = opb[62:52]; |
wire a_is_norm = |expon_a; |
wire b_is_norm = |expon_b; |
wire a_is_zero = !(|opa[62:0]); |
wire [11:0] exponent_a = { 1'b0, expon_a}; |
wire [11:0] exponent_b = { 1'b0, expon_b}; |
reg [51:0] dividend_a; |
reg [51:0] dividend_a_shifted; |
wire [52:0] dividend_denorm = { dividend_a_shifted, 1'b0}; |
wire [53:0] dividend_1 = a_is_norm ? { 2'b01, dividend_a } : { 1'b0, dividend_denorm}; |
reg [51:0] divisor_b; |
reg [51:0] divisor_b_shifted; |
wire [52:0] divisor_denorm = { divisor_b_shifted, 1'b0}; |
wire [53:0] divisor_1 = b_is_norm ? { 2'b01, divisor_b } : { 1'b0, divisor_denorm}; |
wire [5:0] count_index = count_out; |
wire count_nonzero = !(count_index == 0); |
reg [53:0] quotient; |
reg [53:0] quotient_out; |
reg [53:0] remainder; |
reg [53:0] remainder_out; |
reg remainder_msb; |
reg count_nonzero_reg; |
reg count_nonzero_reg_2; |
reg [11:0] expon_term; |
reg expon_uf_1; |
reg [11:0] expon_uf_term_1; |
reg [11:0] expon_final_1; |
reg [11:0] expon_final_2; |
reg [11:0] expon_shift_a; |
reg [11:0] expon_shift_b; |
reg expon_uf_2; |
reg [11:0] expon_uf_term_2; |
reg [11:0] expon_uf_term_3; |
reg expon_uf_gt_maxshift; |
reg [11:0] expon_uf_term_4; |
reg [11:0] expon_final_3; |
reg [11:0] expon_final_4; |
wire quotient_msb = quotient_out[53]; |
reg expon_final_4_et0; |
reg expon_final_4_term; |
reg [11:0] expon_final_5; |
reg [51:0] mantissa_1; |
wire [51:0] mantissa_2 = quotient_out[52:1]; |
wire [51:0] mantissa_3 = quotient_out[51:0]; |
wire [51:0] mantissa_4 = quotient_msb ? mantissa_2 : mantissa_3; |
wire [51:0] mantissa_5 = (expon_final_4 == 1) ? mantissa_2 : mantissa_4; |
wire [51:0] mantissa_6 = expon_final_4_et0 ? mantissa_1 : mantissa_5; |
wire [107:0] remainder_a = { quotient_out[53:0] , remainder_msb, remainder_out[52:0]}; |
reg [6:0] remainder_shift_term; |
reg [107:0] remainder_b; |
wire [55:0] remainder_1 = remainder_b[107:52]; |
wire [55:0] remainder_2 = { quotient_out[0] , remainder_msb, remainder_out[52:0], 1'b0 }; |
wire [55:0] remainder_3 = { remainder_msb , remainder_out[52:0], 2'b0 }; |
wire [55:0] remainder_4 = quotient_msb ? remainder_2 : remainder_3; |
wire [55:0] remainder_5 = (expon_final_4 == 1) ? remainder_2 : remainder_4; |
wire [55:0] remainder_6 = expon_final_4_et0 ? remainder_1 : remainder_5; |
wire m_norm = |expon_final_5; |
wire rem_lsb = |remainder_6[54:0]; |
wire [55:0] mantissa_7 = { 1'b0, m_norm, mantissa_6, remainder_6[55], rem_lsb }; |
|
always @ (posedge clk) |
begin |
if (rst) |
exponent_out <= 0; |
else |
exponent_out <= a_is_zero ? 12'b0 : expon_final_5; |
end |
|
always @ (posedge clk) |
begin |
if (rst) |
count_out <= 0; |
else if (enable_reg) |
count_out <= preset; |
else if (count_nonzero) |
count_out <= count_out - 1; |
end |
|
always @ (posedge clk) |
begin |
if (rst) begin |
quotient_out <= 0; |
remainder_out <= 0; |
end |
else begin |
quotient_out <= quotient; |
remainder_out <= remainder; |
end |
end |
|
|
always @ (posedge clk) |
begin |
if (rst) |
quotient <= 0; |
else if (count_nonzero_reg) |
quotient[count_index] <= !(divisor_reg > dividend_reg); |
end |
|
always @ (posedge clk) |
begin |
if (rst) begin |
remainder <= 0; |
remainder_msb <= 0; |
end |
else if (!count_nonzero_reg & count_nonzero_reg_2) begin |
remainder <= dividend_reg; |
remainder_msb <= (divisor_reg > dividend_reg) ? 0 : 1; |
end |
end |
|
always @ (posedge clk) |
begin |
if (rst) begin |
dividend_reg <= 0; |
divisor_reg <= 0; |
end |
else if (enable_reg_e) begin |
dividend_reg <= dividend_1; |
divisor_reg <= divisor_1; |
end |
else if (count_nonzero_reg) |
dividend_reg <= (divisor_reg > dividend_reg) ? dividend_reg << 1 : |
(dividend_reg - divisor_reg) << 1; |
// divisor doesn't change for the divide |
end |
|
always @ (posedge clk) |
begin |
if (rst) begin |
expon_term <= 0; |
expon_uf_1 <= 0; |
expon_uf_term_1 <= 0; |
expon_final_1 <= 0; |
expon_final_2 <= 0; |
expon_shift_a <= 0; |
expon_shift_b <= 0; |
expon_uf_2 <= 0; |
expon_uf_term_2 <= 0; |
expon_uf_term_3 <= 0; |
expon_uf_gt_maxshift <= 0; |
expon_uf_term_4 <= 0; |
expon_final_3 <= 0; |
expon_final_4 <= 0; |
expon_final_4_et0 <= 0; |
expon_final_4_term <= 0; |
expon_final_5 <= 0; |
mantissa_a <= 0; |
mantissa_b <= 0; |
dividend_a <= 0; |
divisor_b <= 0; |
dividend_shift_2 <= 0; |
divisor_shift_2 <= 0; |
remainder_shift_term <= 0; |
remainder_b <= 0; |
dividend_a_shifted <= 0; |
divisor_b_shifted <= 0; |
mantissa_1 <= 0; |
end |
else if (enable_reg_2) begin |
expon_term <= exponent_a + 1023; |
expon_uf_1 <= exponent_b > expon_term; |
expon_uf_term_1 <= expon_uf_1 ? (exponent_b - expon_term) : 0; |
expon_final_1 <= expon_term - exponent_b; |
expon_final_2 <= expon_uf_1 ? 0 : expon_final_1; |
expon_shift_a <= a_is_norm ? 0 : dividend_shift_2; |
expon_shift_b <= b_is_norm ? 0 : divisor_shift_2; |
expon_uf_2 <= expon_shift_a > expon_final_2; |
expon_uf_term_2 <= expon_uf_2 ? (expon_shift_a - expon_final_2) : 0; |
expon_uf_term_3 <= expon_uf_term_2 + expon_uf_term_1; |
expon_uf_gt_maxshift <= (expon_uf_term_3 > 51); |
expon_uf_term_4 <= expon_uf_gt_maxshift ? 52 : expon_uf_term_3; |
expon_final_3 <= expon_uf_2 ? 0 : (expon_final_2 - expon_shift_a); |
expon_final_4 <= expon_final_3 + expon_shift_b; |
expon_final_4_et0 <= (expon_final_4 == 0); |
expon_final_4_term <= expon_final_4_et0 ? 0 : 1; |
expon_final_5 <= quotient_msb ? expon_final_4 : expon_final_4 - expon_final_4_term; |
mantissa_a <= opa[51:0]; |
mantissa_b <= opb[51:0]; |
dividend_a <= mantissa_a; |
divisor_b <= mantissa_b; |
dividend_shift_2 <= dividend_shift; |
divisor_shift_2 <= divisor_shift; |
remainder_shift_term <= 52 - expon_uf_term_4; |
remainder_b <= remainder_a << remainder_shift_term; |
dividend_a_shifted <= dividend_a << dividend_shift_2; |
divisor_b_shifted <= divisor_b << divisor_shift_2; |
mantissa_1 <= quotient_out[53:2] >> expon_uf_term_4; |
end |
end |
|
always @ (posedge clk) |
begin |
if (rst) begin |
count_nonzero_reg <= 0; |
count_nonzero_reg_2 <= 0; |
enable_reg <= 0; |
enable_reg_a <= 0; |
enable_reg_b <= 0; |
enable_reg_c <= 0; |
enable_reg_d <= 0; |
enable_reg_e <= 0; |
end |
else begin |
count_nonzero_reg <= count_nonzero; |
count_nonzero_reg_2 <= count_nonzero_reg; |
enable_reg <= enable_reg_e; |
enable_reg_a <= enable; |
enable_reg_b <= enable_reg_a; |
enable_reg_c <= enable_reg_b; |
enable_reg_d <= enable_reg_c; |
enable_reg_e <= enable_reg_d; |
end |
end |
|
always @ (posedge clk) |
begin |
if (rst) |
enable_reg_2 <= 0; |
else if (enable) |
enable_reg_2 <= 1; |
end |
|
|
always @(dividend_a) |
casex(dividend_a) |
52'b1???????????????????????????????????????????????????: dividend_shift <= 0; |
52'b01??????????????????????????????????????????????????: dividend_shift <= 1; |
52'b001?????????????????????????????????????????????????: dividend_shift <= 2; |
52'b0001????????????????????????????????????????????????: dividend_shift <= 3; |
52'b00001???????????????????????????????????????????????: dividend_shift <= 4; |
52'b000001??????????????????????????????????????????????: dividend_shift <= 5; |
52'b0000001?????????????????????????????????????????????: dividend_shift <= 6; |
52'b00000001????????????????????????????????????????????: dividend_shift <= 7; |
52'b000000001???????????????????????????????????????????: dividend_shift <= 8; |
52'b0000000001??????????????????????????????????????????: dividend_shift <= 9; |
52'b00000000001?????????????????????????????????????????: dividend_shift <= 10; |
52'b000000000001????????????????????????????????????????: dividend_shift <= 11; |
52'b0000000000001???????????????????????????????????????: dividend_shift <= 12; |
52'b00000000000001??????????????????????????????????????: dividend_shift <= 13; |
52'b000000000000001?????????????????????????????????????: dividend_shift <= 14; |
52'b0000000000000001????????????????????????????????????: dividend_shift <= 15; |
52'b00000000000000001???????????????????????????????????: dividend_shift <= 16; |
52'b000000000000000001??????????????????????????????????: dividend_shift <= 17; |
52'b0000000000000000001?????????????????????????????????: dividend_shift <= 18; |
52'b00000000000000000001????????????????????????????????: dividend_shift <= 19; |
52'b000000000000000000001???????????????????????????????: dividend_shift <= 20; |
52'b0000000000000000000001??????????????????????????????: dividend_shift <= 21; |
52'b00000000000000000000001?????????????????????????????: dividend_shift <= 22; |
52'b000000000000000000000001????????????????????????????: dividend_shift <= 23; |
52'b0000000000000000000000001???????????????????????????: dividend_shift <= 24; |
52'b00000000000000000000000001??????????????????????????: dividend_shift <= 25; |
52'b000000000000000000000000001?????????????????????????: dividend_shift <= 26; |
52'b0000000000000000000000000001????????????????????????: dividend_shift <= 27; |
52'b00000000000000000000000000001???????????????????????: dividend_shift <= 28; |
52'b000000000000000000000000000001??????????????????????: dividend_shift <= 29; |
52'b0000000000000000000000000000001?????????????????????: dividend_shift <= 30; |
52'b00000000000000000000000000000001????????????????????: dividend_shift <= 31; |
52'b000000000000000000000000000000001???????????????????: dividend_shift <= 32; |
52'b0000000000000000000000000000000001??????????????????: dividend_shift <= 33; |
52'b00000000000000000000000000000000001?????????????????: dividend_shift <= 34; |
52'b000000000000000000000000000000000001????????????????: dividend_shift <= 35; |
52'b0000000000000000000000000000000000001???????????????: dividend_shift <= 36; |
52'b00000000000000000000000000000000000001??????????????: dividend_shift <= 37; |
52'b000000000000000000000000000000000000001?????????????: dividend_shift <= 38; |
52'b0000000000000000000000000000000000000001????????????: dividend_shift <= 39; |
52'b00000000000000000000000000000000000000001???????????: dividend_shift <= 40; |
52'b000000000000000000000000000000000000000001??????????: dividend_shift <= 41; |
52'b0000000000000000000000000000000000000000001?????????: dividend_shift <= 42; |
52'b00000000000000000000000000000000000000000001????????: dividend_shift <= 43; |
52'b000000000000000000000000000000000000000000001???????: dividend_shift <= 44; |
52'b0000000000000000000000000000000000000000000001??????: dividend_shift <= 45; |
52'b00000000000000000000000000000000000000000000001?????: dividend_shift <= 46; |
52'b000000000000000000000000000000000000000000000001????: dividend_shift <= 47; |
52'b0000000000000000000000000000000000000000000000001???: dividend_shift <= 48; |
52'b00000000000000000000000000000000000000000000000001??: dividend_shift <= 49; |
52'b000000000000000000000000000000000000000000000000001?: dividend_shift <= 50; |
52'b0000000000000000000000000000000000000000000000000001: dividend_shift <= 51; |
52'b0000000000000000000000000000000000000000000000000000: dividend_shift <= 52; |
|
endcase |
|
always @(divisor_b) |
casex(divisor_b) |
52'b1???????????????????????????????????????????????????: divisor_shift <= 0; |
52'b01??????????????????????????????????????????????????: divisor_shift <= 1; |
52'b001?????????????????????????????????????????????????: divisor_shift <= 2; |
52'b0001????????????????????????????????????????????????: divisor_shift <= 3; |
52'b00001???????????????????????????????????????????????: divisor_shift <= 4; |
52'b000001??????????????????????????????????????????????: divisor_shift <= 5; |
52'b0000001?????????????????????????????????????????????: divisor_shift <= 6; |
52'b00000001????????????????????????????????????????????: divisor_shift <= 7; |
52'b000000001???????????????????????????????????????????: divisor_shift <= 8; |
52'b0000000001??????????????????????????????????????????: divisor_shift <= 9; |
52'b00000000001?????????????????????????????????????????: divisor_shift <= 10; |
52'b000000000001????????????????????????????????????????: divisor_shift <= 11; |
52'b0000000000001???????????????????????????????????????: divisor_shift <= 12; |
52'b00000000000001??????????????????????????????????????: divisor_shift <= 13; |
52'b000000000000001?????????????????????????????????????: divisor_shift <= 14; |
52'b0000000000000001????????????????????????????????????: divisor_shift <= 15; |
52'b00000000000000001???????????????????????????????????: divisor_shift <= 16; |
52'b000000000000000001??????????????????????????????????: divisor_shift <= 17; |
52'b0000000000000000001?????????????????????????????????: divisor_shift <= 18; |
52'b00000000000000000001????????????????????????????????: divisor_shift <= 19; |
52'b000000000000000000001???????????????????????????????: divisor_shift <= 20; |
52'b0000000000000000000001??????????????????????????????: divisor_shift <= 21; |
52'b00000000000000000000001?????????????????????????????: divisor_shift <= 22; |
52'b000000000000000000000001????????????????????????????: divisor_shift <= 23; |
52'b0000000000000000000000001???????????????????????????: divisor_shift <= 24; |
52'b00000000000000000000000001??????????????????????????: divisor_shift <= 25; |
52'b000000000000000000000000001?????????????????????????: divisor_shift <= 26; |
52'b0000000000000000000000000001????????????????????????: divisor_shift <= 27; |
52'b00000000000000000000000000001???????????????????????: divisor_shift <= 28; |
52'b000000000000000000000000000001??????????????????????: divisor_shift <= 29; |
52'b0000000000000000000000000000001?????????????????????: divisor_shift <= 30; |
52'b00000000000000000000000000000001????????????????????: divisor_shift <= 31; |
52'b000000000000000000000000000000001???????????????????: divisor_shift <= 32; |
52'b0000000000000000000000000000000001??????????????????: divisor_shift <= 33; |
52'b00000000000000000000000000000000001?????????????????: divisor_shift <= 34; |
52'b000000000000000000000000000000000001????????????????: divisor_shift <= 35; |
52'b0000000000000000000000000000000000001???????????????: divisor_shift <= 36; |
52'b00000000000000000000000000000000000001??????????????: divisor_shift <= 37; |
52'b000000000000000000000000000000000000001?????????????: divisor_shift <= 38; |
52'b0000000000000000000000000000000000000001????????????: divisor_shift <= 39; |
52'b00000000000000000000000000000000000000001???????????: divisor_shift <= 40; |
52'b000000000000000000000000000000000000000001??????????: divisor_shift <= 41; |
52'b0000000000000000000000000000000000000000001?????????: divisor_shift <= 42; |
52'b00000000000000000000000000000000000000000001????????: divisor_shift <= 43; |
52'b000000000000000000000000000000000000000000001???????: divisor_shift <= 44; |
52'b0000000000000000000000000000000000000000000001??????: divisor_shift <= 45; |
52'b00000000000000000000000000000000000000000000001?????: divisor_shift <= 46; |
52'b000000000000000000000000000000000000000000000001????: divisor_shift <= 47; |
52'b0000000000000000000000000000000000000000000000001???: divisor_shift <= 48; |
52'b00000000000000000000000000000000000000000000000001??: divisor_shift <= 49; |
52'b000000000000000000000000000000000000000000000000001?: divisor_shift <= 50; |
52'b0000000000000000000000000000000000000000000000000001: divisor_shift <= 51; |
52'b0000000000000000000000000000000000000000000000000000: divisor_shift <= 52; |
|
endcase |
|
endmodule |
/tags/arelease/fpu_sub.v
0,0 → 1,221
///////////////////////////////////////////////////////////////////// |
//// //// |
//// FPU //// |
//// Floating Point Unit (Double precision) //// |
//// //// |
//// Author: David Lundgren //// |
//// davidklun@gmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 David Lundgren //// |
//// davidklun@gmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
|
`timescale 1ns / 100ps |
|
|
module fpu_sub( clk, rst, enable, opa, opb, fpu_op, sign, diff_2, exponent_2); |
input clk; |
input rst; |
input enable; |
input [63:0] opa, opb; |
input [2:0] fpu_op; |
output sign; |
output [55:0] diff_2; |
output [10:0] exponent_2; |
|
reg [6:0] diff_shift; |
reg [6:0] diff_shift_2; |
|
|
reg [10:0] exponent_a; |
reg [10:0] exponent_b; |
reg [51:0] mantissa_a; |
reg [51:0] mantissa_b; |
reg expa_gt_expb; |
reg expa_et_expb; |
reg mana_gtet_manb; |
reg a_gtet_b; |
reg sign; |
reg [10:0] exponent_small; |
reg [10:0] exponent_large; |
reg [51:0] mantissa_small; |
reg [51:0] mantissa_large; |
reg small_is_denorm; |
reg large_is_denorm; |
reg large_norm_small_denorm; |
reg small_is_nonzero; |
reg [10:0] exponent_diff; |
reg [54:0] minuend; |
reg [54:0] subtrahend; |
reg [54:0] subtra_shift; |
wire subtra_shift_nonzero = |subtra_shift[54:0]; |
wire subtra_fraction_enable = small_is_nonzero & !subtra_shift_nonzero; |
wire [54:0] subtra_shift_2 = { 54'b0, 1'b1 }; |
reg [54:0] subtra_shift_3; |
reg [54:0] diff; |
reg diffshift_gt_exponent; |
reg diffshift_et_55; // when the difference = 0 |
reg [54:0] diff_1; |
reg [10:0] exponent; |
reg [10:0] exponent_2; |
wire in_norm_out_denorm = (exponent_large > 0) & (exponent== 0); |
reg [55:0] diff_2; |
|
|
always @(posedge clk) |
begin |
if (rst) begin |
exponent_a <= 0; |
exponent_b <= 0; |
mantissa_a <= 0; |
mantissa_b <= 0; |
expa_gt_expb <= 0; |
expa_et_expb <= 0; |
mana_gtet_manb <= 0; |
a_gtet_b <= 0; |
sign <= 0; |
exponent_small <= 0; |
exponent_large <= 0; |
mantissa_small <= 0; |
mantissa_large <= 0; |
small_is_denorm <= 0; |
large_is_denorm <= 0; |
large_norm_small_denorm <= 0; |
small_is_nonzero <= 0; |
exponent_diff <= 0; |
minuend <= 0; |
subtrahend <= 0; |
subtra_shift <= 0; |
subtra_shift_3 <= 0; |
diff_shift_2 <= 0; |
diff <= 0; |
diffshift_gt_exponent <= 0; |
diffshift_et_55 <= 0; |
diff_1 <= 0; |
exponent <= 0; |
exponent_2 <= 0; |
diff_2 <= 0; |
end |
else if (enable) begin |
exponent_a <= opa[62:52]; |
exponent_b <= opb[62:52]; |
mantissa_a <= opa[51:0]; |
mantissa_b <= opb[51:0]; |
expa_gt_expb <= exponent_a > exponent_b; |
expa_et_expb <= exponent_a == exponent_b; |
mana_gtet_manb <= mantissa_a >= mantissa_b; |
a_gtet_b <= expa_gt_expb | (expa_et_expb & mana_gtet_manb); |
sign <= a_gtet_b ? opa[63] :!opb[63] ^ (fpu_op == 3'b000); |
exponent_small <= a_gtet_b ? exponent_b : exponent_a; |
exponent_large <= a_gtet_b ? exponent_a : exponent_b; |
mantissa_small <= a_gtet_b ? mantissa_b : mantissa_a; |
mantissa_large <= a_gtet_b ? mantissa_a : mantissa_b; |
small_is_denorm <= !(exponent_small > 0); |
large_is_denorm <= !(exponent_large > 0); |
large_norm_small_denorm <= (small_is_denorm == 1 && large_is_denorm == 0); |
small_is_nonzero <= (exponent_small > 0) | |mantissa_small[51:0]; |
exponent_diff <= exponent_large - exponent_small - large_norm_small_denorm; |
minuend <= { !large_is_denorm, mantissa_large, 2'b00 }; |
subtrahend <= { !small_is_denorm, mantissa_small, 2'b00 }; |
subtra_shift <= subtrahend >> exponent_diff; |
subtra_shift_3 <= subtra_fraction_enable ? subtra_shift_2 : subtra_shift; |
diff_shift_2 <= diff_shift; |
diff <= minuend - subtra_shift_3; |
diffshift_gt_exponent <= diff_shift_2 > exponent_large; |
diffshift_et_55 <= diff_shift_2 == 55; |
diff_1 <= diffshift_gt_exponent ? diff << exponent_large : diff << diff_shift_2; |
exponent <= diffshift_gt_exponent ? 0 : (exponent_large - diff_shift_2); |
exponent_2 <= diffshift_et_55 ? 0 : exponent; |
diff_2 <= in_norm_out_denorm ? { 1'b0, diff_1 >> 1} : {1'b0, diff_1}; |
|
end |
end |
|
|
always @(diff) |
casex(diff) |
55'b1??????????????????????????????????????????????????????: diff_shift <= 0; |
55'b01?????????????????????????????????????????????????????: diff_shift <= 1; |
55'b001????????????????????????????????????????????????????: diff_shift <= 2; |
55'b0001???????????????????????????????????????????????????: diff_shift <= 3; |
55'b00001??????????????????????????????????????????????????: diff_shift <= 4; |
55'b000001?????????????????????????????????????????????????: diff_shift <= 5; |
55'b0000001????????????????????????????????????????????????: diff_shift <= 6; |
55'b00000001???????????????????????????????????????????????: diff_shift <= 7; |
55'b000000001??????????????????????????????????????????????: diff_shift <= 8; |
55'b0000000001?????????????????????????????????????????????: diff_shift <= 9; |
55'b00000000001????????????????????????????????????????????: diff_shift <= 10; |
55'b000000000001???????????????????????????????????????????: diff_shift <= 11; |
55'b0000000000001??????????????????????????????????????????: diff_shift <= 12; |
55'b00000000000001?????????????????????????????????????????: diff_shift <= 13; |
55'b000000000000001????????????????????????????????????????: diff_shift <= 14; |
55'b0000000000000001???????????????????????????????????????: diff_shift <= 15; |
55'b00000000000000001??????????????????????????????????????: diff_shift <= 16; |
55'b000000000000000001?????????????????????????????????????: diff_shift <= 17; |
55'b0000000000000000001????????????????????????????????????: diff_shift <= 18; |
55'b00000000000000000001???????????????????????????????????: diff_shift <= 19; |
55'b000000000000000000001??????????????????????????????????: diff_shift <= 20; |
55'b0000000000000000000001?????????????????????????????????: diff_shift <= 21; |
55'b00000000000000000000001????????????????????????????????: diff_shift <= 22; |
55'b000000000000000000000001???????????????????????????????: diff_shift <= 23; |
55'b0000000000000000000000001??????????????????????????????: diff_shift <= 24; |
55'b00000000000000000000000001?????????????????????????????: diff_shift <= 25; |
55'b000000000000000000000000001????????????????????????????: diff_shift <= 26; |
55'b0000000000000000000000000001???????????????????????????: diff_shift <= 27; |
55'b00000000000000000000000000001??????????????????????????: diff_shift <= 28; |
55'b000000000000000000000000000001?????????????????????????: diff_shift <= 29; |
55'b0000000000000000000000000000001????????????????????????: diff_shift <= 30; |
55'b00000000000000000000000000000001???????????????????????: diff_shift <= 31; |
55'b000000000000000000000000000000001??????????????????????: diff_shift <= 32; |
55'b0000000000000000000000000000000001?????????????????????: diff_shift <= 33; |
55'b00000000000000000000000000000000001????????????????????: diff_shift <= 34; |
55'b000000000000000000000000000000000001???????????????????: diff_shift <= 35; |
55'b0000000000000000000000000000000000001??????????????????: diff_shift <= 36; |
55'b00000000000000000000000000000000000001?????????????????: diff_shift <= 37; |
55'b000000000000000000000000000000000000001????????????????: diff_shift <= 38; |
55'b0000000000000000000000000000000000000001???????????????: diff_shift <= 39; |
55'b00000000000000000000000000000000000000001??????????????: diff_shift <= 40; |
55'b000000000000000000000000000000000000000001?????????????: diff_shift <= 41; |
55'b0000000000000000000000000000000000000000001????????????: diff_shift <= 42; |
55'b00000000000000000000000000000000000000000001???????????: diff_shift <= 43; |
55'b000000000000000000000000000000000000000000001??????????: diff_shift <= 44; |
55'b0000000000000000000000000000000000000000000001?????????: diff_shift <= 45; |
55'b00000000000000000000000000000000000000000000001????????: diff_shift <= 46; |
55'b000000000000000000000000000000000000000000000001???????: diff_shift <= 47; |
55'b0000000000000000000000000000000000000000000000001??????: diff_shift <= 48; |
55'b00000000000000000000000000000000000000000000000001?????: diff_shift <= 49; |
55'b000000000000000000000000000000000000000000000000001????: diff_shift <= 50; |
55'b0000000000000000000000000000000000000000000000000001???: diff_shift <= 51; |
55'b00000000000000000000000000000000000000000000000000001??: diff_shift <= 52; |
55'b000000000000000000000000000000000000000000000000000001?: diff_shift <= 53; |
55'b0000000000000000000000000000000000000000000000000000001: diff_shift <= 54; |
55'b0000000000000000000000000000000000000000000000000000000: diff_shift <= 55; |
endcase |
|
|
|
|
endmodule |
/tags/arelease/fpu_mul.v
0,0 → 1,273
///////////////////////////////////////////////////////////////////// |
//// //// |
//// FPU //// |
//// Floating Point Unit (Double precision) //// |
//// //// |
//// Author: David Lundgren //// |
//// davidklun@gmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 David Lundgren //// |
//// davidklun@gmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
|
`timescale 1ns / 100ps |
|
module fpu_mul( clk, rst, enable, opa, opb, sign, product_7, exponent_5); |
input clk; |
input rst; |
input enable; |
input [63:0] opa, opb; |
output sign; |
output [55:0] product_7; |
output [11:0] exponent_5; |
|
reg [5:0] product_shift; |
reg [5:0] product_shift_2; |
|
|
reg sign; |
reg [51:0] mantissa_a; |
reg [51:0] mantissa_b; |
reg [10:0] exponent_a; |
reg [10:0] exponent_b; |
reg a_is_norm; |
reg b_is_norm; |
reg a_is_zero; |
reg b_is_zero; |
reg in_zero; |
reg [11:0] exponent_terms; |
reg exponent_gt_expoffset; |
reg [11:0] exponent_under; |
reg [11:0] exponent_1; |
wire [11:0] exponent = 0; |
reg [11:0] exponent_2; |
reg exponent_gt_prodshift; |
reg [11:0] exponent_3; |
reg [11:0] exponent_4; |
reg exponent_et_zero; |
reg [52:0] mul_a; |
reg [52:0] mul_b; |
reg [40:0] product_a; |
reg [40:0] product_b; |
reg [40:0] product_c; |
reg [25:0] product_d; |
reg [33:0] product_e; |
reg [33:0] product_f; |
reg [35:0] product_g; |
reg [28:0] product_h; |
reg [28:0] product_i; |
reg [30:0] product_j; |
reg [41:0] sum_0; |
reg [35:0] sum_1; |
reg [41:0] sum_2; |
reg [35:0] sum_3; |
reg [36:0] sum_4; |
reg [27:0] sum_5; |
reg [29:0] sum_6; |
reg [36:0] sum_7; |
reg [30:0] sum_8; |
reg [105:0] product; |
reg [105:0] product_1; |
reg [105:0] product_2; |
reg [105:0] product_3; |
reg [105:0] product_4; |
reg [105:0] product_5; |
reg [105:0] product_6; |
reg product_lsb; // if there are any 1's in the remainder |
wire [55:0] product_7 = { 1'b0, product_6[105:52], product_lsb }; |
reg [11:0] exponent_5; |
|
always @(posedge clk) |
begin |
if (rst) begin |
sign <= 0; |
mantissa_a <= 0; |
mantissa_b <= 0; |
exponent_a <= 0; |
exponent_b <= 0; |
a_is_norm <= 0; |
b_is_norm <= 0; |
a_is_zero <= 0; |
b_is_zero <= 0; |
in_zero <= 0; |
exponent_terms <= 0; |
exponent_gt_expoffset <= 0; |
exponent_under <= 0; |
exponent_1 <= 0; |
exponent_2 <= 0; |
exponent_gt_prodshift <= 0; |
exponent_3 <= 0; |
exponent_4 <= 0; |
exponent_et_zero <= 0; |
mul_a <= 0; |
mul_b <= 0; |
product_a <= 0; |
product_b <= 0; |
product_c <= 0; |
product_d <= 0; |
product_e <= 0; |
product_f <= 0; |
product_g <= 0; |
product_h <= 0; |
product_i <= 0; |
product_j <= 0; |
sum_0 <= 0; |
sum_1 <= 0; |
sum_2 <= 0; |
sum_3 <= 0; |
sum_4 <= 0; |
sum_5 <= 0; |
sum_6 <= 0; |
sum_7 <= 0; |
sum_8 <= 0; |
product <= 0; |
product_1 <= 0; |
product_2 <= 0; |
product_3 <= 0; |
product_4 <= 0; |
product_5 <= 0; |
product_6 <= 0; |
product_lsb <= 0; |
exponent_5 <= 0; |
product_shift_2 <= 0; |
end |
else if (enable) begin |
sign <= opa[63] ^ opb[63]; |
mantissa_a <= opa[51:0]; |
mantissa_b <= opb[51:0]; |
exponent_a <= opa[62:52]; |
exponent_b <= opb[62:52]; |
a_is_norm <= |exponent_a; |
b_is_norm <= |exponent_b; |
a_is_zero <= !(|opa[62:0]); |
b_is_zero <= !(|opb[62:0]); |
in_zero <= a_is_zero | b_is_zero; |
exponent_terms <= exponent_a + exponent_b + !a_is_norm + !b_is_norm; |
exponent_gt_expoffset <= exponent_terms > 1021; |
exponent_under <= 1022 - exponent_terms; |
exponent_1 <= exponent_terms - 1022; |
exponent_2 <= exponent_gt_expoffset ? exponent_1 : exponent; |
exponent_gt_prodshift <= exponent_2 > product_shift_2; |
exponent_3 <= exponent_2 - product_shift; |
exponent_4 <= exponent_gt_prodshift ? exponent_3 : exponent; |
exponent_et_zero <= exponent_4 == 0; |
mul_a <= { a_is_norm, mantissa_a }; |
mul_b <= { b_is_norm, mantissa_b }; |
product_a <= mul_a[23:0] * mul_b[16:0]; |
product_b <= mul_a[23:0] * mul_b[33:17]; |
product_c <= mul_a[23:0] * mul_b[50:34]; |
product_d <= mul_a[23:0] * mul_b[52:51]; |
product_e <= mul_a[40:24] * mul_b[16:0]; |
product_f <= mul_a[40:24] * mul_b[33:17]; |
product_g <= mul_a[40:24] * mul_b[52:34]; |
product_h <= mul_a[52:41] * mul_b[16:0]; |
product_i <= mul_a[52:41] * mul_b[33:17]; |
product_j <= mul_a[52:41] * mul_b[52:34]; |
sum_0 <= product_a[40:17] + product_b; |
sum_1 <= sum_0[41:7] + product_e; |
sum_2 <= sum_1[35:10] + product_c; |
sum_3 <= sum_2[41:7] + product_h; |
sum_4 <= sum_3 + product_f; |
sum_5 <= sum_4[36:10] + product_d; |
sum_6 <= sum_5[27:7] + product_i; |
sum_7 <= sum_6 + product_g; |
sum_8 <= sum_7[36:17] + product_j; |
product <= { sum_8, sum_7[16:0], sum_5[6:0], sum_4[9:0], sum_2[6:0], |
sum_1[9:0], sum_0[6:0], product_a[16:0] }; |
product_1 <= product >> exponent_under; |
product_2 <= exponent_gt_expoffset ? product : product_1; |
product_3 <= product_2 << product_shift_2; |
product_4 <= product_2 << exponent_2; |
product_5 <= exponent_gt_prodshift ? product_3 : product_4; |
product_6 <= exponent_et_zero ? product_5 >> 1 : product_5; |
product_lsb <= |product_6[51:0]; |
exponent_5 <= in_zero ? 12'b0 : exponent_4; |
product_shift_2 <= product_shift; // redundant register |
// reduces fanout on product_shift |
end |
end |
|
always @(product) |
casex(product) |
106'b1?????????????????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 0; |
106'b01????????????????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 1; |
106'b001???????????????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 2; |
106'b0001??????????????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 3; |
106'b00001?????????????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 4; |
106'b000001????????????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 5; |
106'b0000001???????????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 6; |
106'b00000001??????????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 7; |
106'b000000001?????????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 8; |
106'b0000000001????????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 9; |
106'b00000000001???????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 10; |
106'b000000000001??????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 11; |
106'b0000000000001?????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 12; |
106'b00000000000001????????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 13; |
106'b000000000000001???????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 14; |
106'b0000000000000001??????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 15; |
106'b00000000000000001?????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 16; |
106'b000000000000000001????????????????????????????????????????????????????????????????????????????????????????: product_shift <= 17; |
106'b0000000000000000001???????????????????????????????????????????????????????????????????????????????????????: product_shift <= 18; |
106'b00000000000000000001??????????????????????????????????????????????????????????????????????????????????????: product_shift <= 19; |
106'b000000000000000000001?????????????????????????????????????????????????????????????????????????????????????: product_shift <= 20; |
106'b0000000000000000000001????????????????????????????????????????????????????????????????????????????????????: product_shift <= 21; |
106'b00000000000000000000001???????????????????????????????????????????????????????????????????????????????????: product_shift <= 22; |
106'b000000000000000000000001??????????????????????????????????????????????????????????????????????????????????: product_shift <= 23; |
106'b0000000000000000000000001?????????????????????????????????????????????????????????????????????????????????: product_shift <= 24; |
106'b00000000000000000000000001????????????????????????????????????????????????????????????????????????????????: product_shift <= 25; |
106'b000000000000000000000000001???????????????????????????????????????????????????????????????????????????????: product_shift <= 26; |
106'b0000000000000000000000000001??????????????????????????????????????????????????????????????????????????????: product_shift <= 27; |
106'b00000000000000000000000000001?????????????????????????????????????????????????????????????????????????????: product_shift <= 28; |
106'b000000000000000000000000000001????????????????????????????????????????????????????????????????????????????: product_shift <= 29; |
106'b0000000000000000000000000000001???????????????????????????????????????????????????????????????????????????: product_shift <= 30; |
106'b00000000000000000000000000000001??????????????????????????????????????????????????????????????????????????: product_shift <= 31; |
106'b000000000000000000000000000000001?????????????????????????????????????????????????????????????????????????: product_shift <= 32; |
106'b0000000000000000000000000000000001????????????????????????????????????????????????????????????????????????: product_shift <= 33; |
106'b00000000000000000000000000000000001???????????????????????????????????????????????????????????????????????: product_shift <= 34; |
106'b000000000000000000000000000000000001??????????????????????????????????????????????????????????????????????: product_shift <= 35; |
106'b0000000000000000000000000000000000001?????????????????????????????????????????????????????????????????????: product_shift <= 36; |
106'b00000000000000000000000000000000000001????????????????????????????????????????????????????????????????????: product_shift <= 37; |
106'b000000000000000000000000000000000000001???????????????????????????????????????????????????????????????????: product_shift <= 38; |
106'b0000000000000000000000000000000000000001??????????????????????????????????????????????????????????????????: product_shift <= 39; |
106'b00000000000000000000000000000000000000001?????????????????????????????????????????????????????????????????: product_shift <= 40; |
106'b000000000000000000000000000000000000000001????????????????????????????????????????????????????????????????: product_shift <= 41; |
106'b0000000000000000000000000000000000000000001???????????????????????????????????????????????????????????????: product_shift <= 42; |
106'b00000000000000000000000000000000000000000001??????????????????????????????????????????????????????????????: product_shift <= 43; |
106'b000000000000000000000000000000000000000000001?????????????????????????????????????????????????????????????: product_shift <= 44; |
106'b0000000000000000000000000000000000000000000001????????????????????????????????????????????????????????????: product_shift <= 45; |
106'b00000000000000000000000000000000000000000000001???????????????????????????????????????????????????????????: product_shift <= 46; |
106'b000000000000000000000000000000000000000000000001??????????????????????????????????????????????????????????: product_shift <= 47; |
106'b0000000000000000000000000000000000000000000000001?????????????????????????????????????????????????????????: product_shift <= 48; |
106'b00000000000000000000000000000000000000000000000001????????????????????????????????????????????????????????: product_shift <= 49; |
106'b000000000000000000000000000000000000000000000000001???????????????????????????????????????????????????????: product_shift <= 50; |
106'b0000000000000000000000000000000000000000000000000001??????????????????????????????????????????????????????: product_shift <= 51; |
106'b00000000000000000000000000000000000000000000000000001?????????????????????????????????????????????????????: product_shift <= 52; |
106'b000000000000000000000000000000000000000000000000000000????????????????????????????????????????????????????: product_shift <= 53; |
// It's not necessary to go past 53, because you will only get more than 53 zeros |
// when multiplying 2 denormalized numbers together, in which case you will underflow |
endcase |
|
endmodule |
/tags/arelease/pipeline/Readme_pipeline.txt
0,0 → 1,114
The verilog files, fpu_addsub.v and fpu_mul.v, are pipelined versions of |
floating point operators. The four rounding modes (Nearest, To Zero, To |
Positive Infintiy, To Negative Infinity) are supported by these operators. |
Denormalized numbers are not supported, but instead are treated as 0. |
If infinity or NaN is on either of the inputs, |
then infinity will be the output. Addition and subtraction have a latency |
of 24 clock cycles, and then an output is available on each clock cycle after the latency. |
Multiplication has a latency of 21 clock cycles, and |
then an output is available on each clock cycle after the latency. |
|
For addition and subtraction, fpu_addsub.v was synthesized with an estimated |
frequency of 259 MHz for a Virtex5 device. The synthesis results are below. |
The file, fpu_addsub_TB.v, is the testbench used to simulate fpu_addsub.v. |
|
For multiplication, fpu_mul.v was synthesized with an estimated |
frequency of 393 MHz for a Virtex5 device. The synthesis results are below. |
The file, fpu_mul_TB.v, is the testbench used to simulate fpu_mul.v. |
|
Please email me any questions. |
|
David Lundgren |
davidklun@gmail.com |
|
addsub synthesis results: |
|
--------------------------------------- |
Resource Usage Report for fpu_addsub |
|
Mapping to part: xc5vsx95tff1136-2 |
Cell usage: |
FDE 55 uses |
FDR 6 uses |
FDRE 2848 uses |
GND 1 use |
MUXCY 8 uses |
MUXCY_L 293 uses |
VCC 1 use |
XORCY 240 uses |
XORCY_L 5 uses |
LUT1 98 uses |
LUT2 377 uses |
LUT3 522 uses |
LUT4 151 uses |
LUT5 101 uses |
LUT6 517 uses |
|
I/O ports: 199 |
I/O primitives: 198 |
IBUF 133 uses |
OBUF 65 uses |
|
BUFGP 1 use |
|
SRL primitives: |
SRLC32E 1 use |
SRL16E 54 uses |
|
I/O Register bits: 0 |
Register bits not including I/Os: 2909 (4%) |
|
Global Clock Buffers: 1 of 32 (3%) |
|
Total load per clock: |
fpu_addsub|clk: 2964 |
|
Mapping Summary: |
Total LUTs: 1821 (3%) |
|
------------------------------ |
|
multiply synthesis results: |
|
--------------------------------------- |
Resource Usage Report for fpu_mul |
|
Mapping to part: xc5vsx95tff1136-2 |
Cell usage: |
DSP48E 9 uses |
FDE 83 uses |
FDRE 1536 uses |
FDRSE 11 uses |
GND 1 use |
MUXCY 7 uses |
MUXCY_L 164 uses |
VCC 1 use |
XORCY 128 uses |
XORCY_L 5 uses |
LUT1 82 uses |
LUT2 215 uses |
LUT3 170 uses |
LUT4 48 uses |
LUT5 13 uses |
LUT6 32 uses |
|
I/O ports: 198 |
I/O primitives: 197 |
IBUF 132 uses |
OBUF 65 uses |
|
BUFGP 1 use |
|
SRL primitives: |
SRL16E 83 uses |
|
I/O Register bits: 0 |
Register bits not including I/Os: 1630 (2%) |
|
Global Clock Buffers: 1 of 32 (3%) |
|
Total load per clock: |
fpu_mul|clk: 1722 |
|
Mapping Summary: |
Total LUTs: 643 (1%) |
/tags/arelease/pipeline/fpu_addsub.v
0,0 → 1,367
///////////////////////////////////////////////////////////////////// |
//// //// |
//// FPU //// |
//// Floating Point Unit (Double precision) //// |
//// //// |
//// Author: David Lundgren //// |
//// davidklun@gmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 David Lundgren //// |
//// davidklun@gmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
// fpu_op, add = 0, subtract = 1 |
// rmode = 00 (nearest), 01 (to zero), 10 (+ infinity), 11 (- infinity) |
|
`timescale 1ns / 100ps |
|
module fpu_addsub( clk, rst, enable, fpu_op, rmode, opa, opb, out, ready); |
input clk; |
input rst; |
input enable; |
input fpu_op; |
input [1:0] rmode; |
input [63:0] opa, opb; |
output [63:0] out; |
output ready; |
|
|
|
reg [63:0] outfp, out; |
reg [1:0] rm_1, rm_2, rm_3, rm_4, rm_5, rm_6, rm_7, rm_8, rm_9; |
reg [1:0] rm_10, rm_11, rm_12, rm_13, rm_14, rm_15, rm_16; |
reg sign, sign_a, sign_b, fpu_op_1, fpu_op_2, fpu_op_3, fpu_op_final; |
reg fpuf_2, fpuf_3, fpuf_4, fpuf_5, fpuf_6, fpuf_7, fpuf_8, fpuf_9, fpuf_10; |
reg fpuf_11, fpuf_12, fpuf_13, fpuf_14, fpuf_15, fpuf_16; |
reg fpuf_17, fpuf_18, fpuf_19, fpuf_20, fpuf_21; |
reg sign_a2, sign_a3, sign_b2, sign_b3, sign_2, sign_3, sign_4, sign_5, sign_6; |
reg sign_7, sign_8, sign_9, sign_10, sign_11, sign_12; |
reg sign_13, sign_14, sign_15, sign_16, sign_17, sign_18, sign_19; |
reg [10:0] exponent_a, exponent_b, expa_2, expb_2, expa_3, expb_3; |
reg [51:0] mantissa_a, mantissa_b, mana_2, mana_3, manb_2, manb_3; |
reg expa_et_inf, expb_et_inf, input_is_inf, in_inf2, in_inf3, in_inf4, in_inf5; |
reg in_inf6, in_inf7, in_inf8, in_inf9, in_inf10, in_inf11, in_inf12, in_inf13; |
reg in_inf14, in_inf15, in_inf16, in_inf17, in_inf18, in_inf19, in_inf20; |
reg in_inf21, expa_gt_expb, expa_et_expb, mana_gtet_manb, a_gtet_b; |
reg [10:0] exponent_small, exponent_large, expl_2, expl_3, expl_4; |
reg [10:0] expl_5, expl_6, expl_7, expl_8, expl_9, expl_10, expl_11; |
reg [51:0] mantissa_small, mantissa_large; |
reg [51:0] mantissa_small_2, mantissa_large_2; |
reg [51:0] mantissa_small_3, mantissa_large_3; |
reg exp_small_et0, exp_large_et0, exp_small_et0_2, exp_large_et0_2; |
reg [10:0] exponent_diff, exponent_diff_2, exponent_diff_3; |
reg [107:0] bits_shifted_out, bits_shifted_out_2; |
reg bits_shifted; |
reg [55:0] large_add, large_add_2, large_add_3, small_add; |
reg [55:0] small_shift, small_shift_2, small_shift_3, small_shift_4; |
reg [55:0] large_add_4, large_add_5; |
reg small_shift_nonzero; |
reg small_is_nonzero, small_is_nonzero_2, small_is_nonzero_3; |
reg small_fraction_enable; |
wire [55:0] small_shift_LSB = { 55'b0, 1'b1 }; |
reg [55:0] sum, sum_2, sum_3, sum_4, sum_5; |
reg [55:0] sum_6, sum_7, sum_8, sum_9, sum_10, sum_11; |
reg sum_overflow, sumround_overflow, sum_lsb, sum_lsb_2; |
reg [10:0] exponent_add, exp_add_2, exponent_sub, exp_sub_2; |
reg [10:0] exp_sub_3, exp_sub_4, exp_sub_5, exp_sub_6, exp_sub_7; |
reg [10:0] exp_sub_8, exp_add_3, exp_add_4, exp_add_5, exp_add_6; |
reg [10:0] exp_add_7, exp_add_8, exp_add_9; |
reg [5:0] diff_shift, diff_shift_2; |
reg [55:0] diff, diff_2, diff_3, diff_4, diff_5; |
reg [55:0] diff_6, diff_7, diff_8, diff_9, diff_10, diff_11; |
reg diffshift_gt_exponent, diffshift_et_55, diffround_overflow; |
reg round_nearest_mode, round_posinf_mode, round_neginf_mode; |
reg round_nearest_trigger, round_nearest_exception; |
reg round_nearest_enable, round_posinf_trigger, round_posinf_enable; |
reg round_neginf_trigger, round_neginf_enable, round_enable; |
reg ready, count_ready, count_ready_0; |
reg [4:0] count; |
|
always @(posedge clk) |
begin |
if (rst) begin |
fpu_op_1 <= 0; fpu_op_final <= 0; fpu_op_2 <= 0; |
fpu_op_3 <= 0; fpuf_2 <= 0; fpuf_3 <= 0; fpuf_4 <= 0; |
fpuf_5 <= 0; fpuf_6 <= 0; fpuf_7 <= 0; fpuf_8 <= 0; fpuf_9 <= 0; |
fpuf_10 <= 0; fpuf_11 <= 0; fpuf_12 <= 0; fpuf_13 <= 0; fpuf_14 <= 0; |
fpuf_15 <= 0; fpuf_16 <= 0; fpuf_17 <= 0; fpuf_18 <= 0; fpuf_19 <= 0; |
fpuf_20 <= 0; fpuf_21 <= 0; |
rm_1 <= 0; rm_2 <= 0; rm_3 <= 0; rm_4 <= 0; rm_5 <= 0; |
rm_6 <= 0; rm_7 <= 0; rm_8 <= 0; rm_9 <= 0; rm_10 <= 0; rm_11 <= 0; |
rm_12 <= 0; rm_13 <= 0; rm_14 <= 0; rm_15 <= 0; rm_16 <= 0; sign_a <= 0; |
sign_b <= 0; sign_a2 <= 0; sign_b2 <= 0; sign_a3 <= 0; sign_b3 <= 0; |
exponent_a <= 0; exponent_b <= 0; expa_2 <= 0; expa_3 <= 0; |
expb_2 <= 0; expb_3 <= 0; mantissa_a <= 0; mantissa_b <= 0; mana_2 <= 0; mana_3 <= 0; |
manb_2 <= 0; manb_3 <= 0; expa_et_inf <= 0; expb_et_inf <= 0; |
input_is_inf <= 0; in_inf2 <= 0; in_inf3 <= 0; in_inf4 <= 0; in_inf5 <= 0; |
in_inf6 <= 0; in_inf7 <= 0; in_inf8 <= 0; in_inf9 <= 0; in_inf10 <= 0; |
in_inf11 <= 0; in_inf12 <= 0; in_inf13 <= 0; in_inf14 <= 0; in_inf15 <= 0; |
in_inf16 <= 0; in_inf17 <= 0; in_inf18 <= 0; in_inf19 <= 0; in_inf20 <= 0; |
in_inf21 <= 0; expa_gt_expb <= 0; expa_et_expb <= 0; mana_gtet_manb <= 0; |
a_gtet_b <= 0; sign <= 0; sign_2 <= 0; sign_3 <= 0; sign_4 <= 0; sign_5 <= 0; |
sign_6 <= 0; sign_7 <= 0; sign_8 <= 0; sign_9 <= 0; |
sign_10 <= 0; sign_11 <= 0; sign_12 <= 0; sign_13 <= 0; sign_14 <= 0; |
sign_15 <= 0; sign_16 <= 0; sign_17 <= 0; sign_18 <= 0; sign_19 <= 0; |
exponent_small <= 0; exponent_large <= 0; expl_2 <= 0; |
expl_3 <= 0; expl_4 <= 0; expl_5 <= 0; expl_6 <= 0; expl_7 <= 0; |
expl_8 <= 0; expl_9 <= 0; expl_10 <= 0; expl_11 <= 0; |
exp_small_et0 <= 0; exp_large_et0 <= 0; |
exp_small_et0_2 <= 0; exp_large_et0_2 <= 0; |
mantissa_small <= 0; mantissa_large <= 0; |
mantissa_small_2 <= 0; mantissa_large_2 <= 0; |
mantissa_small_3 <= 0; mantissa_large_3 <= 0; |
exponent_diff <= 0; exponent_diff_2 <= 0; exponent_diff_3 <= 0; |
bits_shifted_out <= 0; |
bits_shifted_out_2 <= 0; bits_shifted <= 0; |
large_add <= 0; large_add_2 <= 0; |
large_add_3 <= 0; large_add_4 <= 0; large_add_5 <= 0; small_add <= 0; |
small_shift <= 0; small_shift_2 <= 0; small_shift_3 <= 0; |
small_shift_4 <= 0; small_shift_nonzero <= 0; |
small_is_nonzero <= 0; small_is_nonzero_2 <= 0; small_is_nonzero_3 <= 0; |
small_fraction_enable <= 0; |
sum <= 0; sum_2 <= 0; sum_overflow <= 0; sum_3 <= 0; sum_4 <= 0; |
sum_5 <= 0; sum_6 <= 0; sum_7 <= 0; sum_8 <= 0; sum_9 <= 0; sum_10 <= 0; |
sum_11 <= 0; sumround_overflow <= 0; sum_lsb <= 0; sum_lsb_2 <= 0; |
exponent_add <= 0; exp_add_2 <= 0; exp_add_3 <= 0; exp_add_4 <= 0; |
exp_add_5 <= 0; exp_add_6 <= 0; exp_add_7 <= 0; exp_add_8 <= 0; |
exp_add_9 <= 0; diff_shift_2 <= 0; diff <= 0; |
diffshift_gt_exponent <= 0; diffshift_et_55 <= 0; diff_2 <= 0; |
diff_3 <= 0; diff_4 <= 0; diff_5 <= 0; diff_6 <= 0; diff_7 <= 0; diff_8 <= 0; |
diff_9 <= 0; diff_10 <= 0; |
diff_11 <= 0; diffround_overflow <= 0; exponent_sub <= 0; |
exp_sub_2 <= 0; exp_sub_3 <= 0; exp_sub_4 <= 0; exp_sub_5 <= 0; |
exp_sub_6 <= 0; exp_sub_7 <= 0; exp_sub_8 <= 0; outfp <= 0; |
round_nearest_mode <= 0; round_posinf_mode <= 0; round_neginf_mode <= 0; round_nearest_trigger <= 0; |
round_nearest_exception <= 0; round_nearest_enable <= 0; round_posinf_trigger <= 0; round_posinf_enable <= 0; |
round_neginf_trigger <= 0; round_neginf_enable <= 0; round_enable <= 0; |
end |
else if (enable) begin |
fpu_op_1 <= fpu_op; fpu_op_final <= fpu_op_1 ^ (sign_a ^ sign_b); |
fpuf_2 <= fpu_op_final; fpuf_3 <= fpuf_2; fpuf_4 <= fpuf_3; |
fpuf_5 <= fpuf_4; fpuf_6 <= fpuf_5; fpuf_7 <= fpuf_6; fpuf_8 <= fpuf_7; |
fpuf_9 <= fpuf_8; fpuf_10 <= fpuf_9; fpuf_11 <= fpuf_10; fpuf_12 <= fpuf_11; |
fpuf_13 <= fpuf_12; fpuf_14 <= fpuf_13; fpuf_15 <= fpuf_14; |
fpuf_16 <= fpuf_15; fpuf_17 <= fpuf_16; fpuf_18 <= fpuf_17; |
fpuf_19 <= fpuf_18; fpuf_20 <= fpuf_19; fpuf_21 <= fpuf_20; |
fpu_op_2 <= fpu_op_1; fpu_op_3 <= fpu_op_2; |
rm_1 <= rmode; rm_2 <= rm_1; rm_3 <= rm_2; rm_4 <= rm_3; |
rm_5 <= rm_4; rm_6 <= rm_5; rm_7 <= rm_6; rm_8 <= rm_7; rm_9 <= rm_8; |
rm_10 <= rm_9; rm_11 <= rm_10; rm_12 <= rm_11; rm_13 <= rm_12; |
rm_14 <= rm_13; rm_15 <= rm_14; rm_16 <= rm_15; |
sign_a <= opa[63]; sign_b <= opb[63]; sign_a2 <= sign_a; |
sign_b2 <= sign_b; sign_a3 <= sign_a2; sign_b3 <= sign_b2; |
exponent_a <= opa[62:52]; expa_2 <= exponent_a; expa_3 <= expa_2; |
exponent_b <= opb[62:52]; expb_2 <= exponent_b; expb_3 <= expb_2; |
mantissa_a <= opa[51:0]; mana_2 <= mantissa_a; mana_3 <= mana_2; |
mantissa_b <= opb[51:0]; manb_2 <= mantissa_b; manb_3 <= manb_2; |
expa_et_inf <= exponent_a == 2047; |
expb_et_inf <= exponent_b == 2047; |
input_is_inf <= expa_et_inf | expb_et_inf; in_inf2 <= input_is_inf; |
in_inf3 <= in_inf2; in_inf4 <= in_inf3; in_inf5 <= in_inf4; in_inf6 <= in_inf5; |
in_inf7 <= in_inf6; in_inf8 <= in_inf7; in_inf9 <= in_inf8; in_inf10 <= in_inf9; |
in_inf11 <= in_inf10; in_inf12 <= in_inf11; in_inf13 <= in_inf12; |
in_inf14 <= in_inf13; in_inf15 <= in_inf14; in_inf16 <= in_inf15; |
in_inf17 <= in_inf16; in_inf18 <= in_inf17; in_inf19 <= in_inf18; |
in_inf20 <= in_inf19; in_inf21 <= in_inf20; |
expa_gt_expb <= exponent_a > exponent_b; |
expa_et_expb <= exponent_a == exponent_b; |
mana_gtet_manb <= mantissa_a >= mantissa_b; |
a_gtet_b <= expa_gt_expb | (expa_et_expb & mana_gtet_manb); |
sign <= a_gtet_b ? sign_a3 :!sign_b3 ^ (fpu_op_3 == 0); |
sign_2 <= sign; sign_3 <= sign_2; sign_4 <= sign_3; sign_5 <= sign_4; |
sign_6 <= sign_5; sign_7 <= sign_6; sign_8 <= sign_7; sign_9 <= sign_8; |
sign_10 <= sign_9; sign_11 <= sign_10; sign_12 <= sign_11; |
sign_13 <= sign_12; sign_14 <= sign_13; sign_15 <= sign_14; |
sign_16 <= sign_15; sign_17 <= sign_16; sign_18 <= sign_17; |
sign_19 <= sign_18; |
exponent_small <= a_gtet_b ? expb_3 : expa_3; |
exponent_large <= a_gtet_b ? expa_3 : expb_3; |
expl_2 <= exponent_large; expl_3 <= expl_2; expl_4 <= expl_3; |
expl_5 <= expl_4; expl_6 <= expl_5; expl_7 <= expl_6; expl_8 <= expl_7; |
expl_9 <= expl_8; expl_10 <= expl_9; expl_11 <= expl_10; |
exp_small_et0 <= exponent_small == 0; |
exp_large_et0 <= exponent_large == 0; |
exp_small_et0_2 <= exp_small_et0; |
exp_large_et0_2 <= exp_large_et0; |
mantissa_small <= a_gtet_b ? manb_3 : mana_3; |
mantissa_large <= a_gtet_b ? mana_3 : manb_3; |
mantissa_small_2 <= mantissa_small; |
mantissa_large_2 <= mantissa_large; |
mantissa_small_3 <= exp_small_et0 ? 0 : mantissa_small_2; |
mantissa_large_3 <= exp_large_et0 ? 0 : mantissa_large_2; |
exponent_diff <= exponent_large - exponent_small; |
exponent_diff_2 <= exponent_diff; |
exponent_diff_3 <= exponent_diff_2; |
bits_shifted_out <= exp_small_et0 ? 108'b0 : { 1'b1, mantissa_small_2, 55'b0 }; |
bits_shifted_out_2 <= bits_shifted_out >> exponent_diff_2; |
bits_shifted <= |bits_shifted_out_2[52:0]; |
large_add <= { 1'b0, !exp_large_et0_2, mantissa_large_3, 2'b0}; |
large_add_2 <= large_add; large_add_3 <= large_add_2; |
large_add_4 <= large_add_3; large_add_5 <= large_add_4; |
small_add <= { 1'b0, !exp_small_et0_2, mantissa_small_3, 2'b0}; |
small_shift <= small_add >> exponent_diff_3; |
small_shift_2 <= { small_shift[55:1], (bits_shifted | small_shift[0]) }; |
small_shift_3 <= small_shift_2; |
small_fraction_enable <= small_is_nonzero_3 & !small_shift_nonzero; |
small_shift_4 <= small_fraction_enable ? small_shift_LSB : small_shift_3; |
small_shift_nonzero <= |small_shift[54:0]; |
small_is_nonzero <= !exp_small_et0_2; |
small_is_nonzero_2 <= small_is_nonzero; small_is_nonzero_3 <= small_is_nonzero_2; |
sum <= large_add_5 + small_shift_4; |
sum_overflow <= sum[55]; |
sum_2 <= sum; sum_lsb <= sum[0]; |
sum_3 <= sum_overflow ? sum_2 >> 1 : sum_2; sum_lsb_2 <= sum_lsb; |
sum_4 <= { sum_3[55:1], sum_lsb_2 | sum_3[0] }; |
sum_5 <= sum_4; sum_6 <= sum_5; sum_7 <= sum_6; sum_8 <= sum_7; |
exponent_add <= sum_overflow ? expl_10 + 1: expl_10; |
exp_add_2 <= exponent_add; |
diff_shift_2 <= diff_shift; |
diff <= large_add_5 - small_shift_4; diff_2 <= diff; diff_3 <= diff_2; |
diffshift_gt_exponent <= diff_shift > expl_10; |
diffshift_et_55 <= diff_shift_2 == 55; |
diff_4 <= diffshift_gt_exponent ? diff_3 << expl_11 : diff_3 << diff_shift_2; |
diff_5 <= diff_4; diff_6 <= diff_5; diff_7 <= diff_6; diff_8 <= diff_7; |
exponent_sub <= diffshift_gt_exponent ? 0 : (expl_11 - diff_shift_2); |
exp_sub_2 <= diffshift_et_55 ? 0 : exponent_sub; |
round_nearest_mode <= rm_16 == 2'b00; |
round_posinf_mode <= rm_16 == 2'b10; |
round_neginf_mode <= rm_16 == 2'b11; |
round_nearest_trigger <= fpuf_15 ? diff_5[1] : sum_5[1]; |
round_nearest_exception <= fpuf_15 ? !diff_5[0] & !diff_5[2] : !sum_5[0] & !sum_5[2]; |
round_nearest_enable <= round_nearest_mode & round_nearest_trigger & !round_nearest_exception; |
round_posinf_trigger <= fpuf_15 ? |diff_5[1:0] & !sign_13 : |sum_5[1:0] & !sign_13; |
round_posinf_enable <= round_posinf_mode & round_posinf_trigger; |
round_neginf_trigger <= fpuf_15 ? |diff_5[1:0] & sign_13 : |sum_5[1:0] & sign_13; |
round_neginf_enable <= round_neginf_mode & round_neginf_trigger; |
round_enable <= round_posinf_enable | round_neginf_enable | round_nearest_enable; |
sum_9 <= round_enable ? sum_8 + 4 : sum_8; |
sumround_overflow <= sum_9[55]; sum_10 <= sum_9; |
sum_11 <= sumround_overflow ? sum_10 >> 1 : sum_10; |
diff_9 <= round_enable ? diff_8 + 4 : diff_8; |
diffround_overflow <= diff_9[55]; diff_10 <= diff_9; |
diff_11 <= diffround_overflow ? diff_10 >> 1 : diff_10; |
exp_add_3 <= exp_add_2; exp_add_4 <= exp_add_3; exp_add_5 <= exp_add_4; |
exp_add_6 <= exp_add_5; exp_add_7 <= exp_add_6; exp_add_8 <= exp_add_7; |
exp_add_9 <= sumround_overflow ? exp_add_8 + 1 : exp_add_8; |
exp_sub_3 <= exp_sub_2; exp_sub_4 <= exp_sub_3; exp_sub_5 <= exp_sub_4; |
exp_sub_6 <= exp_sub_5; exp_sub_7 <= exp_sub_6; |
exp_sub_8 <= diffround_overflow ? exp_sub_7 + 1 : exp_sub_7; |
outfp <= fpuf_21 ? {sign_19, exp_sub_8, diff_11[53:2]} : {sign_19, exp_add_9, sum_11[53:2]}; |
end |
end |
|
|
|
always @(posedge clk) |
casex(diff[54:0]) |
55'b1??????????????????????????????????????????????????????: diff_shift <= 0; |
55'b01?????????????????????????????????????????????????????: diff_shift <= 1; |
55'b001????????????????????????????????????????????????????: diff_shift <= 2; |
55'b0001???????????????????????????????????????????????????: diff_shift <= 3; |
55'b00001??????????????????????????????????????????????????: diff_shift <= 4; |
55'b000001?????????????????????????????????????????????????: diff_shift <= 5; |
55'b0000001????????????????????????????????????????????????: diff_shift <= 6; |
55'b00000001???????????????????????????????????????????????: diff_shift <= 7; |
55'b000000001??????????????????????????????????????????????: diff_shift <= 8; |
55'b0000000001?????????????????????????????????????????????: diff_shift <= 9; |
55'b00000000001????????????????????????????????????????????: diff_shift <= 10; |
55'b000000000001???????????????????????????????????????????: diff_shift <= 11; |
55'b0000000000001??????????????????????????????????????????: diff_shift <= 12; |
55'b00000000000001?????????????????????????????????????????: diff_shift <= 13; |
55'b000000000000001????????????????????????????????????????: diff_shift <= 14; |
55'b0000000000000001???????????????????????????????????????: diff_shift <= 15; |
55'b00000000000000001??????????????????????????????????????: diff_shift <= 16; |
55'b000000000000000001?????????????????????????????????????: diff_shift <= 17; |
55'b0000000000000000001????????????????????????????????????: diff_shift <= 18; |
55'b00000000000000000001???????????????????????????????????: diff_shift <= 19; |
55'b000000000000000000001??????????????????????????????????: diff_shift <= 20; |
55'b0000000000000000000001?????????????????????????????????: diff_shift <= 21; |
55'b00000000000000000000001????????????????????????????????: diff_shift <= 22; |
55'b000000000000000000000001???????????????????????????????: diff_shift <= 23; |
55'b0000000000000000000000001??????????????????????????????: diff_shift <= 24; |
55'b00000000000000000000000001?????????????????????????????: diff_shift <= 25; |
55'b000000000000000000000000001????????????????????????????: diff_shift <= 26; |
55'b0000000000000000000000000001???????????????????????????: diff_shift <= 27; |
55'b00000000000000000000000000001??????????????????????????: diff_shift <= 28; |
55'b000000000000000000000000000001?????????????????????????: diff_shift <= 29; |
55'b0000000000000000000000000000001????????????????????????: diff_shift <= 30; |
55'b00000000000000000000000000000001???????????????????????: diff_shift <= 31; |
55'b000000000000000000000000000000001??????????????????????: diff_shift <= 32; |
55'b0000000000000000000000000000000001?????????????????????: diff_shift <= 33; |
55'b00000000000000000000000000000000001????????????????????: diff_shift <= 34; |
55'b000000000000000000000000000000000001???????????????????: diff_shift <= 35; |
55'b0000000000000000000000000000000000001??????????????????: diff_shift <= 36; |
55'b00000000000000000000000000000000000001?????????????????: diff_shift <= 37; |
55'b000000000000000000000000000000000000001????????????????: diff_shift <= 38; |
55'b0000000000000000000000000000000000000001???????????????: diff_shift <= 39; |
55'b00000000000000000000000000000000000000001??????????????: diff_shift <= 40; |
55'b000000000000000000000000000000000000000001?????????????: diff_shift <= 41; |
55'b0000000000000000000000000000000000000000001????????????: diff_shift <= 42; |
55'b00000000000000000000000000000000000000000001???????????: diff_shift <= 43; |
55'b000000000000000000000000000000000000000000001??????????: diff_shift <= 44; |
55'b0000000000000000000000000000000000000000000001?????????: diff_shift <= 45; |
55'b00000000000000000000000000000000000000000000001????????: diff_shift <= 46; |
55'b000000000000000000000000000000000000000000000001???????: diff_shift <= 47; |
55'b0000000000000000000000000000000000000000000000001??????: diff_shift <= 48; |
55'b00000000000000000000000000000000000000000000000001?????: diff_shift <= 49; |
55'b000000000000000000000000000000000000000000000000001????: diff_shift <= 50; |
55'b0000000000000000000000000000000000000000000000000001???: diff_shift <= 51; |
55'b00000000000000000000000000000000000000000000000000001??: diff_shift <= 52; |
55'b000000000000000000000000000000000000000000000000000001?: diff_shift <= 53; |
55'b0000000000000000000000000000000000000000000000000000001: diff_shift <= 54; |
55'b0000000000000000000000000000000000000000000000000000000: diff_shift <= 55; |
endcase |
|
|
always @(posedge clk) |
begin |
if (rst) begin |
ready <= 0; |
count_ready_0 <= 0; |
count_ready <= 0; |
end |
else if (enable) begin |
ready <= count_ready; |
count_ready_0 <= count == 21; |
count_ready <= count == 22; |
end |
end |
|
always @(posedge clk) |
begin |
if (rst) |
count <= 0; |
else if (enable & !count_ready_0 & !count_ready) |
count <= count + 1; |
end |
|
always @(posedge clk) |
begin |
if (rst) |
out <= 0; |
else if (enable & count_ready) |
out <= in_inf21 ? { outfp[63], 11'b11111111111, 52'b0 } : outfp; |
end |
endmodule |
/tags/arelease/pipeline/fpu_mul_TB.v
0,0 → 1,168
|
`timescale 1ps / 1ps |
module fpu_mul_tb; |
|
reg clk; |
reg rst; |
reg enable; |
reg [1:0]rmode; |
reg [63:0]opa; |
reg [63:0]opb; |
wire ready; |
wire [63:0]outfp; |
|
fpu_mul UUT ( |
.clk(clk), |
.rst(rst), |
.enable(enable), |
.rmode(rmode), |
.opa(opa), |
.opb(opb), |
.ready(ready), |
.outfp(outfp)); |
|
initial |
begin : STIMUL |
#0 |
enable = 1'b0; |
rst = 1'b1; |
#10000; //0 |
enable = 1'b1; |
rst = 1'b0; |
//inputA:9.6300000000e+001 |
//inputB:-2.5600000000e-001 |
opa = 64'b0100000001011000000100110011001100110011001100110011001100110011; |
opb = 64'b1011111111010000011000100100110111010010111100011010100111111100; |
rmode = 2'b11; |
#10000; |
//inputA:3.6600000000e+000 |
//inputB:2.2500000000e+000 |
opa = 64'b0100000000001101010001111010111000010100011110101110000101001000; |
opb = 64'b0100000000000010000000000000000000000000000000000000000000000000; |
rmode = 2'b00; |
#10000; |
//inputA:-5.6970000000e+001 |
//inputB:1.2340000000e-001 |
opa = 64'b1100000001001100011111000010100011110101110000101000111101011100; |
opb = 64'b0011111110111111100101110010010001110100010100111000111011110011; |
rmode = 2'b11; |
#10000; |
//inputA:4.5680000000e+001 |
//inputB:2.1300000000e+000 |
opa = 64'b0100000001000110110101110000101000111101011100001010001111010111; |
opb = 64'b0100000000000001000010100011110101110000101000111101011100001010; |
rmode = 2'b00; |
#10000; |
//inputA:3.0000000000e-311 |
//inputB:-4.0000000000e+060 |
opa = 64'b0000000000000000000001011000010111000011011011101010101101110011; |
opb = 64'b1100110010000011111010011110010011100100110000101111001101000100; |
rmode = 2'b10; |
#10000; |
//inputA:4.6300000000e+001 |
//inputB:2.3110000000e+001 |
opa = 64'b0100000001000111001001100110011001100110011001100110011001100110; |
opb = 64'b0100000000110111000111000010100011110101110000101000111101011100; |
rmode = 2'b00; |
#10000; |
//inputA:5.0000000000e-250 |
//inputB:-1.#INF000000e+000 |
opa = 64'b0000110000101100101000111000111100110101000010110010001011011111; |
opb = 64'b1111111111110000000000000000000000000000000000000000000000000000; |
rmode = 2'b11; |
#10000; |
//inputA: |
//inputB: |
opa = 64'b0100000000111111111111111111111111111111111111111111111111111110; |
opb = 64'b0100000000110000000000000000000000000000000000000000000000000001; |
rmode = 2'b00; |
#10000; |
//inputA:1.2000000000e-001 |
//inputB:5.2000000000e+001 |
opa = 64'b0011111110111110101110000101000111101011100001010001111010111000; |
opb = 64'b0100000001001010000000000000000000000000000000000000000000000000; |
rmode = 2'b00; |
#10000; |
//inputA:8.9999000000e+004 |
//inputB:1.6000000000e+001 |
opa = 64'b0100000011110101111110001111000000000000000000000000000000000000; |
opb = 64'b0100000000110000000000000000000000000000000000000000000000000000; |
rmode = 2'b10; |
|
#120000; |
//Output:-2.465280000000000e+001 |
if (outfp==64'hC038A71DE69AD42D) |
$display($time,"ps Answer is correct %h", outfp); |
else |
$display($time,"ps Error! out is incorrect %h", outfp); |
#10000; //0 |
//Output:8.235000000000001e+000 |
if (outfp==64'h40207851EB851EB8) |
$display($time,"ps Answer is correct %h", outfp); |
else |
$display($time,"ps Error! out is incorrect %h", outfp); |
#10000; //0 |
//Output:-7.030098000000000e+000 |
if (outfp==64'hC01C1ED20296B335) |
$display($time,"ps Answer is correct %h", outfp); |
else |
$display($time,"ps Error! out is incorrect %h", outfp); |
#10000; //0 |
//Output:9.729840000000000e+001 |
if (outfp==64'h40585318FC504817) |
$display($time,"ps Answer is correct %h", outfp); |
else |
$display($time,"ps Error! out is incorrect %h", outfp); |
#10000; //0 |
//Output:-0 |
if (outfp==64'h8000000000000000) |
$display($time,"ps Answer is correct %h", outfp); |
else |
$display($time,"ps Error! out is incorrect %h", outfp); |
#10000; //0 |
//Output:1.069993000000000e+003 |
if (outfp==64'h4090B7F8D4FDF3B6) |
$display($time,"ps Answer is correct %h", outfp); |
else |
$display($time,"ps Error! out is incorrect %h", outfp); |
#10000; //0 |
//Output:-INF |
if (outfp==64'hFFF0000000000000) |
$display($time,"ps Answer is correct %h", outfp); |
else |
$display($time,"ps Error! out is incorrect %h", outfp); |
#10000; //0 |
//Output |
if (outfp==64'h4080000000000000) |
$display($time,"ps Answer is correct %h", outfp); |
else |
$display($time,"ps Error! out is incorrect %h", outfp); |
#10000; //0 |
//Output:6.240000000000000e+000 |
if (outfp==64'h4018F5C28F5C28F6) |
$display($time,"ps Answer is correct %h", outfp); |
else |
$display($time,"ps Error! out is incorrect %h", outfp); |
|
#10000; //0 |
//Output:1.439984000000000e+006 |
if (outfp==64'h4135F8F000000000) |
$display($time,"ps Answer is correct %h", outfp); |
else |
$display($time,"ps Error! out is incorrect %h", outfp); |
|
#290000; //10000 |
$finish; |
end // end of stimulus process |
|
always |
begin : CLOCK_clk |
|
clk = 1'b0; |
#5000; |
clk = 1'b1; |
#5000; |
end |
|
|
endmodule |
/tags/arelease/pipeline/fpu_addsub_TB.v
0,0 → 1,254
|
`timescale 1ps / 1ps |
module fpu_addsub_tb; |
|
reg clk; |
reg rst; |
reg enable; |
reg fpu_op; |
reg [1:0]rmode; |
reg [63:0]opa; |
reg [63:0]opb; |
wire [63:0]out; |
wire ready; |
|
|
fpu_addsub UUT ( |
.clk(clk), |
.rst(rst), |
.enable(enable), |
.fpu_op(fpu_op), |
.rmode(rmode), |
.opa(opa), |
.opb(opb), |
.out(out), |
.ready(ready)); |
|
initial |
begin : STIMUL |
#0 |
enable = 1'b0; |
rst = 1'b1; |
#10000; |
enable = 1'b1; |
rst = 1'b0; |
opa = 64'b0100000000010001010110010001011010000111001010110000001000001100; |
opb = 64'b0000110000000110111010010011111101011101101000101000001001001100; |
fpu_op = 1'b0; |
rmode = 2'b10; |
#10000; |
//inputA:1.6000000000e+001 |
//inputB:1.0000000000e-208 |
opa = 64'b0100000000110000000000000000000000000000000000000000000000000000; |
opb = 64'b0001010011000000011100000001101111010101001001111011010010011000; |
fpu_op = 1'b1; |
rmode = 2'b10; |
#10000; |
//inputA:9.9999999996e-314 |
//inputB:4.6770000000e+000 |
opa = 64'b0000000000000000000000000000010010110110011010010101010000110010; |
opb = 64'b0100000000010010101101010011111101111100111011011001000101101000; |
fpu_op = 1'b1; |
rmode = 2'b11; |
#10000; |
//inputA:5.3620000000e+003 |
//inputB:1.9999999999e-314 |
opa = 64'b0100000010110100111100100000000000000000000000000000000000000000; |
opb = 64'b0000000000000000000000000000000011110001010010000100010000001010; |
fpu_op = 1'b0; |
rmode = 2'b10; |
#10000; |
//inputA:5.8000000000e+000 |
//inputB:5.7900000000e+000 |
opa = 64'b0100000000010111001100110011001100110011001100110011001100110011; |
opb = 64'b0100000000010111001010001111010111000010100011110101110000101001; |
fpu_op = 1'b1; |
rmode = 2'b10; |
#10000; |
opa = 64'b0100000000010001010110010001011010000111001010110000001000001100; |
opb = 64'b0000110000000110111010010011111101011101101000101000001001001100; |
fpu_op = 1'b0; |
rmode = 2'b00; |
#10000; |
//inputA:-9.4000000000e+035 |
//inputB:9.4770000000e+035 |
opa = 64'b1100011101100110101000010011001010000000011101101111101100010011; |
opb = 64'b0100011101100110110100001010011011110101101100101001000000100011; |
fpu_op = 1'b0; |
rmode = 2'b10; |
#10000; |
//inputA:-3.6680000000e+000 |
//inputB:9.0007340000e+003 |
opa = 64'b1100000000001101010110000001000001100010010011011101001011110010; |
opb = 64'b0100000011000001100101000101110111110011101101100100010110100010; |
fpu_op = 1'b1; |
rmode = 2'b11; |
#10000; |
//inputA:4.7700000000e+000 |
//inputB:-2.5000000000e-003 |
opa = 64'b0100000000010011000101000111101011100001010001111010111000010100; |
opb = 64'b1011111101100100011110101110000101000111101011100001010001111011; |
fpu_op = 1'b0; |
rmode = 2'b10; |
#10000; |
//inputA:7.9500000000e+000 |
//inputB:-7.9433210000e+000 |
opa = 64'b0100000000011111110011001100110011001100110011001100110011001101; |
opb = 64'b1100000000011111110001011111010111110000101100101000010100100011; |
fpu_op = 1'b1; |
rmode = 2'b00; |
#10000; |
//inputA:8.0260000000e+000 |
//inputB:1.0000000000e-106 |
opa = 64'b0100000000100000000011010100111111011111001110110110010001011010; |
opb = 64'b0010100111101101010110110101011000010101011101000111011001011011; |
fpu_op = 1'b0; |
rmode = 2'b10; |
#10000; |
//inputA:9.9230000000e+001 |
//inputB:2.5370000000e-003 |
opa = 64'b0100000001011000110011101011100001010001111010111000010100011111; |
opb = 64'b0011111101100100110010000111100110000000111101010101110111100110; |
fpu_op = 1'b1; |
rmode = 2'b11; |
#10000; |
//inputA:1.7179869184e+010 |
//inputB:4.0000000000e-176 |
opa = 64'b0100001000001111111111111111111111111111111111111111111111111111; |
opb = 64'b0001101110000100010000101110010011111011011001110001100101100000; |
fpu_op = 1'b0; |
rmode = 2'b10; |
#10000; |
//inputA:-2.6800000000e-005 |
//inputB:-8.5400000000e-013 |
opa = 64'b1011111011111100000110100001000111111001111111011000011110000000; |
opb = 64'b1011110101101110000011000010010111101110000010111101110010010110; |
fpu_op = 1'b0; |
rmode = 2'b00; |
#10000; |
//inputA:-8.5400000000e-013 |
//inputB:INF |
opa = 64'b1011110101101110000011000010010111101110000010111101110010010110; |
opb = 64'b0111111111110000000000000000000000000000000000000000000000000000; |
fpu_op = 1'b0; |
rmode = 2'b00; |
#10000; |
//inputA:-5.6555650000e+006 |
//inputB:-2.3665000000e-001 |
opa = 64'b1100000101010101100100110000001101000000000000000000000000000000; |
opb = 64'b1011111111001110010010101000110000010101010011001001100001011111; |
fpu_op = 1'b1; |
rmode = 2'b11; |
#90000; |
//Output:4.337000000000001e+000 |
if (out==64'h40115916872B020D) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:1.600000000000000e+001 |
if (out==64'h4030000000000000) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:-4.677000000000000e+000 |
if (out==64'hC012B53F7CED9168) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:5.362000000000001e+003 |
if (out==64'h40B4F20000000000) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:9.999999999999787e-003 |
if (out==64'h3F847AE147AE1400) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:4.337000000000001e+000 |
if (out==64'h40115916872B020C) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:7.699999999999867e+033 |
if (out==64'h46F7BA3A9DCA8800) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:-9.004402000000000e+003 |
if (out==64'hC0C1963374BC6A80) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:4.767500000000000e+000 |
if (out==64'h401311EB851EB852) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:1.589332100000000e+001 |
if (out==64'h402FC9615EBFA8F8) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:8.026000000000002e+000 |
if (out==64'h40200D4FDF3B645B) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:9.922746300000000e+001 |
if (out==64'h4058CE8EC0F88334) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:1.717986918400000e+010 |
if (out==64'h4210000000000000) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:-2.680000085400000e-005 |
if (out==64'hBEFC1A1209039A77) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:INF |
if (out==64'h7FF0000000000000) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#10000; |
//Output:-5.655564763350001e+006 |
if (out==64'hC155930330DAB9F6) |
$display($time,"ps Answer is correct %h", out); |
else |
$display($time,"ps Error! out is incorrect %h", out); |
#390000; |
$finish; |
end |
|
always |
begin : CLOCK_clk |
clk = 1'b0; |
#5000; |
clk = 1'b1; |
#5000; |
end |
|
|
|
|
endmodule |
|
/tags/arelease/pipeline/fpu_mul.v
0,0 → 1,270
///////////////////////////////////////////////////////////////////// |
//// //// |
//// FPU //// |
//// Floating Point Unit (Double precision) //// |
//// //// |
//// Author: David Lundgren //// |
//// davidklun@gmail.com //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 David Lundgren //// |
//// davidklun@gmail.com //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer.//// |
//// //// |
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //// |
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //// |
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //// |
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR //// |
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, //// |
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES //// |
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE //// |
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR //// |
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF //// |
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT //// |
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT //// |
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE //// |
//// POSSIBILITY OF SUCH DAMAGE. //// |
//// //// |
///////////////////////////////////////////////////////////////////// |
|
// rmode = 00 (nearest), 01 (to zero), 10 (+ infinity), 11 (- infinity) |
|
`timescale 1ns / 100ps |
|
module fpu_mul( clk, rst, enable, rmode, opa, opb, ready, outfp); |
input clk; |
input rst; |
input enable; |
input [1:0] rmode; |
input [63:0] opa, opb; |
output ready; |
output [63:0] outfp; |
|
|
reg product_shift; |
reg [1:0] rm_1, rm_2, rm_3, rm_4, rm_5, rm_6, rm_7, rm_8, rm_9; |
reg [1:0] rm_10, rm_11, rm_12, rm_13, rm_14, rm_15; |
reg sign, sign_1, sign_2, sign_3, sign_4, sign_5, sign_6, sign_7, sign_8; |
reg sign_9, sign_10, sign_11, sign_12, sign_13, sign_14, sign_15, sign_16, sign_17; |
reg sign_18, sign_19, sign_20; |
reg [51:0] mantissa_a1, mantissa_a2; |
reg [51:0] mantissa_b1, mantissa_b2; |
reg [10:0] exponent_a; |
reg [10:0] exponent_b; |
reg ready, count_ready, count_ready_0; |
reg [4:0] count; |
reg a_is_zero, b_is_zero, a_is_inf, b_is_inf, in_inf_1, in_inf_2; |
reg in_zero_1; |
reg [11:0] exponent_terms_1, exponent_terms_2, exponent_terms_3, exponent_terms_4; |
reg [11:0] exponent_terms_5, exponent_terms_6, exponent_terms_7; |
reg [11:0] exponent_terms_8, exponent_terms_9; |
reg exponent_gt_expoffset; |
reg [11:0] exponent_1; |
wire [11:0] exponent = 0; |
reg [11:0] exponent_2, exponent_2_0, exponent_2_1; |
reg exponent_gt_prodshift, exponent_is_infinity; |
reg [11:0] exponent_3, exponent_4; |
reg set_mantissa_zero, set_mz_1; |
reg [52:0] mul_a, mul_a1, mul_a2, mul_a3, mul_a4, mul_a5, mul_a6, mul_a7, mul_a8; |
reg [52:0] mul_b, mul_b1, mul_b2, mul_b3, mul_b4, mul_b5, mul_b6, mul_b7, mul_b8; |
reg [40:0] product_a; |
reg [16:0] product_a_2, product_a_3, product_a_4, product_a_5, product_a_6; |
reg [16:0] product_a_7, product_a_8, product_a_9, product_a_10; |
reg [40:0] product_b; |
reg [40:0] product_c; |
reg [25:0] product_d; |
reg [33:0] product_e; |
reg [33:0] product_f; |
reg [35:0] product_g; |
reg [28:0] product_h; |
reg [28:0] product_i; |
reg [30:0] product_j; |
reg [41:0] sum_0; |
reg [6:0] sum_0_2, sum_0_3, sum_0_4, sum_0_5, sum_0_6, sum_0_7, sum_0_8, sum_0_9; |
reg [35:0] sum_1; |
reg [9:0] sum_1_2, sum_1_3, sum_1_4, sum_1_5, sum_1_6, sum_1_7, sum_1_8; |
reg [41:0] sum_2; |
reg [6:0] sum_2_2, sum_2_3, sum_2_4, sum_2_5, sum_2_6, sum_2_7; |
reg [35:0] sum_3; |
reg [36:0] sum_4; |
reg [9:0] sum_4_2, sum_4_3, sum_4_4, sum_4_5; |
reg [27:0] sum_5; |
reg [6:0] sum_5_2, sum_5_3, sum_5_4; |
reg [29:0] sum_6; |
reg [36:0] sum_7; |
reg [16:0] sum_7_2; |
reg [30:0] sum_8; |
reg [105:0] product; |
reg [105:0] product_1; |
reg [52:0] product_2, product_3; |
reg [53:0] product_4, product_5, product_6, product_7; |
reg product_overflow; |
reg [11:0] exponent_5, exponent_6, exponent_7, exponent_8, exponent_9; |
reg round_nearest_mode, round_posinf_mode, round_neginf_mode; |
reg round_nearest_trigger, round_nearest_exception; |
reg round_nearest_enable, round_posinf_trigger, round_posinf_enable; |
reg round_neginf_trigger, round_neginf_enable, round_enable; |
wire [63:0] outfp = { sign, exponent_9[10:0], product_7[51:0]}; |
|
always @(posedge clk) |
begin |
if (rst) begin |
sign <= 0; sign_1 <= 0; sign_2 <= 0; sign_3 <= 0; sign_4 <= 0; |
sign_5 <= 0; sign_6 <= 0; sign_7 <= 0; sign_8 <= 0; sign_9 <= 0; |
sign_10 <= 0; sign_11 <= 0; sign_12 <= 0; sign_13 <= 0; |
sign_14 <= 0; sign_15 <= 0; sign_16 <= 0; sign_17 <= 0; sign_18 <= 0; sign_19 <= 0; |
sign_20 <= 0; mantissa_a1 <= 0; mantissa_b1 <= 0; mantissa_a2 <= 0; mantissa_b2 <= 0; |
exponent_a <= 0; exponent_b <= 0; rm_1 <= 0; rm_2 <= 0; rm_3 <= 0; rm_4 <= 0; rm_5 <= 0; |
rm_6 <= 0; rm_7 <= 0; rm_8 <= 0; rm_9 <= 0; rm_10 <= 0; rm_11 <= 0; |
rm_12 <= 0; rm_13 <= 0; rm_14 <= 0; rm_15 <= 0; |
a_is_zero <= 0; b_is_zero <= 0; a_is_inf <= 0; b_is_inf <= 0; in_inf_1 <= 0; in_inf_2 <= 0; |
in_zero_1 <= 0; exponent_terms_1 <= 0; exponent_terms_2 <= 0; exponent_terms_3 <= 0; |
exponent_terms_4 <= 0; exponent_terms_5 <= 0; exponent_terms_6 <= 0; exponent_terms_7 <= 0; |
exponent_terms_8 <= 0; exponent_terms_9 <= 0; exponent_gt_expoffset <= 0; exponent_1 <= 0; |
exponent_2_0 <= 0; exponent_2_1 <= 0; exponent_2 <= 0; exponent_gt_prodshift <= 0; |
exponent_is_infinity <= 0; exponent_3 <= 0; exponent_4 <= 0; |
set_mantissa_zero <= 0; set_mz_1 <= 0; mul_a <= 0; mul_b <= 0; mul_a1 <= 0; mul_b1 <= 0; |
mul_a2 <= 0; mul_b2 <= 0; mul_a3 <= 0; mul_b3 <= 0; mul_a4 <= 0; mul_b4 <= 0; mul_a5 <= 0; |
mul_b5 <= 0; mul_a6 <= 0; mul_b6 <= 0; mul_a7 <= 0; mul_b7 <= 0; mul_a8 <= 0; mul_b8 <= 0; |
product_a <= 0; product_a_2 <= 0; product_a_3 <= 0; product_a_4 <= 0; product_a_5 <= 0; |
product_a_6 <= 0; product_a_7 <= 0; product_a_8 <= 0; product_a_9 <= 0; product_a_10 <= 0; |
product_b <= 0; product_c <= 0; product_d <= 0; product_e <= 0; product_f <= 0; |
product_g <= 0; product_h <= 0; product_i <= 0; product_j <= 0; |
sum_0 <= 0; sum_0_2 <= 0; sum_0_3 <= 0; sum_0_4 <= 0; sum_0_5 <= 0; sum_0_6 <= 0; |
sum_0_7 <= 0; sum_0_8 <= 0; sum_0_9 <= 0; sum_1 <= 0; sum_1_2 <= 0; sum_1_3 <= 0; sum_1_4 <= 0; |
sum_1_5 <= 0; sum_1_6 <= 0; sum_1_7 <= 0; sum_1_8 <= 0; sum_2 <= 0; sum_2_2 <= 0; sum_2_3 <= 0; |
sum_2_4 <= 0; sum_2_5 <= 0; sum_2_6 <= 0; sum_2_7 <= 0; sum_3 <= 0; sum_4 <= 0; sum_4_2 <= 0; |
sum_4_3 <= 0; sum_4_4 <= 0; sum_4_5 <= 0; sum_5 <= 0; sum_5_2 <= 0; sum_5_3 <= 0; sum_5_4 <= 0; |
sum_6 <= 0; sum_7 <= 0; sum_7_2 <= 0; sum_8 <= 0; product <= 0; product_1 <= 0; product_2 <= 0; |
product_3 <= 0; product_4 <= 0; product_5 <= 0; product_overflow <= 0; product_6 <= 0; |
exponent_5 <= 0; exponent_6 <= 0; exponent_7 <= 0; exponent_8 <= 0; product_shift <= 0; |
product_7 <= 0; exponent_9 <= 0; |
round_nearest_mode <= 0; round_posinf_mode <= 0; round_neginf_mode <= 0; round_nearest_trigger <= 0; |
round_nearest_exception <= 0; round_nearest_enable <= 0; round_posinf_trigger <= 0; round_posinf_enable <= 0; |
round_neginf_trigger <= 0; round_neginf_enable <= 0; round_enable <= 0; |
end |
else if (enable) begin |
sign_1 <= opa[63] ^ opb[63]; sign_2 <= sign_1; sign_3 <= sign_2; sign_4 <= sign_3; |
sign_5 <= sign_4; sign_6 <= sign_5; sign_7 <= sign_6; sign_8 <= sign_7; sign_9 <= sign_8; |
sign_10 <= sign_9; sign_11 <= sign_10; sign_12 <= sign_11; sign_13 <= sign_12; |
sign_14 <= sign_13; sign_15 <= sign_14; sign_16 <= sign_15; sign_17 <= sign_16; |
sign_18 <= sign_17; sign_19 <= sign_18; sign_20 <= sign_19; sign <= sign_20; |
mantissa_a1 <= opa[51:0]; mantissa_b1 <= opb[51:0]; mantissa_a2 <= mantissa_a1; |
mantissa_b2 <= mantissa_b1; exponent_a <= opa[62:52]; exponent_b <= opb[62:52]; |
rm_1 <= rmode; rm_2 <= rm_1; rm_3 <= rm_2; rm_4 <= rm_3; |
rm_5 <= rm_4; rm_6 <= rm_5; rm_7 <= rm_6; rm_8 <= rm_7; rm_9 <= rm_8; |
rm_10 <= rm_9; rm_11 <= rm_10; rm_12 <= rm_11; rm_13 <= rm_12; rm_14 <= rm_13; |
rm_15 <= rm_14; |
a_is_zero <= !(|exponent_a); b_is_zero <= !(|exponent_b); |
a_is_inf <= exponent_a == 2047; b_is_inf <= exponent_b == 2047; |
in_inf_1 <= a_is_inf | b_is_inf; in_inf_2 <= in_inf_1; |
in_zero_1 <= a_is_zero | b_is_zero; |
exponent_terms_1 <= exponent_a + exponent_b; |
exponent_terms_2 <= exponent_terms_1; |
exponent_terms_3 <= in_zero_1 ? 12'b0 : exponent_terms_2; |
exponent_terms_4 <= in_inf_2 ? 12'b110000000000 : exponent_terms_3; |
exponent_terms_5 <= exponent_terms_4; exponent_terms_6 <= exponent_terms_5; |
exponent_terms_7 <= exponent_terms_6; exponent_terms_8 <= exponent_terms_7; |
exponent_terms_9 <= exponent_terms_8; |
exponent_gt_expoffset <= exponent_terms_9 > 1022; |
exponent_1 <= exponent_terms_9 - 1022; |
exponent_2_0 <= exponent_gt_expoffset ? exponent_1 : exponent; |
exponent_2_1 <= exponent_2_0; |
exponent_2 <= exponent_2_1; |
exponent_is_infinity <= (exponent_3 > 2046) & exponent_gt_prodshift; |
exponent_3 <= exponent_2 - product_shift; |
exponent_gt_prodshift <= exponent_2 >= product_shift; |
exponent_4 <= exponent_gt_prodshift ? exponent_3 : exponent; |
exponent_5 <= exponent_is_infinity ? 12'b011111111111 : exponent_4; |
set_mantissa_zero <= exponent_4 == 0 | exponent_is_infinity; |
set_mz_1 <= set_mantissa_zero; |
exponent_6 <= exponent_5; |
mul_a <= { !a_is_zero, mantissa_a2 }; mul_b <= { !b_is_zero, mantissa_b2 }; |
mul_a1 <= mul_a; mul_b1 <= mul_b; |
mul_a2 <= mul_a1; mul_b2 <= mul_b1; mul_a3 <= mul_a2; mul_b3 <= mul_b2; |
mul_a4 <= mul_a3; mul_b4 <= mul_b3; mul_a5 <= mul_a4; mul_b5 <= mul_b4; |
mul_a6 <= mul_a5; mul_b6 <= mul_b5; mul_a7 <= mul_a6; mul_b7 <= mul_b6; |
mul_a8 <= mul_a7; mul_b8 <= mul_b7; |
product_a <= mul_a[23:0] * mul_b[16:0]; product_a_2 <= product_a[16:0]; |
product_a_3 <= product_a_2; product_a_4 <= product_a_3; product_a_5 <= product_a_4; |
product_a_6 <= product_a_5; product_a_7 <= product_a_6; product_a_8 <= product_a_7; |
product_a_9 <= product_a_8; product_a_10 <= product_a_9; |
product_b <= mul_a[23:0] * mul_b[33:17]; |
product_c <= mul_a2[23:0] * mul_b2[50:34]; |
product_d <= mul_a5[23:0] * mul_b5[52:51]; |
product_e <= mul_a1[40:24] * mul_b1[16:0]; |
product_f <= mul_a4[40:24] * mul_b4[33:17]; |
product_g <= mul_a7[40:24] * mul_b7[52:34]; |
product_h <= mul_a3[52:41] * mul_b3[16:0]; |
product_i <= mul_a6[52:41] * mul_b6[33:17]; |
product_j <= mul_a8[52:41] * mul_b8[52:34]; |
sum_0 <= product_a[40:17] + product_b; sum_0_2 <= sum_0[6:0]; sum_0_3 <= sum_0_2; |
sum_0_4 <= sum_0_3; sum_0_5 <= sum_0_4; sum_0_6 <= sum_0_5; sum_0_7 <= sum_0_6; |
sum_0_8 <= sum_0_7; sum_0_9 <= sum_0_8; |
sum_1 <= sum_0[41:7] + product_e; sum_1_2 <= sum_1[9:0]; sum_1_3 <= sum_1_2; |
sum_1_4 <= sum_1_3; sum_1_5 <= sum_1_4; sum_1_6 <= sum_1_5; sum_1_7 <= sum_1_6; |
sum_1_8 <= sum_1_7; |
sum_2 <= sum_1[35:10] + product_c; sum_2_2 <= sum_2[6:0]; sum_2_3 <= sum_2_2; |
sum_2_4 <= sum_2_3; sum_2_5 <= sum_2_4; sum_2_6 <= sum_2_5; sum_2_7 <= sum_2_6; |
sum_3 <= sum_2[41:7] + product_h; |
sum_4 <= sum_3 + product_f; sum_4_2 <= sum_4[9:0]; sum_4_3 <= sum_4_2; |
sum_4_4 <= sum_4_3; sum_4_5 <= sum_4_4; |
sum_5 <= sum_4[36:10] + product_d; sum_5_2 <= sum_5[6:0]; |
sum_5_3 <= sum_5_2; sum_5_4 <= sum_5_3; |
sum_6 <= sum_5[27:7] + product_i; |
sum_7 <= sum_6 + product_g; sum_7_2 <= sum_7[16:0]; |
sum_8 <= sum_7[36:17] + product_j; |
product <= { sum_8, sum_7_2[16:0], sum_5_4[6:0], sum_4_5[9:0], sum_2_7[6:0], |
sum_1_8[9:0], sum_0_9[6:0], product_a_10[16:0] }; |
product_1 <= product << product_shift; |
product_2 <= product_1[105:53]; product_3 <= product_2; |
product_4 <= set_mantissa_zero ? 54'b0 : { 1'b0, product_3}; |
product_shift <= !sum_8[30]; |
round_nearest_mode <= rm_15 == 2'b00; |
round_posinf_mode <= rm_15 == 2'b10; |
round_neginf_mode <= rm_15 == 2'b11; |
round_nearest_trigger <= product_1[52]; |
round_nearest_exception <= !(|product_1[51:0]) & (product_1[53] == 0); |
round_nearest_enable <= round_nearest_mode & round_nearest_trigger & !round_nearest_exception; |
round_posinf_trigger <= |product_1[52:0] & !sign_15; |
round_posinf_enable <= round_posinf_mode & round_posinf_trigger; |
round_neginf_trigger <= |product_1[52:0] & sign_15; |
round_neginf_enable <= round_neginf_mode & round_neginf_trigger; |
round_enable <= round_posinf_enable | round_neginf_enable | round_nearest_enable; |
product_5 <= round_enable & !set_mz_1 ? product_4 + 1 : product_4; |
product_overflow <= product_5[53]; |
product_6 <= product_5; |
product_7 <= product_overflow ? product_6 >> 1 : product_6; |
exponent_7 <= exponent_6; exponent_8 <= exponent_7; |
exponent_9 <= product_overflow ? exponent_8 + 1 : exponent_8; |
end |
end |
|
always @(posedge clk) |
begin |
if (rst) begin |
ready <= 0; |
count_ready_0 <= 0; |
count_ready <= 0; |
end |
else if (enable) begin |
ready <= count_ready; |
count_ready_0 <= count == 18; |
count_ready <= count == 19; |
end |
end |
|
always @(posedge clk) |
begin |
if (rst) |
count <= 0; |
else if (enable & !count_ready_0 & !count_ready) |
count <= count + 1; |
end |
|
endmodule |
/tags/arelease/Double_FPU.PDF
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
tags/arelease/Double_FPU.PDF
Property changes :
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: tags/arelease/fpu_exceptions.v
===================================================================
--- tags/arelease/fpu_exceptions.v (nonexistent)
+++ tags/arelease/fpu_exceptions.v (revision 12)
@@ -0,0 +1,280 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// FPU ////
+//// Floating Point Unit (Double precision) ////
+//// ////
+//// Author: David Lundgren ////
+//// davidklun@gmail.com ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2009 David Lundgren ////
+//// davidklun@gmail.com ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer.////
+//// ////
+//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
+//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
+//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
+//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
+//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
+//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
+//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
+//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
+//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
+//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
+//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
+//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
+//// POSSIBILITY OF SUCH DAMAGE. ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+
+
+`timescale 1ns / 100ps
+
+module fpu_exceptions( clk, rst, enable, rmode, opa, opb, in_except,
+exponent_in, mantissa_in, fpu_op, out, ex_enable, underflow, overflow,
+inexact, exception, invalid);
+input clk;
+input rst;
+input enable;
+input [1:0] rmode;
+input [63:0] opa;
+input [63:0] opb;
+input [63:0] in_except;
+input [11:0] exponent_in;
+input [1:0] mantissa_in;
+input [2:0] fpu_op;
+output [63:0] out;
+output ex_enable;
+output underflow;
+output overflow;
+output inexact;
+output exception;
+output invalid;
+
+reg [63:0] out;
+reg ex_enable;
+reg underflow;
+reg overflow;
+reg inexact;
+reg exception;
+reg invalid;
+
+reg in_et_zero;
+reg opa_et_zero;
+reg opb_et_zero;
+reg input_et_zero;
+reg add;
+reg subtract;
+reg multiply;
+reg divide;
+reg opa_QNaN;
+reg opb_QNaN;
+reg opa_SNaN;
+reg opb_SNaN;
+reg opa_pos_inf;
+reg opb_pos_inf;
+reg opa_neg_inf;
+reg opb_neg_inf;
+reg opa_inf;
+reg opb_inf;
+reg NaN_input;
+reg SNaN_input;
+reg a_NaN;
+reg div_by_0;
+reg div_0_by_0;
+reg div_inf_by_inf;
+reg div_by_inf;
+reg mul_0_by_inf;
+reg mul_inf;
+reg div_inf;
+reg add_inf;
+reg sub_inf;
+reg addsub_inf_invalid;
+reg addsub_inf;
+reg out_inf_trigger;
+reg out_pos_inf;
+reg out_neg_inf;
+reg round_nearest;
+reg round_to_zero;
+reg round_to_pos_inf;
+reg round_to_neg_inf;
+reg inf_round_down_trigger;
+reg mul_uf;
+reg div_uf;
+reg underflow_trigger;
+reg invalid_trigger;
+reg overflow_trigger;
+reg inexact_trigger;
+reg except_trigger;
+reg enable_trigger;
+reg NaN_out_trigger;
+reg SNaN_trigger;
+
+
+wire [10:0] exp_2047 = 11'b11111111111;
+wire [10:0] exp_2046 = 11'b11111111110;
+reg [62:0] NaN_output_0;
+reg [62:0] NaN_output;
+wire [51:0] mantissa_max = 52'b1111111111111111111111111111111111111111111111111111;
+reg [62:0] inf_round_down;
+reg [62:0] out_inf;
+reg [63:0] out_0;
+reg [63:0] out_1;
+reg [63:0] out_2;
+
+always @(posedge clk)
+begin
+ if (rst) begin
+ in_et_zero <= 0;
+ opa_et_zero <= 0;
+ opb_et_zero <= 0;
+ input_et_zero <= 0;
+ add <= 0;
+ subtract <= 0;
+ multiply <= 0;
+ divide <= 0;
+ opa_QNaN <= 0;
+ opb_QNaN <= 0;
+ opa_SNaN <= 0;
+ opb_SNaN <= 0;
+ opa_pos_inf <= 0;
+ opb_pos_inf <= 0;
+ opa_neg_inf <= 0;
+ opb_neg_inf <= 0;
+ opa_inf <= 0;
+ opb_inf <= 0;
+ NaN_input <= 0;
+ SNaN_input <= 0;
+ a_NaN <= 0;
+ div_by_0 <= 0;
+ div_0_by_0 <= 0;
+ div_inf_by_inf <= 0;
+ div_by_inf <= 0;
+ mul_0_by_inf <= 0;
+ mul_inf <= 0;
+ div_inf <= 0;
+ add_inf <= 0;
+ sub_inf <= 0;
+ addsub_inf_invalid <= 0;
+ addsub_inf <= 0;
+ out_inf_trigger <= 0;
+ out_pos_inf <= 0;
+ out_neg_inf <= 0;
+ round_nearest <= 0;
+ round_to_zero <= 0;
+ round_to_pos_inf <= 0;
+ round_to_neg_inf <= 0;
+ inf_round_down_trigger <= 0;
+ mul_uf <= 0;
+ div_uf <= 0;
+ underflow_trigger <= 0;
+ invalid_trigger <= 0;
+ overflow_trigger <= 0;
+ inexact_trigger <= 0;
+ except_trigger <= 0;
+ enable_trigger <= 0;
+ NaN_out_trigger <= 0;
+ SNaN_trigger <= 0;
+ NaN_output_0 <= 0;
+ NaN_output <= 0;
+ inf_round_down <= 0;
+ out_inf <= 0;
+ out_0 <= 0;
+ out_1 <= 0;
+ out_2 <= 0;
+ end
+ else if (enable) begin
+ in_et_zero <= !(|in_except[62:0]);
+ opa_et_zero <= !(|opa[62:0]);
+ opb_et_zero <= !(|opb[62:0]);
+ input_et_zero <= !(|in_except[62:0]);
+ add <= fpu_op == 3'b000;
+ subtract <= fpu_op == 3'b001;
+ multiply <= fpu_op == 3'b010;
+ divide <= fpu_op == 3'b011;
+ opa_QNaN <= (opa[62:52] == 2047) & |opa[51:0] & opa[51];
+ opb_QNaN <= (opb[62:52] == 2047) & |opb[51:0] & opb[51];
+ opa_SNaN <= (opa[62:52] == 2047) & |opa[51:0] & !opa[51];
+ opb_SNaN <= (opb[62:52] == 2047) & |opb[51:0] & !opb[51];
+ opa_pos_inf <= !opa[63] & (opa[62:52] == 2047) & !(|opa[51:0]);
+ opb_pos_inf <= !opb[63] & (opb[62:52] == 2047) & !(|opb[51:0]);
+ opa_neg_inf <= opa[63] & (opa[62:52] == 2047) & !(|opa[51:0]);
+ opb_neg_inf <= opb[63] & (opb[62:52] == 2047) & !(|opb[51:0]);
+ opa_inf <= (opa[62:52] == 2047) & !(|opa[51:0]);
+ opb_inf <= (opb[62:52] == 2047) & !(|opb[51:0]);
+ NaN_input <= opa_QNaN | opb_QNaN | opa_SNaN | opb_SNaN;
+ SNaN_input <= opa_SNaN | opb_SNaN;
+ a_NaN <= opa_QNaN | opa_SNaN;
+ div_by_0 <= divide & opb_et_zero & !opa_et_zero;
+ div_0_by_0 <= divide & opb_et_zero & opa_et_zero;
+ div_inf_by_inf <= divide & opa_inf & opb_inf;
+ div_by_inf <= divide & !opa_inf & opb_inf;
+ mul_0_by_inf <= multiply & ((opa_inf & opb_et_zero) | (opa_et_zero & opb_inf));
+ mul_inf <= multiply & (opa_inf | opb_inf) & !mul_0_by_inf;
+ div_inf <= divide & opa_inf & !opb_inf;
+ add_inf <= (add & (opa_inf | opb_inf));
+ sub_inf <= (subtract & (opa_inf | opb_inf));
+ addsub_inf_invalid <= (add & opa_pos_inf & opb_neg_inf) | (add & opa_neg_inf & opb_pos_inf) |
+ (subtract & opa_pos_inf & opb_pos_inf) | (subtract & opa_neg_inf & opb_neg_inf);
+ addsub_inf <= (add_inf | sub_inf) & !addsub_inf_invalid;
+ out_inf_trigger <= addsub_inf | mul_inf | div_inf | div_by_0 | (exponent_in > 2046);
+ out_pos_inf <= out_inf_trigger & !in_except[63];
+ out_neg_inf <= out_inf_trigger & in_except[63];
+ round_nearest <= (rmode == 2'b00);
+ round_to_zero <= (rmode == 2'b01);
+ round_to_pos_inf <= (rmode == 2'b10);
+ round_to_neg_inf <= (rmode == 2'b11);
+ inf_round_down_trigger <= (out_pos_inf & round_to_neg_inf) |
+ (out_neg_inf & round_to_pos_inf) |
+ (out_inf_trigger & round_to_zero);
+ mul_uf <= multiply & !opa_et_zero & !opb_et_zero & in_et_zero;
+ div_uf <= divide & !opa_et_zero & in_et_zero;
+ underflow_trigger <= div_by_inf | mul_uf | div_uf;
+ invalid_trigger <= SNaN_input | addsub_inf_invalid | mul_0_by_inf |
+ div_0_by_0 | div_inf_by_inf;
+ overflow_trigger <= out_inf_trigger & !NaN_input;
+ inexact_trigger <= (|mantissa_in[1:0] | out_inf_trigger | underflow_trigger) &
+ !NaN_input;
+ except_trigger <= invalid_trigger | overflow_trigger | underflow_trigger |
+ inexact_trigger;
+ enable_trigger <= except_trigger | out_inf_trigger | NaN_input;
+ NaN_out_trigger <= NaN_input | invalid_trigger;
+ SNaN_trigger <= invalid_trigger & !SNaN_input;
+ NaN_output_0 <= a_NaN ? { exp_2047, 1'b1, opa[50:0]} : { exp_2047, 1'b1, opb[50:0]};
+ NaN_output <= SNaN_trigger ? { exp_2047, 2'b01, opa[49:0]} : NaN_output_0;
+ inf_round_down <= { exp_2046, mantissa_max };
+ out_inf <= inf_round_down_trigger ? inf_round_down : { exp_2047, 52'b0 };
+ out_0 <= underflow_trigger ? { in_except[63], 63'b0 } : in_except;
+ out_1 <= out_inf_trigger ? { in_except[63], out_inf } : out_0;
+ out_2 <= NaN_out_trigger ? { in_except[63], NaN_output} : out_1;
+ end
+end
+
+always @(posedge clk)
+begin
+ if (rst) begin
+ ex_enable <= 0;
+ underflow <= 0;
+ overflow <= 0;
+ inexact <= 0;
+ exception <= 0;
+ invalid <= 0;
+ out <= 0;
+ end
+ else if (enable) begin
+ ex_enable <= enable_trigger;
+ underflow <= underflow_trigger;
+ overflow <= overflow_trigger;
+ inexact <= inexact_trigger;
+ exception <= except_trigger;
+ invalid <= invalid_trigger;
+ out <= out_2;
+ end
+end
+
+endmodule
Index: tags/arelease/fpu_TB.v
===================================================================
--- tags/arelease/fpu_TB.v (nonexistent)
+++ tags/arelease/fpu_TB.v (revision 12)
@@ -0,0 +1,845 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// FPU ////
+//// Floating Point Unit (Double precision) ////
+//// ////
+//// Author: David Lundgren ////
+//// davidklun@gmail.com ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2009 David Lundgren ////
+//// davidklun@gmail.com ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer.////
+//// ////
+//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
+//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
+//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
+//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
+//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
+//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
+//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
+//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
+//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
+//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
+//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
+//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
+//// POSSIBILITY OF SUCH DAMAGE. ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+
+`timescale 1ps / 1ps
+
+module fpu_tb;
+
+reg clk;
+reg rst;
+reg enable;
+reg [1:0]rmode;
+reg [2:0]fpu_op;
+reg [63:0]opa;
+reg [63:0]opb;
+wire [63:0]out;
+wire ready;
+wire underflow;
+wire overflow;
+wire inexact;
+wire exception;
+wire invalid;
+
+reg [6:0] count;
+
+
+ fpu UUT (
+ .clk(clk),
+ .rst(rst),
+ .enable(enable),
+ .rmode(rmode),
+ .fpu_op(fpu_op),
+ .opa(opa),
+ .opb(opb),
+ .out(out),
+ .ready(ready),
+ .underflow(underflow),
+ .overflow(overflow),
+ .inexact(inexact),
+ .exception(exception),
+ .invalid(invalid));
+
+
+initial
+begin : STIMUL
+ #0
+ count = 0;
+ rst = 1'b1;
+ #20000;
+ rst = 1'b0; // paste after this
+//inputA:1.6999999999e-314
+//inputB:4.0000000000e-300
+enable = 1'b1;
+opa = 64'b0000000000000000000000000000000011001101000101110000011010100010;
+opb = 64'b0000000111000101011011100001111111000010111110001111001101011001;
+fpu_op = 3'b011;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:4.249999999722977e-015
+if (out==64'h3CF323EA98D06FB6)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:3.0000000000e-290
+//inputB:3.0000000000e-021
+enable = 1'b1;
+opa = 64'b0000001111010010101101100000010001001001010000101111100001010101;
+opb = 64'b0011101110101100010101011000111000001111000101011110100011110111;
+fpu_op = 3'b010;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:9.000000000000022e-311
+if (out==64'h000010914A4C025A)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:4.6500000000e+002
+//inputB:6.5000000000e+001
+enable = 1'b1;
+opa = 64'b0100000001111101000100000000000000000000000000000000000000000000;
+opb = 64'b0100000001010000010000000000000000000000000000000000000000000000;
+fpu_op = 3'b001;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:4.000000000000000e+002
+if (out==64'h4079000000000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:2.2700000000e-001
+//inputB:3.4000000000e+001
+enable = 1'b1;
+opa = 64'b0011111111001101000011100101011000000100000110001001001101110101;
+opb = 64'b0100000001000001000000000000000000000000000000000000000000000000;
+fpu_op = 3'b000;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:3.422700000000000e+001
+if (out==64'h40411D0E56041894)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:2.2300000000e+002
+//inputB:5.6000000000e+001
+enable = 1'b1;
+opa = 64'b0100000001101011111000000000000000000000000000000000000000000000;
+opb = 64'b0100000001001100000000000000000000000000000000000000000000000000;
+fpu_op = 3'b011;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:3.982142857142857e+000
+if (out==64'h400FDB6DB6DB6DB7)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-9.5000000000e+001
+//inputB:2.0000000000e+002
+enable = 1'b1;
+opa = 64'b1100000001010111110000000000000000000000000000000000000000000000;
+opb = 64'b0100000001101001000000000000000000000000000000000000000000000000;
+fpu_op = 3'b010;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-1.900000000000000e+004
+if (out==64'hC0D28E0000000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-4.5000000000e+001
+//inputB:-3.2000000000e+001
+enable = 1'b1;
+opa = 64'b1100000001000110100000000000000000000000000000000000000000000000;
+opb = 64'b1100000001000000000000000000000000000000000000000000000000000000;
+fpu_op = 3'b001;
+rmode = 2'b11;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-1.300000000000000e+001
+if (out==64'hC02A000000000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-9.0300000000e+002
+//inputB:2.1000000000e+001
+enable = 1'b1;
+opa = 64'b1100000010001100001110000000000000000000000000000000000000000000;
+opb = 64'b0100000000110101000000000000000000000000000000000000000000000000;
+fpu_op = 3'b000;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-8.820000000000000e+002
+if (out==64'hC08B900000000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:4.5500000000e+002
+//inputB:-4.5900000000e+002
+enable = 1'b1;
+opa = 64'b0100000001111100011100000000000000000000000000000000000000000000;
+opb = 64'b1100000001111100101100000000000000000000000000000000000000000000;
+fpu_op = 3'b011;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-9.912854030501089e-001
+if (out==64'hBFEFB89C2A6346D5)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:2.3577000000e+002
+//inputB:2.0000000000e-002
+enable = 1'b1;
+opa = 64'b0100000001101101011110001010001111010111000010100011110101110001;
+opb = 64'b0011111110010100011110101110000101000111101011100001010001111011;
+fpu_op = 3'b010;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:4.715400000000001e+000
+if (out==64'h4012DC91D14E3BCE)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:4.0195000000e+002
+//inputB:-3.3600000000e+001
+enable = 1'b1;
+opa = 64'b0100000001111001000111110011001100110011001100110011001100110011;
+opb = 64'b1100000001000000110011001100110011001100110011001100110011001101;
+fpu_op = 3'b001;
+rmode = 2'b11;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:4.355500000000000e+002
+if (out==64'h407B38CCCCCCCCCC)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-1.0000000000e-309
+//inputB:1.1000000000e-309
+enable = 1'b1;
+opa = 64'b1000000000000000101110000001010101110010011010001111110110101110;
+opb = 64'b0000000000000000110010100111110111111101110110011110001111011001;
+fpu_op = 3'b000;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:9.999999999999969e-311
+if (out==64'h000012688B70E62B)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:4.0000000000e-200
+//inputB:2.0000000000e+002
+enable = 1'b1;
+opa = 64'b0001011010001000011111101001001000010101010011101111011110101100;
+opb = 64'b0100000001101001000000000000000000000000000000000000000000000000;
+fpu_op = 3'b011;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:2.000000000000000e-202
+if (out==64'h160F5A549627A36C)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:4.0000000000e+020
+//inputB:2.0000000000e+002
+enable = 1'b1;
+opa = 64'b0100010000110101101011110001110101111000101101011000110001000000;
+opb = 64'b0100000001101001000000000000000000000000000000000000000000000000;
+fpu_op = 3'b011;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:2.000000000000000e+018
+if (out==64'h43BBC16D674EC800)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:5.0000000000e+000
+//inputB:2.5000000000e+000
+enable = 1'b1;
+opa = 64'b0100000000010100000000000000000000000000000000000000000000000000;
+opb = 64'b0100000000000100000000000000000000000000000000000000000000000000;
+fpu_op = 3'b011;
+rmode = 2'b11;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:2.000000000000000e+000
+if (out==64'h4000000000000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:1.0000000000e-312
+//inputB:1.0000000000e+000
+enable = 1'b1;
+opa = 64'b0000000000000000000000000010111100100000000111010100100111111011;
+opb = 64'b0011111111110000000000000000000000000000000000000000000000000000;
+fpu_op = 3'b011;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:9.999999999984653e-313
+if (out==64'h0000002F201D49FB)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:4.8999000000e+004
+//inputB:2.3600000000e+001
+enable = 1'b1;
+opa = 64'b0100000011100111111011001110000000000000000000000000000000000000;
+opb = 64'b0100000000110111100110011001100110011001100110011001100110011010;
+fpu_op = 3'b001;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:4.897540000000000e+004
+if (out==64'h40E7E9ECCCCCCCCD)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:4.0000000000e-200
+//inputB:3.0000000000e+111
+enable = 1'b1;
+opa = 64'b0001011010001000011111101001001000010101010011101111011110101100;
+opb = 64'b0101011100010011111101011000110101000011010010100010101110101110;
+fpu_op = 3'b011;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:1.333333333333758e-311
+if (out==64'h0000027456DBDA6D)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:7.0000000000e-310
+//inputB:8.0000000000e-100
+enable = 1'b1;
+opa = 64'b0000000000000000100000001101101111010000000101100100101100101101;
+opb = 64'b0010101101011011111111110010111011100100100011100000010100110000;
+fpu_op = 3'b011;
+rmode = 2'b11;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:8.749999999999972e-211
+if (out==64'h14526914EEBBD470)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:1.4000000000e-311
+//inputB:2.5000000000e-310
+enable = 1'b1;
+opa = 64'b0000000000000000000000101001001111000001100110100000101110111110;
+opb = 64'b0000000000000000001011100000010101011100100110100011111101101011;
+fpu_op = 3'b011;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:5.599999999999383e-002
+if (out==64'h3FACAC083126E600)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-4.0600000000e+001
+//inputB:-3.5700000000e+001
+enable = 1'b1;
+opa = 64'b1100000001000100010011001100110011001100110011001100110011001101;
+opb = 64'b1100000001000001110110011001100110011001100110011001100110011010;
+fpu_op = 3'b000;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-7.630000000000001e+001
+if (out==64'hC053133333333334)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:3.4500000000e+002
+//inputB:-3.4400000000e+002
+enable = 1'b1;
+opa = 64'b0100000001110101100100000000000000000000000000000000000000000000;
+opb = 64'b1100000001110101100000000000000000000000000000000000000000000000;
+fpu_op = 3'b000;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:1.000000000000000e+000
+if (out==64'h3FF0000000000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:2.3770000000e+001
+//inputB:-4.5000000000e+001
+enable = 1'b1;
+opa = 64'b0100000000110111110001010001111010111000010100011110101110000101;
+opb = 64'b1100000001000110100000000000000000000000000000000000000000000000;
+fpu_op = 3'b001;
+rmode = 2'b11;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:6.877000000000000e+001
+if (out==64'h40513147AE147AE1)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-4.7700000000e+002
+//inputB:4.8960000000e+002
+enable = 1'b1;
+opa = 64'b1100000001111101110100000000000000000000000000000000000000000000;
+opb = 64'b0100000001111110100110011001100110011001100110011001100110011010;
+fpu_op = 3'b010;
+rmode = 2'b11;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-2.335392000000000e+005
+if (out==64'hC10C82199999999A)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:2.0000000000e-311
+//inputB:0.0000000000e+000
+enable = 1'b1;
+opa = 64'b0000000000000000000000111010111010000010010010011100011110100010;
+opb = 64'b0000000000000000000000000000000000000000000000000000000000000000;
+fpu_op = 3'b000;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:1.999999999999895e-311
+if (out==64'h000003AE8249C7A2)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:0.0000000000e+000
+//inputB:9.0000000000e+050
+enable = 1'b1;
+opa = 64'b0000000000000000000000000000000000000000000000000000000000000000;
+opb = 64'b0100101010000011001111100111000010011110001011100011000100101101;
+fpu_op = 3'b010;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:0.000000000000000e+000
+if (out==64'h0000000000000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:5.4000000000e+001
+//inputB:0.0000000000e+000
+enable = 1'b1;
+opa = 64'b0100000001001011000000000000000000000000000000000000000000000000;
+opb = 64'b0000000000000000000000000000000000000000000000000000000000000000;
+fpu_op = 3'b000;
+rmode = 2'b11;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:5.400000000000000e+001
+if (out==64'h404B000000000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-6.7000000000e+001
+//inputB:0.0000000000e+000
+enable = 1'b1;
+opa = 64'b1100000001010000110000000000000000000000000000000000000000000000;
+opb = 64'b0000000000000000000000000000000000000000000000000000000000000000;
+fpu_op = 3'b011;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-1.#INF00000000000e+000
+if (out==64'hFFEFFFFFFFFFFFFF)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-4.5600000000e+001
+//inputB:-6.9000000000e+001
+enable = 1'b1;
+opa = 64'b1100000001000110110011001100110011001100110011001100110011001101;
+opb = 64'b1100000001010001010000000000000000000000000000000000000000000000;
+fpu_op = 3'b011;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:6.608695652173914e-001
+if (out==64'h3FE525D7EE30F953)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-5.9900000000e+002
+//inputB:2.7000000000e-002
+enable = 1'b1;
+opa = 64'b1100000010000010101110000000000000000000000000000000000000000000;
+opb = 64'b0011111110011011101001011110001101010011111101111100111011011001;
+fpu_op = 3'b011;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-2.218518518518519e+004
+if (out==64'hC0D5AA4BDA12F685)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:2.1000000000e-308
+//inputB:2.0000000000e-308
+enable = 1'b1;
+opa = 64'b0000000000001111000110011100001001100010100111001100111101010011;
+opb = 64'b0000000000001110011000011010110011110000001100111101000110100100;
+fpu_op = 3'b000;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:4.100000000000000e-308
+if (out==64'h001D7B6F52D0A0F7)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:5.0000000000e-308
+//inputB:2.0000000000e-312
+enable = 1'b1;
+opa = 64'b0000000000100001111110100001100000101100010000001100011000001101;
+opb = 64'b0000000000000000000000000101111001000000001110101001001111110110;
+fpu_op = 3'b000;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:5.000199999999999e-308
+if (out==64'h0021FA474C5E1008)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:3.9800000000e+000
+//inputB:3.7700000000e+000
+enable = 1'b1;
+opa = 64'b0100000000001111110101110000101000111101011100001010001111010111;
+opb = 64'b0100000000001110001010001111010111000010100011110101110000101001;
+fpu_op = 3'b000;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:7.750000000000000e+000
+if (out==64'h401F000000000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:4.4000000000e+001
+//inputB:7.9000000000e-002
+enable = 1'b1;
+opa = 64'b0100000001000110000000000000000000000000000000000000000000000000;
+opb = 64'b0011111110110100001110010101100000010000011000100100110111010011;
+fpu_op = 3'b000;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:4.407900000000000e+001
+if (out==64'h40460A1CAC083127)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:5.0000000000e-311
+//inputB:9.0000000000e+009
+enable = 1'b1;
+opa = 64'b0000000000000000000010010011010001000101101110000111001100010101;
+opb = 64'b0100001000000000110000111000100011010000000000000000000000000000;
+fpu_op = 3'b010;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:4.499999999999764e-301
+if (out==64'h01934982FC467380)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-4.0000000000e-305
+//inputB:2.0000000000e-008
+enable = 1'b1;
+opa = 64'b1000000010111100000101101100010111000101001001010011010101110101;
+opb = 64'b0011111001010101011110011000111011100010001100001000110000111010;
+fpu_op = 3'b010;
+rmode = 2'b11;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-8.000000000007485e-313
+if (out==64'h80000025B34AA196)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:3.0000000000e-308
+//inputB:1.0000000000e-012
+enable = 1'b1;
+opa = 64'b0000000000010101100100101000001101101000010011011011101001110111;
+opb = 64'b0011110101110001100101111001100110000001001011011110101000010001;
+fpu_op = 3'b010;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:2.999966601548049e-320
+if (out==64'h00000000000017B8)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:5.6999990000e+006
+//inputB:5.6999989900e+006
+enable = 1'b1;
+opa = 64'b0100000101010101101111100110011111000000000000000000000000000000;
+opb = 64'b0100000101010101101111100110011110111111010111000010100011110110;
+fpu_op = 3'b001;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:9.999999776482582e-003
+if (out==64'h3F847AE140000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-4.0000000000e+000
+//inputB:9.0000000000e+000
+enable = 1'b1;
+opa = 64'b1100000000010000000000000000000000000000000000000000000000000000;
+opb = 64'b0100000000100010000000000000000000000000000000000000000000000000;
+fpu_op = 3'b001;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-1.300000000000000e+001
+if (out==64'hC02A000000000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:3.9700000000e+001
+//inputB:2.5700000000e-002
+enable = 1'b1;
+opa = 64'b0100000001000011110110011001100110011001100110011001100110011010;
+opb = 64'b0011111110011010010100010001100111001110000001110101111101110000;
+fpu_op = 3'b001;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:3.967430000000001e+001
+if (out==64'h4043D64F765FD8AF)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:2.3000000000e+000
+//inputB:7.0000000000e-002
+enable = 1'b1;
+opa = 64'b0100000000000010011001100110011001100110011001100110011001100110;
+opb = 64'b0011111110110001111010111000010100011110101110000101000111101100;
+fpu_op = 3'b001;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:2.230000000000000e+000
+if (out==64'h4001D70A3D70A3D7)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:1.9999999673e-316
+//inputB:1.9999999673e-317
+enable = 1'b1;
+opa = 64'b0000000000000000000000000000000000000010011010011010111011000010;
+opb = 64'b0000000000000000000000000000000000000000001111011100010010101101;
+fpu_op = 3'b001;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:1.799999970587486e-316
+if (out==64'h00000000022BEA15)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:1.9999999970e-315
+//inputB:-1.9999999673e-316
+enable = 1'b1;
+opa = 64'b0000000000000000000000000000000000011000001000001101001110011010;
+opb = 64'b1000000000000000000000000000000000000010011010011010111011000010;
+fpu_op = 3'b001;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:2.199999993695311e-315
+if (out==64'h000000001A8A825C)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:4.0000000000e+000
+//inputB:1.0000000000e-025
+enable = 1'b1;
+opa = 64'b0100000000010000000000000000000000000000000000000000000000000000;
+opb = 64'b0011101010111110111100101101000011110101110110100111110111011001;
+fpu_op = 3'b001;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:4.000000000000000e+000
+if (out==64'h4010000000000000)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:3.0000000000e-310
+//inputB:4.0000000000e-304
+enable = 1'b1;
+opa = 64'b0000000000000000001101110011100110100010010100101011001010000001;
+opb = 64'b0000000011110001100011100011101110011011001101110100000101101001;
+fpu_op = 3'b000;
+rmode = 2'b10;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:4.000003000000000e-304
+if (out==64'h00F18E3C781DCAB4)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:3.5000000000e-313
+//inputB:7.0000000000e+004
+enable = 1'b1;
+opa = 64'b0000000000000000000000000001000001111110011100001010011010110001;
+opb = 64'b0100000011110001000101110000000000000000000000000000000000000000;
+fpu_op = 3'b011;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:4.999998683134458e-318
+if (out==64'h00000000000F712B)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-5.1000000000e-306
+//inputB:2.0480000000e+003
+enable = 1'b1;
+opa = 64'b1000000010001100101001101001011010000110100001110011101110100101;
+opb = 64'b0100000010100000000000000000000000000000000000000000000000000000;
+fpu_op = 3'b011;
+rmode = 2'b11;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-2.490234375000003e-309
+if (out==64'h8001CA69686873BB)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-1.5000000000e-305
+//inputB:1.0240000000e+003
+enable = 1'b1;
+opa = 64'b1000000010100101000100010001010001010011110110111110100000011000;
+opb = 64'b0100000010010000000000000000000000000000000000000000000000000000;
+fpu_op = 3'b011;
+rmode = 2'b11;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:-1.464843750000000e-308
+if (out==64'h800A888A29EDF40C)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:-3.4000000000e+056
+//inputB:-4.0000000000e+199
+enable = 1'b1;
+opa = 64'b1100101110101011101110111000100000000000101110111001110000000101;
+opb = 64'b1110100101100000101110001110000010101100101011000100111010101111;
+fpu_op = 3'b011;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:8.500000000000000e-144
+if (out==64'h223A88ECC2AC8317)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+//inputA:1.3559000000e-001
+//inputB:2.3111240000e+003
+enable = 1'b1;
+opa = 64'b0011111111000001010110110000001101011011110101010001001011101100;
+opb = 64'b0100000010100010000011100011111101111100111011011001000101101000;
+fpu_op = 3'b011;
+rmode = 2'b00;
+#20000;
+enable = 1'b0;
+#800000;
+//Output:5.866842281071894e-005
+if (out==64'h3F0EC257A882625F)
+ $display($time,"ps Answer is correct %h", out);
+else
+ $display($time,"ps Error! out is incorrect %h", out);
+
+// end of paste
+$finish;
+end
+
+always
+begin : CLOCK_clk
+
+ clk = 1'b0;
+ #5000;
+ clk = 1'b1;
+ #5000;
+end
+
+endmodule
Index: tags/arelease/fpu_round.v
===================================================================
--- tags/arelease/fpu_round.v (nonexistent)
+++ tags/arelease/fpu_round.v (revision 12)
@@ -0,0 +1,92 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// FPU ////
+//// Floating Point Unit (Double precision) ////
+//// ////
+//// Author: David Lundgren ////
+//// davidklun@gmail.com ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2009 David Lundgren ////
+//// davidklun@gmail.com ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer.////
+//// ////
+//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
+//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
+//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
+//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
+//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
+//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
+//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
+//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
+//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
+//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
+//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
+//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
+//// POSSIBILITY OF SUCH DAMAGE. ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+
+
+`timescale 1ns / 100ps
+
+module fpu_round( clk, rst, enable, round_mode, sign_term,
+mantissa_term, exponent_term, round_out, exponent_final);
+input clk;
+input rst;
+input enable;
+input [1:0] round_mode;
+input sign_term;
+input [55:0] mantissa_term;
+input [11:0] exponent_term;
+output [63:0] round_out;
+output [11:0] exponent_final;
+
+wire [55:0] rounding_amount = { 53'b0, 1'b1, 2'b0};
+wire round_nearest = (round_mode == 2'b00);
+wire round_to_zero = (round_mode == 2'b01);
+wire round_to_pos_inf = (round_mode == 2'b10);
+wire round_to_neg_inf = (round_mode == 2'b11);
+wire round_nearest_trigger = round_nearest & mantissa_term[1];
+wire round_to_pos_inf_trigger = !sign_term & |mantissa_term[1:0];
+wire round_to_neg_inf_trigger = sign_term & |mantissa_term[1:0];
+wire round_trigger = ( round_nearest & round_nearest_trigger)
+ | (round_to_pos_inf & round_to_pos_inf_trigger)
+ | (round_to_neg_inf & round_to_neg_inf_trigger);
+
+
+reg [55:0] sum_round;
+wire sum_round_overflow = sum_round[55];
+ // will be 0 if no carry, 1 if overflow from the rounding unit
+ // overflow from rounding is extremely rare, but possible
+reg [55:0] sum_round_2;
+reg [11:0] exponent_round;
+reg [55:0] sum_final;
+reg [11:0] exponent_final;
+reg [63:0] round_out;
+
+always @(posedge clk)
+ begin
+ if (rst) begin
+ sum_round <= 0;
+ sum_round_2 <= 0;
+ exponent_round <= 0;
+ sum_final <= 0;
+ exponent_final <= 0;
+ round_out <= 0;
+ end
+ else begin
+ sum_round <= rounding_amount + mantissa_term;
+ sum_round_2 <= sum_round_overflow ? sum_round >> 1 : sum_round;
+ exponent_round <= sum_round_overflow ? (exponent_term + 1) : exponent_term;
+ sum_final <= round_trigger ? sum_round_2 : mantissa_term;
+ exponent_final <= round_trigger ? exponent_round : exponent_term;
+ round_out <= { sign_term, exponent_final[10:0], sum_final[53:2] };
+ end
+ end
+endmodule
\ No newline at end of file
Index: tags/arelease/fpu_add.v
===================================================================
--- tags/arelease/fpu_add.v (nonexistent)
+++ tags/arelease/fpu_add.v (revision 12)
@@ -0,0 +1,130 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// FPU ////
+//// Floating Point Unit (Double precision) ////
+//// ////
+//// Author: David Lundgren ////
+//// davidklun@gmail.com ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2009 David Lundgren ////
+//// davidklun@gmail.com ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer.////
+//// ////
+//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
+//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
+//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
+//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
+//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
+//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
+//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
+//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
+//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
+//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
+//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
+//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
+//// POSSIBILITY OF SUCH DAMAGE. ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+
+`timescale 1ns / 100ps
+
+module fpu_add( clk, rst, enable, opa, opb, sign, sum_2, exponent_2);
+input clk;
+input rst;
+input enable;
+input [63:0] opa, opb;
+output sign;
+output [55:0] sum_2;
+output [10:0] exponent_2;
+
+reg sign;
+reg [10:0] exponent_a;
+reg [10:0] exponent_b;
+reg [51:0] mantissa_a;
+reg [51:0] mantissa_b;
+reg expa_gt_expb;
+reg [10:0] exponent_small;
+reg [10:0] exponent_large;
+reg [51:0] mantissa_small;
+reg [51:0] mantissa_large;
+reg small_is_denorm;
+reg large_is_denorm;
+reg large_norm_small_denorm;
+reg [10:0] exponent_diff;
+reg [55:0] large_add;
+reg [55:0] small_add;
+reg [55:0] small_shift;
+wire small_shift_nonzero = |small_shift[55:0];
+wire small_is_nonzero = (exponent_small > 0) | |mantissa_small[51:0];
+wire small_fraction_enable = small_is_nonzero & !small_shift_nonzero;
+wire [55:0] small_shift_2 = { 55'b0, 1'b1 };
+reg [55:0] small_shift_3;
+reg [55:0] sum;
+wire sum_overflow = sum[55]; // sum[55] will be 0 if there was no carry from adding the 2 numbers
+reg [55:0] sum_2;
+reg [10:0] exponent;
+wire sum_leading_one = sum_2[54]; // this is where the leading one resides, unless denorm
+reg denorm_to_norm;
+reg [10:0] exponent_2;
+
+always @(posedge clk)
+ begin
+ if (rst) begin
+ sign <= 0;
+ exponent_a <= 0;
+ exponent_b <= 0;
+ mantissa_a <= 0;
+ mantissa_b <= 0;
+ expa_gt_expb <= 0;
+ exponent_small <= 0;
+ exponent_large <= 0;
+ mantissa_small <= 0;
+ mantissa_large <= 0;
+ small_is_denorm <= 0;
+ large_is_denorm <= 0;
+ large_norm_small_denorm <= 0;
+ exponent_diff <= 0;
+ large_add <= 0;
+ small_add <= 0;
+ small_shift <= 0;
+ small_shift_3 <= 0;
+ sum <= 0;
+ sum_2 <= 0;
+ exponent <= 0;
+ denorm_to_norm <= 0;
+ exponent_2 <= 0;
+ end
+ else if (enable) begin
+ sign <= opa[63];
+ exponent_a <= opa[62:52];
+ exponent_b <= opb[62:52];
+ mantissa_a <= opa[51:0];
+ mantissa_b <= opb[51:0];
+ expa_gt_expb <= exponent_a > exponent_b;
+ exponent_small <= expa_gt_expb ? exponent_b : exponent_a;
+ exponent_large <= expa_gt_expb ? exponent_a : exponent_b;
+ mantissa_small <= expa_gt_expb ? mantissa_b : mantissa_a;
+ mantissa_large <= expa_gt_expb ? mantissa_a : mantissa_b;
+ small_is_denorm <= !(exponent_small > 0);
+ large_is_denorm <= !(exponent_large > 0);
+ large_norm_small_denorm <= (small_is_denorm && !large_is_denorm);
+ exponent_diff <= exponent_large - exponent_small - large_norm_small_denorm;
+ large_add <= { 1'b0, !large_is_denorm, mantissa_large, 2'b0 };
+ small_add <= { 1'b0, !small_is_denorm, mantissa_small, 2'b0 };
+ small_shift <= small_add >> exponent_diff;
+ small_shift_3 <= small_fraction_enable ? small_shift_2 : small_shift;
+ sum <= large_add + small_shift_3;
+ sum_2 <= sum_overflow ? sum >> 1 : sum;
+ exponent <= sum_overflow ? exponent_large + 1: exponent_large;
+ denorm_to_norm <= sum_leading_one & large_is_denorm;
+ exponent_2 <= denorm_to_norm ? exponent + 1 : exponent;
+ end
+ end
+
+endmodule
Index: tags/arelease/fpu_double.v
===================================================================
--- tags/arelease/fpu_double.v (nonexistent)
+++ tags/arelease/fpu_double.v (revision 12)
@@ -0,0 +1,302 @@
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// FPU ////
+//// Floating Point Unit (Double precision) ////
+//// ////
+//// Author: David Lundgren ////
+//// davidklun@gmail.com ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+//// ////
+//// Copyright (C) 2009 David Lundgren ////
+//// davidklun@gmail.com ////
+//// ////
+//// This source file may be used and distributed without ////
+//// restriction provided that this copyright statement is not ////
+//// removed from the file and that any derivative work contains ////
+//// the original copyright notice and the associated disclaimer.////
+//// ////
+//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
+//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
+//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
+//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
+//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
+//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
+//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
+//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
+//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
+//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
+//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
+//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
+//// POSSIBILITY OF SUCH DAMAGE. ////
+//// ////
+/////////////////////////////////////////////////////////////////////
+
+
+`timescale 1ns / 100ps
+/* FPU Operations (fpu_op):
+========================
+0 = add
+1 = sub
+2 = mul
+3 = div
+
+Rounding Modes (rmode):
+=======================
+0 = round_nearest_even
+1 = round_to_zero
+2 = round_up
+3 = round_down */
+
+module fpu( clk, rst, enable, rmode, fpu_op, opa, opb, out, ready, underflow,
+overflow, inexact, exception, invalid);
+input clk;
+input rst;
+input enable;
+input [1:0] rmode;
+input [2:0] fpu_op;
+input [63:0] opa, opb;
+output [63:0] out;
+output ready;
+output underflow;
+output overflow;
+output inexact;
+output exception;
+output invalid;
+
+reg [63:0] opa_reg;
+reg [63:0] opb_reg;
+reg [2:0] fpu_op_reg;
+reg [1:0] rmode_reg;
+reg enable_reg;
+reg enable_reg_1; // high for one clock cycle
+reg enable_reg_2; // high for one clock cycle
+reg enable_reg_3; // high for two clock cycles
+reg op_enable;
+reg [63:0] out;
+reg [6:0] count_cycles;
+reg [6:0] count_ready;
+wire count_busy = (count_ready <= count_cycles);
+reg ready;
+reg ready_0;
+reg ready_1;
+reg underflow;
+reg overflow;
+reg inexact;
+reg exception;
+reg invalid;
+wire underflow_0;
+wire overflow_0;
+wire inexact_0;
+wire exception_0;
+wire invalid_0;
+
+wire add_enable_0 = (fpu_op_reg == 3'b000) & !(opa_reg[63] ^ opb_reg[63]);
+wire add_enable_1 = (fpu_op_reg == 3'b001) & (opa_reg[63] ^ opb_reg[63]);
+reg add_enable;
+wire sub_enable_0 = (fpu_op_reg == 3'b000) & (opa_reg[63] ^ opb_reg[63]);
+wire sub_enable_1 = (fpu_op_reg == 3'b001) & !(opa_reg[63] ^ opb_reg[63]);
+reg sub_enable;
+reg mul_enable;
+reg div_enable;
+wire [55:0] sum_out;
+wire [55:0] diff_out;
+reg [55:0] addsub_out;
+wire [55:0] mul_out;
+wire [55:0] div_out;
+reg [55:0] mantissa_round;
+wire [10:0] exp_add_out;
+wire [10:0] exp_sub_out;
+wire [11:0] exp_mul_out;
+wire [11:0] exp_div_out;
+reg [11:0] exponent_round;
+reg [11:0] exp_addsub;
+wire [11:0] exponent_post_round;
+wire add_sign;
+wire sub_sign;
+wire mul_sign;
+wire div_sign;
+reg addsub_sign;
+reg sign_round;
+wire [63:0] out_round;
+wire [63:0] out_except;
+
+fpu_add u1(
+ .clk(clk),.rst(rst),.enable(add_enable),.opa(opa_reg),.opb(opb_reg),
+ .sign(add_sign),.sum_2(sum_out),.exponent_2(exp_add_out));
+
+fpu_sub u2(
+ .clk(clk),.rst(rst),.enable(sub_enable),.opa(opa_reg),.opb(opb_reg),
+ .fpu_op(fpu_op_reg),.sign(sub_sign),.diff_2(diff_out),
+ .exponent_2(exp_sub_out));
+
+fpu_mul u3(
+ .clk(clk),.rst(rst),.enable(mul_enable),.opa(opa_reg),.opb(opb_reg),
+ .sign(mul_sign),.product_7(mul_out),.exponent_5(exp_mul_out));
+
+fpu_div u4(
+ .clk(clk),.rst(rst),.enable(div_enable),.opa(opa_reg),.opb(opb_reg),
+ .sign(div_sign),.mantissa_7(div_out),.exponent_out(exp_div_out));
+
+fpu_round u5(.clk(clk),.rst(rst),.enable(op_enable), .round_mode(rmode_reg),
+ .sign_term(sign_round),.mantissa_term(mantissa_round), .exponent_term(exponent_round),
+ .round_out(out_round),.exponent_final(exponent_post_round));
+
+fpu_exceptions u6(.clk(clk),.rst(rst),.enable(op_enable),.rmode(rmode_reg),
+ .opa(opa_reg),.opb(opb_reg),
+ .in_except(out_round), .exponent_in(exponent_post_round),
+ .mantissa_in(mantissa_round[1:0]),.fpu_op(fpu_op_reg),.out(out_except),
+ .ex_enable(except_enable),.underflow(underflow_0),.overflow(overflow_0),
+ .inexact(inexact_0),.exception(exception_0),.invalid(invalid_0));
+
+
+always @(posedge clk)
+begin
+ case (fpu_op_reg)
+ 3'b000: mantissa_round <= addsub_out;
+ 3'b001: mantissa_round <= addsub_out;
+ 3'b010: mantissa_round <= mul_out;
+ 3'b011: mantissa_round <= div_out;
+ default: mantissa_round <= 0;
+ endcase
+end
+
+always @(posedge clk)
+begin
+ case (fpu_op_reg)
+ 3'b000: exponent_round <= exp_addsub;
+ 3'b001: exponent_round <= exp_addsub;
+ 3'b010: exponent_round <= exp_mul_out;
+ 3'b011: exponent_round <= exp_div_out;
+ default: exponent_round <= 0;
+ endcase
+end
+
+always @(posedge clk)
+begin
+ case (fpu_op_reg)
+ 3'b000: sign_round <= addsub_sign;
+ 3'b001: sign_round <= addsub_sign;
+ 3'b010: sign_round <= mul_sign;
+ 3'b011: sign_round <= div_sign;
+ default: sign_round <= 0;
+ endcase
+end
+
+always @(posedge clk)
+begin
+ case (fpu_op_reg)
+ 3'b000: count_cycles <= 20;
+ 3'b001: count_cycles <= 21;
+ 3'b010: count_cycles <= 24;
+ 3'b011: count_cycles <= 71;
+ default: count_cycles <= 0;
+ endcase
+end
+
+always @(posedge clk)
+begin
+ if (rst) begin
+ add_enable <= 0;
+ sub_enable <= 0;
+ mul_enable <= 0;
+ div_enable <= 0;
+ addsub_out <= 0;
+ addsub_sign <= 0;
+ exp_addsub <= 0;
+ end
+ else begin
+ add_enable <= (add_enable_0 | add_enable_1) & op_enable;
+ sub_enable <= (sub_enable_0 | sub_enable_1) & op_enable;
+ mul_enable <= (fpu_op_reg == 3'b010) & op_enable;
+ div_enable <= (fpu_op_reg == 3'b011) & op_enable & enable_reg_3;
+ // div_enable needs to be high for two clock cycles
+ addsub_out <= add_enable ? sum_out : diff_out;
+ addsub_sign <= add_enable ? add_sign : sub_sign;
+ exp_addsub <= add_enable ? { 1'b0, exp_add_out} : { 1'b0, exp_sub_out};
+ end
+end
+
+always @ (posedge clk)
+begin
+ if (rst)
+ count_ready <= 0;
+ else if (enable_reg_1)
+ count_ready <= 0;
+ else if (count_busy)
+ count_ready <= count_ready + 1;
+end
+
+always @(posedge clk)
+begin
+ if (rst) begin
+ enable_reg <= 0;
+ enable_reg_1 <= 0;
+ enable_reg_2 <= 0;
+ enable_reg_3 <= 0;
+ end
+ else begin
+ enable_reg <= enable;
+ enable_reg_1 <= enable & !enable_reg;
+ enable_reg_2 <= enable_reg_1;
+ enable_reg_3 <= enable_reg_1 | enable_reg_2;
+ end
+end
+
+always @(posedge clk)
+begin
+ if (rst) begin
+ opa_reg <= 0;
+ opb_reg <= 0;
+ fpu_op_reg <= 0;
+ rmode_reg <= 0;
+ op_enable <= 0;
+ end
+ else if (enable_reg_1) begin
+ opa_reg <= opa;
+ opb_reg <= opb;
+ fpu_op_reg <= fpu_op;
+ rmode_reg <= rmode;
+ op_enable <= 1;
+ end
+end
+
+always @(posedge clk)
+begin
+ if (rst) begin
+ ready_0 <= 0;
+ ready_1 <= 0;
+ ready <= 0;
+ end
+ else if (enable_reg_1) begin
+ ready_0 <= 0;
+ ready_1 <= 0;
+ ready <= 0;
+ end
+ else begin
+ ready_0 <= !count_busy;
+ ready_1 <= ready_0;
+ ready <= ready_1;
+ end
+end
+
+always @(posedge clk)
+begin
+ if (rst) begin
+ underflow <= 0;
+ overflow <= 0;
+ inexact <= 0;
+ exception <= 0;
+ invalid <= 0;
+ out <= 0;
+ end
+ else if (ready_1) begin
+ underflow <= underflow_0;
+ overflow <= overflow_0;
+ inexact <= inexact_0;
+ exception <= exception_0;
+ invalid <= invalid_0;
+ out <= except_enable ? out_except : out_round;
+ end
+end
+endmodule
Index: tags/arelease/Readme.txt
===================================================================
--- tags/arelease/Readme.txt (nonexistent)
+++ tags/arelease/Readme.txt (revision 12)
@@ -0,0 +1,130 @@
+The following describes the IEEE-Standard-754 compliant, double-precision floating point unit,
+written in Verilog. The module consists of the following files:
+
+1. fpu_double.v (top level)
+2. fpu_add.v
+3. fpu_sub.v
+4. fpu_mul.v
+5. fpu_div.v
+6. fpu_round.v
+7. fpu_exceptions.v
+
+And a testbench file is included, containing 50 test-case operations:
+1. fpu_tb.v
+
+This unit has been extensively simulated, covering all operations, rounding modes, exceptions
+like underflow and overflow, and even the obscure corner cases, like when overflowing from
+denormalized to normalized, and vice-versa.
+
+The floating point unit supports denormalized numbers,
+4 operations (add, subtract, multiply, divide), and 4 rounding
+modes (nearest, zero, + inf, - inf). The unit was synthesized with an
+estimated frequency of 230 MHz, for a Virtex5 target device. The synthesis results
+are below. fpu_double.v is the top-level module, and it contains the input
+and output signals from the unit. The unit was designed to be synchronous with
+one global clock, and all of the registers can be reset with an synchronous global reset.
+When the inputs signals (a and b operands, fpu operation code, rounding mode code) are
+available, set the enable input high, then set it low after 2 clock cycles. When the
+operation is complete and the output is available, the ready signal will go high. To start
+the next operation, set the enable input high.
+
+Each operation takes the following amount of clock cycles to complete:
+1. addition : 20 clock cycles
+2. subtraction: 21 clock cycles
+3. multiplication: 24 clock cycles
+4. division: 71 clock cycles
+
+This is longer than other floating point units, but supporting denormalized numbers
+requires more signals and logic levels to accommodate gradual underflow. The supported
+clock speed of 230 MHz makes up for the large number of clock cycles required for each
+operation to complete. If you have a lower clock speed, the code can be changed to
+reduce the number of registers and latency of each operation. I purposely increased the
+number of logic levels to get the code to synthesize to a faster clock frequency, but of course,
+this led to longer latency. I guess it depends on your application what is more important.
+
+The following output signals are also available: underflow, overflow, inexact, exception,
+and invalid. They are compliant with the IEEE-754 definition of each signal. The unit
+will handle QNaN and SNaN inputs per the standard.
+
+I'm planning on adding more operations, like square root, sin, cos, tan, etc.,
+so check back for updates.
+
+Multiply:
+The multiply module is written specifically for a Virtex5 target device. The DSP48E slices
+can perform a 25-bit by 18-bit Twos-complement multiply (24 by 17 unsigned multiply). I broke up the multiply to
+fit these DSP48E slices. The breakdown is similar to the design in Figure 4-15 of the
+Xilinx User Guide Document, "Virtex-5 FPGA XtremeDSP Design Considerations", also known as UG193.
+You can find this document at xilinx.com by searching for "UG193".
+Depending on your device, the multiply can be changed to match the bit-widths of the available
+multipliers. A total of 9 DSP48E slices are used to do the 53-bit by 53-bit multiply of 2
+floating point numbers.
+
+If you have any questions, please email me at: davidklun@gmail.com
+
+Thanks,
+David Lundgren
+
+-----
+
+Synthesis Results:
+
+
+
+
+Performance Summary
+*******************
+
+
+Worst slack in design: -0.971
+
+ Requested Estimated Requested Estimated Clock Clock
+Starting Clock Frequency Frequency Period Period Slack Type Group
+-----------------------------------------------------------------------------------------------------------
+fpu|clk 300.0 MHz 232.3 MHz 3.333 4.304 -0.971 inferred
+==========================================================================
+
+---------------------------------------
+Resource Usage Report for fpu
+
+Mapping to part: xc5vsx95tff1136-2
+Cell usage:
+DSP48E 9 uses
+FD 5 uses
+FDR 519 uses
+FDRE 3920 uses
+FDRSE 1 use
+GND 6 uses
+LD 6 uses
+MUXCY 35 uses
+MUXCY_L 704 uses
+MUXF7 1 use
+VCC 5 uses
+XORCY 491 uses
+XORCY_L 12 uses
+LUT1 185 uses
+LUT2 725 uses
+LUT3 1523 uses
+LUT4 738 uses
+LUT5 604 uses
+LUT6 2506 uses
+
+I/O ports: 206
+I/O primitives: 205
+IBUF 135 uses
+OBUF 70 uses
+
+BUFGP 1 use
+
+I/O Register bits: 0
+Register bits not including I/Os: 4445 (7%)
+Latch bits not including I/Os: 6 (0%)
+
+Global Clock Buffers: 1 of 32 (3%)
+
+Total load per clock:
+ fpu|clk: 4454
+
+Mapping Summary:
+Total LUTs: 6281 (10%)
+
+