《FPGA基础知识》系列导航
本专栏专为FPGA新手打造的Xilinx平台入门指南。旨在手把手带你走通从代码、仿真、约束到生成比特流并烧录的全过程。
本篇是该系列的第十八篇内容
上一篇:FPGA基础知识(十七):Xilinx Block Memory IP核(2)--单端口 RAM 的三种操作模式详解-优快云博客
下一篇:关注我,第一时间获取更新!!
1 核心概念:读写分离的存储架构
想象一个双车道收费站:一条车道专门负责车辆进入(写入数据),另一条车道专门负责车辆离开(读取数据),两者互不干扰,同时运行。这正是Simple Dual Port RAM的核心设计哲学。
与单端口RAM的本质区别在于:单端口RAM只能在同一个时钟下进行读写操作,而Simple Dual Port RAM可以进行异步读写。但与True Dual Port RAM(两个端口都可读写)不同,它的端口角色是固定的:Port A专用于写,Port B专用于读。
2 IP核配置与使用
2.1 端口信号
端口信号如下图所示:

信号说明如下:
ENTITY blk_mem_gen_0 IS
PORT (
--- 端口A:写端口
clka : IN STD_LOGIC; --- Port A的时钟
ena : IN STD_LOGIC; --- Port A使能信号
wea : IN STD_LOGIC_VECTOR(0 DOWNTO 0); --- 写使能,高电平有效,与clka同步
addra : IN STD_LOGIC_VECTOR(3 DOWNTO 0); --- 写地址
dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0); --- 写数据
--- 端口B:读端口
clkb : IN STD_LOGIC; --- Port B的时钟
enb : IN STD_LOGIC; --- Port B的使能信号
addrb : IN STD_LOGIC_VECTOR(3 DOWNTO 0); --- 读地址
doutb : OUT STD_LOGIC_VECTOR(31 DOWNTO 0) --- 读数据
);
END blk_mem_gen_0;
关键时序特性:读操作有一个固定的时钟周期延迟。当你在第N个时钟周期给出读地址后,数据将在第N+1个时钟周期出现在输出端口。如果启用了输出寄存器选项,延迟会变为两个周期,但这能显著改善时序性能。
2.2 属性配置
在Simple Dual Port RAM下对应的配置选项有两页,一个是Port A一个是Port B,Port A的Mode可以选择No change / Write First / Read First 而 Port B只能设定Write First模式,即到达Port B的数据就是直接可以输出的。

我们根据上述配置,看一下时序:

Port A依据ena 和 wea 给对应的地址addra写入数据,Port B依据enb从对应的地址addrb读出数据,port A与Port B的时钟是异步的,其实这非常类似于异步FIFO,这个是配置为No change模式的情况。
3 三种工作模式的深度剖析
当读写地址恰好相同时,Simple Dual Port RAM的行为由所选的工作模式决定。这三种模式是设计中最微妙也最重要的部分:
3.1 No Change模式
当发生地址冲突时,读端口输出保持不变,不反映写入的新数据,也不保证是旧数据。
// No Change 模式
always_ff @(posedge clk) begin
if (we) begin
ram[addr] <= din; // 仅执行写操作,输出dout保持不变
end else begin
dout <= ram[addr]; // 非写时,正常输出
end
en
适用场景:适用于设计上能保证避免地址冲突的系统,或对读取数据实时性要求不高的场景,这种模式通常功耗最低。
3.2 Write First模式
与Read First相反,Write First模式下新写入的数据会立即出现在输出端口。这意味着写操作"覆盖"了该地址的当前可见状态。
适用场景:适用于需要数据"透明"传递或旁路写入的场景,如实时数据流处理。
当我们配置Write First,即写优先模式,
Port B的输出还是要依赖enb和addrb给的时机,
所以我们可以通过调整enb和addrb的时机达到边写边读的效果。
程序只做参考说明,不是实际实现方式哈
// Write First 模式 (类似边写边读)
always_ff @(posedge clk) begin
if (we) begin
ram[addr] <= din; // 新数据写入RAM
dout <= din; // 同时,新数据直接送到输出端口
end else begin
dout <= ram[addr];
end
end
assign enb = ena;
assign addrb = addra;
3.3 Read First模式
在这种模式下,当对同一地址进行读写时,系统会先读出旧数据,然后再写入新数据。这保证了读操作总能获取到写入前该地址存储的内容。
当我们配置为Read First,即读优先,
那上一次我们讲过,读优先就是可以先读出老数据再写入新数据,防止老数据丢失,
那我们依旧可以通过调整enb和addrb的时机以读取老数据
// Read First 模式 (类似先读后写)
always_ff @(posedge clk) begin
if (we) begin
dout <= ram[addr]; // 时钟沿来时,先输出旧数据
ram[addr] <= din; // 同时将新数据写入RAM
end else begin
dout <= ram[addr]; // 非写时,正常输出
end
end
适用场景:适用于需要严格数据一致性的系统,例如在写入前需要备份旧值或执行读-修改-写操作。
4 总结
-
角色固定:Simple Dual Port RAM的A口写、B口读,结构清晰,非常适合单向数据流缓冲。
-
延迟特性:读操作有至少一个时钟周期的延迟。如果启用了输出寄存器,则延迟为两个周期。
-
模式是关键:
Write First、Read First、No Change三种模式解决了读写地址冲突时的行为问题,选择取决于具体应用逻辑。 -
独立与共享:两个端口的时钟、使能、地址线完全独立,但访问的是同一块物理内存空间。
希望今天的分享能帮助大家更好地理解和使用Simple Dual Port RAM。在实际项目中,结合设计需求选择合适的配置,可以极大地提高系统的效率和可靠性。
2828

被折叠的 条评论
为什么被折叠?



