[X]关闭

2-3-06 AXI4总线axi-stream总线协议

文档创建者:uisrc
浏览次数:590
最后更新:2023-12-30
文档课程分类
AMD: FPGA部分(2024样板资料) » 2_FPGA实验篇(仅旗舰) » 3-FPGA AXI 总线入门
软件版本:vitis2021.1(vivado2021.1)
操作系统:WIN10 64bit
硬件平台:适用XILINX A7/K7/Z7/ZU/KU系列FPGA
登录"米联客"FPGA社区-www.uisrc.com视频课程、答疑解惑!
1概述
AXI4-Stream去掉了地址,允许无限制的数据突发传输规模,AXI4-Stream接口在数据流传输中应用非常方便,本来首先介绍了AXI4-Stream协议的型号定义,并且给出了一些Stream接口的时序方案图。之后通过VIVADO自带的AXI4模板,创建axi-stream-master和axi-stream-slave ip。通过图形设计连线,添加仿真激励完成验证。
本文实验目的:
1:掌握基于VIVADO工具产生AXI协议模板
2:掌握通过VIVADO工具产生AXI-Stream代码
3:掌握通过VIVADO封装AXI-Stream图形化IP
4:通过仿真验证AXI-Stream IP的工作是否正常。
2 AXI4-Stream协议介绍2.1信号定义
信号
描述
ACLK
时钟源
信号在ACLK信号上升沿采样
ARESETn
复位源
复位信号,ARESETn低电平有效
TVALID
master
TVALID代表主设备数据有效,当TVALID和TREADY同时有效完成数据收发
TREADY
slave
TREADY表示从设备准备可以,主设备可以发送数据,当TVALID和TREADY同时有效完成数据收发
TDATA[(8n-1):0]
master
TDATA axi-stream的数据
TSTRB[(n-1):0]
master
TSTRB[n-1:0]对应的bit位为1代表对应的字节有效,否则无效,但是会占用这个数据位。
TKEEP[(n-1):0]
master
KEEP[n-1:0]对应的bit位为1代表对应的字节有效,否则为空,可以丢掉。
TLAST
master
TLAST代表最后一个数据。
TID[(i-1):0]
master
TID是数据流的标识符,用来表明不同的数据流。
TDEST[(d-1):0]
master
TDEST为据流提供路由信息。
TUSER[(n-1):0]
master
TUSER一般用于数据的同步,代表stream数据的开始。


以上所有信号,在axi-stream传输中,不一定全部用到,具体根据应用场景的情况而定。
2.2 axi-stream方案展示
下图中除了ACLK外,axi-stream的信号用到了,TVALID、TREADY、TLAST、TDATA。其中TDATA虽然是12bit但是实际上会占用16bit的物理总线。并且数据是循环发送,用TLAST标识了一次循环的最后一个数据。
2504661-20231230152501004-2143594714.jpg
下图中截图来自AXI-DMA mm2s接口的时序图,除了ACLK外,axi-stream的信号用到了,TVALID、TREADY、TLAST、TDATA、TKEEP。用TLAST标识了一次循环的最后一个数据。
2504661-20231230152501431-1738763280.jpg
下图中是来自于xilinx vivado自带的axis_vid_out ip的视频输出时序。EOL就是tlast ,SOF就是tuser初次外还包括了VALID、READY、DATA信号。
2504661-20231230152501819-219356491.jpg
3创建axi-stream-slave总线接口IP
新建fpga工程,过程省略
2504661-20231230152502224-1270857629.jpg
2504661-20231230152502670-1274804539.jpg
2504661-20231230152503170-1276942192.jpg
2504661-20231230152503672-894334711.jpg
2504661-20231230152504129-1508594926.jpg
2504661-20231230152504532-1929016650.jpg
4创建axi-stream-master总线接口IP
未来完成axi-steam协议的验证,采用以上方法,我们再创建一个saxis的IP
2504661-20231230152504922-1073394306.jpg
2504661-20231230152510282-683152971.jpg
2504661-20231230152515719-344475245.jpg
创建完成后如下图所示
2504661-20231230152516122-120831070.jpg
5创建FPGA图像化设计
2504661-20231230152516542-438309576.jpg
设置IP路径
2504661-20231230152516984-1593403865.jpg

