Vivado DDR4和BRAM交互调试经验分享
Vivado DDR4和BRAM交互调试经验分享
一、实验目的
在上一实验《Vivado DDR4读写调试经验分享 - George2024 - 博客园 (cnblogs.com)》利用UI端接口完成DDR4读写调试的基础上,加入BRAM,实现DDR4和BRAM的交互。
二、实验设计
实验通过六个顺序切换的状态完成对DDR4与BRAM交互的初步测试。状态详情及其示意图如下:
| State Index | Description |
|---|---|
| ① | 数据由外界写入DDR4,完成DDR4中数据的初始化 |
| ② | 刚刚写入DDR4的数据从DDR4中读出,并写入到指定的BRAM中 |
| ③ | 刚刚写入BRAM的数据从BRAM中读出,检验正确性 |
| ④ | 向BRAM中写入新的一组数据 |
| ⑤ | 刚刚写入BRAM的数据从BRAM中读出,并写入到DDR4中 |
| ⑥ | 从DDR4中读出刚刚写入的数据,检验正确性 |

接口方面,假设存储的矩阵列宽FM_COL = 4,行高FM_ROW = 5,DDR4接口数据位宽APP_DATA_WIDTH = 64, 则设计BRAM接口数据位宽BRAM_DATA_WIDTH = APP_WIDTH * FM_COL,以适应后续可能接入BRAM的功能模块运算速度。
三、BRAM时序说明
DDR4读写时序已在上一实验说明,此处介绍本实验采用的BRAM接口时序。简单起见,本实验采用单口BRAM,不带Output Register,所以本实验BRAM的读延迟为1周期。另外,本实验BRAM接入了使能信号(en),未使能时,BRAM无法写入,BRAM输出端为不定态x。主要代码如下:
(* RAM_STYLE="BLOCK" *) reg [BRAM_DATA_WIDTH - 1 : 0] ram [BRAM_DEPTH - 1 : 0];
always @(posedge clk) begin
if (en) begin
if (we)
ram[addr] <= din;
dout <= ram[addr];
end
end
四、状态具体说明
状态①和⑥在上一实验《Vivado DDR4读写调试经验分享 - George2024 - 博客园 (cnblogs.com)》已经充分验证,开发重点在于剩余四个状态,尤以DDR4和BRAM位宽不匹配的状态②和⑤为重。
对于状态②,采用串并转换模块匹配位宽,具体代码详见fm_add_s2p_x.sv项目文件。串并转换模块输入带en信号,输出带valid信号。输入及其en信号直接接DDR UI端app_rd_data & app_rd_data_valid信号,输出及其valid信号直接接BRAM端bram_din及bram_we信号(DDR与BRAM交互模块内部看起来是这样,到top模块,还有总的控制器调度DDR和BRAM数据流动方向)。
对于状态⑤,采用并串转换模块匹配位宽,具体代码详见fm_add_p2s_x.sv项目文件。并串转换模块输入(par)带en信号,输出(seq)带valid信号。输入和输出信号直接分别接BRAM输出(bram_dout)和DDR UI端(app_wdf_data),输出有效seq_valid与app_wdf_rdy配合接DDR UI端app_wdf_wren。输入使能par_en信号单独精细控制。
五、实验中的一些体悟
-
上一实验中提到的cmd_en信号的进一步理解
上一实验中提到,cmd_en & app_rdy可以很有效地控制DDR UI端命令通道,但对于cmd_en的具体作用尚无说法。本实验中发现,cmd_en信号虽然大体是app_rdy打一拍的产物,但是却可以通过精细操纵cmd_en,实现对于命令通道的更好控制。实验前期,由于并串转换模块输出端数据的不连续性,输入DDR的写数据往往大幅落后于较为连续的写命令,进而无法成功写入。后期,通过采用DDR UI端写使能app_wdf_wren信号直接控制cmd_en信号,有效地将写命令卡在写数据之后,从而契合DDR特性,成功写入。核心代码如下,具体详见fm_add_ddr_to_bram.sv项目文件:
if (state == WR & (wr_cmd_cnt < WR_MAX - 1)) begin
cmd_en <= app_rdy & app_wdf_wren; //cope with the discontinuity of write data
end
-
模块化对于设计便捷性的提升
此处的“模块化”指:通过模块启动信号module_en和模块完成信号module_done实现各模块的真正分离,减少开发过程中需要考虑的因素,只需用一个顶层模块通盘控制各模块的启动、完成和需配置的输入参数即可,有些类似软件开发中的“函数”。采用模块化方法后,开发效率确实大幅提高。
-
一些Bugs
Bug1: 仿真出现某些信号的不定态X,要考虑重复驱动问题。
Bug2: 在上层模块中实例化各下层模块时,要牢记声明接口信号,否则接口信号全部默认1bit位宽的wire类型,位宽对不上,很可能产生addr / data等信号的高阻态Z。
本实验所有代码已托管在Github上,见GeorgeLin200100/ddr_bram_interface (github.com)
如有任何错漏,欢迎指正。
六、参考
Xilinx官方文档:Block Memory Generator v8.4 Product Guide (PG058)

浙公网安备 33010602011771号