通过上 一节的学习已经能够实现通过ISE搭建DDR IP CORE并且顺利通例程的仿真,那么接下来的这一一节我们就要根据ISE给的Example 来搭建自己所需要的仿真平台。
第一:对ISE给定的Example 要有所了解,包括结构和内容;如图所示:其中docs 文件中是DDR IPCore的使用手册和指导文档;example_design存放的是ISE官方给出的仿真例程,即一个完整的DDR IP的工程,user_design 文件下存放的是与DDR IP 相关的一些文件。这里我们用到的example _design 文件多一些。
第二:开始搭建仿真平台;
(1)将上文提到的example _design 文件拷贝到 一个相对独立的路径下面,如下图所示;
(2)创建ISE工程,把创建的工程路径放到我们拷贝的example _ design 文件下。然后添加example_design->rtl文件下(包括rtl下子文件里面的所有)的所有.v文件;添加xample_design->par文件下的example_design.ucf 文件;添加example_design->sim->function文件下的(ddr3_model_c3.v仿真模型文件,ddr3_model_pararmeters_c3.v模型参数文件,sim_tb_top文件激励文件),点击MODESIM开始仿真
(2)仿真的时候会出现需要把,仿真模型的参数文件拷贝到example_design所在的文件夹下,(就是在色的仿真路径下),还会出现一些其他错误,对应的修改一下就好。仿真过后会出现一些错误,当出现TESTpassed时,说明搭建成功。
第三: 接下来就是搭建自己的所DDR工程了
(1)添加ddr_top.v文件。就添加在之前我们建好的USB工程当中,如下图所示。
(2)在这个ddr_top.v 中对DDR IPcore例化进来,就是加入mig_39_2.xco文件。找到其中的例化模板,复制到ddr_top.v 文件当中。如下图所示,其中包括ddr对一些参数的设置。
(3)例化DDR中对参数的设置如下;当然这些事工程自己生成的,你也可以更改一些,
1 mig_39_2 # ( 2 .C3_P0_MASK_SIZE(8), 3 .C3_P0_DATA_PORT_SIZE(64), 4 .C3_P1_MASK_SIZE(8), 5 .C3_P1_DATA_PORT_SIZE(64), 6 .DEBUG_EN(0), 7 .C3_MEMCLK_PERIOD(3200),//当前的时钟周期 8 .C3_CALIB_SOFT_IP("TRUE"), 9 .C3_SIMULATION("TRUE"),//仿真 10 .C3_RST_ACT_LOW(1),//复位信号的配置 11 .C3_INPUT_CLK_TYPE("SINGLE_ENDED"),//时钟模式 12 .C3_MEM_ADDR_ORDER("BANK_ROW_COLUMN"),//内存读取的顺序模式 13 .C3_NUM_DQ_PINS(16), 14 .C3_MEM_ADDR_WIDTH(13), 15 .C3_MEM_BANKADDR_WIDTH(3) 16 )
DDR的接口介绍;
(c3_calib_done), //全局完成初始化标志,在此信号没有拉高之前,不能对DDR3进行操作。,从代码中可以看出,DDR3的端口分成了两部分,分别是DDR3的芯片接口以及提供给用户的逻辑操作接口。
1 u_mig_39_2 ( 2 //DDR3 的接口 3 .c3_sys_clk (c3_sys_clk),//input DDR3的参考时钟 4 .c3_sys_rst_i (c3_sys_rst_i), //input DDR3的复位信号 5 6 .mcb3_dram_dq (mcb3_dram_dq), 7 .mcb3_dram_a (mcb3_dram_a), 8 .mcb3_dram_ba (mcb3_dram_ba), 9 .mcb3_dram_ras_n (mcb3_dram_ras_n), 10 .mcb3_dram_cas_n (mcb3_dram_cas_n), 11 .mcb3_dram_we_n (mcb3_dram_we_n), 12 .mcb3_dram_odt (mcb3_dram_odt), 13 .mcb3_dram_cke (mcb3_dram_cke), 14 .mcb3_dram_ck (mcb3_dram_ck), 15 .mcb3_dram_ck_n (mcb3_dram_ck_n), 16 .mcb3_dram_dqs (mcb3_dram_dqs), 17 .mcb3_dram_dqs_n (mcb3_dram_dqs_n), 18 .mcb3_dram_udqs (mcb3_dram_udqs), // for X16 parts 19 .mcb3_dram_udqs_n (mcb3_dram_udqs_n), // for X16 parts 20 .mcb3_dram_udm (mcb3_dram_udm), // for X16 parts 21 .mcb3_dram_dm (mcb3_dram_dm), 22 .mcb3_dram_reset_n (mcb3_dram_reset_n), 23 24 25 26 27 //sppourt for user 28 .c3_clk0 (c3_clk0),//output 输出给用户提供的 29 .c3_rst0 (c3_rst0),//output 输出给用户提供的 30 31 32 33 .c3_calib_done (c3_calib_done), //全局完成初始化标志 34 .mcb3_rzq ( mcb3_rzq ), 35 36 .mcb3_zio (mcb3_zio ), 37 38 //P0,p1表示两个用户会接口 39 /*********************command path****************************/ 40 .c3_p0_cmd_clk (c3_clk0 ), //命令FIFO的用户时钟。 FIFO信号是 在这个时钟的上升沿捕获。 41 .c3_p0_cmd_en (p0_cmd_en), //该高电平有效信号是用于写入的写入使能信号命令FIFO。 42 .c3_p0_cmd_instr (p0_cmd_instr), //当前指令的命令代码。 位0表示READ / WRITE选择,Bit 1为Auto预充电启用,位2代表刷新总是优先考虑 43 .c3_p0_cmd_bl (p0_cmd_bl), //当前用户字数的突发长度交易。 突发长度编码为0到63,代表1到64个用户词(例如,6'b00011 是一个突发长度4的交易)。 用户字宽等于端口宽度(例如,突发长度为3 64位端口传输3 x 64位用户字= 192位 总)。 44 /*当前事务的字节起始地址。地址 45 必须与端口大小对齐: 46 32位端口:低两位必须为0。 47 64位端口:低三位必须为0。 48 128位端口:低4位必须为0*/ 49 .c3_p0_cmd_byte_addr (p0_cmd_addr), 50 51 .c3_p0_cmd_empty ( ), //这个命令FIFO的高电平有效空标志 52 .c3_p0_cmd_full ( ), //此高电平有效输出是命令的man标志 53 54 /*********************write cmd****************************/ 55 .c3_p0_wr_clk (c3_clk0 ),//该信号是写数据FIFO的用户时钟 56 /*该高电平有效信号是写使能 57 用于写数据FIFO。它表明了 58 pX_wr_data上的值有效 59 加载到FIFO。数据已加载 60 pX_wr_clk的上升沿时 61 pX_wr_en = 1且pX_wr_full = 0。*/ 62 .c3_p0_wr_en (p0_wr_en), 63 .c3_p0_wr_mask (p0_wr_mask),//写数据的掩码, 64 /*写入要写入的数据值 65 数据FIFO并发送到内存。 PX_SIZE 66 可以是32位,64位或128位,具体取决于 67 端口配置*/ 68 .c3_p0_wr_data (p0_wr_data), 69 .c3_p0_wr_full ( ), //高有效的满信号 70 .c3_p0_wr_empty ( ),//高有效的空信号 71 /*写入数据FIFO的计数值。这个 72 输出表示有多少用户单词 73 在FIFO中(从1到64)。计数值为 74 0表示FIFO为空。这个信号 75 延迟的延迟比 76 pX_wr_empty标志。因此,FIFO 77 可能是空的或经历不足 78 即使计数不为0。*/ 79 .c3_p0_wr_count ( ), 80 .c3_p0_wr_underrun ( ),//高电平有效,欠载标志。 81 .c3_p0_wr_error ( ), 82 /*********************read cmd****************************/ 83 .c3_p0_rd_clk (c3_p0_rd_clk ),//该信号是du数据FIFO的用户时钟 84 .c3_p0_rd_en (c3_p0_rd_en ), 85 .c3_p0_rd_data (c3_p0_rd_data ), 86 .c3_p0_rd_full (c3_p0_rd_full ), 87 .c3_p0_rd_empty (c3_p0_rd_empty), 88 .c3_p0_rd_count (c3_p0_rd_count), 89 .c3_p0_rd_overflow (c3_p0_rd_overflow), 90 .c3_p0_rd_error (c3_p0_rd_error ), 91 /********************P1 user port************************/ 92 .c3_p1_cmd_clk (c3_p1_cmd_clk ), 93 .c3_p1_cmd_en (c3_p1_cmd_en ), 94 .c3_p1_cmd_instr (c3_p1_cmd_instr ), 95 .c3_p1_cmd_bl (c3_p1_cmd_bl ), 96 .c3_p1_cmd_byte_addr (c3_p1_cmd_byte_addr), 97 .c3_p1_cmd_empty (c3_p1_cmd_empty ), 98 .c3_p1_cmd_full (c3_p1_cmd_full ), 99 .c3_p1_wr_clk (c3_p1_wr_clk), 100 .c3_p1_wr_en (c3_p1_wr_en), 101 .c3_p1_wr_mask (c3_p1_wr_mask), 102 .c3_p1_wr_data (c3_p1_wr_data), 103 .c3_p1_wr_full (c3_p1_wr_full), 104 .c3_p1_wr_empty (c3_p1_wr_empty), 105 .c3_p1_wr_count (c3_p1_wr_count), 106 .c3_p1_wr_underrun (c3_p1_wr_underrun), 107 .c3_p1_wr_error (c3_p1_wr_error), 108 .c3_p1_rd_clk (c3_p1_rd_clk), 109 .c3_p1_rd_en (c3_p1_rd_en), 110 .c3_p1_rd_data (c3_p1_rd_data), 111 .c3_p1_rd_full (c3_p1_rd_full), 112 .c3_p1_rd_empty (c3_p1_rd_empty), 113 .c3_p1_rd_count (c3_p1_rd_count), 114 .c3_p1_rd_overflow (c3_p1_rd_overflow), 115 .c3_p1_rd_error (c3_p1_rd_error) 116 );
(3)从上文中所提到的Example_design 文件中把DDr所有的顶层接口复制到ddr_top.v文件中:
1 //sysyterm interface 2 input c3_sys_clk , 3 input c3_sys_rst_i , 4 //ddr3 interface 5 inout [15:0] mcb3_dram_dq , 6 output wire [12:0] mcb3_dram_a , 7 output wire [2:0] mcb3_dram_ba , 8 output wire mcb3_dram_ras_n , 9 output wire mcb3_dram_cas_n , 10 output wire mcb3_dram_we_n , 11 output wire mcb3_dram_odt , 12 output wire mcb3_dram_reset_n , 13 output wire mcb3_dram_cke , 14 output wire mcb3_dram_dm , 15 inout mcb3_dram_udqs , 16 inout mcb3_dram_udqs_n , 17 inout mcb3_rzq , 18 inout mcb3_zio , 19 output wire mcb3_dram_udm , 20 inout mcb3_dram_dqs , 21 inout mcb3_dram_dqs_n , 22 output wire mcb3_dram_ck , 23 output wire mcb3_dram_ck_n ,
其中例程中给出的为如下所示:
1 module example_top # 2 ( 3 parameter C3_P0_MASK_SIZE = 8, 4 parameter C3_P0_DATA_PORT_SIZE = 64, 5 parameter C3_P1_MASK_SIZE = 8, 6 parameter C3_P1_DATA_PORT_SIZE = 64, 7 parameter DEBUG_EN = 0, 8 // # = 1, Enable debug signals/controls, 9 // = 0, Disable debug signals/controls. 10 parameter C3_MEMCLK_PERIOD = 3200, 11 // Memory data transfer clock period 12 parameter C3_CALIB_SOFT_IP = "TRUE", 13 // # = TRUE, Enables the soft calibration logic, 14 // # = FALSE, Disables the soft calibration logic. 15 parameter C3_SIMULATION = "FALSE", 16 // # = TRUE, Simulating the design. Useful to reduce the simulation time, 17 // # = FALSE, Implementing the design. 18 parameter C3_HW_TESTING = "FALSE", 19 // Determines the address space accessed by the traffic generator, 20 // # = FALSE, Smaller address space, 21 // # = TRUE, Large address space. 22 parameter C3_RST_ACT_LOW = 0, 23 // # = 1 for active low reset, 24 // # = 0 for active high reset. 25 parameter C3_INPUT_CLK_TYPE = "DIFFERENTIAL", 26 // input clock type DIFFERENTIAL or SINGLE_ENDED 27 parameter C3_MEM_ADDR_ORDER = "BANK_ROW_COLUMN", 28 // The order in which user address is provided to the memory controller, 29 // ROW_BANK_COLUMN or BANK_ROW_COLUMN 30 parameter C3_NUM_DQ_PINS = 16, 31 // External memory data width 32 parameter C3_MEM_ADDR_WIDTH = 13, 33 // External memory address width 34 parameter C3_MEM_BANKADDR_WIDTH = 3 35 // External memory bank address width 36 ) 37 38 ( 39 output calib_done, 40 output error, 41 inout [C3_NUM_DQ_PINS-1:0] mcb3_dram_dq, 42 output [C3_MEM_ADDR_WIDTH-1:0] mcb3_dram_a, 43 output [C3_MEM_BANKADDR_WIDTH-1:0] mcb3_dram_ba, 44 output mcb3_dram_ras_n, 45 output mcb3_dram_cas_n, 46 output mcb3_dram_we_n, 47 output mcb3_dram_odt, 48 output mcb3_dram_reset_n, 49 output mcb3_dram_cke, 50 output mcb3_dram_dm, 51 inout mcb3_dram_udqs, 52 inout mcb3_dram_udqs_n, 53 inout mcb3_rzq, 54 inout mcb3_zio, 55 output mcb3_dram_udm, 56 input c3_sys_clk_p, 57 input c3_sys_clk_n, 58 input c3_sys_rst_i, 59 inout mcb3_dram_dqs, 60 inout mcb3_dram_dqs_n, 61 output mcb3_dram_ck, 62 output mcb3_dram_ck_n 63 );
第四:创建TB激励文件;主要是根据历程中来创建的。
`timescale 1ps/1ps module tb_ddr_top ; reg ddr3_ref_clk ; reg ddr3_rst_n ; //bebug signals reg wr_trig ; wire c3_calib_done ; //ddr3 interface wire [15:0] mcb3_dram_dq ; wire [12:0] mcb3_dram_a ; wire [2:0] mcb3_dram_ba ; wire mcb3_dram_ras_n ; wire mcb3_dram_cas_n ; wire mcb3_dram_we_n ; wire mcb3_dram_odt ; wire mcb3_dram_reset_n ; wire mcb3_dram_cke ; wire mcb3_dram_dm ; wire mcb3_dram_udqs ; wire mcb3_dram_udqs_n ; wire mcb3_rzq ; wire mcb3_zio ; wire mcb3_dram_udm ; wire mcb3_dram_dqs ; wire mcb3_dram_dqs_n ; wire mcb3_dram_ck ; wire mcb3_dram_ck_n ; parameter C3_MEMCLK_PERIOD = 3200; initial begin ddr3_ref_clk = 1; ddr3_rst_n = 0; #20000; ddr3_rst_n = 1; end //produce debug signals initial begin wr_trig <= 0; @(posedge c3_calib_done) #100000 wr_trig <= 1; #25600 wr_trig <= 0; end always #(C3_MEMCLK_PERIOD/2) ddr3_ref_clk = ~ddr3_ref_clk ; ddr_top ddr_top_inst( //sysyterm interface .c3_sys_clk (ddr3_ref_clk ), .c3_sys_rst_i (ddr3_rst_n ), //ddr3 interface .mcb3_dram_dq (mcb3_dram_dq ), .mcb3_dram_a (mcb3_dram_a ), .mcb3_dram_ba (mcb3_dram_ba ), .mcb3_dram_ras_n (mcb3_dram_ras_n ), .mcb3_dram_cas_n (mcb3_dram_cas_n ), .mcb3_dram_we_n (mcb3_dram_we_n ), .mcb3_dram_odt (mcb3_dram_odt ), .mcb3_dram_reset_n (mcb3_dram_reset_n ), .mcb3_dram_cke (mcb3_dram_cke ), .mcb3_dram_dm (mcb3_dram_dm ), .mcb3_dram_udqs (mcb3_dram_udqs ), .mcb3_dram_udqs_n (mcb3_dram_udqs_n ), .mcb3_rzq (mcb3_rzq ), .mcb3_zio (mcb3_zio ), .mcb3_dram_udm (mcb3_dram_udm ), .mcb3_dram_dqs (mcb3_dram_dqs ), .mcb3_dram_dqs_n (mcb3_dram_dqs_n ), .mcb3_dram_ck (mcb3_dram_ck ), .mcb3_dram_ck_n (mcb3_dram_ck_n ), //debug signals .wr_trig (wr_trig) , .c3_calib_done (c3_calib_done) ); ddr3_model_c3 u_mem_c3( .ck (mcb3_dram_ck), .ck_n (mcb3_dram_ck_n), .cke (mcb3_dram_cke), .cs_n (1'b0), .ras_n (mcb3_dram_ras_n), .cas_n (mcb3_dram_cas_n), .we_n (mcb3_dram_we_n), .dm_tdqs ({mcb3_dram_udm,mcb3_dram_dm}), .ba (mcb3_dram_ba), .addr (mcb3_dram_a), .dq (mcb3_dram_dq), .dqs ({mcb3_dram_udqs,mcb3_dram_dqs}), .dqs_n ({mcb3_dram_udqs_n,mcb3_dram_dqs_n}), .tdqs_n (), .odt (mcb3_dram_odt), .rst_n (mcb3_dram_reset_n) ); // The PULLDOWN component is connected to the ZIO signal primarily to avoid the // unknown state in simulation. In real hardware, ZIO should be a no connect(NC) pin. PULLDOWN zio_pulldown3 (.O(zio3)); PULLDOWN rzq_pulldown3 (.O(rzq3)); endmodule
这样自己搭建的就好了。有些细节小问题,没讲,不懂得化联系我吧,一起进步;