AXI4控制MIG遍历 1GB的 DDR3

发布于:2024-12-18 ⋅ 阅读:(81) ⋅ 点赞:(0)

遍历DDR3 test,内存大小1GB
下面代码直接上板测试,遍历整个DDR空间,仅供参考

仿真没有问题,上板测试可能出现问题就是:
连续 读写 MIG 时候,中途 bvalid 不拉高。暂未查到问题,可能是过程中硬件出现问题,DDR传输出现错误。

如果需要仿真的话:

  1. 使用官方例程 仿真 init 信号在 54us 附近会出现
  2. 把官方 example_top中的 激励给注释掉,换成自己写的 ddr 驱动
  3. 要注意 位宽 匹配,复位以及 AXI 总线的连接
  4. 仿真波形
    在这里插入图片描述
// Author : felixgao      遍历DDR test
// File   : ddr_test_20240812.v
// Create : 2024-08-12 11:48:14
// Revise : 2024-08-12 11:48:14
// -----------------------------------------------------------------------------
module ddr_test_20240812 
	#(parameter AXI_WRITE_BASEADDR = 0,
				AXI_READ_BASEADDR  = 0,
				DDR_STROBE_CAP     = 256*1024*1024*16*2/8    //256M X 32 bit /8      BYTE
				)
	(
    input			i_clk_p, //100MHZ
    input			i_clk_n,

    input			sys_clk_p,//200MHZ   MIG sys_clk
    input			sys_clk_n,

    output	[14:0]	ddr3_addr , 
    output	[2:0]	ddr3_ba  ,
    output			ddr3_cas_n  ,
    output	[0:0]	ddr3_ck_n,
    output	[0:0]	ddr3_ck_p,
    output	[0:0]	ddr3_cke  ,
    output			ddr3_ras_n,
    output			ddr3_reset_n,
    output			ddr3_we_n,
    inout	[31:0]	ddr3_dq,
    inout	[3:0]	ddr3_dqs_n,
    inout	[3:0]	ddr3_dqs_p,
//    		(*mark_debug = "true"*) output			init_calib_complete,
    output	[0:0]	ddr3_cs_n,
    output	[3:0]	ddr3_dm,
    output	[0:0]	ddr3_odt
	
);

/*------------------------------------------*\
                调试
\*------------------------------------------*/	

	vio_0 your_instance_name (
  .clk(clk_ref_i),                // input wire clk
  .probe_out0(vio)  // output wire [0 : 0] probe_out0
);
    reg	[15:0]	r_rst_cnt;
	reg			i_rst;
	wire			r_sys_rst;

// assign r_sys_rst = vio;

always @ (posedge clk_ref_i) begin
	if (vio == 1)
		r_rst_cnt <= 0;
	else if (r_rst_cnt == 1024 )
		r_rst_cnt <= r_rst_cnt;
	else if (r_rst_cnt < 1024)
		r_rst_cnt <= r_rst_cnt + 1'b1;
	else
		r_rst_cnt <= r_rst_cnt;
end

always @ (posedge clk_ref_i) begin
	if (r_rst_cnt < 1024 )
		i_rst <= 1;
	else
		i_rst <= 0;
end

assign ui_clk_sync_rst = i_rst || ddr_ui_clk_sync_rst ;
/*------------------------------------------*\
                  main code
\*------------------------------------------*/

parameter DDR_IDLE       = 0,
		  DDR_INIT_DONE  = 1,
		  DDR_WRITE      = 2,
		  DDR_WRITE_RESP = 3,
		  DDR_WRITE_ADDR = 4,
		  DDR_WRITE_DELAY= 5,
		  DDR_WAIT_READ  = 6,
		  DDR_READ       = 7,
		  DDR_READ_ADDR  = 8,
		  DDR_END        = 9;

parameter AXI_DATA_WIDTH     = 256;
parameter AXI_BURST_LEN      = 128;
parameter AXI_SEND_ONETIME   = AXI_DATA_WIDTH * AXI_BURST_LEN /8  ;  // data size * burst len
// parameter DDR_SEND_ALL_TIMES = DDR_STROBE_CAP / AXI_SEND_ONETIME ;
parameter DDR_SEND_ALL_TIMES = 262144;

