繁体   English   中英

在 SystemVerilog 的 for 循环中使用总线的正确方法?

[英]Proper way to use a bus in a for loop in SystemVerilog?

我正在尝试在 SystemVerilog 中创建一个模块,该模块可以找到最多具有 8 个 8 位值的两个向量之间的点积。 我试图让它对不同长度的向量具有灵活性,所以我有一个名为 EN 的输入,它是 3 位并确定要执行的乘法次数。

因此,如果 EN == 3'b101,则每个向量的前五个值将相乘并相加,然后输出为 32 位值。 现在,我正在尝试这样做:

int acc = 0;

always_comb
begin
for(int i = 0; i < EN; i++) begin
    acc += A[i] * B[i];
    end
end
assign OUT = acc;

其中 A 和 B 是两个输入向量。 但是,SystemVerilog 告诉我在 i 和 EN 之间进行了非法比较。

所以我的问题是:

1) 这是在 SystemVerilog 中使用可变向量“长度”的正确方法吗?

2)如果是这样,迭代 n 次的正确方法是什么,其中 n 是总线上的值?

谢谢!

我必须在这里猜测,但我假设它是一个抱怨该代码的合成器。 我使用的合成器接受您的代码稍加修改,但可能不是全部都这样做,因为循环不能静态展开(注意我有input logic [2:0] EN ,也许input int EN由于太大而不起作用最大循环数)。 你的循环本身(问题#2)很好。

int acc;
always_comb
begin
// If acc is not reset always_comb tries to update on its old value and puts
// it in sensitivity list, halting simulation... also no initialization to variable
// used in always_comb is allowed.
acc = 0;
...

这是抱怨您在其他方面非常好的代码的一个有点体面的理由,并且该工具不会假设在这种特定情况下生成所有可能的循环是“合理的”(如果 EN 是无符号整数,您的芯片将是愚蠢的毕竟巨大):您可以强制该工具使用如下所示的内容推断所有可能性:

module test (
    input int A[8],
    input int B[8],
    input logic [2:0] EN,
    output int OUT
);

    int acc[8];  // 8 accumulators

    always_comb begin
        acc[0] = A[0] * B[0];  // acc[-1] does not exist, different formula!
        for (int i = 1; i < 8; i++) begin
            // Each partial sum builds on previous one.
            acc[i] = acc[i-1] + (A[i] * B[i]);
        end
    end

    assign OUT = acc[EN];  // EN used as selector for a multiplexer on partial sums

endmodule: test

上面的模块是对我的合成器推断的“并行循环”的明确描述。

关于您的问题#1,答案是“视情况而定”。 在硬件中没有可变长度,因此除非您将迭代次数固定为参数而不是输入,否则您要么具有最大大小并忽略某些值,要么使用指向某些内存的指针迭代多个周期。 如果您想在测试中使用可变矢量长度(而不是硅片),那么您可以声明一个“动态数组”,您可以随意调整其大小(IEEE 1800-2017, 7.5: Dynamic arrays):

int dyn_vec[];

最后要注意的是, int bad integer对所有非测试平台都有好处,以便捕获X值并避免 RTL 合成不匹配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM