快速上手Xilinx DDR3 IP核(2)—-MIG IP核的官方例程与读写测试模块(Native接口)

写在前面 接上一篇文章(配置MIG IP过程): 快速上手Xilin…

写在前面

接上一篇文章(配置MIG IP过程):

快速上手Xilinx DDR3 IP核(1)—-MIG IP核的介绍及配置(Native接口)

DDR3系列文章:

快速上手Xilinx DDR3 IP核—-汇总篇(直达链接)


1、官方例程(example design)

在我心中,Xilinx是一家完美的公司(自动忽略vivado编译太慢),技术生态支持实在是做的太好了。Xilinx也知道我们不会用DDR3,所以提供了一个example design给你学习,怎么样?惊不惊喜?意不意外?(实际上,绝大多数的IP Xilinx都提供了example design~~)

那么接下来就一起学习下官方提供的参考设计呗。

1.1、示例生成步骤

右击生成的IP核(默认你已经生成了MIG IP核),选择open IP example design,选择好路径后就会生成一个新的工程mig_7series_0_ex。

打开工程mig_7series_0_ex,看下整个工程的结构—-2个主要部分:1、MIG IP核;2、读写测试的数据生成模块

读写测试模块我们不展开讲(太多了,一时半会讲不完),我们直接通过波形来学习。