2504661-20231230152517380-256687614.jpg
添加已经创建好的IP
2504661-20231230152517701-1550639147.jpg
输入关键词axis,在最后可以看到,双击添加Ip
2504661-20231230152518033-377937466.jpg
2504661-20231230152518391-96150295.jpg
完成连线
2504661-20231230152518746-1417631744.jpg
maxis的ip参数设置
2504661-20231230152519107-28294720.jpg
saxis的ip参数设置
2504661-20231230152519509-1774837238.jpg
自动创建顶层文件
2504661-20231230152519877-303165816.jpg
2504661-20231230152520208-814240177.jpg
6创建仿真文件
2504661-20231230152520632-321678643.jpg

2504661-20231230152526075-103349872.jpg
2504661-20231230152526547-1813604387.jpg
仿真程序非常简单,只要提供时钟和复位信号
`timescale 1ns / 1ns
module axis_top_sim();
reg m00_axis_aclk_0;
reg m00_axis_aresetn_0;   
system_wrappertem system_wrapper_inst
    (
    .m00_axis_aclk_0(m00_axis_aclk_0),  
    .m00_axis_aresetn_0(m00_axis_aresetn_0)
    );   
initial begin
    m00_axis_aclk_0  = 1'b0;
    m00_axis_aresetn_0 = 1'b0;
    #100;
    m00_axis_aresetn_0 = 1'b1;
end
always
    begin
        #5 m00_axis_aclk_0 = ~m00_axis_aclk_0;
    end      
endmodule


7程序分析
默认的maxis模板的代码有bug,我们对其进行修改。
1:把以下代码替换默认的代码并且保存
`timescale 1 ns / 1 ps
    module maxis_v1_0_M00_AXIS #
    (
        // Width of S_AXIS address bus. The slave accepts the read and write addresses of width C_M_AXIS_TDATA_WIDTH.
        parameter integer C_M_AXIS_TDATA_WIDTH  = 32,
        // Start count is the number of clock cycles the master will wait before initiating/issuing any transaction.
        parameter integer C_M_START_COUNT   = 32
    )
    (
        // Global ports
        input wire  M_AXIS_ACLK,
        //
        input wire  M_AXIS_ARESETN,
        // Master Stream Ports. TVALID indicates that the master is driving a valid transfer, A transfer takes place when both TVALID and TREADY are asserted.
        output wire  M_AXIS_TVALID,
        // TDATA is the primary payload that is used to provide the data that is passing across the interface from the master.
        output wire [C_M_AXIS_TDATA_WIDTH-1 : 0] M_AXIS_TDATA,
        // TSTRB is the byte qualifier that indicates whether the content of the associated byte of TDATA is processed as a data byte or a position byte.
        output wire [(C_M_AXIS_TDATA_WIDTH/8)-1 : 0] M_AXIS_TSTRB,
        // TLAST indicates the boundary of a packet.
        output wire  M_AXIS_TLAST,
        // TREADY indicates that the slave can accept a transfer in the current cycle.
        input wire  M_AXIS_TREADY
    );
    // Total number of output data                                                
    localparam NUMBER_OF_OUTPUT_WORDS = 8;                                             

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

    // WAIT_COUNT_BITS is the width of the wait counter.                                
    localparam integer WAIT_COUNT_BITS = clogb2(C_M_START_COUNT-1);                     

    // bit_num gives the minimum number of bits needed to address 'depth' size of FIFO.  
    localparam bit_num  = clogb2(NUMBER_OF_OUTPUT_WORDS);                                

    // Define the states of state machine                                                
    // The control state machine oversees the writing of input streaming data to the FIFO,
    // and outputs the streaming data from the FIFO                                      
    parameter [1:0] IDLE = 2'b00,        // This is the initial/idle state              

                    INIT_COUNTER  = 2'b01, // This state initializes the counter, once  
                                    // the counter reaches C_M_START_COUNT count,        
                                    // the state machine changes state to SEND_STREAM   
                    SEND_STREAM   = 2'b10; // In this state the                          
                                         // stream data is output through M_AXIS_TDATA  
    // State variable                                                                    
    reg [1:0] mst_exec_state;                                                            
    // Example design FIFO read pointer                                                  
    reg [bit_num-1:0] read_pointer;                                                      

    // AXI Stream internal signals
    //wait counter. The master waits for the user defined number of clock cycles before initiating a transfer.
    reg [WAIT_COUNT_BITS-1 : 0]     count;
    //streaming data valid
    wire    axis_tvalid;
    //Last of the streaming data
    wire    axis_tlast;
    wire    tx_en;
    //The master has issued all the streaming data stored in FIFO
    wire    tx_done;

    // I/O Connections assignments
    assign M_AXIS_TVALID    = axis_tvalid;
    assign M_AXIS_TDATA = read_pointer;
    assign M_AXIS_TLAST = axis_tlast;
    assign M_AXIS_TSTRB = {(C_M_AXIS_TDATA_WIDTH/8){1'b1}};

    // Control state machine implementation                           
    always @(posedge M_AXIS_ACLK)                                            
    begin                                                                    
      if (!M_AXIS_ARESETN)                                                   
      // Synchronous reset (active low)                                      
        begin                                                               
          mst_exec_state <= IDLE;                                            
          count    <= 0;                                                      
        end                                                                  
      else                                                                    
        case (mst_exec_state)                                                
          IDLE:                                                                                                            
            mst_exec_state  <=                                                                                                                                 
          INIT_COUNTER:                                                      
            // The slave starts accepting tdata when                          
            // there tvalid is asserted to mark the                          
            // presence of valid streaming data                              
            if ( count == C_M_START_COUNT - 1 )                              
              begin                                                         
                mst_exec_state  <= SEND_STREAM;                              
              end                                                            
            else                                                              
              begin                                                         
                count <= count + 1;                                          
                mst_exec_state  <= INIT_COUNTER;                              
              end                                                            

          SEND_STREAM:                                                        
            // The example design streaming master functionality starts      
            // when the master drives output tdata from the FIFO and the slave
            // has finished storing the S_AXIS_TDATA                          
            if (tx_done)                                                      
              begin                                                         
                mst_exec_state <= IDLE;                                      
              end                                                            
            else                                                              
              begin                                                         
                mst_exec_state <= SEND_STREAM;                                
              end                                                            
        endcase                                                              
    end                                                                     

    //tvalid generation
    //axis_tvalid is asserted when the control state machine's state is SEND_STREAM and
    //number of output streaming data is less than the NUMBER_OF_OUTPUT_WORDS.                        
    assign axis_tvalid = ((mst_exec_state == SEND_STREAM) && (read_pointer < NUMBER_OF_OUTPUT_WORDS));

    // AXI tlast generation                                                                                                                              

    assign axis_tlast = (read_pointer == NUMBER_OF_OUTPUT_WORDS - 1'b1)&& tx_en;  

    assign tx_done = axis_tlast;

    //FIFO read enable generation

    assign tx_en = M_AXIS_TREADY && axis_tvalid;  

        // Streaming output data is read from FIFO      
        always @( posedge M_AXIS_ACLK )                  
        begin                                            
          if(!M_AXIS_ARESETN)                           
            begin                                       
              read_pointer <= 0;                     
            end                                          
          else if (tx_en)
            begin                                       
              read_pointer <= read_pointer + 32'b1;  
            end                                          
        end  

    endmodule


2:在Tcl Console中输入reset_project对工程IP复位
2504661-20231230152526954-1673679323.jpg
3:之后单击Refresh IP Catalog
2504661-20231230152527294-384380396.jpg
最后单击upgrade Selected完成更新
2504661-20231230152527674-1950002596.jpg
在看saxis的源码,这部分代码非常简单
首先是状态机,当S_AXI_TVALID有效,saxis的状态机进入WRITE_FIFO
2504661-20231230152528117-1054258760.jpg
只要接收的数据小于(write_pointer <= NUMBER_OF_INPUT_WORDS-1)并且saxis状态机是WRITE_FIFO状态机,表示saxis可以接收数据,设置axis_tready==1如下:assign axis_tready = ((mst_exec_state == WRITE_FIFO) && (write_pointer <= NUMBER_OF_INPUT_WORDS-1));
write_pointer 用于写入了多少个数据。
2504661-20231230152533617-1685047757.jpg
写数据到fifo中
2504661-20231230152534122-1418655371.jpg
8实验结果
仿真结果
2504661-20231230152534568-1399777781.jpg

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则