DDR3控制器测试--基于Vivado2021.1的MIG核

        以前在学习和工作中,都是使用的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仿真了,可以不需要设计仿真脚本。

genvar r,i;

  generate

    for (r = 0; r < CS_WIDTH; r = r + 1) begin: mem_rnk

      if(DQ_WIDTH/16) begin: mem

        for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem

          ddr3_model u_comp_ddr3

            (

             .rst_n   (ddr3_reset_n),

             .ck      (ddr3_ck_p_sdram),

             .ck_n    (ddr3_ck_n_sdram),

             .cke     (ddr3_cke_sdram[r]),

             .cs_n    (ddr3_cs_n_sdram[r]),

             .ras_n   (ddr3_ras_n_sdram),

             .cas_n   (ddr3_cas_n_sdram),

             .we_n    (ddr3_we_n_sdram),

             .dm_tdqs (ddr3_dm_sdram[(2*(i+1)-1):(2*i)]),

             .ba      (ddr3_ba_sdram[r]),

             .addr    (ddr3_addr_sdram[r]),

             .dq      (ddr3_dq_sdram[16*(i+1)-1:16*(i)]),

             .dqs     (ddr3_dqs_p_sdram[(2*(i+1)-1):(2*i)]),

             .dqs_n   (ddr3_dqs_n_sdram[(2*(i+1)-1):(2*i)]),

             .tdqs_n  (),

             .odt     (ddr3_odt_sdram[r])

             );

        end

      end

      if (DQ_WIDTH%16) begin: gen_mem_extrabits

        ddr3_model u_comp_ddr3

          (

           .rst_n   (ddr3_reset_n),

           .ck      (ddr3_ck_p_sdram),

           .ck_n    (ddr3_ck_n_sdram),

           .cke     (ddr3_cke_sdram[r]),

           .cs_n    (ddr3_cs_n_sdram[r]),

           .ras_n   (ddr3_ras_n_sdram),

           .cas_n   (ddr3_cas_n_sdram),

           .we_n    (ddr3_we_n_sdram),

           .dm_tdqs ({ddr3_dm_sdram[DM_WIDTH-1],ddr3_dm_sdram[DM_WIDTH-1]}),

           .ba      (ddr3_ba_sdram[r]),

           .addr    (ddr3_addr_sdram[r]),

           .dq      ({ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)],

                      ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)]}),

           .dqs     ({ddr3_dqs_p_sdram[DQS_WIDTH-1],

                      ddr3_dqs_p_sdram[DQS_WIDTH-1]}),

           .dqs_n   ({ddr3_dqs_n_sdram[DQS_WIDTH-1],

                      ddr3_dqs_n_sdram[DQS_WIDTH-1]}),

           .tdqs_n  (),

           .odt     (ddr3_odt_sdram[r])

           );

      end

    end

  endgenerate

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

六、总结

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

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值