Превышение предела повторения цикла в синтезе, но не в моделировании

Я написал код на Verilog, который циклически перебирает активные каналы. Идея состоит в том, чтобы пропустить каналы, отмеченные 0 в векторе активности.

Я протестировал код в симуляторе, снимок экрана из симулятора, он работает и работает так, как ожидалось. .

Когда я пытаюсь синтезировать код с помощью Synplify Pro, я получаю сообщение об ошибке: «E CS162 Превышен предел итераций цикла 4000 — добавьте ‘// synchronous loop_limit 8000’ перед созданием цикла test1.v (11)».

Ошибка указывает на состояние цикла (i < 6'b100000).

В поисках ошибки в Google я обнаружил распространенную ошибку в аналогичном коде, когда i имеет ту же длину, что и channel, что заставляет цикл работать бесконечно, потому что 11111 + 1 = 00000.

Кроме того, в программном обеспечении Xilinx есть ошибка, но я ею не пользуюсь.

Любая идея, почему я получаю эту ошибку или почему она отличается от моделирования? Есть ли способ реализовать эту функцию без цикла?

Это код:

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

person Alexander Tarnavsky    schedule 16.03.2019    source источник
comment
Вы не должны получить эту ошибку, если предел цикла на самом деле является константой (‹4K). Для чего предназначена строка i = 47? Вы пытаетесь выйти из цикла раньше? Я думаю, вы сбиваете с толку компилятор, который считает (правильно), что теперь у вас есть переменный счетчик итераций. Я не думаю, что Synplify достаточно умен, чтобы справиться с переменным лимитом. Подумайте об аппаратном обеспечении — работающая симуляция не гарантирует, что вы сможете синтезировать.   -  person EML    schedule 17.03.2019


Ответы (1)


Во-первых, количество итераций — это не количество итераций цикла, а количество итераций компиляции.

Проблема заключается в попытке выйти из цикла в середине (строка i = 6'b101111). Это не может быть развернуто в серию команд. Кажется, что циклы только спасают вас от повторного ввода одного и того же снова и снова и не могут сделать ничего более сложного.

Возможным решением было бы ввести все 32 if...else...if...else... таким образом, чтобы при обнаружении первого 1 в activity условие выполнялось, и вы не вводили следующее 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; 
    .
    .
    .

Я решил проблему с помощью флага (как предложил EML). С флагом код разворачивается на 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

Это прошло синтез и дает ожидаемые результаты при моделировании.

person Alexander Tarnavsky    schedule 17.03.2019
comment
правильно, вы никогда не должны изменять переменную итератора цикла в середине цикла или использовать любые другие способы выхода из цикла из середины. Он должен быть полностью развернут во время компиляции для успешного синтеза. - person Serge; 17.03.2019
comment
+1 за исправление. Но обратите внимание, что вы решаете это как программист — ваш харддер слишком велик и слишком медленный, и вы полагаетесь на синтезатор, чтобы понять его. Вам нужно мыслить параллельно — для начала найдите приоритетные кодировщики. - person EML; 18.03.2019
comment
@EML, я нашел это реализация кодировщика приоритетов, и это очень похоже на решение, которое я предложил с вложенными ifs. Как вы думаете, это решение лучше? Не могли бы вы объяснить, как вы видите, что аппаратное обеспечение меньше и быстрее? Модуль, над которым я работаю, больше похож на круговой арбитр, но он должен пропускать неактивные каналы, и я не нашел никаких реализаций в Интернете. - person Alexander Tarnavsky; 20.03.2019