黑金核心板32bitDDR3 MIG核UI接口仿真模型搭建

图2-4-1为黑金开发板上两片DDR3原理图。

1. 搭建仿真模型时需要例化两个ddr3_model,不然仿真时init_calib_complete信号会一直低。

2.还要考虑信号的延时,需要例化WireDelay模块,如Xilinx官方中给的例程中所示,不然app_rd_data数据一直是红色的。

3.自己顶层模块中例化的MIG核中的app_wdf_mask信号一定要给32‘d0,不然读出的app_rd_data数据一直是乱的。

下面贴出test_bench顶层代码


`timescale 1ps/100fs
module	tb_ddr3_rw_top();

   //***************************************************************************
   // Traffic Gen related parameters
   //***************************************************************************
   parameter SIMULATION            = "TRUE";
   parameter PORT_MODE             = "BI_MODE";
   parameter DATA_MODE             = 4'b0010;
   parameter TST_MEM_INSTR_MODE    = "R_W_INSTR_MODE";
   parameter EYE_TEST              = "FALSE";
   parameter DATA_PATTERN          = "DGEN_ALL";
   parameter CMD_PATTERN           = "CGEN_ALL";
   parameter BEGIN_ADDRESS         = 32'h00000000;
   parameter END_ADDRESS           = 32'h00000fff;
   parameter PRBS_EADDR_MASK_POS   = 32'hff000000;

   parameter COL_WIDTH             = 10;
   parameter CS_WIDTH              = 1;
   parameter DM_WIDTH              = 4;
   parameter DQ_WIDTH              = 32;
   parameter DQS_WIDTH             = 4;
   parameter DQS_CNT_WIDTH         = 2;
   parameter DRAM_WIDTH            = 8;
   parameter ECC                   = "OFF";
   parameter RANKS                 = 1;
   parameter ODT_WIDTH             = 1;
   parameter ROW_WIDTH             = 15;
   parameter ADDR_WIDTH            = 29;
   //***************************************************************************
   // The following parameters are mode register settings
   //***************************************************************************
   parameter BURST_MODE            = "8";
   parameter CA_MIRROR             = "OFF";
   parameter CLKIN_PERIOD          = 5000;

   parameter SIM_BYPASS_INIT_CAL   = "FAST";
   parameter TCQ                   = 100;

   parameter RST_ACT_LOW           = 1;
   parameter REFCLK_FREQ           = 200.0;
                                  
   parameter tCK                   = 2500;
   parameter nCK_PER_CLK           = 4;
                                
   parameter DEBUG_PORT            = "OFF";
   parameter DRAM_TYPE             = "DDR3";
  localparam real TPROP_DQS          = 0.00;
  localparam real TPROP_DQS_RD       = 0.00;
  localparam real TPROP_PCB_CTRL     = 0.00;
  localparam real TPROP_PCB_DATA     = 0.00;
  localparam real TPROP_PCB_DATA_RD  = 0.00;

  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;
  localparam real SYSCLK_PERIOD = tCK;
  
  reg                                sys_rst_n;
  wire                               sys_rst;


  reg                     sys_clk_i;
  wire                    sys_clk_i_n;
  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 [(CS_WIDTH*1)-1:0]            ddr3_cs_n_sdram;
  wire [ODT_WIDTH-1:0]               ddr3_odt_sdram;
  reg  [1-1:0]                       ddr3_cke_sdram;
  wire [DM_WIDTH-1:0]                ddr3_dm_sdram;
  wire [DQS_WIDTH-1:0]               ddr3_dqs_p_sdram;
  wire [DQS_WIDTH-1:0]               ddr3_dqs_n_sdram;
  reg [1-1:0]                        ddr3_ck_p_sdram;
  reg [1-1:0]                        ddr3_ck_n_sdram;
  

  //**************************************************************************//
  // Reset Generation
  //**************************************************************************//
  initial begin
    sys_rst_n = 1'b0;
    #RESET_PERIOD
      sys_rst_n = 1'b1;
   end

   assign sys_rst = RST_ACT_LOW ? sys_rst_n : ~sys_rst_n;

  //**************************************************************************//
  // Clock Generation
  //**************************************************************************//

  initial
    sys_clk_i = 1'b0;
  always
    sys_clk_i = #(CLKIN_PERIOD/2.0) ~sys_clk_i;
    
  assign  sys_clk_i_n = ~sys_clk_i;

  initial
    clk_ref_i = 1'b0;
  always
    clk_ref_i = #REFCLK_PERIOD ~clk_ref_i;




  always @( * ) begin
    ddr3_ck_p_sdram      <=  #(TPROP_PCB_CTRL) ddr3_ck_p_fpga;
    ddr3_ck_n_sdram      <=  #(TPROP_PCB_CTRL) ddr3_ck_n_fpga;
    ddr3_addr_sdram[0]   <=  #(TPROP_PCB_CTRL) ddr3_addr_fpga;
    ddr3_addr_sdram[1]   <=  #(TPROP_PCB_CTRL) (CA_MIRROR == "ON") ?
                                                 {ddr3_addr_fpga[ROW_WIDTH-1:9],
                                                  ddr3_addr_fpga[7], ddr3_addr_fpga[8],
                                                  ddr3_addr_fpga[5], ddr3_addr_fpga[6],
                                                  ddr3_addr_fpga[3], ddr3_addr_fpga[4],
                                                  ddr3_addr_fpga[2:0]} :
                                                 ddr3_addr_fpga;
    ddr3_ba_sdram[0]     <=  #(TPROP_PCB_CTRL) ddr3_ba_fpga;
    ddr3_ba_sdram[1]     <=  #(TPROP_PCB_CTRL) (CA_MIRROR == "ON") ?
                                                 {ddr3_ba_fpga[3-1:2],
                                                  ddr3_ba_fpga[0],
                                                  ddr3_ba_fpga[1]} :
                                                 ddr3_ba_fpga;
    ddr3_ras_n_sdram     <=  #(TPROP_PCB_CTRL) ddr3_ras_n_fpga;
    ddr3_cas_n_sdram     <=  #(TPROP_PCB_CTRL) ddr3_cas_n_fpga;
    ddr3_we_n_sdram      <=  #(TPROP_PCB_CTRL) ddr3_we_n_fpga;
    ddr3_cke_sdram       <=  #(TPROP_PCB_CTRL) ddr3_cke_fpga;
  end
    

  always @( * )
    ddr3_cs_n_sdram_tmp   <=  #(TPROP_PCB_CTRL) ddr3_cs_n_fpga;
  assign ddr3_cs_n_sdram =  ddr3_cs_n_sdram_tmp;
    

  always @( * )
    ddr3_dm_sdram_tmp <=  #(TPROP_PCB_DATA) ddr3_dm_fpga;//DM signal generation
  assign ddr3_dm_sdram = ddr3_dm_sdram_tmp;
    

  always @( * )
    ddr3_odt_sdram_tmp  <=  #(TPROP_PCB_CTRL) ddr3_odt_fpga;
  assign ddr3_odt_sdram =  ddr3_odt_sdram_tmp;
    

// Controlling the bi-directional BUS

  genvar dqwd;
  generate
    for (dqwd = 1;dqwd < DQ_WIDTH;dqwd = dqwd+1) begin : dq_delay
      WireDelay #
       (
        .Delay_g    (TPROP_PCB_DATA),
        .Delay_rd   (TPROP_PCB_DATA_RD),
        .ERR_INSERT ("OFF")
       )
      u_delay_dq
       (
        .A             (ddr3_dq_fpga[dqwd]),
        .B             (ddr3_dq_sdram[dqwd]),
        .reset         (sys_rst_n),
        .phy_init_done (init_calib_complete)
       );
    end
          WireDelay #
       (
        .Delay_g    (TPROP_PCB_DATA),
        .Delay_rd   (TPROP_PCB_DATA_RD),
        .ERR_INSERT ("OFF")
       )
      u_delay_dq_0
       (
        .A             (ddr3_dq_fpga[0]),
        .B             (ddr3_dq_sdram[0]),
        .reset         (sys_rst_n),
        .phy_init_done (init_calib_complete)
       );
  endgenerate

  genvar dqswd;
  generate
    for (dqswd = 0;dqswd < DQS_WIDTH;dqswd = dqswd+1) begin : dqs_delay
      WireDelay #
       (
        .Delay_g    (TPROP_DQS),
        .Delay_rd   (TPROP_DQS_RD),
        .ERR_INSERT ("OFF")
       )
      u_delay_dqs_p
       (
        .A             (ddr3_dqs_p_fpga[dqswd]),
        .B             (ddr3_dqs_p_sdram[dqswd]),
        .reset         (sys_rst_n),
        .phy_init_done (init_calib_complete)
       );

      WireDelay #
       (
        .Delay_g    (TPROP_DQS),
        .Delay_rd   (TPROP_DQS_RD),
        .ERR_INSERT ("OFF")
       )
      u_delay_dqs_n
       (
        .A             (ddr3_dqs_n_fpga[dqswd]),
        .B             (ddr3_dqs_n_sdram[dqswd]),
        .reset         (sys_rst_n),
        .phy_init_done (init_calib_complete)
       );
    end
  endgenerate
    
//============================< 被测试模块例化 >===============================
//例化DDR3读写测试-------------------
ddr3_rw_top	ddr3_rw_top_inst(
   .ddr3_dq			(ddr3_dq_fpga	    ),			//DDR3 数据
   .ddr3_dqs_n		(ddr3_dqs_n_fpga    ),      	//DDR3 dqs负
   .ddr3_dqs_p		(ddr3_dqs_p_fpga    ),      	//DDR3 dqs正       
   .ddr3_addr		(ddr3_addr_fpga     ),       	//DDR3 地址
   .ddr3_ba			(ddr3_ba_fpga       ),         	//DDR3 banck 选择
   .ddr3_ras_n		(ddr3_ras_n_fpga    ),      	//DDR3 行选择
   .ddr3_cas_n		(ddr3_cas_n_fpga    ),      	//DDR3 列选择
   .ddr3_we_n		(ddr3_we_n_fpga     ),       	//DDR3 读写选择
   .ddr3_reset_n	(ddr3_reset_n	    ),    		//DDR3 复位
   .ddr3_ck_p		(ddr3_ck_p_fpga		),       	//DDR3 时钟正
   .ddr3_ck_n		(ddr3_ck_n_fpga	    ),       	//DDR3 时钟负
   .ddr3_cke		(ddr3_cke_fpga      ),        	//DDR3 时钟使能
   .ddr3_cs_n		(ddr3_cs_n_fpga	    ),       	//DDR3 片选
   .ddr3_dm			(ddr3_dm_fpga 	    ),         	//DDR3_dm
   .ddr3_odt		(ddr3_odt_fpga 		),       	//DDR3_odt
   .sys_clk_p       (sys_clk_i          ),                    //system clock positive on board
   .sys_clk_n       (sys_clk_i_n        ),                    //system clock negative on board
   .rst_n           (sys_rst            ),                        //reset ,low active
   .error_flag		(tg_compare_error	)			//错误标志
);   
  //**************************************************************************//
  // Memory Models instantiations
  //**************************************************************************//
 //**************************************************************************//
  // Memory Models instantiations
  //**************************************************************************//

  genvar r,i;
  generate
    for (r = 0; r < CS_WIDTH; r = r + 1) begin: mem_rnk
      if(DQ_WIDTH/16) begin: mem
        for (i = 0; i < NUM_COMP; i = i + 1) begin: gen_mem
          ddr3_model u_comp_ddr3
            (
             .rst_n   (ddr3_reset_n),
             .ck      (ddr3_ck_p_sdram),
             .ck_n    (ddr3_ck_n_sdram),
             .cke     (ddr3_cke_sdram[r]),
             .cs_n    (ddr3_cs_n_sdram[r]),
             .ras_n   (ddr3_ras_n_sdram),
             .cas_n   (ddr3_cas_n_sdram),
             .we_n    (ddr3_we_n_sdram),
             .dm_tdqs (ddr3_dm_sdram[(2*(i+1)-1):(2*i)]),
             .ba      (ddr3_ba_sdram[r]),
             .addr    (ddr3_addr_sdram[r]),
             .dq      (ddr3_dq_sdram[16*(i+1)-1:16*(i)]),
             .dqs     (ddr3_dqs_p_sdram[(2*(i+1)-1):(2*i)]),
             .dqs_n   (ddr3_dqs_n_sdram[(2*(i+1)-1):(2*i)]),
             .tdqs_n  (),
             .odt     (ddr3_odt_sdram[r])
             );
        end
      end
      if (DQ_WIDTH%16) begin: gen_mem_extrabits
        ddr3_model u_comp_ddr3
          (
           .rst_n   (ddr3_reset_n),
           .ck      (ddr3_ck_p_sdram),
           .ck_n    (ddr3_ck_n_sdram),
           .cke     (ddr3_cke_sdram[r]),
           .cs_n    (ddr3_cs_n_sdram[r]),
           .ras_n   (ddr3_ras_n_sdram),
           .cas_n   (ddr3_cas_n_sdram),
           .we_n    (ddr3_we_n_sdram),
           .dm_tdqs ({ddr3_dm_sdram[DM_WIDTH-1],ddr3_dm_sdram[DM_WIDTH-1]}),
           .ba      (ddr3_ba_sdram[r]),
           .addr    (ddr3_addr_sdram[r]),
           .dq      ({ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)],
                      ddr3_dq_sdram[DQ_WIDTH-1:(DQ_WIDTH-8)]}),
           .dqs     ({ddr3_dqs_p_sdram[DQS_WIDTH-1],
                      ddr3_dqs_p_sdram[DQS_WIDTH-1]}),
           .dqs_n   ({ddr3_dqs_n_sdram[DQS_WIDTH-1],
                      ddr3_dqs_n_sdram[DQS_WIDTH-1]}),
           .tdqs_n  (),
           .odt     (ddr3_odt_sdram[r])
           );
      end
    end
  endgenerate

    
endmodule

 ddr3_rw_top.v(借用他人的demo)

`timescale 1ns / 1ps

