Przeglądaj źródła

pipeline works on adder

Oliver Jaison 4 lat temu
rodzic
commit
f95265d149
3 zmienionych plików z 177 dodań i 136 usunięć
  1. 30 20
      src/fpu16/fp_adder.sv
  2. 143 112
      src/fpu16/fp_product.sv
  3. 4 4
      src/fpu16/fpu16.sv

+ 30 - 20
src/fpu16/fp_adder.sv

@@ -1,37 +1,37 @@
 module fp_adder #(parameter N=16, M=5)(input_a, input_b, output_z, clk, reset);
-	input logic [N-1:0] input_a, input_b;
+	input reg [N-1:0] input_a, input_b;
 	input logic clk, reset;
-	output logic [N-1:0] output_z;
+	output reg [N-1:0] output_z;
 	
 	reg [N-2-M:0] a_m, b_m, z_m; // mantissa
 	reg [N-2-M:0] a_m1, b_m1; 
 	
-	reg [M-1:0] a_e, b_e, z_e; // exponent
-	reg a_s, b_s, z_s; // sign
+	reg [M-1:0] a_e, b_e, z_e, z_e1; // exponent
+	reg a_s, b_s, z_s, z_s1; // 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 between exponents
-	logic [N-2-M:0] res; // For the addition result
-	
-	
-	always_comb
-	begin
-		// Unpacking the inputs
-		a_m = input_a[N-M-2:0];
-		a_e = input_a[N-2:N-M-1];
-		a_s = input_a[N-1];
-		
-		b_m = input_b[N-M-2:0];
-		b_e = input_b[N-2:N-M-1];
-		b_s = input_b[N-1];
-	end
+	reg [N-2-M:0] res; // For the addition result
 	
 	always_ff @(posedge clk)
 	begin
 		if(~reset)
 		begin
+				// Unpacking the inputs
+			a_m <= input_a[N-M-2:0];
+			a_e <= input_a[N-2:N-M-1];
+			a_s <= input_a[N-1];
+			
+			b_m <= input_b[N-M-2:0];
+			b_e <= input_b[N-2:N-M-1];
+			b_s <= input_b[N-1];
+			
 			a_m1 <= a_m;
 			b_m1 <= b_m;
+			
+			z_e1 <= z_e;
+			z_s1 <= z_s;
+			
 			// If input_a has the bigger exponent then flag it with greater and find the absolute difference
 			if (a_e > b_e)
 			begin
@@ -155,16 +155,26 @@ module fp_adder #(parameter N=16, M=5)(input_a, input_b, output_z, clk, reset);
 				// Assigning the mantissa of output the the sum of input mantissa
 				z_m <= res;
 			end
-			output_z[N-1] <= z_s;
-			output_z[N-2:N-1-M] <= z_e;
+			output_z[N-1] <= z_s1;
+			output_z[N-2:N-1-M] <= z_e1;
 			output_z[N-2-M:0] <= z_m;
 		end
 
 	
 		else
 		begin
+			a_m <= 0;
+			a_e <= 0;
+			a_s <= 0;
+			
+			b_m <= 0;
+			b_e <= 0;
+			b_s <= 0;
+		
 			a_m1 <= 0;
 			b_m1 <= 0;
+			z_e1 <= 0;
+			z_s1 <= 0;
 			
 			z_s <= 0;
 			z_e <= 0;

+ 143 - 112
src/fpu16/fp_product.sv

@@ -3,182 +3,213 @@ module fp_product #(parameter N=16, M=4)(input_a, input_b, output_z, clk, reset)
 	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 [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 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
 	
-	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];
-			output_z <= z;
-		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;
-			output_z <= 0;
-		end
-	end
-	
 	always_ff @(posedge clk)
 	begin
 		if (~reset)
 		begin
+			// Unpacking the inputs
+			a_s0 <= input_a[N-1];
+			a_e0 <= input_a[N-2:N-2-M];
+			a_m0 <= input_a[N-3-M:0];
+			
+			b_s0 <= input_b[N-1];
+			b_e0 <= input_b[N-2:N-2-M];
+			b_m0 <= input_b[N-3-M:0];
+			
+			// Untouched pipelined registers
+			a_s1 <= a_s0;
+			a_s2 <= a_s1;
+			a_e1 <= a_e0;
+			a_m1 <= a_m0;
+			b_s1 <= b_s0;
+			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_m2 <= z_m1;
+
 			// 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)))
+			if (((a_e0 ==(1<<M)) && (a_m0 != 0)) || ((b_e0 == (1<<M)) && (b_m0 != 0)))
 			begin
-				z_s <= 1;
-				z_e <= (1 << (M+1)) - 1;
-				z_m[N-3-M] <= 1;
-				z_m[N-4-M:0] <= 0;
+				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;
 			end
 			// If a is infinity then return infinity
-			else if (a_e == (1<<M))
+			else if (a_e0 == (1<<M))
 			begin
 				// Unless b is zero, then you return NaN instead
-				if (($signed(b_e) == (-1*((1<<M)-1))) && b_m == 0)
+				if (($signed(b_e0) == (-1*((1<<M)-1))) && b_m0 == 0)
 				begin
-					z_s <= 1;
-					z_e <= (1 << (M+1)) - 1;
-					z_m[N-3-M] <= 1;
-					z_m[N-4-M] <= 0;
+					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;
 				end
 				else
 				// Returning infinity
 				begin
