Min 4 лет назад
Родитель
Сommit
87e179418b
4 измененных файлов с 259 добавлено и 18 удалено
  1. 45 0
      scripts/neuron_net_test.py
  2. 24 0
      scripts/number_conv.py
  3. 182 13
      src/neural/layer.sv
  4. 8 5
      src/neural/neuron.sv

+ 45 - 0
scripts/neuron_net_test.py

@@ -0,0 +1,45 @@
+import numpy as np
+from matplotlib import pyplot as plt
+from fpu_test_gen import reverse_endian, dtype_size
+
+WEIGTHS = [
+    [
+        [0.7095146, -0.41895103, -0.08075078, -0.5218736],
+        [-0.4351325, 1.0214638, 0.14494987, -0.78134096],
+        [0.38553882, -1.0607314, 0.01327306, -0.28972188],
+        [0.84955347, 0.32464203, 0.8879888, 0.00756884],
+        [-0.8693629, 0.8418823, 0.60206324, -0.78290594],
+        [0.1586302, 0.01737848, 0.75329006, -0.57819647],
+        [-0.16126093, 0.5317601, 0.34316933, -0.7074082],
+        [0.09219088, -0.624525, -0.61903083, -0.87057704]
+    ],
+    [[0.36770403, -0.78046024, 0.3979908, 0.5494289, -0.13859335, 0.40053025, 0.08249452, -0.32528356],
+     [-0.17659009, 0.13901198, -0.45248222, -0.7894139, -0.81092286, -0.521815, 0.30632392, -0.3143816],
+     [-0.04314173, 0.14361085, 0.6259473, 0.3571782, -0.38011226, 0.01378736, 0.05794358, 0.09667788],
+     [-0.46864474, 0.36618456, -0.45595396, -0.39789405, 0.73964316, -0.30294785, 0.2482118, -0.2127953],
+     [-0.37941265, 0.45330787, -0.12066315, 0.5636705, 0.68990386, 0.6543718, 0.86367106, -0.5707757],
+     [-0.78606385, 0.24032554, -0.4472755, -0.24661142, -0.2698564, -0.8365823, -0.13674814, -0.39799848],
+     [0.11138931, 0.48950365, 0.12998834, 0.4947537, 0.516593, 0.82281274, 0.04789656, 0.30206403],
+     [0.23097174, 0.30290592, -0.596446, -0.40108407, 0.12246455, -0.47260976, -0.55030185, 0.44481543]
+     ]
+    [
+        [0.5724262, 0.5853241, 0.3748752, -0.892384, -1.0270239, 0.2170913, -0.07271451, 0.14661156],
+        [0.30391088, -0.92324615, 0.8088594, -1.0522624, 0.07374455, -0.550893, 0.8194236, -0.62796086]
+    ]
+]
+BIAS = [
+    # L1
+    [0.01425434, -0.06219335, -0.0201127, -0.04791382, -0.04360008, -0.05311861, -0.01731363, -0.00014839],
+    # L2
+    [0.03480967, 0.06208326, -0.01576317, -0.00037753, -0.03940378, 0.05157978, -0.02775403, 0.04540931],
+    # L3
+    [0.03787775, -0.03655371],
+]
+
+
+def generate_nn_values(dtype=np.float32):
+    dsize = dtype_size(dtype)
+
+
+if __name__ == '__main__':
+    generate_nn_values()

+ 24 - 0
scripts/number_conv.py

@@ -0,0 +1,24 @@
+import numpy as np
+from fpu_test_gen import reverse_endian, dtype_size
+import sys
+
+
+def float2verilog(lines, dtype=np.float32):
+    dsize = dtype_size(dtype)
+    print("")
+    for i, line in enumerate(lines):
+        arr = line.replace('[', '').replace(']', '').split()
+        nums = np.array([float(f.strip(',')) for f in arr if f], dtype=dtype)
+        b = nums.tobytes()
+        print(f'[{i}] = {{' +
+              ', '.join(["'h" + reverse_endian(b[i*dsize:i*dsize+dsize]).hex() for i in range(len(arr))]) +
+              '};')
+
+
+if __name__ == '__main__':
+    print("Press Ctrl-D to proceed")
+    while True:
+        lines = sys.stdin.readlines()
+        if len(lines) == 0:
+            break
+        float2verilog(lines)

