DDR3(2):IP核初始化

  调取 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 需要的输入输出端口,将其复制过来。

 1 module top_ddr3_hdmi
 2 //========================< 端口 >==========================================
 3 (
 4 // inout ----------------------------------------
 5 inout   wire  [15:0]        ddr3_dq             ,
 6 inout   wire  [ 1:0]        ddr3_dqs_n          ,
 7 inout   wire  [ 1:0]        ddr3_dqs_p          ,
 8 // output ---------------------------------------
 9 output  wire  [13:0]        ddr3_addr           ,
10 output  wire  [ 2:0]        ddr3_ba             ,
11 output  wire                ddr3_ras_n          ,
12 output  wire                ddr3_cas_n          ,
13 output  wire                ddr3_we_n           ,
14 output  wire                ddr3_reset_n        ,
15 output  wire  [ 0:0]        ddr3_ck_p           ,
16 output  wire  [ 0:0]        ddr3_ck_n           ,
17 output  wire  [ 0:0]        ddr3_cke            ,
18 output  wire  [ 0:0]        ddr3_cs_n           ,
19 output  wire  [ 1:0]        ddr3_dm             ,
20 output  wire  [ 0:0]        ddr3_odt            ,
21 // system ---------------------------------------
22 input   wire                sclkin              ,
23 input   wire                srst_n              
24 );

3、对顶层模块进行编写,可以进入 IP Source 的 ddr3_ctrl.veo文件找到接口复制过来例化,并根据需求更改部分信号。

 

 1 ddr3_ctrl u_ddr3_ctrl
 2 (
 3     // Memory interface ports -----------------------
 4     .ddr3_addr              (ddr3_addr              ),  // output [13:0]    ddr3_addr
 5     .ddr3_ba                (ddr3_ba                ),  // output [2:0]     ddr3_ba
 6     .ddr3_cas_n             (ddr3_cas_n             ),  // output           ddr3_cas_n
 7     .ddr3_ck_n              (ddr3_ck_n              ),  // output [0:0]     ddr3_ck_n
 8     .ddr3_ck_p              (ddr3_ck_p              ),  // output [0:0]     ddr3_ck_p
 9     .ddr3_cke               (ddr3_cke               ),  // output [0:0]     ddr3_cke
10     .ddr3_ras_n             (ddr3_ras_n             ),  // output           ddr3_ras_n
11     .ddr3_reset_n           (ddr3_reset_n           ),  // output           ddr3_reset_n
12     .ddr3_we_n              (ddr3_we_n              ),  // output           ddr3_we_n
13     .ddr3_dq                (ddr3_dq                ),  // inout [15:0]     ddr3_dq
14     .ddr3_dqs_n             (ddr3_dqs_n             ),  // inout [1:0]      ddr3_dqs_n
15     .ddr3_dqs_p             (ddr3_dqs_p             ),  // inout [1:0]      ddr3_dqs_p
16     .init_calib_complete    (init_calib_complete    ),  // output           init_calib_complete
17     .ddr3_cs_n              (ddr3_cs_n              ),  // output [0:0]     ddr3_cs_n
18     .ddr3_dm                (ddr3_dm                ),  // output [1:0]     ddr3_dm
19     .ddr3_odt               (ddr3_odt               ),  // output [0:0]     ddr3_odt
20     // Application interface ports ------------------
21     .app_addr               (app_addr               ),  // input [27:0]     app_addr
22     .app_cmd                (app_cmd                ),  // input [2:0]      app_cmd
23     .app_en                 (1'b0                   ),  // input            app_en
24     .app_wdf_data           (app_wdf_data           ),  // input [127:0]    app_wdf_data
25     .app_wdf_end            (1'b0                   ),  // input            app_wdf_end
26     .app_wdf_wren           (1'b0                   ),  // input            app_wdf_wren
27     .app_rd_data            (app_rd_data            ),  // output [127:0]   app_rd_data
28     .app_rd_data_end        (app_rd_data_end        ),  // output           app_rd_data_end
29     .app_rd_data_valid      (app_rd_data_valid      ),  // output           app_rd_data_valid
30     .app_rdy                (app_rdy                ),  // output           app_rdy
31     .app_wdf_rdy            (app_wdf_rdy            ),  // output           app_wdf_rdy
32     .app_sr_req             (1'b0                   ),  // input            app_sr_req
33     .app_ref_req            (1'b0                   ),  // input            app_ref_req
34     .app_zq_req             (1'b0                   ),  // input            app_zq_req
35     .app_sr_active          (app_sr_active          ),  // output           app_sr_active
36     .app_ref_ack            (app_ref_ack            ),  // output           app_ref_ack
37     .app_zq_ack             (app_zq_ack             ),  // output           app_zq_ack
38     .ui_clk                 (ui_clk                 ),  // output           ui_clk
39     .ui_clk_sync_rst        (ui_clk_sync_rst        ),  // output           ui_clk_sync_rst
40     .app_wdf_mask           (app_wdf_mask           ),  // input [15:0]     app_wdf_mask
41     // System Clock Ports ---------------------------
42     .sys_clk_i              (sysclk                 ),  // input            sys_clk_i 200Mhz
43     .sys_rst                (srst_n                 )   // input            sys_rst
44 );

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

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

1 ddr3_clk_gen u_ddr3_clk_gen
2 (
3     .clk_out1               (sysclk                 ),  // output           clk_out1
4     .clk_in1                (sclkin                 )   // input            clk_in1
5 );

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

1 //========================< 连线 >==========================================
2 wire                        sysclk              ;
3 wire                        init_calib_complete ;
4 wire                        ui_clk              ;
5 wire                        ui_clk_sync_rst     ;

二、测试文件

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

2、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 即是我们需要的仿真模型,将其接口在 testbench 中例化过来。

 1 ddr3_model u_ddr3_model
 2 (
 3     .rst_n                  (ddr3_reset_n                   ),
 4     .ck                     (ddr3_ck_p                      ),
 5     .ck_n                   (ddr3_ck_n                      ),
 6     .cke                    (ddr3_cke                       ),
 7     .cs_n                   (ddr3_cs_n                      ),
 8     .ras_n                  (ddr3_ras_n                     ),
 9     .cas_n                  (ddr3_cas_n                     ),
10     .we_n                   (ddr3_we_n                      ),
11     .dm_tdqs                ({ddr3_dm[1],ddr3_dm[0]}        ),
12     .ba                     (ddr3_ba                        ),
13     .addr                   (ddr3_addr                      ),
14     .dq                     (ddr3_dq[15:0]                  ),
15     .dqs                    ({ddr3_dqs_p[1],ddr3_dqs_p[0]}  ),
16     .dqs_n                  ({ddr3_dqs_n[1],ddr3_dqs_n[0]}  ),
17     .tdqs_n                 (                               ),
18     .odt                    (ddr3_odt                       )
19 );

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

 1 //==========================================================================
 2 //==    时钟信号和复位信号
 3 //==========================================================================
 4 initial begin
 5     clk = 0;
 6     forever
 7         #(`Clock/2) clk = ~clk;
 8 end
 9 
10 initial begin
11     rst_n = 0; #(`Clock*20+1);
12     rst_n = 1;
13 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教程

猜你喜欢

转载自www.cnblogs.com/xianyufpga/p/11784493.html