Параметр SystemVerilog/Verilator WIDTH и индексирование структуры кейса за пределами

В настоящее время я реализую PRNG в SystemVerilog, используя LFSR, как описано здесь. Ширина должна изменяться с помощью параметра. Я достигаю конструкции:

module PRNG
#(
    parameter WIDTH = 32,
    parameter SEED = 1
)
(
    input clk,
    input update,
    output reg [WIDTH-1:0] prng
);

reg [WIDTH-1:0] lastRng = WIDTH'(SEED);

always_comb begin
    var tap;

    case (WIDTH)
        default: tap = 0;
        3: tap = lastRng[2] ^~ lastRng[1];
        [...]
        168: tap = lastRng[167] ^~ lastRng[165] ^~ lastRng[152] ^~ lastRng[150];
    endcase

    if (update) begin
        prng = {lastRng[WIDTH-2:0], tap};
    end else begin
        prng = lastRng;
    end
end

always_ff @(posedge clk) begin
    lastRng <= prng;
end

endmodule

Теперь, моделируя этот модуль с помощью Verilator, он жалуется на то, что индексы выбора выходят за пределы диапазона для каждого случая. > WIDTH-1, хотя (я думаю, что) эти случаи явно должны быть оптимизированы, поскольку WIDTH является константой:

Selection index out of range: 167:167 outside 31:0

Есть ли простой способ обойти эту ошибку, например, без. логика сдвига бит только для индексации n-го бита?

2 ответа

Решение

Для этого вам нужно использовать generate.

Попробуй это

  1. Переместите блок оператора case за пределы always_comb (вы не можете использовать generate в always блок, кто-нибудь поправит меня, если это не означает always_comb
  2. Изменить tap = заявления быть assign tap =.
  3. (необязательно) Окружите case блок с generate/endgenerate. Это не обязательно, но может помочь читаемости.

Вам необходимо реструктурировать свой блок, чтобы у вас не было ссылок, выходящих за пределы. При моделировании компилятор не требуется для оптимизации вашего процедурного кода на основе постоянных значений, поэтому он должен быть законным. Перемещение оператора case за пределыalways блок изменяет его с процедурного на основанный на разработке (то же самое для if а также for-циклические операторы.

logic tap;// same as var tap, but better to show the implicit data type

case (WIDTH)
    default: assign tap = 0;
    3: assign tap = lastRng[2] ^~ lastRng[1];
    [...]
    168: assign tap = lastRng[167] ^~ lastRng[165] ^~ lastRng[152] ^~ lastRng[150];
endcase

always_comb
if (update)
    prng = {lastRng[WIDTH-2:0], tap};
else 
    prng = lastRng;
Другие вопросы по тегам