调取 DDR3 IP核后,是不能直接进行读写测试的,必须先进行初始化操作,对 IP 核进行校验。本篇采用 Modelsim 软件配合 DDR3 IP核生成的仿真模型,搭建出 IP核的初始化过程。

一、顶层文件

1、生成 DDR3 IP 核后,在 Source 界面空白处右键点击 Add Source,添加顶层文件。

2、在 DDR3_HDMI\DDR3_HDMI.srcs\sources_1\ip\ddr3_ctrl\ddr3_ctrl\user_design\rtl\ddr3_ctrl.v 可得到 top_ddr3_hdmi 需要的输入输出端口,将其复制过来。

//========================< 端口 >==========================================
(
//system ----------------------------------------
input wire sclkin , //50Mhz
input wire srst_n , //复位,低电平有效
//DDR3 ------------------------------------------
inout wire [:] ddr3_dq ,
inout wire [ :] ddr3_dqs_n ,
inout wire [ :] ddr3_dqs_p ,
output wire [:] ddr3_addr ,
output wire [ :] ddr3_ba ,
output wire ddr3_ras_n ,
output wire ddr3_cas_n ,
output wire ddr3_we_n ,
output wire ddr3_reset_n ,
output wire [ :] ddr3_ck_p ,
output wire [ :] ddr3_ck_n ,
output wire [ :] ddr3_cke ,
output wire [ :] ddr3_cs_n ,
output wire [ :] ddr3_dm ,
output wire [ :] ddr3_odt
);

3、对顶层模块进行编写,可以进入 IP Source 的 ddr3_ctrl.veo文件找到接口复制过来例化,并根据需求更改部分信号,仿真时希望app接口不工作,所有输入接口连接为 0

//DDR3_IP核 -----------------------------------------------------------------
ddr3_ctrl u_ddr3_ctrl //输入为200Mhz,芯片需400Mhz,内部速率为4:1 = 100Mhz
(
// Memory interface ports ----------------------------------------
.ddr3_addr (ddr3_addr ), // output [13:0]
.ddr3_ba (ddr3_ba ), // output [ 2:0]
.ddr3_cas_n (ddr3_cas_n ), // output
.ddr3_ck_n (ddr3_ck_n ), // output
.ddr3_ck_p (ddr3_ck_p ), // output
.ddr3_cke (ddr3_cke ), // output
.ddr3_ras_n (ddr3_ras_n ), // output
.ddr3_reset_n (ddr3_reset_n ), // output
.ddr3_we_n (ddr3_we_n ), // output
.ddr3_dq (ddr3_dq ), // inout [15:0]
.ddr3_dqs_n (ddr3_dqs_n ), // inout [ 1:0]
.ddr3_dqs_p (ddr3_dqs_p ), // inout [ 1:0]
.init_calib_complete (init_calib_complete ), // output
.ddr3_cs_n (ddr3_cs_n ), // output
.ddr3_dm (ddr3_dm ), // output [ 1:0]
.ddr3_odt (ddr3_odt ), // output
// Application interface ports -----------------------------------
.app_addr ( ), // input [27:0]
.app_cmd ( ), // input [ 2:0]
.app_en ( ), // input
.app_wdf_data ( ), // input [127:0]
.app_wdf_end ( ), // input
.app_wdf_wren ( ), // input
.app_rd_data ( ), // output [127:0]
.app_rd_data_end ( ), // output
.app_rd_data_valid ( ), // output
.app_rdy ( ), // output
.app_wdf_rdy ( ), // output
.app_sr_req ( ), // input
.app_ref_req ( ), // input
.app_zq_req ( ), // input
.app_sr_active ( ), // output
.app_ref_ack ( ), // output
.app_zq_ack ( ), // output
.ui_clk ( ), // output 100Mhz
.ui_clk_sync_rst ( ), // output
.app_wdf_mask ( ), // input [15:0]
// System Clock Ports --------------------------------------------
.sys_clk_i (sysclk ), // input 200Mhz
.sys_rst (srst_n ) // input 系统复位
);

