AXI-LITE使用教程(二)

免责声明:

本文所提供的信息和内容仅供参考。作者对本文内容的准确性、完整性、及时性或适用性不作任何明示或暗示的保证。在任何情况下,作者不对因使用本文内容而导致的任何直接或间接损失承担责任,包括但不限于数据丢失、业务中断或其他经济损失。

读者在使用本文信息时,应自行验证其准确性和适用性,并对其使用结果负责。本文内容不构成专业技术咨询或建议,具体的技术实现和应用应根据实际情况和需要进行详细分析和验证。

本文所涉及的任何商标、版权或其他知识产权均属于其各自的所有者。若本文中引用了第三方的资料或信息,引用仅为学术交流目的,不构成对第三方内容的认可或保证。

若有任何疑问或需进一步信息,请联系本文作者或相关专业人士。

目录

前言

一、生成AXI-LITE

二、示例程序讲解

1.IO接口

2.需要控制的接口

3.局部参数

4.定义所需的logic register space

5.生成axi_awready

6.锁存axi_awaddr

7.生成axi_wready

8.握手信号slv_reg_wren

9.更新寄存器

10.生成axi_bvalid、axi_bresp

11.生成axi_arready并锁存axi_araddr

12.生成axi_rvalid以及响应信号

13.更新待读寄存器数据

14.更新读端口数据axi_rdata

 

总结

 


前言

本期文章将讲述xilinx-vivado-AXI-LITE的程序


 

一、生成AXI-LITE

1.

cc4b5dcfb96f4bbc8d164aa2133ed55b.png

2.

4e71e99650cc45c68ccd9ad60fa54770.png

3.选择lite,slave,寄存器数量随意

228526fcefee4901b0f79fb55b283f44.png

 

二、示例程序讲解

AXI-Lite协议因其简单、低资源占用和低延迟等优点,非常适合作为从设备的接口协议。它在需要简单、快速和可靠访问的场景中,如控制和状态寄存器访问中,表现尤为出色。

1.IO接口

	module myip_v1_0_S00_AXI #
	(
		parameter integer C_S_AXI_DATA_WIDTH	= 32,//数据位宽
		parameter integer C_S_AXI_ADDR_WIDTH	= 4//地址位宽,与之前选择的寄存器数量对应,为什么是4bit? 0-3号地址空间存储第一个数据,依次类推
	)
	(

		input wire  S_AXI_ACLK,//AXI时钟
		input wire  S_AXI_ARESETN,//复位,低电平有效
		input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,//写地址
		input wire [2 : 0] S_AXI_AWPROT,//保护类型
		input wire  S_AXI_AWVALID,//写地址有效信号
		output wire  S_AXI_AWREADY,//从设备准备好接收写地址信号
		input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,//写数据信号  
		input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,//指定写数据中哪些字节是有效的
		input wire  S_AXI_WVALID,//写数据有效信号
		output wire  S_AXI_WREADY,//从设备准备好接收写数据信号。
		output wire [1 : 0] S_AXI_BRESP,//写响应信号
		output wire  S_AXI_BVALID,//写响应有效信号
		input wire  S_AXI_BREADY,//主设备准备好接收写响应信号
		input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,//读地址信号。
		input wire [2 : 0] S_AXI_ARPROT,//保护类型
		input wire  S_AXI_ARVALID,//读地址有效信号。
		output wire  S_AXI_ARREADY,//从设备准备好接收读地址信号。
		output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,//读数据信号
		output wire [1 : 0] S_AXI_RRESP,//读响应信号。
		output wire  S_AXI_RVALID,//读数据有效信号。
		input wire  S_AXI_RREADY//主设备准备好接收读数据信号。
	);

