21 Achegas df9f091caa ... 27bd00db7d

Autor SHA1 Mensaxe Data
  Min 27bd00db7d 32bit neural network WIP %!s(int64=4) %!d(string=hai) anos
  Min 997dfecb29 Merge branch 'Oliver_FPA' %!s(int64=4) %!d(string=hai) anos
  Min 34507cd57d mult WIP %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison e67af9f1a5 checking fp_mult.sv %!s(int64=4) %!d(string=hai) anos
  Min 2d55a99e3c new fp mult module WIP %!s(int64=4) %!d(string=hai) anos
  Min 1e4f1528e2 multiplication WIP %!s(int64=4) %!d(string=hai) anos
  Min e35aadc65c Improved fpu adder %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison fab843dd47 debugging fp16_tb %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison ecb6290f9a debugging fp16_tb %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison f95265d149 pipeline works on adder %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison 0cf1a7ac88 ... %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison 9ffa687117 pipe problems %!s(int64=4) %!d(string=hai) anos
  Min 854447288f Shell basename fix %!s(int64=4) %!d(string=hai) anos
  Min 1098628719 Fixed typos %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison 6f7d61c699 new pipelined project folder %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison 0417484054 new pipeline method %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison 7eaf6f6ca7 reworked multiplication module %!s(int64=4) %!d(string=hai) anos
  Min ebda5d8719 Pipelined testbench %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison 26d71e28ca debugging %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison 9551d9f4cd debugging pipeline %!s(int64=4) %!d(string=hai) anos
  Oliver Jaison 63b811e3ce fixed pipelining? %!s(int64=4) %!d(string=hai) anos

+ 2 - 1
scripts/fpu_test_gen.py

@@ -18,6 +18,7 @@ def dtype_size(dtype):
     else:
         raise ValueError(f"Unknown dtype {dtype}")
 
+
 def generate_numbers(cases, dtype=np.float16):
     dsize = dtype_size(dtype)
     x = np.frombuffer(os.urandom(cases * dsize), dtype=dtype)
@@ -38,7 +39,7 @@ def generate_fp_vector(cases, filename, dtype=np.float16, big_endian=False, comp
                 t(y.tobytes()[i * dsize:i * dsize + dsize]).hex(),
                 t(sum.tobytes()[i * dsize:i * dsize + dsize]).hex(),
                 t(mul.tobytes()[i * dsize:i * dsize + dsize]).hex(),
-            ]) + '\n')
+            ]) + f'  // {x[i]:10.6e} {y[i]:10.6e} {sum[i]:10.6e} {mul[i]:10.6e}\n')
     if comp_file is not None:
         gt = x > y
         lt = x < y

+ 28 - 0
simulation/modelsim/wave_floating_tb.do

@@ -0,0 +1,28 @@
+onerror {resume}
+quietly WaveActivateNextPane {} 0
+add wave -noupdate -label CLK /floating_tb/clk
+add wave -noupdate -label RESET /floating_tb/reset
+add wave -noupdate -label {INPUT A} -radix hexadecimal /floating_tb/input_a
+add wave -noupdate -label {INPUT B} -radix hexadecimal /floating_tb/input_b
+add wave -noupdate -label ADD -radix hexadecimal /floating_tb/result_add
+add wave -noupdate -label {ADD expected} -radix hexadecimal /floating_tb/expected_add
+add wave -noupdate -label MULT -radix hexadecimal /floating_tb/result_mult
+add wave -noupdate -label {MULT expected} -radix hexadecimal /floating_tb/expected_mult
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 1} {81 ps} 0}
+quietly wave cursor active 1
+configure wave -namecolwidth 150
+configure wave -valuecolwidth 100
+configure wave -justifyvalue left
+configure wave -signalnamewidth 0
+configure wave -snapdistance 10
+configure wave -datasetprefix 0
+configure wave -rowmargin 4
+configure wave -childrowmargin 2
+configure wave -gridoffset 0
+configure wave -gridperiod 1
+configure wave -griddelta 40
+configure wave -timeline 0
+configure wave -timelineunits ns
+update
+WaveRestoreZoom {0 ps} {124 ps}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 92 - 0
simulation/modelsim/wave_fpu16_tb.do


+ 155 - 50
src/FPA_module_test.sv

@@ -156,69 +156,156 @@ module floating_product #(parameter N=16, M=4)(input_1, input_2, product, clk, r
 	input logic [N-1:0] input_1, input_2;
 	input logic clk, reset;
 	output logic [N-1:0] product;
-
+	
+	logic [2*N-1:0] D0 [7:0];
+	logic [2*N-1:0] Q0 [7:0];
+	logic [2*N-1:0] Q1 [7:0];
+	logic [2*N-1:0] Q2 [7:0];
+	
+	always_comb
+	begin
+		D0[0][N-1:0] = input_1;
+		D0[1][N-1:0] = input_2;
+		D0[2] = 0; // product (output)
+		D0[3] = 0; // multiple for multiplying the mantissa
+		D0[4] = 0; // flag for return NaN
+		D0[5] = 0; // flag for return infinity
+		D0[6] = 0; // flag for return zero
+		D0[7][N-3-M:0] = input_1[N-3-M:0]; // for storing the mantissa of input 1
+	end
 	// sign_x = x[N-1]
 	// exponent_x = x[N-2:N-2-M]
 	// mantissa_x = x[N-3-M:0]
-
-	logic [N-2:N-2-M] sum;
-	logic [2*(N-3-M):0] mult;
-	logic [2*(N-3-M):0] D0 [4:0];
-	logic [2*(N-3-M):0] Q0 [4:0];
-	logic [2*(N-3-M):0] Q1 [4:0];
-	logic [2*(N-3-M):0] Q2 [4:0];
 	
-	// First pipeline stage
+	pipe #(.N(2*N-1), .K(7)) pipe0(.clk(clk), .reset(reset), .D(D0), .Q(Q0));
+	
 	always_comb
+	begin
+		// if input_1 or input_2 is NaN then return NaN
+		if ((Q0[0][N-2:N-2-M] == (1<<M) && Q0[0][N-3-M:0] != 0) || (Q1[0][N-2:N-2-M] == (1<<M) && Q1[0][N-3-M:0] != 0))
 		begin
-			D0[0] = input_1;
-			D0[1] = input_2;
-			D0[2] = 0; // product
-			D0[3] = 0; // sum
-			D0[4] = 0; // mult
+			Q0[2][N-1] = 1;
+			Q0[2][N-2:N-2-M] = (1 << (M+1)) - 1;
+			Q0[2][N-3-M] = 1;
+			Q0[2][N-4-M:0] = 0;
+			Q0[4][0] = 1;
 		end