+ 182 - 13
src/neural/layer.sv

@@ -2,22 +2,191 @@
 `timescale 1 ps / 1 ps
 // synopsys translate_on
 
+module neuron_layer#(parameter C, K, N=32)(clk, rst, x, y, w, b, left, right);
+    localparam NEURONS = 2**K;
+    localparam CONNS = 2**C;
+
+    input wire clk, rst;
+    input wire [N-1:0] x [CONNS-1:0];
+    input wire [N-1:0] w [NEURONS-1:0][CONNS-1:0];
+    input wire [N-1:0] b [NEURONS-1:0];
+    output wire [N-1:0] y [NEURONS-1:0];
+    abus_io left [CONNS-1:0];
+    abus_io right [NEURONS-1:0];
+
+    wire [NEURONS-1:0] ack_t [CONNS-1:0];
+    reg [CONNS-1:0] ack [NEURONS-1:0];
+    reg [CONNS-1:0] stb;
+
+    genvar i, j;
+    generate
+        for(i=0; i<CONNS; i++) begin
+            assign stb[i] = left[i].stb;
+            assign left[i].ack = &ack_t[i];
+        end
+    endgenerate
+
+    generate
+        for(i=0; i<NEURONS; i++) begin
+            for(j=0; j<CONNS; j++) begin
+                assign ack_t[j][i] = ack[i][j];
+            end
+            neuron#(.K(C), .N(N)) n(
+                .clk(clk),
+                .rst(rst),
+                .x(x),
+                .y(y[i]),
+                .w(w[i]),
+                .b(b[i]),
+                .ack(ack[i]),
+                .stb(stb),
+                .right(right[i])
+            );
+        end
+    endgenerate
+
+endmodule : neuron_layer
+
 /*
+Testbench for a 8x8x2 neuron network as shown below:
 
-    =>
-    =>
-    =>
-    =>
+                8       8
+             . [ ] ... [ ] .
+ONE HOT -> ... [ ] ... [ ] ..   2
+ONE HOT -> ... [ ] ... [ ] ... [ ] -> [ Hard Sigmoid ] -> Q
+ONE HOT -> ... [ ] ... [ ] ... [ ] -> [ Hard Sigmoid ] -> I
+ONE HOT -> ... [ ] ... [ ] ..
+             . [ ] ... [ ] .
 
 */
-module neuron_layer#(parameter K, N=32)(clk, rst, x, y, w, b, left, right);
-    localparam M = 2**K;
-    input wire clk, rst;
-    input wire [N-1:0] x [M-1:0];
-    input wire [N-1:0] w [M-1:0];
-    input wire [N-1:0] b;
-    output logic [N-1:0] y;
-    abus left, right;
+
+module neuron_network_tb;
+    reg clk, rst;
+    reg [31:0] x [3:0];
+    reg [31:0] y [1:0];
+
+    abus_io left[3:0]();
+    abus_io right[1:0]();
+
+    reg [31:0] layer1_w [7:0][3:0];
+    reg [31:0] layer1_b [7:0];
+    reg [31:0] layer1_o [7:0];
+    abus_io layer1_io [7:0]();
+
+    reg [31:0] layer2_w [7:0][7:0];
+    reg [31:0] layer2_b [7:0];
+    reg [31:0] layer2_o [7:0];
+    abus_io layer2_io [7:0]();
+
+    reg [31:0] layer3_w [1:0][7:0];
+    reg [31:0] layer3_b [1:0];
+    reg [31:0] layer3_o [1:0];
+    abus_io layer3_io [1:0]();
+
+    neuron_layer#(.C(2), .K(3)) layer1(
+        .clk(clk),
+        .rst(rst),
+        .x(x),
+        .y(layer1_o),
+        .w(layer1_w),
+        .b(layer1_b),
+        .left(left),
+        .right(layer1_io)
+    );
+
+    neuron_layer#(.C(3), .K(3)) layer2(
+        .clk(clk),
+        .rst(rst),
+        .x(layer1_o),
+        .y(layer2_o),
+        .w(layer2_w),
+        .b(layer2_b),
+        .left(layer1_io),
+        .right(layer2_io)
+    );
+
+    neuron_layer#(.C(3), .K(1)) layer3(
+        .clk(clk),
+        .rst(rst),
+        .x(layer2_o),
+        .y(layer3_o),
+        .w(layer3_w),
+        .b(layer3_b),
+        .left(layer2_io),
+        .right(layer3_io)
+    );
+
+    hard_sigmoid sigmoid0(
+        .clk(clk),
+        .rst(rst),
+        .x(layer3_o[0]),
+        .y(y[0]),
+        .left(layer3_io[0]),
+        .right(right[0])
+    );
+
+    hard_sigmoid sigmoid1(
+        .clk(clk),
+        .rst(rst),
+        .x(layer3_o[1]),
+        .y(y[1]),
+        .left(layer3_io[1]),
+        .right(right[1])
+    );
+
+    initial forever #5 clk = ~clk;
+
+    initial begin
+        clk = 0;
+        rst = 1;
+
+        left[0].stb = 0;
+        left[1].stb = 0;
+        left[2].stb = 0;
+        left[3].stb = 0;
+        right[0].ack = 0;
+        right[1].ack = 0;
+
+        layer1_w[0] = {'h3f35a2c0, 'hbed680c0, 'hbda560aa, 'hbf059982};
+        layer1_w[1] = {'hbedec9b0, 'h3f82bf53, 'h3e146dbd, 'hbf4805f6};
+        layer1_w[2] = {'h3ec56558, 'hbf87c60c, 'h3c597740, 'hbe94566d};
+        layer1_w[3] = {'h3f597c56, 'h3ea6377b, 'h3f63533c, 'h3bf80408};
+        layer1_w[4] = {'hbf5e8e91, 'h3f578599, 'h3f1a20d1, 'hbf486c86};
+        layer1_w[5] = {'h3e226ff5, 'h3c8e5d50, 'h3f40d79e, 'hbf1404af};
+        layer1_w[6] = {'hbe252196, 'h3f08216e, 'h3eafb3e4, 'hbf3518b4};
+        layer1_w[7] = {'h3dbcce92, 'hbf1fe0df, 'hbf1e78ce, 'hbf5ede23};
+
+        layer2_w[0] = {'h3ebc43b4, 'hbf47cc3e, 'h3ecbc573, 'h3f0ca75f, 'hbe0deb6a, 'h3ecd124d, 'h3da8f2e3, 'hbea68b91};
+        layer2_w[1] = {'hbe34d408, 'h3e0e5928, 'hbee7abc0, 'hbf4a1708, 'hbf4f98a4, 'hbf0595ab, 'h3e9cd67d, 'hbea0f6a0};
+        layer2_w[2] = {'hbd30b562, 'h3e130eb9, 'h3f203e15, 'h3eb6e010, 'hbec29e13, 'h3c61e461, 'h3d6d563f, 'h3dc5ff0d};
+        layer2_w[3] = {'hbeeff234, 'h3ebb7c8b, 'hbee972cc, 'hbecbb8c5, 'h3f3d5941, 'hbe9b1bfb, 'h3e7e2b3c, 'hbe59e703};
+        layer2_w[4] = {'hbec24260, 'h3ee817f8, 'hbdf71e3e, 'h3f104cb6, 'h3f309d8a, 'h3f2784e9, 'h3f5d198c, 'hbf121e5b};
+        layer2_w[5] = {'hbf493b7b, 'h3e7617e6, 'hbee5014b, 'hbe7c87b4, 'hbe8a2a9e, 'hbf562a42, 'hbe0c07b4, 'hbecbc675};
+        layer2_w[6] = {'h3de42014, 'h3efaa039, 'h3e051baa, 'h3efd505b, 'h3f043f70, 'h3f52a3db, 'h3d442f2f, 'h3e9aa823};
+        layer2_w[7] = {'h3e6c83db, 'h3e9b167c, 'hbf18b0af, 'hbecd5ae4, 'h3dfaceb2, 'hbef1f9e8, 'hbf0ce095, 'h3ee3bed9};
+
+        layer3_w[0] = {'h3f128a86, 'h3f15d7cd, 'h3ebfefa4, 'hbf647347, 'hbf837585, 'h3e5e4d2f, 'hbd94eb58, 'h3e162157};
+        layer3_w[1] = {'h3e9b9a35, 'hbf6c59dc, 'h3f4f1169, 'hbf86b089, 'h3d970762, 'hbf0d0753, 'h3f51c5bf, 'hbf20c20b};
+
+        layer1_b = {'h3c698b09, 'hbd7ebe74, 'hbca4c364, 'hbd444148, 'hbd3295ff, 'hbd5992e6, 'hbc8dd550, 'hb91b9923};
+        layer2_b = {'h3d0e9496, 'h3d7e4b04, 'hbc8121c3, 'hb9c5ef38, 'hbd2165dc, 'h3d534552, 'hbce35c6b, 'h3d39ff1d};
+        layer3_b = {'h3d1b25b3, 'hbd15b958};
+
+        #15;
+        rst = 0;
+        x = {0, 0, 0 , 'h3f800000};
+        left[0].stb = 1;
+        left[1].stb = 1;
+        left[2].stb = 1;
+        left[3].stb = 1;
+
+        #15;
+        left[0].stb = 0;
+        left[1].stb = 0;
+        left[2].stb = 0;
+        left[3].stb = 0;
+
+    end
 
 
-endmodule : neuron_layer
+endmodule : neuron_network_tb

+ 8 - 5
src/neural/neuron.sv

@@ -17,7 +17,7 @@
 
 */
 
-module neuron#(parameter K, N=32)(x, y, w, b, left, right, clk, rst);
+module neuron#(parameter K, N=32)(x, y, w, b, ack, stb, right, clk, rst);
     localparam M = 2**K;
     input wire [N-1:0] x [M-1:0];
     input wire [N-1:0] w [M-1:0];
@@ -27,7 +27,9 @@ module neuron#(parameter K, N=32)(x, y, w, b, left, right, clk, rst);
     input wire clk;
     input wire rst;
 
-    abus_io left[M-1:0];
+    output wire [M-1:0] ack;
+    input wire [M-1:0] stb;
+
     abus_io inner_io0[M-1:0]();
     abus_io inner_io1();
     abus_io right;
@@ -43,8 +45,8 @@ module neuron#(parameter K, N=32)(x, y, w, b, left, right, clk, rst);
                 .rst(rst),
                 .input_a(x[i]),
                 .input_b(w[i]),
-                .input_stb(left[i].stb),
-                .input_ack(left[i].ack),
+                .input_stb(stb[i]),
+                .input_ack(ack[i]),
                 .output_z(inner_w[i]),
                 .output_z_ack(inner_io0[i].ack),
                 .output_z_stb(inner_io0[i].stb)
@@ -97,7 +99,8 @@ module neuron_tb;
         .y(y),
         .w(w),
         .b(b),
-        .left(left),
+        .ack(),
+        .stb(),
         .right(right)
     );