Parcourir la source

Merge branch 'master' into Oliver_FPA

# Conflicts:
#	scripts/fpu_test_gen.py
Oliver Jaison il y a 4 ans
Parent
commit
86e11fb66f
4 fichiers modifiés avec 151 ajouts et 110 suppressions
  1. 17 6
      scripts/fpu_test_gen.py
  2. 43 50
      src/fpu32/adder.v
  3. 54 23
      src/fpu32/fpu32.sv
  4. 37 31
      src/fpu32/mult.v

+ 17 - 6
scripts/fpu_test_gen.py

@@ -1,7 +1,16 @@
 import numpy as np
 import os
+import struct
 
-def generate_fp_vector(cases, filename, dtype=np.float16):
+
+def reverse_endian(data):
+    result = bytearray()
+    for i in range(len(data), 0, -1):
+        result.append(data[i - 1])
+    return bytes(result)
+
+
+def generate_fp_vector(cases, filename, dtype=np.float16, big_endian=False):
     dsize = 0
     if dtype == np.float16:
         dsize = 2
@@ -12,6 +21,7 @@ def generate_fp_vector(cases, filename, dtype=np.float16):
 
     x = np.frombuffer(os.urandom(cases * dsize), dtype=dtype)
     y = np.frombuffer(os.urandom(cases * dsize), dtype=dtype)
+    np.seterr(all='ignore')
     sum = x + y
     mul = x * y
     x = x.tobytes()
@@ -20,13 +30,14 @@ def generate_fp_vector(cases, filename, dtype=np.float16):
     mul = mul.tobytes()
     with open(filename, 'w') as f:
         for i in range(cases):
+            t = lambda v: reverse_endian(v) if big_endian else v
             f.write(' '.join([
-                x[i*dsize:i*dsize+dsize].hex(),
-                y[i*dsize:i*dsize+dsize].hex(),
-                sum[i*dsize:i*dsize+dsize].hex(),
-                mul[i*dsize:i*dsize+dsize].hex(),
+                t(x[i * dsize:i * dsize + dsize]).hex(),
+                t(y[i * dsize:i * dsize + dsize]).hex(),
+                t(sum[i * dsize:i * dsize + dsize]).hex(),
+                t(mul[i * dsize:i * dsize + dsize]).hex(),
             ]) + '\n')
 
 
 if __name__ == '__main__':
-    generate_fp_vector(30, 'fp16_test.hex', dtype=np.float16)
+    generate_fp_vector(10000, 'fp32_test.hex', dtype=np.float32, big_endian=True)

+ 43 - 50
src/fpu32/adder.v

@@ -3,28 +3,25 @@
 //2013-12-12
 
 module adder(
-        input_a,
-        input_b,
-        input_a_stb,
-        input_b_stb,
-        output_z_ack,
         clk,
         rst,
+        input_a,
+        input_b,
+        input_stb,
+        input_ack,
         output_z,
         output_z_stb,
-        input_a_ack,
-        input_b_ack);
+        output_z_ack,
+        );
 
   input     clk;
   input     rst;
 
   input     [31:0] input_a;
-  input     input_a_stb;
-  output    input_a_ack;
-
   input     [31:0] input_b;
-  input     input_b_stb;
-  output    input_b_ack;
+
+  input     input_stb;
+  output    input_ack;
 
   output    [31:0] output_z;
   output    output_z_stb;
