|
@@ -0,0 +1,184 @@
|
|
|
|
|
+module fp_product #(parameter N=16, M=4)(input_a, input_a, ouput_z, clk, reset);
|
|
|
|
|
+ input logic [N-1:0] input_a, input_a;
|
|
|
|
|
+ input logic clk, reset;
|
|
|
|
|
+ output logic [N-1:0] output_z;
|
|
|
|
|
+
|
|
|
|
|
+ reg [N-1:0] a, b, z;
|
|
|
|
|
+ reg [N-M-3:0] a_m, b_m, z_m; // mantissa
|
|
|
|
|
+ reg [M:0] a_e, b_e, z_e; // exponent
|
|
|
|
|
+ reg a_s, b_s, z_s; // 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
|
|
|
|
|
+
|
|
|
|
|
+ always_ff @(posedge clk)
|
|
|
|
|
+ begin
|
|
|
|
|
+ // Unpacking the inputs
|
|
|
|
|
+ if (~reset)
|
|
|
|
|
+ begin
|
|
|
|
|
+ a <= input_a;
|
|
|
|
|
+ a_s <= a[N-1];
|
|
|
|
|
+ a_e <= a[N-2:N-2-M];
|
|
|
|
|
+ a_m <= a[N-3-M:0];
|
|
|
|
|
+
|
|
|
|
|
+ b <= input_b;
|
|
|
|
|
+ b_s <= b[N-1];
|
|
|
|
|
+ b_e <= b[N-2:N-2-M];
|
|
|
|
|
+ b_m <= b[N-3-M:0];
|
|
|
|
|
+ end
|
|
|
|
|
+ else
|
|
|
|
|
+ begin
|
|
|
|
|
+ a <= 0;
|
|
|
|
|
+ a_s <= 0;
|
|
|
|
|
+ a_e <= 0;
|
|
|
|
|
+ a_m <= 0;
|
|
|
|
|
+
|
|
|
|
|
+ b <= 0;
|
|
|
|
|
+ b_s <= 0;
|
|
|
|
|
+ b_e <= 0;
|
|
|
|
|
+ b_m <= 0;
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ always_ff @(posedge clk)
|
|
|
|
|
+ begin
|
|
|
|
|
+ if (~reset)
|
|
|
|
|
+ begin
|
|
|
|
|
+ // If input a or input b is NaN then return NaN
|
|
|
|
|
+ if (((a_e ==(1<<M)) && (a_m != 0)) || ((b_e == (1<<M)) && (b_m != 0)))
|
|
|
|
|
+ begin
|
|
|
|
|
+ z_s <= 1;
|
|
|
|
|
+ z_e <= (1 << (M+1)) - 1;
|
|
|
|
|
+ z_m[N-3-M] <= 1;
|
|
|
|
|
+ z_m[N-4-M:0] <= 0;
|
|
|
|
|
+ flags <= 2'b01;
|
|
|
|
|
+ end
|
|
|
|
|
+ // If a is infinity then return infinity
|
|
|
|
|
+ else if (a_e == (1<<M))
|
|
|
|
|
+ begin
|
|
|
|
|
+ // Unless b is zero, then you return NaN instead
|
|
|
|
|
+ if (($signed(b_e) == (-1*((1<<M)-1))) && b_m == 0)
|
|
|
|
|
+ begin
|
|
|
|
|
+ z_s <= 1;
|
|
|
|
|
+ z_e <= (1 << (M+1)) - 1;
|
|
|
|
|
+ z_m[N-3-M] <= 1;
|
|
|
|
|
+ z_m[N-4-M] <= 0;
|
|
|
|
|
+ flags <= 2b'01;
|
|
|
|
|
+ end
|
|
|
|
|
+ else
|
|
|
|
|
+ // Returning infinity
|
|
|
|
|
+ begin
|
|
|
|
|
+ z_s <= a_s ^ b_s;
|
|
|
|
|
+ z_e <= (1 << (M+1)) - 1;
|
|
|
|
|
+ z_m <= 0;
|
|
|
|
|
+ flags <= 2b'10;
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+ // If b is infinity then return infinity
|
|
|
|
|
+ else if (b_s (1<<M))
|
|
|
|
|
+ begin
|
|
|
|
|
+ //Unless a is zero, then return NaN instead
|
|
|
|
|
+ if (($signed(a_e) == (-1*((1<<M)-1))) && a_m == 0)
|
|
|
|
|
+ begin
|
|
|
|
|
+ z_s <= 1;
|
|
|
|
|
+ z_e <= (1 << (M+1)) - 1;
|
|
|
|
|
+ z_m[N-3-M] <= 1;
|
|
|
|
|
+ z_m[N-4-M] <= 0;
|
|
|
|
|
+ flags <= 2b'01;
|
|
|
|
|
+ end
|
|
|
|
|
+ else
|
|
|
|
|
+ // Returning infinity
|
|
|
|
|
+ begin
|
|
|
|
|
+ z_s <= a_s ^ b_s;
|
|
|
|
|
+ z_e <= (1 << (M+1)) - 1;
|
|
|
|
|
+ z_m <= 0;
|
|
|
|
|
+ flags <= 2b'10;
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+ // If either input is zero then return zero
|
|
|
|
|
+ else if ((($signed(a_e) == (-1*((1<<M)-1))) && (a_m == 0)) || (($signed(b_e) == (-1*((1<<M)-1))) && (b_m == 0)))
|
|
|
|
|
+ begin
|
|
|
|
|
+ z_s <= a_s ^ b_s;
|
|
|
|
|
+ z_e <= 0;
|
|
|
|
|
+ z_m <= 0;
|
|
|
|
|
+ flags <= 2'b11;
|
|
|
|
|
+ end
|
|
|
|
|
+ // If b is zero then return zero
|
|
|
|
|
+ end
|
|
|
|
|
+ else
|
|
|
|
|
+ begin
|
|
|
|
|
+ z_s <= 0;
|
|
|
|
|
+ z_e <= 0;
|
|
|
|
|
+ z_m <= 0;
|
|
|
|
|
+ flags <= 0;
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ always_ff @(posedge clk)
|
|
|
|
|
+ begin
|
|
|
|
|
+ if (~reset)
|
|
|
|
|
+ begin
|
|
|
|
|
+ // If none of the return flags have been set
|
|
|
|
|
+ if (flags == 2'b00)
|
|
|
|
|
+ begin
|
|
|
|
|
+ // If msb of a_m is 0 then shift left and reduce exponent by 1
|
|
|
|
|
+ if (a_m[N-3-M] == 0)
|
|
|
|
|
+ begin
|
|
|
|
|
+ a_m <= a_m << 1;
|
|
|
|
|
+ a_e <= a_e - 1;
|
|
|
|
|
+ end
|
|
|
|
|
+ //Just for completion of logic
|
|
|
|
|
+ else
|
|
|
|
|
+ begin
|
|
|
|
|
+ a_m <= a_m;
|
|
|
|
|
+ a_e <= a_e;
|
|
|
|
|
+ end
|
|
|
|
|
+ // If msb of b_m is 0 then shift left and reduce exponent by 1
|
|
|
|
|
+ if (b_m[N-3-M] == 0)
|
|
|
|
|
+ begin
|
|
|
|
|
+ b_m <= b_m << 1;
|
|
|
|
|
+ b_e <= b_e - 1;
|
|
|
|
|
+ end
|
|
|
|
|
+ //Just for completion of logic
|
|
|
|
|
+ else
|
|
|
|
|
+ begin
|
|
|
|
|
+ b_m <= b_m;
|
|
|
|
|
+ b_e <= b_e;
|
|
|
|
|
+ end
|
|
|
|
|
+ z_s <= a_s ^ b_s; //signs xor together
|
|
|
|
|
+ z_e <= a_e + b_e - (1<<M); // exponents added together subtracting one offset
|
|
|
|
|
+ product <= a_m * b_m; // mantissa multiplied together and the most significant bits are stored in the output mantissa
|
|
|
|
|
+ z_m <= product[2*(N-3-M):N-2-M];
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ else
|
|
|
|
|
+ begin
|
|
|
|
|
+ a_m <= 0;
|
|
|
|
|
+ a_e <= 0;
|
|
|
|
|
+ b_m <= 0;
|
|
|
|
|
+ b_e <= 0;
|
|
|
|
|
+ z_s <= 0;
|
|
|
|
|
+ z_e <= 0;
|
|
|
|
|
+ product <= 0;
|
|
|
|
|
+ z_m <= 0;
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ always_ff @(posedge clk)
|
|
|
|
|
+ begin
|
|
|
|
|
+ if (~reset)
|
|
|
|
|
+ begin
|
|
|
|
|
+ z[N-1] <= z_s;
|
|
|
|
|
+ z[N-2:N-2-M] <= z_e;
|
|
|
|
|
+ z[N-3-M:0] <= z_m;
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ else
|
|
|
|
|
+ begin
|
|
|
|
|
+ z <= 0;
|
|
|
|
|
+ end
|
|
|
|
|
+ end
|
|
|
|
|
+
|
|
|
|
|
+ output_z <= z;
|
|
|
|
|
+endmodule : fp_product
|