如何在 Yosys 的初始块中分配 RAM 值?

How to assign RAM values in an initial block in Yosys?

我正在尝试使用初始块将值分配给只读推断 RAM:

module rom (
    input clk,
    input [5:0] addr,
    output reg [15:0] data);

    reg [15:0] mem [0:63];

    initial begin
        mem[0] = 1;
        mem[1] = 2;
    end

    always @(posedge clk)
        data <= mem[addr];

endmodule

Yosys 发出此警告消息:

$ yosys -q -p "synth_ice40 -blif rom.blif" rom.v
Warning: Blocking assignment to memory in line rom.v:9 is handled like a non-blocking assignment.
Warning: Blocking assignment to memory in line rom.v:10 is handled like a non-blocking assignment.

如果我忽略警告(或将初始分配更改为非阻塞),我通过实验发现 RAM 在加电后的某些时钟周期之前不会获得正确的值。

难道不能这样使用初始块吗? yosys github repo 中对问题 #50 的讨论提供了一个示例模块 mem2reg_with_two_always_blocks,这表明它应该是。但是编译该模块会绘制相同的警告消息。

I find experimentally that the RAM doesn't get its correct values until some clock cycles after power-up.

不幸的是你没有说你是怎么做到的。我假设您正在使用 iCE40 综合,并且 运行 它在硬件中使用 SRAM 编程,因为这将匹配已知的 iCE40 硬件问题。

另请参阅 here and here 了解更多信息。

解决方法:不要使用 SRAM 编程或让您的设计再复位几个周期,以便给 BRAM 初始化一些时间来完成。

使用 Lattice 工具时也可以重现该问题。这是一个硬件错误。综合流程对此无能为力。

您的 HDL 代码没问题,当使用支持初始化存储器的流程(例如 iCE40 综合或 Xilinx 7 系列综合)时,应该会生成具有初始化存储器资源的网表。


编辑评论:您可以忽略初始块中的警告 re blocking vs nonblocking assignments。在您的情况下,如果分配被解释为阻塞或非阻塞,则没有任何区别。但是像下面这样的代码会导致问题:

initial begin
    mem[0] = 1;
    mem[1] = mem[0];
end

I want to express the intention that the initialization happens at (or before!) the beginning of timestep 0.

这就是任何初始块所做的,无论其中使用的是阻塞赋值还是非阻塞赋值。