Verilog, general summation tree

So I am trying to write an adder tree in verilog. The general part of it is that it has a configurable number of added elements and a configurable word size. However, I ran into issue after issue and I am starting to doubt if this is the correct way to solve my problem. (I will be using it in a larger project.) You can definitely just hard-code the adder tree, although it will take a lot of text.

So while I would check with you on Stack Overflow for what you think of it. Is this the "way to do it"? I am open to suggestions for different approaches.

I can also mention that I am completely new to verilog.

In case anyone is interested, here is my current non-working code: (I don't expect you to solve problems, I'll just show it for convenience.)

module adderTree(
    input clk,
    input [`WORDSIZE * `BANKSIZE - 1 : 0] terms_flat,
    output [`WORDSIZE - 1 : 0] sum
);

genvar i, j;

reg [`WORDSIZE - 1 : 0] pipeline [2 * `BANKSIZE - 1 : 0];   // Pipeline array
reg clkPl = 0;                                              // Pipeline clock

assign sum = pipeline[0];

// Pack flat terms
generate
    for (i = `BANKSIZE; i < 2 * `BANKSIZE; i = i + 1) begin
        always @ (posedge clk) begin
            pipeline[i] <= terms_flat[i * `WORDSIZE +: `WORDSIZE];
            clkPl = 1;
        end
    end
endgenerate

// Add terms logarithmically
generate
    for (i = 0; i < $clog2(`BANKSIZE); i = i + 1) begin
        for (j = 0; j < 2 ** i; j = j + 1) begin
            always @ (posedge clkPl) begin
                pipeline[i * (2 ** i) + j] <= pipeline[i * 2 * (2 ** i) + 2 * j] + pipeline[i * 2 * (2 ** i) + 2 * j + 1];
            end
        end
    end
endgenerate

endmodule

      

+3


source to share


1 answer


Here are some notes you might find useful:

Clocking

It is generally good to have as few clocks as possible in your design (preferably only one).

In this particular case, it seems that you are trying to generate a new clkPl clock , but that doesn't work because it will never go back to 0. ("reg clkPl = 0;" will reset to 0 at time 0, then it is permanently set to 1 in "clkPl = 1;".)

You can fix this by simply replacing

always @ (posedge clkPl)

      

from

always @ (posedge clk)

      

APPOINTMENTS

A good form is to only use blocking assignments in combinatorial blocks, and non-blocking in clocked blocks. You mix both blocking and non-blocking assignments in the Flat Package Conditions section.

As you don't need clkPl , you can simply delete the line with the lock assignment ("clkPl = 1;")



WOOD STRUCTURE

Your double loop:

for (i = 0; i < $clog2(`BANKSIZE); i = i + 1) begin
    for (j = 0; j < 2 ** i; j = j + 1) begin
        always @ (posedge clkPl) begin
            pipeline[i * (2 ** i) + j] <= pipeline[i * 2 * (2 ** i) + 2 * j] + pipeline[i * 2 * (2 ** i) + 2 * j + 1];
        end
    end
end

      

it looks like it will access the wrong elements.

eg. for BANKSIZE = 2 8, ** i will be counted up to 7, then "pipeline [i * (2 ** i) + j]" = "pipeline [7 * 2 ** 7 + j]" = "pipeline [896 + j] which will be outside of the array. (The array has 2 * BANKSIZE = 512 elements in it.)

I think you really want this structure:

assign sum = pipeline[1];
for (i = 1; i < `BANKSIZE; i = i + 1) begin
    always @ (posedge clk) begin
        pipeline[i] <= pipeline[i*2] + pipeline[i*2 + 1];
        end
    end

      

LOWER LATNESS

Note that most verilog tools are very good at synthesizing multiple additions, so you may want to consider combining more terms at each level of the hierarchy.

(Adding more terms costs less than one might expect, because instruments might use optimizations like carry-over accumulators to reduce shutter lag.)

+5


source







All Articles