当前位置:   article > 正文

DDR3控制器测试--基于Vivado2021.1的MIG核_vivado ddr3 上板

vivado ddr3 上板

        以前在学习和工作中,都是使用的Intel的开发平台,前些时间在某宝买了块米联客的ZYNQ7035板卡来学习。因为对Xilinx的平台并不熟悉,所以首先使用MIG核设计一个DDR3控制器测试一下PL端的DDR3来练手。本文就简单记录一下使用ZYNQ7035开发平台测试PL端DDR3的过程吧。

一、软硬件环境

本文用于验证DDR3控制器所使用的软件版本为Vivado 2021.1,FPGA板卡硬件详情如下:

  1. FPGA板卡是MIZ7035FC,FPGA芯片型号是XC7Z035FFG900-2;

  2. PL端搭载4片镁光DDR3L存储器芯片,兼容MT41K256M16 RE-125,单片DDR3L容量为512MB*16bit,内存主频高达1600MHz,每片的容量为2^15*2^10*2^3*16bit=4Gbit,通过4片DDR3扩展组成了16Gbit容量的DDR3内存,4片DDR3L存储芯片连接方式如下图示。

二、MIG IP核介绍

  1. MIG内部结构

        和Quartus一样,Xilinx的Vivado开发套件同样为用户提供了高效、灵活的外部存储器接口解决方案,能够快速实现FPGA与外部DDR SDRAM高速存储器之间的数据交互。7系列MIS所提供的MIG(Memory Interface Generator) IP核包含了用户接口、存储器控制器以及物理层(PHY),结构示意图如图2.1所示。7系列FPGA的MIG(Memory Interface Generator)是一个集成了控制器与物理层的存储器接口,可以用于连接FPGA内部的用户逻辑与外部的DDR3/DDR2存储器芯片,其内部结构如下图所示。MIG IP核用户手册--UG586

        可以看到,整个MIG IP核的左侧User Interface(UI,用户接口),用于连接控制MIG IP核的用户逻辑;右侧是Physical Interface,即用于和DDR3存储器芯片交互的物理层接口,产生DDR3芯片工作所需的具体控制、命令和数据等时序,并直接驱动DDR3芯片的引脚。在实际使用时,我们只需要搞清楚左侧的UI的接口时序即可控制MIG IP核完成对DDR3存储器的数据读写操作了;然后对Physical Interface只需要做物理上的引脚分配,将其与DDR3存储器的引脚连接到一起就可以了。

  1. User FPGA Logic:即用户逻辑,是MIG IP核之外的部分,用于向MIG产生读操作、写操作相关的请求、地址和数据等;

  2. User Interface Block and User Interface:用于连接MIG与用户逻辑的接口,用户逻辑通过UI与MIG进行交互,控制MIG执行读数据或写数据操作;

  3. Memory Controller and Native Interface:Memory Controller用于处理UI接收到的各种请求,并对其进行排序以优化数据吞吐量和传输延时;Native Interface则是向User FPGA Logic提供了向存储器发起读写请求以及数据存取机制;

  4. Physical Layer and Physical Interface:Physical Layer是用于产生DDR3存储器所需的地址、数据、控制等信号时序的;Physical Interface则是MIG和DDR3存储器芯片连接的通信通道。

  5. User Interface侧接口说明

信号名称

输入/输出

功能描述

sys_clk_i

input

MIG系统时钟输入,用于生成内部逻辑、移相器参考时钟等

sys_rst

input

系统异步复位信号,低电平有效,复位脉冲至少需要5ns

ui_clk

output

用户接口时钟,频率为DDR3工作时钟频率的1/2或1/4

ui_clk_sync_rst

output

用户接口的同步复位时钟,高电平有效

init_calib_complete

output

ddr3初始化完成,高电平有效

app_addr

input

UI侧读/写请求对应的地址

app_cmd

input

UI侧用于选择读操作或写操作的命令,1表示读,0表示写

app_en

input

UI侧输入使能信号,只有app_rdy有效时,app_en才有效

app_rdy

output

UI准备好接收读写操作对应的命令

app_wdf_rdy

output

MIG内部的FIFO可以接收数据的标志信号

app_wdf_data

input

用户逻辑写入MIG的数据

app_wdf_end

input

当前周期是写入的最后一个数据

app_wdf_mask

input

app_wdf_data的掩码信号,每一个bit对应一个byte

