惠州网站小程序建设点公众号制作视频教学视频
1、范围
前面让团队小伙伴仿照米联客教程测试了一下,后面似乎读写有时候有误码,后期小伙伴离职,这个事情就不了了之。最近工作又需要对PL端DDR3进行读写,于是亲自对这一部分进行详细测试论证。该文档用来描述如何读写PL端DDR3、形成统一的接口模块,最后在实际板卡中对DDR3进行功能及性能验证测试。
2、基本概念
2.1、DDR3
目前主流的DDR有DDR3、DDR4和DDR5,DDR属于SDRAM一类的数据存储器,它是一种同步动态存储器,断点数据会丢失。DDR是Double Date Rate的英文缩写,后面数值表示第几代,例如DDR3表示第三代DDR,数值越高表示性能越好。市面上常用的DDR3来自美光的MT41K系列,在贸泽上搜索价格在二十多元。找到美光手册,如下:

可以看到有三个型号,分别为MT41K1G4、MT41K512M8、MT41K256M16,三种型号的容量均为4Gb。4、8和16表示数据线位宽,1G、512M和256M由bank地址、行地址和列地址位宽共同决定,具体如下所示:

同样的数据容量不同的后缀代表不同的速率。

2.2、硬件设计
DDR3供电电压一般为1.5V,如果是在PS端接入DDR3,则固定接在BANK502端,需要将管脚一一对应。例如PYNQ中接入的DDR3连接如下所示:

如果想用两块DDR3扩展出1GB容量,将BANK502高16位的数据线接在另外一块DDR中,DM和DQS接在2、3接口,其他连线两块DDR共接。 当PL端接入DDR3时,需要注意DDR管脚连接关系,应尽量用MIG IP推荐的连接管脚。
3、FPGA设计
本设计实现的功能为基于MIG 完成对DDR3读写操作,最后对读写数据进行校验。DDR3读写有两种工作方式:FIFO模式和RAM模式。在FIFO模式,DDR3可以理解为超大的FIFO,当没有写数据时,禁止读数据。例如当写入10个字节数据,在读取10个数据以后,再读数据时,输出数据内容为0,并将空标志拉高。在RAM模式时,可以允许反复读数据。例如当写入10个数据时,当读取10个数据以后,再读取第11个数据时,将重复读取第1个数据。
3.1、管脚约束
DDR的管脚约束为DDR3.ucf文件,具体将原理图与文件内容进行一一对应就行。
3.2、IP配置
在工程中增加MIG IP,具体步骤如下所示:
a) 选择IP


时钟选择为800MHz,根据板卡硬件选择DDR型号,由于有两片拼接,所以位宽选择为32。

选择系统时钟和参考时钟为no buffer,选中DCI cache


点击Read XDC/UCF,选择前面修改的约束文件,点击Validate,就可以选择Next。


b) 例化IP
mig_7series_0模块对外接口,时钟关系如下图所示,本部分参考其他博客:

