Параметр 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
.
Попробуй это
- Переместите блок оператора case за пределы
always_comb
(вы не можете использоватьgenerate
вalways
блок, кто-нибудь поправит меня, если это не означаетalways_comb
- Изменить
tap =
заявления бытьassign tap =
. - (необязательно) Окружите
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;