[英]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.