I'm currently implementing a PRNG in SystemVerilog using an LFSR as described here. The width should be variable using a parameter. I reach a construct of:
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
Now, while simulating this module using Verilator it complains of selection indices out of range for every case > WIDTH-1
, even though (I think that) these cases should clearly be optimized out, since WIDTH is a constant:
Selection index out of range: 167:167 outside 31:0
Is there a simple way around this error, without eg. bit shifting logic just to index the nth bit?
To do this, you need to use a generate
.
Try this
always_comb
(you can't use generate
in an always
block, someone correct me if that does not stand for always_comb
tap =
statements to be assign tap =
.case
block with generate
/endgenerate
. This isn't required but you might find it helps readability.