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

article/2025/3/10 21:11:08

图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 beginsys_rst_n = 1'b0;#RESET_PERIODsys_rst_n = 1'b1;endassign sys_rst = RST_ACT_LOW ? sys_rst_n : ~sys_rst_n;//**************************************************************************//// Clock Generation//**************************************************************************//initialsys_clk_i = 1'b0;alwayssys_clk_i = #(CLKIN_PERIOD/2.0) ~sys_clk_i;assign  sys_clk_i_n = ~sys_clk_i;initialclk_ref_i = 1'b0;alwaysclk_ref_i = #REFCLK_PERIOD ~clk_ref_i;always @( * ) beginddr3_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;endalways @( * )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 generationassign 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 BUSgenvar dqwd;generatefor (dqwd = 1;dqwd < DQ_WIDTH;dqwd = dqwd+1) begin : dq_delayWireDelay #(.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));endWireDelay #(.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));endgenerategenvar dqswd;generatefor (dqswd = 0;dqswd < DQS_WIDTH;dqswd = dqswd+1) begin : dqs_delayWireDelay #(.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));endendgenerate//============================< 被测试模块例化 >===============================
//例化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;generatefor (r = 0; r < CS_WIDTH; r = r + 1) begin: mem_rnkif(DQ_WIDTH/16) begin: memfor (i = 0; i < NUM_COMP; i = i + 1) begin: gen_memddr3_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]));endendif (DQ_WIDTH%16) begin: gen_mem_extrabitsddr3_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]));endendendgenerateendmodule

 ddr3_rw_top.v(借用他人的demo)

