DDR3_舊版(2):初始化


  調取 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  [15:0]        ddr3_dq             ,
inout   wire  [ 1:0]        ddr3_dqs_n          ,
inout   wire  [ 1:0]        ddr3_dqs_p          ,
output  wire  [13:0]        ddr3_addr           ,
output  wire  [ 2:0]        ddr3_ba             ,
output  wire                ddr3_ras_n          ,
output  wire                ddr3_cas_n          ,
output  wire                ddr3_we_n           ,
output  wire                ddr3_reset_n        ,
output  wire  [ 0:0]        ddr3_ck_p           ,
output  wire  [ 0:0]        ddr3_ck_n           ,
output  wire  [ 0:0]        ddr3_cke            ,
output  wire  [ 0:0]        ddr3_cs_n           ,
output  wire  [ 1:0]        ddr3_dm             ,
output  wire  [ 0:0]        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  [27:0]                app_addr            ;
wire  [ 2:0]                app_cmd             ;
wire  [15:0]                app_wdf_mask        ;
wire                        app_wdf_wren        ;
wire [127:0]                app_wdf_data        ;
wire                        app_wdf_end         ;
wire [127:0]                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 中寫好。

 1 `timescale 1ns/1ps  //時間精度
 2 `define    Clock 20 //時鍾周期
 3 
 4 module top_ddr3_hdmi_tb;
 5 //========================< 端口 >==========================================
 6 reg                         clk                             ;
 7 reg                         rst_n                           ;
 8 wire  [15:0]                ddr3_dq                         ;
 9 wire  [ 1:0]                ddr3_dqs_n                      ;
10 wire  [ 1:0]                ddr3_dqs_p                      ;
11 wire  [13:0]                ddr3_addr                       ;
12 wire  [ 2:0]                ddr3_ba                         ;
13 wire                        ddr3_ras_n                      ;
14 wire                        ddr3_cas_n                      ;
15 wire                        ddr3_we_n                       ;
16 wire                        ddr3_reset_n                    ;
17 wire  [ 0:0]                ddr3_ck_p                       ;
18 wire  [ 0:0]                ddr3_ck_n                       ;
19 wire  [ 0:0]                ddr3_cke                        ;
20 wire  [ 0:0]                ddr3_cs_n                       ;
21 wire  [ 1:0]                ddr3_dm                         ;
22 wire  [ 0:0]                ddr3_odt                        ;
23 
24 //==========================================================================
25 //==    模塊例化
26 //==========================================================================
27 //頂層模塊
28 top_ddr3_hdmi u_top_ddr3_hdmi
29 (
30     .ddr3_dq                (ddr3_dq                        ),
31     .ddr3_dqs_n             (ddr3_dqs_n                     ),
32     .ddr3_dqs_p             (ddr3_dqs_p                     ),
33     .ddr3_addr              (ddr3_addr                      ),
34     .ddr3_ba                (ddr3_ba                        ),
35     .ddr3_ras_n             (ddr3_ras_n                     ),
36     .ddr3_cas_n             (ddr3_cas_n                     ),
37     .ddr3_we_n              (ddr3_we_n                      ),
38     .ddr3_reset_n           (ddr3_reset_n                   ),
39     .ddr3_ck_p              (ddr3_ck_p                      ),
40     .ddr3_ck_n              (ddr3_ck_n                      ),
41     .ddr3_cke               (ddr3_cke                       ),
42     .ddr3_cs_n              (ddr3_cs_n                      ),
43     .ddr3_dm                (ddr3_dm                        ),
44     .ddr3_odt               (ddr3_odt                       ),
45     .sclkin                 (clk                            ),
46     .srst_n                 (rst_n                          )
47 );

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 中,並根據此次設計情況,更改部分參數。

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

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教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM