您当前的位置: 首页 > 

9527华安

暂无认证

  • 3浏览

    0关注

    35博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

米联客FDMA及其控制器代码逐行讲解,全网最细,不接受反驳

9527华安 发布时间:2021-11-16 14:33:41 ,浏览量:3

米联客FDMA及其控制器代码逐行讲解,全网最细,不接受反驳 对于做图像处理的兄弟来说,图像缓存是基本操作,一般是图像三帧缓存于DDR3,然后再读出显示,DDR3操作很复杂,所以Xilinx官方出了个MIG 的IP核供开发者使用,但对于像我这样的little_white来说,操作MIG 的用户接口还是不方便,所以又有了挂载AXI4总线的AXI4_MIG,这下不就简单了,直接操作AXI不就完了吗?不再需要关心底层怎么搞了。 基于此,米联客搞了一个叫做FDMA的东西,实质就是一个AXI4_FULL的主机总线,即使有了FDMA还不行,还得有控制图像读写发热控制器,米联客都给出了源码,也给了文档,但无奈,米联客的代码虽然写得精简漂亮,但文档写得确实一般,加之代码的有些变量命名也不太恰当,使得像我这样的little_white有些云雾缭绕 所以我对FDMA及其控制器的源码进行了优化,现在逐行解读: FDMA部分:


	module uiFDMA#
	(
		parameter  integer        C_M_AXI_BURST_LEN	 = 64 , //AXI的一次读写突发长度
		parameter  integer        C_M_AXI_ID_WIDTH	 = 1  ,
		parameter  integer        C_M_AXI_ID		 = 0  ,
		parameter  integer        C_M_AXI_ADDR_WIDTH = 32 , 
		parameter  integer        C_M_AXI_DATA_WIDTH = 32  //AXI的数据位宽					
	)
	(

		//user logic 
		input   wire                               pkg_wr_areq         ,	//FDMS包写请求,一个时钟脉冲		
		output  wire                               pkg_wr_last		   ,	//FDMS包写数据结尾
		input   wire [C_M_AXI_DATA_WIDTH-1 :0]     pkg_wr_data		   ,	//FDMS包写数据包
		output	wire                               pkg_wr_en		   ,	//指示FDMS正在写数据,高有效
		input   wire [C_M_AXI_ADDR_WIDTH-1 :0]     pkg_wr_addr		   ,	//FDMS包写数据包地址
		input   wire [C_M_AXI_ADDR_WIDTH-1 :0]     pkg_wr_size         ,	//FDMS包写数据包长度,应为
																			//C_M_AXI_BURST_LEN的整数倍 

        input   wire                               pkg_rd_areq         ,     
		output  wire                               pkg_rd_last			,
		output  wire [C_M_AXI_DATA_WIDTH-1 :0]     pkg_rd_data			,	
		output  wire                               pkg_rd_en           ,  	
		input   wire [C_M_AXI_ADDR_WIDTH-1 :0]     pkg_rd_addr			, 	
		input   wire [C_M_AXI_ADDR_WIDTH-1 :0]     pkg_rd_size         , 			
		//input  	wire  							INIT_AXI_TXN		,
		
		input 	wire  								M_AXI_ACLK			,
		input 	wire  								M_AXI_ARESETN		,
		output 	wire [C_M_AXI_ID_WIDTH-1 : 0]		M_AXI_AWID			,	 
		output 	wire [C_M_AXI_ADDR_WIDTH-1 : 0] 	M_AXI_AWADDR		,    
		output 	wire [7 : 0]						M_AXI_AWLEN			,    
		output 	wire [2 : 0] 						M_AXI_AWSIZE		,    
		output 	wire [1 : 0] 						M_AXI_AWBURST		,    
		output 	wire  								M_AXI_AWLOCK		,    
		output 	wire [3 : 0] 						M_AXI_AWCACHE		,    
		output 	wire [2 : 0] 						M_AXI_AWPROT		,    
		output 	wire [3 : 0] 						M_AXI_AWQOS			,     
		output 	wire  								M_AXI_AWVALID		,    
		input	wire  								M_AXI_AWREADY		,    
		output  wire [C_M_AXI_DATA_WIDTH-1 : 0] 	M_AXI_WDATA			,	 
		output  wire [C_M_AXI_DATA_WIDTH/8-1 : 0] 	M_AXI_WSTRB			,	 
		output  wire  								M_AXI_WLAST			,	 			
		output  wire  								M_AXI_WVALID		,	 
		input   wire  								M_AXI_WREADY		,	 
		input   wire [C_M_AXI_ID_WIDTH-1 : 0] 		M_AXI_BID			,		
		input   wire [1 : 0] 						M_AXI_BRESP			,		
		input   wire  								M_AXI_BVALID		,	
		output  wire  								M_AXI_BREADY		,	 
		                                                                     
		output  wire [C_M_AXI_ID_WIDTH-1 : 0] 		M_AXI_ARID			,	 
		output  wire [C_M_AXI_ADDR_WIDTH-1 : 0] 	M_AXI_ARADDR		,	 	
		output  wire [7 : 0] 						M_AXI_ARLEN			,	 
		output  wire [2 : 0] 						M_AXI_ARSIZE		,	 
		output  wire [1 : 0] 						M_AXI_ARBURST		,	 
		output  wire  								M_AXI_ARLOCK		,	 
		output  wire [3 : 0] 						M_AXI_ARCACHE		,	 
		output  wire [2 : 0] 						M_AXI_ARPROT		,	 
		output  wire [3 : 0] 						M_AXI_ARQOS			,	 	   
		output  wire  								M_AXI_ARVALID		,	 
		input   wire  								M_AXI_ARREADY		,	 
		input   wire [C_M_AXI_ID_WIDTH-1 : 0] 		M_AXI_RID			,	 
		input   wire [C_M_AXI_DATA_WIDTH-1 : 0] 	M_AXI_RDATA			,	 
		input   wire [1 : 0] 						M_AXI_RRESP			,	 
		input   wire  								M_AXI_RLAST			,	 
		input   wire  								M_AXI_RVALID		,    
		output  wire  								M_AXI_RREADY			 
	);
         
	  function integer clogb2 (input integer bit_depth);              
	  begin                                                           
	    for(clogb2=0; bit_depth>0; clogb2=clogb2+1)                   
	      bit_depth = bit_depth >> 1;                                 
	    end                                                           
	  endfunction                                                     

	 localparam integer C_TRANSACTIONS_NUM = clogb2(C_M_AXI_BURST_LEN-1);	
	 localparam integer BURST_SIZE = C_M_AXI_BURST_LEN * C_M_AXI_DATA_WIDTH/8;	//一包FDMA数据包所占的字节数(或理解为一包数据的总地址)
	// AXI4LITE signals
	//AXI4 internal temp signals
