|
|
@@ -1,12 +1,12 @@
|
|
|
-module floating_add #(parameter N=16, M=4)(a, b, c, flag_double);
|
|
|
- input logic [N-1:0] a, b;
|
|
|
- output logic [N-1:0] c;
|
|
|
- output logic flag_double;
|
|
|
+module floating_add #(parameter N=16, M=4)(input_1, input_2, sum, diff);
|
|
|
+ input logic [N-1:0] input_1, input_2;
|
|
|
+ output logic [N-1:0] sum;
|
|
|
+ output logic [M:0] diff;
|
|
|
|
|
|
logic flag_a;
|
|
|
logic flag_b;
|
|
|
- logic abs;
|
|
|
- logic res;
|
|
|
+ logic [M:0] abs;
|
|
|
+ logic [N-3-M:0] res;
|
|
|
|
|
|
// sign_x = x[N-1]
|
|
|
// exponent_x = x[N-2:N-2-M]
|
|
|
@@ -14,91 +14,108 @@ module floating_add #(parameter N=16, M=4)(a, b, c, flag_double);
|
|
|
|
|
|
always_comb
|
|
|
begin
|
|
|
- if (a[N-2:N-2-M] > b[N-2:N-2-M])
|
|
|
+ if (input_1[N-2:N-2-M] > input_2[N-2:N-2-M]) // If input 1 has the bigger exponent
|
|
|
begin
|
|
|
// Flags input a as larger and calculates the absolute difference
|
|
|
flag_a = 1;
|
|
|
flag_b = 0;
|
|
|
- abs = a[N-2:N-2-M] - b[N-2:N-2-M];
|
|
|
+ abs = input_1[N-2:N-2-M] - input_2[N-2:N-2-M];
|
|
|
// ASsigning overall sign of the output
|
|
|
- c[N-1] = a[N-1];
|
|
|
+ sum[N-1] = input_1[N-1];
|
|
|
// Sets output to have the same exponent
|
|
|
- c[N-2:N-2-M] = a[N-2:N-2-M];
|
|
|
+ sum[N-2:N-2-M] = input_1[N-2:N-2-M];
|
|
|
end
|
|
|
- else if (b[N-2:N-2-M] > a[N-2:N-2-M])
|
|
|
+ else if (input_2[N-2:N-2-M] > input_1[N-2:N-2-M]) // If input 2 has the bigger exponent
|
|
|
begin
|
|
|
// Similarly flags input b as larger and calculates the absolute difference
|
|
|
flag_a = 0;
|
|
|
flag_b = 1;
|
|
|
- abs = b[N-2:N-2-M] - a[N-2:N-2-M];
|
|
|
+ abs = input_2[N-2:N-2-M] - input_1[N-2:N-2-M];
|
|
|
// ASsigning overall sign of the output
|
|
|
- c[N-1] = b[N-1];
|
|
|
+ sum[N-1] = input_2[N-1];
|
|
|
// Sets ouput to have the same exponent
|
|
|
- c[N-2:N-2-M] = b[N-2:N-2-M];
|
|
|
+ sum[N-2:N-2-M] = input_2[N-2:N-2-M];
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
|
// THe condition that both inputs have the same exponent
|
|
|
flag_a = 1;
|
|
|
flag_b = 1;
|
|
|
- abs <= 0;
|
|
|
+ abs = 0;
|
|
|
// ASsigning overall sign of the output based on size of the mantissa
|
|
|
- if (a[N-3-M:0] >= b[N-3-M:0]) c[N-1] = a[N-1];
|
|
|
- else c[N-1] = b[N-1];
|
|
|
- c[N-2:N-2-M] = a[N-2:N-2-M];
|
|
|
+ if (input_1[N-3-M:0] >= input_2[N-3-M:0]) sum[N-1] = input_1[N-1];
|
|
|
+ else sum[N-1] = input_2[N-1];
|
|
|
+ sum[N-2:N-2-M] = input_1[N-2:N-2-M];
|
|
|
end
|
|
|
+ diff = abs;
|
|
|
end
|
|
|
|
|
|
always_comb
|
|
|
begin
|
|
|
// Condition for overflow is that it sets the output to the larger input
|
|
|
- if (abs > 3'b100) // Because size of exponent is 4 bits
|
|
|
+ if (abs > 9) // Because size of mantissa is 10 bits and shifting by 10 would give 0
|
|
|
begin
|
|
|
- if (flag_a & ~flag_b) c = a;
|
|
|
- else if (~flag_a & flag_b) c = b;
|
|
|
- else c = a;
|
|
|
- flag_double = 0;
|
|
|
+ if (flag_a & ~flag_b) sum = input_1; // input 1 is larger and is translated to output
|
|
|
+ else if (~flag_a & flag_b) sum = input_2; // input 2 is larger and is translated to output
|
|
|
+ else // exponents are the same
|
|
|
+ begin
|
|
|
+ if (input_1[N-3-M:0] >= input_2[N-3-M:0]) sum = input_1;// input 1 has the bigger mantissa
|
|
|
+ else sum = input_2; // input 2 has the bigger mantissa
|
|
|
+ end
|
|
|
end
|
|
|
else
|
|
|
begin
|
|
|
- // Shifts the lower mantissa right based on the absolute difference
|
|
|
- if (flag_a & ~flag_b)
|
|
|
+ // Shifts the smaller input's mantissa to the right based on abs
|
|
|
+ if (flag_a & ~flag_b)// If input 1 has the larger exponent
|
|
|
begin
|
|
|
// If the signs of both inputs are the same you add, otherwise you subtract
|
|
|
- if (a[N-1] == b[N-1])
|
|
|
- c[N-3-M:0] = a[N-3-M:0] + (b[N-3-M:0] >> abs);
|
|
|
+ if (input_1[N-1] == input_2[N-1])
|
|
|
+ begin
|
|
|
+ res = input_1[N-3-M:0] + (input_2[N-3-M:0] >> abs-1); // Sum the mantissa
|
|
|
+ sum[N-3-M:0] = res;
|
|
|
+ end
|
|
|
else
|
|
|
- c[N-3-M:0] = a[N-3-M:0] - (b[N-3-M:0] >> abs);
|
|
|
- flag_double = 0;
|
|
|
+ begin
|
|
|
+ res = input_1[N-3-M:0] - (input_2[N-3-M:0] >> abs-1); // Subtract the mantissas
|
|
|
+ sum[N-3-M:0] = res;
|
|
|
+ end
|
|
|
end
|
|
|
else if (~flag_a & flag_b)
|
|
|
begin
|
|
|
- if (a[N-1] == b[N-1])
|
|
|
- c[N-3-M:0] = b[N-3-M:0] + (a[N-3-M:0] >> abs);
|
|
|
+ // If the signs of both inputs are the same you add, otherwise you subtract
|
|
|
+ if (input_1[N-1] == input_2[N-1])
|
|
|
+ begin
|
|
|
+ res = (input_1[N-3-M:0] >> abs-1) + input_2[N-3-M:0]; // Sum the mantissa
|
|
|
+ sum[N-3-M:0] = res;
|
|
|
+ end
|
|
|
else
|
|
|
- c[N-3-M:0] = b[N-3-M:0] - (a[N-3-M:0] >> abs);
|
|
|
- flag_double = 0;
|
|
|
+ begin
|
|
|
+ res = input_2[N-3-M:0] - (input_1[N-3-M:0] >> abs-1); // Subtract the mantissas
|
|
|
+ sum[N-3-M:0] = res;
|
|
|
+ end
|
|
|
end
|
|
|
else
|
|
|
- begin
|
|
|
- if (a[N-1] == b[N-1])
|
|
|
+ begin
|
|
|
+ if (input_1[N-1] == input_2[N-1]) // If exponents and signs equal
|
|
|
begin
|
|
|
- res = a[N-3-M:0] + b[N-3-M:0];
|
|
|
- if (res > 1)
|
|
|
- begin
|
|
|
- c[N-3-M:0] = res >> 1;
|
|
|
- c[N-2:N-2-M] = c[N-2:N-2-M] + 1;
|
|
|
- end
|
|
|
- else c[N-3-M:0] = res;
|
|
|
+ res = input_1[N-3-M:0] + input_2[N-3-M:0]; // Sum the mantissa
|
|
|
+ sum[N-3-M:0] = res;
|
|
|
end
|
|
|
- else
|
|
|
+ else // In this case it will be a subtraction
|
|
|
begin
|
|
|
- if (a[N-3-M:0] > b[N-3-M:0]) res = a[N-3-M:0] - b[N-3-M:0];
|
|
|
- else if (a[N-3-M:0] < b[N-3-M:0]) res = b[N-3-M:0] - a[N-3-M:0];
|
|
|
- else res = 0;
|
|
|
- c[N-3-M:0] = res;
|
|
|
+ if (input_1[N-3-M:0] > input_2[N-3-M:0]) // Which has the larger mantissa
|
|
|
+ begin
|
|
|
+ res = input_1[N-3-M:0] - input_2[N-3-M:0]; // Subtract the mantissa
|
|
|
+ sum[N-3-M:0] = res;
|
|
|
+ end
|
|
|
+ else if (input_1[N-3-M:0] < input_2[N-3-M:0])
|
|
|
+ begin
|
|
|
+ res = input_2[N-3-M:0] - input_1[N-3-M:0]; // Subtract the mantissa
|
|
|
+ sum[N-3-M:0] = res;
|
|
|
+ end
|
|
|
+ else res = 0; // Both the exponent and the mantissa are equal so subtraction leads to 0
|
|
|
+ sum[N-3-M:0] = res;
|
|
|
end
|
|
|
- flag_double = 1;
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
@@ -106,51 +123,28 @@ endmodule : floating_add
|
|
|
|
|
|
|
|
|
|
|
|
-module floating_product #(parameter N=16, M=4)(a, b, c, underflow, zero_flag);
|
|
|
- input logic [N-1:0] a, b;
|
|
|
- output logic [N-1:0] c;
|
|
|
- output logic underflow, zero_flag;
|
|
|
+module floating_product #(parameter N=16, M=4)(input_1, input_2, product);
|
|
|
+ input logic [N-1:0] input_1, input_2;
|
|
|
+ output logic [N-1:0] product;
|
|
|
|
|
|
// sign_x = x[N-1]
|
|
|
// exponent_x = x[N-2:N-2-M]
|
|
|
// mantissa_x = x[N-3-M:0]
|
|
|
|
|
|
- logic sum;
|
|
|
- logic [2*N-6-2*M:0] product;
|
|
|
+ logic [N-2:N-2-M] sum;
|
|
|
+ logic [2*(N-3-M):0] mult;
|
|
|
|
|
|
// We have assigned an {M+1} bit exponent so we must have a 2^{M} offset
|
|
|
- assign sum = a[N-2:N-2-M] + b[N-2:N-2-M];
|
|
|
- assign c[N-2:N-2-M] = sum - (1 << M);
|
|
|
+ assign sum = input_1[N-2:N-2-M] + input_2[N-2:N-2-M];
|
|
|
+ assign product[N-2:N-2-M] = sum - (1'b1 << M) + 2;
|
|
|
|
|
|
always_comb
|
|
|
begin
|
|
|
- // If the sums of the exponents is less than 2^M then the exponent will underflow and the product is zero
|
|
|
- if (sum < (1 << M))
|
|
|
- begin
|
|
|
- c[N-1:0] = 0;
|
|
|
- underflow = 1;
|
|
|
- zero_flag = 0;
|
|
|
- end
|
|
|
- // If either input number has a high-order bit of zero, then that input is zero and the product is zero
|
|
|
- else if (!a[N-2] || !b[N-2])
|
|
|
- begin
|
|
|
- c[N-1:0] = 0;
|
|
|
- zero_flag = 1;
|
|
|
- underflow = 0;
|
|
|
- end
|
|
|
- else
|
|
|
- begin
|
|
|
- // Setting the mantissa of the output
|
|
|
- product = a[N-3-M:0] * b[N-3-M];
|
|
|
- if (product[N-3-M])
|
|
|
- c[N-3-M:0] = product[N-3-M:0];
|
|
|
- else
|
|
|
- c[N-3-M:0] = product[N-3-M:0] << 1;
|
|
|
- // Setting the sign of the output
|
|
|
- c[N-1] = a[N-1]^b[N-1];
|
|
|
- underflow = 0;
|
|
|
- zero_flag = 0;
|
|
|
- end
|
|
|
+ // Setting the mantissa of the output
|
|
|
+ mult = input_1[N-3-M:0] * input_2[N-3-M:0];
|
|
|
+ if (mult[N-3-M]) product[N-3-M:0] = mult[2*(N-3-M):2*(N-3-M)-9];
|
|
|
+ else product[N-3-M:0] = mult[2*(N-3-M):2*(N-3-M)-9] << 1;
|
|
|
+ product[N-1] = input_1[N-1] ^ input_2[N-1];
|
|
|
end
|
|
|
endmodule : floating_product
|
|
|
|
|
|
@@ -197,11 +191,11 @@ endmodule : floating_product
|
|
|
module floating_tb;
|
|
|
reg reset, clk;
|
|
|
logic [15:0] input_a, input_b, result_add, result_mult;
|
|
|
- wire flag_double, underflow, zero_flag;
|
|
|
+ logic [4:0] diff;
|
|
|
|
|
|
- floating_add adder1(.a(input_a), .b(input_b), .c(result_add), .flag_double(flag_double));
|
|
|
+ floating_add adder1(.input_1(input_a), .input_2(input_b), .sum(result_add), .diff(diff));
|
|
|
|
|
|
- floating_product multiplier1(.a(input_a), .b(input_b), .c(result_mult), .underflow(underflow), .zero_flag(zero_flag));
|
|
|
+ floating_product multiplier1(.input_1(input_a), .input_2(input_b), .product(result_mult));
|
|
|
|
|
|
|
|
|
reg [15:0] test_mem [29:0][3:0];
|
|
|
@@ -214,12 +208,10 @@ module floating_tb;
|
|
|
static int num_tests = $size(test_mem) * 2;
|
|
|
|
|
|
for (int i=0; i < $size(test_mem); i++) begin
|
|
|
- input_a = 0;
|
|
|
- input_b = 0;
|
|
|
+ input_a = test_mem[i][0];
|
|
|
+ input_b = test_mem[i][1];
|
|
|
|
|
|
#10;
|
|
|
- $display("%d + %d = %d, expected %d", input_a, input_b, result_add, 0);
|
|
|
- $finish();
|
|
|
if(result_add != test_mem[i][2]) begin
|
|
|
if(num_err < 20)
|
|
|
$display("FAIL ADD: %H + %H = %H, expected %H", input_a, input_b, result_add, test_mem[i][2]);
|