-		
-	pipe#(.N(2*(N-3-M)), .K(4)) pipe0(.clk(clk), .reset(reset), .D(D0), .Q(Q0));
-
-	// We have assigned an {M+1} bit exponent so we must have a 2^{M} offset
-	assign Q0[3] = Q0[0][N-2:N-2-M] + Q0[1][N-2:N-2-M];
-	assign Q0[2][N-2:N-2-M] = Q0[3] - (1'b1 << M) + 2;
+		// if input 1 is infinity then return infinity
+		else if (Q0[0][N-2:N-2-M] == (1<<M))
+		begin
+			Q0[2][N-1] = Q0[0][N-1] ^ Q0[1][N-1];
+			Q0[2][N-2:N-2-M] = (1 << (M+1)) - 1;
+			Q0[2][N-3-M:0] = 0;
+			Q0[5] = 1;
+			// if input 2 is zero then return NaN
+			if (($signed(Q0[1][N-2:N-2-M]) == (-1*((1<<M)-1))) && (Q0[1][N-3-M:0] == 0))
+			begin
+				Q0[2][N-1] = 1;
+				Q0[2][N-2:N-2-M] = (1 << (M+1)) - 1;
+				Q0[2][N-3-M] = 1;
+				Q0[2][N-4-M:0] = 0;
+				Q0[4][0] = 1;
+			end
+		end
+		// if input 2 is infinity then return infinity
+		else if (Q0[1][N-2:N-2-M] == (1<<M))
+		begin
+			Q0[2][N-1] = Q0[0][N-1] ^ Q0[1][N-1];
+			Q0[2][N-2:N-2-M] = (1 << (M+1)) - 1;
+			Q0[2][N-3-M:0] = 0;
+			Q0[5][0] = 1;
+			// if input 1 is zero then return NaN
+			if (($signed(Q0[0][N-2:N-2-M]) == (-1*((1<<M)-1))) && (Q0[0][N-3-M:0] == 0))
+			begin
+				Q0[2][N-1] = 1;
+				Q0[2][N-2:N-2-M] = (1 << (M+1)) - 1;
+				Q0[2][N-3-M] = 1;
+				Q0[2][N-4-M:0] = 0;
+				Q0[4][0] = 1;
+			end
+		end
+		// if input 1 is zero then return zero
+		else if (($signed(Q0[0][N-2:N-2-M]) == (-1*((1<<M)-1))) && (Q0[0][N-3-M:0] == 0))
+		begin
+			Q0[2][N-1] = Q0[0][N-1] ^ Q0[1][N-1];
+			Q0[2][N-2:N-2-M] = 0;
+			Q0[2][N-3-M:0] = 0;
+			Q0[6][0] = 1;
+		end
+		// if input 2 is zero then return zero
+		else if (($signed(Q0[1][N-2:N-2-M]) == (-1*((1<<M)-1))) && (Q0[1][N-3-M:0] == 0))
+		begin
+			Q0[2][N-1] = Q0[0][N-1] ^ Q0[1][N-1];
+			Q0[2][N-2:N-2-M] = 0;
+			Q0[2][N-3-M:0] = 0;
+			Q0[6][0] = 1;
+		end
+	end
+	
+	pipe #(.N(2*N-1), .K(7)) pipe1(.clk(clk), .reset(reset), .D(Q0), .Q(Q1));
 	
-	// Second pipeline stage
-	pipe#(.N(2*(N-3-M)), .K(4)) pipe1(.clk(clk), .reset(reset), .D(Q0), .Q(Q1));
-
 	always_comb
+	begin
+	// If none of the return flags have been triggered
+		if ((Q1[4][0] && Q1[5][0] && Q1[6][0]) != 1)
 		begin
-				// Setting the mantissa of the output
-				Q1[4] = Q1[0][N-3-M:0] * Q1[1][N-3-M:0];
-				if (Q1[4][N-3-M]) Q1[2][N-3-M:0] = Q1[4][2*(N-3-M):2*(N-3-M)-9];
-				else Q1[2][N-3-M:0] = Q1[4][2*(N-3-M):2*(N-3-M)-9] << 1;
-				Q1[2][N-1] = Q1[0][N-1] ^ Q1[1][N-1];
+			// if msb of input 1 mantissa is not 1 then shift left by 1 and reduce exponent by 1
+			if (Q1[0][N-3-M] != 1)
+			begin
+				Q1[0][N-3-M:0] = Q1[0][N-3-M:0] << 1;
+				Q1[0][N-2:N-2-M] = Q1[0][N-2:N-2-M] - 1;
+			end
+			// if msb of input 2 mantissa is not 1 then shift left by 1 and reduce exponent by 1
+			if (Q1[1][N-3-M] != 1)
+			begin
+				Q1[1][N-3-M:0] = Q1[1][N-3-M:0] << 1;
+				Q1[1][N-2:N-2-M] = Q1[1][N-2:N-2-M] - 1;
+			end
+			Q1[2][N-1] = Q1[2][N-1] ^ Q1[2][N-1]; // ouput sign = input_1 sign xor input_2 sign
+			Q1[2][N-2:N-2-M] = Q1[0][N-2:N-2-M] + Q1[1][N-2:N-2-M] - (1<<M); // out exp = in1 exp + in2 exp - 2**M
+			// multiplying mantissa
+			for (int i = 0; i<N-2-M; i++)
+			begin
+				// multiplying each digit of input 2 by all of input 1 shifting the bits left each time and adding result to the array
+				if (Q1[1][i] == 1)
+				begin
+					Q1[3] = Q1[3] +(Q1[7]<<i);
+				end
+				else
+				begin
+					Q1[3] = Q1[3] + 0;
+				end
+			end
+			// Assigning the top set of bits to the mantissa of the output 
+			Q1[2][N-3-M:0] = Q1[3][2*N-1:2*N-1-N-3-M];
 		end
+	end
 	
-	//Final Pipeline stage
-	pipe#(.N(2*N-3-M), .K(4)) pipe2(.clk(clk), .reset(reset), .D(Q1), .Q(Q2));
+	pipe #(.N(2*N-1), .K(7)) pipe2(.clk(clk), .reset(reset), .D(Q1), .Q(Q2));
 	assign product = Q2[2][N-1:0];
+	
 endmodule : floating_product
 
 
 
-module pipe #(parameter N=16)(clk, reset, Q, D);
+module pipe #(parameter N, K)(clk, reset, Q, D);
 	input logic clk, reset;
-	input logic [N-1:0] D;
-	output reg [N-1:0] Q;
-	reg [N-1:0] in_pipe;
-	
-	always @(posedge clk or negedge reset)
-		begin
-			if(reset) in_pipe = 0;
-			else in_pipe = D;
-		end
+	input logic [N:0] D [K:0];
+	output reg [N:0] Q [K:0];
+	reg [N:0] in_pipe [K:0];
 	
-	always @(posedge clk or negedge reset)
+	always_ff @(posedge clk or negedge reset)
 		begin
-			if(reset) Q = 0;
-			else Q = in_pipe;
+			if(reset) 
+				begin
+					in_pipe <= '{default:0};
+					Q <= '{default:0};
+				end
+			else 
+				begin
+					in_pipe <= D;
+					Q <= in_pipe;
+				end
 		end
 endmodule : pipe
 
@@ -228,22 +315,37 @@ module floating_tb;
 	reg reset, clk;
 	logic [15:0] input_a, input_b, result_add, result_mult;
 	logic [4:0] diff;
+	logic [15:0] expected_add, expected_mult;
 
-	floating_add adder1(.input_1(input_a), .input_2(input_b), .sum(result_add), .diff(diff));
-
-	floating_product multiplier1(.input_1(input_a), .input_2(input_b), .product(result_mult));
+	floating_add adder1(.input_1(input_a), .input_2(input_b), .sum(result_add), .diff(diff), .clk(clk), .reset(reset));
 
+	floating_product multiplier1(.input_1(input_a), .input_2(input_b), .product(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 $readmemh("scripts/fp16_test.hex", test_mem);
 
 	initial begin
         static int num_err = 0;
         static int num_tests = $size(test_mem) * 2;
 
-        for (int i=0; i < $size(test_mem); i++) begin
+		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];
 
@@ -260,7 +362,10 @@ module floating_tb;
                 num_err = num_err + 1;
             end
 
-        end
+		end
+		expected_add = 0;
+		expected_mult = 0;
+		#50;
         $display("Passed %d of %d tests", num_tests-num_err, num_tests);
         $finish();
 	end

+ 168 - 0
src/fpu16/fp_adder.sv

@@ -0,0 +1,168 @@
+typedef enum logic [1:0]{
+    greater_a,
+    greater_b,
+    equal_ab
+
+} grater_state;
+
+module fp_adder#(parameter N=16, M=5)(input_a, input_b, output_z, clk, reset);
+    localparam K=N-M-1;  // Size of mantissa
+
+    input reg [N-1:0] input_a, input_b;
+    input logic clk, reset;
+    output reg [N-1:0] output_z;
+
+    reg [K-1:0] a_m0, b_m0; // mantissa
+    reg [K-1:0] a_m1, b_m1, z_m2;
+
+    reg [K*2-1:0] z_m1a, z_m1b, z_m1z;  // Double mantissa
+    reg z_m1s;
+
+    reg [M-1:0] a_e0, b_e0; // exponent
+    reg [M-1:0] z_e1, z_e2;
+
+    reg a_s0, b_s0; // sign
+    reg a_s1, b_s1, z_s1, z_s2;
+
+    grater_state greater; // 01 for a, 10 for b, 11 for both and 00 for neither
+    reg [M:0] abs; // For the absolute difference between exponents
+
+    always_comb begin
+        output_z = {z_s2, z_e2, z_m2};
+        z_m1a = {a_m1, {K{1'b0}}};
+        z_m1b = {b_m1, {K{1'b0}}};
+
+        // If a has the bigger exponent
+        if (greater == greater_a)
+            begin
+                // If the signs are the same then add
+                if (a_s1 == b_s1) {z_m1s, z_m1z} = z_m1a+(z_m1b >> abs - 2);
+                    // If they are different then subtract
+                else {z_m1s, z_m1z} = z_m1a-(z_m1b >> abs - 2);
+            end
+            // If b has the bigger exponent
+        else if (greater == greater_b)
+            begin
+                // If the signs are the same then add
+                if (a_s1 == b_s1) {z_m1s, z_m1z} = z_m1b+(z_m1a >> abs - 2);
+                    // If they are different then subtract
+                else {z_m1s, z_m1z} = z_m1b-(z_m1a >> abs - 2);
+            end
+            // If the exponents are equal
+        else
+            begin
+                // If the signs are the same then add
+                if (a_s1 == b_s1) {z_m1s, z_m1z} = (z_m1a + z_m1b) >> 1;
+                    // If the signs are different then subtract
+                else
+                    begin
+                        // First checking which has the bigger mantissa
+                        if (a_m1 > b_m1) {z_m1s, z_m1z} = z_m1a-z_m1b;
+                        else if (b_m1 > a_m1) {z_m1s, z_m1z} = z_m1b-z_m1a;
+                            // If the mantissa are the same as well then the result should be 0
+                        else {z_m1s, z_m1z} = 0;
+                    end
+            end
+    end
+
+    always_ff @(posedge clk)
+        begin
+            if (~reset)
+                begin
+                    // Unpacking the inputs
+                    a_m0 <= input_a[K-1:0];
+                    a_e0 <= input_a[N-2:K];
+                    a_s0 <= input_a[N-1];
+
+                    b_m0 <= input_b[K-1:0];
+                    b_e0 <= input_b[N-2:K];
+                    b_s0 <= input_b[N-1];
+
+                    // Second stage
+                    a_m1 <= a_m0;
+                    a_s1 <= a_s0;
+                    b_m1 <= b_m0;
+                    b_s1 <= b_s0;
+
+                    z_e2 <= z_e1;
+                    z_s2 <= z_s1;
+
+                    // If input_a has the bigger exponent then flag it with greater and find the absolute difference
+                    if (a_e0 > b_e0)
+                        begin
+                            greater <= greater_a;
+                            abs <= a_e0 - b_e0 - 1;
+                            z_s1 <= a_s0;
+                            z_e1 <= a_e0;
+                        end
+
+                        // If input_a has the bigger exponent then flag it with greater and find the absolute difference
+                    else if (b_e0 > a_e0)
+                        begin
+                            greater <= greater_b;
+                            abs <= b_e0 - a_e0 - 1;
+                            z_s1 <= b_s0;
+                            z_e1 <= b_e0;
+                        end
+
+                        // If the inputs have equal exponent
+                    else
+                        begin
+                            greater <= equal_ab;
+                            abs <= 0;
+                            z_e1 <= a_e0;
+                            // Assigning the overall sign based on the difference between the mantissa
+                            if (a_m0 > b_m0) z_s1 <= a_s0;
+                            else if (b_m0 > a_m0) z_s1 <= b_s0;
+                            else z_s1 <= 0;
+                        end
+
+                    // Condition for overflow is that it sets the output to the larger input
+                    if (abs > K) // Shifting by N-1-M would give 0
+                        begin
+                            z_m2 <= (greater == greater_a) ? a_m1 : b_m1;
+
+                            // Input a is larger and is translated to the output
+                            // if (greater == greater_a) z_m0 <= a_m1;
+
+                            // Input b is larger and is translated to the output
+                            // else if (greater == greater_b) z_m0 <= b_m1;
+
+                            // Shouldn't happen as abs should be 0 for this to occur
+                            // else begin
+                            // 	if (a_m1 >= b_m1) z_m0 <= a_m1; // Equal exponents but a has the larger mantissa
+                            // 	else if (b_m1 > a_m1) z_m0 <= b_m1; // Equal exponents but b has the larger mantissa
+                            // end
+                        end
+
+                    else
+                        begin
+							z_m2 <= z_m1z[K*2-1:K];
+                        end
+                end
+            else
+                begin
+                    a_m0 <= 0;
+                    a_e0 <= 0;
+                    a_s0 <= 0;
+
+                    b_m0 <= 0;
+                    b_e0 <= 0;
+                    b_s0 <= 0;
+
+                    a_m1 <= 0;
+                    b_m1 <= 0;
+                    z_e2 <= 0;
+                    z_s2 <= 0;
+
+                    z_s1 <= 0;
+                    z_e1 <= 0;
+                    z_s2 <= 0;
+                    z_e2 <= 0;
+                    z_m2 <= 0;
+
+                    greater <= equal_ab;
+                    abs <= 0;
+                end
+        end
+endmodule : fp_adder

+ 250 - 0
src/fpu16/fp_mult.sv

@@ -0,0 +1,250 @@
+`include "lead_zero.sv"
+
+
+module lead_zeros_enc #(K=10)(in, out);
+    localparam L = $clog2(K) +1;
+
+    input wire [K-1:0] in;
+    output logic [L-1:0] out;
+    always_comb begin
+        if(K == 10) begin
+            casez (in)
+                10'b00000_00000 :out = 4'd10;
+                10'b00000_0000? :out = 4'd9;
+                10'b00000_000?? :out = 4'd8;
+                10'b00000_00??? :out = 4'd7;
+                10'b00000_0???? :out = 4'd6;
+                10'b00000_????? :out = 4'd5;
+                10'b0000?_????? :out = 4'd4;
+                10'b000??_????? :out = 4'd3;
+                10'b00???_????? :out = 4'd2;
+                10'b0????_????? :out = 4'd1;
+                default : out = 4'd0;
+            endcase
+        end
+        else if (K == 23) begin
+            casez (in)
+                23'b000_00000_00000_00000_00000 :out = 5'd23;
+                23'b000_00000_00000_00000_0000? :out = 5'd22;
+                23'b000_00000_00000_00000_000?? :out = 5'd21;
+                23'b000_00000_00000_00000_00??? :out = 5'd20;
+                23'b000_00000_00000_00000_0???? :out = 5'd19;
+                23'b000_00000_00000_00000_????? :out = 5'd18;
+                23'b000_00000_00000_0000?_????? :out = 5'd17;
+                23'b000_00000_00000_000??_????? :out = 5'd16;
+                23'b000_00000_00000_00???_????? :out = 5'd15;
+                23'b000_00000_00000_0????_????? :out = 5'd14;
+                23'b000_00000_00000_?????_????? :out = 5'd13;
+                23'b000_00000_0000?_?????_????? :out = 5'd12;
+                23'b000_00000_000??_?????_????? :out = 5'd11;
+                23'b000_00000_00???_?????_????? :out = 5'd10;
+                23'b000_00000_0????_?????_????? :out = 5'd9;
+                23'b000_00000_?????_?????_????? :out = 5'd8;
+                23'b000_0000?_?????_?????_????? :out = 5'd7;
+                23'b000_000??_?????_?????_????? :out = 5'd6;
+                23'b000_00???_?????_?????_????? :out = 5'd5;
+                23'b000_0????_?????_?????_????? :out = 5'd4;
+                23'b000_?????_?????_?????_????? :out = 5'd3;
+                23'b00?_?????_?????_?????_????? :out = 5'd2;
+                23'b0??_?????_?????_?????_????? :out = 5'd1;
+                default : out = 5'd0;
+            endcase
+        end
+    end
+endmodule : lead_zeros_enc
+
+module fp_mult #(parameter N=16, M=5)(input_a, input_b, output_z, clk, reset);
+    localparam K=N-M-1;  // Size of mantissa
+    localparam L=$clog2(10);  // Size of shifting representation
+
+    input logic [N-1:0] input_a, input_b;
+    input logic clk, reset;
+    output logic [N-1:0] output_z;
+
+    // ====================
+    // Stage 0 store input
+    // ====================
+
+    reg [M-1:0] a_e0, b_e0;
+    reg [K-1:0] a_m0, b_m0;
+    reg  a_s0, b_s0;
+
+    always_ff @(posedge clk) begin
+        {a_s0, a_e0, a_m0} <= input_a;
+        {b_s0, b_e0, b_m0} <= input_b;
+    end
+
+    // ====================
+    // Stage 1 denormalise0
+    // ====================
+
+    reg [M-1:0] a_e1, b_e1;
+    reg [K-1:0] a_m1, b_m1;
+    reg z_s1;
+
+    // leading zeros
+    wire [L-1:0] a_z1w, b_z1w;
+    reg [L-1:0] a_z1, b_z1;
+
+    lead_zeros_enc #(.K(K)) lz_a1(a_m1, a_z1w);
+    lead_zeros_enc #(.K(K)) lz_b1(b_m1, b_z1w);
+
+    always_ff @(posedge clk) begin
+        z_s1 <= a_s0 ^ b_s0;  // We don't need to track and propagate signs
+        {a_e1, a_m1} <= {a_e0, a_m0};
+        {b_e1, b_m1} <= {b_e0, b_m0};
+        a_z1 <= a_z1w;
+        b_z1 <= b_z1w;
+    end
+
+    // ====================
+    // Stage 2 denormalise1
+    // ====================
+
+    reg [M-1:0] a_e2, b_e2;
+    reg [K-1:0] a_m2, b_m2;
+    reg z_s2;
+
+    always_ff @(posedge clk) begin
+        a_e2 <= a_e1 - a_z1;
+        a_m2 <= a_m1 << a_z1;
+
+        b_e2 <= b_e1 - b_z1;
+        b_m2 <= b_m1 << b_z1;
+
+        z_s2 <= z_s1;
+    end
+
+    // ====================
+    // Stage 3 product
+    // ====================
+
+    reg z_s3;
+    reg [M-1:0] z_e3;
+    reg [K*2-1:0] z_p3;  // product is double mantissa
+
+    always_ff @(posedge clk) begin
+        z_e3 <= a_e2 + b_e2 + 1;
+        z_p3 <= a_m2 * b_m2;
+        z_s3 <= z_s2;
+    end
+
+    // ====================
+    // Stage 4 unpack/normalise0
+    // ====================
+
+    reg z_s4;
+    reg [M-1:0] z_e4;
+    reg [K-1:0] z_m4;
+    reg [1:0] z_bits4; // guard and round_bit
+    reg z_sticky4;
+
+
+    wire [K-1:0] p3;
+    // leading zeros
+    wire [3:0] z_z4w;
+    reg [3:0] z_z4;
+
+    assign p3 = z_p3[K*2-1:K];
+    lead_zeros_enc #(.K(K)) lz_p3(p3, z_z4w);
+
+    always_ff @(posedge clk) begin
+        z_m4 <= p3;
+        z_bits4 <= z_p3[K:K-2];
+        z_sticky4 <= z_p3[K-2:0] != 0;
+        z_z4 <= z_z4w;
+
+        z_e4 <= z_e3;
+        z_s4 <= z_s3;
+    end
+
+    // ====================
+    // Stage 5 normalise1
+    // ====================
+
+    reg z_s5;
+    reg [M-1:0] z_e5;
+    reg [K-1:0] z_m5;
+
+    reg [1:0] z_bits5; // guard and round_bit
+    reg z_sticky5;
+
+    always_ff @(posedge clk) begin
+        z_e5 <= z_e4 - z_z4;
+        z_m5 <= z_m4 << z_z4;
+
+        case (z_z4)
+            4'd0: begin
+                z_bits5 <= z_bits4;
+            end
+            4'd1: begin
+                z_m5[0] <= z_bits4[0];
+                z_bits5 <= {z_bits4[1], 1'b0};
+            end
+            4'd2: begin
+                z_m5[1-:2] <= z_bits4; // ?
+                z_bits5 <= 2'b00;
+            end
+            default : begin
+                z_m5[z_z4-1-:2] <= z_bits4; // ?
+                z_bits5 <= 2'b00;
+            end
+        endcase
+
+        z_sticky5 <= z_sticky4;
+        z_s5 <= z_s4;
+    end
+
+    // ====================
+    // Stage 6 normalise2
+    // ====================
+    reg z_s6;
+    reg [M-1:0] z_e6;
+    reg [K-1:0] z_m6;
+
+    reg [1:0] z_bits6;
+    reg z_sticky6;
+
+
+    always_ff @(posedge clk) begin
+        // TODO: Fix this stage
+        // if ($signed(z_e5) < -126) begin
+        //     shift6 <= $signed(z_e5) -126;
+        // end else begin
+        //     shift6 <= 0;
+        // end
+
+        z_s6 <= z_s5;
+        z_e6 <= z_e5;
+        z_m6 <= z_m5;
+        z_bits6 <= z_bits5;
+        z_sticky6 <= z_sticky5;
+    end
+
+    // ====================
+    // Stage 7 round
+    // ====================
+    reg z_s7;
+    reg [M-1:0] z_e7;
+    reg [K-1:0] z_m7;
+
+    always_ff @(posedge clk) begin
+        if (z_bits6[0] && (z_bits6[1] | z_sticky6 | z_m6[0])) begin
+            z_m7 <= z_m6 + 1;
+            // TODO: Check for all 1s
+        end else begin
+            z_m7 <= z_m6;
+        end
+        z_e7 <= z_e6;
+        z_s7 <= z_s6;
+    end
+
+    // ====================
+    // Stage 8 pack
+    // ====================
+    // This stage is skipped as it checks for overflow
+
+
+    always_comb output_z = {z_s7, z_e7, z_m7};
+
+endmodule : fp_mult

+ 222 - 0
src/fpu16/fp_product.sv

@@ -0,0 +1,222 @@
+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 [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 [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)
+		begin
+			// Unpacking the inputs
+			a_s0 <= input_a[N-1];
+			a_e0 <= input_a[N-2:N-2-M] - (1<<M);
+			a_m0 <= input_a[N-3-M:0];
+			
+			b_s0 <= input_b[N-1];
+			b_e0 <= input_b[N-2:N-2-M] - (1<<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_s2 <= z_s1;
+			z_s4 <= z_s3;
+			z_e4 <= z_e3;
+			z_m2 <= z_m1;
+			z_m3 <= z_m2;
+
+			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];
+
+			// 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_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))
+			begin
+				// Unless b is zero, then you return NaN instead
+				if (($signed(b_e0) == (-1*((1<<M)-1))) && b_m0 == 0)
+				begin
+					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_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
+			else if (b_s0 == (1<<M))
+			begin
+				//Unless a is zero, then return NaN instead
+				if (($signed(a_e0) == (-1*((1<<M)-1))) && a_m0 == 0)
+				begin
+					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_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_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 (flags1 == flag_none)
+			begin
+				// If msb of a_m is 0 then shift left and reduce exponent by 1
+				if (a_m1[K-1] == 0)
+				begin
+					a_m2 <= a_m1 << 1;
+					a_e2 <= a_e1 - 1;
+				end
+				//Just for completion of logic
+				else
+				begin
+					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_m1[K-1] == 0)
+				begin
+					b_m2 <= b_m1 << 1;
+					b_e2 <= b_e1 - 1;
+				end
+				//Just for completion of logic
+				else
+				begin
+					b_m2 <= b_m1;
+					b_e2 <= b_e1;
+				end
+			end
+			
+			else
+			begin
+				a_m2 <= a_m1;
+				a_e2 <= a_e1;
+				b_m2 <= b_m1;
+				b_e2 <= b_e1;
+				z_s3 <= z_s2;
+				z_e2 <= z_e1;
+				z_e3 <= z_e2;
+				z_m4 <= z_m3;
+				z_p3 <= 0;
+			end
+		end
+		else
+		begin
+			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_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;
+			
+			z_s4 <= 0;
+			z_e4 <= 0;
+			z_m4 <= 0;
+			
+			z_p3 <= 0;
+			
+			flags1 <= flag_none;
+		end
+	end
+
+endmodule : fp_product

+ 91 - 0
src/fpu16/fpu16.sv

@@ -0,0 +1,91 @@
+`include "fp_adder.sv"
+`include "fp_product.sv"
+`include "fp_mult.sv"
+
+
+module fpu16_tb;
+	localparam N=32;
+	localparam M=8;
+
+	reg reset, clk;
+	logic [N-1:0] input_a, input_b, result_add, result_mult;
+	logic [31:0] expected_add, expected_mult;
+
+	fp_adder #(.N(N), .M(M)) adder1(
+		.clk(clk),
+		.reset(reset),
+		.input_a(input_a),
+		.input_b(input_b),
+		.output_z(result_add)
+	);
+
+	fp_product #(.N(N), .M(M)) multiplier1(
+		.clk(clk),
+		.reset(reset),
+		.input_a(input_a),
+		.input_b(input_b),
+		.output_z(result_mult)
+	);
+	
+	initial forever #5 clk = ~clk;
+	localparam PIPELINES_ADD = 2;
+	localparam PIPELINES_MUL = 7;
+
+	reg [N-1:0] test_mem [29:0][3:0];
+
+	initial $readmemh("scripts/fp32_test.hex", test_mem);
+
+	reg [N-2-M:0] exp0_m;
+	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_s, exp0_e, exp0_m} = expected_add;
+		{exp1_s, exp1_e, exp1_m} = expected_mult;
+	end
+
+	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_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_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_MUL][0], test_mem[i-PIPELINES_MUL][1], 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 : fpu16_tb

+ 58 - 0
src/fpu16/lead_zero.sv

@@ -0,0 +1,58 @@
+module count_lead_zero #(
+    parameter W_IN = 64, // Must be power of 2, >=2
+    parameter W_OUT = $clog2(W_IN) // Let this default
+) (
+    input wire  [W_IN-1:0] in,
+    output wire [W_OUT-1:0] out
+);
+
+    generate
+        if (W_IN == 2) begin: base
+            assign out = !in[1];
+        end else begin: recurse
+            wire [W_OUT-2:0] half_count;
+            wire [W_IN / 2-1:0] lhs = in[W_IN / 2 +: W_IN / 2];
+            wire [W_IN / 2-1:0] rhs = in[0        +: W_IN / 2];
+            wire left_empty = ~|lhs;
+
+            count_lead_zero #(
+                .W_IN (W_IN / 2)
+            ) inner (
+                .in  (left_empty ? rhs : lhs),
+                .out (half_count)
+            );
+
+            assign out = {left_empty, half_count};
+        end
+    endgenerate
+
+endmodule : count_lead_zero
+
+
+module count_lead_zero_tb;
+
+    reg [15:0] x0;
+    wire [3:0] y0;
+    count_lead_zero #(16) clz16(x0, y0);
+
+
+    task test_clz;
+        input b;
+        #5;
+        if(y0 != b) $display("FAIL %B: got %d expected %d", x0, y0, b);
+        else $display("OK %B: got %d", x0, y0);
+    endtask : test_clz
+
+    initial begin
+        x0 = 0;
+        test_clz(16);
+        x0 = 1;
+        test_clz(15);
+        for(int i=14; i>=0; i--) begin
+            x0 <<= 1;
+            x0[0] = 1;
+            test_clz(i);
+        end
+    end
+
+endmodule : count_lead_zero_tb

+ 481 - 0
src/fpu32p/div32.v

@@ -0,0 +1,481 @@
+// Adopted from
+// https://github.com/naveethmeeran/floating-point-coprocessor/blob/master/single_precision/single_precision.srcs/sources_1/new/singlediv.v
+
+module singlediv(
+    input [31:0] a,
+    input [31:0] b,
+    input clk,
+    output [31:0] out
+);
+    wire [28:0] mantissaout2;
+    wire ql,ql1,ql2,ql3,ql4,ql5,ql6,ql7,ql8,ql9,ql10,ql11,ql12,ql13,ql14,ql15,ql16,ql17,ql18,ql19,ql20,ql21,ql22,ql23,ql24,ql25,ql26,ql27,ql28;
+    wire [25:0] c25,c26,c27,c28,A25,A26,A27,A28,A24,c24,A23,c23,A22,c22,A,c,A1,c1,A2,c2,A3,c3,A4,c4,A5,c5,A6,c6,A7,c7,A8,c8,A9,c9,A10,c10,A11,c11,A12,c12,A13,c13,A14,c14,A15,c15,A16,c16,A17,c17,A18,c18,A19,c19,A20,c20,A21,c21;
+    wire [24:0] mantissaa,q,q1,q2,q3,q4,q5,q6,q7,q8,q9,q10,q11,q12,q13,q14,q15,q16,q17,q18,q19,q20,q21,q22,q23,q24,q25,q26,q27,q28;
+    wire [25:0] mantissab,mantissamdash;
+    wire [7:0] exponenta,exponentb,outexponent;
+    wire signa,signb,outsign;
+    reg [28:0] mantissaout;
+    reg [2:0] ext,ext1,ext2;
+    reg [4:0] shift;
+    reg [24:0] outmantissa,outmantissa1,outmantissa2;
+    reg signout26,signout27,signout28,signout29,signout25,signout24,signout,signout1,signout2,signout3,signout4,signout5,signout6,signout7,signout8,signout9,signout10,signout11,signout12,signout13,signout14,signout15,signout16,signout17,signout18,signout19,signout20,signout21,signout22,signout23;
+    reg [25:0] Areg,Areg1,Areg2,Areg3,Areg4,Areg5,Areg6,Areg7,Areg8,Areg9,Areg10,Areg11,Areg12,Areg13,Areg14,Areg15,Areg16,Areg17,Areg18,Areg19,Areg20,Areg21,Areg22,Areg23,Areg24,Areg25,Areg26,Areg27,Areg28;
+    reg [25:0] mdash26,mdash27,mdash28,m26,m27,m28,m25,mdash25,m24,mdash24,m23,mdash23,m,mdash,m1,mdash1,m2,mdash2,m3,mdash3,m4,mdash4,m5,mdash5,m6,m7,m8,m9,m10,mdash6,mdash7,mdash8,mdash9,mdash10,m11,m12,m13,m14,m15,m16,m17,m18,m19,m20,m21,m22,mdash11,mdash12,mdash13,mdash14,mdash15,mdash16,mdash17,mdash18,mdash19,mdash20,mdash21,mdash22;
+    reg [24:0] qreg,qreg1,qreg2,qreg3,qreg4,qreg5,qreg6,qreg7,qreg8,qreg9,qreg10,qreg11,qreg12,qreg13,qreg14,qreg15,qreg16,qreg17,qreg18,qreg19,qreg20,qreg21,qreg22,qreg23,qreg24,qreg25,qreg26,qreg27,qreg28;
+    reg [7:0] exponentout26,exponentout27,exponentout28,exponentout29,exponentout25,exponentout24,exponentout,exponentout1,exponentout2,exponentout3,exponentout4,exponentout5,exponentout6,exponentout7,exponentout8,exponentout9,exponentout10,exponentout11,exponentout12,exponentout13,exponentout14,exponentout15,exponentout16,exponentout17,exponentout18,exponentout19,exponentout20,exponentout21,exponentout22,exponentout23;
+    function [4:0] leadingzerodetector;
+        input [28:0] mant;
+        reg [28:0]ma;
+        reg [4:0] co;
+        begin
+            ma=mant;
+            co=5'b0;
+            repeat(29)
+                begin
+                    if (ma[28]==1'b0)
+                        begin
+                            co=co+1;
+                            ma=ma<<1;
+                        end
+                end
+            leadingzerodetector=co;
+        end
+    endfunction
+    assign signa=a[31];
+    assign signb=b[31];
+    assign outsign=signa^signb;
+    //assign gre=a[22:0]>b[22:0]?1'b0:1'b1;
+    assign exponenta=a[22:0]>b[22:0]?a[30:23]:a[30:23]-1'b1;
+
+    assign exponentb=b[30:23];
+    assign outexponent=exponenta-exponentb+127;
+    //assign ebit=a[22];
+    assign mantissaa=a[22:0]>b[22:0]?{1'b0,1'b1,a[22:0]}:{1'b0,1'b1,a[22:0]}<<1;
+    //assign mantissaa={1'b0,1'b1,a[22:0]};
+    assign mantissab={1'b0,1'b0,1'b1,b[22:0]};
+    assign mantissamdash=(~mantissab)+1'b1;
+    always@(posedge clk)
+        begin
+            Areg=26'd0;
+            qreg=mantissaa;
+            m=mantissab;
+            mdash=mantissamdash;
+            //exbit=ebit;
+            signout=outsign;
+            exponentout=outexponent;
+            //agre=gre;
+        end
+    assign {A,q}={Areg,qreg}<<1;
+    assign c=Areg[25]?A+m:A+mdash;
+    assign ql=~c[25];
+    always@(posedge clk)
+        begin
+            Areg1=c;
+            qreg1={q[24:1],ql};
+            m1=m;
+            mdash1=mdash;
+            //exbit1=exbit;
+            signout1=signout;
+            exponentout1=exponentout;
+            //agre1=agre;
+        end
+    assign {A1,q1}={Areg1,qreg1}<<1;
+    assign c1=Areg1[25]?A1+m1:A1+mdash1;
+    assign ql1=~c1[25];
+    always@(posedge clk)
+        begin
+            Areg2=c1;
+            qreg2={q1[24:1],ql1};
+            m2=m1;
+            mdash2=mdash1;
+            //exbit2=exbit1;
+            signout2=signout1;
+            exponentout2=exponentout1;
+            //agre2=agre1;
+        end
+    assign {A2,q2}={Areg2,qreg2}<<1;
+    assign c2=Areg2[25]?A2+m2:A2+mdash2;
+    assign ql2=~c2[25];
+    always@(posedge clk)
+        begin
+            Areg3=c2;
+            qreg3={q2[24:1],ql2};
+            m3=m2;
+            mdash3=mdash2;
+            //exbit3=exbit2;
+            signout3=signout2;
+            exponentout3=exponentout2;
+            //agre3=agre2;
+        end
+    assign {A3,q3}={Areg3,qreg3}<<1;
+    assign c3=Areg3[25]?A3+m3:A3+mdash3;
+    assign ql3=~c3[25];
+    always@(posedge clk)
+        begin
+            Areg4=c3;
+            qreg4={q3[24:1],ql3};
+            m4=m3;
+            mdash4=mdash3;
+            //exbit4=exbit3;
+            signout4=signout3;
+            exponentout4=exponentout3;
+            //agre4=agre3;
+        end
+    assign {A4,q4}={Areg4,qreg4}<<1;
+    assign c4=Areg4[25]?A4+m4:A4+mdash4;
+    assign ql4=~c4[25];
+    always@(posedge clk)
+        begin
+            Areg5=c4;
+            qreg5={q4[24:1],ql4};
+            m5=m4;
+            mdash5=mdash4;
+            //exbit5=exbit4;
+            signout5=signout4;
+            exponentout5=exponentout4;
+            //agre5=agre4;
+        end
+    assign {A5,q5}={Areg5,qreg5}<<1;
+    assign c5=Areg5[25]?A5+m5:A5+mdash5;
+    assign ql5=~c5[25];
+    always@(posedge clk)
+        begin
+            Areg6=c5;
+            qreg6={q5[24:1],ql5};
+            m6=m5;
+            mdash6=mdash5;
+            //exbit6=exbit5;
+            signout6=signout5;
+            exponentout6=exponentout5;
+            //agre6=agre5;
+        end
+    assign {A6,q6}={Areg6,qreg6}<<1;
+    assign c6=Areg6[25]?A6+m6:A6+mdash6;
+    assign ql6=~c6[25];
+    always@(posedge clk)
+        begin
+            Areg7=c6;
+            qreg7={q6[24:1],ql6};
+            m7=m6;
+            mdash7=mdash6;
+            //exbit7=exbit6;
+            signout7=signout6;
+            exponentout7=exponentout6;
+            //agre7=agre6;
+        end
+    assign {A7,q7}={Areg7,qreg7}<<1;
+    assign c7=Areg7[25]?A7+m7:A7+mdash7;
+    assign ql7=~c7[25];
+    always@(posedge clk)
+        begin
+            Areg8=c7;
+            qreg8={q7[24:1],ql7};
+            m8=m7;
+            mdash8=mdash7;
+            //exbit8=exbit7;
+            signout8=signout7;
+            exponentout8=exponentout7;
+            //agre8=agre7;
+        end
+    assign {A8,q8}={Areg8,qreg8}<<1;
+    assign c8=Areg8[25]?A8+m8:A8+mdash8;
+    assign ql8=~c8[25];
+    always@(posedge clk)
+        begin
+            Areg9=c8;
+            qreg9={q8[24:1],ql8};
+            m9=m8;
+            mdash9=mdash8;
+            //exbit9=exbit8;
+            signout9=signout8;
+            exponentout9=exponentout8;
+            //agre9=agre8;
+        end
+    assign {A9,q9}={Areg9,qreg9}<<1;
+    assign c9=Areg9[25]?A9+m9:A9+mdash9;
+    assign ql9=~c9[25];
+    always@(posedge clk)
+        begin
+            Areg10=c9;
+            qreg10={q9[24:1],ql9};
+            m10=m9;
+            mdash10=mdash9;
+            //exbit10=exbit9;
+            signout10=signout9;
+            exponentout10=exponentout9;
+            //agre10=agre9;
+        end
+    assign {A10,q10}={Areg10,qreg10}<<1;
+    assign c10=Areg10[25]?A10+m10:A10+mdash10;
+    assign ql10=~c10[25];
+    always@(posedge clk)
+        begin
+            Areg11=c10;
+            qreg11={q10[24:1],ql10};
+            m11=m10;
+            mdash11=mdash10;
+            //exbit11=exbit10;
+            signout11=signout10;
+            exponentout11=exponentout10;
+            //agre11=agre10;
+        end
+    assign {A11,q11}={Areg11,qreg11}<<1;
+    assign c11=Areg11[25]?A11+m11:A11+mdash11;
+    assign ql11=~c11[25];
+    always@(posedge clk)
+        begin
+            Areg12=c11;
+            qreg12={q11[24:1],ql11};
+            m12=m11;
+            mdash12=mdash11;
+            //exbit12=exbit11;
+            signout12=signout11;
+            exponentout12=exponentout11;
+            //agre12=agre11;
+        end
+    assign {A12,q12}={Areg12,qreg12}<<1;
+    assign c12=Areg12[25]?A12+m12:A12+mdash12;
+    assign ql12=~c12[25];
+    always@(posedge clk)
+        begin
+            Areg13=c12;
+            qreg13={q12[24:1],ql12};
+            m13=m12;
+            mdash13=mdash12;
+            //exbit13=exbit12;
+            signout13=signout12;
+            exponentout13=exponentout12;
+            //agre13=agre12;
+        end
+    assign {A13,q13}={Areg13,qreg13}<<1;
+    assign c13=Areg13[25]?A13+m13:A13+mdash13;
+    assign ql13=~c13[25];
+    always@(posedge clk)
+        begin
+            Areg14=c13;
+            qreg14={q13[24:1],ql13};
+            m14=m13;
+            mdash14=mdash13;
+            //exbit14=exbit13;
+            signout14=signout13;
+            exponentout14=exponentout13;
+            //agre14=agre13;
+        end
+    assign {A14,q14}={Areg14,qreg14}<<1;
+    assign c14=Areg14[25]?A14+m14:A14+mdash14;
+    assign ql14=~c14[25];
+    always@(posedge clk)
+        begin
+            Areg15=c14;
+            qreg15={q14[24:1],ql14};
+            m15=m14;
+            mdash15=mdash14;
+            //exbit15=exbit14;
+            signout15=signout14;
+            exponentout15=exponentout14;
+            //agre15=agre14;
+        end
+    assign {A15,q15}={Areg15,qreg15}<<1;
+    assign c15=Areg15[25]?A15+m15:A15+mdash15;
+    assign ql15=~c15[25];
+    always@(posedge clk)
+        begin
+            Areg16=c15;
+            qreg16={q15[24:1],ql15};
+            m16=m15;
+            mdash16=mdash15;
+            //exbit16=exbit15;
+            signout16=signout15;
+            exponentout16=exponentout15;
+            //agre16=agre15;
+        end
+    assign {A16,q16}={Areg16,qreg16}<<1;
+    assign c16=Areg16[25]?A16+m16:A16+mdash16;
+    assign ql16=~c16[25];
+    always@(posedge clk)
+        begin
+            Areg17=c16;
+            qreg17={q16[24:1],ql16};
+            m17=m16;
+            mdash17=mdash16;
+            //exbit17=exbit16;
+            signout17=signout16;
+            exponentout17=exponentout16;
+            //agre17=agre16;
+        end
+    assign {A17,q17}={Areg17,qreg17}<<1;
+    assign c17=Areg17[25]?A17+m17:A17+mdash17;
+    assign ql17=~c17[25];
+    always@(posedge clk)
+        begin
+            Areg18=c17;
+            qreg18={q17[24:1],ql17};
+            m18=m17;
+            mdash18=mdash17;
+            //exbit18=exbit17;
+            signout18=signout17;
+            exponentout18=exponentout17;
+            //agre18=agre17;
+        end
+    assign {A18,q18}={Areg18,qreg18}<<1;
+    assign c18=Areg18[25]?A18+m18:A18+mdash18;
+    assign ql18=~c18[25];
+    always@(posedge clk)
+        begin
+            Areg19=c18;
+            qreg19={q18[24:1],ql18};
+            m19=m18;
+            mdash19=mdash18;
+            //exbit19=exbit18;
+            signout19=signout18;
+            exponentout19=exponentout18;
+            //agre19=agre18;
+        end
+    assign {A19,q19}={Areg19,qreg19}<<1;
+    assign c19=Areg19[25]?A19+m19:A19+mdash19;
+    assign ql19=~c19[25];
+    always@(posedge clk)
+        begin
+            Areg20=c19;
+            qreg20={q19[24:1],ql19};
+            m20=m19;
+            mdash20=mdash19;
+            //exbit20=exbit19;
+            signout20=signout19;
+            exponentout20=exponentout19;
+            //agre20=agre19;
+        end
+    assign {A20,q20}={Areg20,qreg20}<<1;
+    assign c20=Areg20[25]?A20+m20:A20+mdash20;
+    assign ql20=~c20[25];
+    always@(posedge clk)
+        begin
+            Areg21=c20;
+            qreg21={q20[24:1],ql20};
+            m21=m20;
+            mdash21=mdash20;
+            //exbit21=exbit20;
+            signout21=signout20;
+            exponentout21=exponentout20;
+            //agre21=agre20;
+        end
+    assign {A21,q21}={Areg21,qreg21}<<1;
+    assign c21=Areg21[25]?A21+m21:A21+mdash21;
+    assign ql21=~c21[25];
+    always@(posedge clk)
+        begin
+            Areg22=c21;
+            qreg22={q21[24:1],ql21};
+            m22=m21;
+            mdash22=mdash21;
+            //exbit22=exbit21;
+            signout22=signout21;
+            exponentout22=exponentout21;
+            //agre22=agre21;
+        end
+    assign {A22,q22}={Areg22,qreg22}<<1;
+    assign c22=Areg22[25]?A22+m22:A22+mdash22;
+    assign ql22=~c22[25];
+    always@(posedge clk)
+        begin
+            Areg23=c22;
+            qreg23={q22[24:1],ql22};
+            m23=m22;
+            mdash23=mdash22;
+            //exbit23=exbit22;
+            signout23=signout22;
+            exponentout23=exponentout22;
+            //agre23=agre22;
+        end
+    assign {A23,q23}={Areg23,qreg23}<<1;
+    assign c23=Areg23[25]?A23+m23:A23+mdash23;
+    assign ql23=~c23[25];
+    always@(posedge clk)
+        begin
+            Areg24=c23;
+            qreg24={q23[24:1],ql23};
+            m24=m23;
+            mdash24=mdash23;
+            //exbit24=exbit23;
+            signout24=signout23;
+            exponentout24=exponentout23;
+            //agre24=agre23;
+        end
+    assign {A24,q24}={Areg24,qreg24}<<1;
+    assign c24=Areg24[25]?A24+m24:A24+mdash24;
+    assign ql24=~c24[25];
+    always@(posedge clk)
+        begin
+            Areg25=c24;
+            qreg25={q24[24:1],ql24};
+            m25=m24;
+            mdash25=mdash24;
+            //exbit25=exbit24;
+            signout25=signout24;
+            exponentout25=exponentout24;
+            //agre25=agre24;
+        end
+    assign {A25,q25}={Areg25,qreg25}<<1;
+    assign c25=Areg25[25]?A25+m25:A25+mdash25;
+    assign ql25=~c25[25];
+    always@(posedge clk)
+        begin
+            outmantissa=qreg25;
+            Areg26=c25;
+            qreg26={q25[24:1],ql25};
+            ext[2:0]={ql25,2'b00};
+            m26=m25;
+            mdash26=mdash25;
+            //exbit26=exbit25;
+            signout26=signout25;
+            exponentout26=exponentout25;
+            //agre26=agre25;
+        end
+    assign {A26,q26}={Areg26,qreg26}<<1;
+    assign c26=Areg26[25]?A26+m26:A26+mdash26;
+    assign ql26=~c26[25];
+    always@(posedge clk)
+        begin
+            outmantissa1=outmantissa;
+            Areg27=c26;
+            qreg27={q26[24:1],ql26};
+            ext1[2:0]={ext[2],ql26,1'b0};
+            m27=m26;
+            mdash27=mdash26;
+            //exbit27=exbit26;
+            signout27=signout26;
+            exponentout27=exponentout26;
+            //agre27=agre26;
+        end
+    assign {A27,q27}={Areg27,qreg27}<<1;
+    assign c27=Areg27[25]?A27+m27:A27+mdash27;
+    assign ql27=~c27[25];
+    always@(posedge clk)
+        begin
+            outmantissa2=outmantissa1;
+            Areg28=c27;
+            qreg28={q27[24:1],ql27};
+            ext2[2:0]={ext1[2],ext1[1],ql27};
+            m28=m27;
+            mdash28=mdash27;
+
+            signout28=signout27;
+            exponentout28=exponentout27;
+
+        end
+    assign {A28,q28}={Areg28,qreg28}<<1;
+    assign c28=Areg28[25]?A28+m28:A28+mdash28;
+    assign ql28=~c28[25];
+    always@(posedge clk)
+        begin
+            mantissaout={outmantissa2,ext2,ql28};
+            shift=leadingzerodetector(mantissaout);
+            signout29=signout28;
+            exponentout29=exponentout28;
+        end
+    assign mantissaout2=mantissaout<<shift+1;
+
+
+    assign out={signout29,exponentout29,mantissaout2[28:6]};
+
+endmodule

+ 78 - 0
src/fpu32p/fpu32p.sv

@@ -0,0 +1,78 @@
+`include "mult32.v"
+
+
+module fpu32p_tb;
+
+    reg reset, clk;
+    logic [31:0] input_a, input_b, result_add, result_mult;
+    logic [31:0] expected_add, expected_mult;
+
+    fp_adder#(.N(32), .M(8)) adder1(
+        .clk(clk),
+        .reset(reset),
+        .input_a(input_a),
+        .input_b(input_b),
+        .output_z(result_add)
+    );
+
+    mult_32 multiplier1(
+        .clk(clk),
+        .a(input_a),
+        .b(input_b),
+        .out(result_mult),
+        .zero2(),
+        .invalid2(),
+        .overflow1()
+    );
+
+    initial forever #5 clk = ~clk;
+    localparam PIPELINES_ADD = 2;
+    localparam PIPELINES_MUL = 12;
+
+    reg [31:0] test_mem [29:0][3:0];
+
+    initial $readmemh("scripts/fp32_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_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_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_MUL][0], test_mem[i-PIPELINES_MUL][1], 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 : fpu32p_tb

+ 405 - 0
src/fpu32p/mult32.v

@@ -0,0 +1,405 @@
+// Adopted from
+// https://github.com/naveethmeeran/floating-point-coprocessor/blob/master/single_precision/single_precision.srcs/sources_1/new/singlemul.v
+
+module mult_32(
+    input clk,
+    input [31:0] a,
+    input [31:0] b,
+    output reg [31:0] out,
+    output reg zero2,invalid2,overflow1
+    );
+    reg outsign_reg,zero_reg,outsign_reg1,zero_reg1,invalid_reg,invalid_reg1,outsign_reg2,zero_reg2,invalid_reg2,outsign_reg3,zero_reg3,invalid_reg3,outsign_reg4,zero_reg4,invalid_reg4,outsign_reg5,zero_reg5,invalid_reg5,outsign_reg6,zero_reg6,invalid_reg6,outsign_reg7,zero_reg7,invalid_reg7,outsign_reg8,zero_reg8,invalid_reg8,outsign_reg9,zero_reg9,invalid_reg9,outsign_reg10,zero_reg10,invalid_reg10,outsign_reg11,zero_reg11,invalid_reg11;
+    reg [23:0] mantissaa_reg,mantissab_reg;
+    reg overflow_reg,overflow_reg1,overflow_reg2,overflow_reg3,overflow_reg4,overflow_reg5,overflow_reg6,overflow_reg7,overflow_reg8,overflow_reg9,overflow_reg10,overflow_reg11;
+    reg [39:0] s41_reg,s41_reg1;
+    reg [27:0] s21_reg,s22_reg,s23_reg,s24_reg,s25_reg,s26_reg,s21_reg1,s22_reg1,s23_reg1,s24_reg1,s25_reg1,s26_reg1;
+    reg [15:0] s31a_reg,s32a_reg,s33a_reg,s51a_reg;
+    reg [31:0] s31_reg,s32_reg,s33_reg,s31_reg1,s32_reg1,s33_reg1,s42_reg,s42_reg1;
+    reg [13:0] s21a_reg,s22a_reg,s23a_reg,s24a_reg,s25a_reg,s26a_reg,s41a_reg;
+    reg [47:0] s51_reg;
+    reg [25:0] s11_reg,s12_reg,s13_reg,s14_reg,s15_reg,s16_reg,s17_reg,s18_reg,s19_reg,s110_reg,s111_reg,s112_reg,s11_reg1,s12_reg1,s13_reg1,s14_reg1,s15_reg1,s16_reg1,s17_reg1,s18_reg1,s19_reg1,s110_reg1,s111_reg1,s112_reg1;
+    reg [23:0] p1_reg,p2_reg,p3_reg,p4_reg,p5_reg,p6_reg,p7_reg,p8_reg,p9_reg,p10_reg,p11_reg,p12_reg,p13_reg,p14_reg,p15_reg,p16_reg,p17_reg,p18_reg,p19_reg,p20_reg,p21_reg,p22_reg,p23_reg,p24_reg;
+    reg [23:0] p1_reg1,p2_reg1,p3_reg1,p4_reg1,p5_reg1,p6_reg1,p7_reg1,p8_reg1,p9_reg1,p10_reg1,p11_reg1,p12_reg1,p13_reg1,p14_reg1,p15_reg1,p16_reg1,p17_reg1,p18_reg1,p19_reg1,p20_reg1,p21_reg1,p22_reg1,p23_reg1,p24_reg1;
+    reg[7:0] outexponent_reg,outexponent_reg1,outexponent_reg2,outexponent_reg3,outexponent_reg4,outexponent_reg5,outexponent_reg6,outexponent_reg7,outexponent_reg8,outexponent_reg9,outexponent_reg10,outexponent_reg11;
+    reg [11:0] s11a_reg,s12a_reg,s13a_reg,s14a_reg,s15a_reg,s16a_reg,s17a_reg,s18a_reg,s19a_reg,s110a_reg,s111a_reg,s112a_reg;
+    reg p1_reg2,p3_reg2,p5_reg2,p7_reg2,p9_reg2,p11_reg2,p13_reg2,p15_reg2,p17_reg2,p19_reg2,p21_reg2,p23_reg2;
+    reg [1:0] s11_reg2,s13_reg2,s15_reg2,s17_reg2,s19_reg2,s111_reg2;
+    reg [3:0] s21_reg2,s23_reg2,s25_reg2;
+    reg [7:0] s31_reg2;
+    reg [15:0] s41_reg2;
+    wire [11:0] s11a,s12a,s13a,s14a,s15a,s16a,s17a,s18a,s19a,s110a,s111a,s112a;
+    wire [12:0] s21b,s22b,s23b,s24b,s25b,s26b;
+    wire [27:0] s21,s22,s23,s24,s25,s26;
+    wire [15:0] s31a,s32a,s33a,s51a;
+    wire outsign,zero,zero1,invalid,invalid1;
+    wire [7:0] outexponent,outexponent1,outexponent2;
+    wire [22:0] outmantissa;
+    wire [23:0] mantissaa,mantissab;
+    wire [23:0] p1,p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12,p13,p14,p15,p16,p17,p18,p19,p20,p21,p22,p23,p24;
+    wire [13:0] s11b,s12b,s13b,s14b,s15b,s16b,s17b,s18b,s19b,s110b,s111b,s112b,s21a,s22a,s23a,s24a,s25a,s26a,s41a;
+    wire [25:0] s11,s12,s13,s14,s15,s16,s17,s18,s19,s110,s111,s112;
+    wire [12:0] s31b,s32b,s33b;
+    wire [31:0] s31,s32,s33;
+    wire [18:0] s41b;
+    wire [39:0] s41;
+    wire[16:0] s51b;
+    wire[47:0] s51;
+    wire ca,overflow;
+    assign {ca,outexponent}=a[30:23]+b[30:23]-127;
+    assign outsign=a[31]^b[31];
+    assign mantissaa={1'b1,a[22:0]};
+    assign mantissab={1'b1,b[22:0]};
+    assign invalid=(a[30:23]==8'b11111111)||(b[30:23]==8'b11111111)?1'b1:1'b0;
+    assign zero=(a[30:0]==31'b0)||(b[30:0]==31'b0)?1'b1:1'b0;
+    assign overflow=(ca==1'b1)||(outexponent==8'b11111111)?1'b1:1'b0;
+    always@(posedge clk)
+        begin
+            outexponent_reg<=outexponent;
+            outsign_reg<=outsign;
+            mantissaa_reg<=mantissaa;
+            mantissab_reg<=mantissab;
+            zero_reg<=zero;
+            invalid_reg<=invalid;
+            overflow_reg<=overflow;
+        end
+    assign p1=mantissaa_reg[23:0] & {24{mantissab_reg[0]}};
+    assign p2=mantissaa_reg[23:0] & {24{mantissab_reg[1]}};
+    assign p3=mantissaa_reg[23:0] & {24{mantissab_reg[2]}};
+    assign p4=mantissaa_reg[23:0] & {24{mantissab_reg[3]}};
+    assign p5=mantissaa_reg[23:0] & {24{mantissab_reg[4]}};
+    assign p6=mantissaa_reg[23:0] & {24{mantissab_reg[5]}};
+    assign p7=mantissaa_reg[23:0] & {24{mantissab_reg[6]}};
+    assign p8=mantissaa_reg[23:0] & {24{mantissab_reg[7]}};
+    assign p9=mantissaa_reg[23:0] & {24{mantissab_reg[8]}};
+    assign p10=mantissaa_reg[23:0] & {24{mantissab_reg[9]}};
+    assign p11=mantissaa_reg[23:0] & {24{mantissab_reg[10]}};
+    assign p12=mantissaa_reg[23:0] & {24{mantissab_reg[11]}};
+    assign p13=mantissaa_reg[23:0] & {24{mantissab_reg[12]}};
+    assign p14=mantissaa_reg[23:0] & {24{mantissab_reg[13]}};
+    assign p15=mantissaa_reg[23:0] & {24{mantissab_reg[14]}};
+    assign p16=mantissaa_reg[23:0] & {24{mantissab_reg[15]}};
+    assign p17=mantissaa_reg[23:0] & {24{mantissab_reg[16]}};
+    assign p18=mantissaa_reg[23:0] & {24{mantissab_reg[17]}};
+    assign p19=mantissaa_reg[23:0] & {24{mantissab_reg[18]}};
+    assign p20=mantissaa_reg[23:0] & {24{mantissab_reg[19]}};
+    assign p21=mantissaa_reg[23:0] & {24{mantissab_reg[20]}};
+    assign p22=mantissaa_reg[23:0] & {24{mantissab_reg[21]}};
+    assign p23=mantissaa_reg[23:0] & {24{mantissab_reg[22]}};
+    assign p24=mantissaa_reg[23:0] & {24{mantissab_reg[23]}};
+    assign outexponent1=outexponent_reg;
+
+    assign zero1=zero_reg;
+    assign invalid1=invalid_reg;
+    always@(posedge clk)
+        begin
+            p1_reg[23:0]<=p1;
+            p2_reg[23:0]<=p2;
+            p3_reg[23:0]<=p3;
+            p4_reg[23:0]<=p4;
+            p5_reg[23:0]<=p5;
+            p6_reg[23:0]<=p6;
+            p7_reg[23:0]<=p7;
+            p8_reg[23:0]<=p8;
+            p9_reg[23:0]<=p9;
+            p10_reg[23:0]<=p10;
+            p11_reg[23:0]<=p11;
+            p12_reg[23:0]<=p12;
+            p13_reg[23:0]<=p13;
+            p14_reg[23:0]<=p14;
+            p15_reg[23:0]<=p15;
+            p16_reg[23:0]<=p16;
+            p17_reg[23:0]<=p17;
+            p18_reg[23:0]<=p18;
+            p19_reg[23:0]<=p19;
+            p20_reg[23:0]<=p20;
+            p21_reg[23:0]<=p21;
+            p22_reg[23:0]<=p22;
+            p23_reg[23:0]<=p23;
+            p24_reg[23:0]<=p24;
+            outexponent_reg1<=outexponent1;
+            outsign_reg1<=outsign_reg;
+            zero_reg1<=zero1;
+            invalid_reg1<=invalid1;
+            overflow_reg1<=overflow_reg;
+        end
+    assign s11a[11:0]=p1_reg[11:1]+p2_reg[10:0];
+    assign s12a[11:0]=p3_reg[11:1]+p4_reg[10:0];
+    assign s13a[11:0]=p5_reg[11:1]+p6_reg[10:0];
+    assign s14a[11:0]=p7_reg[11:1]+p8_reg[10:0];
+    assign s15a[11:0]=p9_reg[11:1]+p10_reg[10:0];
+    assign s16a[11:0]=p11_reg[11:1]+p12_reg[10:0];
+    assign s17a[11:0]=p13_reg[11:1]+p14_reg[10:0];
+    assign s18a[11:0]=p15_reg[11:1]+p16_reg[10:0];
+    assign s19a[11:0]=p17_reg[11:1]+p18_reg[10:0];
+    assign s110a[11:0]=p19_reg[11:1]+p20_reg[10:0];
+    assign s111a[11:0]=p21_reg[11:1]+p22_reg[10:0];
+    assign s112a[11:0]=p23_reg[11:1]+p24_reg[10:0];
+    always@(posedge clk)
+        begin
+            s11a_reg<=s11a;
+            s12a_reg<=s12a;
+            s13a_reg<=s13a;
+            s14a_reg<=s14a;
+            s15a_reg<=s15a;
+            s16a_reg<=s16a;
+            s17a_reg<=s17a;
+            s18a_reg<=s18a;
+            s19a_reg<=s19a;
+            s110a_reg<=s110a;
+            s111a_reg<=s111a;
+            s112a_reg<=s112a;
+            p1_reg1[23:12]<=p1_reg[23:12];
+            p2_reg1[23:11]<=p2_reg[23:11];
+            p3_reg1[23:12]<=p3_reg[23:12];
+            p4_reg1[23:11]<=p4_reg[23:11];
+            p5_reg1[23:12]<=p5_reg[23:12];
+            p6_reg1[23:11]<=p6_reg[23:11];
+            p7_reg1[23:12]<=p7_reg[23:12];
+            p8_reg1[23:11]<=p8_reg[23:11];
+            p9_reg1[23:12]<=p9_reg[23:12];
+            p10_reg1[23:11]<=p10_reg[23:11];
+            p11_reg1[23:12]<=p11_reg[23:12];
+            p12_reg1[23:11]<=p12_reg[23:11];
+            p13_reg1[23:12]<=p13_reg[23:12];
+            p14_reg1[23:11]<=p14_reg[23:11];
+            p15_reg1[23:12]<=p15_reg[23:12];
+            p16_reg1[23:11]<=p16_reg[23:11];
+            p17_reg1[23:12]<=p17_reg[23:12];
+            p18_reg1[23:11]<=p18_reg[23:11];
+            p19_reg1[23:12]<=p19_reg[23:12];
+            p20_reg1[23:11]<=p20_reg[23:11];
+            p21_reg1[23:12]<=p21_reg[23:12];
+            p22_reg1[23:11]<=p22_reg[23:11];
+            p23_reg1[23:12]<=p23_reg[23:12];
+            p24_reg1[23:11]<=p24_reg[23:11];
+            p1_reg2<=p1_reg[0];
+            p3_reg2<=p3_reg[0];
+            p5_reg2<=p5_reg[0];
+            p7_reg2<=p7_reg[0];
+            p9_reg2<=p9_reg[0];
+            p11_reg2<=p11_reg[0];
+            p13_reg2<=p13_reg[0];
+            p15_reg2<=p15_reg[0];
+            p17_reg2<=p17_reg[0];
+            p19_reg2<=p19_reg[0];
+            p21_reg2<=p21_reg[0];
+            p23_reg2<=p23_reg[0];
+            outexponent_reg2<=outexponent_reg1;
+            outsign_reg2<=outsign_reg1;
+            zero_reg2<=zero_reg1;
+            invalid_reg2<=invalid_reg1;
+            overflow_reg2<=overflow_reg1;
+        end
+    assign s11b[13:0]={1'b0,p1_reg1[23:12]}+p2_reg1[23:11]+s11a_reg[11];
+    assign s12b[13:0]={1'b0,p3_reg1[23:12]}+p4_reg1[23:11]+s12a_reg[11];
+    assign s13b[13:0]={1'b0,p5_reg1[23:12]}+p6_reg1[23:11]+s13a_reg[11];
+    assign s14b[13:0]={1'b0,p7_reg1[23:12]}+p8_reg1[23:11]+s14a_reg[11];
+    assign s15b[13:0]={1'b0,p9_reg1[23:12]}+p10_reg1[23:11]+s15a_reg[11];
+    assign s16b[13:0]={1'b0,p11_reg1[23:12]}+p12_reg1[23:11]+s16a_reg[11];
+    assign s17b[13:0]={1'b0,p13_reg1[23:12]}+p14_reg1[23:11]+s17a_reg[11];
+    assign s18b[13:0]={1'b0,p15_reg1[23:12]}+p16_reg1[23:11]+s18a_reg[11];
+    assign s19b[13:0]={1'b0,p17_reg1[23:12]}+p18_reg1[23:11]+s19a_reg[11];
+    assign s110b[13:0]={1'b0,p19_reg1[23:12]}+p20_reg1[23:11]+s110a_reg[11];
+    assign s111b[13:0]={1'b0,p21_reg1[23:12]}+p22_reg1[23:11]+s111a_reg[11];
+    assign s112b[13:0]={1'b0,p23_reg1[23:12]}+p24_reg1[23:11]+s112a_reg[11];
+    assign s11[25:0]={s11b,s11a_reg[10:0],p1_reg2};
+    assign s12[25:0]={s12b,s12a_reg[10:0],p3_reg2};
+    assign s13[25:0]={s13b,s13a_reg[10:0],p5_reg2};
+    assign s14[25:0]={s14b,s14a_reg[10:0],p7_reg2};
+    assign s15[25:0]={s15b,s15a_reg[10:0],p9_reg2};
+    assign s16[25:0]={s16b,s16a_reg[10:0],p11_reg2};
+    assign s17[25:0]={s17b,s17a_reg[10:0],p13_reg2};
+    assign s18[25:0]={s18b,s18a_reg[10:0],p15_reg2};
+    assign s19[25:0]={s19b,s19a_reg[10:0],p17_reg2};
+    assign s110[25:0]={s110b,s110a_reg[10:0],p19_reg2};
+    assign s111[25:0]={s111b,s111a_reg[10:0],p21_reg2};
+    assign s112[25:0]={s112b,s112a_reg[10:0],p23_reg2};
+    always@(posedge clk)
+        begin
+            s11_reg[25:0]<=s11[25:0];
+            s12_reg[25:0]<=s12[25:0];
+            s13_reg[25:0]<=s13[25:0];
+            s14_reg[25:0]<=s14[25:0];
+            s15_reg[25:0]<=s15[25:0];
+            s16_reg[25:0]<=s16[25:0];
+            s17_reg[25:0]<=s17[25:0];
+            s18_reg[25:0]<=s18[25:0];
+            s19_reg[25:0]<=s19[25:0];
+            s110_reg[25:0]<=s110[25:0];
+            s111_reg[25:0]<=s111[25:0];
+            s112_reg[25:0]<=s112[25:0];
+            outexponent_reg3<=outexponent_reg2;
+            outsign_reg3<=outsign_reg2;
+            zero_reg3<=zero_reg2;
+            invalid_reg3<=invalid_reg2;
+            overflow_reg3<=overflow_reg2;
+        end
+    assign s21a[13:0]=s11_reg[14:2]+s12_reg[12:0];
+    assign s22a[13:0]=s13_reg[14:2]+s14_reg[12:0];
+    assign s23a[13:0]=s15_reg[14:2]+s16_reg[12:0];
+    assign s24a[13:0]=s17_reg[14:2]+s18_reg[12:0];
+    assign s25a[13:0]=s19_reg[14:2]+s110_reg[12:0];
+    assign s26a[13:0]=s111_reg[14:2]+s112_reg[12:0];
+    always@(posedge clk)
+        begin
+            s21a_reg[13:0]<=s21a[13:0];
+            s22a_reg[13:0]<=s22a[13:0];
+            s23a_reg[13:0]<=s23a[13:0];
+            s24a_reg[13:0]<=s24a[13:0];
+            s25a_reg[13:0]<=s25a[13:0];
+            s26a_reg[13:0]<=s26a[13:0];
+            s11_reg1[25:15]<=s11_reg[25:15];
+            s12_reg1[25:13]<=s12_reg[25:13];
+            s13_reg1[25:15]<=s13_reg[25:15];
+            s14_reg1[25:13]<=s14_reg[25:13];
+            s15_reg1[25:15]<=s15_reg[25:15];
+            s16_reg1[25:13]<=s16_reg[25:13];
+            s17_reg1[25:15]<=s17_reg[25:15];
+            s18_reg1[25:13]<=s18_reg[25:13];
+            s19_reg1[25:15]<=s19_reg[25:15];
+            s110_reg1[25:13]<=s110_reg[25:13];
+            s111_reg1[25:15]<=s111_reg[25:15];
+            s112_reg1[25:13]<=s112_reg[25:13];
+            s11_reg2[1:0]<=s11_reg[1:0];
+            s13_reg2[1:0]<=s13_reg[1:0];
+            s15_reg2[1:0]<=s15_reg[1:0];
+            s17_reg2[1:0]<=s17_reg[1:0];
+            s19_reg2[1:0]<=s19_reg[1:0];
+            s111_reg2[1:0]<=s111_reg[1:0];
+            outexponent_reg4<=outexponent_reg3;
+            outsign_reg4<=outsign_reg3;
+            zero_reg4<=zero_reg3;
+            invalid_reg4<=invalid_reg3;
+            overflow_reg4<=overflow_reg3;
+        end
+    assign s21b[12:0]={2'b00,s11_reg1[25:15]}+s12_reg1[25:13]+s21a_reg[13];
+    assign s22b[12:0]={2'b00,s13_reg1[25:15]}+s14_reg1[25:13]+s22a_reg[13];
+    assign s23b[12:0]={2'b00,s15_reg1[25:15]}+s16_reg1[25:13]+s23a_reg[13];
+    assign s24b[12:0]={2'b00,s17_reg1[25:15]}+s18_reg1[25:13]+s24a_reg[13];
+    assign s25b[12:0]={2'b00,s19_reg1[25:15]}+s110_reg1[25:13]+s25a_reg[13];
+    assign s26b[12:0]={2'b00,s111_reg1[25:15]}+s112_reg1[25:13]+s26a_reg[13];
+    assign s21[27:0]={s21b,s21a_reg[12:0],s11_reg2[1:0]};
+    assign s22[27:0]={s22b,s22a_reg[12:0],s13_reg2[1:0]};
+    assign s23[27:0]={s23b,s23a_reg[12:0],s15_reg2[1:0]};
+    assign s24[27:0]={s24b,s24a_reg[12:0],s17_reg2[1:0]};
+    assign s25[27:0]={s25b,s25a_reg[12:0],s19_reg2[1:0]};
+    assign s26[27:0]={s26b,s26a_reg[12:0],s111_reg2[1:0]};
+    always@(posedge clk)
+        begin
+            s21_reg[27:0]<=s21[27:0];
+            s22_reg[27:0]<=s22[27:0];
+            s23_reg[27:0]<=s23[27:0];
+            s24_reg[27:0]<=s24[27:0];
+            s25_reg[27:0]<=s25[27:0];
+            s26_reg[27:0]<=s26[27:0];
+            outexponent_reg5<=outexponent_reg4;
+            outsign_reg5<=outsign_reg4;
+            zero_reg5<=zero_reg4;
+            invalid_reg5<=invalid_reg4;
+            overflow_reg5<=overflow_reg4;
+        end
+    assign s31a[15:0]=s21_reg[18:4]+s22_reg[14:0];
+    assign s32a[15:0]=s23_reg[18:4]+s24_reg[14:0];
+    assign s33a[15:0]=s25_reg[18:4]+s26_reg[14:0];
+    always@(posedge clk)
+        begin
+            s31a_reg[15:0]<=s31a;
+            s32a_reg[15:0]<=s32a;
+            s33a_reg[15:0]<=s33a;
+            s21_reg1[27:19]<=s21_reg[27:19];
+            s22_reg1[27:15]<=s22_reg[27:15];
+            s23_reg1[27:19]<=s23_reg[27:19];
+            s24_reg1[27:15]<=s24_reg[27:15];
+            s25_reg1[27:19]<=s25_reg[27:19];
+            s26_reg1[27:15]<=s26_reg[27:15];
+            s21_reg2[3:0]<=s21_reg[3:0];
+            s23_reg2[3:0]<=s23_reg[3:0];
+            s25_reg2[3:0]<=s25_reg[3:0];
+            outexponent_reg6<=outexponent_reg5;
+            outsign_reg6<=outsign_reg5;
+            zero_reg6<=zero_reg5;
+            invalid_reg6<=invalid_reg5;
+            overflow_reg6<=overflow_reg5;
+        end
+    assign s31b[12:0]={4'b0,s21_reg1[27:19]}+s22_reg1[27:15]+s31a_reg[15];
+    assign s32b[12:0]={4'b0,s23_reg1[27:19]}+s24_reg1[27:15]+s32a_reg[15];
+    assign s33b[12:0]={4'b0,s25_reg1[27:19]}+s26_reg1[27:15]+s33a_reg[15];
+    assign s31[31:0]={s31b,s31a_reg[14:0],s21_reg2[3:0]};
+    assign s32[31:0]={s32b,s32a_reg[14:0],s23_reg2[3:0]};
+    assign s33[31:0]={s33b,s33a_reg[14:0],s25_reg2[3:0]};
+    always@(posedge clk)
+        begin
+            s31_reg[31:0]<=s31[31:0];
+            s32_reg[31:0]<=s32[31:0];
+            s33_reg[31:0]<=s33[31:0];
+            outexponent_reg7<=outexponent_reg6;
+            outsign_reg7<=outsign_reg6;
+            zero_reg7<=zero_reg6;
+            invalid_reg7<=invalid_reg6;
+            overflow_reg7<=overflow_reg6;
+        end
+    assign s41a[13:0]=s31_reg[20:8]+s32[12:0];
+    always@(posedge clk)
+        begin
+            s41a_reg[13:0]<=s41a;
+            s31_reg1[31:21]<=s31_reg[31:21];
+            s32_reg1[31:13]<=s32_reg[31:13];
+            s31_reg2[7:0]<=s31_reg[7:0];
+            s33_reg1<=s33_reg;
+            outexponent_reg8<=outexponent_reg7;
+            outsign_reg8<=outsign_reg7;
+            zero_reg8<=zero_reg7;
+            invalid_reg8<=invalid_reg7;
+            overflow_reg8<=overflow_reg7;
+        end
+    assign s41b[18:0]={8'b0,s31_reg1[31:21]}+s32_reg1[31:13]+s41a_reg[13];
+    assign s41[39:0]={s41b,s41a_reg[12:0],s31_reg2[7:0]};
+    always@(posedge clk)
+        begin
+            s41_reg[39:0]<=s41[39:0];
+            s42_reg[31:0]<=s33_reg1[31:0];
+            outexponent_reg9<=outexponent_reg8;
+            outsign_reg9<=outsign_reg8;
+            zero_reg9<=zero_reg8;
+            invalid_reg9<=invalid_reg8;
+            overflow_reg9<=overflow_reg8;
+        end
+    assign s51a[15:0]=s41_reg[30:16]+s42_reg[14:0];
+    always@(posedge clk)
+        begin
+            s51a_reg[15:0]<=s51a[15:0];
+            s41_reg1[39:31]<=s41_reg[39:31];
+            s42_reg1[31:15]<=s42_reg[31:15];
+            s41_reg2[15:0]<=s41_reg[15:0];
+            outexponent_reg10<=outexponent_reg9;
+            outsign_reg10<=outsign_reg9;
+            zero_reg10<=zero_reg9;
+            invalid_reg10<=invalid_reg9;
+            overflow_reg10<=overflow_reg9;
+        end
+    assign s51b[16:0]={8'b0,s41_reg1[39:31]}+s42_reg1[31:15]+s51a_reg[15];
+    assign s51[47:0]={s51b,s51a_reg[14:0],s41_reg2[15:0]};
+    always@(posedge clk)
+        begin
+            s51_reg<=s51;
+            outexponent_reg11<=outexponent_reg10;
+            outsign_reg11<=outsign_reg10;
+            zero_reg11<=zero_reg10;
+            invalid_reg11<=invalid_reg10;
+            overflow_reg11<=overflow_reg10;
+        end
+    assign outmantissa=(s51_reg[47]==1'b1)?s51_reg[46:24]:s51_reg[45:23];
+    assign outexponent2=(s51_reg[47]==1'b1)?outexponent_reg11+1'b1:outexponent_reg11;
+    always@(posedge clk)
+        begin
+            zero2<=zero_reg11;
+            invalid2<=invalid_reg11;
+            overflow1<=overflow_reg11;
+            if (zero_reg11==1'b1)
+                out<={outsign_reg11,8'b0,23'b0};
+            else if(invalid_reg11==1'b1)
+                out<={outsign_reg11,8'b11111111,23'b1};
+            else
+                out<={outsign_reg11,outexponent2,outmantissa};
+        end
+endmodule

+ 64 - 57
src/neural/comp.sv

@@ -1,3 +1,7 @@
+// synopsys translate_off
+`timescale 1 ps / 1 ps
+// synopsys translate_on
+
 /*
               _____
      x[0] ==>|  A  |
@@ -61,60 +65,6 @@ x size: 2**K
 left io size: 2**K
 */
 
-module adder_casc_sync#(parameter K,N=32)(clk, rst, x, y);
-    input logic clk;
-    input logic rst;
-    input wire [N-1:0] x [2**K-1:0];
-    output logic [N-1:0] y;
-    wire [N-1:0] layer_w [2**K-3:0];
-
-    genvar i,j;
-    generate
-        for(i=0; i<K; i++) begin : generate_layers
-            // First layer
-            if(i == 0) begin
-                for(j=0; j<2**(K-1); j++) begin : gen_first_layer
-                    neural_adder a(
-                        .clk(clk),
-                        .rst(rst),
-                        .x0(x[j*2]),
-                        .x1(x[j*2+1]),
-                        .y(layer_w[j])
-                    );
-                end
-            end
-            // Last layer
-            else if((K-i) <= 1) begin
-                localparam s0 = 2**K-4;
-                localparam s1 = s0+1;
-                neural_adder c(
-                    .clk(clk),
-                    .rst(rst),
-                    .x0(layer_w[s0]),
-                    .x1(layer_w[s1]),
-                    .y(y)
-                );
-            end
-            // Middle layer
-            else begin
-                for(j=0; j<2**(K-i-1); j++) begin : gen_mid_layer
-                    localparam s = $floor((2.0**(K-1.0) * (2.0**(i-1)-1.0)/2.0**(i-1))+j);
-                    localparam ix = s*2;
-                    localparam ix1 = s*2+1;
-                    localparam iy = s+2**(K-1);
-                    neural_adder b(
-                        .clk(clk),
-                        .rst(rst),
-                        .x0(layer_w[ix]),
-                        .x1(layer_w[ix1]),
-                        .y(layer_w[iy])
-                    );
-                end
-            end
-        end
-    endgenerate
-endmodule : adder_casc_sync
-
 module adder_casc#(parameter K,N=32)(clk, rst, x, y, left, right);
     input logic clk;
     input logic rst;
@@ -185,12 +135,66 @@ module adder_casc#(parameter K,N=32)(clk, rst, x, y, left, right);
 
 endmodule : adder_casc
 
+module adder_casc_p #(parameter K, N=32)(clk, rst, x, y);
+    input logic clk;
+    input logic rst;
+    input wire [N-1:0] x [2**K-1:0];
+    output logic [N-1:0] y;
+    wire [N-1:0] layer_w [2**K-3:0];
+
+    genvar i,j;
+    generate
+        for(i=0; i<K; i++) begin : generate_layers
+            // First layer
+            if(i == 0) begin
+                for(j=0; j<2**(K-1); j++) begin : gen_first_layer
+                    neural_adder a(
+                        .clk(clk),
+                        .rst(rst),
+                        .x0(x[j*2]),
+                        .x1(x[j*2+1]),
+                        .y(layer_w[j])
+                    );
+                end
+            end
+                // Last layer
+            else if((K-i) <= 1) begin
+                localparam s0 = 2**K-4;
+                localparam s1 = s0+1;
+                neural_adder c(
+                    .clk(clk),
+                    .rst(rst),
+                    .x0(layer_w[s0]),
+                    .x1(layer_w[s1]),
+                    .y(y)
+                );
+            end
+                // Middle layer
+            else begin
+                for(j=0; j<2**(K-i-1); j++) begin : gen_mid_layer
+                    localparam s = $floor((2.0**(K-1.0) * (2.0**(i-1)-1.0)/2.0**(i-1))+j);
+                    localparam ix = s*2;
+                    localparam ix1 = s*2+1;
+                    localparam iy = s+2**(K-1);
+                    neural_adder b(
+                        .clk(clk),
+                        .rst(rst),
+                        .x0(layer_w[ix]),
+                        .x1(layer_w[ix1]),
+                        .y(layer_w[iy])
+                    );
+                end
+            end
+        end
+    endgenerate
+endmodule : adder_casc_p
+
 module adder_casc_tb();
     logic clk, rst;
     
     localparam K=2;
     logic [31:0] x [2**K-1:0];
-    logic [31:0] y;
+    logic [31:0] y0, y1;
     logic ack [2**K-1:0];
     logic stb [2**K-1:0];
 
@@ -206,7 +210,10 @@ module adder_casc_tb();
     endgenerate
     
     
-    adder_casc#(.K(K)) adder_casc0(.clk(clk), .rst(rst), .x(x), .y(y), .left(input_ios), .right(output_io.left));
+    adder_casc#(.K(K)) adder_casc0(.clk(clk), .rst(rst), .x(x), .y(y0), .left(input_ios), .right(output_io.left));
+
+    adder_casc_p#(.K(K)) adder_casc1(.clk(clk), .rst(rst), .x(x), .y(y1));
+
     initial forever #5 clk = ~clk;
     initial begin
         
@@ -227,7 +234,7 @@ module adder_casc_tb();
         foreach(stb[i]) stb[i] = 0;
         wait(output_io.stb == 1);
         output_io.ack = 1;
-        assert(y[0] == 'h47ffff00);
+        assert(y0[0] == 'h47ffff00);
         wait(output_io.stb == 0);
         output_io.ack = 0;
     end

+ 9 - 9
src/neural/layer.sv

@@ -47,7 +47,7 @@ module neuron_layer#(parameter C, K, N=32)(clk, rst, x, y, w, b, left, right);
 
 endmodule : neuron_layer
 
-module neuron_layer_sync#(parameter C, K, N=32)(clk, rst, x, y, w, b);
+module neuron_layer_p#(parameter C, K, N=32)(clk, rst, x, y, w, b);
     localparam NEURONS = 2**K;
     localparam CONNS = 2**C;
 
@@ -60,7 +60,7 @@ module neuron_layer_sync#(parameter C, K, N=32)(clk, rst, x, y, w, b);
     genvar i;
     generate
         for(i=0; i<NEURONS; i++) begin: gen_neruons
-            neuron_sync#(.K(C), .N(N)) n(
+            neuron_p#(.K(C), .N(N)) n(
                 .clk(clk),
                 .rst(rst),
                 .x(x),
@@ -70,7 +70,7 @@ module neuron_layer_sync#(parameter C, K, N=32)(clk, rst, x, y, w, b);
             );
         end
     endgenerate
-endmodule : neuron_layer_sync
+endmodule : neuron_layer_p
 
 /*
 Testbench for a 8x8x2 neuron network as shown below:
@@ -170,7 +170,7 @@ module neuron_network_tb;
     reg [31:0] layer3_s [1:0];
     reg [31:0] ys [1:0];
 
-    neuron_layer_sync#(.C(2), .K(3)) layer_s1(
+    neuron_layer_p#(.C(2), .K(3)) layer_s1(
         .clk(clk),
         .rst(rst),
         .x(x),
@@ -179,7 +179,7 @@ module neuron_network_tb;
         .b(layer1_b)
     );
 
-    neuron_layer_sync#(.C(3), .K(3)) layer_s2(
+    neuron_layer_p#(.C(3), .K(3)) layer_s2(
         .clk(clk),
         .rst(rst),
         .x(layer1_s),
@@ -188,7 +188,7 @@ module neuron_network_tb;
         .b(layer2_b)
     );
 
-    neuron_layer_sync#(.C(3), .K(1)) layer_s3(
+    neuron_layer_p#(.C(3), .K(1)) layer_s3(
         .clk(clk),
         .rst(rst),
         .x(layer2_s),
@@ -197,17 +197,17 @@ module neuron_network_tb;
         .b(layer3_b)
     );
 
-    hard_sigmoid_sync sigmoid_s0(
+    hard_sigmoid_p sigmoid_s0(
         .clk(clk),
         .rst(rst),
         .x(layer3_s[0]),
         .y(ys[0])
     );
 
-    hard_sigmoid_sync sigmoid_s1(
+    hard_sigmoid_p sigmoid_s1(
         .clk(clk),
         .rst(rst),
-        .x(layer3_o[1]),
+        .x(layer3_s[1]),
         .y(ys[1])
     );
 

+ 28 - 11
src/neural/neural.sv

@@ -8,14 +8,22 @@ module neural_adder(clk, rst, x0, x1, y);
     input clk, rst;
     input [31:0] x0, x1;
     output [31:0] y;
-    floating_add#(.N(32), .M(8)) add0(
-        .input_1(x0),
-        .input_2(x1),
-        .sum(y),
-        .diff(),
+    // floating_add#(.N(32), .M(8)) add0(
+    //     .input_1(x0),
+    //     .input_2(x1),
+    //     .sum(y),
+    //     .diff(),
+    //     .clk(clk),
+    //     .reset(rst)
+    // );
+    fp_adder#(.N(32), .M(8)) adder1(
         .clk(clk),
-        .reset(rst)
+        .reset(rst),
+        .input_a(x0),
+        .input_b(x1),
+        .output_z(y)
     );
+
 endmodule : neural_adder
 
 
@@ -23,12 +31,21 @@ module neural_mult(clk, rst, x0, x1, y);
     input clk, rst;
     input [31:0] x0, x1;
     output [31:0] y;
-    floating_product#(.N(32), .M(8)) mul0(
-        .input_1(x0),
-        .input_2(x1),
-        .product(y),
+    // floating_product#(.N(32), .M(8)) mul0(
+    //     .input_1(x0),
+    //     .input_2(x1),
+    //     .product(y),
+    //     .clk(clk),
+    //     .reset(rst)
+    // );
+    mult_32 multiplier1(
         .clk(clk),
-        .reset(rst)
+        .a(x0),
+        .b(x1),
+        .out(y),
+        .zero2(),
+        .invalid2(),
+        .overflow1()
     );
 endmodule : neural_mult
 

+ 26 - 17
src/neural/neuron.sv

@@ -17,7 +17,7 @@
 
 */
 
-module neuron_sync#(parameter K, N=32)(clk, rst, x, y, w, b);
+module neuron_p#(parameter K, N=32)(clk, rst, x, y, w, b);
     localparam M = 2**K;
     input wire [N-1:0] x [M-1:0];
     input wire [N-1:0] w [M-1:0];
@@ -43,7 +43,7 @@ module neuron_sync#(parameter K, N=32)(clk, rst, x, y, w, b);
         end
     endgenerate
 
-    adder_casc_sync#(.K(K), .N(N)) adder0(
+    adder_casc_p#(.K(K), .N(N)) adder0(
         .clk(clk),
         .rst(rst),
         .x(inner_w),
@@ -58,7 +58,7 @@ module neuron_sync#(parameter K, N=32)(clk, rst, x, y, w, b);
         .y(y)
     );
 
-endmodule : neuron_sync
+endmodule : neuron_p
 
 module neuron#(parameter K, N=32)(x, y, w, b, ack, stb, right, clk, rst);
     localparam M = 2**K;
@@ -127,33 +127,42 @@ module neuron_tb;
     logic [31:0] x [7:0];
     logic [31:0] w [7:0];
     logic [31:0] b;
-    logic [31:0] y;
+    logic [31:0] y0, y1;
 
-    logic ack [7:0];
-    logic stb [7:0];
+    wire [7:0] ack;
+    logic [7:0] stb;
 
     abus_io left[7:0]();
     abus_io right();
 
-    neuron#(.K(3)) neu0(
+    neuron #(.K(3)) neu0(
         .clk(clk),
         .rst(rst),
         .x(x),
-        .y(y),
+        .y(y0),
         .w(w),
         .b(b),
-        .ack(),
-        .stb(),
+        .ack(ack),
+        .stb(stb),
         .right(right)
     );
 
-    genvar k;
-    generate
-        for(k=0; k<8; k++) begin : io_mapper
-            assign left[k].stb = stb[k];
-            assign ack[k] = left[k].ack;
-        end
-    endgenerate
+    neuron_p #(.K(3)) neu1(
+        .clk(clk),
+        .rst(rst),
+        .x(x),
+        .y(y1),
+        .w(w),
+        .b(b)
+    );
+
+    // genvar k;
+    // generate
+    //     for(k=0; k<8; k++) begin : io_mapper
+    //         assign left[k].stb = stb[k];
+    //         // assign ack[k] = left[k].ack;
+    //     end
+    // endgenerate
 
     initial forever #5 clk = ~clk;
     initial begin

+ 2 - 2
src/neural/sigmoid.sv

@@ -123,7 +123,7 @@ module hard_sigmoid #(parameter N=32)(clk, rst, x, y, left, right);
 
 endmodule : hard_sigmoid
 
-module hard_sigmoid_sync #(parameter N=32)(clk, rst, x, y);
+module hard_sigmoid_p #(parameter N=32)(clk, rst, x, y);
     input clk, rst;
     input [N-1:0] x;
     output logic [N-1:0] y;
@@ -175,7 +175,7 @@ module hard_sigmoid_sync #(parameter N=32)(clk, rst, x, y);
         end
     end
 
-endmodule : hard_sigmoid_sync
+endmodule : hard_sigmoid_p
 
 
 module hard_sigmoid_tb;