DDR2(1):Quartus DDR2 IP 官方例程仿真

  DDR2难度比 SDRAM 复杂,自己写控制器不现实,直接用 IP 核比较靠谱。本篇博客记录一下 QuartusII 13.0 软件下的 DDR2 IP 核的官方例程仿真。

 

注意事项

1、关闭 Windows 的防火墙和电脑里的各种奇葩电脑管家。

2、以“管理员身份”打开 Quartus II 13.0。

3、所建工程要和 Quartus II 13.0 的安装盘符不同。

4、DDR2 IP 创建于工程目录下,否则仿真出错。

 

一、建工程

建立工程,命名为:DDR2_test,不引入任何 .v 文件。

 

二、IP调用

1、 打开 IP 创建界面:Tools ---> MegaWizard Plug-in Menager。

2、找到 DDR2 IP 并命名。

DDR2(1):Quartus DDR2 IP 官方例程仿真

 

3、点击 OK,等待约 10 秒则会弹出 IP 核配置界面。

4、若 IP 核界面显示不完整,可查看文档《小梅哥DDR2简明教程》寻找解决办法。

5、设置 IP 参数,先设置第 1 个界面。

DDR2(1):Quartus DDR2 IP 官方例程仿真

6、一路 next,直到 EDA 选项界面,勾选 Generate Simulation model,生成仿真模型。

DDR2(1):Quartus DDR2 IP 官方例程仿真

7、点击 Finish,等待 1 分钟,生成 IP 完毕。如果等了 3 分钟还未生成,表明生成 IP 失败,请删除工程,检查注意事项后重新操作。

 

三、添加例程

1、点击 Quartus II 界面的 File,将例程添加进来。

(1)DDR2_example_top.v

(2)DDR2_example_driver.v

2、将 DDR2_example_top 右键设为顶层模块。

DDR2(1):Quartus DDR2 IP 官方例程仿真

