基于A7的DDR3 SDRAM 控制器IP核相关操作(一)

目录

一、概述

二、DDR3 SDRAM 控制器IP核的调取

三、DDR3 SDRAM 控制器IP核的初始化

(一)顶层源文件的建立

(二)测试文件建立

(三)仿真

四、DDR3 SDRAM 控制器IP核的写

(一)知识铺垫

(二)建立新的文件并编写代码

(三)测试文件改写

(四)仿真

五、DDR3 SDRAM 控制器IP核的读

六、DDR3 SDRAM 控制器IP核的仲裁

七、总结

一、概述

掌握Xilinx A7 FPGA芯片内已集成的用于控制SDRAM的IP核的调取和使用。

二、DDR3 SDRAM 控制器IP核的调取

1. DDR3的IP核是软核,需要占用FPGA的逻辑。

2. 在建立工程后,在“IPCatalog”里面搜索“memory interface generator”。然后按照里面的提升,一步一步的设置自己需要的IP核。

3.本设计的一些参数有:

  (1)DDR3工作频率400MHz;

  (2)PHY与用户端的时钟速率设置的4:1模式;

  (3)控制器输入时钟200MHz;

4. 导入相应的约束文件(UCF/XDC)。

三、DDR3 SDRAM 控制器IP核的初始化

1. 每次在Controller 初始化之前,首先要进行阻抗设置、IP核自动设置、调整读写时钟相位延迟等操作,目的是为了使DDR3收发数据更加稳定。该操作被称为——自动校准。

在IP核自动校准的时候,勿进行任何操作。

具体初始化思路步骤如下:

(一)顶层源文件的建立

1.在vivado中“sources”栏中添加新的源文件——"top_ctrl",该文件即为顶层源文件;

2.打开"top_ctrl"文件进行编写。

  (1)将二中调取的DDR3 SDRAM 控制器的IP 核例化到"top_ctrl"中;在实例化的模板中,以ddr3开头的信号是DDR3 SDRAM芯片引脚的变量,因此在该文件中需要将其设置为端口变量,端口变量模板在ddr_hdmi.srcs\sources_1\ip\DDR3_ctrl\DDR3_ctrl\user_design\rtl 里面的.v文件里便可以找到。

  (2)然后在端口列表中再加入系统时钟和复位信号;

  (3)由于系统时钟是50MHz输入的,而我们在二中调取IP核的时候选择的输入时钟是200Mhz,所以需要倍频,调取一个“clock wizard”的IP核实现50->200Mhz。再将该IP核例化到"top_ctrl"中;

  (4)连接端口信号和例化模块信号;

(二)测试文件建立

1. 在“sources”栏中的“simulation sources”中添加新的仿真源文件——"tb_top";

2.打开"tb_top"文件,在该文件中需要例化顶层文件,并且需要添加DDR3的模型来用于仿真;

3. 模型文件在ddr_hdmi.srcs\sources_1\ip\DDR3_ctrl\DDR3_ctrl\user_design\sim中将.sv和.vh的模型文件复制到和新建的测试文件同一个目录下。然后测试文件需要例化的代码到sim文件夹里的.v文件中找;

4. 在测试文件中产生一个复位和50MHz的系统时钟;

(三)仿真

1. 编译vivado软件和modelsim之间关联的库;

2.启动仿真;观察信号init_calib_complete是否有拉高,如若拉高则DDR3 SDRAM控制器IP核初始化成功。

四、DDR3 SDRAM 控制器IP核的写

1.  调取的ddr3_sdram控制器的ip核给用户预留了接口,我们可以通过这些预留的接口实现对IP核的控制,我们在这个章节中实现写控制。

2.实现的思路步骤如下:

(一)知识铺垫

1.存储器接口的方案核心如图4-1所示。相关信号的作用可自行到xilinx官方下载文档进行查看。

图4-1 7系列FPGA存储器接口方案

2. 在“二”调取的IP核DDR3的PHY与用户端的时钟速率设置的4:1模式,所以app_wdf_wren和app_wdf_end信号满足如图4-2所示的关系,即app_wdf_wren=app_wdf_end。

图4-2  4:1模式用户界面写入命令时序表

3. 写数据与写命令之间的关系我选择数据先到,然后再启动命令。即图4-3中的模式2.

图4-3 4:1模式用户接口时序表

4.我创建A7_wr_ctrl模块来对IP核进行控制,控制模块框图如图4-4所示。

图4-4 写控制框图

(二)建立新的文件并编写代码

1.在vivado中“sources”栏中添加新的文件“A7_wr_ctrl”;

2. 代码实现,在实现的过程中,要注意的一些问题:

  (1)由于我是选择先来数据再给写命令,所以在wr_cmd_start信号拉高一拍以后,先是控制写数据的app_wdf_wren先拉高,然后才是控制写命令的app_en拉高;

  (2)输入数据位宽为128bit,DDR3的数据位宽为16bit,burst_length系统默认最大为8,16x8刚好128bit;

  (3)app_wdf_rdy和app_wdf_wren同时有效的时候才可以接收数据,同理,app_en和app_rdy同时有效才可以接收写命令进行数据的写入;

  (4)为了控制app_wdf_wren和app_en的拉低,要加入data_cnt 和cmd_cnt 信号。

3.代码实现后,将其例化到顶层模块内。

(三)测试文件改写

