AXI4的主机协议代码分析

Posted on 2020-09-04 10:36  绿叶落秋风  阅读(1480)  评论(0编辑  收藏  举报

AXI4的主机协议代码分析

一、模块分析

(1)端口列表

 

        input wire  INIT_AXI_TXN,
        // Asserts when ERROR is detected
        output reg  ERROR,
        // Asserts when AXI transactions is complete
        output wire  TXN_DONE,
        // 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

识别方法:M_AXI作为前缀,表明是主机的AXI协议变量。AR开头的是读地址,AW开头的是写地址,R开头的是读数据,W开头的是写数据,B开头的是写响应。这是五个通道的基本判断(前面是后面的必要条件,但不是充分条件,即AR不一定是读地址,例如ARESETN是低电平复位信号,具体的看英文注释即可判断)。

(2)clogb2函数

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

这个函数的功能就是返回一个整型变量的位宽深度(也就是二进制的有效数据,排除前面的多余0所剩下的位宽)。

(3)内部信号声明

xilinx的IP中端口信号一定是大写的,内部使用信号则是小写,方便阅读时判断信号是否为端口列表中的信号。端口信号需要考虑和其他模块连接的问题,二内部信号则没有这么多的考虑。

(4)初始化信号init_txn_ff2

//Generate a pulse to initiate AXI transaction.
    always @(posedge M_AXI_ACLK)                                              
      begin                                                                        
        // Initiates AXI transaction delay    
        if (M_AXI_ARESETN == 0 )                                                   
          begin                                                                    
            init_txn_ff <= 1'b0;                                                   
            init_txn_ff2 <= 1'b0;                                                   
          end                                                                               
        else                                                                       
          begin  
            init_txn_ff <= INIT_AXI_TXN;
            init_txn_ff2 <= init_txn_ff;                                                                 
          end                                                                      
      end  

采用两级reg延时将INIT_AXI_TXN初始化信号接收过来。

(5)写地址通道的实现

 

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

使用开始写入信号触发写地址通道的握手信号。写通道初始信号也是由其控制的。

always @(posedge M_AXI_ACLK)                                                 
      begin                                                                        
        if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                   
          begin                                                                    
            write_index <= 0;                                                      
          end                                                                      
          // Signals a new write address/ write data is                            
          // available by user logic                                               
        else if (start_single_write)                                               
          begin                                                                    
            write_index <= write_index + 1;                                        
          end                                                                      
      end        

(6)写数据通道的实现

由于前面在从机的时候就详细地介绍了如何区分每个信号的作用。这里不再列举代码,对源码感兴趣的可以在vivado的工程中寻找。这里关注如何理解这些信号的变化,为理解时序图打下基础。

axi_wvalid受start_single_write控制拉高,由其他信号拉低。这个实际上需要对整个数据传输的流程有所认识,这里不做解释。

(7)写响应通道

axi_bready:等待握手信号,等待从机发送写完成后握手信号。

(8)读地址通道

read_index:读初始化信号

axi_arvalid:读地址通道的握手信号。

(9)读数据通道

axi_rready:读数据等待握手信号。

read_resp_error:读数据错误信号。

这里的基本功能和从机的lite形似,但是,作为主机,其还有重要的逻辑需要实现。在基本的通道构建完成后,还需要对其作为主机的协调和链接选择的功能实现。

二、系统功能

(1)写入地址

 axi_awaddr在M_AXI_AWREADY和axi_awvalid握手成功后即写入地址32'h0000_0004的地址位。

//Write Addresses                                        
      always @(posedge M_AXI_ACLK)                                  
          begin                                                     
            if (M_AXI_ARESETN == 0  || init_txn_pulse == 1'b1)                                
              begin                                                 
                axi_awaddr <= 0;                                    
              end                                                   
              // Signals a new write address/ write data is         
              // available by user logic                            
            else if (M_AXI_AWREADY && axi_awvalid)                  
              begin                                                 
                axi_awaddr <= axi_awaddr + 32'h00000004;            
                                                                    
              end                                                   
          end    

(2)写入数据

axi_wdata在写入数据握手成功后即可将初始化的数据write_index写入数据通道。具体实现和前面的写入地址是一致的。

(3)读地址

将axi_araddr通道加上想要读的地址即可实现。和前面的实现方式一样,都是等待握手成功后完成地址操作。由expected_rdata实现地址的接收。

(4)指令连接状态机

IDLE负责实现所有信号初始化。INIT_WRITE负责将初始化写信号。INIT_READ负责初始化读信号。INIT_COMPARE负责处理读写冲突信号。具有报错的作用。具体实现方法在代码中可以一一看到。

(5)终端写入统计

通过一个last_write信号表明写入数据的结束。可以切入时钟刻度得到数据写入的数量。

(6)最后写入校对

writes_done可以完成用于和last_write比较,校对写入的数据是否有正确的写响应信号。

(7)终端读取统计

last_read可以判断最后一位数据的读取完成。

(8)最后读取校对

reads_done可以在last_read基础上加上读握手判断,用于判断读数据是否成功。

(9)报错机制

read_mismatch用于数据的判断读信号是否匹配。error_reg用于判断存储的数据和传输的数据是否匹配。判断方法就是是否有错误的信号。

三、总结反思

相对于AXI4从机的协议,主机需要的内容显然更多,抽象的层次也不一样。从机可以直接得到通道的信号得到数据,而主机则需要更多的判断机制。需要使用线路判断逻辑和错误信号判断逻辑来支持数据的传输。这些额外的逻辑需要认真学习。事实上,其他的传输逻辑也是需要这些部分的辅助的。这个学会了,其他的也就触类旁通了。