|
@@ -2,22 +2,191 @@
|
|
|
`timescale 1 ps / 1 ps
|
|
`timescale 1 ps / 1 ps
|
|
|
// synopsys translate_on
|
|
// 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
|