Verilog中单端口RAM的推断

Verilog中单端口RAM的推断,verilog,fpga,intel-fpga,Verilog,Fpga,Intel Fpga,我正在尝试制作一个32x4(32字,4位)单端口RAM块。这是我的Verilog代码: module RAM_array (input clk, wren, input [4:0] address, input [3:0] data, output reg [3:0] q); reg [3:0] mem [31:0]; // a 4 bit wide 32 word RAM block. always @(posedge clk

我正在尝试制作一个32x4(32字,4位)单端口RAM块。这是我的Verilog代码:

module RAM_array (input clk, wren, input [4:0] address,
                        input [3:0] data, output reg [3:0] q);

    reg [3:0] mem [31:0]; // a 4 bit wide 32 word RAM block.

    always @(posedge clk) begin
            if (wren)
                mem[address] <= data;
            q <= mem[address];
    end
endmodule
模块RAM_阵列(输入时钟、扳手、输入[4:0]地址、,
输入[3:0]数据,输出reg[3:0]q);
注册[3:0]成员[31:0];//一个4位宽的32字RAM块。
始终@(posedge clk)开始
如果(鹪鹩)

mem[address]我猜当您尝试在写入后读取一个时钟周期,但仍然得到旧值时,您会看到“额外的时钟周期”。 发生这种情况的原因是,当您写入mem时,以及当您驱动输出q时,使用的是非阻塞分配。 因此,写入mem需要一个时钟周期,读取mem需要一个时钟周期。总共是两个周期

如果要减少内存延迟,请使用concurrent语句并“分配”输出q。 这将实现从mem到输出q的简单连接:

module RAM_array (input clk, wren, input [4:0] address,
                    input [3:0] data, output [3:0] q);

    reg [3:0] mem [31:0]; // a 4 bit wide 32 word RAM block.

    always @(posedge clk) 
            if (wren)
                mem[address] <= data;

    assign q = mem[address];

endmodule
模块RAM_阵列(输入时钟、扳手、输入[4:0]地址、,
输入[3:0]数据,输出[3:0]q);
注册[3:0]成员[31:0];//一个4位宽的32字RAM块。
始终@(posedge clk)
如果(鹪鹩)
mem[address]零周期读取延迟,1周期写入延迟)。

这是可以的,不应该影响你的合成,因为它是一个非常小的数组

您的意思是“等待一个额外的时钟周期以使其写入”还是“等待一个额外的时钟周期以使
q
输出改变”?考虑到您编写代码的方式,更改输出
q
需要2个时钟周期。您能否详细说明在什么意义上插入了额外的延迟周期?如果希望
q
在下一个循环中反映新值,请尝试阻塞赋值。至少Verilog不是我的强项,但如果合成器决定将逻辑映射到一个语义与代码本身不同的块,我会感到惊讶。因为在代码中使用“非阻塞”赋值,q将始终获得mem[address]的旧值。因此,如果数据更改,比如说更改为“1”,并且mem[address]之前为“0”,verilog会将“1”分配给“mem”,但之后会将“0”分配给q。所以,你需要下一个时钟周期来将值传播到“q”。啊,我现在明白了。如果我想让q的值改变下一个时钟周期,那么使用阻塞分配是实现这一点的唯一方法吗?在顺序块中使用块分配不是总是很糟糕吗?或者这将是一个例外的指导方针(我很确定必须有一种方法来改进我的设计,而不是使用阻塞语句…)是的,在触发器块的输出上使用阻塞是不好的。不过,你可以在内部temp上使用它。但你现在问的是另一个问题。因此有一个问题要问你:它在你的设计中应该如何工作?谢谢!因此,这意味着,如果我有一个尺寸大得多的SRAM块,如果我需要减少延迟,我需要像Pulimon建议的那样,在写操作期间,在读操作上有某种“新数据”与“旧数据”的对比?因为使用32k触发器代替sram块并不是一个好主意……并非所有FPGA设备都支持这种带有sram块的内存。另外,请注意,这种SRAM的写入延迟为零——当它是同一地址时,从写入到读取之间存在一个旁路。一般来说,对于32Kb的大内存,我不推荐使用它,除非对您来说时间不是问题。在我看来,对于您描述的场景,正确的做法是使用原始SRAM和延迟,并修改与之交互的RTL以预期延迟。但是,这又是一个需要和资源的问题