wire			locked;

wire	[3:0]	s_axi_awid;
		(*mark_debug = "true"*) reg	[29:0]		s_axi_awaddr;
reg	[7:0]		s_axi_awlen;
reg	[2:0]	s_axi_awsize;
reg	[1:0]	s_axi_awburst;
wire	[0:0]	s_axi_awlock;
wire	[3:0]	s_axi_awcache;
wire	[2:0]	s_axi_awprot;
wire	[3:0]	s_axi_awqos;
reg				s_axi_awvalid;
wire			s_axi_awready;

		(*mark_debug = "true"*) reg	[255:0]		s_axi_wdata;
reg	[31:0]	s_axi_wstrb;
		(*mark_debug = "true"*) reg				s_axi_wlast;
		(*mark_debug = "true"*) reg				s_axi_wvalid;
		(*mark_debug = "true"*) wire			s_axi_wready;

wire	[3:0]	s_axi_bid;
		(*mark_debug = "true"*) wire	[1:0]	s_axi_bresp;
		(*mark_debug = "true"*) wire			s_axi_bvalid;
		(*mark_debug = "true"*) reg				s_axi_bready;

wire	[3:0]	s_axi_arid;
		(*mark_debug = "true"*) reg	[29:0]		s_axi_araddr;
wire	[7:0]	s_axi_arlen;
reg	[2:0]	s_axi_arsize;
reg	[1:0]	s_axi_arburst;
wire	[0:0]	s_axi_arlock;
wire	[3:0]	s_axi_arcache;
wire	[2:0]	s_axi_arprot;
wire	[3:0]	s_axi_arqos;
		(*mark_debug = "true"*) reg				s_axi_arvalid;
		(*mark_debug = "true"*) wire			s_axi_arready;

wire	[3:0]	s_axi_rid;
(*mark_debug = "true"*) wire	[255:0]	s_axi_rdata;
(*mark_debug = "true"*) wire	[1:0]	s_axi_rresp;
		(*mark_debug = "true"*) wire			s_axi_rlast;
		(*mark_debug = "true"*) wire			s_axi_rvalid;
		(*mark_debug = "true"*) reg				s_axi_rready;


		(*mark_debug = "true"*) reg	[3:0]	r_ddr_cu_state;
reg	[3:0]	r_ddr_nx_state;
reg	[15:0]	r_ddr_state_cnt;
		(*mark_debug = "true"*) reg	[31:0]	r_send_times;
		(*mark_debug = "true"*) reg	[31:0]	r_recv_times;
