Selaa lähdekoodia

working add and multiply

Oliver Jaison 4 vuotta sitten
vanhempi
commit
4b437b8178
2 muutettua tiedostoa jossa 128 lisäystä ja 90 poistoa
  1. 46 0
      scripts/hex2fp.py
  2. 82 90
      src/FPA_module_test.sv

+ 46 - 0
scripts/hex2fp.py

@@ -0,0 +1,46 @@
+import pandas as pd
+import math
+
+
+def dec_mantissa(bin_mantissa):
+    res = 0
+    for k in range(len(bin_mantissa)):
+        res = res + (int(bin_mantissa[k]) * (2 ** (-1 - k)))
+    return res
+
+
+def hex2dec(hex):
+    binary = "{0:08b}".format(int(hex, 16))
+    if len(binary) < 16:
+        while len(binary) < 16:
+            binary = "0" + binary
+        sign = 1
+    else:
+        sign = -1 ** int(binary[0])
+    exp = 2 ** (int(binary[1:6], 2) - 16)
+    mantissa = 1 + dec_mantissa(binary[6:])
+    return [binary, sign * exp * mantissa]
+
+
+# df = pd.read_csv("fp16_test.hex")
+# bins = []
+# decs = []
+# for i in range(df.shape[0]):
+#     hexs = df.iloc[i][0].split()
+#     bins.append([])
+#     decs.append([])
+#     for j in range(4):
+#         bins[i].append("{0:08b}".format(int(hexs[j], 16)))
+#         exp = 2 ** (int(bins[i][j][1:6], 2) - 16)
+#         sign = -1 ** int(bins[i][j][0])
+#         mantissa = 1 + dec_mantissa(bins[i][j][6:])
+#         decs[i].append(sign * exp * mantissa)
+input_1 = "bbeb"
+input_2 = "58fe"
+result = "d8f1"
+calc_res = "d9f1"
+
+print("input 1 :", input_1, ", ", hex2dec(input_1)[0], ", ", hex2dec(input_1)[1])
+print("input 2 :", input_2, ", ", hex2dec(input_2)[0], ", ", hex2dec(input_2)[1])
+print("result  :", result, ", ", hex2dec(result)[0], ", ", hex2dec(result)[1])
+print("calc res:", calc_res, ", ", hex2dec(calc_res)[0], ", ", hex2dec(calc_res)[1])

+ 82 - 90
src/FPA_module_test.sv

@@ -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]);