Xilinx 2020.1 MIG核读写DDR3内存,新建工程时配置MIG核的完整步骤

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ZLK1214/article/details/111349678

本文以XC7A35TFGG484-2这款芯片为例,采用米联客FPGA开发板,用MIG核驱动DDR3内存。FPGA外接的晶振大小为50MHz,DDR3内存的驱动频率(ddr3_ck_p和ddr3_ck_n)为400MHz。选用的DDR3内存型号为MT41K128M16,内存容量为256MB。

首先用Clocking Wizard配置时钟,由50MHz倍频到200MHz,作为MIG的系统时钟(sys_clk_i)和参考时钟(clk_ref_i)。


用MMCM倍频,输入的时钟为50MHz:

输出的时钟为200MHz:

点击OK,产生IP核,方式选择默认的Out of context per IP即可:

然后选择添加MIG核:


这些保持默认。代码中我们用的是默认的接口,不使用AXI4接口,不需要勾选AXI4 Interface:

这个也不用管:

选择驱动的是DDR3内存:

Clock Period设为2500ps,这样DDR3内存的驱动频率就是400MHz。后面还要选择DDR3内存的型号和位宽。
MIG核最关键的配置就是时钟的配置。这里的4:1表示DDR3内存的驱动频率,和用户程序代码运行的时钟频率之比为4:1,DDR3运行于400MHz,那么用户程序就运行于100MHz。

MIG内部PLL倍频器的输入时钟为200MHz:

(为了方便期间,MIG PLL输入时钟、系统时钟和参考时钟全部采用Clocking Wizard产生的200MHz时钟)

系统时钟和参考时钟要选择No Buffer。

这个保持默认:

从外部ucf文件读DDR3内存的引脚配置:

导入UCF文件,然后Validate,OK:

MA703-35T_MIG.ucf文件的内容如下:
NET "ddr3_dq[0]" LOC = "P6" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[1]" LOC = "R1" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[2]" LOC = "M5" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[3]" LOC = "N4" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[4]" LOC = "N5" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[5]" LOC = "N2" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[6]" LOC = "M6" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[7]" LOC = "P1" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[8]" LOC = "L3" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[9]" LOC = "J4" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[10]" LOC = "M3" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[11]" LOC = "K4" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[12]" LOC = "M2" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[13]" LOC = "K3" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[14]" LOC = "L4" | IOSTANDARD = SSTL15 ;
NET "ddr3_dq[15]" LOC = "L5" | IOSTANDARD = SSTL15 ;
NET "ddr3_dm[0]" LOC = "P2" | IOSTANDARD = SSTL15 ;
NET "ddr3_dm[1]" LOC = "J6" | IOSTANDARD = SSTL15 ;
NET "ddr3_dqs_p[0]" LOC = "P5" | IOSTANDARD = DIFF_SSTL15 ;
NET "ddr3_dqs_n[0]" LOC = "P4" | IOSTANDARD = DIFF_SSTL15 ;
NET "ddr3_dqs_p[1]" LOC = "M1" | IOSTANDARD = DIFF_SSTL15 ;
NET "ddr3_dqs_n[1]" LOC = "L1" | IOSTANDARD = DIFF_SSTL15 ;
NET "ddr3_addr[13]" LOC = "W5" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[12]" LOC = "AA5" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[11]" LOC = "AB7" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[10]" LOC = "Y9" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[9]" LOC = "Y4" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[8]" LOC = "AA8" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[7]" LOC = "AA4" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[6]" LOC = "Y7" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[5]" LOC = "AA3" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[4]" LOC = "AB6" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[3]" LOC = "Y2" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[2]" LOC = "Y3" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[1]" LOC = "AA6" | IOSTANDARD = SSTL15 ;
NET "ddr3_addr[0]" LOC = "AB3" | IOSTANDARD = SSTL15 ;
NET "ddr3_ba[2]" LOC = "W2" | IOSTANDARD = SSTL15 ;
NET "ddr3_ba[1]" LOC = "AB5" | IOSTANDARD = SSTL15 ;
NET "ddr3_ba[0]" LOC = "AB2" | IOSTANDARD = SSTL15 ;
NET "ddr3_ck_p[0]" LOC = "T5" | IOSTANDARD = DIFF_SSTL15 ;
NET "ddr3_ck_n[0]" LOC = "U5" | IOSTANDARD = DIFF_SSTL15 ;
NET "ddr3_ras_n" LOC = "V2" | IOSTANDARD = SSTL15 ;
NET "ddr3_cas_n" LOC = "AA1" | IOSTANDARD = SSTL15 ;
NET "ddr3_we_n" LOC = "W1" | IOSTANDARD = SSTL15 ;
NET "ddr3_reset_n" LOC = "W4" | IOSTANDARD = LVCMOS15 ;
NET "ddr3_cke[0]" LOC = "Y6" | IOSTANDARD = SSTL15 ;
NET "ddr3_odt[0]" LOC = "AB1" | IOSTANDARD = SSTL15 ;
NET "ddr3_cs_n[0]" LOC = "Y1" | IOSTANDARD = SSTL15 ;

这些保持默认:

同意完所有的协议后,生成MIG IP核,综合选项仍然选择Out of context per IP:


生成IP核后,可以在IP核里面的mig_7series_0.v里面看到这个IP核究竟有哪些引脚:


每个引脚的格式一目了然。

最后,在综合完自己的代码后,进入Schematic一看,可以看到DDR3的引脚早已配置好了,我们只需要配置其他的引脚就可以了。


也就是说,保存的pins.xdc里面是不包含DDR3引脚的配置的。DDR3引脚配置是专门在MIG IP核的文件夹里面有一个xdc文件。

工程建好了,IP核也配置好了,接下来就是编写代码了:https://blog.csdn.net/ZLK1214/article/details/111085879

MIG核自带的那个example工程很复杂,里面参数也很多,阅读起来很难懂。我们不用那个example工程,自己写代码调用IP核,简单易懂。

最后编译代码产生bit文件的时候,是没有报任何错误的,直接成功:

最新文章

最新文章