一、DDR3用户端见
如图是中间部分是我们MIG核,它分为,左边的用户接口与右边的DDR3接口,vivado给我们提供了便利的MIG核,我们只需要通过配置用户端的接口,就可以直接控制DDR3了。
MIG核的配置,网上一大堆,在这里,我就挑几个需要重点理解选项。
在应用一个模块之前,我们首先要了解这个模块的时钟树。
从上图中,我们可以得到 CLOCK PERIOD(clk1)、INPUT CLOCK PERIOD(clk2) 、SYStem clock、PHY to control(clk4)以及Reference clock(clk3)。咋一看,是不是头都大了,别急,听我慢慢道来。为了方便起见,我i给时钟标了个名字。
这样看能理解了吗?clk2是系统输入时钟,可以选差分,单端,还是no buffer(PLL输出时钟)。
clk1是mig内部PLL核倍频出来给DDR的时钟(如何看DDR时钟,因为DDR3是差分读写,所以时钟就等于DDR3传输速率的一半),clk3是MIg内部自刷新的时钟,逻辑部分我们不用管。clk4是DDR为了能够同步数据输入端的时序,而自己产生出来给用户用的,也就是说,你用户端想操作我,必须用这个时钟,不然就是白搭!!
还有一个特别需要注意的就是位宽,因为我们DDR的数据最终还是要通过cpu走通,cpu一个周期传输64bit,如果不够,就要想办法去凑了,可以用过RANK的方式。这里正好是64bit。附带一下,此DDR3默认的8个长度的突发,后面代码部分很重要!!
还有其他一些配置,可以参考其他博主,太多了。就不介绍了。这里就介绍我在自学的时候遇到的苦难。
下面附上用户接口端的说明,我们就直接讲代码了!!(为了节约时间,直接从vivado示例中copy过来了)
.app_addr (app_addr), // input [28:0] =bank + row + col(对应的芯片手册上都有)
.app_cmd (app_cmd), // input [2:0] 000写,001读
.app_en (app_en), // input app_cmd使能信号
.app_wdf_data (app_wdf_data), // input [511:0] 数据写入,这里的位宽要注意,DDR3位宽 * 突发长度,上面就强调了。
.app_wdf_end (app_wdf_end), // input 最后一个数据读出,8突发的话,让他等于app_wdf_wren就好了。
.app_wdf_wren (app_wdf_wren), // input 写数据有没有用就看它了
.app_rd_data (app_rd_data), // output [511:0]
.app_rd_data_end (app_rd_data_end), // output
.app_rd_data_valid (app_rd_data_valid), // output 数据能不能读出来就看它了
.app_rdy (app_rdy), // output DDR准备好接收地址啦啦!
.app_wdf_rdy (app_wdf_rdy), // output DDR准备好接受数据啦
.app_sr_req (1'b0), // input 我没写的,不需要就可以不用,写了的就一定要用
.app_ref_req (1'b0), // input app_ref_req
.app_zq_req (1'b0), // input app_zq_req
.app_sr_active (), // output app_sr_active
.app_ref_ack (), // output app_ref_ack
.app_zq_ack (), // output app_zq_ack
.ui_clk (ui_clk), // output //给用户逻辑的时钟
.ui_clk_sync_rst (ui_clk_sync_rst), // output