前言
3.图像写请求模块(img_write_req_gen.v)仿真
5.图像通道写仲裁模块(mem_write_arbit.v)仿真(可选,非必须)
9.图像通道读仲裁模块(mem_read_arbit.v)仿真(可选,非必须)
前言
上一篇文章谈到如何利用Xilinx 7系列FPGA实现DDR3 SDRAM的读写操作(详情请参见基于FPGA+MIG+AXI4实现DDR3 SDRAM读写操作(附代码)_春风细雨无声的博客-CSDN博客),大家积极留言或发消息联系希望能用仿真的形式和大家进一步沟通。本篇文章利用第三方软件Modelsim(没有该软件的小伙伴可以联系我获取)对工程中涉及到的各模块进行仿真,给出仿真时序图,帮助大家进一步理解FPGA实现DDR3 SDRAM读写的整个过程。
一、仿真工程结构
首先建立仿真工程,需要包含Test Bench文件、源文件顶层模块、DDR3模型和连接线延迟等模块,工程结构如图所示。
二、Test Bench文件代码
Test Bench文件是整个工程仿真的第一步,如何用代码来描述Test Bench文件可能是大家比较关心的问题,此处直接附上源码,如下。
`timescale 1ps/100fs
module tb_top_design;
//***************************************************************************
// Traffic Gen related parameters
//***************************************************************************
parameter SIMULATION = "TRUE";
parameter BEGIN_ADDRESS = 32'h00000000;
parameter END_ADDRESS = 32'h00000fff;
parameter PRBS_EADDR_MASK_POS = 32'hff000000;
//***************************************************************************
// The following parameters refer to width of various ports
//***************************************************************************
parameter COL_WIDTH = 10;
// # of memory Column Address bits.
parameter CS_WIDTH = 1;
// # of unique CS outputs to memory.
parameter DM_WIDTH = 2;
// # of DM (data mask)
parameter DQ_WIDTH = 16;
// # of DQ (data)
parameter DQS_WIDTH = 2;
parameter DQS_CNT_WIDTH = 1;
// = ceil(log2(DQS_WIDTH))
parameter DRAM_WIDTH = 8;
// # of DQ per DQS
parameter ECC = "OFF";
parameter RANKS = 1;
// # of Ranks.
parameter ODT_WIDTH = 1;
// # of ODT outputs to memory.
parameter ROW_WIDTH = 15;
// # of memory Row Address bits.
parameter ADDR_WIDTH = 29;
// # = RANK_WIDTH + BANK_WIDTH
// + ROW_WIDTH + COL_WIDTH;
// Chip Select is always tied to low for
// single rank devices
//***************************************************************************
// The following parameters are mode register settings
//***************************************************************************
parameter BURST_MODE = "8";
// DDR3 SDRAM:
// Burst Length (Mode Register 0).
// # = "8", "4", "OTF".
// DDR2 SDRAM:
// Burst Length (Mode Register).
// # = "8", "4".
parameter CA_MIRROR = "OFF";
// C/A mirror opt for DDR3 dual rank
//***************************************************************************
// The following parameters are multiplier and divisor factors for PLLE2.
// Based on the selected design frequency these parameters vary.
//***************************************************************************
parameter CLKIN_PERIOD = 5000;
// Input Clock Period
//***************************************************************************
// Simulation parameters
//***************************************************************************
parameter SIM_BYPASS_INIT_CAL = "FAST";
// # = "SIM_INIT_CAL_FULL" - Complete
// memory init &
// calibration sequence
// # = "SKIP" - Not supported
// # = "FAST" - Complete memory init & use
// abbreviated calib sequence
//***************************************************************************
// IODELAY and PHY related parameters
//***************************************************************************
parameter TCQ = 100;
//***************************************************************************
// IODELAY and PHY related parameters
//***************************************************************************
parameter RST_ACT_LOW = 1;
// =1 for active low reset,
// =0 for active high.
//***************************************************************************
// Referece clock frequency parameters
//***************************************************************************
parameter REFCLK_FREQ = 200.0;
// IODELAYCTRL reference clock frequency
//***************************************************************************
// System clock frequency parameters
//***************************************************************************
parameter tCK = 2500;
// memory tCK paramter.
// # = Clock Period in pS.
parameter nCK_PER_CLK = 4;
// # of memory CKs per fabric CLK
//***************************************************************************
// AXI4 Shim parameters
//***************************************************************************
parameter C_S_AXI_ID_WIDTH = 4;
// Width of all master and slave ID signals.
// # = >= 1.
parameter C_S_AXI_ADDR_WIDTH = 29;
// Width of S_AXI_AWADDR, S_AXI_ARADDR, M_AXI_AWADDR and
// M_AXI_ARADDR for all SI/MI slots.
// # = 32.
parameter C_S_AXI_DATA_WIDTH = 64;
// Width of WDATA and RDATA on SI slot.
// Must be <= APP_DATA_WIDTH.
// # = 32, 64, 128, 256.
parameter C_S_AXI_SUPPORTS_NARROW_BURST = 0;
// Indicates whether to instatiate upsizer
// Range: 0, 1
//***************************************************************************
// Debug and Internal parameters
//***************************************************************************
parameter DEBUG_PORT = "OFF";
// # = "ON" Enable debug signals/controls.
// = "OFF" Disable debug signals/controls.
//***************************************************************************
// Debug and Internal parameters
//***************************************************************************
parameter DRAM_TYPE = "DDR3";
//**************************************************************************//
// Local parameters Declarations
//**************************************************************************//
localparam real TPROP_DQS = 0.00;
// Delay for DQS signal during Write Operation
localparam real TPROP_DQS_RD = 0.00;
// Delay for DQS signal during Read Operation
localparam real TPROP_PCB_CTRL = 0.00;
// Delay for Address and Ctrl signals
localparam real TPROP_PCB_DATA = 0.00;
// Delay for data signal during Write operation
localparam real TPROP_PCB_DATA_RD = 0.00;
// Delay for data signal during Read operation
localparam MEMORY_WIDTH = 16;
localparam NUM_COMP = DQ_WIDTH/MEMORY_WIDTH;
localparam ECC_TEST = "OFF" ;
localparam ERR_INSERT = (ECC_TEST == "ON") ? "OFF" : ECC ;
localparam real REFCLK_PERIOD = (1000000.0/(2*REFCLK_FREQ));
localparam RESET_PERIOD = 200000; //in pSec
localparam real SYSCLK_PERIOD = tCK;
//**************************************************************************//
// Wire Declarations
//**************************************************************************//
reg sys_rst_n;
wire sys_rst;
reg sys_clk_i;
reg clk_ref_i;
wire ddr3_reset_n;
wire [DQ_WIDTH-1:0] ddr3_dq_fpga;
wire [DQS_WIDTH-1:0] ddr3_dqs_p_fpga;
wire [DQS_WIDTH-1:0] ddr3_dqs_n_fpga;
wire [ROW_WIDTH-1:0] ddr3_addr_fpga;
wire [3-1:0] ddr3_ba_fpga;
wire ddr3_ras_n_fpga;
wire ddr3_cas_n_fpga;
wire ddr3_we_n_fpga;
wire [1-1:0] ddr3_cke_fpga;
wire [1-1:0] ddr3_ck_p_fpga;
wire [1-1:0] ddr3_ck_n_fpga;
wire init_calib_complete;
wire tg_compare_error;
wire [(CS_WIDTH*1)-1:0] ddr3_cs_n_fpga;
wire [DM_WIDTH-1:0] ddr3_dm_fpga;
wire [ODT_WIDTH-1:0] ddr3_odt_fpga;
reg [(CS_WIDTH*1)-1:0] ddr3_cs_n_sdram_tmp;
reg [DM_WIDTH-1:0] ddr3_dm_sdram_tmp;
reg [ODT_WIDTH-1:0] ddr3_odt_sdram_tmp;
wire [DQ_WIDTH-1:0] ddr3_dq_sdram;
reg [ROW_WIDTH-1:0] ddr3_addr_sdram [0:1];
reg [3-1:0] ddr3_ba_sdram [0:1];
reg ddr3_ras_n_sdram;
reg ddr3_cas_n_sdram;
reg ddr3_we_n_sdram;
wire