2.需要控制的接口

	// AXI4LITE signals
	reg [C_S_AXI_ADDR_WIDTH-1 : 0] 	axi_awaddr;
	reg  	axi_awready;
	reg  	axi_wready;
	reg [1 : 0] 	axi_bresp;
	reg  	axi_bvalid;
	reg [C_S_AXI_ADDR_WIDTH-1 : 0] 	axi_araddr;
	reg  	axi_arready;
	reg [C_S_AXI_DATA_WIDTH-1 : 0] 	axi_rdata;
	reg [1 : 0] 	axi_rresp;
	reg  	axi_rvalid;

3.局部参数

用于处理AXI接口中的地址位偏移和内存地址位数。

    // Example-specific design signals
    // local parameter for addressing 32 bit / 64 bit C_S_AXI_DATA_WIDTH
    // ADDR_LSB is used for addressing 32/64 bit registers/memories
    // ADDR_LSB = 2 for 32 bits (n downto 2)
    // ADDR_LSB = 3 for 64 bits (n downto 3)
    localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
    localparam integer OPT_MEM_ADDR_BITS = 1;

OPT_MEM_ADDR_BITS随设置的寄存器数量变化

4.定义所需的logic register space

	//----------------------------------------------
	//-- Signals for user logic register space example
	//------------------------------------------------
	//-- Number of Slave Registers 4
	reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg0;
	reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg1;
	reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg2;
	reg [C_S_AXI_DATA_WIDTH-1:0]	slv_reg3;
	wire	 slv_reg_rden;
	wire	 slv_reg_wren;
	reg [C_S_AXI_DATA_WIDTH-1:0]	 reg_data_out;
	integer	 byte_index;
	reg	 aw_en;

	// I/O Connections assignments

	assign S_AXI_AWREADY	= axi_awready;
	assign S_AXI_WREADY	= axi_wready;
	assign S_AXI_BRESP	= axi_bresp;
	assign S_AXI_BVALID	= axi_bvalid;
	assign S_AXI_ARREADY	= axi_arready;
	assign S_AXI_RDATA	= axi_rdata;
	assign S_AXI_RRESP	= axi_rresp;
	assign S_AXI_RVALID	= axi_rvalid;

5.生成axi_awready

c90095b896cd4d08af5204375189f830.png

当~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en条件满足,axi_awready就拉高一个时钟周期,其余情况下axi_awready始终为低;aw_en等待写相应握手后拉低。

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

6.锁存axi_awaddr

触发条件与axi_awready相似(地址与其有效信号同步)

	// Implement axi_awaddr latching
	// This process is used to latch the address when both 
	// S_AXI_AWVALID and S_AXI_WVALID are valid. 

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_awaddr <= 0;
	    end 
	  else
	    begin    
	      if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
	        begin
	          // Write Address latching 
	          axi_awaddr <= S_AXI_AWADDR;
	        end
	    end 
	end 

7.生成axi_wready

触发条件与axi_awready相似

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

8.握手信号slv_reg_wren

    axi_wready、S_AXI_WVALID、 axi_awready 、S_AXI_AWVALID同时有效标志数据有效

	assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;

9.更新寄存器

AXI-LITE总线的数据位宽位32bit,一个地址空间存储一个字节的数据;因此第一个32bit数据的空间地址为0-3;第二个为4-7;第三个为8-11,第四个为12-15;这样就能理解axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]  

注:当slv_reg_wren拉高时标志数据有效;举例,当byte_index=0时,[(byte_index*8) +: 8]

等效为 (7:0)

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      slv_reg0 <= 0;
	      slv_reg1 <= 0;
	      slv_reg2 <= 0;
	      slv_reg3 <= 0;
	    end 
	  else begin
	    if (slv_reg_wren)
	      begin
	        case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
	          2'h0:
	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
	                // Respective byte enables are asserted as per write strobes 
	                // Slave register 0
	                slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
	              end  
	          2'h1:
	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
	                // Respective byte enables are asserted as per write strobes 
	                // Slave register 1
	                slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
	              end  
	          2'h2:
	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
	                // Respective byte enables are asserted as per write strobes 
	                // Slave register 2
	                slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
	              end  
	          2'h3:
	            for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
	              if ( S_AXI_WSTRB[byte_index] == 1 ) begin
	                // Respective byte enables are asserted as per write strobes 
	                // Slave register 3
	                slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
	              end  
	          default : begin
	                      slv_reg0 <= slv_reg0;
	                      slv_reg1 <= slv_reg1;
	                      slv_reg2 <= slv_reg2;
	                      slv_reg3 <= slv_reg3;
	                    end
	        endcase
	      end
	  end
	end 

