Procházet zdrojové kódy

multiplication WIP

Min před 4 roky
rodič
revize
1e4f1528e2
2 změnil soubory, kde provedl 93 přidání a 84 odebrání
  1. 79 73
      src/fpu16/fp_product.sv
  2. 14 11
      src/fpu16/fpu16.sv

+ 79 - 73
src/fpu16/fp_product.sv

@@ -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 clk, reset;
 	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)
 	begin
 		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_e1 <= b_e0;
 			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_m3 <= z_m2;
 
 			// 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)))
 			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
 			// If a is infinity then return infinity
 			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
 				if (($signed(b_e0) == (-1*((1<<M)-1))) && b_m0 == 0)
 				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
 				else
 				// Returning infinity
 				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
 			// 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
 				if (($signed(a_e0) == (-1*((1<<M)-1))) && a_m0 == 0)
 				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
 				else
 				// Returning infinity
 				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
 			// 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)))
 			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
 			// If b is zero then return zero
 			
 			// If none of the return flags have been set
-			if (flags == 2'b00)
+			if (flags1 == flag_none)
 			begin
 				// 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
 					a_m2 <= a_m1 << 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;
 				end
 				// 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
 					b_m2 <= b_m1 << 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_e2 <= b_e1;
 				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
 			
 			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;
 				b_m2 <= b_m1;
 				b_e2 <= b_e1;
-				z_s2 <= z_s1;
-				z_e1 <= z_e0;
+				z_s3 <= z_s2;
 				z_e2 <= z_e1;
-				z_m3 <= z_m2;
-				product <= 0;
+				z_e3 <= z_e2;
+				z_m4 <= z_m3;
+				z_p3 <= 0;
 			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
-		
-		
 		else
 		begin
 			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_m2 <= 0;
 			
-			z_s0 <= 0;
-			z_e0 <= 0;
-			z_m0 <= 0;
-			
 			z_s1 <= 0;
 			z_e1 <= 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_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
 

+ 14 - 11
src/fpu16/fpu16.sv

@@ -15,7 +15,8 @@ module fpu16_tb;
 	fp_product multiplier1(.input_a(input_a), .input_b(input_b), .output_z(result_mult), .clk(clk), .reset(reset));
 	
 	initial forever #5 clk = ~clk;
-	localparam PIPELINES = 2;
+	localparam PIPELINES_ADD = 2;
+	localparam PIPELINES_MUL = 4;
 
 	reg [15:0] test_mem [29:0][3:0];
 
@@ -25,10 +26,13 @@ module fpu16_tb;
 	reg [M-1:0] exp0_e;
 	reg exp0_s;
 
+	reg [N-2-M:0] exp1_m;
+	reg [M-1:0] exp1_e;
+	reg exp1_s;
+
 	always_comb begin
-		exp0_m = expected_add[N-M-2:0];
-		exp0_e = expected_add[N-2:N-M-1];
-		exp0_s = expected_add[N-1];
+		{exp0_s, exp0_e, exp0_m} = expected_add;
+		{exp1_s, exp1_e, exp1_m} = expected_mult;
 	end
 
 	initial begin
@@ -44,24 +48,23 @@ module fpu16_tb;
 		expected_add = 0;
 		expected_mult = 0;
 
-        for (int i=0; i < $size(test_mem)+PIPELINES; i++) begin
-			if(i >= PIPELINES) begin
-				expected_add = test_mem[i-PIPELINES][2];
-				expected_mult = test_mem[i-PIPELINES][3];
-			end
+        for (int i=0; i < $size(test_mem)+PIPELINES_MUL; i++) begin
+			if(i >= PIPELINES_ADD) expected_add = test_mem[i-PIPELINES_ADD][2];
+			if(i >= PIPELINES_MUL) expected_mult = test_mem[i-PIPELINES_MUL][3];
+
             input_a = test_mem[i][0];
             input_b = test_mem[i][1];
 
             #10;
             if(result_add != expected_add) begin
                 if(num_err < 20)
-                    $display("FAIL ADD: %H + %H = %H, expected %H", test_mem[i-PIPELINES][0], test_mem[i-PIPELINES][1], result_add, test_mem[i][2]);
+                    $display("FAIL ADD: %H + %H = %H, expected %H", test_mem[i-PIPELINES_ADD][0], test_mem[i-PIPELINES_ADD][1], result_add, test_mem[i][2]);
                 num_err = num_err + 1;
             end
 
 			if(result_mult != expected_mult) begin
                 if(num_err < 20)
-                    $display("FAIL MULTIPLY: %H x %H = %H, expected %H", test_mem[i-PIPELINES][0], test_mem[i-PIPELINES][1], result_mult, test_mem[i][3]);
+                    $display("FAIL MULTIPLY: %H x %H = %H, expected %H", test_mem[i-PIPELINES_MUL][0], test_mem[i-PIPELINES_MUL][1], result_mult, test_mem[i][3]);
                 num_err = num_err + 1;
             end