如上图,包含了四个时钟:
1)系统时钟,即MIG核工作时钟,通常命名sys_clk;
2)参考时钟,即MIG核参考时钟,通常命名ref_clk,必须是200MHz;
3)DDR芯片工作时钟,由FPGA输出给DDR的差分时钟,可以命名ddr_clk;
4)用户时钟,MIG核输出给用户端的时钟,通常命名ui_clk。
注意1:ddr_clk与ui_clk有比例关系,ddr_clk:ui_clk = 4:1或2:1,当ddr_clk=800MHz时,只能是4:1。
注意2:用户数据位宽如何计算,例如ddr_clk=800MHz时,ui_clk = 200MHz,ddr物理位宽为16bit(2片ddr菊花链连接就是32bit),上下沿采集(2倍),因此用户数据位宽=800*32*2/200=256bit。
注意3:256bit/32bit=8,所以ddr用户地址每次加8。
注意4:app地址位宽:
ADDR_WIDTH = RANK_WIDTH + BANK_WIDTH + ROW_WIDTH + COL_WIDTH
通过UG586可知RANK_WIDTH默认为1,查看DDR手册可以知道BANK_WIDTH为3,ROW_WIDTH为15,COL_WIDTH为10,所以app_addr位宽为29。
|   序号  |   信号名称  |   位宽  |   方向  |   说明  | 
|   1  |   ddr3_dq  |   32  |   IO  |   与DDR连接  | 
|   2  |   ddr3_dqs_n  |   4  |   IO  | |
|   3  |   ddr3_dqs_p  |   4  |   IO  | |
|   4  |   ddr3_addr  |   15  |   O  | |
|   5  |   ddr3_ba  |   3  |   O  | |
|   6  |   ddr3_ras_n  |   1  |   O  | |
|   7  |   ddr3_cas_n  |   1  |   O  | |
|   8  |   ddr3_we_n  |   1  |   O  | |
|   9  |   ddr3_reset_n  |   1  |   O  | |
|   10  |   ddr3_ck_p  |   1  |   O  | |
|   11  |   ddr3_ck_n  |   1  |   O  | |
|   12  |   ddr3_cke  |   1  |   O  | |
|   13  |   ddr3_cs_n  |   1  |   O  | |
|   14  |   ddr3_dm  |   4  |   O  | |
|   15  |   ddr3_odt  |   1  |   O  | |
|   16  |   sys_clk_i  |   1  |   I  |   系统时钟,频率为200MHz  | 
|   17  |   clk_ref_i  |   1  |   I  |   参考时钟,频率为200MHz  | 
|   18  |   app_addr  |   29  |   I  |   地址输入  | 
|   19  |   app_cmd  |   3  |   I  |   读写控制命令0:写 1:读  | 
|   20  |   app_en  |   1  |   I  |   命令写入使能,高有效  | 
|   21  |   app_wdf_data  |   256  |   I  |   写数据  | 
|   22  |   app_wdf_end  |   1  |   I  |   突发写最后一个时钟  | 
|   23  |   app_wdf_mask  |   32  |   I  |   写数据掩码  | 
|   24  |   app_wdf_rdy  |   1  |   O  |   写DDR准备完成,高有效  | 
|   25  |   app_rd_data  |   256  |   O  |   读数据  | 
|   26  |   app_rd_data_end  |   1  |   O  |   突发读最后一个时钟  | 
|   27  |   app_rd_data_valid  |   1  |   O  |   读数据有效  | 
|   28  |   app_rdy  |   1  |   O  |   读写接收准备完成,高有效  | 
|   29  |   app_sr_req  |   1  |   I  |   保留位  | 
|   30  |   app_ref_req  |   1  |   I  |   刷新请求  | 
|   31  |   app_zq_req  |   1  |   I  |   ZQ校准请求  | 
|   32  |   app_sr_active  |   1  |   O  |   保留位  | 
|   33  |   app_ref_ack  |   1  |   O  |   刷新响应  | 
|   34  |   app_zq_ack  |   1  |   O  |   ZQ校准响应  | 
|   35  |   ui_clk  |   1  |   O  |   用户时钟  | 
|   36  |   ui_clk_sync_rst  |   1  |   O  |   复位,高电平  | 
|   37  |   init_calib_complete  |   1  |   O  |   IP初始化完成标志,高电平有效  | 
|   38  |   device_temp  |   12  |   O  | |
|   39  |   sys_rst  |   1  |   I  |   低电平复位  | 
3.3、时序与流程
a) 命令操作时序
当用户逻辑app_en信号被断言且app_rdy信号从MIG被断言时,MIG接受命令。每当app_rdy被取消断言时,MIG将忽略该命令。用户逻辑需要将app_en与有效命令和地址值沿着保持为高电平,直到app_rdy被断言,如下图所示:

只有当app_rdy 与 app_en同时为高时,命令和地址才会被写入到MIG,如图红色的位置,这类似于AXI里的握手信号。
b) 写数据
首先需要检查app_wdf_rdy,该信号为高表明此时IP核数据接收处于准备状态,可以接收用户发过来的数据,在当前时钟拉高写使能(app_wdf_wren),同时给出写数据这样加上发起的写命令操作就可以成功向IP核写数据,具体时序如下图所示:

如上图所示,写数据有三种情形均可以正确写入:
- 写数据时序和写命令时序发生在同一拍
 - 写数据时序比写命令时序提前一拍
 - 写数据时序比写命令时序至多延迟两拍
 
c)读数据
用户发出读命令后,用户只需等待数据有效信号(app_rd_data_valid)拉高,为高表明此时数据总线上的数据是有效的返回数据,有效读数据要晚若干周期才出现在数据总线上。如下图所示:

至此已经完成vivado中DDR的配置和相关基础知识的了解。后续需要自己根据app信号的时序关系,编写对应的控制信号。网络上有很多,但是似乎直接能用的并不多。下一文档详细编写如何编写app控制时序。同时ug586似乎在xilinx官网无法下载,这里将ucf文件和ug586上传到CSDN,可以免费下载:https://download.csdn.net/download/weixin_39813867/91008302
