3.AXI协议讲解

1.简介

  AXI4协议是ZYNQ中非常重要的一个协议,包括AXI4_FULL、AXI4_LITE、AXI4_Stream三大协议。是XILINX官方IP的重要接口以及PS、PL通讯的主要手段。
  AXI4协议分为读写两类通道,这两类通道又分为地址通道和数据通道,另外写通道多一个写响应通道。所以AXI4的LITE和FULL都有五个通道。
  通道信号的命名规则为xx_xx_xx。
  第一个xx有S和M两种,M为Master表示AXI主机。S为Slave表示AXI从机。
  第二个xx有axi和axis两种,axi表示该接口为axi_full或者lite。axis表示axi_stream。
  第三个xx表示通道以及通道内的型号,前两个字母表示通道的简写,其中有r(read),w(write),a(addr),data这几个含义的简写。
  axi_lite和axi_full最大的区别就是一个不支持突发一个支持突发。
  axi和axis的区别就是一个带地址映射一个不带地址映射。

2.AXI4_LITE

  AXI4_LITE一次只能传输一个数据,不支持突发
  axi_slave内部的寻址方式:
  当SLAVE接收到地址后,如何判断这是SLAVE内部的那个寄存器呢?当我们运用官方IP例化一个四个32位寄存器的SLAVE接口时,查看内部代码。
    在寄存器的赋值语句块中方可以看到:
    case中是主机发送的地址位。可以看到当位宽为32位四个寄存器时例化。SLAVE接口只认axi_addr第三位和第四位的地址。其余地址不认。OPT_MEM_ADDR_BITS=1代表有效的地址位只有两位,可以识别四个寄存器。ADDR_LSB表示从第三位开始有效,因为一个字节占就是axi_addr的1bit,32位有4字节。
这里贴出例化的axi_slave和改造后的axi_master,axi_test以及测试仿真模块。

	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

以及

	localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
	localparam integer OPT_MEM_ADDR_BITS = 1;
