2
votes

I wrote code in verilog that cycles through active channels. The idea is to skip channels that are marked by 0 in the activity vector.

I tested the code in a simulator screen shot from simulatior, it works and performs as expected.

When I try to synthesize the code using Synplify Pro, I get an error: "E CS162 Loop iteration limit 4000 exceeded - add '// synthesis loop_limit 8000' before the loop construct test1.v (11)"

The error points to the condition of the loop (i < 6'b100000).

Searching for the error in google I found a common mistake in a similar code of having i the same length as channel which makes the loop to run indefinetly because 11111 + 1 = 00000.

Also, there is some bug in Xilinx software but i'm not using it.

Any idea why i'm getting this error or why it differs from simulation? Is there a way to implement this function without a loop?

This is the code:

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
You shouldn't get this error if the loop limit is actually a (<4K) constant. What's the i = 47 line meant to do? Are you trying to exit the loop early? I think you're confusing the compiler, which thinks (correctly) that you've now got a variable iteration count. I don't think Synplify is smart enough to handle a variable limit. Think hardware - a functioning simulation is no guarantee that you can synthesise. - EML

1 Answers

3
votes

First, the number of iterrations is not loop iterations but rather compiling iterations.

The problem is trying to exit the loop in the middle (the i = 6'b101111 line). This can't be unrolled into a series of commands. Seems that loops only save you from re-typing the same thing over and over and can't do anything more complex.

A possible solution would be to type all the 32 if...else...if...else... such that when the first 1 in activity is found the condition is met and you don't enter the next else. I think it would look like this:

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; 
    .
    .
    .

I solved the problem with a flag (as EML suggested). With the flag, the code is unrolled into 32 repetitions of the same code with different i and the "stopping" is acheived by changing the flas so that the condition is not met in further repetitions.

The solution code:

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

This passed synthesis and gives the expected results in simulation.