Pārlūkot izejas kodu

Merge branch 'master' of https://gogs.infcof.com/4ycp/altera_devel into Oliver_FPA

Oliver Jaison 4 gadi atpakaļ
vecāks
revīzija
66394f0166

+ 48 - 0
simulation/modelsim/sim_neural.do

@@ -0,0 +1,48 @@
+#transcript on
+if {[file exists rtl_work]} {
+	vdel -lib rtl_work -all
+}
+set rootdir [pwd]/../..
+puts "Root Directory $rootdir"
+vlib rtl_work
+vmap work rtl_work
+
+vlog -sv -work work +incdir+${rootdir}/src/blocks ${rootdir}/src/blocks/abus.sv
+vlog -sv -work work +incdir+${rootdir}/src/fpu32 ${rootdir}/src/fpu32/fpu32.sv
+vlog -sv -work work +incdir+${rootdir}/src/neural ${rootdir}/src/neural/comp.sv
+vsim -t 1ps -L altera_ver -L lpm_ver -L sgate_ver -L altera_mf_ver -L altera_lnsim_ver -L cycloneive_ver -L rtl_work -L work -voptargs="+acc" adder_casc_tb
+view structure
+view signals
+
+add wave -position end -label CLK sim:/adder_casc_tb/clk
+add wave -position end -label RST sim:/adder_casc_tb/rst
+add wave -position end -label X -radix float32 sim:/adder_casc_tb/x
+add wave -position end -label Y -radix float32 sim:/adder_casc_tb/y
+
+add wave -position end -label output_stb sim:/adder_casc_tb/output_io/stb
+add wave -position end -label output_ack sim:/adder_casc_tb/output_io/ack
+
+add wave -position end -label inputs_ack sim:/adder_casc_tb/input_ack
+add wave -position end -label input1_stb sim:/adder_casc_tb/input_ios[1]/stb
+add wave -position end -label input1_ack sim:/adder_casc_tb/input_ios[1]/ack
+add wave -position end -label input0_stb sim:/adder_casc_tb/input_ios[0]/stb
+add wave -position end -label input0_ack sim:/adder_casc_tb/input_ios[0]/ack
+
+TreeUpdate [SetDefaultTree]
+WaveRestoreCursors {{Cursor 1} {0 ps} 0}
+quietly wave cursor active 0
+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} {1 ns}

+ 26 - 0
src/blocks/abus.sv

@@ -0,0 +1,26 @@
+
+//
+// This is asynchronious bus interface.
+// It carries control signals between blocks
+//
+//                 CLK RST
+//                  |   |
+//                 _v___v_
+//                |   M   |
+//       in_stk ->|   O   |-> out_stb
+//       in_ack <-|   D   |<- out_ack
+//                |   U   |
+//       inputs =>|   L   |=> outputs
+//                |   E   |
+//                |_______|
+//
+// Input stb tells module that input is read, ack tells sender back that input has been accepted
+// Output stb tells next receiver that output is ready, ack tells module back that output is accepted
+
+interface abus_io ();
+    logic stb, ack;
+
+    modport left(input stb, output ack);
+    modport right(output stb, input ack);
+
+endinterface : abus_io

+ 3 - 3
src/fpu32/adder.v

@@ -11,7 +11,7 @@ module adder(
         input_ack,
         output_z,
         output_z_stb,
-        output_z_ack,
+        output_z_ack
         );
 
   input     clk;
