Browse Source

new pipelined project folder

Oliver Jaison 4 years ago
parent
commit
6f7d61c699
3 changed files with 243 additions and 1 deletions
  1. 1 1
      src/fpu16/fp_adder.sv
  2. 184 0
      src/fpu16/fp_product.sv
  3. 58 0
      src/fpu16/fpu16.sv

+ 1 - 1
src/fpu16/fp_adder.sv

@@ -1,4 +1,4 @@
-module fp_adder #(parameter N=16, M=4)(input_a, input_b, output_z, diff, clk, reset);
+module fp_adder #(parameter N=16, M=4)(input_a, input_b, output_z, clk, reset);
 	input logic [N-1:0] input_a, input_a;
 	input logic clk, reset;
 	output logic [N-1:0] output_z;

+ 184 - 0
src/fpu16/fp_product.sv

@@ -0,0 +1,184 @@
+module fp_product #(parameter N=16, M=4)(input_a, input_a, ouput_z, 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-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 [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];
+		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;			
+		end
+	end
+	
+	always_ff @(posedge clk)
+	begin
+		if (~reset)
+		begin
+			// 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)))
+			begin
+				z_s <= 1;
+				z_e <= (1 << (M+1)) - 1;
+				z_m[N-3-M] <= 1;
+				z_m[N-4-M:0] <= 0;
+				flags <= 2'b01;
+			end
+			// If a is infinity then return infinity
+			else if (a_e == (1<<M))
+			begin
+				// Unless b is zero, then you return NaN instead
+				if (($signed(b_e) == (-1*((1<<M)-1))) && b_m == 0)
+				begin
+					z_s <= 1;
+					z_e <= (1 << (M+1)) - 1;
+					z_m[N-3-M] <= 1;
+					z_m[N-4-M] <= 0;
+					flags <= 2b'01;
+				end
+				else
+				// Returning infinity
+				begin
+					z_s <= a_s ^ b_s;
+					z_e <= (1 << (M+1)) - 1;
+					z_m <= 0;
+					flags <= 2b'10;
+				end
+			end
+			// If b is infinity then return infinity
+			else if (b_s (1<<M))
+			begin
+				//Unless a is zero, then return NaN instead
+				if (($signed(a_e) == (-1*((1<<M)-1))) && a_m == 0)
+				begin
+					z_s <= 1;
+					z_e <= (1 << (M+1)) - 1;
+					z_m[N-3-M] <= 1;
+					z_m[N-4-M] <= 0;
+					flags <= 2b'01;
+				end
+				else
+				// Returning infinity
+				begin
+					z_s <= a_s ^ b_s;
+					z_e <= (1 << (M+1)) - 1;
+					z_m <= 0;
+					flags <= 2b'10;
+				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)))
+			begin
+				z_s <= a_s ^ b_s;
+				z_e <= 0;
+				z_m <= 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)
+				begin
+					a_m <= a_m << 1;
+					a_e <= a_e - 1;
+				end
+				//Just for completion of logic
+				else
+				begin
+					a_m <= a_m;
+					a_e <= a_e;
+				end
+				// If msb of b_m is 0 then shift left and reduce exponent by 1
+				if (b_m[N-3-M] == 0)
+				begin
+					b_m <= b_m << 1;
+					b_e <= b_e - 1;
+				end
+				//Just for completion of logic
+				else
+				begin
+					b_m <= b_m;
+					b_e <= b_e;
+				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];
+			end
+		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;
+		end
+	end
+	
+	output_z <= z;
+endmodule : fp_product

+ 58 - 0
src/fpu16/fpu16.sv

@@ -0,0 +1,58 @@
+module floating_tb;
+	reg reset, clk;
+	logic [15:0] input_a, input_b, result_add, result_mult;
+	logic [15:0] expected_add, expected_mult;
+
+	fp_adder adder1(.input_a(input_a), .input_a(input_b), .output_z(result_add), .clk(clk), .reset(reset));
+
+	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 = 3;
+
+	reg [15:0] test_mem [29:0][3:0];
+
+	initial $readmemh("../scripts/fp16_test.hex", test_mem);
+
+	initial begin
+        static int num_err = 0;
+        static int num_tests = $size(test_mem) * 2;
+
+		clk = 0;
+		reset = 1;
+		  
+		#15;
+		reset = 0;
+
+		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
+            input_a = test_mem[i][0];
+            input_b = test_mem[i][1];
+
+            #10;
+            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]);
+                num_err = num_err + 1;
+            end
+
+			if(result_mult != test_mem[i][3]) begin
+                if(num_err < 20)
+                    $display("FAIL MULTIPLY: %H + %H = %H, expected %H", input_a, input_b, result_mult, test_mem[i][3]);
+                num_err = num_err + 1;
+            end
+
+		end
+		expected_add = 0;
+		expected_mult = 0;
+		#50;
+        $display("Passed %d of %d tests", num_tests-num_err, num_tests);
+        $finish();
+	end
+endmodule : floating_tb