reg	[15:0]	r_wr_data_cnt;
(*mark_debug = "true"*) wire init_calib_complete;
reg [255:0] r_ddr_read_data;

  clk_wiz_0 clk_wiz_0_inst
   (
    // Clock out ports
    .clk_out1(clk_ref_i),     // output clk_out1
    // Status and control signals
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1_p(i_clk_p),    // input clk_in1_p
    .clk_in1_n(i_clk_n));    // input clk_in1_n

  mig_7series_0 u_mig_7series_0 (

    // 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

    .ui_clk                         (ui_clk),  // output			ui_clk
    .ui_clk_sync_rst                (ddr_ui_clk_sync_rst),  // output			ui_clk_sync_rst
    .mmcm_locked                    (mmcm_locked),  // output			mmcm_locked
    .aresetn                        (~ui_clk_sync_rst),  // input			aresetn
    .app_sr_req                     (0),  // input			app_sr_req
    .app_ref_req                    (0),  // input			app_ref_req
    .app_zq_req                     (0),  // input			app_zq_req
    .app_sr_active                  (),  // output			app_sr_active
    .app_ref_ack                    (),  // output			app_ref_ack
    .app_zq_ack                     (),  // output			app_zq_ack
    // Slave Interface Write Address Ports
    .s_axi_awid                     (0),    // input [3:0]			s_axi_awid
    .s_axi_awaddr                   (s_axi_awaddr),  // input [29:0]			s_axi_awaddr
    .s_axi_awlen                    (s_axi_awlen),   // input [7:0]			s_axi_awlen
    .s_axi_awsize                   (s_axi_awsize  ),  // input [2:0]			s_axi_awsize
    .s_axi_awburst                  (s_axi_awburst ), // input [1:0]			s_axi_awburst
    .s_axi_awlock                   (0),  // input [0:0]			s_axi_awlock
    .s_axi_awcache                  (0), // input [3:0]			s_axi_awcache
    .s_axi_awprot                   (0),  // input [2:0]			s_axi_awprot
    .s_axi_awqos                    (0),   // input [3:0]			s_axi_awqos
    .s_axi_awvalid                  (s_axi_awvalid), // input			s_axi_awvalid
    .s_axi_awready                  (s_axi_awready), // output			s_axi_awready

    // Slave Interface Write Data Ports

    .s_axi_wdata                    (s_axi_wdata),  // input [255:0]			s_axi_wdata
    .s_axi_wstrb                    (s_axi_wstrb),  // input [31:0]			s_axi_wstrb
    .s_axi_wlast                    (s_axi_wlast),  // input			s_axi_wlast
    .s_axi_wvalid                   (s_axi_wvalid), // input			s_axi_wvalid
    .s_axi_wready                   (s_axi_wready), // output			s_axi_wready

    // Slave Interface Write Response Ports

    .s_axi_bid                      (),     // output [3:0]			s_axi_bid
    .s_axi_bresp                    (s_axi_bresp),   // output [1:0]			s_axi_bresp
    .s_axi_bvalid                   (s_axi_bvalid),  // output			s_axi_bvalid
    .s_axi_bready                   (s_axi_bready),  // input			s_axi_bready

    // Slave Interface Read Address Ports

    .s_axi_arid                     (0),    // input [3:0]			s_axi_arid
    .s_axi_araddr                   (s_axi_araddr),  // input [29:0]			s_axi_araddr
    .s_axi_arlen                    (s_axi_arlen),   // input [7:0]			s_axi_arlen
    .s_axi_arsize                   (s_axi_arsize  ),  // input [2:0]			s_axi_arsize
    .s_axi_arburst                  (s_axi_arburst ), // input [1:0]			s_axi_arburst
    .s_axi_arlock                   (0),  // input [0:0]			s_axi_arlock
    .s_axi_arcache                  (0), // input [3:0]			s_axi_arcache
    .s_axi_arprot                   (0),  // input [2:0]			s_axi_arprot
    .s_axi_arqos                    (0),   // input [3:0]			s_axi_arqos
    .s_axi_arvalid                  (s_axi_arvalid), // input			s_axi_arvalid
    .s_axi_arready                  (s_axi_arready), // output			s_axi_arready

    // Slave Interface Read Data Ports

    .s_axi_rid                      (),    // output [3:0]			s_axi_rid
    .s_axi_rdata                    (s_axi_rdata),  // output [255:0]			s_axi_rdata
    .s_axi_rresp                    (s_axi_rresp),  // output [1:0]			s_axi_rresp
    .s_axi_rlast                    (s_axi_rlast),  // output			s_axi_rlast
    .s_axi_rvalid                   (s_axi_rvalid), // output			s_axi_rvalid
    .s_axi_rready                   (s_axi_rready), // input			s_axi_rready

    // System Clock Ports

    .sys_clk_p                       (sys_clk_p),  // input				sys_clk_p
    .sys_clk_n                       (sys_clk_n),  // input				sys_clk_n

    // Reference Clock Ports

    // .clk_ref_i                      (clk_ref_i),
    .sys_rst                        (1) // input sys_rst

    );


always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst) begin
		s_axi_arsize  <= 3'b000 ;
		s_axi_arburst <= 2'b00 ;
		s_axi_awsize  <= 3'b000;
        s_axi_awburst <= 2'b00 ;
        s_axi_wstrb   <= 0;
	end else begin
		s_axi_arsize  <= 3'b101 ;
		s_axi_arburst <= 2'b01 ;
		s_axi_awsize  <= 3'b101;
        s_axi_awburst <= 2'b01 ;
        s_axi_wstrb   <= 32'hffffffff;
	end
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		r_ddr_state_cnt <= 0;
	else if (r_ddr_cu_state !=  r_ddr_nx_state)
		r_ddr_state_cnt <= 0;
	else 
		r_ddr_state_cnt <= r_ddr_state_cnt + 1;