1.对三中建立的测试文件进行改写,如图4-4中A7_wr_ctrl模块左边的信号,除了从IP核中引出来的输入信号外都要在测试文件中生成;

2.生成这些信号要用到“A7_wr_ctrl” 模块中的时钟信号和复位信号,因为该模块中的时钟信号是由IP核输出给用户端的,与FPGA 提供的时钟不同,所以要用force 语句将“A7_wr_ctrl”模块中的相应信号引入到tb测试文件中,也可以用force 语句将产生的数据、突发长度、开始、地址、掩码、模式信号输入到“A7_wr_ctrl” 模块中。

3.用task-endtask语句产生wr_cmd_start 信号和64 个128bit 的从0到63递增的数据。

(四)仿真

1.在vivado中启动仿真。

2.我在仿真中遇到的问题:

(1)仿真中出现错误:“找不到用force传输的相应的信号”。原因是因为忘记了加“force”了;

 (2)发现modelsim中打印的信息中,写到DDR3的数据为“xxx”。经过查找波形图,发现top模块内的mask信号为不定态,到top模块的代码中发现,因为信号命名的问题,掩码没有信号输入。

  (3)在data_req为0的时候,数据还是依然递增,但实际在此时数据是不需要的,所以数据不应该递增,而是应该保持;到tb文件中将产生数据的task-endtask语句进行了更改,加入了判断条件;

(4)应注意信号是先赋值再检测时钟上升沿还是相反,将导致波形不一样哦。先检测时钟沿再赋值可能会有延迟哦。

五、DDR3 SDRAM 控制器IP核的读

1. 读的实现与写非常相似,读的控制模块框图如图5-1所示。

图5-1 读控制模块框图

 从图中不难发现,他与写模块只是在数据相关的信号处理上不一样,其他均类似。

2. 由于P核DDR3的PHY与用户端的时钟速率设置的4:1模式,所以app_rd_data_valid信号与app_rd_data_end信号是一样的。

3. 先有读命令再有读数据。

4. app_en拉低的条件是读命令发完了,所以要有命令计数器,用来判断当IP核控制执行达到设计要求的读数据后,作为判断条件之一将app_en拉低。

5. rd_end的产生需要有数据计数器,数据计数器用来判断读出的数据是否满足设计要求。

6.例化到顶层模块,注意要将写控制的相关代码先注释掉,因为此刻还没有仲裁模块,有些信号是读、写共用的,没有仲裁模块的话就乱套了。就像十字路口没有红绿灯。

7.编写测试文件,仿真调试。

六、DDR3 SDRAM 控制器IP核的仲裁

1.该部分主要控制IP核的读写,决定什么时候进行写操作,什么时候进行读操作,以保证读、写不会冲突。为此,我们设计的仲裁模块,有限状态机如图6-1所示。

图6-1 仲裁有限状态机

2.  需要输入信号rd_req和wr_req(由tb文件产生)、rd_end和wr_end,输出信号rd_cmd_start和wr_cmd_start。

3.文件步骤和前面的读写相同,仲裁代码实现也相对简单,这里介绍一下将仲裁模块例化到top顶层后信号的调整和连接,tb文件的书写:

  (1)此时读写共用的信号有:命令、地址、使能、准备信号,在这四个信号中,前三个是DDR3_ctrl的输入信号,最后一个是输出信号。输出信号rdy可以“扇出”,分别给两个读、写两个模、块用,但是输入信号不可以读、写共用。因此,应分别定义读、写的命令、地址、使能信号,然后用按位或的方式输入给IP核。

assign app_en = app_rd_en | app_wr_en;
assign app_addr = app_rd_addr | app_wr_addr;
assign app_cmd = (app_wr_en == 1'b1)?app_wr_cmd:app_rd_cmd;

(2) tb文件之前是产生rd_cmd_start 或 wr_cmd_start 信号来激活相应的读、写模块。此时,我们需要产生rd_req和wr_req信号(我们设计写请求优先),由仲裁模块产生rd_cmd_start 或 wr_cmd_start 信号来激活相应的读、写模块。

注:在写tb文件时候,要先定义信号,然后才可以在initial语句中对该信号进行操作,否则仿真时候会报错相关信号未定义。

(3)可在tb中加入判断读回来的数据是否和写进去的数据相同的信号,并且使用"$display"语句打印不相同数据的个数。该信号在判断时,一定要注意再读数据有效的时候再判断,即要注意ra_data_valid信号的高低。

(4)进行仿真调试。

七、总结

1.要注意IP核DDR3的PHY与用户端的时钟速率设置4:1模式和2:1模式是不一样的,这将会影响写模块的app_wdf_wren和app_wdf_end信号、读模块的app_rd_data_valid 和 app_rd_data_end信号是否一样。

2.注意写入数据的位宽(128bit),ddr3的数据位宽(16bit),突发长度(8)之间的关系,以确定地址的增量。

3.写模块要选择合适的写数据和写命令的先后关系(先数据后命令或者数据命令同时)。

4.这里面的时钟要注意,FPGA的时钟,IP核需要和输出的时钟。

5.注意读、写模块共用的信号可以由IP核输出后进行扇出,但是不能合并输入到IP核。

6.注意信号之间的配合,在开始设计前,应仔细查阅官方文档,理解每个信号及之间的相互配合关系,这个至关重要。要学会看官方文档。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敲敲打打在创造

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值