点击RUN SIMULATION,直接执行仿真(这里可能等几分钟(吃电脑配置)—-强烈建议使用Modelsim仿真,速度快的不是一星半点

1.2、仿真结果

仿真结果出来后,只保留一些比较有用的信号,并进行分组,如下:

找init_calib_complete拉高后(DDR3初始化完成)的一些局部时序图,如下图:

蓝线、和黄线处,app_cmd为0,app_en、app_rdy均为高,代表在执行写命令操作;同时app_wdf_data同地址一致,app_wdf_en、app_wdf_rdy均为高,代表在进行写数据操作

如下图:

很多个周期的app_rdy拉低,代表MIG没有准备好进行写数据命令,但此时app_wdf_data同地址一致,app_wdf_en、app_wdf_rdy均为高,代表在进行写数据操作。这正是前面章节提到了写数据提前与写命令,因为MIG种有一个FIFO,将要写入的数据存入FIFO,等到写命令有效时,再对FIFO进行读取。这样做的好处是可以很大程度上做到写命令和写数据分离。

如下图:

蓝线处,app_cmd为1,app_en、app_rdy均为高,地址app_addr为0x0000200,代表在执行读命令操作。经过若干个周期后,黄线处读取数据有效标志信号app_rd_data_valid拉高,代表成功读取到了一个数据,数据为0x0000200000020000002000000200,与前面写入的一致

2、读写测试模块

通过上节对官方例程的学习,已经初步了解了DDR3的接口时序,接下来就自己编写一个简单的读写测试模块来对DDR3操作一番。(不当云玩家)

2.1、Verilog代码

读写测试模块预期要实现的功能:

  • 写入一定量的数据(可设置,默认512个)到DDR3,写入地址从0开始
  • 从地址0开始读取之前写入DDR3的数据,同时判断读、写数据是否一致
  • 循环上两个步骤,即写、读、写、读····

不妨先来回顾下DDR3提供的Native接口的时序。

DDR3 的读或者写都包含写命令操作,其中写操作命令(app_cmd)的值等于 0,读操作 app_cmd 的值 等于 1。首先来看写命令时序,如下图所示。首先检查 app_rdy,为高则表明此时 IP 核命令接收处于准备好 状态,可以接收用户命令,在当前时钟拉高 app_en,同时发送命令(app_cmd)和地址(app_addr),此时命令和地址被写入。

写数据的时序,如下图所示:

写数据的情况有3种:

  1. 写命令与写数据发生在同一时钟周期
  2. 写数据先于写命令发生(不一定是图上的一个时钟周期,因为数据是先写到了FIFO)发生在同一时钟周期
  3. 写数据落后于写命令发生,但不能超过两个时钟周期

结合上图,写时序总结如下:首先需要检查 app_wdf_rdy,该信号为高表明此时 IP 核数据接收处于准备完成状态,可以接收用户发过来的数据,在当前时钟拉高写使能(app_wdf_wren),给出写数据 (app_wdf_data)。这样加上发起的写命令操作就可以成功向 IP 核写数据。

接着来看读数据,如下图所示:

读时序比较简单,发出读命令后,用户只需等待数据有效信号(app_rd_data_valid)拉高,为高表明此 时数据总线上的数据是有效的返回数据。需要注意的是,在发出读命令后,有效读数据要晚若干周期才出现在数据总线上 (延迟的时间不定)。

2.1.1、PLL模块

本来仿真是不需要PLL模块的(直接写时钟激励就行),但是考虑到等下还需要上板测试,而我手头的开发板主频50M,MIG的工作时钟却是200M,所以需要PLL模块生成工作时钟。具体配置略。

2.1.2、DDR3仿真模型

在生成的example design中提供了DDR3的仿真模型,共两个文件:

1、DDR3仿真模型的头文件

2、DDR3仿真模型

找到这两个文件,把它们添加进我们自己的测试工程里。

2.1.3、读写测试模块

读写测试模块生成对MIG IP核的控制时序,并使用一个状态机来实现循环写、读的过程。状态机如下:

  • IDLE:初始状态,等MIG IP核初始化完成后跳转到写数据状态WRITE
  • WRITE:写数据状态,在这个状态向MIG IP核写入一定量的数据(测试为512个)。当写入最后一个数据时,同步跳转到等待状态WAIT
  • WAIT:过渡状态,仅维持一个周期
  • READ:读数据状态,在这个状态从MIG IP核读取一定量的数据(测试为512个)。当读取最后一个数据时,同步跳转到初始状态IDLE。开始新一轮的写、读过程

前面说到,DDR3写数据的时候有3种模式,我们在测试的时候,固定使用“写命令与写数据发生在同一时钟周期这一模式。这样一来,代码编写会简单很多,但相应的会牺牲一点点效率(不会造成多大的影响)。

完整的读写模块测试代码如下:

注释还是比较详细的,就不讲解了,只说几个需要注意的点。

  • DDR3的突发长度固定为8,选择的DDR3芯片为16bit,所以数据位宽 = 8 * 16bit = 128bit
  • DDR3的突发长度固定为8,等于每次操作实际上是对8个地址操作,所以每次写入数据的地址需要累加8

2.1.4、顶层模块

顶层模块的设计十分简单:只要例化上述3个模块即可。如下:

2.2、Testbench及仿真结果

好的,Verilog代码写完了,接下来就跑跑仿真验证以下。

2.2.1、Testbench

Testbench也很简单,只需要提供时钟、复位激励;例化读写测试模块及DDR3仿真模型就好了,如下:

2.2.2、仿真结果

仿真我们不用Vivado跑了(不是说慢,是真慢),改用Modelsim跑。Modelsim跑仿真速度快,来来回回的修改调试也方便。

废话少说,仿真结果如下:

上图中:MIG初始化完成信号init_calib_complete拉高,表示MIG控制器初始化完成。然后,进入开始写数据,再读数据。如此不停重复。

上图是:写数据过程的开头部分:

写入地址从0开始累加,每次累加8,因为突发长度为8;

写入数据从0开始累加,每次累加1;

当命令有效、写命令有效,且写指令为低(代表写)时,数据被写入。

上图是:写数据过程的结束部分:

写入地址从0开始累加,每次累加8,因为突发长度为8,到4088截止;

写入数据从0开始累加,每次累加1,到511截止,共写入512个数据;

当命令有效、写命令有效,且写指令为低(代表写)时,数据被写入。

上图是:读数据过程的开始部分:

读取地址从0开始累加,每次累加8,因为突发长度为8;

从发出读取指令到真正读到数据需要一定的时间;

当命令有效,且指令为高(代表读)时,数据被读出;

读出的数据与写入的数据一致(0-1-2-······)。

上图是:读数据过程的结束部分:

读取地址从0开始累加,每次累加8,因为突发长度为8,到4088;

从发出读取指令到真正读到数据需要一定的时间;

当命令有效,且指令为高(代表读)时,数据被读出;

读出的数据与写入的数据一致(0-1-2-······511)。

3、上板验证

3.1、验证环境

FPGA:XC7A35T FGG484-2

DDR3:NT5CB128M16CP-DI

Vivado:Vivado 2019.2

Modelsim:Modelsim SE-64 2020.4

文件:V1.0

编号:71

3.2、验证结果

结果基本与仿真结果一致,写、读验证无误,读取数据一致。截几张图贴出来

初始化完成后进行的写操作:

读操作:

至此,读写模块验证成功。

3、其他

3.1、可能遇到的问题:

3.1.1、Vivado如何联合modelsim仿真?

使用modelsim仿真xilinx的IP核,主要需要解决仿真库的问题。不得不说modelsim是真的好用。

供参考:vivado与modelsim的联合仿真

3.1.2、使用modelsim仿真DDR3报错Module ‘SIP_PHY_CONTROL‘ is not defined

没找到什么好办法,重装了新版本的modelsim(2020.4版本)。重装以后问题解决。

3.1.3、VIVADO调用 ModelSim一直无响应

基本上是语法错误,请仔细检查。

供参考:Xilinx VIVADO 仿真时无法调用 ModelSim 失败的解决办法

3.1.4、app_rdy信号被拉高一段时间后,然后一直为低的问题

下面三个保留的信号全接到0后解决(Xilinx都在手册告诉你这么做了,你又不听,哎······)

3.2、后记

  • 可以看到,Native接口其实相对来讲已经很好用了。但是有没有办法用起来更方便一点?当然有咯!FIFO用起来方不方便,一个使能信号就能写数据了。我们接下来就把MIG给封装成一个FIFO来用,大大简化工作量。
  • 创作不易,如果本文对您有帮助,还请多多点赞、评论和收藏。您的支持是我持续更新的最大动力!
  • 关于本文,您有什么想法均可在评论区留言交流。如果需要整个工程,请在评论留下邮箱或者私信我邮箱(注意保护隐私)。
  • 自身能力不足,如有错误还请多多指出!

本文来自网络,不代表软粉网立场,转载请注明出处:https://www.rfff.net/p/4129.html

作者: HUI

发表评论

您的电子邮箱地址不会被公开。

返回顶部