Litedram仿真验证(四):AXI接口完成板级DDR3读写测试(FPGA-Artix7)

目录

日常·唠嗑

接上一篇Litedram仿真验证(三):AXI接口完成仿真(FPGA/Modelsim)之后,本篇对仿真后的工程进行板级验证。

本次板级验证用到的开发板:Arty-a7,目前已经停产了,某宝上面还有卖,溢价比较严重。

板子资料链接:https://digilent.com/reference/programmable-logic/arty-a7/start

需要科学上网才能打开,因为是官方的板子资料很详细,有需要可以看看。

FPGA:xc7a35tcsg324-1

DDR3:MT41K128M16

一、仿真中遗留的问题

在上一篇文章中,提到AXI读写中,读会读不出来:

因为存在这一错误,所以迟迟没有上板,最近特地对这一问题进行了追踪,发现这一问题主要是出现在DDR3仿真模型的初始化上面:

----------------授人以鱼不如授人以渔,这里讲一下调试过程-----------------------

正确的DDR3初始化过程应该是这样的:

这是我用MIG example跑出来的log信息。

c 复制代码
relaunch_sim
Command: launch_simulation -simset sim_1 -mode behavioral
INFO: [Vivado 12-5698] Checking validity of IPs in the design for the 'XSim' simulator...
INFO: [Vivado 12-5682] Launching behavioral simulation in 'f:/Fpga/vivado_test2/mig_7series_0_ex/mig_7series_0_ex.sim/sim_1/behav/xsim'
INFO: [Vivado 12-4795] Using compiled simulation libraries for IPs
INFO: [SIM-utils-51] Simulation object is 'sim_1'
INFO: [USF-XSim-7] Finding pre-compiled libraries...
INFO: [USF-XSim-11] File 'E:/Tool/vivado/Vivado/2019.2/data/xsim/xsim.ini' copied to run dir:'f:/Fpga/vivado_test2/mig_7series_0_ex/mig_7series_0_ex.sim/sim_1/behav/xsim'
INFO: [SIM-utils-54] Inspecting design source files for 'sim_tb_top' in fileset 'sim_1'...
INFO: [SIM-utils-43] Exported 'f:/Fpga/vivado_test2/mig_7series_0_ex/mig_7series_0_ex.sim/sim_1/behav/xsim/xsim_run.bat'
INFO: [USF-XSim-97] Finding global include files...
INFO: [USF-XSim-98] Fetching design files from 'sim_1'...
INFO: [USF-XSim-2] XSim::Compile design
INFO: [USF-XSim-61] Executing 'COMPILE and ANALYZE' step in 'f:/Fpga/vivado_test2/mig_7series_0_ex/mig_7series_0_ex.sim/sim_1/behav/xsim'
"xvlog --incr --relax -prj sim_tb_top_vlog.prj"
INFO: [USF-XSim-69] 'compile' step finished in '2' seconds
Command: launch_simulation -simset sim_1 -mode behavioral
INFO: [Vivado 12-5698] Checking validity of IPs in the design for the 'XSim' simulator...
INFO: [Vivado 12-5682] Launching behavioral simulation in 'f:/Fpga/vivado_test2/mig_7series_0_ex/mig_7series_0_ex.sim/sim_1/behav/xsim'
INFO: [Vivado 12-4795] Using compiled simulation libraries for IPs
INFO: [USF-XSim-3] XSim::Elaborate design
INFO: [USF-XSim-61] Executing 'ELABORATE' step in 'f:/Fpga/vivado_test2/mig_7series_0_ex/mig_7series_0_ex.sim/sim_1/behav/xsim'
"xelab -wto db7f1812aaa74905a81e46e866e8f86b --incr --debug typical --relax --mt 2 -L xil_defaultlib -L unisims_ver -L unimacro_ver -L secureip -L xpm --snapshot sim_tb_top_behav xil_defaultlib.sim_tb_top xil_defaultlib.glbl -log elaborate.log"
Vivado Simulator 2019.2
Copyright 1986-1999, 2001-2019 Xilinx, Inc. All Rights Reserved.
Running: E:/Tool/vivado/Vivado/2019.2/bin/unwrapped/win64.o/xelab.exe -wto db7f1812aaa74905a81e46e866e8f86b --incr --debug typical --relax --mt 2 -L xil_defaultlib -L unisims_ver -L unimacro_ver -L secureip -L xpm --snapshot sim_tb_top_behav xil_defaultlib.sim_tb_top xil_defaultlib.glbl -log elaborate.log 
Using 2 slave threads.
Starting static elaboration
Pass Through NonSizing Optimizer
WARNING: [VRFC 10-3091] actual bit length 12 differs from formal bit length 4 for port 'pi_dqs_found_lanes' [f:/Fpga/vivado_test2/mig_7series_0_ex/mig_7series_0_ex.srcs/sources_1/ip/mig_7series_0/mig_7series_0/user_design/rtl/phy/mig_7series_v4_2_ddr_mc_phy_wrapper.v:1671]
WARNING: [VRFC 10-3091] actual bit length 12 differs from formal bit length 4 for port 'pi_phase_locked_lanes' [f:/Fpga/vivado_test2/mig_7series_0_ex/mig_7series_0_ex.srcs/sources_1/ip/mig_7series_0/mig_7series_0/user_design/rtl/phy/mig_7series_v4_2_ddr_mc_phy_wrapper.v:1679]
WARNING: [VRFC 10-3091] actual bit length 12 differs from formal bit length 4 for port 'pi_dqs_found_lanes' [f:/Fpga/vivado_test2/mig_7series_0_ex/mig_7series_0_ex.srcs/sources_1/ip/mig_7series_0/mig_7series_0/user_design/rtl/phy/mig_7series_v4_2_ddr_phy_top.v:1340]
WARNING: [VRFC 10-3091] actual bit length 1 differs from formal bit length 2 for port 'axi_wlock' [f:/Fpga/vivado_test2/mig_7series_0_ex/imports/example_top.v:544]
WARNING: [VRFC 10-3091] actual bit length 1 differs from formal bit length 4 for port 'axi_wd_wid' [f:/Fpga/vivado_test2/mig_7series_0_ex/imports/example_top.v:551]
WARNING: [VRFC 10-3091] actual bit length 1 differs from formal bit length 2 for port 'axi_rlock' [f:/Fpga/vivado_test2/mig_7series_0_ex/imports/example_top.v:570]
WARNING: [VRFC 10-5021] port 'complex_oclk_prech_req' is not connected on this instance [f:/Fpga/vivado_test2/mig_7series_0_ex/mig_7series_0_ex.srcs/sources_1/ip/mig_7series_0/mig_7series_0/user_design/rtl/phy/mig_7series_v4_2_ddr_calib_top.v:1318]
Completed static elaboration
INFO: [XSIM 43-4323] No Change in HDL. Linking previously generated obj files to create kernel
INFO: [USF-XSim-69] 'elaborate' step finished in '4' seconds
Vivado Simulator 2019.2
Time resolution is 1 fs
WARNING: file design.txt could not be opened
 *** Warning: The analog data file design.txt for XADC instance sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.temp_mon_enabled.u_tempmon.xadc_supplied_temperature.XADC_inst was not found. Use the SIM_MONITOR_FILE parameter to specify the analog data file name or use the default name: design.txt.