`timescale 1 ns / 1 ps

	module axi_master #
	(
		// Users to add parameters here		
		// User parameters ends
		// Do not modify the parameters beyond this line

		// The master requires a target slave base address.
    // The master will initiate read and write transactions on the slave with base address specified here as a parameter.
		parameter  C_M_TARGET_SLAVE_BASE_ADDR	= 32'h00000000,
		// Width of M_AXI address bus. 
    // The master generates the read and write addresses of width specified as C_M_AXI_ADDR_WIDTH.
		parameter integer C_M_AXI_ADDR_WIDTH	= 32,
		// Width of M_AXI data bus. 
    // The master issues write data and accept read data where the width of the data bus is C_M_AXI_DATA_WIDTH
		parameter integer C_M_AXI_DATA_WIDTH	= 32
    // and read transactions the master will perform as a part of this example memory test.
	)
	(
		// Users to add ports here
 		input 	wire  [C_M_AXI_ADDR_WIDTH-1: 0]		wr_addr 	,
  		input  	wire   		 						wr_start 	,
 		input 	wire  [C_M_AXI_ADDR_WIDTH-1 :0]		wr_data 	,
 		output 	reg  		 						wr_done  	,

 		input  	wire  [C_M_AXI_ADDR_WIDTH-1 :0] 	rd_addr 	,
 		input 	wire   		 	  					rd_start 	,
 		output 	reg   [C_M_AXI_ADDR_WIDTH-1 :0]		rd_data 	,
 		output 	reg   		 						rd_done 	,
		// User ports ends
		// Do not modify the ports beyond this line

		// Initiate AXI transactions
		// Asserts when ERROR is detected
		// Asserts when AXI transactions is complete
		// AXI clock signal
		input wire  M_AXI_ACLK,
		// AXI active low reset signal
		input wire  M_AXI_ARESETN,
		// Master Interface Write Address Channel ports. Write address (issued by master)
		output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR,
		// Write channel Protection type.
    // This signal indicates the privilege and security level of the transaction,
    // and whether the transaction is a data access or an instruction access.
		output wire [2 : 0] M_AXI_AWPROT,
		// Write address valid. 
    // This signal indicates that the master signaling valid write address and control information.
		output wire  M_AXI_AWVALID,
		// Write address ready. 
    // This signal indicates that the slave is ready to accept an address and associated control signals.
		input wire  M_AXI_AWREADY,
		// Master Interface Write Data Channel ports. Write data (issued by master)
		output wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_WDATA,
		// Write strobes. 
    // This signal indicates which byte lanes hold valid data.
    // There is one write strobe bit for each eight bits of the write data bus.
		output wire [C_M_AXI_DATA_WIDTH/8-1 : 0] M_AXI_WSTRB,
		// Write valid. This signal indicates that valid write data and strobes are available.
		output wire  M_AXI_WVALID,
		// Write ready. This signal indicates that the slave can accept the write data.
		input wire  M_AXI_WREADY,
		// Master Interface Write Response Channel ports. 
    // This signal indicates the status of the write transaction.
		input wire [1 : 0] M_AXI_BRESP,
		// Write response valid. 
    // This signal indicates that the channel is signaling a valid write response
		input wire  M_AXI_BVALID,
		// Response ready. This signal indicates that the master can accept a write response.
		output wire  M_AXI_BREADY,
		// Master Interface Read Address Channel ports. Read address (issued by master)
		output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR,
		// Protection type. 
    // This signal indicates the privilege and security level of the transaction, 
    // and whether the transaction is a data access or an instruction access.
		output wire [2 : 0] M_AXI_ARPROT,
		// Read address valid. 
    // This signal indicates that the channel is signaling valid read address and control information.
		output wire  M_AXI_ARVALID,
		// Read address ready. 
    // This signal indicates that the slave is ready to accept an address and associated control signals.
		input wire  M_AXI_ARREADY,
		// Master Interface Read Data Channel ports. Read data (issued by slave)
		input wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA,
		// Read response. This signal indicates the status of the read transfer.
		input wire [1 : 0] M_AXI_RRESP,
		// Read valid. This signal indicates that the channel is signaling the required read data.
		input wire  M_AXI_RVALID,
		// Read ready. This signal indicates that the master can accept the read data and response information.
		output wire  M_AXI_RREADY
	);

	// function called clogb2 that returns an integer which has the
	// value of the ceiling of the log base 2

	 function integer clogb2 (input integer bit_depth);
		 begin
		 for(clogb2=0; bit_depth>0; clogb2=clogb2+1)
			 bit_depth = bit_depth >> 1;
		 end
	 endfunction

	// TRANS_NUM_BITS is the width of the index counter for 
	// number of write or read transaction.

	// Example State machine to initialize counter, initialize write transactions, 
	// initialize read transactions and comparison of read data with the 
	// written data words.

	 reg [1:0] mst_exec_state;

	// AXI4LITE signals
	//write address valid
	reg  	axi_awvalid;
	//write data valid
	reg  	axi_wvalid;
	//read address valid
	reg  	axi_arvalid;
	//read data acceptance
	reg  	axi_rready;
	//write response acceptance
	reg  	axi_bready;
	//write address
	reg [C_M_AXI_ADDR_WIDTH-1 : 0] 	axi_awaddr;
	//write data
	reg [C_M_AXI_DATA_WIDTH-1 : 0] 	axi_wdata;
	//read addresss
	reg [C_M_AXI_ADDR_WIDTH-1 : 0] 	axi_araddr;
	//Asserts when there is a write response error
	wire  	write_resp_error;
	//Asserts when there is a read response error
	wire  	read_resp_error;
	//A pulse to initiate a write transaction
	reg  	start_single_write;
	//A pulse to initiate a read transaction
	reg  	start_single_read;
	//Asserts when a single beat write transaction is issued and remains asserted till the completion of write trasaction.
	reg  	write_issued;
	//Asserts when a single beat read transaction is issued and remains asserted till the completion of read trasaction.
	reg  	read_issued;
	//flag that marks the completion of write trasactions. The number of write transaction is user selected by the parameter C_M_TRANSACTIONS_NUM.
	reg  	writes_done;
	//flag that marks the completion of read trasactions. The number of read transaction is user selected by the parameter C_M_TRANSACTIONS_NUM
	reg  	reads_done;
	//The error register is asserted when any of the write response error, read response error or the data mismatch flags are asserted.
	reg  	error_reg;
	//Expected read data used to compare with the read data.
	//Flag marks the completion of comparison of the read data with the expected read data
	// I/O Connections assignments

	//Adding the offset address to the base addr of the slave
	assign M_AXI_AWADDR	= C_M_TARGET_SLAVE_BASE_ADDR + axi_awaddr;
	//AXI 4 write data
	assign M_AXI_WDATA	= axi_wdata;
	assign M_AXI_AWPROT	= 3'b000;
	assign M_AXI_AWVALID	= axi_awvalid;
	//Write Data(W)
	assign M_AXI_WVALID	= axi_wvalid;
	//Set all byte strobes in this example
	assign M_AXI_WSTRB	= 4'b1111;
	//Write Response (B)
	assign M_AXI_BREADY	= axi_bready;
	//Read Address (AR)
	assign M_AXI_ARADDR	= C_M_TARGET_SLAVE_BASE_ADDR + axi_araddr;
	assign M_AXI_ARVALID	= axi_arvalid;
	assign M_AXI_ARPROT	= 3'b001;
	//Read and Read Response (R)
	assign M_AXI_RREADY	= axi_rready;   

	//--------------------
	//Write Address Channel
	//--------------------
	  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)                                                   
	      begin                                                                    
	        axi_awvalid <= 1'b0;                                                   
	      end                                                                      
	      //Signal a new address/data command is available by user logic           
	    else                                                                       
	      begin                                                                    
	        if (wr_start)                                                
	          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)                                                    
	       begin                                                                     
	         axi_wvalid <= 1'b0;                                                     
	       end                                                                       
	     //Signal a new address/data command is available by user logic              
	     else if (wr_start)                                                
	       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  

	  always @(posedge M_AXI_ACLK)                                  
	      begin                                                     
	        if (M_AXI_ARESETN == 0 )                                
	          begin                                                 
	            wr_done <= 0;             
	          end                                                   
	          // Signals a new write address/ write data is         
	          // available by user logic                            
	        else if (M_AXI_WREADY && axi_wvalid)                    
	          begin                                                 
	            wr_done <= 1;
	          end
	        else 
	          begin                                                 
	            wr_done <= 0;
	          end                                               
	      end                                                               


	//----------------------------
	//Write Response (B) Channel
	//----------------------------

	//The write response channel provides feedback that the write has committed
	//to memory. BREADY will occur after both the data and the write address
	//has arrived and been accepted by the slave, and can guarantee that no
	//other accesses launched afterwards will be able to be reordered before it.

	//The BRESP bit [1] is used indicate any errors from the interconnect or
	//slave for the entire write burst. This example will capture the error.

	//While not necessary per spec, it is advisable to reset READY signals in
	//case of differing reset latencies between master/slave.

	  always @(posedge M_AXI_ACLK)                                    
	  begin                                                                
	    if (M_AXI_ARESETN == 0)                                           
	      begin                                                            
	        axi_bready <= 1'b0;                                            
	      end                                                              
	    // accept/acknowledge bresp with axi_bready by the master          
	    // when M_AXI_BVALID is asserted by slave                          
	    else if (M_AXI_BVALID && ~axi_bready)                              
	      begin                                                            
	        axi_bready <= 1'b1;                                            
	      end                                                              
	    // deassert after one clock cycle                                  
	    else if (axi_bready)                                               
	      begin                                                            
	        axi_bready <= 1'b0;                                            
	      end                                                              
	    // retain the previous value                                       
	    else                                                               
	      axi_bready <= axi_bready;                                        
	  end                                                                  
	                                                                       
	//Flag write errors                                                    
	assign write_resp_error = (axi_bready & M_AXI_BVALID & M_AXI_BRESP[1]);


	//----------------------------
	//Read Address Channel
	//----------------------------                                                                                                                                                              
	  // A new axi_arvalid is asserted when there is a valid read address              
	  // available by the master. start_single_read triggers a new read                
	  // transaction                                                                   
	  always @(posedge M_AXI_ACLK)                                                     
	  begin                                                                            
	    if (M_AXI_ARESETN == 0)                                                       
	      begin                                                                        
	        axi_arvalid <= 1'b0;                                                       
	      end                                                                          
	    //Signal a new read address command is available by user logic                 
	    else if (rd_start)                                                    
	      begin                                                                        
	        axi_arvalid <= 1'b1;                                                       
	      end                                                                          
	    //RAddress accepted by interconnect/slave (issue of M_AXI_ARREADY by slave)    
	    else if (M_AXI_ARREADY && axi_arvalid)                                         
	      begin                                                                        
	        axi_arvalid <= 1'b0;                                                       
	      end                                                                          
	    // retain the previous value                                                   
	  end                                                                              


	//--------------------------------
	//Read Data (and Response) Channel
	//--------------------------------

	//The Read Data channel returns the results of the read request 
	//The master will accept the read data by asserting axi_rready
	//when there is a valid read data available.
	//While not necessary per spec, it is advisable to reset READY signals in
	//case of differing reset latencies between master/slave.

	  always @(posedge M_AXI_ACLK)                                    
	  begin                                                                 
	    if (M_AXI_ARESETN == 0)                                            
	      begin                                                             
	        axi_rready <= 1'b0;                                             
	      end                                                               
	    // accept/acknowledge rdata/rresp with axi_rready by the master     
	    // when M_AXI_RVALID is asserted by slave                           
	    else if (M_AXI_RVALID && ~axi_rready)                               
	      begin                                                             
	        axi_rready <= 1'b1;                                             
	      end                                                               
	    // deassert after one clock cycle                                   
	    else if (axi_rready)                                                
	      begin                                                             
	        axi_rready <= 1'b0;                                             
	      end                                                               
	    // retain the previous value                                        
	  end                                                                   
	                                                                        
	//Flag write errors                                                     
	assign read_resp_error = (axi_rready & M_AXI_RVALID & M_AXI_RRESP[1]);  


	//--------------------------------
	//User Logic
	//--------------------------------

	//Address/Data Stimulus

	//Address/data pairs for this example. The read and write values should
	//match.
	//Modify these as desired for different address patterns.

	  //Write Addresses                                        
	  always @(posedge M_AXI_ACLK)                                  
	      begin                                                     
	        if (M_AXI_ARESETN == 0)                                
	          begin                                                 
	            axi_awaddr <= 0;                                    
	          end                                                   
	          // Signals a new write address/ write data is         
	          // available by user logic                            
	        else if (wr_start)                  
	          begin                                                 
	            axi_awaddr <= wr_addr;                                                        
	          end                                                   
	      end                                                       
	                                                                
	  // Write data generation                                      
	  always @(posedge M_AXI_ACLK)                                  
	      begin                                                     
	        if (M_AXI_ARESETN == 0)                                
	          begin                                                 
	            axi_wdata <= 0;                  
	          end                                                   
	        // Signals a new write address/ write data is           
	        // available by user logic                              
	        else if (wr_start)                    
	          begin                                                 
	            axi_wdata <= wr_data;    
	          end                                                   
	        end          	                                       
	                                                                
	  //Read Addresses                                              
	  always @(posedge M_AXI_ACLK)                                  
	      begin                                                     
	        if (M_AXI_ARESETN == 0)                                
	          begin                                                 
	            axi_araddr <= 0;                                    
	          end                                                   
	          // Signals a new write address/ write data is         
	          // available by user logic                            
	        else if (rd_start)                  
	          begin                                                 
	            axi_araddr <= rd_addr;            
	          end                                                   
	      end                                                       
	                                                                
	                                                                
	                                                                
	  always @(posedge M_AXI_ACLK)                                  
	      begin                                                     
	        if (M_AXI_ARESETN == 0 )                                
	          begin                                                 
	            rd_data <= 0;             
	          end                                                   
	          // Signals a new write address/ write data is         
	          // available by user logic                            
	        else if (M_AXI_RVALID && axi_rready)                    
	          begin                                                 
	            rd_data <= M_AXI_RDATA;
	          end                                                   
	      end 

	  always @(posedge M_AXI_ACLK)                                  
	      begin                                                     
	        if (M_AXI_ARESETN == 0 )                                
	          begin                                                 
	            rd_done <= 0;             
	          end                                                   
	          // Signals a new write address/ write data is         
	          // available by user logic                            
	        else if (M_AXI_RVALID && axi_rready)                    
	          begin                                                 
	            rd_done <= 1;
	          end
	        else 
	          begin                                                 
	            rd_done <= 0;
	          end                                               
	      end                                                                                                        
	// Add user logic here

	// User logic ends

	endmodule


`timescale 1 ns / 1 ps

	module axi_slave #
	(
		// Users to add parameters here

		// User parameters ends
		// Do not modify the parameters beyond this line

		// Width of S_AXI data bus
		parameter integer C_S_AXI_DATA_WIDTH	= 32,
		// Width of S_AXI address bus
		parameter integer C_S_AXI_ADDR_WIDTH	= 4
	)
	(
		// Users to add ports here

		// User ports ends
		// Do not modify the ports beyond this line

		// Global Clock Signal
		input wire  S_AXI_ACLK,
		// Global Reset Signal. This Signal is Active LOW
		input wire  S_AXI_ARESETN,
		// Write address (issued by master, acceped by Slave)
		input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_AWADDR,
		// Write channel Protection type. This signal indicates the
    		// privilege and security level of the transaction, and whether
    		// the transaction is a data access or an instruction access.
		input wire [2 : 0] S_AXI_AWPROT,
		// Write address valid. This signal indicates that the master signaling
    		// valid write address and control information.
		input wire  S_AXI_AWVALID,
		// Write address ready. This signal indicates that the slave is ready
    		// to accept an address and associated control signals.
		output wire  S_AXI_AWREADY,
		// Write data (issued by master, acceped by Slave) 
		input wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_WDATA,
		// Write strobes. This signal indicates which byte lanes hold
    		// valid data. There is one write strobe bit for each eight
    		// bits of the write data bus.    
		input wire [(C_S_AXI_DATA_WIDTH/8)-1 : 0] S_AXI_WSTRB,
		// Write valid. This signal indicates that valid write
    		// data and strobes are available.
		input wire  S_AXI_WVALID,
		// Write ready. This signal indicates that the slave
    		// can accept the write data.
		output wire  S_AXI_WREADY,
		// Write response. This signal indicates the status
    		// of the write transaction.
		output wire [1 : 0] S_AXI_BRESP,
		// Write response valid. This signal indicates that the channel
    		// is signaling a valid write response.
		output wire  S_AXI_BVALID,
		// Response ready. This signal indicates that the master
    		// can accept a write response.
		input wire  S_AXI_BREADY,
		// Read address (issued by master, acceped by Slave)
		input wire [C_S_AXI_ADDR_WIDTH-1 : 0] S_AXI_ARADDR,
		// Protection type. This signal indicates the privilege
    		// and security level of the transaction, and whether the
    		// transaction is a data access or an instruction access.
		input wire [2 : 0] S_AXI_ARPROT,
		// Read address valid. This signal indicates that the channel
    		// is signaling valid read address and control information.
		input wire  S_AXI_ARVALID,
		// Read address ready. This signal indicates that the slave is
    		// ready to accept an address and associated control signals.
		output wire  S_AXI_ARREADY,
		// Read data (issued by slave)
		output wire [C_S_AXI_DATA_WIDTH-1 : 0] S_AXI_RDATA,
		// Read response. This signal indicates the status of the
    		// read transfer.
		output wire [1 : 0] S_AXI_RRESP,
		// Read valid. This signal indicates that the channel is
    		// signaling the required read data.
		output wire  S_AXI_RVALID,
		// Read ready. This signal indicates that the master can
    		// accept the read data and response information.
		input wire  S_AXI_RREADY
	);

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

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

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

	// Implement memory mapped register select and write logic generation
	// The write data is accepted and written to memory mapped registers when
	// axi_awready, S_AXI_WVALID, axi_wready and S_AXI_WVALID are asserted. Write strobes are used to
	// select byte enables of slave registers while writing.
	// These registers are cleared when reset (active low) is applied.
	// Slave register write enable is asserted when valid address and data are available
	// and the slave is ready to accept the write address and write data.
	assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;

	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    

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

	// Implement axi_arready generation
	// axi_arready is asserted for one S_AXI_ACLK clock cycle when
	// S_AXI_ARVALID is asserted. axi_awready is 
	// de-asserted when reset (active low) is asserted. 
	// The read address is also latched when S_AXI_ARVALID is 
	// asserted. axi_araddr is reset to zero on reset assertion.

	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       

	// Implement axi_arvalid generation
	// axi_rvalid is asserted for one S_AXI_ACLK clock cycle when both 
	// S_AXI_ARVALID and axi_arready are asserted. The slave registers 
	// data are available on the axi_rdata bus at this instance. The 
	// assertion of axi_rvalid marks the validity of read data on the 
	// bus and axi_rresp indicates the status of read transaction.axi_rvalid 
	// is deasserted on reset (active low). axi_rresp and axi_rdata are 
	// cleared to zero on reset (active low).  
	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    

	// Implement memory mapped register select and read logic generation
	// Slave register read enable is asserted when valid address is available
	// and the slave is ready to accept the read address.
	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

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

	// Add user logic here

	// User logic ends

	endmodule
