|
@@ -1,26 +1,40 @@
|
|
|
-module fp_product #(parameter N=16, M=4)(input_a, input_b, output_z, clk, reset);
|
|
|
|
|
|
|
+typedef enum logic [1:0]{
|
|
|
|
|
+ flag_none,
|
|
|
|
|
+ flag_nan,
|
|
|
|
|
+ flag_inf,
|
|
|
|
|
+ flag_zero
|
|
|
|
|
+} product_flags;
|
|
|
|
|
+
|
|
|
|
|
+module fp_product #(parameter N=16, M=5)(input_a, input_b, output_z, clk, reset);
|
|
|
|
|
+ localparam K=N-M-1; // Size of mantissa
|
|
|
|
|
+
|
|
|
input logic [N-1:0] input_a, input_b;
|
|
input logic [N-1:0] input_a, input_b;
|
|
|
input logic clk, reset;
|
|
input logic clk, reset;
|
|
|
output logic [N-1:0] output_z;
|
|
output logic [N-1:0] output_z;
|
|
|
|
|
|
|
|
- reg [N-M-3:0] a_m0, b_m0, z_m0; // mantissa
|
|
|
|
|
- reg [N-M-3:0] a_m1, b_m1, z_m1; // mantissa
|
|
|
|
|
- reg [N-M-3:0] a_m2, b_m2, z_m2; // mantissa
|
|
|
|
|
- reg [N-M-3:0] z_m3;
|
|
|
|
|
-
|
|
|
|
|
- reg [M:0] a_e0, b_e0, z_e0; // exponent
|
|
|
|
|
- reg [M:0] a_e1, b_e1, z_e1; // exponent
|
|
|
|
|
- reg [M:0] a_e2, b_e2, z_e2; // exponent
|
|
|
|
|
- reg [M:0] z_e3;
|
|
|
|
|
|
|
+ reg [K-1:0] a_m0, b_m0, z_m1; // mantissa
|
|
|
|
|
+ reg [K-1:0] a_m1, b_m1, z_m2; // mantissa
|
|
|
|
|
+ reg [K-1:0] a_m2, b_m2, z_m3; // mantissa
|
|
|
|
|
+ reg [K-1:0] z_m4;
|
|
|
|
|
|
|
|
- reg a_s0, b_s0, z_s0; // sign
|
|
|
|
|
- reg a_s1, b_s1, z_s1; // sign
|
|
|
|
|
- reg a_s2, b_s2, z_s2; // sign
|
|
|
|
|
- reg z_s3; // sign
|
|
|
|
|
-
|
|
|
|
|
- reg [1:0] flags; // 00 for no flag, 01 for NaN, 10 for infinity, 11 for zero
|
|
|
|
|
- reg [2*(N-M-3):0] product; // For storing the product of the two mantissa
|
|
|
|
|
|
|
+ reg [M:0] a_e0, b_e0, z_e1; // exponent
|
|
|
|
|
+ reg [M:0] a_e1, b_e1, z_e2; // exponent
|
|
|
|
|
+ reg [M:0] a_e2, b_e2, z_e3; // exponent
|
|
|
|
|
+ reg [M:0] z_e4;
|
|
|
|
|
|
|
|
|
|
+ reg a_s0, b_s0, z_s1; // sign
|
|
|
|
|
+ reg a_s1, b_s1, z_s2; // sign
|
|
|
|
|
+ reg a_s2, b_s2, z_s3; // sign
|
|
|
|
|
+ reg z_s4; // sign
|
|
|
|
|
+
|
|
|
|
|
+ product_flags flags1; // 00 for no flag, 01 for NaN, 10 for infinity, 11 for zero
|
|
|
|
|
+ reg [2*K-1:0] z_p3; // For storing the product of the two mantissa
|
|
|
|
|
+
|
|
|
|
|
+ always_comb begin
|
|
|
|
|
+ // Packing the output
|
|
|
|
|
+ output_z = {z_s4, z_e4 + (1<<M), z_m4};
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
always_ff @(posedge clk)
|
|
always_ff @(posedge clk)
|
|
|
begin
|
|
begin
|
|
|
if (~reset)
|
|
if (~reset)
|
|
@@ -43,20 +57,20 @@ module fp_product #(parameter N=16, M=4)(input_a, input_b, output_z, clk, reset)
|
|
|
b_s2 <= b_s1;
|
|
b_s2 <= b_s1;
|
|
|
b_e1 <= b_e0;
|
|
b_e1 <= b_e0;
|
|
|
b_m1 <= b_m0;
|
|
b_m1 <= b_m0;
|
|
|
- z_s1 <= z_s0;
|
|
|
|
|
- z_s3 <= z_s2;
|
|
|
|
|
- z_e3 <= z_e2;
|
|
|
|
|
- z_m1 <= z_m0;
|
|
|
|
|
|
|
+ z_s2 <= z_s1;
|
|
|
|
|
+ z_s4 <= z_s3;
|
|
|
|
|
+ z_e4 <= z_e3;
|
|
|
z_m2 <= z_m1;
|
|
z_m2 <= z_m1;
|
|
|
|
|
+ z_m3 <= z_m2;
|
|
|
|
|
|
|
|
// If input a or input b is NaN then return NaN
|
|
// If input a or input b is NaN then return NaN
|
|
|
if (((a_e0 ==(1<<M)) && (a_m0 != 0)) || ((b_e0 == (1<<M)) && (b_m0 != 0)))
|
|
if (((a_e0 ==(1<<M)) && (a_m0 != 0)) || ((b_e0 == (1<<M)) && (b_m0 != 0)))
|
|
|
begin
|
|
begin
|
|
|
- z_s0 <= 1;
|
|
|
|
|
- z_e0 <= (1 << (M+1)) - 1;
|
|
|
|
|
- z_m0[N-3-M] <= 1;
|
|
|
|
|
- z_m0[N-4-M:0] <= 0;
|
|
|
|
|
- flags <= 2'b01;
|
|
|
|
|
|
|
+ z_s1 <= 1;
|
|
|
|
|
+ z_e1 <= (1 << (M+1)) - 1;
|
|
|
|
|
+ z_m1[K-1] <= 1;
|
|
|
|
|
+ z_m1[K-2:0] <= 0;
|
|
|
|
|
+ flags1 <= flag_nan;
|
|
|
end
|
|
end
|
|
|
// If a is infinity then return infinity
|
|
// If a is infinity then return infinity
|
|
|
else if (a_e0 == (1<<M))
|
|
else if (a_e0 == (1<<M))
|
|
@@ -64,19 +78,19 @@ module fp_product #(parameter N=16, M=4)(input_a, input_b, output_z, clk, reset)
|
|
|
// Unless b is zero, then you return NaN instead
|
|
// Unless b is zero, then you return NaN instead
|
|
|
if (($signed(b_e0) == (-1*((1<<M)-1))) && b_m0 == 0)
|
|
if (($signed(b_e0) == (-1*((1<<M)-1))) && b_m0 == 0)
|
|
|
begin
|
|
begin
|
|
|
- z_s0 <= 1;
|
|
|
|
|
- z_e0 <= (1 << (M+1)) - 1;
|
|
|
|
|
- z_m0[N-3-M] <= 1;
|
|
|
|
|
- z_m0[N-4-M:0] <= 0;
|
|
|
|
|
- flags <= 2'b01;
|
|
|
|
|
|
|
+ z_s1 <= 1;
|
|
|
|
|
+ z_e1 <= (1 << (M+1)) - 1;
|
|
|
|
|
+ z_m1[K-1] <= 1;
|
|
|
|
|
+ z_m1[K-2:0] <= 0;
|
|
|
|
|
+ flags1 <= flag_nan;
|
|
|
end
|
|
end
|
|
|
else
|
|
else
|
|
|
// Returning infinity
|
|
// Returning infinity
|
|
|
begin
|
|
begin
|
|
|
- z_s0 <= a_s0 ^ b_s0;
|
|
|
|
|
- z_e0 <= (1 << (M+1)) - 1;
|
|
|
|
|
- z_m0 <= 0;
|
|
|
|
|
- flags <= 2'b10;
|
|
|
|
|
|
|
+ z_s1 <= a_s0 ^ b_s0;
|
|
|
|
|
+ z_e1 <= (1 << (M+1)) - 1;
|
|
|
|
|
+ z_m1 <= 0;
|
|
|
|
|
+ flags1 <= flag_inf;
|
|
|
end
|
|
end
|
|
|
end
|
|
end
|
|
|
// If b is infinity then return infinity
|
|
// If b is infinity then return infinity
|
|
@@ -85,36 +99,36 @@ module fp_product #(parameter N=16, M=4)(input_a, input_b, output_z, clk, reset)
|
|
|
//Unless a is zero, then return NaN instead
|
|
//Unless a is zero, then return NaN instead
|
|
|
if (($signed(a_e0) == (-1*((1<<M)-1))) && a_m0 == 0)
|
|
if (($signed(a_e0) == (-1*((1<<M)-1))) && a_m0 == 0)
|
|
|
begin
|
|
begin
|
|
|
- z_s0 <= 1;
|
|
|
|
|
- z_e0 <= (1 << (M+1)) - 1;
|
|
|
|
|
- z_m0[N-3-M] <= 1;
|
|
|
|
|
- z_m0[N-4-M:0] <= 0;
|
|
|
|
|
- flags <= 2'b01;
|
|
|
|
|
|
|
+ z_s1 <= 1;
|
|
|
|
|
+ z_e1 <= (1 << (M+1)) - 1;
|
|
|
|
|
+ z_m1[K-1] <= 1;
|
|
|
|
|
+ z_m1[K-2:0] <= 0;
|
|
|
|
|
+ flags1 <= flag_nan;
|
|
|
end
|
|
end
|
|
|
else
|
|
else
|
|
|
// Returning infinity
|
|
// Returning infinity
|
|
|
begin
|
|
begin
|
|
|
- z_s0 <= a_s0 ^ b_s0;
|
|
|
|
|
- z_e0 <= (1 << (M+1)) - 1;
|
|
|
|
|
- z_m0 <= 0;
|
|
|
|
|
- flags <= 2'b10;
|
|
|
|
|
|
|
+ z_s1 <= a_s0 ^ b_s0;
|
|
|
|
|
+ z_e1 <= (1 << (M+1)) - 1;
|
|
|
|
|
+ z_m1 <= 0;
|
|
|
|
|
+ flags1 <= flag_inf;
|
|
|
end
|
|
end
|
|
|
end
|
|
end
|
|
|
// If either input is zero then return zero
|
|
// If either input is zero then return zero
|
|
|
else if ((($signed(a_e0) == (-1*((1<<M)-1))) && (a_m0 == 0)) || (($signed(b_e0) == (-1*((1<<M)-1))) && (b_m0 == 0)))
|
|
else if ((($signed(a_e0) == (-1*((1<<M)-1))) && (a_m0 == 0)) || (($signed(b_e0) == (-1*((1<<M)-1))) && (b_m0 == 0)))
|
|
|
begin
|
|
begin
|
|
|
- z_s0 <= a_s0 ^ b_s0;
|
|
|
|
|
- z_e0 <= 0;
|
|
|
|
|
- z_m0 <= 0;
|
|
|
|
|
- flags <= 2'b11;
|
|
|
|
|
|
|
+ z_s1 <= a_s0 ^ b_s0;
|
|
|
|
|
+ z_e1 <= 0;
|
|
|
|
|
+ z_m1 <= 0;
|
|
|
|
|
+ flags1 <= flag_zero;
|
|
|
end
|
|
end
|
|
|
// If b is zero then return zero
|
|
// If b is zero then return zero
|
|
|
|
|
|
|
|
// If none of the return flags have been set
|
|
// If none of the return flags have been set
|
|
|
- if (flags == 2'b00)
|
|
|
|
|
|
|
+ if (flags1 == flag_none)
|
|
|
begin
|
|
begin
|
|
|
// If msb of a_m is 0 then shift left and reduce exponent by 1
|
|
// If msb of a_m is 0 then shift left and reduce exponent by 1
|
|
|
- if (a_m1[N-3-M] == 0)
|
|
|
|
|
|
|
+ if (a_m1[K-1] == 0)
|
|
|
begin
|
|
begin
|
|
|
a_m2 <= a_m1 << 1;
|
|
a_m2 <= a_m1 << 1;
|
|
|
a_e2 <= a_e1 - 1;
|
|
a_e2 <= a_e1 - 1;
|
|
@@ -126,7 +140,7 @@ module fp_product #(parameter N=16, M=4)(input_a, input_b, output_z, clk, reset)
|
|
|
a_e2 <= a_e1;
|
|
a_e2 <= a_e1;
|
|
|
end
|
|
end
|
|
|
// If msb of b_m is 0 then shift left and reduce exponent by 1
|
|
// If msb of b_m is 0 then shift left and reduce exponent by 1
|
|
|
- if (b_m1[N-3-M] == 0)
|
|
|
|
|
|
|
+ if (b_m1[K-1] == 0)
|
|
|
begin
|
|
begin
|
|
|
b_m2 <= b_m1 << 1;
|
|
b_m2 <= b_m1 << 1;
|
|
|
b_e2 <= b_e1 - 1;
|
|
b_e2 <= b_e1 - 1;
|
|
@@ -137,10 +151,6 @@ module fp_product #(parameter N=16, M=4)(input_a, input_b, output_z, clk, reset)
|
|
|
b_m2 <= b_m1;
|
|
b_m2 <= b_m1;
|
|
|
b_e2 <= b_e1;
|
|
b_e2 <= b_e1;
|
|
|
end
|
|
end
|
|
|
- z_s2 <= a_s2 ^ b_s2; //signs xor together
|
|
|
|
|
- z_e2 <= a_e2 + b_e2 - (1<<M); // exponents added together subtracting one offset
|
|
|
|
|
- product <= a_m2 * b_m2; // mantissa multiplied together and the most significant bits are stored in the output mantissa
|
|
|
|
|
- z_m3 <= product[2*(N-3-M):N-2-M];
|
|
|
|
|
end
|
|
end
|
|
|
|
|
|
|
|
else
|
|
else
|
|
@@ -149,20 +159,18 @@ module fp_product #(parameter N=16, M=4)(input_a, input_b, output_z, clk, reset)
|
|
|
a_e2 <= a_e1;
|
|
a_e2 <= a_e1;
|
|
|
b_m2 <= b_m1;
|
|
b_m2 <= b_m1;
|
|
|
b_e2 <= b_e1;
|
|
b_e2 <= b_e1;
|
|
|
- z_s2 <= z_s1;
|
|
|
|
|
- z_e1 <= z_e0;
|
|
|
|
|
|
|
+ z_s3 <= z_s2;
|
|
|
z_e2 <= z_e1;
|
|
z_e2 <= z_e1;
|
|
|
- z_m3 <= z_m2;
|
|
|
|
|
- product <= 0;
|
|
|
|
|
|
|
+ z_e3 <= z_e2;
|
|
|
|
|
+ z_m4 <= z_m3;
|
|
|
|
|
+ z_p3 <= 0;
|
|
|
end
|
|
end
|
|
|
-
|
|
|
|
|
- // Packing the output
|
|
|
|
|
- output_z[N-1] <= z_s3;
|
|
|
|
|
- output_z[N-2:N-2-M] <= z_e3+(1<<M);
|
|
|
|
|
- output_z[N-3-M:0] <= z_m3;
|
|
|
|
|
|
|
+
|
|
|
|
|
+ z_s3 <= a_s2 ^ b_s2; //signs xor together
|
|
|
|
|
+ z_e3 <= a_e2 + b_e2 - (1<<M); // exponents added together subtracting one offset
|
|
|
|
|
+ z_p3 <= a_m2 * b_m2; // mantissa multiplied together and the most significant bits are stored in the output mantissa
|
|
|
|
|
+ z_m4 <= z_p3[2*K-1:K];
|
|
|
end
|
|
end
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
else
|
|
else
|
|
|
begin
|
|
begin
|
|
|
a_s0 <= 0;
|
|
a_s0 <= 0;
|
|
@@ -189,10 +197,6 @@ module fp_product #(parameter N=16, M=4)(input_a, input_b, output_z, clk, reset)
|
|
|
b_e2 <= 0;
|
|
b_e2 <= 0;
|
|
|
b_m2 <= 0;
|
|
b_m2 <= 0;
|
|
|
|
|
|
|
|
- z_s0 <= 0;
|
|
|
|
|
- z_e0 <= 0;
|
|
|
|
|
- z_m0 <= 0;
|
|
|
|
|
-
|
|
|
|
|
z_s1 <= 0;
|
|
z_s1 <= 0;
|
|
|
z_e1 <= 0;
|
|
z_e1 <= 0;
|
|
|
z_m1 <= 0;
|
|
z_m1 <= 0;
|
|
@@ -205,11 +209,13 @@ module fp_product #(parameter N=16, M=4)(input_a, input_b, output_z, clk, reset)
|
|
|
z_e3 <= 0;
|
|
z_e3 <= 0;
|
|
|
z_m3 <= 0;
|
|
z_m3 <= 0;
|
|
|
|
|
|
|
|
- product <= 0;
|
|
|
|
|
|
|
+ z_s4 <= 0;
|
|
|
|
|
+ z_e4 <= 0;
|
|
|
|
|
+ z_m4 <= 0;
|
|
|
|
|
|
|
|
- flags <= 0;
|
|
|
|
|
|
|
+ z_p3 <= 0;
|
|
|
|
|
|
|
|
- output_z <= 0;
|
|
|
|
|
|
|
+ flags1 <= flag_none;
|
|
|
end
|
|
end
|
|
|
end
|
|
end
|
|
|
|
|
|