app_wdf_wren

input

app_wdf_wren和app_wdf_rdy都有效时,app_wdf_data才会被写入

app_rd_data

output

MIG从DDR3读取并输出给用户逻辑的数据

app_rd_data_end

output

表示当前周期输出的数据是此次读操作的最后一个数据

app_rd_data_valid

output

app_rd_data_valid为高时,表示app_rd_data有效

注:1、app_wdf_end和app_rd_data_end什么时候拉高,跟Memory Controller和DDR3的时钟比例有关系。2、我们使用MIG时,用户逻辑与MIG交互时可以使用上面的User Interface,也可以使用AXI4接口,这里先只介绍User Interface的接口信号。

  1. User Interface侧接口时序

  1. 命令通道

        可以发现,当app_rdy和app_en同时为高电平时,命令(app_cmd)和地址(app_addr)才会被MIG所接收。

  1. 写数据通道

        对于写操作,命令(app_cmd、app_addr、app_en、app_rdy)和数据(app_wdf_data、app_wdf_wren、app_wdf_end)可以不用同步寄存,也就是说--命令可以先于数据被输入,也可以后于数据被输入,但是数据和命令之间的延迟不可以超过2个时钟周期;并且,只有在app_wdf_rdy有效时数据才能寄存,这是因为MIG内部有一个FIFO用于存储接收到的数据,只有当此FIFO处于ready(app_wdf_rdy为1)状态且app_wdf_wren与app_wdf_end都有效时才能接收数据app_wdf_data。另外,当UI侧的数据速率与PHY侧的DDR3时钟速率比为4:1时,app_wdf_end与app_wdf_en两者的时序一样;当UI侧的数据速率与PHY侧的DDR3时钟速率比为2:1时,app_wdf_end与app_wdf_en两者的时序不一样,app_wdf_end每拉高两个周期,app_wdf_en在第二个周期拉高;这块跟我们对MIG IP核的配置有关系。

  1. 读数据通道

        读操作的时序比较简单,只需要在MIG准备好(app_rdy为1)时,给入命令即可控制MIG从DDR3突发数据返回给用户逻辑。

        需要注意的是,虽然三个通道相互独立,但是写数据通道与读数据通道共用命令通道,因此,在UI侧不能同时给入读操作的命令和写操作的命令,这一点也和DDR3存储器的分时读写特点是一致的。

  1. 地址映射

        UI侧输入的地址和Memory Controller的地址有两种映射方式:BANK_ROW_COLUMN和ROW_BANK_COLUMN,可以在配置MIG IP核时选择不同的映射方式。例如:当DDR3的Bank地址位宽为3、Row地址位宽为15、Column地址位宽为10时,则BANK_ROW_COLUMN方式下,app_addr的值为{Bank[2:0],Row[14:0],Column[9:0]},ROW_BANK_COLUMN方式下,app_addr的值为:{Row[14:0],Bank[2:0],Column[9:0]}。

三、MIG IP核配置

  1. 在IP Catalog中搜索“mig”,即可找到Memory Interface Generator,然后双击打开;

  1. 在接下来的界面中直接点击"Next",进入下一个界面,根据自己的需求配置基本信息,然后点击"Next";
  1. 选择引脚兼容的FPGA,此次使用的芯片是xc7z035-ffg900-2,所以保持默认型号即可,直接点击"Next"进入下一步;

  1. 存储器型号选择”DDR3 SDRAM“,然后点击"Next"进入下一步;

  1. 控制器配置:

Clock Period:配置为2000ps即可,DDR3的工作时钟频率为500MH,实际的传输频率为1GHz,这个根据自己项目中所需要的数据传输带宽设置即可。

PHY to Controller Clcok Rate:PHY与控制器的时钟频率比(一般是2:1或4:1)。2:1时,UI侧app_wdf_data的位宽是DDR3物理内存接口位宽的4倍,延迟更低但是会因为FPGA逻辑的时序限制导致内存接口频率折损;4:1时,UI侧app_wdf_data的位宽是DDR3物理内存接口位宽的8倍,数据速率较高。一般来说,当工作频率较高时,选择4:1比较合适。

Memory Part:选择自己的板卡上DDR3存储器型号或者是兼容的型号就行;

Memory Voltage:DDR3存储器的工作电压,板卡上的DDR3是LPDDR3,所以其工作电压设置为1.35V即可;

