我正在尝试在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是总线上的值?
谢谢!
答案 0 :(得分:0)
我必须在这里猜测,但是我假设它是一个合成器,抱怨该代码。我使用的合成器接受了稍作修改的代码,但是由于循环不能静态展开,所以可能无法全部接受(请注意,我有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:动态数组):
int dyn_vec[];
最后一点要注意的是,int
不好的integer
对于不是测试台的所有内容都有好处,以便捕获X
的值并避免RTL合成不匹配。