SystemVerilog/Verilator WIDTH 参数和 case 结构索引越界
SystemVerilog/Verilator WIDTH parameter and case structure indexing out of bounds
我目前正在使用 LFSR 在 SystemVerilog 中实现 PRNG,如 here 所述。宽度应使用参数可变。我达到了以下结构:
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 位?
为此,您需要使用 generate
。
试试这个
- 将 case 语句块移到
always_comb
之外(您不能在 always
块中使用 generate
,如果这不代表 [=11],请有人纠正我=]
- 将
tap =
语句更改为 assign tap =
。
- (可选)用
generate
/endgenerate
包围 case
块。这不是必需的,但您可能会发现它有助于提高可读性。
您需要重组您的块,这样您就没有越界引用。在模拟中,编译器不需要根据常量值优化你的过程代码,所以它需要是合法的。将 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;
我目前正在使用 LFSR 在 SystemVerilog 中实现 PRNG,如 here 所述。宽度应使用参数可变。我达到了以下结构:
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 位?
为此,您需要使用 generate
。
试试这个
- 将 case 语句块移到
always_comb
之外(您不能在always
块中使用generate
,如果这不代表 [=11],请有人纠正我=] - 将
tap =
语句更改为assign tap =
。 - (可选)用
generate
/endgenerate
包围case
块。这不是必需的,但您可能会发现它有助于提高可读性。
您需要重组您的块,这样您就没有越界引用。在模拟中,编译器不需要根据常量值优化你的过程代码,所以它需要是合法的。将 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;