module ddr3_rw_top(
// Inouts
inout [31:0]                       ddr3_dq,                     //ddr3 data
inout [3:0]                        ddr3_dqs_n,                  //ddr3 dqs negative
inout [3:0]                        ddr3_dqs_p,                  //ddr3 dqs positive
// Outputs
output [14:0]                     ddr3_addr,                    //ddr3 address
output [2:0]                      ddr3_ba,                      //ddr3 bank
output                            ddr3_ras_n,                   //ddr3 ras_n
output                            ddr3_cas_n,                   //ddr3 cas_n
output                            ddr3_we_n,                    //ddr3 write enable 
output                            ddr3_reset_n,                 //ddr3 reset,
output [0:0]                      ddr3_ck_p,                    //ddr3 clock negative
output [0:0]                      ddr3_ck_n,                    //ddr3 clock positive
output [0:0]                      ddr3_cke,                     //ddr3_cke,
output [0:0]                      ddr3_cs_n,                    //ddr3 chip select,
output [3:0]                      ddr3_dm,                      //ddr3_dm
output [0:0]                      ddr3_odt,                     //ddr3_odt
input                             sys_clk_p,                    //system clock positive on board
input                             sys_clk_n,                    //system clock negative on board
input                             rst_n ,                        //reset ,low active
//标志相关------------------------------
 output             	error_flag					//错误指示信号
);
                