end
 
 always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		r_recv_times <= 0;
	else if (r_ddr_cu_state == DDR_IDLE)
		r_recv_times <= 0;
	else if (r_ddr_cu_state == DDR_READ && r_ddr_state_cnt == 0)
		r_recv_times <= r_recv_times + 1;
	else
		r_recv_times <= r_recv_times;
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		r_send_times <= 0;
	else if (r_ddr_cu_state == DDR_IDLE)
		r_send_times <= 0;
	else if (r_ddr_cu_state == DDR_WRITE && r_ddr_state_cnt == 0)
		r_send_times <= r_send_times + 1;
	else
		r_send_times <= r_send_times;
end

(*mark_debug = "true"*) reg r_complate_flag;

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		r_complate_flag <= 0;
	else if (r_ddr_cu_state == DDR_WAIT_READ || r_ddr_cu_state == DDR_END )
		r_complate_flag <= 0;
	else if ((r_ddr_cu_state == DDR_WRITE && r_send_times == DDR_SEND_ALL_TIMES )||(r_ddr_cu_state == DDR_READ && r_recv_times == DDR_SEND_ALL_TIMES))
		r_complate_flag <= 1;
	else 
		r_complate_flag <= r_complate_flag;	
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		r_ddr_cu_state <= DDR_IDLE;
	else
		r_ddr_cu_state <= r_ddr_nx_state;		
end

