Verilog 在合成中超过循环迭代限制,但在模拟中未超过

Verilog 在合成中超过循环迭代限制,但在模拟中未超过,verilog,fpga,synthesis,Verilog,Fpga,Synthesis,我用verilog编写代码,在活动通道中循环。 其思想是跳过活动向量中标记为0的通道 我在模拟器中测试了代码 ,它的工作和性能符合预期 当我尝试使用Synplify Pro合成代码时,我得到一个错误: “超出了E CS162循环迭代限制4000-在循环构造test1.v(11)之前添加'//synthesis Loop_limit 8000'” 错误指向循环的状态(i

我用verilog编写代码,在活动通道中循环。 其思想是跳过活动向量中标记为0的通道

我在模拟器中测试了代码 ,它的工作和性能符合预期

当我尝试使用Synplify Pro合成代码时,我得到一个错误: “超出了E CS162循环迭代限制4000-在循环构造test1.v(11)之前添加'//synthesis Loop_limit 8000'”

错误指向循环的状态(
i<6'b100000

在google中搜索这个错误时,我发现了一个常见的错误,那就是
I
的长度与
channel
的长度相同,这使得循环无法正常运行,因为
11111+1=00000

另外,Xilinx软件中有一些bug,但我没有使用它

知道我为什么会出现这个错误,或者为什么它与模拟不同吗? 有没有一种方法可以在没有循环的情况下实现这个函数

代码如下:

module test1 (
input wire [31:0] activity,
input wire  RESET,
input wire  CLK);

reg [4:0] channel, next_channel;
reg [5:0] i,j;

always @(activity, channel) begin
    next_channel = 5'b0;
    for (i = 6'b0; i < 6'b100000 ; i = i + 6'b1) begin
        j = i + {1'b0, channel} + 6'b1;
        if (j>6'b011111)
            j = j - 6'b100000;
        if (activity[j[4:0]]) begin
            next_channel = j[4:0];
            i = 6'b101111;
        end
    end
end

always @(posedge CLK, negedge RESET) begin
    if (RESET == 1'b0)
        channel = 5'b0;
    else
        channel = next_channel;
end

endmodule
模块测试1(
输入线[31:0]活动,
输入线复位,
输入线(时钟);
reg[4:0]频道,下一个_频道;
reg[5:0]i,j;
始终@(活动、频道)开始
下一个_通道=5'b0;
对于(i=6'b0;i<6'b100000;i=i+6'b1)开始
j=i+{1'b0,通道}+6'b1;
如果(j>6'b011111)
j=j-6'b100000;
如果(活动[j[4:0]])开始
下一个信道=j[4:0];
i=6'b101111;
结束
结束
结束
始终@(posedge时钟、negedge重置)开始
如果(重置==1'b0)
通道=5'b0;
其他的
信道=下一个信道;
结束
端模

首先,迭代次数不是循环迭代次数,而是编译迭代次数

问题是试图退出中间的循环(<代码> i= 6'B101111行)。这不能展开为一系列命令。似乎循环只会让你避免一遍又一遍地重复输入同样的内容,而不能做更复杂的事情

一种可能的解决方案是键入所有32个
if…else…if…else…
,以便在
活动中找到第一个
1
时,条件满足,并且您不输入下一个
else
。我想应该是这样的:

always @(activity, channel) begin
    next_channel = 5'b0;
    if (activity[channel + 1])
        next_channel = channel + 1;
    else if (activity[channel + 2])
            next_channel = channel + 2;  
         else if (activity[channel + 3])
                 next_channel = channel + 3; 
              else if (activity[channel + 4])
                      next_channel = channel + 4; 
    .
    .
    .
我用一个标志(如建议的)解决了这个问题。使用该标志,代码被展开为32个相同代码的不同
i
重复,并通过更改flas实现“停止”,以便在进一步重复时不满足条件

解决方案代码:

reg flag;

always @(activity, channel) begin
    next_channel = 5'b0;
    flag = 1;
    for (i = 6'b0; i < 6'b100000 ; i = i + 6'b1) begin
        j = i + {1'b0, channel} + 6'b1;
        if (j>6'b011111)
            j = j - 6'b100000;
        if (activity[j[4:0]] && flag) begin
            next_channel = j[4:0];
            flag = 0;
        end
    end
end
reg标志;
始终@(活动、频道)开始
下一个_通道=5'b0;
flag=1;
对于(i=6'b0;i<6'b100000;i=i+6'b1)开始
j=i+{1'b0,通道}+6'b1;
如果(j>6'b011111)
j=j-6'b100000;
如果(活动[j[4:0]]&&flag)开始
下一个信道=j[4:0];
flag=0;
结束
结束
结束

这通过了合成,并在模拟中给出了预期的结果。

如果循环限制实际上是一个错误,则不应出现此错误(右),你永远不应该修改循环中间的循环迭代器变量,或者使用任何其他方法从中间退出循环。它需要在编译时完全滚动,以便合成成功。+ 1用于修复它。但是请注意,你像程序员一样解决这个问题——你的HARWDARE太大,太慢了,而且你也会。e依靠合成器来理解它。首先,你需要考虑并行-查找优先级编码器。@EML,我发现了优先级编码器的实现,它看起来与我建议的嵌套ifs的解决方案非常相似。你认为这个解决方案更好吗?你能解释一下你是如何看到硬件很小的吗r和更快?我正在研究的模块更类似于循环仲裁器,但它需要跳过非活动通道,而且我还没有在web上找到任何实现。