`timescale 1ns / 1psmodule 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,共256bitparameter	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) beginif(~rst_n)cur_state <= IDLE;elsecur_state <= next_state;
endalways @(*) beginif(~rst_n)next_state = IDLE;elsecase(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;elsenext_state = READ;					default:;endcase
endalways @(posedge ui_clk or negedge rst_n) beginif(~rst_n) begin				 app_wdf_data <= 0;     wr_addr_cnt  <= 0;      rd_addr_cnt  <= 0;       app_addr     <= 0;          endelsecase(cur_state)IDLE:beginapp_wdf_data <= 0;   wr_addr_cnt  <= 0;     rd_addr_cnt  <= 0;       app_addr     <= 0;endWRITE:beginif(wr_proc)begin   						//写条件满足app_wdf_data <= app_wdf_data + 1;  	//写数据自加wr_addr_cnt  <= wr_addr_cnt + 1;   	//写地址自加app_addr     <= app_addr + 8;      	//DDR3 地址加8endelse begin                             	//写条件不满足,保持当前值app_wdf_data <= app_wdf_data;      wr_addr_cnt  <= wr_addr_cnt;app_addr     <= app_addr; endendWAIT:begin                                                  rd_addr_cnt <= 0;                		//读地址复位app_addr    <= 0;                		//DDR3读从地址0开始endREAD:begin                               	//读到设定的地址长度     if(app_rdy)begin                  		//若MIG已经准备好,则开始读rd_addr_cnt <= rd_addr_cnt + 1'd1; 	//用户地址每次加一app_addr    <= app_addr + 8;       	//DDR3地址加8endelse begin                             	//若MIG没准备好,则保持原值rd_addr_cnt <= rd_addr_cnt;app_addr    <= app_addr; endenddefault:beginapp_wdf_data <= 0;wr_addr_cnt  <= 0;rd_addr_cnt  <= 0;app_addr     <= 0;endendcase
end   
//==========================================================================
//==    其他
//==========================================================================//读信号有效,且读出的数不是写入的数时,将错误标志位拉高
assign error = (app_rd_data_valid && (rd_cnt!=app_rd_data));  //寄存状态标志位
always @(posedge ui_clk or negedge rst_n) beginif(~rst_n) error_flag <= 0;else if(error)error_flag <= 1;
end//对DDR3实际读数据个数编号计数
always @(posedge ui_clk or negedge rst_n) beginif(~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 )	//读有效情况下每个时钟+1rd_cnt <= rd_cnt + 1;
endendmodule

仿真结果如下图所示:

 


http://chatgpt.dhexx.cn/article/Q9EpCp5n.shtml

相关文章

基于FPGA的UDP 通信(五)

引言 前文链接&#xff1a; 基于FPGA的UDP 通信&#xff08;一&#xff09; 基于FPGA的UDP 通信&#xff08;二&#xff09; 基于FPGA的UDP 通信&#xff08;三&#xff09; 基于FPGA的UDP 通信&#xff08;四&#xff09; 本文基于FPGA设计千兆以太网通信模块UDP数据发送…

Verilog:【8】基于FPGA实现SD NAND FLASH的SPI协议读写

碎碎念&#xff1a; 终于熬过了期末周&#xff0c;可以开始快乐的开发之旅了。 这一期作为一千粉后的首篇博客&#xff0c;由于之后项目会涉及到相关的部分&#xff0c;因此介绍的是使用FPGA实现SD NAND FLASH的读写操作&#xff0c;以雷龙发展提供的CS创世SD NAND FLASH样品为…

【FPGA算法加速】运行PYNQ,对应FPGA芯片版本:赛灵思黑金AX7020

黑金AX7020开放板实物图&#xff1a; 这里的右下角需要连接本地的路由器&#xff0c;图中并未连上&#xff0c;PC端与FPGA在同一路由的网下&#xff0c;到时候PC端可以在线访问FPGA的资源。 一、连接FPGA硬件设备 1、 SD卡插回开发板&#xff0c;确认开发板启动模式为 SD卡模…

黑金Xilinx FPGA学习笔记(一)verilogHDL扫盲文-(1)

verilog简介 HDL 顾名思义Hardware Description Languag verilog HDL 语言的语法和格式都比较随便&#xff0c;它没有 VDL HDL 语言那么严谨&#xff0c;因此受到了广泛的应用。 0.3RTL级和组合逻辑级 笔者的眼中 Verilog HDL 语言建立的硬件模块可以 分为有时钟源和无时钟…

基于FPGA的示波器设计

目录 一、设计要求 二、系统架构设计 一、设计要求 本次基于FPGA的示波器设计主要技术要求包含以下内容&#xff1a; 系统能够实现模数转换功能&#xff0c;即包含ADC驱动模块&#xff1b;系统能够实现ADC采集数据的缓存功能&#xff1b;系统包含辅助测试模块&#xff0c;DA…

FPGA实现 贪吃蛇

一. 硬件 黑金AX4010AN430显示屏&#xff08;480*272&#xff09;蓝牙模块安卓手机 采用app通过蓝牙模块来操作蛇的移动情况 二. 数据的存储 reg[18:0] Snake[0:7]; //蛇 18:10 x 9:1 y 0 :flag 是否是蛇身 reg[17:0] Food; // 食物三. 蛇的移动的方向 通过上下左右来…

黑金全部开发板资料(FPGA+ZYNQ)分享

黑金开发板 能找到的所有黑金开发板的资料&#xff0c;足够学习使用。 ALTERA CYCLONE 10 黑金开发板ZYNQ7020_2019 黑金zynq7015_2017 黑金zynq7010_2017 …

FPAG—UART串口实现与解析-黑金fpga资料解析

UART实现-黑金fpga开发板案例解析 uart 异步串口通讯 无需时钟线&#xff0c;俩根线一跟复制发数据一根负责收数据。 具体的时序如下图1&#xff1a; 图1&#xff1a;UART时序图 可以看到 当数据线由高位变为地位时&#xff0c;即遇到一个下降沿时刻&#xff0c;表示开始这一…

【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验二十四:SD卡模块

驱动SD卡是件容易让人抓狂的事情,驱动SD卡好比SDRAM执行页读写,SD卡虽然不及SDRAM的麻烦要求(时序参数),但是驱动过程却有猥琐操作。除此此外,描述语言只要稍微比较一下C语言,描述语言一定会泪流满面,因为嵌套循环,嵌套判断,或者嵌套函数等都是它的痛。. 史莱姆模块是…

黑金AX7Z100 FPGA开发板移植LWIP库(二)PL端

前言 上一篇博文中实验了PS端移植LwIP库的演示程序。本篇接下来基于Vivado17.4整理比较详细的PL端移植过程。 一、Vivado 工程建立 1、新建一个空工程&#xff0c;名称为net_lwip_pl。 2、FPGA芯片选择xc7z100ffg900-2。 二、配置PS&PL系统硬件 1、工程建好以后&…

【FPGA从0开始系列】黑金EP4CE10F17C8开发板按键实验(二)

项目目录 1.实验目的2.准备阶段3.实验原理4.编写Verilog HDL程序5.配置引脚6.查看和分析RTL7.下载程序8.总结 1.实验目的 查阅AX4010黑金系列用户手册&#xff0c;编写按键程序&#xff0c;实验简单的按键控制LED的功能&#xff0c;同时学习 Quartus RTL Viewer 的使用 2.准备…

汉诺塔(C语言实现)

目录 汉诺塔的游戏规则&#xff1a; 当A只有一个环的时候&#xff1a; 当A只有两个环的时候&#xff1a; 当A只有三个环的时候&#xff1a; 思路&#xff1a; 当n1时&#xff1a; 当n2时&#xff1a; 当n3时&#xff1a; 当n4时&#xff1a; 见代码 运行截图 汉诺塔的游戏…

【C语言】汉诺塔问题

汉诺塔是一个非常经典的问题&#xff0c;其背后是一个传说故事&#xff1a; 在世界中心贝拿勒斯&#xff08;在印度北部&#xff09;的圣庙里&#xff0c;一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候&#xff0c;在其中一根针上从下到上地穿好了由大到小的6…

汉诺塔C语言步骤解析

汉诺塔问题在C语言中一般采用递归法来写&#xff0c;假设有A、B、C三根棒&#xff0c;A棒放着若干个圆盘&#xff0c;将其移动到C棒上&#xff0c;中途可在B棒中暂时放置圆盘。 分析&#xff1a; (1) 如果只有一个圆盘&#xff0c;则把该圆盘从A棒移动到C棒 (2) 如果圆盘数量…

汉诺塔递归的c语言实现(递归)

对于递归来讲, 汉诺塔实际是经典到不能再经典的例子了, 每个数据结构的教材对会提到. 但是到最后只给出一段类似下面的一段代码: #include<stdio.h>void move(int n,char a,char b,char c) {if(n1)printf("\t%c->%c\n",a,c); //当n只有1个的时候直接从…

C语言编程实现汉诺塔问题

C语言编程实现汉诺塔问题 1.首先解释一下&#xff0c;汉诺塔问题&#xff1a;古代梵塔内有A、B、C3个座&#xff0c;开始时A座上面有64个盘子&#xff0c;盘子大小不等&#xff0c;大的在下&#xff0c;小的在上。一个老和尚想把64个盘子从A移到C&#xff0c;规定移动过程中3个…

汉诺塔C语言实现(纯代码)

a、b、c三座塔&#xff0c;将n个从小到大&#xff08;自上而下&#xff09;的圆盘从a移动到c&#xff0c;移动期间小圆盘必须在大圆盘上面&#xff0c;问移动步骤。 #include<stdio.h>int main() {void hanoi(int n,char one,char two,char three);int m;printf("…

【汉诺塔】C语言递归解法,深层次地带你理解汉诺塔公式

目录 汉诺塔公式 汉诺塔问题在数学层面的公式&#xff1a; C语言递归公式 两层汉诺塔 三层汉诺塔 递归问题可谓是学习C语言以来的第一个拦路虎&#xff0c;而汉诺塔问题更是递归中对新手很不友好的一道经典题&#xff0c;我们接下来从公式角度和更深层的图解角度来让你理解…

汉诺塔c语言代码实现

汉诺塔&#xff08;Tower of Hanoi&#xff09;&#xff0c;又称河内塔&#xff0c;是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子&#xff0c;在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重…

【C语言】汉诺塔超详解(脑把脑解释)

文章目录 一、前言二、准备工作关于递归函数 三、汉诺塔步数计算详解&#xff1a;函数的设计符合递归函数的两个基本条件&#xff1a; 四、汉诺塔步骤打印&#xff08;绝对详细&#xff0c;仔细看就能看懂 &#xff09;铺垫换个思路&#xff1a;柱子竟然是可以移动的&#xff0…