//============================< 信号定义 >======================================                      
//parameter define
parameter	integer		WR_LEN		= 512	;		//读、写长度	
parameter	integer		DATA_WIDTH	= 256	;	    //数据位宽,突发长度为8,32bit,共256bit
parameter	integer		ADDR_WIDTH	= 29	;	    //根据MIG例化而来
//wire define  
wire                  	ui_clk				;		//用户时钟
wire [ADDR_WIDTH - 1:0]	app_addr			;		//DDR3 地址
wire [2:0]            	app_cmd				;		//用户读写命令
wire                  	app_en				;		//MIG IP核使能
wire                  	app_rdy				;		//MIG IP核空闲
wire [DATA_WIDTH - 1:0]	app_rd_data			;		//用户读数据
wire                  	app_rd_data_end		;     	//突发读当前时钟最后一个数据 
wire                  	app_rd_data_valid	;   	//读数据有效
wire [DATA_WIDTH - 1:0]	app_wdf_data		;		//用户写数据 
wire                  	app_wdf_end			;		//突发写当前时钟最后一个数据 
wire [31:0]           	app_wdf_mask		;		//写数据屏蔽
wire                  	app_wdf_rdy			;		//写空闲
wire                  	app_wdf_wren		;		//DDR3 写使能 
wire                   app_sr_active;
wire                   app_ref_ack;
wire                    app_zq_ack;                 
//wire                  	clk_ref_i			;		//DDR3参考时钟
//wire                  	sys_clk_i			;		//MIG IP核输入时钟
wire                  	sys_clk_200MHz		;		//200M时钟
wire                  	ui_clk_sync_rst		;     	//用户复位信号
wire                  	init_calib_complete	;		//校准完成信号
 
