vivado DDR4读写存储以及一些坑

DDR4读写控制模块

module ddr4_control#(
     parameter         			MEM_DATA_BITS                  		= 512                         			,
     parameter         			ADDR_BITS                  			= 26                         			,
     parameter         			BUSRT_BITS                  		= 10                         			,//突发的位宽长度
     parameter         			BURST_LEN                  			= 5                         			
)
(
    input                                                               i_sys_clk                                   ,                                   
    input                                                               i_sys_rst                                   ,  	
    
    input                                                               i_wr_data_rdy                               ,  	
    output     reg     [MEM_DATA_BITS-1:0]                              o_wr_data		    						,
    output     reg        					                            o_wr_ddr4_req		    					,
    
    input             					                                i_rd_data_vaild		    					,
    input              [MEM_DATA_BITS-1:0]					            i_rd_ddr4_data		    					,
    output     reg                         					            o_rd_ddr4_req		    					,
    
    output             [BUSRT_BITS-1:0]					     	        o_wr_burst_length		    				,
    output             [BUSRT_BITS-1:0]					           	    o_rd_burst_length		    				,
    
    output     reg     [ADDR_BITS-1:0]					           	    o_wr_base_ddr4_addr		    				,
    output     reg     [ADDR_BITS-1:0]					           	    o_rd_base_ddr4_addr		    				,
    
    input         				           	 						    i_wr_finished			    				,
    input         				           	 						    i_rd_finished			    				

);

	localparam													IDLE = 3'b000					;
	localparam													WRITE = 3'b001					;
	localparam													READ = 3'b011					;

	reg						[11:0]								wr_data_count					;	
	reg						[11:0]								rd_data_count					;	
	reg						[2:0]								current_state					;	
	reg						[2:0]								next_state						;	
	
	
	assign	o_wr_burst_length = BURST_LEN;	
	assign	o_rd_burst_length = BURST_LEN;	

	always @(posedge i_sys_clk or posedge i_sys_rst) begin
		if(i_sys_rst) begin
			current_state <= IDLE;
		end
		else begin
			current_state <= next_state;
		end
	end	
	
	always @(*) begin
		case(current_state)
			IDLE: begin
						next_state = WRITE;
				end
			WRITE: begin
					if(i_wr_finished) begin
						next_state = READ;						
					end
					else begin
						next_state = WRITE;
					end
				end
			READ: begin
					if(i_rd_finished) begin
						next_state = IDLE;
					end
					else begin
						next_state = READ; 
					end
				end
			default:begin
						next_state = IDLE;
					end
		    endcase
	end
	
	always @(posedge i_sys_clk or posedge i_sys_rst) begin
		if(i_sys_rst) begin
			o_wr_ddr4_req <= 1'd0;
			o_rd_ddr4_req <= 1'd0;
		end
		else if( current_state == IDLE || (current_state == READ && i_rd_finished))begin
			o_wr_ddr4_req <= 1'd1;
			o_rd_ddr4_req <= 1'd0;
		end
		else if( current_state == WRITE && i_wr_finished)begin
			o_wr_ddr4_req <= 1'd0;
			o_rd_ddr4_req <= 1'd1;
		end		
		else begin
			o_wr_ddr4_req <= o_wr_ddr4_req;
			o_rd_ddr4_req <= o_rd_ddr4_req;
		end
	end		
	
	always @(posedge i_sys_clk or posedge i_sys_rst) begin
		if(i_sys_rst) begin
			wr_data_count <= 12'd0;
		end
		else if(current_state == WRITE && wr_data_count == BURST_LEN - 12'd1 || current_state == IDLE ) begin
			wr_data_count <= 12'd0;		
		end
		else if(current_state == WRITE && i_wr_data_rdy ) begin
			wr_data_count <= wr_data_count + 12'd1;
		end
		else begin
			wr_data_count <= wr_data_count;
		end
	end
	
	always @(posedge i_sys_clk or posedge i_sys_rst) begin
		if(i_sys_rst) begin
			o_wr_data <= {MEM_DATA_BITS{1'd0}};
		end
		else if(current_state == WRITE && i_wr_data_rdy ) begin
			o_wr_data <= o_wr_data + 'd10;
		end
		else begin
			wr_data_count <= wr_data_count;
		end
	end	
				
	always @(posedge i_sys_clk or posedge i_sys_rst) begin
		if(i_sys_rst) begin
			rd_data_count <= 12'd0;
		end
		else if(current_state == READ && rd_data_count == BURST_LEN - 12'd1 || current_state == IDLE ) begin
			rd_data_count <= 12'd0;
		end
		else if(current_state == READ && i_rd_data_vaild ) begin
			rd_data_count <= rd_data_count + 12'd1;
		end
		else begin
			rd_data_count <= rd_data_count;
		end
	end
	
	always @(posedge i_sys_clk or posedge i_sys_rst) begin
		if(i_sys_rst) begin
			o_rd_base_ddr4_addr <= {ADDR_BITS{1'd0}};
			o_wr_base_ddr4_addr <= {ADDR_BITS{1'd0}};
		end
		else if(i_rd_finished ) begin
			o_rd_base_ddr4_addr <= o_rd_base_ddr4_addr + BURST_LEN;
			o_wr_base_ddr4_addr <= o_wr_base_ddr4_addr + BURST_LEN;
		end
		else begin
			o_rd_base_ddr4_addr <= o_rd_base_ddr4_addr;
			o_wr_base_ddr4_addr <= o_wr_base_ddr4_addr;
		end
	end	
	
endmodule	

DDR4 app接口控制

module ddr4_app
#(
    parameter         			ADDR_BITS                  			= 26                         			,
	parameter 					MEM_DATA_BITS 						= 512									,
	parameter 					APP_ADDR_BITS 						= 29									,
	parameter 					BURST_BITS 							= 10 //突发长度的位宽
)
(
    input                                                               i_sys_clk                                   ,                                   
    input                                                               i_sys_rst                                   , 	
	
    output                                                              o_wr_data_rdy                               ,	
    input               [MEM_DATA_BITS-1:0]                             i_wr_data		    						,	
    input             					                                i_wr_ddr4_req		    					,	
	
    output             					                                o_rd_data_vaild		    					,
    output              [MEM_DATA_BITS-1:0]					            o_rd_ddr4_data		    					,
    input               									            i_rd_ddr4_req		    					,	
	
    input               [BURST_BITS-1:0]					     	    i_wr_burst_length		    				,
    input               [BURST_BITS-1:0]					            i_rd_burst_length		    				,
    
    input               [BURST_BITS-1:0]					            i_wr_base_ddr4_addr		    				,
    input               [BURST_BITS-1:0]					            i_rd_base_ddr4_addr		    				,
    
    output         		reg		           	 						    o_wr_finished			    				,
    output         		reg		           	 						    o_rd_finished			    				,	
	
	
	//DDR phy接口的信号
    output                  											o_c0_init_calib_complete					,
    input                   											i_c0_sys_clk_p								,
    input                   											i_c0_sys_clk_n								,
    output                  											o_c0_ddr4_act_n								,
    output 				[16:0]         									o_c0_ddr4_adr								,
    output 				[1:0]          									o_c0_ddr4_ba								,
    output 				[0:0]          									o_c0_ddr4_bg								,
    output 				[0:0]          									o_c0_ddr4_cke								,
    output 				[0:0]          									o_c0_ddr4_odt								,
    output 				[0:0]          									o_c0_ddr4_cs_n								,
    output 				[0:0]          									o_c0_ddr4_ck_t								,
    output 				[0:0]          									o_c0_ddr4_ck_c								,
    output 				               									o_c0_ddr4_reset_n							,
    inout  				[7:0]          									io_c0_ddr4_dm_dbi_n							,
    inout  				[63:0]         									io_c0_ddr4_dq								,
    inout  				[7:0]          									io_c0_ddr4_dqs_t							,
    inout  				[7:0]          									io_c0_ddr4_dqs_c							,
    
    output  				          									o_ddr4_clk									,
    output  					         								o_ddr4_rst									
		
);

	localparam													IDLE = 3'b000					;
	localparam													WRITE = 3'b001					;
	localparam													READ = 3'b011					;
	localparam													READ_WAIT = 3'b010				;



	wire 			[APP_ADDR_BITS-1:0]                  				app_addr						;               
	wire 			[2:0]                                				app_cmd							;                
	wire 			                                     				app_en							;                 
	wire 			[MEM_DATA_BITS-1:0]                  				app_wdf_data					;           
	wire 			                                     				app_wdf_end						;            
	wire 			[MEM_DATA_BITS/8-1:0]                				app_wdf_mask					;           
	wire 			                                     				app_wdf_wren					;           
	wire 			[MEM_DATA_BITS-1:0]                  			   	app_rd_data						;            
	wire                                     					    	app_rd_data_end					;        
	wire         	                          					        app_rd_data_valid				;      
	wire                                     						    app_rdy							;                
	wire                                     						    app_wdf_rdy						;            
	                                         						 	                         
	wire                                     					        c0_ddr4_ui_clk					;         
	wire                                     						    c0_ddr4_ui_clk_sync_rst			;
	
	wire            [BURST_BITS + 12 -1 : 0  ]             			    wr_burst_addr					;// burst_addr = base_addr + offset_addr
	wire            [BURST_BITS + 12 -1 : 0  ]             			    rd_burst_addr					;
 
	reg 			[2:0]                                				app_cmd_r						;    
	reg 			                                     				app_en_r						;       
//	reg 			[MEM_DATA_BITS/8-1:0]                				app_wdf_mask_r					;    
	reg 			                                     				app_wdf_wren_r					;    
	reg 			[MEM_DATA_BITS-1:0]                  			   	app_rd_data_r					;    
	reg                                     					    	app_rd_data_end_r				;    
	reg             [MEM_DATA_BITS-1:0]                        	    	app_wdf_data_r					;    
//	reg         	                          					        app_rd_data_valid_r				;   
//	reg                                     						    app_rdy_r						;    
//	reg                                     						    app_wdf_rdy_r					;
	
	
	reg 			[2:0]                                				current_state					; 	  
	reg 			[2:0]                                				next_state						; 	  
	
	reg 			[11:0]                                				wr_data_count					; 	
	reg 			[11:0]                                				wr_addr_count					; 	

	reg 			[11:0]                                				rd_data_count					; 	
	reg 			[11:0]                                				rd_addr_count					; 
//******************************************assign*****************************************************
//    assign o_ddr4_clk = c0_ddr4_ui_clk;
//    assign o_ddr4_rst = c0_ddr4_ui_clk_sync_rst;
	assign  wr_burst_addr = (wr_addr_count + i_wr_base_ddr4_addr) << 3;
	assign  rd_burst_addr = (rd_addr_count + i_rd_base_ddr4_addr) << 3;
	assign  app_cmd = app_cmd_r;
	assign  app_en = app_en_r;
	assign  o_wr_data_rdy = app_wdf_rdy && (current_state == WRITE)&&app_en;
	assign  o_rd_data_vaild = app_rd_data_valid;
	assign  o_rd_ddr4_data = app_rd_data;
//	assign app_wdf_wren = app_en & app_wdf_rdy;	
	assign app_wdf_wren = app_wdf_wren_r;	
	assign	app_addr = (current_state == WRITE) ? wr_burst_addr:
					    (current_state == READ) ? rd_burst_addr: {APP_ADDR_BITS{1'd0}};
	assign	app_wdf_data = i_wr_data;
	assign app_wdf_mask = {MEM_DATA_BITS/8{1'b0}};	
	assign app_wdf_end = app_wdf_wren;
//*****************************************************************************************************

	always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
		if(o_ddr4_rst) begin
			app_wdf_data_r <= {MEM_DATA_BITS{1'd0}};
		end
		else begin
			app_wdf_data_r <= i_wr_data;
		end
	end	


	always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
		if(o_ddr4_rst) begin
			current_state <= IDLE;
		end
		else begin
			current_state <= next_state;
		end
	end	
	
	always @(*)begin
	   if (o_c0_init_calib_complete)
		case(current_state)
			IDLE: begin
					if (i_wr_ddr4_req) begin
						next_state = WRITE;
					end
					else if (i_rd_ddr4_req) begin
						next_state = READ;
					end
					else begin
						next_state = IDLE;
					end
				end
			WRITE: begin
					if(o_wr_finished) begin
						next_state = IDLE;
					end
					else begin
						next_state = WRITE;
					end	
				end
			READ: begin
					if(rd_addr_count == i_rd_burst_length - 'd1 ) begin
						next_state = READ_WAIT;
					end
					else if(o_rd_finished) begin
						next_state = IDLE;						
					end
					else begin
						next_state = READ;
					end
				end
			READ_WAIT: begin
						if (o_rd_finished) begin
							next_state = IDLE;
						end			
						else begin
							next_state = READ_WAIT;
						end
					end	
			default:begin
						next_state = IDLE;
					end	
		endcase
		else begin
		  next_state = IDLE;
		end
	end



	always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
		if(o_ddr4_rst) begin
			app_cmd_r <= 3'd0;
		end
		else if (current_state == WRITE )begin
			app_cmd_r <= 3'd0;
		end
		else if (current_state == READ )begin
			app_cmd_r <= 3'd1;
		end
		else begin
			app_cmd_r <= app_cmd_r;
		end
	end	
	
	always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin 
		if(o_ddr4_rst) begin
			app_wdf_wren_r <= 1'd0;
		end
//		else if ((current_state == WRITE && o_wr_finished) ||(current_state == READ &&o_rd_finished  ) ) begin
		else if ((current_state == WRITE && o_wr_finished)) begin
			app_wdf_wren_r <= 1'd0;
		end
		else if ((current_state == WRITE)  && app_rdy && app_wdf_rdy )begin
			app_wdf_wren_r <= 1'd1;
		end
		else begin
			app_wdf_wren_r <= app_wdf_wren_r;
		end
	end	

	always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin 
		if(o_ddr4_rst) begin
			app_en_r <= 1'd0;
		end
//		else if ((current_state == WRITE && o_wr_finished) ||(current_state == READ &&o_rd_finished  ) ) begin
		else if ((current_state == WRITE && o_wr_finished) || rd_addr_count == i_rd_burst_length - 1) begin
			app_en_r <= 1'd0;
		end
		else if ((current_state == WRITE || current_state == READ) && app_rdy )begin
			app_en_r <= 1'd1;
		end
		else begin
			app_en_r <= app_en_r;
		end
	end	
	
	always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
		if(o_ddr4_rst) begin
			wr_data_count <= 12'd0;
		end
		else if (current_state == WRITE && wr_data_count == i_wr_burst_length - 12'd1 )begin
			wr_data_count <= 12'd0;
		end
		else if (current_state == WRITE && app_rdy && app_wdf_rdy && app_en_r) begin
			wr_data_count <= wr_data_count + 12'd1;
		end
		else begin
			wr_data_count <= wr_data_count;
		end
	end		
	
	always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
		if(o_ddr4_rst) begin
			wr_addr_count <= 12'd0;
		end
		else if (current_state == WRITE && wr_data_count == i_wr_burst_length - 12'd1 )begin
			wr_addr_count <= 12'd0;
		end
		else if (current_state == WRITE && app_rdy && app_wdf_rdy && app_en_r) begin
			wr_addr_count <= wr_addr_count + 12'd1;
		end
		else begin
			wr_addr_count <= wr_addr_count;
		end
	end		

	always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
		if(o_ddr4_rst) begin
			o_wr_finished <= 1'd0;
		end
		else if (current_state == WRITE && (wr_data_count == i_wr_burst_length - 12'd2 ))begin
			o_wr_finished <= 1'd1;
		end
		else begin
			o_wr_finished <= 1'd0;
		end
	end		

	always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
		if(o_ddr4_rst) begin
			rd_addr_count <= 12'd0;
		end
		else if (current_state == READ &&rd_addr_count == i_rd_burst_length - 'd1  )begin
			rd_addr_count <= 12'd0;
		end
		else if (current_state == READ && app_rdy  && app_en_r) begin
			rd_addr_count <= rd_addr_count + 12'd1;
		end
		else begin
			rd_addr_count <= rd_addr_count;
		end
	end	


	always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
		if(o_ddr4_rst) begin
			rd_data_count <= 12'd0;
		end
		else if ((rd_data_count == i_rd_burst_length -1'd1) && app_rd_data_valid) begin
			rd_data_count <= 12'd0;
		end
		else if ((current_state == READ || current_state == READ_WAIT) && app_rd_data_valid )begin
			rd_data_count <= rd_data_count + 12'd1;
		end
		else begin
			rd_data_count <= rd_data_count;
		end
	end	
	
			

	
	always@(posedge o_ddr4_clk or posedge o_ddr4_rst) begin
		if(o_ddr4_rst) begin
			o_rd_finished <= 1'd0;
		end
		else if (( current_state == READ || current_state == READ_WAIT) && (rd_data_count == i_rd_burst_length - 12'd1 ) && app_rd_data_valid)begin
			o_rd_finished <= 1'd1;
		end
		else begin
			o_rd_finished <= 1'd0;
		end
	end			


ddr4_0 u_ddr4
  (
   .sys_rst           		     	(i_sys_rst			),

   .c0_sys_clk_p                    (i_c0_sys_clk_p		),
   .c0_sys_clk_n                    (i_c0_sys_clk_n		),
   .c0_init_calib_complete (o_c0_init_calib_complete	),
   .c0_ddr4_act_n          			(o_c0_ddr4_act_n	),
   .c0_ddr4_adr            			(o_c0_ddr4_adr		),
   .c0_ddr4_ba             			(o_c0_ddr4_ba		),
   .c0_ddr4_bg             			(o_c0_ddr4_bg		),
   .c0_ddr4_cke            			(o_c0_ddr4_cke		),
   .c0_ddr4_odt            			(o_c0_ddr4_odt		),
   .c0_ddr4_cs_n           			(o_c0_ddr4_cs_n		),
   .c0_ddr4_ck_t           			(o_c0_ddr4_ck_t		),
   .c0_ddr4_ck_c           			(o_c0_ddr4_ck_c		),
   .c0_ddr4_reset_n        			(o_c0_ddr4_reset_n	),
                           			
   .c0_ddr4_dm_dbi_n       			(io_c0_ddr4_dm_dbi_n),
   .c0_ddr4_dq             			(io_c0_ddr4_dq		),
   .c0_ddr4_dqs_c          			(io_c0_ddr4_dqs_c	),
   .c0_ddr4_dqs_t          			(io_c0_ddr4_dqs_t	),

   .c0_ddr4_ui_clk                  (o_ddr4_clk			),
   .c0_ddr4_ui_clk_sync_rst         (o_ddr4_rst			),
   .dbg_clk                         (dbg_clk			),

   .c0_ddr4_app_addr           	    (app_addr			),
   .c0_ddr4_app_cmd            	    (app_cmd			),
   .c0_ddr4_app_en             	    (app_en				),
   .c0_ddr4_app_hi_pri         	    (1'b0				),
   .c0_ddr4_app_wdf_data       	    (app_wdf_data		),
   .c0_ddr4_app_wdf_end        	    (app_wdf_end		),
   .c0_ddr4_app_wdf_mask       	    (app_wdf_mask		),
   .c0_ddr4_app_wdf_wren       	    (app_wdf_wren		),
   .c0_ddr4_app_rd_data        	    (app_rd_data		),
   .c0_ddr4_app_rd_data_end    	    (app_rd_data_end	),
   .c0_ddr4_app_rd_data_valid  	    (app_rd_data_valid	),
   .c0_ddr4_app_rdy            	    (app_rdy			),
   .c0_ddr4_app_wdf_rdy        	    (app_wdf_rdy		),
  
  // Debug Port
  .dbg_bus        				    (dbg_bus			)                                             

  );
endmodule

时序设计图:

DDR4_control

 DDR4_APP

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值