`timescale 1ns / 1ps

module axi_test(
 	input 	wire 			clk 		,
 	input 	wire  			rst_n 		,

 	input 	wire  			wr_done 	,
 	output  wire   	[31:0]	wr_addr   	,
 	output 	wire  	 		wr_start 	,
 	output 	wire  	[31:0] 	wr_data 	,

 	input 	wire  			rd_done 	,
 	input 	wire  	[31:0] 	rd_data 	,
 	output  wire  	[31:0] 	rd_addr 	,
 	output 	wire  	 		rd_start 	
    );

parameter 	CNT_MAX = 100;

reg  	[10:0] 	cnt 	;
always @(posedge clk or negedge rst_n) begin
	if (rst_n == 0) begin
		cnt <= 	0;
	end
	else if (cnt == CNT_MAX) begin
		cnt <= 	0;
	end
	else begin
	 	cnt <= cnt + 1;
	 end 
end

assign 	wr_start = cnt == CNT_MAX;
assign 	rd_start = cnt == CNT_MAX;
assign 	wr_addr = 2<<2;
assign 	rd_addr = 2<<2;
assign 	wr_data = 25236;

endmodule
`timescale 1ns / 1ps

module tb_top();

reg 	clk_100M 	;
reg 	rst_n 		;
always #5 clk_100M = !clk_100M;

