基于 DDR3 的串口传图缓存系统设计实现(fifo_mig_native_fifo )


前言

结合串口接收模块和 tft 显示屏控制模块,设计一个基于 DDR3 的串口传图帧缓存系统。


提示:以下是本篇文章正文内容,下面案例可供参考

一、接口转换模块设计

fifo_mig_native_fifo模块是系统中相对比较重要的模块,涉及到与 DDR 控制器接口对接。该模块的主要是实现接口的转换,将普通的 FIFO 接口转换成native接口,用于将 FIFO 里的数据读出然后存储在 DDR 存储器以及将 DDR 存储器读出的数据存放到 FIFO 缓存。

在这里插入图片描述
上电初始状态为 IDLE 状态,当 DDR 完成初始化和校准(即 init_calib_complete 变为高电平)后进入读状态;代码如下。

IDLE_transform_WRITE   = ((curr_state == S_IDLE  ) && init_calib_complete   && (wr_ddr3_req == 1'b1)  ) ,

if(init_calib_complete)
			begin 
				case(curr_state)
					 S_IDLE:begin   
							   if(IDLE_transform_WRITE)
								  begin
								  curr_state  <= S_WRITE;
								  
								  app_addr    <= 0;
								  end
							   
							   else
								  curr_state  <= curr_state; 
							end




当进入读请求后,根据条件判断是否完成读数据,若完成则跳转等待状态,否则进行数据与地址操作;


WRITE_transform_WAIT   = ((curr_state == S_WRITE ) && app_rdy               && app_wdf_rdy   && (app_addr == wr_rd_cnt-8)), 
WRITE_transform_COUNT  = ((curr_state == S_WRITE)  && app_rdy               && app_wdf_rdy)  &&  wrfifo_rd_cnt_en,	

S_WRITE:begin   
							   if(WRITE_transform_WAIT)
								  curr_state  <= S_WAIT;
							   
								  
							   else if(WRITE_transform_COUNT)        
								  begin
	
								  app_addr    <= app_addr + 8;
								  end
							   else begin
								  curr_state  <= curr_state; 
								  app_addr    <= app_addr;
								  
								  end
							end

进入等待状态后,根据设定条件判断是否进入读状态,此时由于读写共用一个地址因此将地址清0:

WAIT_transform_READ    = ((curr_state == S_WAIT  ) && (rd_ddr3_req == 1'b1)) ,


S_WAIT:begin
								if(WAIT_transform_READ)
								   begin
										curr_state <= S_READ;
										
										if (app_addr == wr_rd_cnt-8)
											app_addr   <= 0;
											
										else if(rdfifo_wr_cnt == 6)
											app_addr    <= app_addr + 8 ;
											
										else
											app_addr    <= app_addr;
								   end
								else
									curr_state <= curr_state;
						   end
				

在满足设定条件后进入读状态,此时由设定条件判断是否连续读取,还是进入等待:

 READ_transform_WAIT    = ((curr_state == S_READ  ) && app_rdy               && (rdfifo_wr_cnt >= rdfifo_depth_max - 30) ),
READ_transform_COUNT   = ((curr_state == S_READ  ) && app_rdy              ) ;


 S_READ:begin
									if(READ_transform_WAIT)
										curr_state <= S_WAIT;
										
									else if(READ_transform_COUNT)
									    
										begin
											if (app_addr == wr_rd_cnt-8)
												 app_addr    <= 0;
											else 
												 app_addr    <= app_addr + 8;
										end
									
									else begin
										curr_state  <= curr_state;
										
										app_addr    <= app_addr;
										end
						 end
				 





完成代码展示:

`timescale 1ns / 1ps





module fifo_ddr3_native_fifo
#(
        
		                 
	  parameter     wr_req_cnt_thresh = 12'd6      ,
	                rd_req_cnt_thresh = 12'd6      ,              
					wr_rd_cnt         = 20'd384000 ,			    
                    rdfifo_depth_max  = 12'd4095					
					
					

      //此部分数据可根据实际需要改变    (wr_rd_cnt)64*16位 = 128位*8(wr_ddr_cnt )



)
(
        
        //wr_ddr3_fifo ports
		 input wrfifo_rst              ,
		 input loc_clk50M              ,
		 input [15:0]wrfifo_din        ,
		 input wrfifo_wren             ,
		 
		 //rd_ddr3_fifo ports
		 input         rdfifo_rst      ,
		 input         loc_clk33M      ,
		 input        rdfifo_rden      ,
		 output [15:0]rdfifo_dout      ,
		 	 
		
		 //tft的EN信号
		 output reg rdfifo_WR_EN       ,
		 
			
		 //DDR3 Interface
		  //input
		  input loc_clk200M             ,
		  input xx_sys_rst              ,       //用于连接 pll_locked
		  
		  //output
		  output ui_clk                 ,
		  output ui_clk_sync_rst        ,
		  
		  output init_calib_complete    ,
		  
			
			

       //DDR3 Interface
		  // Inouts
		  inout  [15:0]   ddr3_dq       ,
		  inout  [1:0]    ddr3_dqs_n    ,
		  inout  [1:0]    ddr3_dqs_p    , 
		  // Outputs      
		  output [13:0]   ddr3_addr     ,
		  output [2:0]    ddr3_ba       ,
		  output          ddr3_ras_n    ,
		  output          ddr3_cas_n    ,
		  output          ddr3_we_n     ,
		  output          ddr3_reset_n  ,
		  output [0:0]    ddr3_ck_p     ,
		  output [0:0]    ddr3_ck_n     ,
		  output [0:0]    ddr3_cke      ,
		  output [0:0]    ddr3_cs_n     ,
		  output [1:0]    ddr3_dm       ,
		  output [0:0]    ddr3_odt        
	);
	
	
  //------------------------------------------
  //状态机参数
  localparam S_IDLE         = 4'b0001     ,
             S_WRITE        = 4'b0010     ,
             S_WAIT         = 4'b0100     ,
			 S_READ         = 4'b1000     ;
             
             
  //------------------------------------------
				
  
  //**********************************
  //信号定义说明
  //**********************************
  
  
  
  
  
  
  
  //wrfifo ports
  wire[127:0]wrfifo_dout               ;
  wire       wrfifo_rden               ;
  wire 	     wrfifo_wr_rst_busy        ;
  wire       wrfifo_rd_rst_busy        ;
  wire [11:0]wrfifo_rd_cnt             ;
  
  
  //rdfifo ports
  wire[127:0]rdfifo_din                ;
  
  wire       rdfifo_wr_rst_busy        ;
  wire       rdfifo_rd_rst_busy        ;
  wire  [11:0]rdfifo_wr_cnt            ;
  
  
  
  
 
  
   
     
  //cmd ports
  reg [27:0]app_addr                   ;
  wire [2:0]app_cmd                    ;
  wire      app_en                     ;
  wire      app_rdy                    ;
  
   
   
  //write data ports
  wire[127:0]app_wdf_data              ;
  wire       app_wdf_end               ; 
  wire       app_wdf_wren              ; 
  wire       app_wdf_rdy               ;
                
  
  
  //read data ports
  wire[127:0]app_rd_data               ;
  wire       app_rd_data_end           ;    
  wire       app_rd_data_valid         ;
  
  //ddr3 相关信号
  wire app_sr_active;
  wire app_ref_ack;
  wire app_zq_ack ;
  
  //状态机控制相关信号
  
  reg  wrfifo_rd_cnt_en;
  reg [3:0]wrfifo_rd_cnt_count;
  reg [23:0]rdfifo_dout_cnt;
  reg [23:0]app_rd_data_valid_cnt;
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
 
  //wr_ddr3_req ports
  wire      wr_fifo_rst_busy           ;
  wire      wr_ddr3_req                ;
  
  //rd_ddr3_req ports
  wire      rd_fifo_rst_busy           ;
  
  wire      rd_ddr3_req                ;
  
  
  //state transform
  reg [3:0] curr_state                 ;
                   
  
  //wrfifo / rdfifo 
  assign wrfifo_rden  = app_wdf_wren && app_wdf_rdy;
  assign rdfifo_din   = app_rd_data                ; 
  assign rdfifo_wren  = app_rd_data_valid          ;
  
  
  
  
  
  
  
  
  
  
  
  
  //--------------------------------------------------------------------------------
  //------------------------------------
  //根据wrfifo写入的是16位数据读出为128,
  //由16->128此过程需要转换时间因此当ddr
  //过早请求数据(128位),而此时wrfifo
  //的16位还未转化为128,将造成数据的丢失。
  //设计将 wrfifo_rd_cnt == 0后ddr不再写入
  //数据,这样可以避免数据丢失
  //------------------------------------
  
  
  
  
  always @ ( posedge ui_clk or negedge wrfifo_rst) 
	   begin
		    if(wrfifo_rst)
			    wrfifo_rd_cnt_count <= 0;
				
            else if(wrfifo_rd_cnt == 1)	
			    wrfifo_rd_cnt_count <= wrfifo_rd_cnt_count + 1'b1;
				
			else
				wrfifo_rd_cnt_count <= 0;			
        end
  
  
  
  
  always @ (posedge ui_clk or negedge wrfifo_rst ) 
	   begin
		    if(wrfifo_rst)
			    wrfifo_rd_cnt_en <= 1; 
			
            else if(wrfifo_rd_cnt_count == 2)
				wrfifo_rd_cnt_en <= 1;			
			
		    else if( wrfifo_rd_cnt == 0)
				wrfifo_rd_cnt_en <= 0;
				
		   
	   end
  
  
  
 
  
 
	
	
	
  
  //判断读写的条件
  assign    wr_fifo_rst_busy  = (wrfifo_wr_rst_busy | wrfifo_rd_rst_busy),
            wr_ddr3_req       = ((wr_fifo_rst_busy == 1'b0) && (wrfifo_rd_cnt >= wr_req_cnt_thresh)) ? 1'b1:1'b0,
			
			rd_fifo_rst_busy  = (rdfifo_wr_rst_busy | rdfifo_rd_rst_busy),
			rd_ddr3_req       = ((rd_fifo_rst_busy == 1'b0) && (rdfifo_wr_cnt <= rd_req_cnt_thresh)) ? 1'b1:1'b0 ;
  
 
  
  
  
  //**********************************
  //state transform
  //**********************************
    assign	IDLE_transform_WRITE   = ((curr_state == S_IDLE  ) && init_calib_complete   && (wr_ddr3_req == 1'b1)  ) ,
			WRITE_transform_WAIT   = ((curr_state == S_WRITE ) && app_rdy               && app_wdf_rdy   && (app_addr == wr_rd_cnt-8)), 
            WRITE_transform_COUNT  = ((curr_state == S_WRITE)  && app_rdy               && app_wdf_rdy)  &&  wrfifo_rd_cnt_en,			
	        WAIT_transform_READ    = ((curr_state == S_WAIT  ) && (rd_ddr3_req == 1'b1)) ,
	        READ_transform_WAIT    = ((curr_state == S_READ  ) && app_rdy               && (rdfifo_wr_cnt >= rdfifo_depth_max - 30) ),
            READ_transform_COUNT   = ((curr_state == S_READ  ) && app_rdy              ) ;
   
  
  
  
  
  
  
  //-----------------------------------------------------------------------------------------------
  
  
              //**********************************
              //状态转移实现
              //**********************************
  

	 
  
 
	        
	  //在写状态或读状态,拉高使能信号,
	 assign app_en = WRITE_transform_COUNT || READ_transform_COUNT ;
	 
	  //在写状态,命令接收和数据接收都准备好,此时拉高写使能
	 assign app_wdf_wren = WRITE_transform_COUNT;
	 
	 //由于 DDR3 芯片时钟和用户时钟的分频选择 4:1,突发长度为 8,故两个信号相同
	 assign app_wdf_end = app_wdf_wren;

	 //ddr读为 1,其他值为 0
	 assign app_cmd = (curr_state == S_READ) ? 3'd1 :3'd0;
	  
	  
	 assign app_wdf_data = wrfifo_dout;
	
	
   //**********************************
   //state machine
   //**********************************
	
	
	always @ (posedge ui_clk or negedge ui_clk_sync_rst)
		if(ui_clk_sync_rst)
			begin
			curr_state <= S_IDLE;
			
			
			app_addr <= 0;
			end
		else if(init_calib_complete)
			begin 
				case(curr_state)
					 S_IDLE:begin   
							   if(IDLE_transform_WRITE)
								  begin
								  curr_state  <= S_WRITE;
								  
								  app_addr    <= 0;
								  end
							   
							   else
								  curr_state  <= curr_state; 
							end
							
					 S_WRITE:begin   
							   if(WRITE_transform_WAIT)
								  curr_state  <= S_WAIT;
							   
								  
							   else if(WRITE_transform_COUNT)        
								  begin
	
								  app_addr    <= app_addr + 8;
								  end
							   else begin
								  curr_state  <= curr_state; 
								  app_addr    <= app_addr;
								  
								  end
							end
							
					S_WAIT:begin
								if(WAIT_transform_READ)
								   begin
										curr_state <= S_READ;
										
										if (app_addr == wr_rd_cnt-8)
											app_addr   <= 0;
											
										else if(rdfifo_wr_cnt == 6)
											app_addr    <= app_addr + 8 ;
											
										else
											app_addr    <= app_addr;
								   end
								else
									curr_state <= curr_state;
						   end
							  
				   S_READ:begin
									if(READ_transform_WAIT)
										curr_state <= S_WAIT;
										
									else if(READ_transform_COUNT)
									    
										begin
											if (app_addr == wr_rd_cnt-8)
												 app_addr    <= 0;
											else 
												 app_addr    <= app_addr + 8;
										end
									
									else begin
										curr_state  <= curr_state;
										
										app_addr    <= app_addr;
										end
						 end
				 
				   

					default:begin
								 curr_state  <= S_IDLE;
								 app_addr    <= 0;
							end
			
			   endcase
			
		  end
			
			
	
//-----------------------------------------------------------------------------------------------	
	
 
 //在rdfifo写数据开始时对TFT相关内容操作
 //防止tft请求数据,而rdfifo还未写入数据,造成数据丢失。
 
 
 
  always @(posedge ui_clk or negedge rdfifo_rst) 
	   begin
	   
		    if(rdfifo_rst)
			
			    rdfifo_WR_EN <= 0; 
				
		    else if( rdfifo_wren)
			
				rdfifo_WR_EN <= 1;
	        
			else	
			    rdfifo_WR_EN <=rdfifo_WR_EN ;
	
	   end
	   
	   
//-----------------------------------------------------------------------------------------------------------	   
	   
	always @(posedge loc_clk33M or negedge rdfifo_rst) 
	   begin
		    if(rdfifo_rst)
			
			    rdfifo_dout_cnt <= 0; 
				
            else if(rdfifo_rden)
				rdfifo_dout_cnt <= rdfifo_dout_cnt + 1;
				
			else 
				rdfifo_dout_cnt <= rdfifo_dout_cnt;
	   
	   end 


    
	
	always @(posedge ui_clk  or negedge ui_clk_sync_rst)
	    if(ui_clk_sync_rst)
			app_rd_data_valid_cnt <= 0;
			
		else if(app_rd_data_valid)
			app_rd_data_valid_cnt <= app_rd_data_valid_cnt + 1;
			
		else
			app_rd_data_valid_cnt <= app_rd_data_valid_cnt;
			
	
	
	
			


//------------------------------------------------------------------------------------------------------------	
	
//**********************************
//例化	wr_ddr3_fifo、rd_ddr3_fifo、mig_7series_0
//**********************************
	
wr_ddr3_fifo wr_ddr3_fifo (
  .rst          (wrfifo_rst),                // input wire rst
  .wr_clk       (loc_clk50M),                // input wire wr_clk
  .rd_clk       (ui_clk    ),                // input wire rd_clk
  .din          (wrfifo_din),                // input wire [15 : 0] din
  .wr_en        (wrfifo_wren),               // input wire wr_en
  .rd_en        (wrfifo_rden),               // input wire rd_en
  .dout         (wrfifo_dout),               // output wire [127 : 0] dout
  .full         (           ),               // output wire full
  .empty        (           ),               // output wire empty
  .rd_data_count(wrfifo_rd_cnt),               // output wire [11 : 0] rd_data_count
  .wr_data_count(             ),               // output wire [14 : 0] wr_data_count
  .wr_rst_busy  (wrfifo_wr_rst_busy),        // output wire wr_rst_busy
  .rd_rst_busy  (wrfifo_rd_rst_busy)         // output wire rd_rst_busy
);	
	





	
  rd_ddr3_fifo rd_ddr3_fifo (
  .rst          (rdfifo_rst ),                // input wire rst
  .wr_clk       (ui_clk     ),                // input wire wr_clk
  .rd_clk       (loc_clk33M ),                // input wire rd_clk
  .din          (rdfifo_din ),                // input wire [127 : 0] din
  .wr_en        (rdfifo_wren),                // input wire wr_en
  .rd_en        (rdfifo_rden),                // input wire rd_en
  .dout         (rdfifo_dout),                // output wire [15 : 0] dout
  .full         (           ),                // output wire full
  .empty        (           ),                // output wire empty
  .rd_data_count(           ),                // output wire [14 : 0] rd_data_count
  .wr_data_count(rdfifo_wr_cnt),              // output wire [11 : 0] wr_data_count
  .wr_rst_busy  (rdfifo_wr_rst_busy),         // output wire wr_rst_busy
  .rd_rst_busy  (rdfifo_rd_rst_busy)          // output wire rd_rst_busy
);	
	
	
  
  
  
	
  
	
	
	mig_7series_native u_mig_7series_native (
    // Memory interface ports
    .ddr3_addr                      (ddr3_addr        ),  // output [13: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 [15:0]		ddr3_dq
    .ddr3_dqs_n                     (ddr3_dqs_n       ),  // inout [1:0]		ddr3_dqs_n
    .ddr3_dqs_p                     (ddr3_dqs_p       ),  // inout [1: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 [1:0]		ddr3_dm
    .ddr3_odt                       (ddr3_odt         ),  // output [0:0]		ddr3_odt
    // Application interface ports
    .app_addr                       (app_addr         ),  // input [27: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 [127: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 [127: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                   (16'h0000         ),  // input [15:0]		app_wdf_mask
    // System Clock Ports
    .sys_clk_i                      (loc_clk200M      ),
    .sys_rst                        (xx_sys_rst       ) // input sys_rst
    );
	
	
endmodule
    
	
	 

二、仿真模块设计

设计写入4096个数据,然后读出两次数据,观察数据是否正确。

`timescale 1ns / 1ns



module fifo_ddr3_native_fifo_tb();
        reg wrfifo_rst;
	    reg loc_clk50M;
        reg [15:0]wrfifo_din;
	    reg wrfifo_wren;
	    reg rdfifo_rst;
	    reg loc_clk33M;
	    reg rdfifo_rden;
	    wire[15:0]rdfifo_dout;
	    wire rdfifo_WR_EN;
	    reg loc_clk200M;
	    reg xx_sys_rst;
	    wire ui_clk;
	    wire ui_clk_sync_rst;
	    wire init_calib_complete;
	    wire[13:0]ddr3_addr   ;
	  
        wire[2:0] ddr3_ba     ;
		wire      ddr3_cas_n  ;
		wire[0:0] ddr3_ck_n   ;
		wire[0:0] ddr3_ck_p   ;
		wire[0:0] ddr3_cke    ;
		wire      ddr3_ras_n  ;
		wire      ddr3_reset_n;
		wire      ddr3_we_n   ;
		wire[15:0]ddr3_dq     ;
		wire[1:0] ddr3_dqs_n  ;
		wire[1:0] ddr3_dqs_p  ;
		wire[0:0] ddr3_cs_n   ;
		wire[1:0] ddr3_dm     ;
		wire[0:0] ddr3_odt    ;
	  
	  
	  


    initial  loc_clk200M = 1'b1;
	always #2.5 loc_clk200M = ~loc_clk200M;
	
	initial  loc_clk50M = 1'b1;
	always #10 loc_clk50M = ~loc_clk50M;
	 
	initial  loc_clk33M = 1'b1;
	always #15 loc_clk33M = ~loc_clk33M;
	
	initial begin
	
		xx_sys_rst = 1'b0;
		wrfifo_rst = 1'b1;
		
		wrfifo_wren= 1'b0;
		wrfifo_din = 16'd0;
		rdfifo_rst = 1'b1;
		rdfifo_rden= 1'b0;
		#201;
		xx_sys_rst = 1'b1;
		#200;
		wrfifo_rst = 1'b0;
		rdfifo_rst = 1'b0;
		@(posedge init_calib_complete)
		#200;
		wr_data(16'd100,16'd4096);
		
		#2000;
		rd_data(16'd4096);
        #5000;
		rd_data(16'd4096);
		#5000;
		$stop;

	end
	
	
	
	
	task wr_data;
		input [15:0]data_begin;
		input [15:0]wr_data_cnt;
		begin
		  wrfifo_wren = 1'b0;
		  wrfifo_din  = data_begin;
		  @(posedge loc_clk50M);
		  #1 wrfifo_wren = 1'b1;
		  repeat(wr_data_cnt)
		  begin        
			@(posedge loc_clk50M);
			wrfifo_din = wrfifo_din + 1'b1;
		  end
		  #1 wrfifo_wren = 1'b0;
		end
    endtask
	
	
	
	
	
	 task rd_data;
		input [15:0]rd_data_cnt;
		begin
		  rdfifo_rden = 1'b0;
		  @(posedge loc_clk33M);
		  #1 rdfifo_rden = 1'b1;
		  repeat(rd_data_cnt)
		  begin
		  @(posedge loc_clk33M);
		  end
		  #1 rdfifo_rden = 1'b0;
		end
     endtask
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
		 fifo_ddr3_native_fifo
	#(
			
			. wr_req_cnt_thresh (24'd6  )       ,
			. rd_req_cnt_thresh (24'd6  )       ,
			. wr_rd_cnt         (28'd4096 )     ,
			. rdfifo_depth_max  (24'd4095 )
				  

	)fifo_ddr3_native_fifo
	(
			
			//wr_ddr3_fifo ports
			 .wrfifo_rst    (wrfifo_rst)           ,
			 .loc_clk50M    (loc_clk50M )          ,
			 .wrfifo_din    (wrfifo_din)           ,
			 .wrfifo_wren   (wrfifo_wren)          ,
			 
			 //rd_ddr3_fifo ports
			 .rdfifo_rst    (rdfifo_rst)           ,
			 .loc_clk33M    (loc_clk33M)           ,
			 .rdfifo_rden   (rdfifo_rden)          ,
			 .rdfifo_dout   (rdfifo_dout)          ,
			 .rdfifo_WR_EN  (rdfifo_WR_EN)		   ,
				
				
				
			//DDR3 Interface
			  //input
			  . loc_clk200M  (loc_clk200M)         ,
			  . xx_sys_rst   (xx_sys_rst)          ,       //用于连接 pll_locked
			  
			  //output
			  . ui_clk          (ui_clk)           ,
			  . ui_clk_sync_rst (ui_clk_sync_rst)  , 
			  . init_calib_complete  (init_calib_complete)  ,
			  
				
				

		   //DDR3 Interface
			  // Inouts
			  . ddr3_dq     (ddr3_dq      )  ,
			  . ddr3_dqs_n  (ddr3_dqs_n   )  ,
			  . ddr3_dqs_p  (ddr3_dqs_p   )  , 
			  // Outputs      
			  . ddr3_addr    (ddr3_addr   )  ,
			  . ddr3_ba      (ddr3_ba     )  ,
			  . ddr3_ras_n   (ddr3_ras_n  )  ,
			  . ddr3_cas_n   (ddr3_cas_n  )  ,
			  . ddr3_we_n    (ddr3_we_n   )  ,
			  . ddr3_reset_n (ddr3_reset_n)  ,
			  . ddr3_ck_p    (ddr3_ck_p   )  ,
			  . ddr3_ck_n    (ddr3_ck_n   )  ,
			  . ddr3_cke     (ddr3_cke    )  ,
			  . ddr3_cs_n    (ddr3_cs_n   )  ,
			  . ddr3_dm      (ddr3_dm     )  ,
			  . ddr3_odt     (ddr3_odt    )    
		);
		
		
		
				ddr3_model ddr3_model
			  (
				.rst_n  (ddr3_reset_n ),
				.ck     (ddr3_ck_p    ),
				.ck_n   (ddr3_ck_n    ),
				.cke    (ddr3_cke     ),
				.cs_n   (ddr3_cs_n    ),
				.ras_n  (ddr3_ras_n   ),
				.cas_n  (ddr3_cas_n   ),
				.we_n   (ddr3_we_n    ),
				.dm_tdqs(ddr3_dm      ),
				.ba     (ddr3_ba      ),
				.addr   (ddr3_addr    ),
				.dq     (ddr3_dq      ),
				.dqs    (ddr3_dqs_p   ),
				.dqs_n  (ddr3_dqs_n   ),
				.tdqs_n (             ),
				.odt    (ddr3_odt     )
			  );
		




















endmodule

三、仿真分析

在这里插入图片描述
通过仿真分析,写入数据与读出数据吻合(黄色标记处)。因此,验证成功。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
异步FIFO(First-In-First-Out,先进先出)是一种常见的数据缓冲器,用于在数据生产者和消费者之间递数据。下面是一个基本的异步FIFO的Verilog实现示例: ```verilog module AsyncFIFO ( input wire clk, input wire rst, input wire wr_en, input wire rd_en, input wire [DATA_WIDTH-1:0] wr_data, output wire [DATA_WIDTH-1:0] rd_data, output wire full, output wire empty ); parameter DEPTH = 16; // FIFO深度 parameter DATA_WIDTH = 8; // 数据宽度 reg [DATA_WIDTH-1:0] mem [0:DEPTH-1]; reg [DATA_WIDTH-1:0] rd_ptr; reg [DATA_WIDTH-1:0] wr_ptr; reg [DATA_WIDTH-1:0] next_wr_ptr; reg [DATA_WIDTH-1:0] next_rd_ptr; reg full, empty; always @(posedge clk or posedge rst) begin if (rst) begin rd_ptr <= 0; wr_ptr <= 0; full <= 0; empty <= 1; end else begin rd_ptr <= next_rd_ptr; wr_ptr <= next_wr_ptr; full <= (next_wr_ptr == next_rd_ptr) && wr_en; empty <= (next_wr_ptr == next_rd_ptr) && rd_en; end end always @(posedge clk) begin if (rst) begin next_wr_ptr <= 0; next_rd_ptr <= 0; end else begin if (wr_en && !full) next_wr_ptr <= wr_ptr + 1; else next_wr_ptr <= wr_ptr; if (rd_en && !empty) next_rd_ptr <= rd_ptr + 1; else next_rd_ptr <= rd_ptr; end end assign rd_data = mem[rd_ptr]; always @(posedge clk) begin if (rst) begin mem[wr_ptr] <= 0; end else begin if (wr_en && !full) mem[wr_ptr] <= wr_data; end end endmodule ``` 这个异步FIFO模块包含了输入和输出端口,以及一些内部寄存器用于存储数据和指针。其中,`clk`是时钟信号,`rst`是复位信号,`wr_en`是写使能信号,`rd_en`是读使能信号,`wr_data`是写入数据,`rd_data`是输出数据,`full`表示FIFO是否已满,`empty`表示FIFO是否为空。 在时钟上升沿触发的过程中,根据输入的控制信号和当前状态,更新下一个时钟周期的指针和状态。同时,根据输入的写使能信号和当前状态,将写入数据存储到相应的位置。 这个异步FIFO模块可以根据需要进行参数化,包括FIFO的深度(DEPTH)和数据宽度(DATA_WIDTH)。 以上是一个基本的异步FIFO的Verilog实现示例,你可以根据实际需求进行修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C.V-Pupil

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值