1.添加空白仿真文件,选择SystemVerilog类型(必须是sv)
2.根据ip设置的参考时钟频率,创建仿真时钟;设置时钟尺度timescale为 1ps/1ps,这样更方便使用整数产生时钟(我的参考时钟是100M)



3.打开IP example,在工程目录下找到import文件夹,复制import文件夹到自己工程仿真目录下,只保留图中蓝色文件,这些文件是DDR4的仿真模型和接口信号等配置信息。



4.添加import里面所有仿真文件,需要将其中几种文件类型改为Verilog Header,将ddr4_sdram_model_wrapper类型改为sv。



5.在仿真文件中添加DDR4仿真模型
(1)将arch_package模块引用到仿真文件中。在ddr4_sdram_model_wrapper.sv中,可以找到DDR4_4G_X8,说明我们DDR4仿真模型内存容量为4G,定义CONFIGURED_DENSITY = _4G

(2)把interface.sv模块中的接口引用进来并声明IDDR4
将ddr4_model模块例化进来,model_enable为使能信号(默认assign model_enable = 1)。
根据DQ数量来设置iDDR4[0:x]和选择例化ddr4_model数量。因为IP设置的DATA WIDTH为16,故x=0,CONFIGURED_DQ_BITS=16,例化一个ddr4_model;
如果IP设置的DATA WIDTH为32,则x=1,CONFIGURED_DQ_BITS=32,例化两个ddr4_model,并将第二个iDDR4[0]改为iDDR4[1];
点击查看代码
DDR4_if #(.CONFIGURED_DQ_BITS(16)) iDDR4[0:0](); ddr4_model #( .CONFIGURED_DQ_BITS(16), .CONFIGURED_DENSITY (CONFIGURED_DENSITY) )
ddr4_model_0( .model_enable (model_enable), .iDDR4 (iDDR4[0]) );tran bidiDQ0(iDDR4[0].DQ[0], ddr4_dq[0]);
tran bidiDQ1(iDDR4[0].DQ[1], ddr4_dq[1]);
tran bidiDQ2(iDDR4[0].DQ[2], ddr4_dq[2]);
tran bidiDQ3(iDDR4[0].DQ[3], ddr4_dq[3]);
tran bidiDQ4(iDDR4[0].DQ[4], ddr4_dq[4]);
tran bidiDQ5(iDDR4[0].DQ[5], ddr4_dq[5]);
tran bidiDQ6(iDDR4[0].DQ[6], ddr4_dq[6]);
tran bidiDQ7(iDDR4[0].DQ[7], ddr4_dq[7]);
tran bidiDQ8(iDDR4[0].DQ[8], ddr4_dq[8]);
tran bidiDQ9(iDDR4[0].DQ[9], ddr4_dq[9]);
tran bidiDQ10(iDDR4[0].DQ[10], ddr4_dq[10]);
tran bidiDQ11(iDDR4[0].DQ[11], ddr4_dq[11]);
tran bidiDQ12(iDDR4[0].DQ[12], ddr4_dq[12]);
tran bidiDQ13(iDDR4[0].DQ[13], ddr4_dq[13]);
tran bidiDQ14(iDDR4[0].DQ[14], ddr4_dq[14]);
tran bidiDQ15(iDDR4[0].DQ[15], ddr4_dq[15]);
(3)其余信号连接
(我这里只用了一个ddr4_model,只需要注意tran对应双向信号就行了,assign根据例化的ddr4模型对iDDR4[0]进行对应修改)
点击查看代码
tran bidiDQS0(iDDR4[0].DQS_t[0], ddr4_dqs_t[0]);
tran bidiDQS1(iDDR4[0].DQS_t[1], ddr4_dqs_t[1]); tran bidiDQS_0(iDDR4[0].DQS_c[0], ddr4_dqs_c[0]);
tran bidiDQS_1(iDDR4[0].DQS_c[1], ddr4_dqs_c[1]); tran bidiDM0(iDDR4[0].DM_n[0], ddr4_dm_dbi_n[0]);
tran bidiDM1(iDDR4[0].DM_n[1], ddr4_dm_dbi_n[1]); assign iDDR4[0].BG = ddr4_bg;
assign iDDR4[0].BA = ddr4_ba[1:0];
assign iDDR4[0].ADDR_17 = 1'b0;
assign iDDR4[0].ADDR = ddr4_adr[13:0];
assign iDDR4[0].CS_n = ddr4_cs_n;
assign iDDR4[0].CK = {ddr4_ck_t, ddr4_ck_c};
assign iDDR4[0].ACT_n = ddr4_act_n;
assign iDDR4[0].RAS_n_A16 = ddr4_adr[16];
assign iDDR4[0].CAS_n_A15 = ddr4_adr[15];
assign iDDR4[0].WE_n_A14 = ddr4_adr[14];
assign iDDR4[0].CKE = ddr4_cke;
assign iDDR4[0].ODT = ddr4_odt;
assign iDDR4[0].PARITY = 1'b0;
assign iDDR4[0].TEN = 1'b0;
assign iDDR4[0].ZQ = 1'b1;
assign iDDR4[0].PWR = 1'b1;
assign iDDR4[0].VREF_CA = 1'b1;
assign iDDR4[0].VREF_DQ = 1'b1;
assign iDDR4[0].RESET_n = ddr4_reset_n;
用到多个ddr4_model的情况,tran部分逻辑参考example中的这里进行推理
点击查看代码
// 这里只展示了dqs_t、dqs_c,其余几个tran信号参考对应逻辑for (r = 0; r < RANK_WIDTH; r++) begin:tranDQSfor (i = 0; i < NUM_PHYSICAL_PARTS; i++) begin:tranDQS1`ifdef XILINX_SIMULATORshort bidiDQS(iDDR4[(r*NUM_PHYSICAL_PARTS)+i].DQS_t, c0_ddr4_dqs_t[i]);short bidiDQS_(iDDR4[(r*NUM_PHYSICAL_PARTS)+i].DQS_c, c0_ddr4_dqs_c[i]);`elsetran bidiDQS(iDDR4[(r*NUM_PHYSICAL_PARTS)+i].DQS_t, c0_ddr4_dqs_t[i]);tran bidiDQS_(iDDR4[(r*NUM_PHYSICAL_PARTS)+i].DQS_c, c0_ddr4_dqs_c[i]);`endifendend
(4)使用simulation仿真,配置正确的情况下c0_init_calib_complate信号拉高后表示初始化成功。
贴一下参考
点击查看代码
`timescale 1ps/1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2025/11/11 10:33:35
// Design Name:
// Module Name: tb_ultra_video
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////module tb_ultra_video();localparam CLK = (10000/2.0);import arch_package::*;
parameter UTYPE_density CONFIGURED_DENSITY = _4G;//-----------------------------------------------------------------
//
//-----------------------------------------------------------------wire ddr4_act_n ;
wire [16:0] ddr4_adr ;
wire [1:0] ddr4_ba ;
wire ddr4_bg ;
wire ddr4_cke ;
wire ddr4_odt ;
wire ddr4_cs_n ;
wire ddr4_ck_t ;
wire ddr4_ck_c ;
wire ddr4_reset_n ;
wire [1:0] ddr4_dm_dbi_n;
wire [15:0] ddr4_dq ;
wire [1:0] ddr4_dqs_c ;
wire [1:0] ddr4_dqs_t ;reg en_model;
tri model_enable = en_model;reg refclk_p = 1'b0;
wire refclk_n = ~refclk_p;
reg resetn = 1'b0;wire serial_rx,serial_tx;
wire [1:0] led;
reg btn;//-----------------------------------------------------------------
//
//-----------------------------------------------------------------always #CLK refclk_p = ~refclk_p; pullup(serial_rx);initial beginen_model = 1'b0;btn = 1'b1;#200resetn = 1'b1;#200en_model = 1'b1;#200;wait(led[0]);#2000repeat(10)begin#2000sim_btn();end#100_000_000;$stop;
endultra_video ultra_video_inst (.refclk_p (refclk_p),.refclk_n (refclk_n),.resetn (resetn),.ddr4_act_n (ddr4_act_n),.ddr4_adr (ddr4_adr),.ddr4_ba (ddr4_ba),.ddr4_bg (ddr4_bg),.ddr4_cke (ddr4_cke),.ddr4_odt (ddr4_odt),.ddr4_cs_n (ddr4_cs_n),.ddr4_ck_t (ddr4_ck_t),.ddr4_ck_c (ddr4_ck_c),.ddr4_reset_n (ddr4_reset_n),.ddr4_dm_dbi_n (ddr4_dm_dbi_n),.ddr4_dq (ddr4_dq),.ddr4_dqs_c (ddr4_dqs_c),.ddr4_dqs_t (ddr4_dqs_t),.btn (btn),.led (led),.serial_rx (serial_rx),.serial_tx (serial_tx));DDR4_if #(.CONFIGURED_DQ_BITS(16)) iDDR4[0:0](); ddr4_model #( .CONFIGURED_DQ_BITS(16), .CONFIGURED_DENSITY (CONFIGURED_DENSITY) )
ddr4_model_0( .model_enable (model_enable), .iDDR4 (iDDR4[0]) );tran bidiDQ0(iDDR4[0].DQ[0], ddr4_dq[0]);
tran bidiDQ1(iDDR4[0].DQ[1], ddr4_dq[1]);
tran bidiDQ2(iDDR4[0].DQ[2], ddr4_dq[2]);
tran bidiDQ3(iDDR4[0].DQ[3], ddr4_dq[3]);
tran bidiDQ4(iDDR4[0].DQ[4], ddr4_dq[4]);
tran bidiDQ5(iDDR4[0].DQ[5], ddr4_dq[5]);
tran bidiDQ6(iDDR4[0].DQ[6], ddr4_dq[6]);
tran bidiDQ7(iDDR4[0].DQ[7], ddr4_dq[7]);
tran bidiDQ8(iDDR4[0].DQ[8], ddr4_dq[8]);
tran bidiDQ9(iDDR4[0].DQ[9], ddr4_dq[9]);
tran bidiDQ10(iDDR4[0].DQ[10], ddr4_dq[10]);
tran bidiDQ11(iDDR4[0].DQ[11], ddr4_dq[11]);
tran bidiDQ12(iDDR4[0].DQ[12], ddr4_dq[12]);
tran bidiDQ13(iDDR4[0].DQ[13], ddr4_dq[13]);
tran bidiDQ14(iDDR4[0].DQ[14], ddr4_dq[14]);
tran bidiDQ15(iDDR4[0].DQ[15], ddr4_dq[15]); tran bidiDQS0(iDDR4[0].DQS_t[0], ddr4_dqs_t[0]);
tran bidiDQS1(iDDR4[0].DQS_t[1], ddr4_dqs_t[1]); tran bidiDQS_0(iDDR4[0].DQS_c[0], ddr4_dqs_c[0]);
tran bidiDQS_1(iDDR4[0].DQS_c[1], ddr4_dqs_c[1]); tran bidiDM0(iDDR4[0].DM_n[0], ddr4_dm_dbi_n[0]);
tran bidiDM1(iDDR4[0].DM_n[1], ddr4_dm_dbi_n[1]); assign iDDR4[0].BG = ddr4_bg;
assign iDDR4[0].BA = ddr4_ba[1:0];
assign iDDR4[0].ADDR_17 = 1'b0;
assign iDDR4[0].ADDR = ddr4_adr[13:0];
assign iDDR4[0].CS_n = ddr4_cs_n;
assign iDDR4[0].CK = {ddr4_ck_t, ddr4_ck_c};
assign iDDR4[0].ACT_n = ddr4_act_n;
assign iDDR4[0].RAS_n_A16 = ddr4_adr[16];
assign iDDR4[0].CAS_n_A15 = ddr4_adr[15];
assign iDDR4[0].WE_n_A14 = ddr4_adr[14];
assign iDDR4[0].CKE = ddr4_cke;
assign iDDR4[0].ODT = ddr4_odt;
assign iDDR4[0].PARITY = 1'b0;
assign iDDR4[0].TEN = 1'b0;
assign iDDR4[0].ZQ = 1'b1;
assign iDDR4[0].PWR = 1'b1;
assign iDDR4[0].VREF_CA = 1'b1;
assign iDDR4[0].VREF_DQ = 1'b1;
assign iDDR4[0].RESET_n = ddr4_reset_n; task sim_btn();begin@(posedge ultra_video_inst.clk_out1);btn = 1'b0; repeat(21) begin #100_000_000;end btn = 1'b1; $display("Btn detect!"); end
endtaskendmodule