DDR2,全称 Double Data Rate 2 SDRAM,即第二代双倍数据速率同步动态随机存取存储器。它属于 SDRAM 家族的存储器产品,提供了相较于 DDR SDRAM 更高的运行效能与更低的电压,是 DDR SDRAM 的后继者,虽然 DDR2 和 DDR 都采用了在时钟的.上升沿和下降沿同时进行数据传输的基本方式,但是 DDR2 拥有两倍于 DDR 的预读取系统命令数据的能力(DDR2 4bit预读,DDR 2bit预读)。也就是说,在同样100MHz 的工作频率下,DDR 的实际频率为 200MHz,而 DDR2 则可以达到 400MHz。 DDR2 难度比 SDRAM 复杂,直接用 IP 核比较靠谱。本篇博客记录一下 QuartusII 13.0 软件下的 DDR2 IP 核的官方例程仿真。
注意事项 1、关闭 Windows 的防火墙和电脑里的各种电脑管家。 2、以“管理员身份”打开 Quartus II 13.0。 3、所建工程要和 Quartus II 13.0 的安装盘符不同。 4、DDR2 IP 创建于工程目录下或其子文件,否则仿真出错。 5、如果无论如何都失败,打开任务管理器,将下面这个鬼东西关闭即可。
一、建工程 建立文件夹 DDR2_test,管理员身份打开 Quartus II,创建工程 DDR2_test,不引入任何 .v 文件。
二、IP调用 打开 IP 创建界面:Tools ---> MegaWizard Plug-in Menager。找到 DDR2 IP 并命名。 1、Memory Settings 若 IP 核界面显示不完整,可查看文档《小梅哥DDR2简明教程》寻找解决办法。先设置第 1 个界面:Memory Seting。 (1)General Settings 即页面左上角,这部分主要是配置驱动 DDR2 存储器的通用设置。
(2)Memory Presets 即页面右下角,这部分主要是选择 DDR2 存储器芯片型号和设置相关参数。如果加载列表中没有我们想要的芯片型号,那么可以点击【Load Preset】选项,通过选择对应的 .xml 文件就能把定制的芯片参数加载到列表中。选好芯片型号后,在右边有个按钮【Modify parameters】,点进去可以设置所选芯片的参数集,如下所示: 整个参数设置分 3 组,分别是 Memory Attributes、Memory Initialization Options 和 Memory Timing Parameters,其中灰色部分代表的是和存储器直接相关的参数,修改这些参数会导致生成一个新的芯片型号参数集。 ① Memory Attributes
② Memory Initialization Options
③ Memory Timing Parameters
2、PHY Settings 这个标签我们一般不用改动。可以看出,这里设置的是 ALTEMEMPHY 有关的参数。对于 cyclone IV E 系列芯片,在 PHY Settings 页面下只有两项可以修改:
3、Board Settings 这个标签我们一般不用改动。可以看出,这里主要是设置一些板级参数来消除对时序的影响。
4、Controller Settings 这个标签我们一般不用改动。可以看出,这里设置的是控制器的参数。我们一般默认选择的是:High Performance Controller II,第二代,性能更好。
5、EDA
从该页面中可以看出,如果我们想要仿真 DDR2 IP 核,那么就需要用到 altera_mf 、220model 和 sgate 这三个仿真库。Generate simulation model 选项可以选择是否要生成这3个文件,Generate netlist 选项可以选择是否生成网表文件,如果用户想用第三方EDA综合工具来综合设计的文件,Quartus可以为该综合工具提供网表文件,用来评估时序和资源利用率。这里需要注意的是,并不是所有的第三方EDA工具都支持。我们需要仿真,因此勾选。 6、Summary 总结页面,不用管。 点击 Finish,等待 1 分钟,生成 IP 完毕。如果等了 3 分钟还未生成,表明生成 IP 失败,请删除工程,检查注意事项后重新操作。
三、添加例程 1、点击 Quartus II 界面的 File,将例程添加进来。 (1)DDR2_example_top.v (2)DDR2_example_driver.v 2、将 DDR2_example_top 右键设为顶层模块。 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 //system -------------------------------------------- 16 input wire clock_source , //时钟 17 input wire global_reset_n , //复位 18 //DDR2 ---------------------------------------------- 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 //DDR2_test ----------------------------------------- 33 output wire pnf , //数据正确指示(pass not fail) 34 output wire [ 3: 0] pnf_per_byte , //数据正确指示(字节) 35 output wire test_complete , //DDR2测试完成指示 36 output wire [ 7: 0] test_status //DDR2测试状态 37 ); 38 //========================< 连线 >========================================== 39 wire cs_n ; 40 wire local_burstbegin_sig ; 41 wire mem_aux_full_rate_clk ; 42 wire mem_aux_half_rate_clk ; 43 wire [ 27: 0] mem_local_addr ; 44 wire [ 3: 0] mem_local_be ; 45 wire [ 9: 0] mem_local_col_addr ; 46 wire mem_local_cs_addr ; 47 wire [ 31: 0] mem_local_rdata ; 48 wire mem_local_rdata_valid ; 49 wire mem_local_read_req ; 50 wire mem_local_ready ; 51 wire [ 2: 0] mem_local_size ; 52 wire [ 31: 0] mem_local_wdata ; 53 wire mem_local_write_req ; 54 wire phy_clk ; 55 wire reset_phy_clk_n ; 56 wire tie_high ; 57 wire tie_low ; 58 //========================================================================== 59 //== code 60 //========================================================================== 61 assign mem_cs_n = cs_n; //多次一举,直接连线mem_cs_n即可 62 assign tie_high = 1'b1; //拉高 63 assign tie_low = 1'b0; //拉低 64 //========================================================================== 65 //== DDR2 IP 66 //========================================================================== 67 DDR2 DDR2_inst 68 ( 69 .aux_full_rate_clk (mem_aux_full_rate_clk ), //全速率时钟 70 .aux_half_rate_clk (mem_aux_half_rate_clk ), //半速率时钟 71 .global_reset_n (global_reset_n ), //全局异步复位 72 //----------------------------------------------- 73 .local_address (mem_local_addr ), //用户_地址总线 74 .local_be (mem_local_be ), //用户_字节使能标志 75 .local_burstbegin (local_burstbegin_sig ), //用户_突发起始 76 .local_init_done ( ), //用户_初始化完成 77 .local_rdata (mem_local_rdata ), //用户_读数据总线 78 .local_rdata_valid (mem_local_rdata_valid ), //用户_读数据有效 79 .local_read_req (mem_local_read_req ), //用户_读数据请求 80 .local_ready (mem_local_ready ), //用户_读写请求被接收指示 81 .local_refresh_ack ( ), //用户_刷新请求 82 .local_size (mem_local_size ), //用户_突发大小 83 .local_wdata (mem_local_wdata ), //用户_写数据总线 84 .local_write_req (mem_local_write_req ), //用户_写数据请求 85 //----------------------------------------------- 86 .mem_addr (mem_addr[15 : 0] ), //DDR2地址总线 87 .mem_ba (mem_ba ), //DDR2组地址总线 88 .mem_cas_n (mem_cas_n ), //DDR2列地址选择 89 .mem_cke (mem_cke ), //DDR2时钟使能 90 .mem_clk (mem_clk ), //DDR2时钟 91 .mem_clk_n (mem_clk_n ), //DDR2时钟反相 92 .mem_cs_n (cs_n ), //DDR2片选 93 .mem_dm (mem_dm[1 : 0] ), //DDR2掩码 94 .mem_dq (mem_dq ), //DDR2数据总线 95 .mem_dqs (mem_dqs[1 : 0] ), //DDR2数据源同步 96 .mem_odt (mem_odt ), //DDR2片内终止控制 97 .mem_ras_n (mem_ras_n ), //DDR2行地址选择 98 .mem_we_n (mem_we_n ), //DDR2写使能 99 //----------------------------------------------- 100 .phy_clk (phy_clk ), //DDR2工作时钟 101 .pll_ref_clk (clock_source ), //IP核中的PLL输入时钟 102 .reset_phy_clk_n (reset_phy_clk_n ), //IP核提供的复位 103 .reset_request_n ( ), //IP核中的PLL锁定 104 .soft_reset_n (tie_high ) //全局异步复位信号(不复位PLL) 105 ); 106 //========================================================================== 107 //== 连接列地址位,因为2:1的数据速率,从示例驱动程序输出中删除1位 108 //========================================================================== 109 assign mem_local_addr[8 : 0] = mem_local_col_addr[9 : 1]; 110 //========================================================================== 111 //== DDR2 控制器 112 //========================================================================== 113 DDR2_example_driver driver 114 ( 115 .clk (phy_clk ), //DDR2工作时钟 116 .local_bank_addr (mem_local_addr[27 : 25]), //用户_地址总线 117 .local_be (mem_local_be ), //用户_字节使能标志 118 .local_burstbegin (local_burstbegin_sig ), //用户_突发起始 119 .local_col_addr (mem_local_col_addr ), //用户_地址总线 120 .local_cs_addr (mem_local_cs_addr ), //未用到 121 .local_rdata (mem_local_rdata ), //用户_读数据总线 122 .local_rdata_valid (mem_local_rdata_valid ), //用户_读数据有效 123 .local_read_req (mem_local_read_req ), //用户_读数据请求 124 .local_ready (mem_local_ready ), //用户_读写请求被接收指示 125 .local_row_addr (mem_local_addr[24 : 9] ), //用户_地址总线 126 .local_size (mem_local_size ), //用户_突发大小 127 .local_wdata (mem_local_wdata ), //用户_写数据总线 128 .local_write_req (mem_local_write_req ), //用户_写数据请求 129 .pnf_per_byte (pnf_per_byte[3 : 0] ), //数据正确指示(字节) 130 .pnf_persist (pnf ), //数据正确指示 131 .reset_n (reset_phy_clk_n ), //IP核提供的复位 132 .test_complete (test_complete ), //DDR2测试完成指示 133 .test_status (test_status ) //DDR2测试的运行状态 134 ); 135 136 137 endmodule
四、仿真搭建 1、Modelsim 软件的路径设置。打开Quartus ii,点击Tools --- Options --- EDA Tool Optinons,将modelsim的安装路径填写进去。我这用的是QuestaSim,和Modelsim是完全没有区别的。为了防止遗漏,我把下面三个位置都填上: 2、Quartus ii 关联 Modelsim,一开始建立工程时就可以设置,如果忘记了或者设置错了也可以再次更改。点击Assignments --- Setings --- Eda Tool Setings,将仿真工具选择好即可。(我的是QuastaSim,就填的QuastaSim) 3、点击Assignments --- Setings --- EDA Tool Setings下的simulation,将 Tool name 选择好,然后点击 Compile testbench,之后点击Test Benches。 4、填写 New Test Bench Settings,添加仿真文件。 (1)DDR2_mem_model.v,DDR2 仿真模型; (2)DDR2_example_top_tb,DDR2 仿真文件; 5、回到 Quartus II 界面,综合编译后点击 RTL Simulation 执行仿真。 经过一小段时间的等待,波形就出来了。
五、上板看波形 上面只是仿真,要上板则增加几点注意事项。 1、选择自己板卡 DDR2 相符的型号 上面仿真时是看着小梅哥《小梅哥DDR2简明教程》做的,但是要上板时发现自己的 DDR2 型号和他的不一致,而且是两片 DDR2 一起用。选择自己的 DDR2 型号,点击 Modify parameter 对 DQ 和 Bank 参数进行修改一下,其他选项都一样,如下所示: 2、添加 tcl 电平标准文件 FPGA板卡是 3.3V,而 DDR2 是 1.8v,还有一些别的东西,都可以通过添加 tcl 文件实现。点击菜单栏 Tools --- Tcl Scripts,选择 DDR2_pin_assignments.tcl,Run 3、添加网表约束文件 点击菜单栏 Assignments --- Settings --- TimeQuest Timing Analyzer,照下图添加即可。 4、添加引脚约束文件 找到开发板原理图,将引脚位置填上去,大多开发板都会提供写好的引脚文件,复制到 qsf 文件中即可。 5、添加 SignalTapII ,编译,查看波形 波形出来了,说明我们操作成功!
六、补充说明 如果使用的 Quartus II 是13.0 以上的版本,在执行仿真这一步会报错:
“仿真需要调用一个叫 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参考资料: 1、小梅哥《DDR2简明教程》 2、锆石科技FPGA教程
|
|