############# Write Clocks PLLE2_ADV Parameters #############

nCK_PER_CLK      =       4
CLK_PERIOD       =    5000
CLKIN1_PERIOD    =   5.000
DIVCLK_DIVIDE    =       1
CLKFBOUT_MULT    =       4
VCO_PERIOD       =  1250.0
CLKOUT0_DIVIDE_F =       1
CLKOUT1_DIVIDE   =       2
CLKOUT2_DIVIDE   =      32
CLKOUT3_DIVIDE   =       8
CLKOUT0_PERIOD   =    1250
CLKOUT1_PERIOD   =    2500
CLKOUT2_PERIOD   =   40000
CLKOUT3_PERIOD   =   10000
CLKOUT4_PERIOD   =    5000
############################################################

############# MMCME2_ADV Parameters #############

MMCM_MULT_F           =           8
MMCM_VCO_FREQ (MHz)   = 800.000
MMCM_VCO_PERIOD       = 1250.000
#################################################

sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : BYTE_LANES_B0 = f BYTE_LANES_B1 = 0 DATA_CTL_B0 = 5 DATA_CTL_B1 = 0
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : HIGHEST_LANE =           4 HIGHEST_LANE_B0 =           4 HIGHEST_LANE_B1 =           0
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : HIGHEST_BANK =           1
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : FREQ_REF_PERIOD         = 1250.00 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : DDR_TCK                 = 2500 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PO_S2_TAPS_SIZE         = 9.77 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PO_CIRC_BUF_EARLY       = 1 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PO_CIRC_BUF_OFFSET      = 1219.75 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PO_CIRC_BUF_META_ZONE   = 200.00 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PO_STG2_FINE_INTR_DLY   = 769.25 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PO_STG2_COARSE_INTR_DLY = 511.00 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PO_STG2_INTRINSIC_DELAY = 1280.25 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PO_CIRC_BUF_DELAY       = 60 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PO_INTRINSIC_DELAY      = 1280.25 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PO_DELAY                = 1866.19 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PO_OCLK_DELAY           = 0 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : L_PHY_0_PO_FINE_DELAY   = 60 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PI_STG1_INTRINSIC_DELAY = 0.00 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PI_STG2_INTRINSIC_DELAY = 744.00 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PI_INTRINSIC_DELAY      = 744.00 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PI_MAX_STG2_DELAY       = 615.23 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PI_OFFSET               = -78.00 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : a negative PI_OFFSET means that rclk path is longer than oclk path so rclk will be delayed to next oclk edge and the negedge of rclk may be used.
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : PI_STG2_DELAY           = 615.23 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy :PI_STG2_DELAY_CAND       = 1172.00 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : DEFAULT_RCLK_DELAY      = 63 
sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy : RCLK_SELECT_EDGE        = 0 
WARNING: sim_tb_top.u_ip_top.u_mig_7series_0.u_mig_7series_0_mig.u_memc_ui_top_axi.mem_intfc0.ddr_phy_top0.u_ddr_mc_phy_wrapper.u_ddr_mc_phy: The required delay though the phaser_in to internally match the aux_out clock  to ddr clock exceeds the maximum allowable delay. The clock edge  will occur at the output registers of aux_out 556.77 ps before the ddr clock  edge. If aux_out is used for memory inputs, this may violate setup or hold time.
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.reset at time 1347600.0 ps WARNING: 200 us is required before RST_N goes inactive.
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task at time 1413314.0 ps WARNING: 500 us is required after RST_N goes inactive before CKE goes active.
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 1715814.0 ps INFO: Load Mode 2
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 1715814.0 ps INFO: Load Mode 2 Partial Array Self Refresh = Bank 0-7
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 1715814.0 ps INFO: Load Mode 2 CAS Write Latency =           5
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 1715814.0 ps INFO: Load Mode 2 Auto Self Refresh = Disabled
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 1715814.0 ps INFO: Load Mode 2 Self Refresh Temperature = Normal
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 1715814.0 ps INFO: Load Mode 2 Dynamic ODT = Disabled
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 3015814.0 ps INFO: Load Mode 3
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 3015814.0 ps INFO: Load Mode 3 MultiPurpose Register Select = Pre-defined pattern
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 3015814.0 ps INFO: Load Mode 3 MultiPurpose Register Enable = Disabled
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 4315814.0 ps INFO: Load Mode 1
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 4315814.0 ps INFO: Load Mode 1 DLL Enable = Enabled
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 4315814.0 ps INFO: Load Mode 1 Output Drive Strength =          34 Ohm
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 4315814.0 ps INFO: Load Mode 1 ODT Rtt =          60 Ohm
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 4315814.0 ps INFO: Load Mode 1 Additive Latency = 0
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 4315814.0 ps INFO: Load Mode 1 Write Levelization = Disabled
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 4315814.0 ps INFO: Load Mode 1 TDQS Enable = Disabled
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 4315814.0 ps INFO: Load Mode 1 Qoff = Enabled
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 5615814.0 ps INFO: Load Mode 0
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 5615814.0 ps INFO: Load Mode 0 Burst Length =  8
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 5615814.0 ps INFO: Load Mode 0 Burst Order = Sequential
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 5615814.0 ps INFO: Load Mode 0 CAS Latency =           6
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 5615814.0 ps INFO: Load Mode 0 DLL Reset = Reset DLL
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 5615814.0 ps INFO: Load Mode 0 Write Recovery =           6
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 5615814.0 ps INFO: Load Mode 0 Power Down Mode = DLL off
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 6915814.0 ps INFO: ZQ        long = 1
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 6915814.0 ps INFO: Initialization Sequence is complete
PHY_INIT: Memory Initialization completed at 9397600.0 ps
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 9495814.0 ps INFO: Activate  bank 0 row 0000
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 10795814.0 ps INFO: Read      bank 0 col 000, auto precharge 0
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 10805814.0 ps INFO: Read      bank 0 col 000, auto precharge 0
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.data_task: at time 10809564.0 ps INFO: READ @ DQS= bank = 0 row = 0000 col = 00000000 data = xxx

