DDR4仿真之仿真环境搭建(二)
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:tranDQS
for (i = 0; i < NUM_PHYSICAL_PARTS; i++) begin:tranDQS1
`ifdef XILINX_SIMULATOR
short 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]);
`else
tran 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]);
`endif
end
end
(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 begin
en_model = 1'b0;
btn = 1'b1;
#200
resetn = 1'b1;
#200
en_model = 1'b1;
#200;
wait(led[0]);
#2000
repeat(10)begin
#2000
sim_btn();
end
#100_000_000;
$stop;
end
ultra_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
endtask
endmodule

浙公网安备 33010602011771号