initial 	begin
	clk_100M 	=  	0;
	rst_n 		= 	0;
	#200
	rst_n 		= 	1;
	#10000
	$stop;
end

design_1_wrapper  u_design_1_wrapper(
	.clk_100M 	(clk_100M 	),
    .rst_n 		(rst_n 		)
);
endmodule

  连接如图
在这里插入图片描述

仿真后的波形如下图,写数据的过程如下图
在这里插入图片描述
读数据的过程如下图:在这里插入图片描述

3.AXI_FULL

这里先把改造后的源码贴出来,改造后提供突发的写起始地址、写开始信号、以及写数据和写数据有效信号,读信号同理。


`timescale 1 ns / 1 ps

	module AXI_Master_Full #
	(
		parameter  C_M_TARGET_SLAVE_BASE_ADDR	= 32'h40000000 	,
		parameter integer C_M_AXI_BURST_LEN		= 16 			,
		parameter integer C_M_AXI_ID_WIDTH		= 1 			,
		parameter integer C_M_AXI_ADDR_WIDTH	= 32 			,
		parameter integer C_M_AXI_DATA_WIDTH	= 32 			,
		parameter integer C_M_AXI_AWUSER_WIDTH	= 0 			,
		parameter integer C_M_AXI_ARUSER_WIDTH	= 0 			,
		parameter integer C_M_AXI_WUSER_WIDTH	= 0 			,
		parameter integer C_M_AXI_RUSER_WIDTH	= 0 			,
		parameter integer C_M_AXI_BUSER_WIDTH	= 0
	)
	(
		// Users to add ports here
 		input 	wire  [C_M_AXI_DATA_WIDTH-1 : 0]	wr_data 		,
 		input  	wire  	 							wr_start 		,
 		output 	wire  								wr_data_vaild 	,	
 		input 	wire  [C_M_AXI_ADDR_WIDTH-1 : 0] 	wr_addr 		,
 		output 	wire  								wr_done  		,
 		output 	reg  								wr_mux 			,

 		output 	wire  [C_M_AXI_DATA_WIDTH-1 : 0]	rd_data 		,
 		input  	wire  	 							rd_start 		,
 		output 	wire  								rd_data_vaild 	,	
 		input 	wire  [C_M_AXI_ADDR_WIDTH-1 : 0] 	rd_addr 		,
  		output 	wire  								rd_done  		,
 		output 	reg  								rd_mux 			,
		// User ports ends
		// Do not modify the ports beyond this line
		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 	[C_M_AXI_AWUSER_WIDTH-1 : 0] 	M_AXI_AWUSER 	,
		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 	[C_M_AXI_WUSER_WIDTH-1 : 0] 	M_AXI_WUSER 	,
		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 	[C_M_AXI_BUSER_WIDTH-1 : 0] 	M_AXI_BUSER 	,
		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 	[C_M_AXI_ARUSER_WIDTH-1 : 0] 	M_AXI_ARUSER 	,
		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 	[C_M_AXI_RUSER_WIDTH-1 : 0] 	M_AXI_RUSER 	,
		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 C_MASTER_LENGTH		= 12;
localparam integer C_NO_BURSTS_REQ  	= C_MASTER_LENGTH-clogb2((C_M_AXI_BURST_LEN*C_M_AXI_DATA_WIDTH/8)-1);

wire  	[C_TRANSACTIONS_NUM+2 : 0] 	burst_size_bytes;


wire  	start_single_burst_write;
wire   	start_single_burst_read;


assign burst_size_bytes	= C_M_AXI_BURST_LEN * C_M_AXI_DATA_WIDTH/8;
    
//Write Address Channel
reg 	[C_M_AXI_ADDR_WIDTH-1 : 0] 	axi_awaddr 		;
reg  								axi_awvalid 	;

assign 	M_AXI_AWID 		= 	'd0 									;
assign 	M_AXI_AWADDR 	= 	C_M_TARGET_SLAVE_BASE_ADDR + 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 	= 	'd0 									;
assign 	M_AXI_AWCACHE 	= 	4'b0010 								;
assign 	M_AXI_AWPROT 	= 	'd0 									;
assign 	M_AXI_AWQOS 	= 	'd0 									;
assign 	M_AXI_AWUSER 	= 	'd0 									;
assign  M_AXI_AWVALID   =   axi_awvalid  							;

always @(posedge M_AXI_ACLK)                                                                                                                                                                  
	if (M_AXI_ARESETN == 0)                                                                                                       
		axi_awvalid <= 1'b0;                                                                                                                        
	else if (~axi_awvalid && start_single_burst_write)                                                                             
	    axi_awvalid <= 1'b1;                                                                                                                                 
	else if (M_AXI_AWREADY && axi_awvalid)                                                                                         
	    axi_awvalid <= 1'b0;                                                                                                         
	else                                                               
	  	axi_awvalid <= axi_awvalid;                                                                                                     
	                                                                       
	                                                                           
always @(posedge M_AXI_ACLK)                                                                                                       
	if (M_AXI_ARESETN == 0)                                                                                                      
	    axi_awaddr <= 'b0;                                                                                                           
	else if (start_single_burst_write)                                                                                        
	    axi_awaddr <= wr_addr;                                                                               
	else                                                               
	  	axi_awaddr <= axi_awaddr;                                                                                                       


//Write Data Channel
reg  	 							axi_wlast 		;
reg  	 							axi_wvalid 		;
reg  	[C_TRANSACTIONS_NUM : 0] 	write_index 	;
wire 	[C_M_AXI_DATA_WIDTH-1 : 0] 	axi_wdata 		;
wire  	 							wnext 			;

assign 	M_AXI_WSTRB		= 	{(C_M_AXI_DATA_WIDTH/8){1'b1}} 			;
assign 	M_AXI_WUSER 	= 	'd0 									;
assign  wnext  			=  	M_AXI_WREADY & axi_wvalid 				;                                   
assign 	M_AXI_WDATA		= 	axi_wdata 								;
assign 	M_AXI_WLAST		= 	axi_wlast 								;
assign 	M_AXI_WVALID	= 	axi_wvalid 								;
assign	axi_wdata  		=  	wr_data;

always @(posedge M_AXI_ACLK)                                                                                                                                  
	if (M_AXI_ARESETN == 0 )                                                                                                                       
	    axi_wvalid <= 1'b0;                                                                                                                                                                
	else if (~axi_wvalid && start_single_burst_write)                                                                                                       
	    axi_wvalid <= 1'b1;                                                                                                                                                                   
	else if (wnext && axi_wlast)                                                    
	  	axi_wvalid <= 1'b0;                                                           
	else                                                                            
	  	axi_wvalid <= axi_wvalid;                                                                                                                                   
	                                                                                    
	                                                                                                         
always @(posedge M_AXI_ACLK)                                                                                                                                   
	if (M_AXI_ARESETN == 0)                                                                                                                                
	    axi_wlast <= 1'b0;                                                                                                                           
	else if (((write_index == C_M_AXI_BURST_LEN-2 && C_M_AXI_BURST_LEN >= 2) && wnext) || (C_M_AXI_BURST_LEN == 1 ))                                                                         
	    axi_wlast <= 1'b1;                                                                                                                                                                      
	else if (wnext)                                                                 
	  	axi_wlast <= 1'b0;                                                            
	else if (axi_wlast && C_M_AXI_BURST_LEN == 1)                                   
	  	axi_wlast <= 1'b0;                                                            
	else                                                                            
	  	axi_wlast <= axi_wlast;                                                                                                                                      
	                                                                                                                                                                                                                           
always @(posedge M_AXI_ACLK)                                                                                                                                 
	if (M_AXI_ARESETN == 0 || start_single_burst_write == 1'b1)                                                                            
		write_index <= 0;                                                                                                                                     
	else if (wnext && (write_index != C_M_AXI_BURST_LEN-1))                                                                                                 
		write_index <= write_index + 1;                                                                                                                   
	else                                                                            
		write_index <= write_index;                                                                                                                                 
	                                                                                            
                                                                           
                                                       
                                                                             
//Write Response (B) Channel 
reg  	 							axi_bready 		;
assign M_AXI_BREADY	= axi_bready;
always @(posedge M_AXI_ACLK)                                                                                                     
	if (M_AXI_ARESETN == 0)                                                                                                       
		axi_bready <= 1'b0;                                                                                                                                
	else if (M_AXI_BVALID && ~axi_bready)                                                                                         
		axi_bready <= 1'b1;                                                                                                                                           
	else if (axi_bready)                                                                                                            
		axi_bready <= 1'b0;                                                                                                                                                
	else                                                                
		axi_bready <= axi_bready;                                         
                                                                
//Read Address Channel
reg  	[C_M_AXI_ADDR_WIDTH-1 : 0] 	axi_araddr 		;
reg  	 							axi_arvalid 	;

assign M_AXI_ARID	 	= 'b0 										;
assign M_AXI_ARADDR	 	= C_M_TARGET_SLAVE_BASE_ADDR + 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_ARUSER	 	= 'b1 										;
assign M_AXI_ARVALID	= axi_arvalid 								;


always @(posedge M_AXI_ACLK)                                                                                                                                                          
	if (M_AXI_ARESETN == 0)                                                                                                  
	    axi_arvalid <= 1'b0;                                                                                                                  
	else if (~axi_arvalid && start_single_burst_read)                                                                          
	    axi_arvalid <= 1'b1;                                                                                                   
	else if (M_AXI_ARREADY && axi_arvalid)                                                                                   
	    axi_arvalid <= 1'b0;                                                                                                    
	else                                                             
	  	axi_arvalid <= axi_arvalid;                                                                                                                                                                        

always @(posedge M_AXI_ACLK)                                                                                           
	if (M_AXI_ARESETN == 0)                                                                                                  
		axi_araddr <= 'b0;                                                                                                     
	else if (start_single_burst_read)                                                                                   
		axi_araddr <= rd_addr;                                                                           
	else                                                             
		axi_araddr <= axi_araddr;                                      

//Read Data (and Response) Channel
reg  	 							axi_rready 					;
reg  	[C_TRANSACTIONS_NUM : 0] 	read_index 		 			;
wire  	rnext 													;

assign M_AXI_RREADY	= axi_rready 								; 
assign rnext  		= M_AXI_RVALID && axi_rready  				;                            
assign M_AXI_RUSER 	= 	'd0 									;
                                
always @(posedge M_AXI_ACLK)                                                                                                    
	if (M_AXI_ARESETN == 0 || start_single_burst_read)                                                                              
		read_index <= 0;                                                                                                             
	else if (rnext && (read_index != C_M_AXI_BURST_LEN-1))                                                                         
		read_index <= read_index + 1;                                                                                                
	else                                                                
		read_index <= read_index;                                                                                                                            
                                                                    
always @(posedge M_AXI_ACLK)                                                                                                          
	if (M_AXI_ARESETN == 0 )                                                                            
		axi_rready <= 1'b0;                                                                                                                                     
	else if (M_AXI_RVALID)                                                            
		if (M_AXI_RLAST && axi_rready)                                         
			axi_rready <= 1'b0;                                                    
		else                                                                    
		 axi_rready <= 1'b1;                                                                                                                                                                                                                 

// Add user logic here
reg 		 						wr_start_r 	;
reg 	[C_M_AXI_ADDR_WIDTH-1 : 0]	wr_addr_r 	;
reg  	[C_M_AXI_DATA_WIDTH-1 : 0]	wr_data_r 	;
reg  								axi_rready_r;

reg 		 						rd_start_r 	;
reg 	[C_M_AXI_ADDR_WIDTH-1 : 0]	rd_addr_r 	;

always @(posedge M_AXI_ACLK)begin
	if(M_AXI_ARESETN == 0)begin
		wr_start_r 	<= 	1'b0 		;
		rd_start_r 	<= 	1'b0 		;
		wr_addr_r 	<= 	0 			;
		rd_addr_r 	<= 	0 			;
		axi_rready_r<=  1'b0  		;  
	end 
	else begin
		wr_start_r 	<= 	wr_start 	;
		rd_start_r 	<= 	rd_start 	;
		wr_addr_r 	<= 	wr_addr 	;
		rd_addr_r 	<= 	rd_addr 	;
		axi_rready_r<=  axi_rready  ;
	end
end 

assign start_single_burst_write = {wr_start_r,wr_start} == 2'b01;
assign wr_data_vaild 			= wnext 	;
assign wr_done 					= axi_bready;

always @(posedge M_AXI_ACLK)
	if(M_AXI_ARESETN == 0)
		wr_mux 	<= 	1'b0 ;
	else if(wr_done)
		wr_mux 	<= 	1'b0 ;
	else if(wr_start)
		wr_mux 	<= 	1'b1 ;

assign start_single_burst_read  = {rd_start_r,rd_start} == 2'b01;
assign rd_data_vaild 			= rnext 	;
assign rd_data 					= M_AXI_RDATA;
assign rd_done  				= {axi_rready_r,axi_rready} == 2'b10;

always @(posedge M_AXI_ACLK)
	if(M_AXI_ARESETN == 0)
		rd_mux 	<= 	1'b0 ;
	else if(rd_done)
		rd_mux 	<= 	1'b0 ;
	else if(rd_start)
		rd_mux 	<= 	1'b1 ;
// User logic ends

	endmodule

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值