3、代码解释

  例程可以帮我们理解 DDR2 IP 的使用,具体的解释可以查看设计文档《emi_ddr_ug.pdf》》。生成的代码有些乱,注释很少,我稍微整理了一下:

  1 //**************************************************************************
  2 // *** 名称 : DDR2_example_top.v
  3 // *** 作者 : xianyu_FPGA
  4 // *** 博客 : https://www.cnblogs.com/xianyufpga/
  5 // *** 日期 : 2020-6-9
  6 // *** 工具 : Quartus 13.0
  7 // *** 芯片 : Cyclone IV E
  8 // *** 型号 : EP4CE30F23C6
  9 // *** 描述 : DDR2_IP官方仿真例程的顶层模块
 10 //**************************************************************************
 11 
 12 module DDR2_example_top
 13 //========================< 端口 >==========================================
 14 (
 15 //inputs --------------------------------------------
 16 input   wire                clock_source            , //时钟
 17 input   wire                global_reset_n          , //复位
 18 //outputs -------------------------------------------
 19 output  wire    [ 15: 0]    mem_addr                , //DDR2地址总线
 20 output  wire    [  2: 0]    mem_ba                  , //DDR2组地址总线
 21 output  wire                mem_cas_n               , //DDR2列地址选择
 22 output  wire                mem_cke                 , //DDR2时钟使能
 23 inout   wire                mem_clk                 , //DDR2时钟
 24 inout   wire                mem_clk_n               , //DDR2时钟反相
 25 output  wire                mem_cs_n                , //DDR2片选
 26 output  wire    [  1: 0]    mem_dm                  , //DDR2掩码
 27 inout   wire    [ 15: 0]    mem_dq                  , //DDR2数据总线
 28 inout   wire    [  1: 0]    mem_dqs                 , //DDR2数据源同步
 29 output  wire                mem_odt                 , //DDR2片内终止控制
 30 output  wire                mem_ras_n               , //DDR2行地址选择
 31 output  wire                mem_we_n                , //DDR2写使能
 32 output  wire                pnf                     , //数据正确指示(pass not fail)
 33 output  wire    [  3: 0]    pnf_per_byte            , //数据正确指示(字节)
 34 output  wire                test_complete           , //DDR2测试完成指示
 35 output  wire    [  7: 0]    test_status               //DDR2测试状态
 36 );
 37 //========================< 连线 >==========================================
 38 wire    [  0: 0]            cs_n                    ;
 39 wire                        local_burstbegin_sig    ;
 40 wire                        mem_aux_full_rate_clk   ;
 41 wire                        mem_aux_half_rate_clk   ;
 42 wire    [ 27: 0]            mem_local_addr          ;
 43 wire    [  3: 0]            mem_local_be            ;
 44 wire    [  9: 0]            mem_local_col_addr      ;
 45 wire                        mem_local_cs_addr       ;
 46 wire    [ 31: 0]            mem_local_rdata         ;
 47 wire                        mem_local_rdata_valid   ;
 48 wire                        mem_local_read_req      ;
 49 wire                        mem_local_ready         ;
 50 wire    [  2: 0]            mem_local_size          ;
 51 wire    [ 31: 0]            mem_local_wdata         ;
 52 wire                        mem_local_write_req     ;
 53 wire                        phy_clk                 ;
 54 wire                        reset_phy_clk_n         ;
 55 wire                        tie_high                ;
 56 wire                        tie_low                 ;
 57 //==========================================================================
 58 //==                        code
 59 //==========================================================================
 60 assign mem_cs_n = cs_n; //多次一举,直接连线mem_cs_n即可
 61 assign tie_high = 1'b1; //拉高
 62 assign tie_low  = 1'b0; //拉低
 63 //==========================================================================
 64 //==                        DDR2 IP
 65 //==========================================================================
 66 DDR2 DDR2_inst
 67 (
 68     .aux_full_rate_clk      (mem_aux_full_rate_clk  ), //全速率时钟
 69     .aux_half_rate_clk      (mem_aux_half_rate_clk  ), //半速率时钟
 70     .global_reset_n         (global_reset_n         ), //全局异步复位
 71     //-----------------------------------------------
 72     .local_address          (mem_local_addr         ), //用户_地址总线
 73     .local_be               (mem_local_be           ), //用户_字节使能标志
 74     .local_burstbegin       (local_burstbegin_sig   ), //用户_突发起始
 75     .local_init_done        (                       ), //用户_初始化完成
 76     .local_rdata            (mem_local_rdata        ), //用户_读数据总线
 77     .local_rdata_valid      (mem_local_rdata_valid  ), //用户_读数据有效
 78     .local_read_req         (mem_local_read_req     ), //用户_读数据请求
 79     .local_ready            (mem_local_ready        ), //用户_读写请求被接收指示
 80     .local_refresh_ack      (                       ), //用户_刷新请求
 81     .local_size             (mem_local_size         ), //用户_突发大小
 82     .local_wdata            (mem_local_wdata        ), //用户_写数据总线
 83     .local_write_req        (mem_local_write_req    ), //用户_写数据请求
 84     //-----------------------------------------------
 85     .mem_addr               (mem_addr[15 : 0]       ), //DDR2地址总线
 86     .mem_ba                 (mem_ba                 ), //DDR2组地址总线
 87     .mem_cas_n              (mem_cas_n              ), //DDR2列地址选择
 88     .mem_cke                (mem_cke                ), //DDR2时钟使能
 89     .mem_clk                (mem_clk                ), //DDR2时钟
 90     .mem_clk_n              (mem_clk_n              ), //DDR2时钟反相
 91     .mem_cs_n               (cs_n                   ), //DDR2片选
 92     .mem_dm                 (mem_dm[1 : 0]          ), //DDR2掩码
 93     .mem_dq                 (mem_dq                 ), //DDR2数据总线
 94     .mem_dqs                (mem_dqs[1 : 0]         ), //DDR2数据源同步
 95     .mem_odt                (mem_odt                ), //DDR2片内终止控制
 96     .mem_ras_n              (mem_ras_n              ), //DDR2行地址选择
 97     .mem_we_n               (mem_we_n               ), //DDR2写使能
 98     //-----------------------------------------------
 99     .phy_clk                (phy_clk                ), //DDR2工作时钟
100     .pll_ref_clk            (clock_source           ), //IP核中的PLL输入时钟
101     .reset_phy_clk_n        (reset_phy_clk_n        ), //IP核提供的复位
102     .reset_request_n        (                       ), //IP核中的PLL锁定
103     .soft_reset_n           (tie_high               )  //全局异步复位信号(不复位PLL)
104 );
105 //==========================================================================
106 //==    连接列地址位,因为2:1的数据速率,从示例驱动程序输出中删除1位
107 //==========================================================================
108 assign mem_local_addr[8 : 0] = mem_local_col_addr[9 : 1];
109 //==========================================================================
110 //==                    DDR2 控制器
111 //==========================================================================
112 DDR2_example_driver driver
113 (
114     .clk                    (phy_clk                ), //DDR2工作时钟
115     .local_bank_addr        (mem_local_addr[27 : 25]), //用户_地址总线
116     .local_be               (mem_local_be           ), //用户_字节使能标志
117     .local_burstbegin       (local_burstbegin_sig   ), //用户_突发起始
118     .local_col_addr         (mem_local_col_addr     ), //用户_地址总线
119     .local_cs_addr          (mem_local_cs_addr      ), //未用到
120     .local_rdata            (mem_local_rdata        ), //用户_读数据总线
121     .local_rdata_valid      (mem_local_rdata_valid  ), //用户_读数据有效
122     .local_read_req         (mem_local_read_req     ), //用户_读数据请求
123     .local_ready            (mem_local_ready        ), //用户_读写请求被接收指示
124     .local_row_addr         (mem_local_addr[24 : 9] ), //用户_地址总线
125     .local_size             (mem_local_size         ), //用户_突发大小
126     .local_wdata            (mem_local_wdata        ), //用户_写数据总线
127     .local_write_req        (mem_local_write_req    ), //用户_写数据请求
128     .pnf_per_byte           (pnf_per_byte[3 : 0]    ), //数据正确指示(字节)
129     .pnf_persist            (pnf                    ), //数据正确指示
130     .reset_n                (reset_phy_clk_n        ), //IP核提供的复位
131     .test_complete          (test_complete          ), //DDR2测试完成指示
132     .test_status            (test_status            )  //DDR2测试的运行状态
133 );
134 
135 
136 endmodule

 

 