Data Width:DDR3 RANK的实际数据位宽,这里选择64(16*4);

Data Mask:勾选则会产生实际的数据掩码引脚,不勾选的话能够提高引脚效率,一般SDRAM都有数据掩码的功能,所以这里勾选上;

Number of Bank Machines:用于对部分或全部BANK进行控制,最大可选8个,值越大可以操作的内从容量越大,消耗的资源也越多;

ORDERING:用来控制MIG是否对它收到的读/写指令进行重新排序以提高总线效率,Normal表示允许,Strict 表示禁止,严格按照UI输入的顺序执行。此处选择 Normal,保证控制器具有较高的效率。

  1. Memory Option:

Input Clock Period:MIG核系统输入时钟周期,需要是PLL生成的时钟;

Read Burst Type and Length:突发类型选择,突发类型有顺序突发和交叉突发两种,选择顺序突发(Sequential),突发长度固定为 8,用于配置DDR3的模式寄存器;

Output Driver Impdance Control:DDR3输出驱动阻抗控制,此处设置为 RZQ/7,RZQ的值为240Ω,根据DDR3的芯片手册可知;

RTT:DDR3的片上终结电阻配置,可进行动态控制,选择 RZQ/4即60Ω;

Controller Chip Select Pin:片选管脚引出使能,选择enable即可,表示生成片选信号 cs#并控制外部DDR3;

BANK_ROW_COLUMN:地址映射方式,选择BANK_ROW_COLUMN形式即可。

  1. FPGA Options:

System Clock:配置MIG的输入系统时钟的类型,可以是单端时钟、差分时钟或No Buffer模式,这里选择No Buffer模式即可,由PLL提供时钟;

Reference Clock:MIG核的参考时钟输入,设置为“Use System Clcok”,表示使用System Clcok作为参考时钟使用;

System Reset Polarity:系统复位信号的极性,设置为低电平有效即可;

Debug Signals Control:用于设置是否需要把MIG IP核的一些如校准状态之类的调试信号引出来,如果引出则会被自动添加到 ILA或VIO,此处可以不需要引出调试信号,选择 “OFF”即可;

Sample Data Depth:采样深度设置,当“Debug Signals Control”设置“OFF”时,此选项不可配置;

IO Power Reduction:IO 管脚节省功耗设置,启用此功能;

XADC Instantiation:XADC补偿使能,若使能则MIG核会调用XADC进行温度监控。

  1. 接下来两个界面可以直接选择默认配置即可;

  1. Pin Selection:这个界面主要是配置DDR3芯片的引脚编号及电平属性,首先点击Read XDC/UCF,导入板卡配套的UCF文件,然后点击Validata进行验证,验证不报错才能点击“Next”进行下一步操作;

  1. 后面的步骤就不需要再多说了,直接点击”Next“,直到最后一个界面时点击”Generate“生成IP核即可完成MIG核的配置。

        配置完IP核之后,我们可以通过对Vivado提供的Example Design工程仿真以进一步搞清楚MIG IP核的UI接口时序,方便后续完整DDR3控制器的设计。

四、MIG IP核仿真

  1. 首先,需要生成Example Design工程,右键选中刚才生成的MIG IP核,在出现的菜单栏中会有一个Open IP Example Design,点击Open IP Example Design即可生成Open IP Example;

  1. 找到刚才生成的Example Design工程,双击.xpr文件即可打开Vivado工程;

  1. 在Vivado工程首页直接点击“Run Simulation”即可打开仿真,这个过程可能会需要一会时间;打开仿真后可以在Scope中将MIG核的信号添加到波形窗口,以便观察MIG的UI侧信号时序,当然,如果有需要也可以把DDR3存储器模型也添加到波形窗口,这样可以观察到DDR3存储器的PHY层时序,有助于我们更好的理解DDR3的工作原理;

  1. 经过大约55us的运行后,MIG完成对DDR3的初始化校准,然后接下来就可以对DDR3进行读写测试了,可以看到MIG的UI侧信号时序跟我们之前分析的是一致的;

  1. 可以发现,每产生一个读/写命令,app_addr相应的偏移8个地址单元,这是因为MIG的UI侧数据总线位宽为512,而DDR3的PHY层数据总线位宽为64,两者之间是8倍的关系;另外,观察UI侧的时钟频率与PHY侧的时钟信号可以发现,UI侧的时钟(ui_clk)周期为5000ps,而PHY侧的时钟(ddr3_ck_p_fpga)的周期为1250ps,两者之间是4倍的关系,但是由于UI侧是单边沿传输,而PHY侧是双边沿传输,因此,两者之间的数据传输速率是4*2倍的关系,这样数据和地址就一一对应上了。

