我为下面的代码编写了2个n位数字(这里n = 16)的简单乘法。它正在使用所需的输出波形进行仿真,但是问题是,即使我编写了静态“ for循环” (即,循环迭代是恒定的),它也无法在vivado 17.2中进行合成。我收到以下提到的错误。
[Synth 8-3380]循环条件在2000次迭代后不收敛
注意:我写过
int sumLength = 0;
ArrayList<String> r = new ArrayList<String>();
for(String s : r)
{
sumLength += s.length();
}
return sumLength;
代替
for(i=i;i<n;i=i+1)
因为后一个在我到达n后再次执行。因此,这不是一个错误。请有人帮助。谢谢您的时间
for(i=0;i<n;i=i+1)
答案 0 :(得分:3)
首先,如果您真的想在FPGA上实现您的设计,则不宜将用于,同时类循环(Vivado已针对用于在FPGA上实现您的设计)。即使您可以成功地综合设计,也可能会遇到时序问题或意外错误。
我认为您可以找到答案here。
编辑:我只是想告诉您,总体上控制时序在硬件设计中非常重要,尤其是当您要将设计与其他系统集成时,循环可能是噩梦。
答案 1 :(得分:2)
返回使用原始的for (i=0
循环。
您的错误是您由于reg [n:0]i='d0;
假设i = 0,这是非常第一次。因此,在仿真开始时仅一次。
因为后一个在我到达n后再次执行。
是的,循环将在每个时钟周期一次又一次地重复 。 @( posedge clk ...)
就是这样做的。
更多错误:
您正在时钟部分使用阻塞分配,请使用非阻塞:
乘积<=(乘数[i] == 1'b1)?产品+(被乘数<< i):产品;
您的产品仅在重置后的第一次(从零开始时)是正确的。重置后的第二个时钟周期,您将再次进行乘法运算,但从乘积的先前值开始。
您的i
有点大,您使用17位来计数到16。而且全局循环变量也有陷阱。我建议您使用系统Verilog语法:`for(int i = 0; ....)
答案 2 :(得分:1)
该错误消息与循环的迭代无关,而是与综合程序内部算法的迭代有关。它告诉您Vivado无法创建一个电路,该电路实际上可以在您选择的时钟频率上在您选择的FPGA上实现,并且实际上可以满足您的要求。
让我详细说明一下,在我提到了两个一般性的含义之后:不要在=
块内使用块分配(always @(posedge clk)
)。他们几乎永远不会做您想要的。只有非阻塞分配(<=
)应该被计时。其次,即使Vivado似乎接受简单的for
,正确的合成generate
循环的方式还是使用for
。
您在此处构建相当大的组合逻辑块。请记住,当您合成组合逻辑时,您所要求的电路可以评估您在一个时钟周期内编写的表达式。考虑的实际表达式是展开for循环之后的表达式。也就是说,您(有条件地)将16位数字添加到32位数字中16次,每次都向左移动一位。这些加法中的每一个都有一个进位位。因此,这些加法中的每一个实际上都必须查看先前加法结果的所有高16位,并且每个都将依赖于除先前加法的最低位以外的所有比特。 1位加进位的加法器需要O(5)门。每次加法都是有条件的,这将为每个位至少增加一个门。因此,您要求至少16 * 16 * 6 = 1300个相互依赖的门,所有这些门必须在一个时钟周期内稳定下来。 Vivado告诉您它不能满足这些要求。
缓解此问题的一种方法是在较低的时钟频率下进行合成,其中门具有更多的稳定时间,因此可以构建更长的逻辑链。另一个选择是对操作进行流水线处理,例如,仅在单个时钟周期内评估与循环的四个迭代相对应的值,然后在多个时钟周期内构建结果。这将在代码中添加一些簿记逻辑,但是如果要在高时钟频率下使用有限的资源来评估复杂的表达式,这是不可避免的。它还将向您介绍同步逻辑,如果您想对FPGA进行一些重要的工作,则无论如何都必须学习。请注意,这种流水线操作不会显着影响吞吐量,因为您的FPGA随后将并行进行多次乘法。
您也许还可以重写表达式,以更智能的方式处理进位位和相互依存关系,从而使Vivado可以通过表达式找到其方式(如果您只是编写乘法运算符?)。
最后,许多FPGA带有专用的乘法器单元,因为乘法是一种常见的操作,但是在逻辑门中实现它会浪费大量资源。如您所知。