OpenCores
URL https://opencores.org/ocsvn/adder_tree/adder_tree/trunk

Subversion Repositories adder_tree

[/] [adder_tree/] [adder_tree.sv] - Rev 3

Compare with Previous | Blame | View Log

`ifndef _adder_tree_
`define _adder_tree_

// DELAY = $clog2(N)
(* multstyle = "dsp" *) module adder_tree #(parameter
        N = 32, DATA_WIDTH = 33, RESULT_WIDTH = ((N-1) < 2**$clog2(N)) ? DATA_WIDTH + $clog2(N) : DATA_WIDTH + $clog2(N) + 1
)(
        input clock, clock_ena,
        input signed [DATA_WIDTH-1:0] data[N-1:0],
        output signed [RESULT_WIDTH-1:0] result
);
        generate
                if (N == 2)
                        add #(.DATAA_WIDTH(DATA_WIDTH), .DATAB_WIDTH(DATA_WIDTH), .RESULT_WIDTH(RESULT_WIDTH))
                                add_inst(.clock(clock), .clock_ena(clock_ena), .dataa(data[0]), .datab(data[1]), .result(result));
                else
                        begin
                                localparam RES_WIDTH = (RESULT_WIDTH > DATA_WIDTH + 1) ? DATA_WIDTH + 1 : RESULT_WIDTH;
                                localparam RESULTS = (N % 2 == 0) ? N/2 : N/2 + 1;
                                
                                wire signed [RES_WIDTH-1:0] res[RESULTS - 1:0];
                                
                                add_pairs #(.N(N), .DATA_WIDTH(DATA_WIDTH), .RESULT_WIDTH(RES_WIDTH))
                                        add_pairs_inst(.clock(clock), .clock_ena(clock_ena), .data(data), .result(res));
                                
                                adder_tree #(.N(RESULTS), .DATA_WIDTH(RES_WIDTH))
                                        adder_tree_inst(.clock(clock), .clock_ena(clock_ena), .data(res), .result(result));
                        end
        endgenerate
        
endmodule :adder_tree

//////////////////////
module add_pairs #(parameter
        N = 32, DATA_WIDTH = 18, RESULT_WIDTH = DATA_WIDTH + 1, RESULTS = (N % 2 == 0) ? N/2 : N/2 + 1
)(
        input clock, clock_ena,
        input signed [DATA_WIDTH-1:0] data[N - 1:0],
        output signed [RESULT_WIDTH-1:0] result[RESULTS - 1:0]
);
        genvar i;
        
        generate
                for (i = 0; i < N/2; i++)
                        begin :a
                                add #(.DATAA_WIDTH(DATA_WIDTH), .DATAB_WIDTH(DATA_WIDTH), .RESULT_WIDTH(RESULT_WIDTH))
                                        add_inst(.clock, .clock_ena, .dataa(data[2*i]), .datab(data[2*i + 1]), .result(result[i]));
                        end
                
                if (RESULTS == N/2 + 1)
                        begin
                                reg [RESULT_WIDTH-1:0] res;
                        
                                always @(posedge clock)
                                        if (clock_ena)
                                                res <= data[N-1];
                                
                                assign result[RESULTS-1] = res;
                        end
        endgenerate
endmodule :add_pairs

//////////////////////
module add #(parameter
        DATAA_WIDTH = 16, DATAB_WIDTH = 17, RESULT_WIDTH = (DATAA_WIDTH > DATAB_WIDTH) ? DATAA_WIDTH + 1 : DATAB_WIDTH + 1
)(
        input clock, clock_ena,
        input signed [DATAA_WIDTH-1:0] dataa,
        input signed [DATAB_WIDTH-1:0] datab,
        output reg signed [RESULT_WIDTH-1:0] result
);
        always_ff @(posedge clock)
                if (clock_ena)
                        result <= dataa + datab;
endmodule :add

`endif

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.