相关文章:
Xilinx IP 解析之 Block Memory Generator v8.4 ——01-手册重点解读(仅Native RAM) – 徐晓康的博客
Xilinx IP 解析之 Block Memory Generator v8.4 ——02-如何配置 IP(仅 Native RAM) – 徐晓康的博客
Verilog功能模块–RAM和ROM(01)–功能说明与关键代码解析 – 徐晓康的博客
Verilog功能模块–RAM和ROM(02)–同步写-写冲突与读-写冲突实测 – 徐晓康的博客
Verilog 功能模块–RAM 和 ROM(03)–自编 RAM 与 Vivado RAM IP 功能对比实测 – 徐晓康的博客
前言
前面文章已经说明了自编 RAM 和 Vivado RAM 的冲突特性,本文将进行两者的功能对比。主要包括初始化功能、使能功能、输出寄存器功能、操作模式功能等。
主要进行 TDPRAM 的测试,对于 SDPRAM、SPRAM、DPROM、SROM 仅进行了少量实验。
部分实验在 300MHz 的条件下进行,所以说也验证了本模块的最大运行频率能达到 300MHz。
一、冲突抑制
因为写-写冲突和读-写冲突会可能导致写入和读取的错乱,所以,本章所有测试都在顶层测试模块,避免了冲突的发生,相关冲突抑制的代码如下:
reg ena_tmp;
always @(posedge clka) begin
ena_tmp <= random_num[14];
wea <= random_num[13];
addra <= random_num[ADDR_WIDTH-1+8 : 8];
dina <= random_num[DATA_WIDTH-1+2 : 2];
end
reg enb_tmp;
always @(posedge clkb) begin
enb_tmp <= random_num[7];
web <= random_num[5];
addrb <= random_num[ADDR_WIDTH-1 : 0];
dinb <= random_num[DATA_WIDTH-1 : 0];
end
// //* 避免写-写冲突 已被读写冲突覆盖
// always @(*) begin
// if (addra == addrb && wea && ena && enb)
// web = 1'b0;
// else
// web = web_tmp;
// end
//* 避免A读-B写冲突
always @(*) begin
if (addra == addrb && web && enb_tmp)
ena = 1'b0;
else
ena = ena_tmp;
end
//* 避免B读-A写冲突
always @(*) begin
if (addra == addrb && wea && ena_tmp)
enb = 1'b0;
else
enb = enb_tmp;
end
//* 两RAM读数据是否一致?
(* mark_debug *)reg douta_is_not_equal_vivado_douta;
(* mark_debug *)reg doutb_is_not_equal_vivado_doutb;
always @(posedge clka) begin
douta_is_not_equal_vivado_douta <= douta != vivado_douta;
end
always @(posedge clkb) begin
doutb_is_not_equal_vivado_doutb <= doutb != vivado_doutb;
end
其中,还包括了判断两 RAM 输出是否一致的代码。
二、TDPRAM 功能对比实验设计
2.1 实验设计
序号 | 实测实验条件 | 波形图 | 通过 ILA 观测,自编 BRAM 和 Vivado BRAM IP 写入/读取是否一致 |
---|---|---|---|
1 | 1.TDPRAM 2.同步时钟–100MHz 3.A 端口和 B 端口均 Write First 模式 4.无输出寄存器 5.带使能信号 ena 和 enb 6.使用相同的初始化文件 COE |
TDPRAM-ILA-1 | 完全一致 功能结论: 1.写优先功能正常 2.使能功能正常 3.初始化功能正常 |
2 | 1.TDPRAM 2.同步时钟–300MHz 其余不变 |
TDPRAM-ILA-2 | 完全一致 功能结论: 1.工作时钟频率可达 300MHz |
3 | 1.TDPRAM 2.同步时钟–300MHz 3.A 端口 Write First 模式,B 端口 Read First 模式 其余不变 |
TDPRAM-ILA-3 | 完全一致 功能结论: Write First 模式和 Read First 模式工作正常 |
4 | 1.TDPRAM 2.同步时钟–300MHz 3.A 端口 Write First 模式,B 端口 No Change 模式 其余不变 |
TDPRAM-ILA-4 | 完全一致 功能结论: Write First 模式和 No Change 模式工作正常 |
5 | 1.TDPRAM 2.异步时钟,clka(300MHz),clkb(120MHz) 3.A 端口和 B 端口均 Write First 模式 其余不变 |
TDPRAM-ILA-5 | 完全一致 功能结论: 异步时钟下工作正常 |
6 | 1.TDPRAM 2.异步时钟,clka(300MHz),clkb(120MHz) 3.A 端口和 B 端口均 Write First 模式 4.A 端口添加一个输出寄存器(Primitives Output Register) 5.B 端口均添加两个输出寄存器(Primitives Output Register + Core Output Register) 其余不变 |
TDPRAM-ILA-6 | 完全一致 功能结论: 输出寄存器功能工作正常 |
2.2 实验波形
TDPRAM-ILA-1
:
两 RAM 输出一致。
TDPRAM-ILA-2
:
TDPRAM-ILA-3
:
TDPRAM-ILA-4
:
TDPRAM-ILA-5
:
TDPRAM-ILA-6
:
2.3 实验结论
-
自编 TDPRAM 和 Vivado TDPRAM IP 在各个条件下的行为完全一致。 -
自编 TDPRAM 支持最大时钟可达 300MHz,更高频率没有经过测试 -
自编 TDPRAM 支持同步时钟与异步时钟 -
自编 TDPRAM 能支持 WF、RF、NC 三种操作模式 -
自编 TDPRAM 使能功能正常 -
自编 TDPRAM 初始化功能正常,能正常读取 COE 文件,也能够指定初始值 -
如果选择一级寄存器,Vivado TDPRAM IP必须需要选择Primitives Output Register,此寄存器对应一级寄存器
,不能只选择 Core Output Register 作为一级寄存器,实测发现,只选择 Core Output Register 作为一级寄存器的行为与自编 TDPRAM 选择一级寄存器行为有小概率不同
三、SDPRAM 功能对比实验设计
3.1 SDPRAM 的三种操作模式
当选择 SDPRAM 时,端口 A 固定为写端口,端口 B 固定为读端口。此时端口 A 的操作模式还是有三种可以选择:WF、RF 和 NC,但是,依据写优先的定义,是当某一端口同时进行读和写时,读数据等于写数据;其它操作模式也都是针对同一端口同时读写的,但 SDPRAM 读写是不同端口,所以,从操作模式的定义来说,无论哪种操作模式对 SDPRAM 应该是无意义的。我不理解的是,为什么Vivado的BRAM IP还保留了SDPRAM的A端口的三种操作模式选择,不同操作模式对SDPRAM究竟有什么不同?
下面进行实测分析。
为了同时比较三种模式的 Vivado SDPRAM IP 输出,将每种模式的 SDPRAM 都实例化,再用 ILA 进行观测,相关代码如下:
blk_mem_gen_0 blk_mem_gen_0_wf (
.clka (clka ), // input wire clka
.ena (ena ),
.wea (wea ), // input wire [0 : 0] wea
.addra (addra), // input wire [3 : 0] addra
.dina (dina ), // input wire [15 : 0] dina
.clkb (clkb ), // input wire clkb
.enb (enb ),
.addrb (addrb), // input wire [3 : 0] addrb
.doutb (vivado_doutb_wf)// output wire [15 : 0] doutb
);
blk_mem_gen_1 blk_mem_gen_1_rf (
.clka (clka ), // input wire clka
.ena (ena ),
.wea (wea ), // input wire [0 : 0] wea
.addra (addra), // input wire [3 : 0] addra
.dina (dina ), // input wire [15 : 0] dina
.clkb (clkb ), // input wire clkb
.enb (enb ),
.addrb (addrb), // input wire [3 : 0] addrb
.doutb (vivado_doutb_rf)// output wire [15 : 0] doutb
);
blk_mem_gen_2 blk_mem_gen_2_nc (
.clka (clka ), // input wire clka
.ena (ena ),
.wea (wea ), // input wire [0 : 0] wea
.addra (addra), // input wire [3 : 0] addra
.dina (dina ), // input wire [15 : 0] dina
.clkb (clkb ), // input wire clkb
.enb (enb ),
.addrb (addrb), // input wire [3 : 0] addrb
.doutb (vivado_doutb_nc)// output wire [15 : 0] doutb
);
再顶层模块修改一下输出一致与否的判断逻辑:
(* mark_debug *)reg doutb_is_not_equal_vivado_doutb;
always @(posedge clkb) begin
if (doutb != vivado_doutb_wf
|| doutb != vivado_doutb_rf
|| doutb != vivado_doutb_nc
)
doutb_is_not_equal_vivado_doutb <= 1'b1;
else
doutb_is_not_equal_vivado_doutb <= 1'b0;
end
3.2 实验设计
序号 | 实测实验条件 | 波形图 | 通过 ILA 观测,自编 BRAM 和 Vivado BRAM IP 写入/读取是否一致 |
---|---|---|---|
1 | 1.SDPRAM 2.同步时钟–300MHz 3.无输出寄存器 5.带使能信号 ena 和 enb 6.使用相同的初始化文件 COE |
SDPRAM-ILA-1 | 完全一致 功能结论: SDPRAM 同步时钟下 工作频率可到 300MHz 使能信号工作正常 初始化功能正常 三种操作模式的 Vivado BRAM IP 输出一致 |
2 | 1.SDPRAM 2.同步时钟–300MHz 3.输出一级寄存器 其余不变 |
SDPRAM-ILA-2 | 完全一致 功能结论: SDPRAM 同步时钟下, 输出一级寄存器工作正常 |
3 | 1.SDPRAM 2.同步时钟–300MHz 3.输出二级寄存器 其余不变 |
SDPRAM-ILA-3 | 完全一致 功能结论: SDPRAM 同步时钟下 输出二级寄存器工作正常 |
4 | 1.SDPRAM 2.异步时钟,clka(300MHz),clkb(120MHz) 3.输出二级寄存器 其余不变 |
SDPRAM-ILA-4 | 完全一致 功能结论: SDPRAM 异步时钟下 输出二级寄存器工作正常 |
3.3 实验波形
SDPRAM-ILA-1
:
显然,三种模式输出没有区别。
同步时钟不变,寄存器设为一级,进行实验,SDPRAM-ILA-2
:
同步时钟不变,寄存器设为二级,进行实验,SDPRAM-ILA-3
:
异步时钟,寄存器仍为二级,进行实验,SDPRAM-ILA-4
:
3.4 实验结论
从各种条件的 ILA 波形看出,三种模式输出没有区别。到这里我们得出结论:Vivado SDPRAM IP的三种操作模式没有意义,每种都一样
,所以,自编的 SDPRAM 不设置操作模式选择。
初始化、使能、寄存器等功能均能正常工作。
自编 SDPRAM 的行为与 Vivado SDPRAM IP 完全一致。
这里就有个疑问,如果说 Vivado SDPRAM IP 的三种操作模式之间没有任何区别的话,为什么 Vivado 中会保留模式选择呢,且 PG058 手册中还有 SDPRAM 的不同模式的说明和推荐,这是怎么回事?有懂的同学可以评论区解答一下。
四、SPRAM 功能对比实验设计
4.1 实验设计
序号 | 实测实验条件 | 波形图 | 通过 ILA 观测,自编 BRAM 和 Vivado BRAM IP 写入/读取是否一致 |
---|---|---|---|
1 | 1.SPRAM 2.时钟–300MHz 3.A 端口 Write First 模式 4.无输出寄存器 5.带使能信号 ena 和 enb 6.使用相同的初始化文件 COE |
SPRAM-ILA-1 | 完全一致 功能结论: SPRAM 在 300MHz 时钟下工作正常 WF 模式工作正常 使能信号工作正常 初始化功能正常 |
2 | 1.SPRAM 2.时钟–300MHz 3.A 端口 Read First 模式 4.一级输出寄存器 其余不变 |
SPRAM-ILA-2 | 完全一致 功能结论: RF 模式工作正常 SPRAM 一级寄存器功能正常 |
3 | 1.SPRAM 2.时钟–300MHz 3.A 端口 No Change 模式 4.二级输出寄存器 其余不变 |
SPRAM-ILA-3 | 完全一致 功能结论: NC 模式工作正常 SPRAM 二级寄存器功能正常 |
4.2 实验波形
SPRAM-ILA-1
其余波形略。
4.3 实验结论
自编 SPRAM 和 Vivado SPRAM IP 行为完全一致。
五、DPROM 功能对比实验设计
5.1 实验设计
序号 | 实测实验条件 | 波形图 | 通过 ILA 观测,自编 BRAM 和 Vivado BRAM IP 写入/读取是否一致 |
---|---|---|---|
1 | 1.DPROM 2.同步时钟–300MHz 3.无输出寄存器 4.带使能信号 ena 和 enb 5.使用相同的初始化文件 COE |
DPROM-ILA-1 | 完全一致 功能结论: DPROM 同步时钟下工作正常 使能信号工作正常 初始化功能正常 |
2 | 1.DPROM 2.同步时钟–300MHz 3.A 端口一级输出寄存器,B 端口二级输出寄存器 其余不变 |
DPROM-ILA-2 | 完全一致 功能结论: DPROM 同步时钟下工作正常 输出寄存器功能正常 |
3 | 1.DPROM 2.异步时钟,clka(300MHz),clkb(120MHz) 3.A 端口二级输出寄存器,A 端口一级输出寄存器 其余不变 |
DPROM-ILA-3 | 完全一致 功能结论: DPROM 异步时钟下工作正常 |
5.2 实验波形
DPROM-ILA-1
:
DPROM-ILA-2
:
DPROM-ILA-3
:
5.3 实验结论
DPROM 功能正常,与 Vivado DPROM IP 行为完全一致。
六、SPROM 功能对比实验设计
6.1 实验设计
序号 | 实测实验条件 | 波形图 | 通过 ILA 观测,自编 BRAM 和 Vivado BRAM IP 写入/读取是否一致 |
---|---|---|---|
1 | 1.SPROM 2.时钟–300MHz 3.无输出寄存器 4.带使能信号 ena 5.使用相同的初始化文件 COE |
SPROM-ILA-1 | 完全一致 功能结论: SROM 工作正常 使能信号正常工作 初始化功能正常 |
2 | 1.SPROM 2.时钟–300MHz 3.一级输出寄存器 其它不变 |
SPROM-ILA-2 | 完全一致 功能结论: SROM 工作正常 寄存器功能正常 |
3 | 1.SPROM 2.时钟–300MHz 3.二级输出寄存器 其它不变 |
SPROM-ILA-3 | 完全一致 功能结论: SROM 工作正常 寄存器功能正常 |
6.2 实验波形
SPROM-ILA-1
:
SPROM-ILA-2
:
SPROM-ILA-3
:
6.3 实验结论
SPROM 功能正常,与 Vivado SPROM IP 行为完全一致。
七、总结与分享
本文对自编 RAM/ROM 与 Vivado BRAM/BROM IP 进行了全面的对比,最终结论是:自编 RAM/ROM 模块的行为和 Vivado 相关 IP 是一样的。
本模块开源,两处仓库同步。
Gitee: Verilog 功能模块–RAM 和 ROM https://gitee.com/xuxiaokang/verilog-function-module–RAM_ROM
仿真和实测的 Vivado 2024.2 工程通过网盘分享(本系列文章所有分享均相同,均需获取一次即可):
欢迎大家关注我的微信公众号:徐晓康的博客,回复以下 6 位数字获取网盘链接。
402368
建议复制过去不会码错字!
如果本文对你有所帮助,欢迎点赞、转发、收藏、评论让更多人看到,赞赏支持就更好了。
如果对文章内容有疑问,请务必清楚描述问题,留言评论或私信告知我,我看到会回复。

徐晓康的博客持续分享高质量硬件、FPGA与嵌入式知识,软件,工具等内容,欢迎大家关注。