Побитовое «И» массив регистров в Verilog

У меня есть массив регистров/шин и одна результирующая шина, определенная следующим образом.

wire [BW-1:0] bus_array[NUM-1:0];
reg  [BW-1:0] and_result;

где

parameter BW  = 4;
parameter NUM = 8;

Я хочу выполнить BW-битную операцию И над элементами массива и присвоить результат регистру and_result.

Я пытаюсь сделать это следующим образом.

integer l;

generate 
genvar m;
for (m=0; m<BW; m=m+1)
begin : BW_LOOP

    always @ (*)
    begin
      and_result[m] = 1'b1;
      for (l=0; l<NUM; l=l+1)
        and_result[m] = and_result[m] & bus_array[l][m];
    end

end
endgenerate

Однако, когда я имитирую это в Modelsim 10.1e, я получаю следующую ошибку.

Ошибка: (vsim-3601) Предел итерации достигнут за время 2 нс

Если я не использую цикл генерации, а вместо этого имею экземпляры BW блока always @ (*), симуляция работает нормально.

Из сообщения об ошибке я могу сделать вывод, что существует проблема с циклом генерации for, но я не могу решить эту проблему.


person Prashant    schedule 25.11.2014    source источник


Ответы (1)


Скорее всего баг с ModelSim. Воспроизводится на EDAplayground с помощью ModelSim10.1d. Отлично работает с Riviera2014 (после локализации l внутри цикла генерации). Я предполагаю, что and_result[m] каким-то образом находится в списке чувствительности @(*), чего быть не должно.

l необходимо локализовать, иначе к нему будут обращаться параллельно с сгенерированными блоками always; создание условия потенциального рейза.

Один из способов обхода — использовать SystemVerilog и использовать always_comb вместо always @(*).

Решение с обратной совместимостью состоит в том, чтобы изменить and_result[m] = and_result[m] & bus_array[l][m]; на if (bus_array[l][m]==1'b0) and_result[m] = 1'b0;, что является эквивалентным кодом. Это сохраняет and_result[m] только как левое выражение, поэтому оно не может быть в списке чувствительности.

genvar m;
for (m=0; m<BW; m=m+1)
begin : BW_LOOP
    integer l; // <== 'l' is local to this generate loop

    always @ (*)
    begin
      and_result[m] = 1'b1;
      for (l=0; l<NUM; l=l+1) begin
        if (bus_array[l][m]==1'b0) begin 
          and_result[m] = 1'b0;
        end
    end

end

Рабочий код здесь

person Greg    schedule 25.11.2014
comment
Грег, я пытался переместить целое число внутри цикла генерации, но это не помогло. Я также попытался заменить параметр BW в цикле генерации на константу. это не помогает - person Prashant; 25.11.2014
comment
Я только что играл с ним на EDAplaygrond с ModelSim10.1d, я могу воссоздать проблему, которую вы видят - person Greg; 25.11.2014
comment
Ух ты, EDAplayground — хороший сайт. Я не знал о существовании этого сайта. Спасибо за ссылку - person Prashant; 25.11.2014
comment
@Prashant, я собираюсь отозвать свой ответ, так как он не работает. Я поставлю ссылку в качестве комментария к вопросу. - person Greg; 25.11.2014
comment
@Prashant, я еще немного поиграл с этим и нашел обходное решение. - person Greg; 25.11.2014
comment
Я решил использовать модифицированную версию вашего решения. Теперь вместо always @(*) у меня есть строка always @(bus_array), и это также решает проблему. Такой код легче понять мне. Спасибо за ваши быстрые ответы. - person Prashant; 25.11.2014