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
source to share
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.)
source to share