4、调取 DDR3 IP 核时,选择了对此 IP 核输入一个200 Mhz 的时钟,由于板卡晶振生成的时钟为 50Mhz,所以还得用一个 IP 核来生出 200 Mhz 时钟。

5、生成时钟后同样找到 .veo 文件接口复制过来例化。

//时钟_IP核 ----------------------------------------------------------------
ddr3_clk_gen u_ddr3_clk_gen
(
.clk_in1 (sclkin ), // input clk_in1
.clk_out1 (sysclk ) // output clk_out1
);

7、有几个信号是我们需要观察的,用 wire 引出来吧。

//========================< 连线 >==========================================
//PLL -------------------------------------------
wire sysclk ;
// ddr3 ip --------------------------------------
wire app_rdy ;
wire app_wdf_rdy ;
wire app_en ;
wire [:] app_addr ;
wire [ :] app_cmd ;
wire [:] app_wdf_mask ;
wire app_wdf_wren ;
wire [:] app_wdf_data ;
wire app_wdf_end ;
wire [:] app_rd_data ;
wire app_rd_data_valid ;
wire app_rd_data_end ;
wire ui_clk ;
wire ui_clk_sync_rst ;
wire init_calib_complete ;

二、测试文件

1、在 Simulation Sources 右键选择 Add Sources,创建 testbench 文件。

2、首先还是把输入输出接口和 top 模块接口在 testbench 中写好。

 `timescale 1ns/1ps  //时间精度
`define Clock //时钟周期 module top_ddr3_hdmi_tb;
//========================< 端口 >==========================================
reg clk ;
reg rst_n ;
wire [:] ddr3_dq ;
wire [ :] ddr3_dqs_n ;
wire [ :] ddr3_dqs_p ;
wire [:] ddr3_addr ;
wire [ :] ddr3_ba ;
wire ddr3_ras_n ;
wire ddr3_cas_n ;
wire ddr3_we_n ;
wire ddr3_reset_n ;
wire [ :] ddr3_ck_p ;
wire [ :] ddr3_ck_n ;
wire [ :] ddr3_cke ;
wire [ :] ddr3_cs_n ;
wire [ :] ddr3_dm ;
wire [ :] ddr3_odt ; //==========================================================================
//== 模块例化
//==========================================================================
//顶层模块
top_ddr3_hdmi u_top_ddr3_hdmi
(
.ddr3_dq (ddr3_dq ),
.ddr3_dqs_n (ddr3_dqs_n ),
.ddr3_dqs_p (ddr3_dqs_p ),
.ddr3_addr (ddr3_addr ),
.ddr3_ba (ddr3_ba ),
.ddr3_ras_n (ddr3_ras_n ),
.ddr3_cas_n (ddr3_cas_n ),
.ddr3_we_n (ddr3_we_n ),
.ddr3_reset_n (ddr3_reset_n ),
.ddr3_ck_p (ddr3_ck_p ),
.ddr3_ck_n (ddr3_ck_n ),
.ddr3_cke (ddr3_cke ),
.ddr3_cs_n (ddr3_cs_n ),
.ddr3_dm (ddr3_dm ),
.ddr3_odt (ddr3_odt ),
.sclkin (clk ),
.srst_n (rst_n )
);

3、DDR3 控制器非常复杂,手写 testbench 是非常困难的。我们上一讲调取 DDR3 IP 核时说过,它已经生成了仿真模型供我们测试。位置在 DDR3_HDMI\DDR3_HDMI.srcs\sources_1\ip\ddr3_ctrl\ddr3_ctrl\example_design\sim,ddr3_model.sv 和 ddr3_model_parameters.vh 即是我们需要的仿真模型,将其复制到 DDR3_HDMI\DDR3_HDMI.srcs\sim_1\new 中,和 top_ddr3_hdmi_tb 文件放在一起。此外还可以看到刚刚那个文件夹中有一个 sim_tb_top 文件,打开它翻到500多行,即可看到该仿真模型的接口模块,我们将其复制到 testbench 中,并根据此次设计情况,更改部分参数。

 //仿真模型