10.生成axi_bvalid、axi_bresp

axi_bresp可以单独拿出来,设置为2'b0;而axi_bvalid需要等待axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID这四个信号握手。

	// Implement write response logic generation
	// The write response and response valid signals are asserted by the slave 
	// when axi_wready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted.  
	// This marks the acceptance of address and indicates the status of 
	// write transaction.

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_bvalid  <= 0;
	      axi_bresp   <= 2'b0;
	    end 
	  else
	    begin    
	      if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID)
	        begin
	          // indicates a valid write response is available
	          axi_bvalid <= 1'b1;
	          axi_bresp  <= 2'b0; // 'OKAY' response 
	        end                   // work error responses in future
	      else
	        begin
	          if (S_AXI_BREADY && axi_bvalid) 
	            //check if bready is asserted while bvalid is high) 
	            //(there is a possibility that bready is always asserted high)   
	            begin
	              axi_bvalid <= 1'b0; 
	            end  
	        end
	    end
	end   

11.生成axi_arready并锁存axi_araddr

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_arready <= 1'b0;
	      axi_araddr  <= 32'b0;
	    end 
	  else
	    begin    
	      if (~axi_arready && S_AXI_ARVALID)
	        begin
	          // indicates that the slave has acceped the valid read address
	          axi_arready <= 1'b1;
	          // Read address latching
	          axi_araddr  <= S_AXI_ARADDR;
	        end
	      else
	        begin
	          axi_arready <= 1'b0;
	        end
	    end 
	end 

12.生成axi_rvalid以及响应信号

	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_rvalid <= 0;
	      axi_rresp  <= 0;
	    end 
	  else
	    begin    
	      if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)
	        begin
	          // Valid read data is available at the read data bus
	          axi_rvalid <= 1'b1;
	          axi_rresp  <= 2'b0; // 'OKAY' response
	        end   
	      else if (axi_rvalid && S_AXI_RREADY)
	        begin
	          // Read data is accepted by the master
	          axi_rvalid <= 1'b0;
	        end                
	    end
	end  

13.更新待读寄存器数据

slv_reg_rden比axi_rvalid快一个时钟周期

	assign slv_reg_rden = axi_arready & S_AXI_ARVALID & ~axi_rvalid;
	always @(*)
	begin
	      // Address decoding for reading registers
	      case ( axi_araddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
	        2'h0   : reg_data_out <= slv_reg0;
	        2'h1   : reg_data_out <= slv_reg1;
	        2'h2   : reg_data_out <= slv_reg2;
	        2'h3   : reg_data_out <= slv_reg3;
	        default : reg_data_out <= 0;
	      endcase
	end

14.更新读端口数据axi_rdata

	// Output register or memory read data
	always @( posedge S_AXI_ACLK )
	begin
	  if ( S_AXI_ARESETN == 1'b0 )
	    begin
	      axi_rdata  <= 0;
	    end 
	  else
	    begin    
	      // When there is a valid read address (S_AXI_ARVALID) with 
	      // acceptance of read address by the slave (axi_arready), 
	      // output the read dada 
	      if (slv_reg_rden)
	        begin
	          axi_rdata <= reg_data_out;     // register read data
	        end   
	    end
	end    

 

 

 


总结

至此,AXI-LITE示例代码讲解完毕,下期会讲解如何将AXI-LITE植入自己的代码中。

 

  • 23
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值