//write
	reg 	[C_M_AXI_ADDR_WIDTH-1 : 0] 	axi_awaddr	;	//写地址
	reg  						 		axi_awvalid	;	//写地址有效
	wire 	[C_M_AXI_DATA_WIDTH-1 : 0] 	axi_wdata	;	//写数据
	reg  								axi_wlast	;	//写数据结尾
	reg  								axi_wvalid	;	//写数据有效
//read	
	reg 	[C_M_AXI_ADDR_WIDTH-1 : 0] 	axi_araddr	;	//读地址
	reg  								axi_arvalid	;	//读地址有效
	reg  								axi_rready	;	//读数据准备
	
//	wire [C_TRANSACTIONS_NUM+2 : 0] 	burst_size_bytes;	
	assign M_AXI_AWID		= C_M_AXI_ID;
	assign M_AXI_AWADDR		= axi_awaddr;
	assign M_AXI_AWLEN		= C_M_AXI_BURST_LEN - 1;
	assign M_AXI_AWSIZE		= clogb2((C_M_AXI_DATA_WIDTH/8)-1);
	assign M_AXI_AWBURST	= 2'b01;
	assign M_AXI_AWLOCK		= 1'b0;
	assign M_AXI_AWCACHE	= 4'b0010;
	assign M_AXI_AWPROT		= 3'h0;
	assign M_AXI_AWQOS		= 4'h0;
	assign M_AXI_AWVALID	= axi_awvalid;
	assign M_AXI_WDATA		= axi_wdata;
	assign M_AXI_WSTRB		= {(C_M_AXI_DATA_WIDTH/8){1'b1}};	//每个字节都选通,都有效
	assign M_AXI_WLAST		= axi_wlast;
	assign M_AXI_WVALID		= axi_wvalid;
	assign M_AXI_BREADY		= axi_bready;
		
	assign M_AXI_ARID		= C_M_AXI_ID;
	assign M_AXI_ARADDR		= axi_araddr;
	assign M_AXI_ARLEN		= C_M_AXI_BURST_LEN - 1;
	assign M_AXI_ARSIZE		= clogb2((C_M_AXI_DATA_WIDTH/8)-1);
	assign M_AXI_ARBURST	= 2'b01;
	assign M_AXI_ARLOCK		= 1'b0;
	assign M_AXI_ARCACHE	= 4'b0010;
	assign M_AXI_ARPROT		= 3'h0;
	assign M_AXI_ARQOS		= 4'h0;
	assign M_AXI_ARVALID	= axi_arvalid;
	assign M_AXI_RREADY		= axi_rready;
	
   	reg [7 :0 ]                      w_axi4_cnt   ; 
    reg [C_M_AXI_ADDR_WIDTH-1 : 0]   WR_BASE_ADDR  ;
    reg [C_M_AXI_ADDR_WIDTH-1 : 0]   RD_BASE_ADDR  ;
	reg [C_M_AXI_ADDR_WIDTH-1 : 0]   w_fdma_cnt   ;
	reg [C_M_AXI_ADDR_WIDTH-1 : 0]   r_fdma_cnt   ;  
    reg                              w_axi4_flag  ;
    reg                              r_axi4_addr_flag ;
    reg                              r_axi4_data_flag;
    
	wire w_next = (axi_wvalid && M_AXI_WREADY);
	wire r_next = (M_AXI_RVALID && axi_rready);
    
	assign pkg_wr_en      =   w_next;  								 //写一包FDMAMA数据标志 
	assign pkg_wr_last    =  (w_next && w_fdma_cnt==pkg_wr_size-1); //写一包FDMAMA数据结尾	
	assign axi_wdata      =  pkg_wr_data;
	
	assign pkg_rd_en      =  r_next;								 //读一包FDMAMA数据标志 	
	assign pkg_rd_last    =  (r_next && r_fdma_cnt==pkg_rd_size-1); //读一包FDMAMA数据结尾	
	assign pkg_rd_data    =  M_AXI_RDATA;

//----------------------------------------------------------------------------	
//AXI4 FULL Write
//AXI4 data is ready for axi master write to slave	

reg w_fdma_flag;	//这里原来不叫这个名字,由于命名不直观,我改了
//标志fdma传输过程
always @(posedge M_AXI_ACLK) begin
	if(M_AXI_ARESETN == 1'b0) w_fdma_flag             
关注
打赏
1659431378
查看更多评论
0.0417s