4

所以,我正在尝试在verilog中编写一个加法器树。它的通用部分是它具有可配置数量的要添加的元素和可配置的字长。但是,我遇到一个又一个问题,我开始质疑这是解决我的问题的正确方法。(我将在一个更大的项目中使用它。)绝对可以对加法器树进行硬编码,尽管这会占用大量文本。

所以,我虽然会和你核对一下你对它的看法。这是“这样做的方法”吗?我也愿意就不同的方法提出建议。

我还可以提到我对verilog很陌生。

如果有人感兴趣,这是我当前的非工作代码:(我不指望你解决问题;我只是为了方便起见。)

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
4

1 回答 1

7

以下是一些您可能会觉得有用的评论:

时钟

在您的设计中使用尽可能少的时钟通常是件好事(最好只有一个)。

在这种特殊情况下,您似乎正在尝试生成新时钟clkPl,但这不起作用,因为它永远不会返回到 0。(“reg clkPl=0;”将在时间 0 将其重置为 0,然后设置在“clkPl = 1;”中永久为 1。)

您可以通过简单地替换来解决此问题

always @ (posedge clkPl)

always @ (posedge clk)

作业

仅在组合块中使用阻塞分配,在时钟块中使用非阻塞是一种很好的形式。您在“打包扁平术语”部分中混合了阻塞和非阻塞分配。

由于您不需要clkPl,您可以简单地删除带有阻塞分配的行 ("clkPl = 1;")

树结构

你的双 for 循环:

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

看起来它将访问不正确的元素。

例如,对于 BANKSIZE = 2 8,**i将计数到 7,此时 "pipeline[i * (2 ** i) + j]"="pipeline[7*2**7+j]"=" pipeline[896+j] 将超出数组的范围。(数组中有 2*BANKSIZE=512 个元素。)

我认为您实际上想要这种结构:

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

更低的延迟

请注意,大多数 Verilog 工具非常擅长合成多个元素的添加,因此您可能需要考虑在层次结构的每个级别组合更多术语。

(添加更多项的成本比人们预期的要低,因为这些工具可以使用诸如进位保存加法器之类的优化来减少门延迟。)

于 2013-01-22T21:43:32.100 回答