简介
DDR3 SDRAM常 简称 DDR3 是当今较为常见的一种储存器,在计算机及嵌入式产品中得到广泛应用,特别是应用在涉及到大量数据交互的场合,比如电脑的内存条。对DDR3的读写操作大都借助IP核来完成,本次实验将采用 Xilinx公司 MIG IP核来实现DDR3读写测试。 DDR3相对于SDRAM是双沿触发,读写速度快一倍。相对于DDR2有更高的运行性能和更低的电压。本次实验使用的 DDR3芯片是MT41J256M16HA-125 ,bank位宽为 3,行位宽为 15,列位宽为10,所以它的地址大小等于即 2^28=256M,数据位宽为 16bit,所以容量大小为 256M*16bit,也就是 512MByte。
具体介绍可以看datasheet
![在这里插入图片描述](https://img-blog.csdnimg.cn/a85eed8f08fc4898aafcc0bc9194b287.png#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/a803863d823e43cc867431b245874641.png#pic_center)
DDR 存储
可以把ddr理解为一个方格本,bank就是代表这个本子有多少页,行列地址,可以理解为一页中一行有多少个格子col,一页有多少行row。ddr写数据和地址就是将数据填到相应的格子里。
![在这里插入图片描述](https://img-blog.csdnimg.cn/32a0a8deb9064b6da31326651a7a51a9.png#pic_center)
硬件部分
根据不同的功能引脚有,可将DDR3引脚划分为4类:地址总线引脚、数据总线引脚、控制引脚、电源与参考电压引脚。在原理图上根据分类连接好引脚,可以参考黑金A7的核心板。
![在这里插入图片描述](https://img-blog.csdnimg.cn/47d8a766b46c4dfc9a3a0fbcef9ffeac.png#pic_center)
布局布线的话,会有硬件工程师和PCB layout工程师进行设计,电源完整性,布局布线,差分,等长,阻抗匹配,EMI问题等。
软件部分
MIG IP核是硬核,左侧是用户接口,右侧是芯片接口。如下图
如果只是单纯想要简洁快速实现DDR读写功能的话,需要着重了解的是用到的用户接口的相关信号,例化配置好 Xilinx公司 MIG IP核 ,然控制各信号进行读写即可。
![在这里插入图片描述](https://img-blog.csdnimg.cn/7fbfb85686c3421da93ab71b7cc34722.png#pic_center)
用户接口信号在后面会详细介绍,下面我们先配置MIG IP。
MIG IP设置
新建MIG IP如下所示,在这里我们不使用AXI接口,下一步;
![在这里插入图片描述](https://img-blog.csdnimg.cn/ea42014a7a5a45088ad712898217b9ed.png#pic_center)
选择兼容其他相同封装不同型号的FPGA,我们这里不选择。
![在这里插入图片描述](https://img-blog.csdnimg.cn/0a1fcb1e02de496d8d82d828bf2e9347.png#pic_center)
选择DDR3;
![在这里插入图片描述](https://img-blog.csdnimg.cn/de37dc9366b6481f80bd90197dd1fac7.png#pic_center)
时钟配置Clock Period,即DDR芯片物理侧的IO时钟频率,称之为核心频率;(选择FPGA性能好的片子,DDR频率也可以到更高,手头上的xc7a100tfgg484-2 DDR3能到400M)
物理侧到控制器时钟的比例,可选4:1或2:1;决定了ui_clk的频率;如图配置的话,ui_clk = 400M /4 =100Mhz
选择DDR3的类型,Components指的是DDR3的型号是元件类,服务器用的是RDIMMs和UDIMMs,笔记本那种的插条类是SODIMMs。
数据位宽,由DDR型号决定,但是当FPGA挂了多片DDR时,位宽相应增加,我们这里用了两片,所以位宽为32;
![在这里插入图片描述](https://img-blog.csdnimg.cn/399bc345c94c413f99340ce9daa300eb.png#pic_center)
系统时钟输入,建议200M,后面参考时钟可以直接使用系统时钟。
![在这里插入图片描述](https://img-blog.csdnimg.cn/92ca86b680a9430eb4a6492faa5cae0c.png#pic_center)
系统时钟是使用200M的差分时钟,低电平复位
![在这里插入图片描述](https://img-blog.csdnimg.cn/3d9333cbd90246fea91d9d1e4483a160.png#pic_center)
50欧电阻,根据硬件而定,不用管,直接NEXT;
![在这里插入图片描述](https://img-blog.csdnimg.cn/eda5ff9a6c564b339a558131b7824f0b.png#pic_center)
新设计 or 管脚已固定
![在这里插入图片描述](https://img-blog.csdnimg.cn/8cd92bab4fc449a897018efc9054a741.png#pic_center)
如果硬件已经定了,那么就选下面管脚已固定,然后读取约束文件,设置管脚就好。
引脚约束
DDR3用到的约束引脚较多,建议导入。 用到3种电平: LVCMOS、 SSTL和 DIFF_SSTL。 LVCMOS:全称 Low Voltage Complementary Metal Oxide Semiconductor,低压互补金属氧化物半导体。 SSTL:全称 Stub Series Terminated Logic 短截线串联端接逻辑。 DIFF_SSTL:全称Difference Stub Series Terminated Logic,差分短截线串联端接逻辑。 LVCMOS 的特点是噪声容限大,速度较SSTL 慢;SSTL 速度快,通常要匹配合适的端接电阻,常用于高速内存接口如DDR3;DIFF_SSTL 则是带有差分功能的SSTL。
![在这里插入图片描述](https://img-blog.csdnimg.cn/e156767a6c6c40c09fe40d1f3e3240a4.png#pic_center)
后面依次NEXT就好了,最后生成。
![在这里插入图片描述](https://img-blog.csdnimg.cn/2f0fbc8d680b4c1cac2a3b059d042ca1.png#pic_center)
下面是设置完成后的总结页面;
![在这里插入图片描述](https://img-blog.csdnimg.cn/b1e6f7866c26418c9482864fb9f3caea.png#pic_center)
IP核生成完毕,打开veo文件查看例化文件,就可以添加到自己的工程里使用了。
ddr3_top ddr3_top_inst(
// Inputs
// Differential system clocks and rst
.sys_clk_p (sys_clk_p ), // input sys_clk_p
.sys_clk_n (sys_clk_n ), // input sys_clk_n
.sys_rst (1'b1 ), // input sys_rst
// Inouts
.ddr3_dq (ddr3_dq ), // inout [31:0] ddr3_dq
.ddr3_dqs_n (ddr3_dqs_n ), // inout [3:0] ddr3_dqs_n
.ddr3_dqs_p (ddr3_dqs_p ), // inout [3:0] ddr3_dqs_p
// Outputs
.ddr3_addr (ddr3_addr ), // output [14:0] ddr3_addr
.ddr3_ba (ddr3_ba ), // output [2:0] ddr3_ba
.ddr3_ras_n (ddr3_ras_n ), // output [0:0] ddr3_ras_n
.ddr3_cas_n (ddr3_cas_n ), // output ddr3_cas_n
.ddr3_we_n (ddr3_we_n ), // output ddr3_we_n
.ddr3_reset_n (ddr3_reset_n ), // output ddr3_reset_n
.ddr3_ck_p (ddr3_ck_p ), // output [0:0] ddr3_ck_p
.ddr3_ck_n (ddr3_ck_n ), // output [0:0] ddr3_ck_n
.ddr3_cke (ddr3_cke ), // output [0:0] ddr3_cke
.ddr3_cs_n (ddr3_cs_n ), // output [0:0] ddr3_cs_n
.ddr3_dm (ddr3_dm ), // output [3:0] ddr3_dm
.ddr3_odt (ddr3_odt ), // output [0:0] ddr3_odt
// user interface signals
.app_addr (app_addr ), // input [27:0] app_addr
.app_cmd (app_cmd ), // input [2:0] app_cmd
.app_en (app_en ), // input app_en
.app_wdf_data (app_wdf_data ), // input [255:0] app_wdf_data
.app_wdf_end (app_wdf_end ), // input app_wdf_end
.app_wdf_mask (32'd0 ), // input [31:0] app_wdf_mask
.app_wdf_wren (app_wdf_wren ), // input app_wdf_wren
.app_rd_data (app_rd_data ), // output [255:0] app_rd_data
.app_rd_data_end (app_rd_data_end ), // output app_rd_data_end
.app_rd_data_valid (app_rd_data_valid ), // output app_rd_data_vali
.app_rdy (app_rdy ), // output app_rdy
.app_wdf_rdy (app_wdf_rdy ), // output app_wdf_rdy
.app_sr_req (1'b0 ), // input app_sr_req
.app_ref_req (app_ref_req ), // input app_ref_req
.app_zq_req (1'b0 ), // input app_zq_req
.app_sr_active (app_sr_active ), // output app_sr_active
.app_ref_ack (app_ref_ack ), // output app_ref_ack
.app_zq_ack (app_zq_ack ), // output app_zq_ack
.ui_clk (ui_clk ), // output ui_clk
.ui_clk_sync_rst (ddr_rst ), // output ui_clk_sync_rst
.init_calib_complete (init_calib_complete ),
.device_temp (device_temp )
);
对于mig与DDR3的读写原理我们不需要了解太多,交给mig就可以了。我们需要做的是控制好用户接口,写出正确的用户逻辑,控制好读写时序。想要写好User logic,我们就必须清楚各个用户控制接口的含义:
![在这里插入图片描述](https://img-blog.csdnimg.cn/f8cf4c59b1034521a8689a7fe084c872.png#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/a64ce05524574165b063cb48e21055dc.png#pic_center)
读写时序
读写时序如下所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/ae3303029b0c417c945ef924f09c536b.png#pic_center)
基本时序如上。app_rdy表示UI已经准备好接收命令了,意思就是说必须要等app_rdy信号拉高了之后,app_en有效,app_cmd命令才能被接收。而且app_rdy信号,不受控制,不管是读还是写,都必须在app_rdy为高的时候进行操作。
写DDR的前提条件是(app_rdy & app_wdf_rdy)全部为高时,给出地址和命令(app_cmd = 3’b000),然后给出写数据的信号(使能与数据),就可以成功写入数据到DDR了。
![在这里插入图片描述](https://img-blog.csdnimg.cn/868c26f365d84994bd569652551ec207.png#pic_center)
地址和命令必须时序严格对齐!写数据信号相对来说有三种情况:①完全同步;②可以提前1拍;③最多延迟2拍;但是最好全部时序对齐,不容易出错。
读操作就简单了,在前提条件app_rdy为高时,给出命令(app_cmd = 3’b001)与地址(app_addr),读出的数据往往要晚若干个周期,以valid信号表示数据有效。
![在这里插入图片描述](https://img-blog.csdnimg.cn/208fbf10d80445d495101999646a1212.png#pic_center)
连读连写的时序如下图所示
![在这里插入图片描述](https://img-blog.csdnimg.cn/3832b48fcf45400d98b189c3469f289c.png#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/23312613abe543e398d1a16b84058f3a.png#pic_center)
总结:
结合上图分析
(1)写数据时需要先满足app_rdy,app_wdf_rdy,app_en有效,然后发送写命令和地址app_cmd,app_addr,最后写数据app_wdf_wren,app_wdf_data,app_wdf_end
(2)读数据时满足app_rdy,app_en有效,然后发送读命令和读地址app_cmd,app_addr,等待有效信号和数据app_rd_data,app_rd_data_valid