From 4682b7e4d5e2080f9fe874e3155193b38d5d09e9 Mon Sep 17 00:00:00 2001 From: Konstantin Pavlov Date: Fri, 13 Dec 2019 13:26:07 +0300 Subject: [PATCH] Added adder_tree module and testbench --- adder_tree.sv | 90 ++++++++++++++++++++++++++++++++++++++++++++ adder_tree_tb.sv | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 187 insertions(+) create mode 100644 adder_tree.sv create mode 100644 adder_tree_tb.sv diff --git a/adder_tree.sv b/adder_tree.sv new file mode 100644 index 0000000..7b44f0c --- /dev/null +++ b/adder_tree.sv @@ -0,0 +1,90 @@ +//------------------------------------------------------------------------------ +// adder_tree.sv +// Konstantin Pavlov, pavlovconst@gmail.com +//------------------------------------------------------------------------------ + +// INFO ------------------------------------------------------------------------- +// Pipelined tree adder with parametrized input width written in System Verilog +// +// - Number of inputs is NOT required to be power of two +// - This code can generate entirely combinational circuit with minimal editing +// + +/* --- INSTANTIATION TEMPLATE BEGIN --- + +adder_tree #( + .INPUTS_NUM( 125 ), + .IDATA_WIDTH( 16 ) +) AT1 ( + .clk( ), + .nrst( ), + .idata( ), + .odata( ) +); + +--- INSTANTIATION TEMPLATE END ---*/ + + +module adder_tree #( + parameter INPUTS_NUM = 125, + parameter IDATA_WIDTH = 16, + + parameter STAGES_NUM = $clog2(INPUTS_NUM), + parameter INPUTS_NUM_INT = 2 ** STAGES_NUM, + parameter ODATA_WIDTH = IDATA_WIDTH + STAGES_NUM +)( + input clk, + input nrst, + input logic [INPUTS_NUM-1:0][IDATA_WIDTH-1:0] idata, + output logic [ODATA_WIDTH-1:0] odata +); + + +logic [STAGES_NUM:0][INPUTS_NUM_INT-1:0][ODATA_WIDTH-1:0] data; + +// generating tree +genvar stage, adder; +generate + for( stage = 0; stage <= STAGES_NUM; stage++ ) begin: stage_gen + + localparam ST_OUT_NUM = INPUTS_NUM_INT >> stage; + localparam ST_WIDTH = IDATA_WIDTH + stage; + + if( stage == '0 ) begin + // stege 0 is actually module inputs + for( adder = 0; adder < ST_OUT_NUM; adder++ ) begin: inputs_gen + + always_comb begin + if( adder < INPUTS_NUM ) begin + data[stage][adder][ST_WIDTH-1:0] <= idata[adder][ST_WIDTH-1:0]; + data[stage][adder][ODATA_WIDTH-1:ST_WIDTH] <= '0; + end else begin + data[stage][adder][ODATA_WIDTH-1:0] <= '0; + end + end // always_comb + + end // for + end else begin + // all other stages hold adders outputs + for( adder = 0; adder < ST_OUT_NUM; adder++ ) begin: adder_gen + + //always_comb begin // is also possible here + always_ff@(posedge clk) begin + if( ~nrst ) begin + data[stage][adder][ODATA_WIDTH-1:0] <= '0; + end else begin + data[stage][adder][ST_WIDTH-1:0] <= + data[stage-1][adder*2][(ST_WIDTH-1)-1:0] + + data[stage-1][adder*2+1][(ST_WIDTH-1)-1:0]; + end + end // always + + end // for + end // if stage + end // for +endgenerate + +assign odata = data[STAGES_NUM][0]; + +endmodule + diff --git a/adder_tree_tb.sv b/adder_tree_tb.sv new file mode 100644 index 0000000..5b6e78c --- /dev/null +++ b/adder_tree_tb.sv @@ -0,0 +1,97 @@ + +// RXI - PIN400M +// testbench for adder_tree.sv module + +`timescale 1ns / 1ps + +module adder_tree_tb(); + +logic clk200; +initial begin + #0 clk200 = 1'b0; + forever + #2.5 clk200 = ~clk200; +end + +logic rst; +initial begin + #0 rst = 1'b0; + #10.2 rst = 1'b1; + #5 rst = 1'b0; + //#10000; + forever begin + #9985 rst = ~rst; + #5 rst = ~rst; + end +end + +logic nrst; +assign nrst = ~rst; + +logic rst_once; +initial begin + #0 rst_once = 1'b0; + #10.2 rst_once = 1'b1; + #5 rst_once = 1'b0; +end + +logic nrst_once; +assign nrst_once = ~rst_once; + +logic [31:0] DerivedClocks; +clk_divider #( + .WIDTH( 32 ) +) cd1 ( + .clk( clk200 ), + .nrst( nrst_once ), + .ena( 1'b1 ), + .out( DerivedClocks[31:0] ) +); + +logic [31:0] E_DerivedClocks; +edge_detect ed1[31:0] ( + .clk( {32{clk200}} ), + .nrst( {32{nrst_once}} ), + .in( DerivedClocks[31:0] ), + .rising( E_DerivedClocks[31:0] ), + .falling( ), + .both( ) +); + +logic [15:0] RandomNumber1; +c_rand rng1 ( + .clk( clk200 ), + .rst( rst_once ), + .reseed( 1'b0 ), + .seed_val( DerivedClocks[31:0] ), + .out( RandomNumber1[15:0] ) +); + +logic start; +initial begin + #0 start = 1'b0; + #100 start = 1'b1; + #20 start = 1'b0; +end + +// Module under test ========================================================== + +adder_tree #( + .INPUTS_NUM( 7 ), + .IDATA_WIDTH( 16 ) +) at ( + .clk( clk200 ), + .nrst( nrst_once ), + .idata( { 12'b0,RandomNumber1[7:0], + 12'b0,RandomNumber1[8:1], + 12'b0,RandomNumber1[9:2], + 12'b0,RandomNumber1[10:3], + 12'b0,RandomNumber1[11:4], + 12'b0,RandomNumber1[12:5], + 12'b0,RandomNumber1[13:6] } ), + .odata( ) +); + + +endmodule +