四、仿真搭建

1、Modelsim软件的路径设置,一次设置好,以后就不用重复设置了。打开Quartus ii,点击Tools --- Options --- EDA Tool Optinons,将modelsim的安装路径填写进去。我这用的是QuestaSim,和Modelsim是完全没有区别的。为了防止遗漏,我把下面三个位置都填上:

DDR2(1):Quartus DDR2 IP 官方例程仿真

2、Quartus ii关联Modelsim,一开始建立工程时就可以设置,如果忘记了或者设置错了也可以再次更改。点击Assignments --- Setings --- Eda Tool Setings,将仿真工具选择好即可。(我的是QuastaSim,就填的QuastaSim)

DDR2(1):Quartus DDR2 IP 官方例程仿真

3、点击Assignments --- Setings --- Eda Tool Setings下的simulation,将Tool name选择好,然后点击Compile testbench,之后点击Test Benches。

DDR2(1):Quartus DDR2 IP 官方例程仿真

4、填写 New Test Bench Settings,添加仿真文件。

(1)DDR2_mem_model.v,DDR2 仿真模型;

(2)DDR2_example_top_tb,DDR2 仿真文件;

DDR2(1):Quartus DDR2 IP 官方例程仿真

5、回到 Quartus II 界面,点击 RTL Simulation 执行仿真。

DDR2(1):Quartus DDR2 IP 官方例程仿真

 

五、波形展现

  经过一小段时间的等待,波形就出来了。

DDR2(1):Quartus DDR2 IP 官方例程仿真

DDR2(1):Quartus DDR2 IP 官方例程仿真

 

六、补充说明

  如果使用的 Quartus II 是13.0 以上的版本,在执行仿真这一步会报错: DDR2(1):Quartus DDR2 IP 官方例程仿真   “仿真需要调用一个叫 cycloneiii_ver 的库,结果找不到这个库,为啥找不到呢?可能这个 IP 核的工程模型是基于 cycloneiii 器件设计的,仿真的时候默认还是调用 cyclone iii 的器件模型,但是从 Quartus II 13.0 以后,Quartus II 软件已经不再支持 cyclone iii 软件,里面也不再提供 cyclone iii 的器件模型,因此仿真时候无法找到这个模型,当然无法开始仿真了。” ——小梅哥   小梅哥没有给出解决办法,但是看到一篇博客里记录了 QuartusII 15.0 仿真 DDR2 官方例程的全过程,链接如下:https://blog.csdn.net/linker00/article/details/98034776  

参考资料:小梅哥DDR2简明教程.pdf

 

上一篇:2020最新java面试题及答案(三十七)


下一篇:Linux下解决centos频繁死机的缓存清理脚本