搞清楚UI接口信号时序后,接下来就可以利用MIG来设计完整的DDR3控制器了。

五、工程设计与仿真

        相比较而言,Xilinx的MIG核仿真比较简单,只需要在我们的Testbench中例化DDR3仿真模型就可以直接使用Xsim仿真了,可以不需要设计仿真脚本。

  1. genvar r,i;
  2. generate
  3. for (r = 0; r < CS_WIDTH; r = r + 1) begin: mem_rnk
  4. if(DQ_WIDTH/16) begin: mem
  5. for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem
  6. ddr3_model u_comp_ddr3
  7. (
  8. .rst_n (ddr3_reset_n),
  9. .ck (ddr3_ck_p_sdram),
  10. .ck_n (ddr3_ck_n_sdram),
  11. .cke (ddr3_cke_sdram[r]),
  12. .cs_n (ddr3_cs_n_sdram[r]),
  13. .ras_n (ddr3_ras_n_sdram),
  14. .cas_n (ddr3_cas_n_sdram),
  15. .we_n (ddr3_we_n_sdram),
  16. .dm_tdqs (ddr3_dm_sdram[(2*(i+1)-1):(2*i)]),
  17. .ba (ddr3_ba_sdram[r]),
  18. .addr (ddr3_addr_sdram[r]),
  19. .dq (ddr3_dq_sdram[16*(i+1)-1:16*(i)]),
  20. .dqs (ddr3_dqs_p_sdram[(2*(i+1)-1):(2*i)]),
  21. .dqs_n (ddr3_dqs_n_sdram[(2*(i+1)-1):(2*i)]),
  22. .tdqs_n (),
  23. .odt (ddr3_odt_sdram[r])
  24. );
  25. end
  26. end
  27. if (DQ_WIDTH%16) begin: gen_mem_extrabits
  28. ddr3_model u_comp_ddr3
  29. (
  30. .rst_n (ddr3_reset_n),
  31. .ck (ddr3_ck_p_sdram),
  32. .ck_n (ddr3_ck_n_sdram),
  33. .cke (ddr3_cke_sdram[r]),
  34. .cs_n (ddr3_cs_n_sdram[r]),
  35. .ras_n (ddr3_ras_n_sdram),
  36. .cas_n (ddr3_cas_n_sdram),
  37. .we_n (ddr3_we_n_sdram),
  38. .dm_tdqs ({ddr3_dm_sdram[DM_WIDTH-1],ddr3_dm_sdram[DM_WIDTH-1]}),
  39. .ba (ddr3_ba_sdram[r]),
  40. .addr (ddr3_addr_sdram[r]),
  41. .dq ({ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)],
  42. ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)]}),
  43. .dqs ({ddr3_dqs_p_sdram[DQS_WIDTH-1],
  44. ddr3_dqs_p_sdram[DQS_WIDTH-1]}),
  45. .dqs_n ({ddr3_dqs_n_sdram[DQS_WIDTH-1],
  46. ddr3_dqs_n_sdram[DQS_WIDTH-1]}),
  47. .tdqs_n (),
  48. .odt (ddr3_odt_sdram[r])
  49. );
  50. end
  51. end
  52. endgenerate

        然后,在Vivado界面Run Simulation,这个过程会需要点时间,大约仿真55us后,DDR3初始化训练校准完成(init_calib_complete拉高),然后我们可以看到我们设计的用户逻辑在对DDR3进行数据写入和读出,而且,读出的数据和写入的数据是一样的,证明我们设计的DDR3控制器基本是可以实现对DDR3的读写的。实际上,上板运行也是正确无误的。

六、总结

        本文主要简单介绍了Vivado中使用MIG核设计DDR3控制器的过程,相比较而言,Vivado的MIG核的接口时序比Quartus的EMIF核的接口时序要略微复杂,但是其仿真过程要简单的多,相对来说比较容易上手。实际上,不管多么复杂的IP核,只要弄清楚了UG,能够有一个Example跑一下仿真,上手做设计其实难度也不大。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/598076
推荐阅读
相关标签
  

闽ICP备14008679号