0

我目前正在使用 LFSR 在 SystemVerilog 中实现 PRNG,如此处所述。宽度应该使用参数可变。我达到了一个结构:

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 位?

4

2 回答 2

1

为此,您需要使用generate.

试试这个

  1. 将 case 语句块移出always_comb(您不能generatealways块中使用,如果这不代表,请有人纠正我always_comb
  2. tap =将语句更改为assign tap =.
  3. (可选)用/包围case块。这不是必需的,但您可能会发现它有助于提高可读性。generateendgenerate
于 2020-01-21T12:11:41.097 回答
1

你需要重组你的块,这样你就没有越界的引用。在模拟中,编译器不需要根据常量值优化你的程序代码,所以它需要是合法的。将 case 语句移到always块之外会将其从过程更改为基于详细说明(与 foriffor-loop 语句相同。

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;
于 2020-01-21T16:32:36.880 回答