always @ (*) begin
	case (r_ddr_cu_state)
		DDR_IDLE     :begin  
			if (init_calib_complete)
				r_ddr_nx_state <= DDR_INIT_DONE;
			else
				r_ddr_nx_state <= r_ddr_cu_state;							
		 end    
		DDR_INIT_DONE:begin 
				r_ddr_nx_state <= DDR_WRITE;
		end
		DDR_WRITE    : begin  
			if (s_axi_wlast)
				r_ddr_nx_state <= DDR_WRITE_RESP;	
			else
				r_ddr_nx_state <= r_ddr_cu_state;							
		end
		DDR_WRITE_RESP    : begin  
			if (s_axi_bresp == 2'b00 && s_axi_bready && s_axi_bvalid && r_complate_flag)
				r_ddr_nx_state <= DDR_WAIT_READ;	
			else if (s_axi_bresp == 2'b00 && s_axi_bready && s_axi_bvalid )
				r_ddr_nx_state <= DDR_WRITE_ADDR;
			else
				r_ddr_nx_state <= r_ddr_cu_state;						
		end
		DDR_WRITE_ADDR    : begin 
				r_ddr_nx_state <= DDR_WRITE_DELAY;			     
		end
		DDR_WRITE_DELAY : begin
			if (r_ddr_state_cnt == 10)
				r_ddr_nx_state <= DDR_WRITE;	
		    else
				r_ddr_nx_state <= r_ddr_cu_state;			     
		end
		DDR_WAIT_READ    :begin 
				r_ddr_nx_state <= DDR_READ;	 
		end					
		DDR_READ     : begin 
			if (s_axi_rlast && s_axi_rvalid && s_axi_rready && s_axi_rresp == 2'b00 )
				r_ddr_nx_state <= DDR_READ_ADDR;	
			else 
				r_ddr_nx_state <= r_ddr_cu_state;				 			
		end
		DDR_READ_ADDR    : begin
			if (r_complate_flag) 
				r_ddr_nx_state <= DDR_END;	
			else  
				r_ddr_nx_state <= DDR_READ;					
		end	
		DDR_END      : begin 
			r_ddr_nx_state <= DDR_IDLE;
		end
		default:begin
			r_ddr_nx_state <= DDR_IDLE;
		end
	endcase
end


/*------------------------------------------*\
                   DDR WRITE
\*------------------------------------------*/

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		s_axi_awaddr <= 0;
	else if (r_ddr_cu_state == DDR_IDLE)
		s_axi_awaddr <= 0;
	else if (r_ddr_cu_state == DDR_WRITE_ADDR)
		s_axi_awaddr <= s_axi_awaddr + (AXI_BURST_LEN << 5);		
	else
		s_axi_awaddr <= s_axi_awaddr;		
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		s_axi_awlen <= 0;
	else if (r_ddr_cu_state == DDR_INIT_DONE)
		s_axi_awlen <= AXI_BURST_LEN - 1;		
	else
		s_axi_awlen <= s_axi_awlen;			
end


always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		s_axi_awvalid <= 0;
	else if (s_axi_awvalid && s_axi_awready)
		s_axi_awvalid <= 0;				
	else if (r_ddr_cu_state == DDR_WRITE && r_ddr_state_cnt == 0)
		s_axi_awvalid <= 1;	
	else
		s_axi_awvalid <= 0;			
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		s_axi_wdata <= 0;			
	else if (s_axi_wvalid && s_axi_wready)
		s_axi_wdata <= s_axi_wdata + 1;	
	else
		s_axi_wdata <= s_axi_wdata;			
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		s_axi_wvalid <= 0;
	else if (s_axi_wvalid && s_axi_wready && s_axi_wlast)
		s_axi_wvalid <= 0;				
	else if (r_ddr_cu_state == DDR_WRITE && r_ddr_state_cnt == 0)
		s_axi_wvalid <= 1;	
	else
		s_axi_wvalid <= s_axi_wvalid;			
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		r_wr_data_cnt <= 0;
	else if (r_wr_data_cnt == AXI_BURST_LEN - 1)
		r_wr_data_cnt <= 0;				
	else if (s_axi_wvalid && s_axi_wready)
		r_wr_data_cnt <= r_wr_data_cnt + 1;	
	else
		r_wr_data_cnt <= r_wr_data_cnt;			
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		s_axi_wlast <= 0;			
	else if (s_axi_wvalid && s_axi_wready && r_wr_data_cnt == AXI_BURST_LEN - 2)
		s_axi_wlast <= 1;	
	else
		s_axi_wlast <= 0;			
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		s_axi_bready <= 0;	
	else if (s_axi_bready && s_axi_bvalid)
		s_axi_bready <= 0;				
	else if (r_ddr_cu_state == DDR_WRITE_RESP)
		s_axi_bready <= 1;	
	else
		s_axi_bready <= s_axi_bready;			
end



/*------------------------------------------*\
                  DDR READ
\*------------------------------------------*/

assign s_axi_arlen = AXI_BURST_LEN -1;

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		s_axi_araddr <= 0;	
	else if (r_ddr_cu_state == DDR_WAIT_READ)
		s_axi_araddr <= 0;				
	else if (r_ddr_cu_state == DDR_READ_ADDR)
		s_axi_araddr <= s_axi_araddr + (AXI_BURST_LEN << 5);	
	else
		s_axi_araddr <= s_axi_araddr;			
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		s_axi_arvalid <= 0;
	else if (s_axi_arvalid && s_axi_arready)
		s_axi_arvalid <= 0;				
	else if (r_ddr_cu_state == DDR_READ && r_ddr_state_cnt == 0)
		s_axi_arvalid <= 1;	
	else
		s_axi_arvalid <= 0;			
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		r_ddr_read_data <= 0;			
	else if (r_ddr_cu_state == DDR_READ && s_axi_rvalid && s_axi_rready)
		r_ddr_read_data <= s_axi_rdata;	
	else
		r_ddr_read_data <= r_ddr_read_data;			
end

always @ (posedge ui_clk) begin
	if (ui_clk_sync_rst)
		s_axi_rready <= 0;
	else if (r_ddr_cu_state == DDR_END)
		s_axi_rready <= 0;				
	else if (r_ddr_cu_state == DDR_WAIT_READ)
		s_axi_rready <= 1;	
	else
		s_axi_rready <= s_axi_rready;			
end

endmodule

网站公告

今日签到

点亮在社区的每一天
去签到