verilog 综合在 2000 次迭代后不收敛
verilog synthesis not converging after 2000 iterations
我编写了下面的代码来实现 2 个 n 位数的简单乘法(这里 n=16)。它正在用所需的输出波形进行模拟,但问题是,它没有在 vivado 17.2 中合成,即使我写了一个 static 'for loop'(即,循环迭代是持续的)。我收到下面提到的错误。
[Synth 8-3380] loop condition does not converge after 2000 iterations
注:我写了
for(i=i;i<n;i=i+1)
而不是
for(i=0;i<n;i=i+1)
因为后一个在我到达n后再次执行。所以这不是一个错误。请有人帮助。谢谢你的时间
//unsigned integer multiplier
module multiplication(product,multiplier,multiplicand,clk,rset);
parameter n = 16;
output reg [(n<<1)-1:0]product;
input [n-1:0]multiplier, multiplicand;
input clk,rset;
reg [n:0]i='d0;
always @( posedge clk or posedge rset)
begin
if (rset) product <= 'd0;
else
begin
for(i=i;i<n;i=i+1)
begin
product =(multiplier[i] == 1'b1)? product + ( multiplicand << i ): product;
$display("product =%d,i=%d",product,i);
end
end
end
endmodule
首先,如果你真的想实现你的目标,那么使用 for、while 之类的循环并不是一个好习惯在 FPGA 上设计(Vivado 经过优化,可用于在 FPGA 上实现您的设计)。即使您可以成功综合您的设计,您也可能会遇到时序问题或意外错误。
我想你能找到你的答案。
编辑:我只是想告诉你,通常控制时序在硬件设计中非常重要,特别是当你想将你的设计与其他系统集成时,循环可能是噩梦。
错误消息与循环的迭代无关,而是与合成程序的内部算法的迭代有关。它告诉您 Vivado 未能创建一个电路,该电路实际上可以在您选择的时钟速度下在您选择的 FPGA 上实现,并且实际上可以满足您的要求。
让我详细说明一下,在我提到两项一般重要事项之后:不要在 always @(posedge clk)
块内使用阻塞赋值 (=
)。他们几乎从不做你想做的事。只有非阻塞分配 (<=
) 应该计时。其次,合成 for
循环的正确方法是使用 generate
,即使 Vivado 似乎接受简单的 for
.
您正在此处构建相当大的组合逻辑块。请记住,当您综合组合逻辑时,您需要的电路可以在单个时钟周期 内评估您编写的表达式 。实际考虑的表达式是展开 for 循环之后的表达式。即,您(有条件地)将 16 位数字与 32 位数字相加 16 次,每次都向左移动一位。这些添加中的每一个都有一个进位。因此,这些加法中的每一个实际上都必须查看前一个加法结果的所有高 16 位,并且每个加法都取决于前一个加法的最低位以外的所有位。一位+进位的加法器需要 O(5) 个门。每次加法都是有条件的,即为每一位至少增加一个门。所以你要求至少 16*16*6 = 1300 个相互依赖的门,它们都必须在一个时钟周期内稳定下来。 Vivado 告诉您它无法满足这些要求。
缓解此问题的一种方法是针对较低的时钟频率进行综合,其中门有更多时间稳定,因此您可以构建更长的逻辑链。另一种选择是流水线操作,例如仅评估与单个时钟周期内循环的四次迭代对应的内容,然后在多个时钟周期内构建结果。这会在您的代码中添加一些簿记逻辑,但如果想要在高时钟频率下使用有限资源评估复杂表达式,这是不可避免的。它还会向您介绍同步逻辑,如果您想用 FPGA 做任何重要的事情,您无论如何都必须学习同步逻辑。请注意,这种流水线不会显着影响吞吐量,因为您的 FPGA 然后会并行执行多个乘法。
您还可以重写表达式,以更智能的方式处理进位位和相互依赖性,从而允许 Vivado 通过表达式找到自己的方式(可能有这样一种方式,我假设它是综合的,如果您只是写乘法运算符?)。
最后,许多 FPGA 都带有专用的乘法器单元,因为乘法是一种常见的运算,但在逻辑门中实现它会浪费大量资源。如您所见。
返回使用原来的 for (i=0
循环。
你的错误是你假设 i=0 因为 reg [n:0]i='d0;
这只是在 第一次 时才正确。因此只有一次,在模拟开始时。
because the latter one was executing once again after i reached n.
是的,对于每个时钟周期,循环将一次又一次地重复。这就是 @( posedge clk ...)
所做的。
更多错误:
你在时钟部分使用阻塞赋值,使用非阻塞:
产品<=(乘数[i] == 1'b1)?乘积 + ( 被乘数 << i ): 乘积;
您的产品仅在重置后第一次正确(当它从零开始时)。重置后的第二个时钟周期,您再次进行乘法运算,但从乘积的前一个值开始。
你的i
有点大你用17位来数到16。全局循环变量也有陷阱。我建议您使用系统 Verilog 语法:`for (int i=0; ....)
我编写了下面的代码来实现 2 个 n 位数的简单乘法(这里 n=16)。它正在用所需的输出波形进行模拟,但问题是,它没有在 vivado 17.2 中合成,即使我写了一个 static 'for loop'(即,循环迭代是持续的)。我收到下面提到的错误。
[Synth 8-3380] loop condition does not converge after 2000 iterations
注:我写了
for(i=i;i<n;i=i+1)
而不是
for(i=0;i<n;i=i+1)
因为后一个在我到达n后再次执行。所以这不是一个错误。请有人帮助。谢谢你的时间
//unsigned integer multiplier
module multiplication(product,multiplier,multiplicand,clk,rset);
parameter n = 16;
output reg [(n<<1)-1:0]product;
input [n-1:0]multiplier, multiplicand;
input clk,rset;
reg [n:0]i='d0;
always @( posedge clk or posedge rset)
begin
if (rset) product <= 'd0;
else
begin
for(i=i;i<n;i=i+1)
begin
product =(multiplier[i] == 1'b1)? product + ( multiplicand << i ): product;
$display("product =%d,i=%d",product,i);
end
end
end
endmodule
首先,如果你真的想实现你的目标,那么使用 for、while 之类的循环并不是一个好习惯在 FPGA 上设计(Vivado 经过优化,可用于在 FPGA 上实现您的设计)。即使您可以成功综合您的设计,您也可能会遇到时序问题或意外错误。
我想你能找到你的答案
编辑:我只是想告诉你,通常控制时序在硬件设计中非常重要,特别是当你想将你的设计与其他系统集成时,循环可能是噩梦。
错误消息与循环的迭代无关,而是与合成程序的内部算法的迭代有关。它告诉您 Vivado 未能创建一个电路,该电路实际上可以在您选择的时钟速度下在您选择的 FPGA 上实现,并且实际上可以满足您的要求。
让我详细说明一下,在我提到两项一般重要事项之后:不要在 always @(posedge clk)
块内使用阻塞赋值 (=
)。他们几乎从不做你想做的事。只有非阻塞分配 (<=
) 应该计时。其次,合成 for
循环的正确方法是使用 generate
,即使 Vivado 似乎接受简单的 for
.
您正在此处构建相当大的组合逻辑块。请记住,当您综合组合逻辑时,您需要的电路可以在单个时钟周期 内评估您编写的表达式 。实际考虑的表达式是展开 for 循环之后的表达式。即,您(有条件地)将 16 位数字与 32 位数字相加 16 次,每次都向左移动一位。这些添加中的每一个都有一个进位。因此,这些加法中的每一个实际上都必须查看前一个加法结果的所有高 16 位,并且每个加法都取决于前一个加法的最低位以外的所有位。一位+进位的加法器需要 O(5) 个门。每次加法都是有条件的,即为每一位至少增加一个门。所以你要求至少 16*16*6 = 1300 个相互依赖的门,它们都必须在一个时钟周期内稳定下来。 Vivado 告诉您它无法满足这些要求。
缓解此问题的一种方法是针对较低的时钟频率进行综合,其中门有更多时间稳定,因此您可以构建更长的逻辑链。另一种选择是流水线操作,例如仅评估与单个时钟周期内循环的四次迭代对应的内容,然后在多个时钟周期内构建结果。这会在您的代码中添加一些簿记逻辑,但如果想要在高时钟频率下使用有限资源评估复杂表达式,这是不可避免的。它还会向您介绍同步逻辑,如果您想用 FPGA 做任何重要的事情,您无论如何都必须学习同步逻辑。请注意,这种流水线不会显着影响吞吐量,因为您的 FPGA 然后会并行执行多个乘法。
您还可以重写表达式,以更智能的方式处理进位位和相互依赖性,从而允许 Vivado 通过表达式找到自己的方式(可能有这样一种方式,我假设它是综合的,如果您只是写乘法运算符?)。
最后,许多 FPGA 都带有专用的乘法器单元,因为乘法是一种常见的运算,但在逻辑门中实现它会浪费大量资源。如您所见。
返回使用原来的 for (i=0
循环。
你的错误是你假设 i=0 因为 reg [n:0]i='d0;
这只是在 第一次 时才正确。因此只有一次,在模拟开始时。
because the latter one was executing once again after i reached n.
是的,对于每个时钟周期,循环将一次又一次地重复。这就是 @( posedge clk ...)
所做的。
更多错误:
你在时钟部分使用阻塞赋值,使用非阻塞:
产品<=(乘数[i] == 1'b1)?乘积 + ( 被乘数 << i ): 乘积;
您的产品仅在重置后第一次正确(当它从零开始时)。重置后的第二个时钟周期,您再次进行乘法运算,但从乘积的前一个值开始。
你的
i
有点大你用17位来数到16。全局循环变量也有陷阱。我建议您使用系统 Verilog 语法:`for (int i=0; ....)