//*****************************************************************************************
//**                    main code
//*****************************************************************************************
 
//============================< 例化DDR3读写测试模块 >======================================
 ddr3_rw #(
	.WR_LEN							(WR_LEN					),
	.DATA_WIDTH                     (DATA_WIDTH 			),
	.ADDR_WIDTH                     (ADDR_WIDTH 			)
 )
 u_ddr3_rw(
    .ui_clk               			(ui_clk					),                
    .ui_clk_sync_rst      			(ui_clk_sync_rst		),       
    .init_calib_complete  			(init_calib_complete	),
	
    .app_rdy              			(app_rdy				),
    .app_wdf_rdy          			(app_wdf_rdy			),
    .app_rd_data_valid    			(app_rd_data_valid		),
    .app_rd_data          			(app_rd_data			),   
    .app_addr             			(app_addr				),
    .app_en               			(app_en					),
    .app_wdf_wren         			(app_wdf_wren			),
    .app_wdf_end          			(app_wdf_end			),
    .app_cmd              			(app_cmd				),
    .app_wdf_data         			(app_wdf_data			),
   
    .error_flag           			(error_flag				)
    );
    
IBUFDS sys_clk_ibufgds
(
.O                              (sys_clk_200MHz           ),
.I                              (sys_clk_p                ),
.IB                             (sys_clk_n                )
);	
//============================< 例化MIG IP核 >===============================================

  ddr3 u_ddr3_inst (
    // Memory interface ports
    .ddr3_addr                      (ddr3_addr              ),  // output [14:0]		ddr3_addr
    .ddr3_ba                        (ddr3_ba                ),  // output [2:0]		ddr3_ba
    .ddr3_cas_n                     (ddr3_cas_n             ),  // output			ddr3_cas_n
    .ddr3_ck_n                      (ddr3_ck_n              ),  // output [0:0]		ddr3_ck_n
    .ddr3_ck_p                      (ddr3_ck_p              ),  // output [0:0]		ddr3_ck_p
    .ddr3_cke                       (ddr3_cke               ),  // output [0:0]		ddr3_cke
    .ddr3_ras_n                     (ddr3_ras_n             ),  // output			ddr3_ras_n
    .ddr3_reset_n                   (ddr3_reset_n           ),  // output			ddr3_reset_n
    .ddr3_we_n                      (ddr3_we_n              ),  // output			ddr3_we_n
    .ddr3_dq                        (ddr3_dq                ),  // inout [31:0]		ddr3_dq
    .ddr3_dqs_n                     (ddr3_dqs_n             ),  // inout [3:0]		ddr3_dqs_n
    .ddr3_dqs_p                     (ddr3_dqs_p             ),  // inout [3:0]		ddr3_dqs_p
    .init_calib_complete            (init_calib_complete    ),  // output			init_calib_complete
     
	.ddr3_cs_n                      (ddr3_cs_n              ),  // output [0:0]		ddr3_cs_n
    .ddr3_dm                        (ddr3_dm                ),  // output [3:0]		ddr3_dm
    .ddr3_odt                       (ddr3_odt               ),  // output [0:0]		ddr3_odt
    // Application interface ports
    .app_addr                       (app_addr               ),  // input [28:0]		app_addr
    .app_cmd                        (app_cmd                ),  // input [2:0]		app_cmd
    .app_en                         (app_en                 ),  // input				app_en
    .app_wdf_data                   (app_wdf_data           ),  // input [255:0]		app_wdf_data
    .app_wdf_end                    (app_wdf_end            ),  // input				app_wdf_end
    .app_wdf_wren                   (app_wdf_wren           ),  // input				app_wdf_wren
    .app_rd_data                    (app_rd_data            ),  // output [255:0]		app_rd_data
    .app_rd_data_end                (app_rd_data_end        ),  // output			app_rd_data_end
    .app_rd_data_valid              (app_rd_data_valid      ),  // output			app_rd_data_valid
    .app_rdy                        (app_rdy                ),  // output			app_rdy
    .app_wdf_rdy                    (app_wdf_rdy            ),  // output			app_wdf_rdy
    .app_sr_req                     (1'b0                   ),  // input			app_sr_req
    .app_ref_req                    (1'b0                   ),  // input			app_ref_req
    .app_zq_req                     (1'b0                   ),  // input			app_zq_req
    .app_sr_active                  (app_sr_active          ),  // output			app_sr_active
    .app_ref_ack                    (app_ref_ack            ),  // output			app_ref_ack
    .app_zq_ack                     (app_zq_ack             ),  // output			app_zq_ack
    .ui_clk                         (ui_clk                 ),  // output			ui_clk
    .ui_clk_sync_rst                (ui_clk_sync_rst        ),  // output			ui_clk_sync_rst
    .app_wdf_mask                   (32'd0                  ),  // input [31:0]		app_wdf_mask         ***** must be set to zero ****
    // System Clock Ports
    .sys_clk_i                      (sys_clk_200MHz         ),
    .sys_rst                        (rst_n                  ) // input sys_rst
    );
    
    
  ila_ddr3_32 u_ila (
	.clk                   (ui_clk                   ), // input wire clk
	.probe0                (app_rd_data_valid        ), // input wire [0:0]  probe0  
	.probe1                (app_rd_data              ) // input wire [255:0]  probe1
);  
                       
endmodule

ddr3_rw.v(借用他人demo)

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2022/06/01 21:41:11
// Design Name: 
// Module Name: ddr3_rw
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
module ddr3_rw #
( 
	parameter	integer					WR_LEN		= 1024		,	//读、写长度
	parameter	integer					DATA_WIDTH	= 256		,	//数据位宽,突发长度为8,32bit,共256bit
	parameter	integer					ADDR_WIDTH	= 29			//根据MIG例化而来
)(   
//DDR3相关 ------------------------------------------------------      
    input                   			ui_clk					,	//用户时钟
    input                   			ui_clk_sync_rst			,	//复位,高有效
    input                   			init_calib_complete		,	//DDR3初始化完成
//DDR3相关 ------------------------------------------------------	
    input                   			app_rdy					,	//MIG 命令接收准备好标致
    input                   			app_wdf_rdy				,	//MIG数据接收准备好
    input                   			app_rd_data_valid		,	//读数据有效
    input		[DATA_WIDTH - 1:0]   	app_rd_data				,	//用户读数据
    output	reg	[ADDR_WIDTH - 1:0]		app_addr				,	//DDR3地址                      
    output	                			app_en					,	//MIG IP发送命令使能
    output	                			app_wdf_wren			,	//用户写数据使能
    output	                			app_wdf_end				,	//突发写当前时钟最后一个数据 
    output		[2:0]     				app_cmd					,	//MIG IP核操作命令,读或者写
    output	reg	[DATA_WIDTH - 1:0]		app_wdf_data			,	//用户写数据
//指示 ----------------------------------------------------------		
    output	reg             			error_flag     	    	   	//读写错误标志
    );
	
//============================< 信号定义 >======================================
//测试状态机-----------------------------------------				
localparam					IDLE	= 4'b0001		;            	//空闲状态
localparam					WRITE 	= 4'b0010		;            	//写状态
localparam					WAIT  	= 4'b0100		;            	//读到写过度等待
localparam					READ  	= 4'b1000		;            	//读状态
//reg define ----------------------------------------
reg	[3:0]					cur_state				;				//三段式状态机现态
reg	[3:0]					next_state				;				//三段式状态机次态
reg	[ADDR_WIDTH - 1:0]		rd_addr_cnt				;				//用户读地址计数
reg	[ADDR_WIDTH - 1:0]		wr_addr_cnt				;				//用户写地址计数
reg	[ADDR_WIDTH - 1:0]		rd_cnt					;				//实际读地址标记
//wire define ---------------------------------------										
wire						error					;     			//读写错误标记
wire						rst_n					;     			//复位,低有效
wire						wr_proc					;				//拉高表示写过程进行
wire						wr_last					;				//拉高表示写入最后一个数据
wire						rd_addr_last			;				//拉高表示是最后一个读地址
 
 //*********************************************************************************************
//**                    main code
//**********************************************************************************************
//==========================================================================
//==    信号赋值
//==========================================================================  
assign rst_n = ~ui_clk_sync_rst;
//当MIG准备好后,用户同步准备好
assign app_en = app_rdy && ((cur_state == WRITE && app_wdf_rdy) || cur_state == READ);              
//写指令,命令接收和数据接收都准备好,此时拉高写使能
assign app_wdf_wren = (cur_state == WRITE) && wr_proc;
//由于DDR3芯片时钟和用户时钟的分频选择4:1,突发长度为8,故两个信号相同
assign app_wdf_end = app_wdf_wren; 
assign app_cmd = (cur_state == READ) ? 3'd1 :3'd0;					//处于读的时候命令值为1,其他时候命令值为0	
assign wr_proc = ~app_cmd && app_rdy && app_wdf_rdy;				//拉高表示写过程进行
//处于写使能且是最后一个数据
assign wr_last = app_wdf_wren && (wr_addr_cnt == WR_LEN - 1) ;
//处于读指令、读有效且是最后一个数据
assign rd_addr_last = (rd_addr_cnt == WR_LEN - 1) && app_rdy && app_cmd;
  
//==========================================================================
//==    状态机
//==========================================================================    
 
always @(posedge ui_clk or negedge rst_n) begin
	if(~rst_n)
		cur_state <= IDLE;
	else
		cur_state <= next_state;
end
 
always @(*) begin
	if(~rst_n)
		next_state = IDLE;
	else
		case(cur_state)
			IDLE:
				if(init_calib_complete)					//MIG IP核初始化完成 
					next_state = WRITE;				
				else				
					next_state = IDLE;				
			WRITE:				
				if(wr_last) 							//写入最后一个数据
					next_state = WAIT;				
				else				
					next_state = WRITE;							
			WAIT:				
					next_state = READ;				
			READ:				
				if(rd_addr_last) 						//写入最后一个读地址,数据读出需要时间
					next_state = IDLE;
				else
					next_state = READ;					
			default:;
		endcase
end
 
always @(posedge ui_clk or negedge rst_n) begin
    if(~rst_n) begin				 
        app_wdf_data <= 0;     
        wr_addr_cnt  <= 0;      
        rd_addr_cnt  <= 0;       
        app_addr     <= 0;          
    end
	else
        case(cur_state)
            IDLE:begin
                app_wdf_data <= 0;   
                wr_addr_cnt  <= 0;     
                rd_addr_cnt  <= 0;       
                app_addr     <= 0;
             end
            WRITE:begin
                if(wr_proc)begin   						//写条件满足
                    app_wdf_data <= app_wdf_data + 1;  	//写数据自加
                    wr_addr_cnt  <= wr_addr_cnt + 1;   	//写地址自加
                    app_addr     <= app_addr + 8;      	//DDR3 地址加8
                end
                else begin                             	//写条件不满足,保持当前值
                    app_wdf_data <= app_wdf_data;      
                    wr_addr_cnt  <= wr_addr_cnt;
                    app_addr     <= app_addr; 
                end
              end
            WAIT:begin                                                  
                rd_addr_cnt <= 0;                		//读地址复位
                app_addr    <= 0;                		//DDR3读从地址0开始
              end
            READ:begin                               	//读到设定的地址长度     
                if(app_rdy)begin                  		//若MIG已经准备好,则开始读
                    rd_addr_cnt <= rd_addr_cnt + 1'd1; 	//用户地址每次加一
                    app_addr    <= app_addr + 8;       	//DDR3地址加8
                end
                else begin                             	//若MIG没准备好,则保持原值
                    rd_addr_cnt <= rd_addr_cnt;
                    app_addr    <= app_addr; 
                end
              end
            default:begin
                app_wdf_data <= 0;
                wr_addr_cnt  <= 0;
                rd_addr_cnt  <= 0;
                app_addr     <= 0;
            end
        endcase
end   
//==========================================================================
//==    其他
//==========================================================================
 
//读信号有效,且读出的数不是写入的数时,将错误标志位拉高
assign error = (app_rd_data_valid && (rd_cnt!=app_rd_data));  
                      
//寄存状态标志位
always @(posedge ui_clk or negedge rst_n) begin
    if(~rst_n) 
        error_flag <= 0;
    else if(error)
        error_flag <= 1;
end
 
//对DDR3实际读数据个数编号计数
always @(posedge ui_clk or negedge rst_n) begin
    if(~rst_n) 
        rd_cnt <= 0;
	//若计数到读写长度,且读有效,地址计数器则置0   		
    else if(app_rd_data_valid && rd_cnt == WR_LEN - 1)
         rd_cnt <= 0;              
    else if (app_rd_data_valid )	//读有效情况下每个时钟+1
        rd_cnt <= rd_cnt + 1;
end
 
endmodule

仿真结果如下图所示:

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值