Min 4 yıl önce
ebeveyn
işleme
34507cd57d
3 değiştirilmiş dosya ile 126 ekleme ve 29 silme
  1. 46 19
      src/fpu16/fp_mult.sv
  2. 22 10
      src/fpu16/fpu16.sv
  3. 58 0
      src/fpu16/lead_zero.sv

+ 46 - 19
src/fpu16/fp_mult.sv

@@ -1,24 +1,55 @@
+`include "lead_zero.sv"
 
 
 module lead_zeros_enc #(K=10)(in, out);
-    localparam L = $clog2(K);
+    localparam L = $clog2(K) +1;
 
     input wire [K-1:0] in;
     output logic [L-1:0] out;
     always_comb 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
+        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
 
@@ -76,7 +107,7 @@ module fp_mult #(parameter N=16, M=5)(input_a, input_b, output_z, clk, reset);
 
     always_ff @(posedge clk) begin
         a_e2 <= a_e1 - a_z1;
-        a_m2 <= a_e1 << a_z1; // a_e1 should be a_m1 maybe?
+        a_m2 <= a_m1 << a_z1;
 
         b_e2 <= b_e1 - b_z1;
         b_m2 <= b_m1 << b_z1;
@@ -91,14 +122,10 @@ module fp_mult #(parameter N=16, M=5)(input_a, input_b, output_z, clk, reset);
     reg z_s3;
     reg [M-1:0] z_e3;
     reg [K*2-1:0] z_p3;  // product is double mantissa
-    wire [K*2-1:0] z_p3w;
-
-    assign z_p3w = a_m2 * b_m2; // unnecessary ?
 
     always_ff @(posedge clk) begin
         z_e3 <= a_e2 + b_e2 + 1;
         z_p3 <= a_m2 * b_m2;
-
         z_s3 <= z_s2;
     end
 

+ 22 - 10
src/fpu16/fpu16.sv

@@ -4,24 +4,36 @@
 
 
 module fpu16_tb;
-	localparam N=16;
-	localparam M=5;
+	localparam N=32;
+	localparam M=8;
 
 	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_b(input_b), .output_z(result_add), .clk(clk), .reset(reset));
-
-	fp_mult multiplier1(.input_a(input_a), .input_b(input_b), .output_z(result_mult), .clk(clk), .reset(reset));
+	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 [15:0] test_mem [29:0][3:0];
+	reg [N-1:0] test_mem [29:0][3:0];
 
-	initial $readmemh("scripts/fp16_test.hex", test_mem);
+	initial $readmemh("scripts/fp32_test.hex", test_mem);
 
 	reg [N-2-M:0] exp0_m;
 	reg [M-1:0] exp0_e;

+ 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