-					z_s <= a_s ^ b_s;
-					z_e <= (1 << (M+1)) - 1;
-					z_m <= 0;
+					z_s0 <= a_s0 ^ b_s0;
+					z_e0 <= (1 << (M+1)) - 1;
+					z_m0 <= 0;
 					flags <= 2'b10;
 				end
 			end
 			// If b is infinity then return infinity
-			else if (b_s == (1<<M))
+			else if (b_s0 == (1<<M))
 			begin
 				//Unless a is zero, then return NaN instead
-				if (($signed(a_e) == (-1*((1<<M)-1))) && a_m == 0)
+				if (($signed(a_e0) == (-1*((1<<M)-1))) && a_m0 == 0)
 				begin
-					z_s <= 1;
-					z_e <= (1 << (M+1)) - 1;
-					z_m[N-3-M] <= 1;
-					z_m[N-4-M] <= 0;
+					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;
 				end
 				else
 				// Returning infinity
 				begin
-					z_s <= a_s ^ b_s;
-					z_e <= (1 << (M+1)) - 1;
-					z_m <= 0;
+					z_s0 <= a_s0 ^ b_s0;
+					z_e0 <= (1 << (M+1)) - 1;
+					z_m0 <= 0;
 					flags <= 2'b10;
 				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)))
+			else if ((($signed(a_e0) == (-1*((1<<M)-1))) && (a_m0 == 0)) || (($signed(b_e0) == (-1*((1<<M)-1))) && (b_m0 == 0)))
 			begin
-				z_s <= a_s ^ b_s;
-				z_e <= 0;
-				z_m <= 0;
+				z_s0 <= a_s0 ^ b_s0;
+				z_e0 <= 0;
+				z_m0 <= 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)
+				if (a_m1[N-3-M] == 0)
 				begin
-					a_m <= a_m << 1;
-					a_e <= a_e - 1;
+					a_m2 <= a_m1 << 1;
+					a_e2 <= a_e1 - 1;
 				end
 				//Just for completion of logic
 				else
 				begin
-					a_m <= a_m;
-					a_e <= a_e;
+					a_m2 <= a_m1;
+					a_e2 <= a_e1;
 				end
 				// If msb of b_m is 0 then shift left and reduce exponent by 1
-				if (b_m[N-3-M] == 0)
+				if (b_m1[N-3-M] == 0)
 				begin
-					b_m <= b_m << 1;
-					b_e <= b_e - 1;
+					b_m2 <= b_m1 << 1;
+					b_e2 <= b_e1 - 1;
 				end
 				//Just for completion of logic
 				else
 				begin
-					b_m <= b_m;
-					b_e <= b_e;
+					b_m2 <= b_m1;
+					b_e2 <= b_e1;
 				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];
+				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
+			begin
+				a_m2 <= a_m1;
+				a_e2 <= a_e1;
+				b_m2 <= b_m1;
+				b_e2 <= b_e1;
+				z_s2 <= z_s1;
+				z_e1 <= z_e0;
+				z_e2 <= z_e1;
+				z_m3 <= z_m2;
+				product <= 0;
 			end
+			
+			// Packing the output
+			output_z[N-1] <= z_s3;
+			output_z[N-2:N-2-M] <= z_e3;
+			output_z[N-3-M:0] <= z_m3;
 		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;
+			a_s0 <= 0;
+			a_e0 <= 0;
+			a_m0 <= 0;
+			
+			a_s1 <= 0;
+			a_e1 <= 0;
+			a_m1 <= 0;
+			
+			a_s2 <= 0;
+			a_e2 <= 0;
+			a_m2 <= 0;
+			
+			b_s0 <= 0;
+			b_e0 <= 0;
+			b_m0 <= 0;
+			
+			b_s1 <= 0;
+			b_e1 <= 0;
+			b_m1 <= 0;
+			
+			b_s2 <= 0;
+			b_e2 <= 0;
+			b_m2 <= 0;
+			
+			z_s0 <= 0;
+			z_e0 <= 0;
+			z_m0 <= 0;
+			
+			z_s1 <= 0;
+			z_e1 <= 0;
+			z_m1 <= 0;
+			
+			z_s2 <= 0;
+			z_e2 <= 0;
+			z_m2 <= 0;
+			
+			z_s3 <= 0;
+			z_e3 <= 0;
+			z_m3 <= 0;
+			
+			product <= 0;
+			
+			flags <= 0;
+			
+			output_z <= 0;
 		end
 	end
 

+ 4 - 4
src/fpu16/fpu16.sv

@@ -40,15 +40,15 @@ module fpu16_tb;
             input_b = test_mem[i][1];
 
             #10;
-            if(result_add != test_mem[i][2]) begin
+            if(result_add != expected_add) begin
                 if(num_err < 20)
-                    $display("FAIL ADD: %H + %H = %H, expected %H", input_a, input_b, result_add, test_mem[i][2]);
+                    $display("FAIL ADD: %H + %H = %H, expected %H", test_mem[i-PIPELINES][0], test_mem[i-PIPELINES][1], result_add, test_mem[i][2]);
                 num_err = num_err + 1;
             end
 
-			if(result_mult != test_mem[i][3]) begin
+			if(result_mult != expected_mult) begin
                 if(num_err < 20)
-                    $display("FAIL MULTIPLY: %H x %H = %H, expected %H", input_a, input_b, result_mult, test_mem[i][3]);
+                    $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]);
                 num_err = num_err + 1;
             end