2

我正在尝试使用初始块将值分配给只读推断 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 中对 issue #50 的讨论提供了一个示例模块mem2reg_with_two_always_blocks,表明它应该是。但是编译该模块会产生相同的警告消息。

4

1 回答 1

3

我通过实验发现,直到上电后的一些时钟周期,RAM 才能获得正确的值。

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

另请参阅此处此处了解更多信息。

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

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

当使用支持初始化存储器的流程(例如 iCE40 综合或 Xilinx 7 系列综合)时,您的 HDL 代码是可以的,并且应该产生具有初始化存储器资源的网表。


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

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

我想表达初始化发生在时间步 0 开始时(或之前!)的意图。

这就是任何初始块所做的,无论其中是否使用了阻塞或非阻塞分配。

于 2017-06-14T10:39:56.713 回答