|
@@ -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
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|