但是,Litedram跑出来的初始化信息是这样的:

c 复制代码
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.main: at time 2765100.0 ps ERROR: CK and CK_N are not allowed to go to an unknown state.
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.reset at time 2775100.0 ps WARNING: 200 us is required before RST_N goes inactive.
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.reset: at time 2775100.0 ps ERROR: CKE must be inactive when RST_N goes inactive.
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3: at time 2775100.0 ps ERROR: RST_N pulse width violation by 90000.0 ps
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task at time 2776350.0 ps WARNING: 500 us is required after RST_N goes inactive before CKE goes active.
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 10646350.0 ps INFO: Precharge All
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 10676350.0 ps INFO: Refresh  
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 18466350.0 ps INFO: Precharge All
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 18496350.0 ps INFO: Refresh  
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 26286350.0 ps INFO: Precharge All
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 26316350.0 ps INFO: Refresh  
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 34106350.0 ps INFO: Precharge All
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 34136350.0 ps INFO: Refresh  
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.main: at time 120135100.0 ps ERROR: CK and CK_N are not allowed to go to an unknown state.
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.reset at time 120145100.0 ps WARNING: 200 us is required before RST_N goes inactive.
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.reset: at time 120145100.0 ps ERROR: CKE must be inactive when RST_N goes inactive.
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3: at time 120145100.0 ps ERROR: RST_N pulse width violation by 90000.0 ps
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 120146350.0 ps ERROR:  tRFC maximum violation during No Op    
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task at time 120146350.0 ps WARNING: 500 us is required after RST_N goes inactive before CKE goes active.
sim_tb_top.mem_rnk[0].mem.gen_mem[0].u_comp_ddr3.cmd_task: at time 200596350.0 ps ERROR: Power Down Failure.  Initialization sequence is not complete.
$stop called at time : 200596350 ps
run: Time (s): cpu = 00:00:11 ; elapsed = 00:02:25 . Memory (MB): peak = 1340.203 ; gain = 0.000

