|
|
@@ -0,0 +1,203 @@
|
|
|
+module fp_adder #(parameter N=16, M=4)(input_a, input_b, output_z, diff, 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-4: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] greater; // 01 for a, 10 for b, 11 for both and 00 for neither
|
|
|
+ reg [M:0] abs; // For the absolute difference
|
|
|
+ logic [N-3-M:0] res; // For the addition result
|
|
|
+
|
|
|
+ always_ff @(posedge clk)
|
|
|
+ begin
|
|
|
+ if (reset)
|
|
|
+ begin
|
|
|
+ a <= 0;
|
|
|
+ b <= 0;
|
|
|
+ a_m <= 0;
|
|
|
+ b_m <= 0;
|
|
|
+ a_e <= 0;
|
|
|
+ b_e <= 0;
|
|
|
+ a_s <= 0;
|
|
|
+ b_s <= 0;
|
|
|
+ end
|
|
|
+
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ // Unpacking the inputs
|
|
|
+ a <= input_a;
|
|
|
+ a_m <= a[N-M-3:0];
|
|
|
+ a_e <= a[N-2:N-2-M];
|
|
|
+ a_s <= a[N-1];
|
|
|
+
|
|
|
+ b <= input_b;
|
|
|
+ b_m <= b[N-M-3:0];
|
|
|
+ b_e <= b[N-2:N-2-M];
|
|
|
+ b_s <= b[N-1];
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ always_ff @(posedge clk)
|
|
|
+ begin
|
|
|
+ if(~reset)
|
|
|
+ begin
|
|
|
+ // If input_a has the bigger exponent then flag it with greater and find the absolute difference
|
|
|
+ if (a_e > b_e)
|
|
|
+ begin
|
|
|
+ greater <= 2'b01;
|
|
|
+ abs <= a_e - b_e;
|
|
|
+ z_s <= a_s;
|
|
|
+ end
|
|
|
+ // If input_a has the bigger exponent then flag it with greater and find the absolute difference
|
|
|
+ else if (b_e > a_e)
|
|
|
+ begin
|
|
|
+ greater <= 2'b10;
|
|
|
+ abs <= b_e - a_e;
|
|
|
+ z_s <= b_s;
|
|
|
+ end
|
|
|
+ // If the inputs have equal exponent
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ greater <= 2'b00;
|
|
|
+ abs <= 0;
|
|
|
+ // Assigning the overall sign based on the difference between the mantissa
|
|
|
+ if(a_m > b_m)
|
|
|
+ begin
|
|
|
+ z_s <= a_s;
|
|
|
+ end
|
|
|
+ else if(b_m > a_m)
|
|
|
+ begin
|
|
|
+ z_s <= b_s;
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ z_s <= 0;
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ greater <= 2'b00;
|
|
|
+ abs <= 0;
|
|
|
+ z_s <= 0;
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ always_ff @(posedge clk)
|
|
|
+ begin
|
|
|
+ if(~reset)
|
|
|
+ begin
|
|
|
+ // Condition for overflow is that it sets the output to the larger input
|
|
|
+ if (abs > N-2-M) // Shifting by N-2-M would give 0
|
|
|
+ begin
|
|
|
+ if (greater == 2'b01)
|
|
|
+ begin
|
|
|
+ z <= a; // Input a is larger and is translated to the output
|
|
|
+ end
|
|
|
+ else if (greater == 2'b10)
|
|
|
+ begin
|
|
|
+ z <= b; // Input b is larger and is translated to the output
|
|
|
+ end
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ if (a_m >= b_m)
|
|
|
+ begin
|
|
|
+ z <= a; // Equal exponents but a has the larger mantissa
|
|
|
+ end
|
|
|
+ else if (b_m > a_m)
|
|
|
+ begin
|
|
|
+ z <= b; // Equal exponents but b has the larger mantissa
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ // If a has the bigger exponent
|
|
|
+ if (greater == 2'b01)
|
|
|
+ begin
|
|
|
+ // If the signs are the same then add
|
|
|
+ if (a_s == b_s)
|
|
|
+ begin
|
|
|
+ res <= a_m + (b_m >> (abs-1));
|
|
|
+ end
|
|
|
+ // If they are different then subtract
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ res <= a_m - (b_m >> (abs-1));
|
|
|
+ end
|
|
|
+ end
|
|
|
+ // If b has the bigger exponent
|
|
|
+ else if (greater == 2'b10)
|
|
|
+ begin
|
|
|
+ // If the signs are the same then add
|
|
|
+ if (a_s == b_s)
|
|
|
+ begin
|
|
|
+ res <= b_m + (a_m >> (abs-1));
|
|
|
+ end
|
|
|
+ // If they are different then subtract
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ res <= b_m - (a_m >> (abs-1));
|
|
|
+ end
|
|
|
+ end
|
|
|
+ // If the exponents are equal
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ // If the signs are the same then add
|
|
|
+ if (a_s == b_s)
|
|
|
+ begin
|
|
|
+ res <= a_m + b_m;
|
|
|
+ end
|
|
|
+ // If the signs are different then subtract
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ // First checking which has the bigger mantissa
|
|
|
+ if (a_m > b_m)
|
|
|
+ begin
|
|
|
+ res <= a_m - b_m;
|
|
|
+ end
|
|
|
+ else if (b_m > a_m)
|
|
|
+ begin
|
|
|
+ res <= b_m - a_m;
|
|
|
+ end
|
|
|
+ // If the mantissa are the same as well then the result should be 0
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ res <= 0;
|
|
|
+ end
|
|
|
+ end
|
|
|
+ end
|
|
|
+ // Assigning the mantissa of output the the sum of input mantissa
|
|
|
+ z_m <= res;
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ else
|
|
|
+ begin
|
|
|
+ z <= 0;
|
|
|
+ z_m <= 0;
|
|
|
+ res <= 0;
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ always_ff @(posedge clk)
|
|
|
+ begin
|
|
|
+ if (~reset)
|
|
|
+ // Packing the output back together
|
|
|
+ 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
|
|
|
+endmodule : fp_adder
|