@@ -32,8 +29,7 @@ module adder(
 
   reg       s_output_z_stb;
   reg       [31:0] s_output_z;
-  reg       s_input_a_ack;
-  reg       s_input_b_ack;
+  reg       s_input_ack;
 
   reg       [3:0] state;
   parameter get_a         = 4'd0,
@@ -63,38 +59,37 @@ module adder(
 
     case(state)
 
-      get_a:
-      begin
-        s_input_a_ack <= 1;
-        if (s_input_a_ack && input_a_stb) begin
-          a <= input_a;
-          s_input_a_ack <= 0;
-          state <= get_b;
-        end
-      end
+//      get_a:
+//      begin
+//        s_input_a_ack <= 1;
+//        if (s_input_a_ack && input_a_stb) begin
+//          a <= input_a;
+//          s_input_a_ack <= 0;
+//          state <= get_b;
+//        end
+//      end
+//      get_b:
+//      begin
+//        s_input_b_ack <= 1;
+//        if (s_input_b_ack && input_b_stb) begin
+//          b <= input_b;
+//          s_input_b_ack <= 0;
+//          state <= unpack;
+//        end
+//      end
 
       get_input:
       begin
-        s_input_a_ack <= 1;
-        s_input_b_ack <= 1;
-        if (s_input_a_ack && input_a_stb && s_input_b_ack && input_b_stb) begin
+        s_input_ack <= 1;
+        if (s_input_ack && input_stb) begin
           a <= input_a;
           b <= input_b;
-          s_input_a_ack <= 0;
-          s_input_b_ack <= 0;
+          s_input_ack <= 0;
           state <= unpack;
         end
       end
 
-      get_b:
-      begin
-        s_input_b_ack <= 1;
-        if (s_input_b_ack && input_b_stb) begin
-          b <= input_b;
-          s_input_b_ack <= 0;
-          state <= unpack;
-        end
-      end
+
 
       unpack:
       begin
@@ -109,20 +104,20 @@ module adder(
 
       special_cases:
       begin
-        //if a is NaN or b is NaN return NaN
-        if ((a_e == 128 && a_m != 0) || (b_e == 128 && b_m != 0)) begin
-          z[31] <= 1;
-          z[30:23] <= 255;
-          z[22] <= 1;
-          z[21:0] <= 0;
+        //if a is NaN return a
+        if (a_e == 8'hff && a_m != 0) begin
+          z <= {a_s, a_e, a[22:0]};
+          state <= put_z;
+        end else if (b_e == 8'hff && b_m != 0) begin
+          z <= {b_s, b_e, b[22:0]};
           state <= put_z;
         //if a is inf return inf
-        end else if (a_e == 128) begin
+        end else if (a_e == 8'hff) begin
           z[31] <= a_s;
           z[30:23] <= 255;
           z[22:0] <= 0;
           //if a is inf and signs don't match return nan
-          if ((b_e == 128) && (a_s != b_s)) begin
+          if ((b_e == 8'hff) && (a_s != b_s)) begin
               z[31] <= b_s;
               z[30:23] <= 255;
               z[22] <= 1;
@@ -130,7 +125,7 @@ module adder(
           end
           state <= put_z;
         //if b is inf return inf
-        end else if (b_e == 128) begin
+        end else if (b_e == 8'hff) begin
           z[31] <= b_s;
           z[30:23] <= 255;
           z[22:0] <= 0;
@@ -291,14 +286,12 @@ module adder(
 
     if (rst == 1) begin
       state <= get_input;
-      s_input_a_ack <= 0;
-      s_input_b_ack <= 0;
+      s_input_ack <= 0;
       s_output_z_stb <= 0;
     end
 
   end
-  assign input_a_ack = s_input_a_ack;
-  assign input_b_ack = s_input_b_ack;
+  assign input_ack = s_input_ack;
   assign output_z_stb = s_output_z_stb;
   assign output_z = s_output_z;
 

+ 54 - 23
src/fpu32/fpu32.sv

@@ -7,67 +7,98 @@
 
 module fpu32_tb();
     reg reset, clk;
-    reg [31:0] input_a, input_b, result_add, result_div, result_mul;
+    reg [31:0] input_a, input_b, result_add, result_div, result_mult;
     wire nan, overflow, underflow, zero;
 
 
-    reg adder_input_a_stb, adder_input_b_stb, adder_output_z_ack;
-    wire adder_input_a_ack, adder_input_b_ack, adder_output_z_stb;
+    reg adder_input_stb, adder_output_z_ack;
+    reg mult_input_stb, mult_output_z_ack;
+    wire adder_input_ack, adder_output_z_stb;
+    wire mult_input_ack, mult_output_z_stb;
 
 	adder add0(
 	    .clk(clk),
 	    .rst(reset),
 	    .input_a(input_a),
-	    .input_a_stb(adder_input_a_stb),
-	    .input_a_ack(adder_input_a_ack),
 	    .input_b(input_b),
-	    .input_b_stb(adder_input_b_stb),
-	    .input_b_ack(adder_input_b_ack),
+	    .input_stb(adder_input_stb),
+	    .input_ack(adder_input_ack),
 	    .output_z(result_add),
 	    .output_z_ack(adder_output_z_ack),
 	    .output_z_stb(adder_output_z_stb)
 	);
 
+    multiplier mult0(
+	    .clk(clk),
+	    .rst(reset),
+	    .input_a(input_a),
+	    .input_b(input_b),
+	    .input_stb(mult_input_stb),
+	    .input_ack(mult_input_ack),
+	    .output_z(result_mult),
+	    .output_z_ack(mult_output_z_ack),
+	    .output_z_stb(mult_output_z_stb)
+	);
+
 
     initial forever #5 clk = ~clk;
 
-    reg [31:0] test_mem [29:0][3:0];
+    reg [31:0] test_mem [9999:0][3:0];
 
-    initial $readmemh("../../scripts/fp32_test.hex", test_mem);
+    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;
-        adder_input_a_stb = 0;
-        adder_input_b_stb = 0;
+        adder_input_stb = 0;
         adder_output_z_ack = 0;
 
+        mult_input_stb = 0;
+        mult_output_z_ack = 0;
+
         #20;
         reset = 0;
 
-        foreach(test_mem[i]) begin
+
+        for (int i=0; i < $size(test_mem); i++) begin
             input_a = test_mem[i][0];
             input_b = test_mem[i][1];
-            adder_input_a_stb = 1;
-            adder_input_b_stb = 1;
+            adder_input_stb = 1;
+            mult_input_stb = 1;
 
-            wait(adder_input_a_ack | adder_input_b_ack == 1);
+            wait(adder_input_ack | mult_input_ack == 1);
             #15;
-            adder_input_a_stb = 0;
-            adder_input_b_stb = 0;
+            adder_input_stb = 0;
+            mult_input_stb = 0;
 
-            @(posedge adder_output_z_stb);
+            @(posedge adder_output_z_stb & mult_output_z_stb);
             adder_output_z_ack = 1;
-            if(result_add != test_mem[i][3])
-                $display("PASS: %H + %H = %H", input_a, input_b, result_add);
-            else
-                $error("FAIL ADD: %H + %H = %H, expected %H", input_a, input_b, result_add, test_mem[i][3]);
+            mult_output_z_ack = 1;
 
-            @(negedge adder_output_z_stb);
+            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 ADD: %H * %H = %H, expected %H", input_a, input_b, result_add, test_mem[i][3]);
+                num_err = num_err + 1;
+            end
+
+            @(negedge adder_output_z_stb & mult_output_z_stb);
             adder_output_z_ack = 0;
+            mult_output_z_ack = 0;
             #10;
         end
 
+        $display("Passed %d of %d tests", num_tests-num_err, num_tests);
+        $finish();
+
 //        assert(result_add == 32'h42440000);
 //        assert(result_mul == 32'hc2480000);
 //        $finish();

+ 37 - 31
src/fpu32/mult.v

@@ -5,26 +5,23 @@
 module multiplier(
         input_a,
         input_b,
-        input_a_stb,
-        input_b_stb,
+        input_stb,
         output_z_ack,
         clk,
         rst,
         output_z,
         output_z_stb,
-        input_a_ack,
-        input_b_ack);
+        input_ack);
 
   input     clk;
   input     rst;
 
   input     [31:0] input_a;
-  input     input_a_stb;
-  output    input_a_ack;
-
   input     [31:0] input_b;
-  input     input_b_stb;
-  output    input_b_ack;
+
+  input     input_stb;
+  output    input_ack;
+
 
   output    [31:0] output_z;
   output    output_z_stb;
@@ -32,8 +29,7 @@ module multiplier(
 
   reg       s_output_z_stb;
   reg       [31:0] s_output_z;
-  reg       s_input_a_ack;
-  reg       s_input_b_ack;
+  reg       s_input_ack;
 
   reg       [3:0] state;
   parameter get_a         = 4'd0,
@@ -48,7 +44,8 @@ module multiplier(
             normalise_2   = 4'd9,
             round         = 4'd10,
             pack          = 4'd11,
-            put_z         = 4'd12;
+            put_z         = 4'd12,
+            get_input     = 4'd13;
 
   reg       [31:0] a, b, z;
   reg       [23:0] a_m, b_m, z_m;
@@ -62,22 +59,33 @@ module multiplier(
 
     case(state)
 
-      get_a:
-      begin
-        s_input_a_ack <= 1;
-        if (s_input_a_ack && input_a_stb) begin
-          a <= input_a;
-          s_input_a_ack <= 0;
-          state <= get_b;
-        end
-      end
+//      get_a:
+//      begin
+//        s_input_a_ack <= 1;
+//        if (s_input_a_ack && input_a_stb) begin
+//          a <= input_a;
+//          s_input_a_ack <= 0;
+//          state <= get_b;
+//        end
+//      end
+//
+//      get_b:
+//      begin
+//        s_input_b_ack <= 1;
+//        if (s_input_b_ack && input_b_stb) begin
+//          b <= input_b;
+//          s_input_b_ack <= 0;
+//          state <= unpack;
+//        end
+//      end
 
-      get_b:
+      get_input:
       begin
-        s_input_b_ack <= 1;
-        if (s_input_b_ack && input_b_stb) begin
+        s_input_ack <= 1;
+        if (s_input_ack && input_stb) begin
+          a <= input_a;
           b <= input_b;
-          s_input_b_ack <= 0;
+          s_input_ack <= 0;
           state <= unpack;
         end
       end
@@ -254,22 +262,20 @@ module multiplier(
         s_output_z <= z;
         if (s_output_z_stb && output_z_ack) begin
           s_output_z_stb <= 0;
-          state <= get_a;
+          state <= get_input;
         end
       end
 
     endcase
 
     if (rst == 1) begin
-      state <= get_a;
-      s_input_a_ack <= 0;
-      s_input_b_ack <= 0;
+      state <= get_input;
+      s_input_ack <= 0;
       s_output_z_stb <= 0;
     end
 
   end
-  assign input_a_ack = s_input_a_ack;
-  assign input_b_ack = s_input_b_ack;
+  assign input_ack = s_input_ack;
   assign output_z_stb = s_output_z_stb;
   assign output_z = s_output_z;