很明显几个error,导致DDR3初始化顺序不对:

跟着这个信息提示还有时间,我追到了出错误的波形,发现初始化过程中,DDR颗粒接口信号,会出现1个时钟周期的X态;基于此,我对OSERDES2进行单独仿真,发现该原语的RST信号,只要跳变一次,就会出现1个时钟周期X态,这个问题属于xilinx的固有问题,仿真无法解决,不影响板级测试。MIG仿真这个问题,没有看到是如何克服的,后面如有空余时间,可以解密IP并看一下处理方式;

单独仿真Oserdese2,只要RST跳变,输出就会出现1个时钟周期X态:

仿真文件:

(因为我自己测试用的,一些注释可能没改,不对,还有一些多余的信号也没删,读者在参考的时候,能测试看一下就行,不要过度纠结)

c 复制代码
`timescale 1ns / 1ps
module oserdese2_wrapper(
    input clk_in_20,
    input rst_N,
    inout [0:0] dq,
    output locked,
    input main_a7ddrphy_rst_storage,
    output ddram_reset_n,
    output test
    );


wire  [7:0] d0     			    ;
wire  [7:0] q0     			    ;

wire        align_ol		    ;
wire        align_il		    ;
  
wire        geclk_ol            ;
wire        geclk_90_il         ;
wire        gsclk_ol            ;
  
wire        geclk_il            ;
wire        gsclk_il            ;
wire        usr_rst_N             ;
wire        align_ol_ready      ;
wire        align_il_ready      ;
  
reg   [3:0] cnt				    ;
reg         rst 			    ;

wire clk_out_40;
wire clk_out_20;
wire clk_out_80;
wire clk_out_80_90;

assign test = clk_out_20;
assign usr_rst_N = rst_N & locked;

wire sys_clk;
wire sys4x_clk;

always @(posedge clk_out_20 or negedge usr_rst_N) begin
	if (~usr_rst_N) begin
		rst <= 1'b1;
	end
	else
		rst <= 1'b0;
end


always @(posedge clk_out_20 or posedge rst) begin
	if (rst) begin
		cnt <= 4'b1100;
	end
	else 
		if(!rst)
			cnt <= cnt + 1;
end

reg  state_3;
always @(posedge clk_out_20 or posedge rst) begin
	if (rst) begin
		state_3 <= 1'b1;
	end
	else 
		if(cnt== 4'b1111)
			state_3 <= 1'b0;
	else 
		if(cnt== 4'b0000)
			state_3 <= 1'b0;
	else 
		if(cnt== 4'b0001)
			state_3 <= 1'b0;
    else 
      state_3 <= 1'b1;
end

wire TQ;
wire OB;
OSERDESE2 #(
	.DATA_RATE_OQ("DDR"),
	.DATA_RATE_TQ("BUF"),
	.DATA_WIDTH(4'd8),
	.SERDES_MODE("MASTER"),
	.TRISTATE_WIDTH(1'd1)
) OSERDESE2_1 (
	.CLK(sys4x_clk),
	.CLKDIV(clk_out_20),
	.D1(1'b1),
	.D2(1'b1),
	.D3(1'b1),
	.D4(1'b1),
	.D5(1'b1),
	.D6(1'b1),
	.D7(1'b1),
	.D8(1'b1),
	.OCE(1'd1),
	//.RST((sys_rst | main_a7ddrphy_rst_storage)), wuyuxin debug 240507
	.RST(main_a7ddrphy_rst_storage),
	.OQ(ddram_reset_n)
);
PLLE2_ADV #(
	.CLKFBOUT_MULT(5'd16),//16
	.CLKIN1_PERIOD(10.0),//in 20mhz
	.CLKOUT0_DIVIDE(4'd2),//20*16/8=40mhz  20*16/2=160mhz
	.CLKOUT0_PHASE(1'd0),
	.CLKOUT1_DIVIDE(5'd16),//20mhz         20*16/4=80mhz
	.CLKOUT1_PHASE(1'd0),
	.CLKOUT2_DIVIDE(3'd4),//20*16/1=320mhz
	.CLKOUT2_PHASE(1'd0),
	.CLKOUT3_DIVIDE(3'd4),
	.CLKOUT3_PHASE(7'd90),
	.DIVCLK_DIVIDE(1'd1),
	.REF_JITTER1(0.01),
	.STARTUP_WAIT("FALSE")
) PLLE2_ADV (
	.CLKFBIN(pll_no_use),
	.CLKIN1(clk_in_20),
	.PWRDWN(1'd0),
	.RST(~rst_N),
	.CLKFBOUT(pll_no_use),
	.CLKOUT0(clk_out_40),//iodelay_clk
	.CLKOUT1(clk_out_20),//sys_clk
	.CLKOUT2(sys4x_clk),//sys4x_clk
	.CLKOUT3(clk_out_80_90),//sys4x_dqs_clk
	.LOCKED(locked)
);	
endmodule

激励文件:

c 复制代码
`timescale 1ns / 1ps
`define clk_50m 20
`define clk_200m 5
`define clk_data_period 5
module OSERDESE2_TEST_tb( );
							

reg			                 clk     ;//?3???????é?????é??è?¤100MHz???
reg			                 rst     ;//?3?????¤???????é??è?¤é????μ?13?????????
reg                         clk_en  ;
reg                         din1    ;
reg                         din2    ;

wire	dq0;
wire locked;
wire test;
	
reg main_a7ddrphy_rst_storage;
wire ddram_reset_n;
	oserdese2_wrapper x_oserdese2(
    .clk_in_20 (clk),
    .rst_N     (~rst),
    .dq        (dq0),
    .locked    (locked),
    .main_a7ddrphy_rst_storage  (main_a7ddrphy_rst_storage),
    .ddram_reset_n              (ddram_reset_n),
    .test      (test)
    );

    initial begin
        clk = 0;
        //forever #(CYCLE/2) clk = ~clk;
	forever #5 clk = ~clk;
    end

    initial begin
        main_a7ddrphy_rst_storage = 1;
        #2755.1;
        main_a7ddrphy_rst_storage = 0;
    end
    
    initial begin
        rst = 1;
        #2000;
        rst = 0;
	#80000;
	rst = 1;
	$stop;
    end
	

	
endmodule

二、板级测试

直接在仿真文件的基础上,上一章的example_top.v里面其实已经有读写测试数据了,现在只要包一层wrapper就行了:

c 复制代码
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2020/11/04 10:29:22
// Design Name: 
// Module Name: ddr_test
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module ddr_test(
  // Inouts
  inout [15:0]    ddr3_dq,
  inout [1:0]     ddr3_dqs_n,
  inout [1:0]     ddr3_dqs_p,
  // Outputs      
  output [13:0]   ddr3_addr,
  output [2:0]    ddr3_ba,
  output          ddr3_ras_n,
  output          ddr3_cas_n,
  output          ddr3_we_n,
  output          ddr3_reset_n,
  output [0:0]    ddr3_ck_p,
  output [0:0]    ddr3_ck_n,
  output [0:0]    ddr3_cke,
  output [0:0]    ddr3_cs_n,
  output [1:0]    ddr3_dm,
  output [0:0]    ddr3_odt,
  // Inputs
  input           clk,
  input           sys_rst,
  // Outputs
  output uart_tx,
  output          tg_compare_error,
  output          init_calib_complete
);
    
  wire   sys_clk_i;
    
    
  example_top u_ip_top
  (
    .ddr3_dq              (ddr3_dq     ),
    .ddr3_dqs_n           (ddr3_dqs_n  ),
    .ddr3_dqs_p           (ddr3_dqs_p  ),
    .ddr3_addr            (ddr3_addr   ),
    .ddr3_ba              (ddr3_ba     ),
    .ddr3_ras_n           (ddr3_ras_n  ),
    .ddr3_cas_n           (ddr3_cas_n  ),
    .ddr3_we_n            (ddr3_we_n   ),
    .ddr3_reset_n         (ddr3_reset_n),
    .ddr3_ck_p            (ddr3_ck_p   ),
    .ddr3_ck_n            (ddr3_ck_n   ),
    .ddr3_cke             (ddr3_cke    ),
    .ddr3_cs_n            (ddr3_cs_n   ),
    .ddr3_dm              (ddr3_dm     ),
    .ddr3_odt             (ddr3_odt    ),
    .sys_clk_i            (clk   ),
    .init_calib_complete  (init_calib_complete),
    .tg_compare_error     (tg_compare_error),
    .uart_tx              (uart_tx),
    .sys_rst              (sys_rst     )
  );

endmodule

三、ILA及逻分抓波形

ILA抓了几个波形,相比于仿真,数据很正常。

c 复制代码
ila_0 ila_debug (
	.clk(clk), // input wire clk


	.probe0(s_axi_awaddr), // input wire [27:0]  probe0  
	.probe1(s_axi_araddr), // input wire [27:0]  probe1 
	.probe2(s_axi_wdata[9:0]), // input wire [9:0]  probe2 
	.probe3(s_axi_rdata[9:0]), // input wire [9:0]  probe3 
	.probe4(s_axi_rid), // input wire [3:0]  probe4 
	.probe5(s_axi_rresp), // input wire [1:0]  probe5 
	.probe6(s_axi_rvalid), // input wire [0:0]  probe6 
	.probe7(s_axi_rready) // input wire [0:0]  probe7
);

用逻辑分析仪抓了几个,也是比较正常:

目前抓的都是AXI用户接口的,DDR3的不太好抓,后面把过孔撬开,抓了,再更新一次。

四、工程获取及交流

这个项目,网上资料少,作者又是法国人,基本前前后后自己摸索了一年多,趟过一堆坑,哎,一言难尽。后面我会继续更进一下这个软核的training机制,有兴趣的可以留意关注一下。

有需要仿真工程或者技术交流的可以私信我:
邮箱:bumianzhe@126.com
(工程和经验,生命换来的,有偿,拒绝白嫖,非诚勿扰,理解一下🐄🐎)

相关推荐
搬砖的小码农_Sky5 小时前
单片机和FPGA有什么区别?
单片机·嵌入式硬件·fpga开发
Jade-YYS8 小时前
如何判断FPGA能够接入几个Camera
fpga开发
apple_ttt1 天前
SystemVerilog学习——虚拟接口(Virtual Interface)
fpga开发·fpga·systemverilog·uvm
学习路上_write1 天前
FPGA/Verilog,Quartus环境下if-else语句和case语句RT视图对比/学习记录
单片机·嵌入式硬件·qt·学习·fpga开发·github·硬件工程
jjjxxxhhh1232 天前
FPGA,使用场景,相比于单片机的优势
单片机·嵌入式硬件·fpga开发
诚实可靠小郎君95272 天前
FPGA高速设计之Aurora64B/66B的应用与不足的修正
fpga开发·aurora·高速通信
百锦再2 天前
基于Zynq FPGA对雷龙SD NAND的测试
fpga开发
∑狸猫不是猫2 天前
HDLBIts习题(4):边沿检测、分频计数器、多位BCD计数器
fpga开发
黑旋风大李逵2 天前
FPGA使用Verilog实现CAN通信
fpga开发·can通信·sja1000t·fpga实现can通信
hi942 天前
PYNQ 框架 - 中断(INTR)驱动
嵌入式硬件·fpga开发·zynq·pynq