20210801:AXI-Lite总线逻辑与关键源码分析

2021/8/2 1:05:51

本文主要是介绍20210801:AXI-Lite总线逻辑与关键源码分析,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

AXI-lite协议源码细读

AXI主从机交互模式

AXI和AXI-lite均包含五个不同的通道(允许同时读写、双向通信)。

  1. 读地址通道
  2. 写地址通道
  3. 读数据通道
  4. 写数据通道
  5. 写响应通道

读交易交互图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-esyNpnKV-1627831948610)(C:\Users\Mr.IMMUNIZE\AppData\Roaming\Typora\typora-user-images\image-20210801111952531.png)]

写交易交互图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TLaBjfm8-1627831948613)(C:\Users\Mr.IMMUNIZE\AppData\Roaming\Typora\typora-user-images\image-20210801112005487.png)]

源码实现细节

简单概括上面两个图。

读交易过程如上图,主端发送要读的地址,从端把这些地址的数据反馈给主端。

写交易过程见1-2,主端发送要写的地址和数据,完成之后从端发送完成响应。

具体的实现细节,我们以源码进行分析仿真,结合官方提供的一系列文档进行说明。最终达到深入理解AXI-lite的交互过程。

	always @(posedge M_AXI_ACLK)										      
	  begin                                                                        
	    //Only VALID signals must be deasserted during reset per AXI spec          
	    //Consider inverting then registering active-low reset for higher fmax     
	    if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                   
	      begin                                                                    
	        axi_awvalid <= 1'b0;                                                   
	      end                                                                      
	      //Signal a new address/data command is available by user logic           
	    else                                                                       
	      begin                                                                    
	        if (start_single_write)                                                
	          begin                                                                
	            axi_awvalid <= 1'b1;                                               
	          end                                                                  
	     //Address accepted by interconnect/slave (issue of M_AXI_AWREADY by slave)
	        else if (M_AXI_AWREADY && axi_awvalid)                                 
	          begin                                                                
	            axi_awvalid <= 1'b0;                                               
	          end                                                                  
	      end                                                                      
	  end  
	//--------------------
	//Write Data Channel
	//--------------------

	//The write data channel is for transfering the actual data.
	//The data generation is speific to the example design, and 
	//so only the WVALID/WREADY handshake is shown here

	   always @(posedge M_AXI_ACLK)                                        
	   begin                                                                         
	     if (M_AXI_ARESETN == 0  || init_txn_pulse == 1'b1)                                                    
	       begin                                                                     
	         axi_wvalid <= 1'b0;                                                     
	       end                                                                       
	     //Signal a new address/data command is available by user logic              
	     else if (start_single_write)                                                
	       begin                                                                     
	         axi_wvalid <= 1'b1;                                                     
	       end                                                                       
	     //Data accepted by interconnect/slave (issue of M_AXI_WREADY by slave)      
	     else if (M_AXI_WREADY && axi_wvalid)                                        
	       begin                                                                     
	        axi_wvalid <= 1'b0;                                                      
	       end                                                                       
	   end    

注意到主端口的源码中,start_single_write拉高时axi_awvalid和axi_wvalid同时拉高。即写地址和写数据通道有效的信号。

写完之后从端口会反馈响应信号M_AXI_WREADY和M_AXI_AWREADY表示地址写入和数据写入完成。而在从端口源码中也提到了类似的信号S_AXI_WREADY和S_AXI_AWREADY的产生逻辑如下:

	// Implement axi_awready generation
	// axi_awready is asserted for one S_AXI_ACLK clock cycle when both
	// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_awready is
	// de-asserted when reset is low.

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_awready <= 1'b0;
	      aw_en <= 1'b1;
	    end 
	  else
	    begin    
	      if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
	        begin
	          // slave is ready to accept write address when 
	          // there is a valid write address and write data
	          // on the write address and data bus. This design 
	          // expects no outstanding transactions. 
	          axi_awready <= 1'b1;
	          aw_en <= 1'b0;
	        end
	        else if (S_AXI_BREADY && axi_bvalid)
	            begin
	              aw_en <= 1'b1;
	              axi_awready <= 1'b0;
	            end
	      else           
	        begin
	          axi_awready <= 1'b0;
	        end
	    end 
	end 

	// Implement axi_wready generation
	// axi_wready is asserted for one S_AXI_ACLK clock cycle when both
	// S_AXI_AWVALID and S_AXI_WVALID are asserted. axi_wready is 
	// de-asserted when reset is low. 

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_wready <= 1'b0;
	    end 
	  else
	    begin    
	      if (~axi_wready && S_AXI_WVALID && S_AXI_AWVALID && aw_en )
	        begin
	          // slave is ready to accept write data when 
	          // there is a valid write address and write data
	          // on the write address and data bus. This design 
	          // expects no outstanding transactions. 
	          axi_wready <= 1'b1;
	        end
	      else
	        begin
	          axi_wready <= 1'b0;
	        end
	    end 
	end  

我们可以在tb中将主从端口全部都输入相同的源信号,然后给与主端口的信号发送开始脉冲,即可启动整个交互过程。

交互的关键tb代码如下:

initial begin
        sys_clk_i = 1;
        sys_rst_n = 0;
        m_axi_init_axi_txn = 0;
        #40 sys_rst_n = 1'b1;
        #20 m_axi_init_axi_txn = 1;
        #20 m_axi_init_axi_txn = 0;
end

.m00_axi_init_axi_txn(m_axi_init_axi_txn),
        

注意到我们启动时会需要一个脉冲起始位,连接到主端口来进行启动。使用block_board直观显示如图。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yxpDSlWh-1627831948619)(C:\Users\Mr.IMMUNIZE\AppData\Roaming\Typora\typora-user-images\image-20210801232310796.png)]

可以很明显的看到主设备端口比从设备端口多出的几个接口设计。也能体现最开始图中出现的AXI读写逻辑。

到此我们再根据tb仿真图可以看到更加清晰的读写逻辑,如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HEMo90td-1627831948626)(C:\Users\Mr.IMMUNIZE\AppData\Roaming\Typora\typora-user-images\image-20210801232705090.png)]

可以清晰的看到先写后读的数据交互过程,从而对AXI-Lite总线协议有个更加深刻的理解。

参考文件(百度直接搜索即可下载)

  1. ug1037-vivado-axi-reference-guide
  2. IHI0022E_amba_axi_and_ace_protocol_spec

写在最后

不必再相信不该相信的人,努力前行就好。



这篇关于20210801:AXI-Lite总线逻辑与关键源码分析的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程