ddr3_model u_ddr3_model
(
.rst_n (ddr3_reset_n ),
.ck (ddr3_ck_p ),
.ck_n (ddr3_ck_n ),
.cke (ddr3_cke ),
.cs_n (ddr3_cs_n ),
.ras_n (ddr3_ras_n ),
.cas_n (ddr3_cas_n ),
.we_n (ddr3_we_n ),
.dm_tdqs ({ddr3_dm[],ddr3_dm[]} ), //ddr3_dm为2位
.ba (ddr3_ba ),
.addr (ddr3_addr ),
.dq (ddr3_dq[:] ), //ddr3_dq为16位
.dqs ({ddr3_dqs_p[],ddr3_dqs_p[]} ), //ddr3_dqs_p为2位
.dqs_n ({ddr3_dqs_n[],ddr3_dqs_n[]} ), //ddr3_dqs_n为2位
.tdqs_n ( ),
.odt (ddr3_odt )
);

3、此外还需要产生一个 50 Mhz 时钟和低电平有效的复位信号。

 //==========================================================================
//== 时钟信号和复位信号
//==========================================================================
initial begin
clk = ;
forever
#(`Clock/) clk = ~clk;
end initial begin
rst_n = ; #(`Clock*+);
rst_n = ;
end

4、回到 Vivado,发现仿真模型文件已经出现了,但是处于问号状态,我们选中它,右键 Add Sources,将 ddr3_model.sv 和 ddr3_model_parameters.vh 添加进来即可。

三、启动 Modelsim 验证 DDR3 IP核

1、使用 Modelsim 进行仿真前,需要先编译 Vivado 和 Modelsim 之间的关联库,具体步骤请另行搜索。

2、点击 Vivado 的 Setting 进行设置,Target simulator 选择 ModelSim Simulator,仿真顶层文件选择第二步的仿真文件,仿真库则自动定位好了。

3、点击 Vivado 左侧菜单 Run Simulation --- Run Behavioral Simulation,Modelsim 就自动打开仿真了。

4、选取信号,跑一段时间,可以看到时钟信号和复位信号正常,  init_calib_complete 信号在拉低一段时间后拉高,表面本次 DDR3 IP核验证成功。

以上。

参考资料:威三学院FPGA教程

最新文章

  1. InnoDB体系结构学习笔记
  2. [AngularJS] AngularJS系列(5) 中级篇之动画
  3. UITableViewController和XML解析还有地图的简单结合
  4. js动态生成二维码图片
  5. RTX二次开发(一)(基于ASP.NET)
  6. 7.js模式-装饰者模式
  7. 疯狂java学习笔记之面向对象(八) - static和final
  8. HDU 3844 Mining Your Own Business
  9. size_t和size_type类型
  10. ASP.NET MVC 解决区域和全局控制器同名的问题
  11. 从零开始学习前端开发 — 14、CSS3变形基础
  12. linux makefile字符串操作函数 替换subst、模式替换patsubst、去首尾空格strip、查找字符串findstring、过滤filter、反过滤filter-out、排序函数sort、取单词word、取单词串wordlist、个数统计words
  13. 解决AspNet Zero Core 5.0.1无法运行的问题
  14. iOS开发——iOS国际化 APP内语言切换
  15. netstat、ps、top 、kill 命令备忘
  16. 【C++】链表回环检测
  17. eclipse中运行tomcat提示端口被占的4种解决方案
  18. Q他中的乱码再理解
  19. Oracle数据库日期范围查询的两种实现方式
  20. Servlet实例开发---学生管理系统

热门文章

  1. vue工作原理分析
  2. flask项目结构
  3. Redis内存模型(1):内存统计及划分
  4. Nginx Rewrite相关功能-防盗链
  5. Nginx 高级配置-压缩功能
  6. linux查看磁盘类型(是否SSD盘)
  7. destoon开发笔记-调取资讯标题图
  8. nginx secure_link_module 访问包含
  9. ajax post 提交无法进入controller 请求200
  10. Super Fish