@@ -32,6 +32,7 @@ module adder(
   reg       s_input_ack;
 
   reg       [3:0] state;
+	
   parameter get_a         = 4'd0,
             get_b         = 4'd1,
             unpack        = 4'd2,
@@ -54,8 +55,7 @@ module adder(
   reg       guard, round_bit, sticky;
   reg       [27:0] sum;
 
-  always @(posedge clk)
-  begin
+  always_ff @(posedge clk) begin
 
     case(state)
 

+ 235 - 0
src/neural/comp.sv

@@ -0,0 +1,235 @@
+`include "../blocks/abus.sv"
+`include "../fpu32/fpu32.sv"
+
+/*
+          ____
+   x0 -->|ADD0|--> y0
+   x1 -->|    |
+ bus0 <->|    |<-- ack0
+ bus1 <->|____|--> stb0 
+          ____ 
+   x2 -->|ADD1|--> y1
+   x3 -->|    |
+ bus2 <->|    |<-- ack1
+ bus3 <->|____|--> stb1
+
+*/
+
+module adder4to2#(parameter N=32)(x, clk, rst, y, left, right);
+    input logic clk;
+    input logic rst;
+    input wire [N-1:0] x [3:0];
+    output logic [N-1:0] y [1:0];
+    abus_io left[3:0];
+    abus_io right[1:0];
+
+    wire out_stb [1:0];
+    assign right.stb = out_stb[0] & out_stb[1];
+
+    adder add0 (
+        .clk(clk),
+        .rst(rst),
+        .input_a(x[0]),
+        .input_b(x[1]),
+        .input_stb(left0.stb),
+        .input_ack(left0.ack),
+        .output_z(y[0]),
+        .output_z_ack(right.ack),
+        .output_z_stb(out_stb[0])
+    );
+
+    adder add1 (
+        .clk(clk),
+        .rst(rst),
+        .input_a(x[2]),
+        .input_b(x[3]),
+        .input_stb(left1.stb),
+        .input_ack(left1.ack),
+        .output_z(y[1]),
+        .output_z_ack(right.ack),
+        .output_z_stb(out_stb[1])
+    );
+
+endmodule : adder4to2
+
+
+module adder4to2_tb();
+    logic clk, rst;
+    
+    logic [31:0] x [3:0];
+    logic [31:0] y [1:0];
+    abus_io inputBus();
+    abus_io outputBus();
+    
+    adder4to2 adder_casc(.clk(clk), .rst(rst), .x(x), .y(y), .left(inputBus.right), .right(outputBus.left));    
+    initial forever #5 clk = ~clk;
+    initial begin
+        $display("Testing adder4to2");
+        clk = 0;
+        rst = 1;
+        inputBus.stb = 0;
+        outputBus.ack = 0;
+        #20
+        rst = 0;
+        x = {'h41388000, 'h407c0000, 'h42480000, 'h42460000};
+        inputBus.stb = 1;
+        wait(inputBus.ack == 1);
+        #15 inputBus.stb = 0;
+        
+        wait(outputBus.stb == 1);
+        outputBus.ack = 1;
+        assert(y[0] == 'h42c70000);
+        assert(y[1] == 'h41778000);
+        wait(outputBus.stb == 0);
+        outputBus.ack = 0;
+    end
+    
+endmodule : adder4to2_tb
+
+/*
+  K layers of cascade adder
+  
+  Example of K=3 adder:
+  
+IN | K3 |  K2  |  K1  | OUT
+     _
+  ->| |    _
+  ->|_|-->| |
+     _    | |--\
+  ->| |-->|_|  |   _
+  ->|_|        \->| |
+     _            | |->
+  ->| |    _   /->|_|
+  ->|_|-->| |  |
+     _    | |--/
+  ->| |-->|_|
+  ->|_|
+  
+[inputs]
+x size: 2**K
+left io size: 2**K
+
+[internal]
+layer connecting wires: 2**K - 2
+number of io buses: 2**(K-1) - 1
+adder4to2 modules: 2**(K-2)
+*/
+
+module adder_casc#(parameter K,N=32)(clk, rst, x, y, left, right);
+    input logic clk;
+    input logic rst;
+    input wire [N-1:0] x [2**K-1:0];
+    output logic [N-1:0] y;
+    
+    abus_io right;
+    abus_io left[2**K-1:0];
+    
+    wire [N-1:0] layer_w [2**K-3:0];
+    abus_io bus_w[2**(K-1)-2:0]();
+    
+    genvar i,j;
+    generate
+        for(i=0; i<K; i++) begin : generate_layers    
+            // First layers
+            if(i == 0) begin
+                for(j=0; j<2**(K-2); j++) begin : generate_casc0
+                    adder4to2 a(
+                      .clk(clk),
+                      .rst(rst),
+                      .x(x[j*4+:4]),
+                      .y(layer_w[j]),
+                      .left0(left[j*2].right),
+                      .left1(left[j*2+1].right),
+                      .right(bus_w[j].left)
+                    );
+                end
+            end
+            // Last layer
+            else if((K-i) <= 1) begin
+                adder c(
+                    .clk(clk),
+                    .rst(rst),
+                    .input_a(layer_w[i-1][0]),
+                    .input_b(layer_w[i-1][1]),
+                    .input_stb(bus_w[i-1].stb),
+                    .input_ack(bus_w[i-1].ack),
+                    .output_z(y),
+                    .output_z_ack(right.ack),
+                    .output_z_stb(right.stb)
+                    );
+            end
+            // Middle layers
+            else begin
+                for(j=0; j<2**(K-i-2); j++) begin : generate_casc1
+                    adder4to2 b(
+                      .clk(clk),
+                      .rst(rst),
+                      .x(layer_w[i-1][j*4+:4]),
+                      .y(layer_w[i][j*2+:2]),
+                      .left(bus_w[i-1][j].right),
+                      .right(bus_w[i][j].left)
+                    );
+                end
+            end
+        end
+    endgenerate
+
+endmodule : adder_casc
+
+module adder_casc_tb();
+    logic clk, rst;
+    
+    localparam K=3;
+    logic [31:0] x [7:0];
+    logic [31:0] y;
+    abus_io input_ios[2**K-1:0]();
+    abus_io output_io();
+    
+    virtual abus_io input_vios[2**K-1:0];
+    genvar k;
+    generate
+        for(k=0; k<2**K; k++) begin : map_generator
+            initial begin : map_physical2virtual
+                input_vios[k] = input_ios[k];
+            end : map_physical2virtual
+        end
+    endgenerate
+    
+    
+    adder_casc#(.K(K)) adder_casc0(.clk(clk), .rst(rst), .x(x), .y(y), .left(input_ios), .right(output_io.left));    
+    initial forever #5 clk = ~clk;
+    initial begin
+        
+        $display("Testing adder_casc");
+        clk = 0;
+        rst = 1;
+        
+        foreach(input_vios[i]) input_vios[i].stb = 0;
+        output_io.ack = 0;
+        #20
+        rst = 0;
+        x = {'h43800000, 'h43000000, 'h42800000, 'h42000000, 'h41800000, 'h41000000, 'h40800000, 'h40000000};
+        fork
+            foreach(input_vios[i]) begin
+                fork
+                    input_vios[i].stb = 1;
+                    wait(input_vios[i].ack == 1);
+                    #10
+                    input_vios[i].stb = 0;
+                join
+            end
+        join
+        #20 
+        
+        wait(output_io.stb == 1);
+        output_io.ack = 1;
+        assert(y[0] == 'h43ff0000);
+        wait(output_io.stb == 0);
+        output_io.ack = 0;
+    end
+    
+endmodule : adder_casc_tb
+
+
+
+

+ 0 - 0
src/neural/layer.sv


+ 31 - 0
src/neural/neuron.sv

@@ -0,0 +1,31 @@
+// synopsys translate_off
+`timescale 1 ps / 1 ps
+// synopsys translate_on
+
+
+module neuron#(parameter M, N=32)(x, y, w, b, stb, ack, clk, rst);
+    input wire [N-1:0] x [M-1:0];
+    input wire [N-1:0] w;
+    input wire [N-1:0] b [M-1:0];
+    output logic stb;
+    input logic ack;
+    input logic clk;
+    input logic rst;
+    output logic [N-1:0] y;
+
+    multiplier mult_array[M-1:0](
+        .clk(clk),
+        .rst(rst),
+        .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),
+    );
+
+endmodule : neuron
+
+
+