AXI-Stream协议详解与仿真实践
1 摘要
AXI-Stream总线是一种高效、简单的数据传输协议,主要用于高吞吐量的数据流传输场景。相比于传统的AXI总线,AXI-Stream总线更加简单和轻量级,它通过无需地址的方式,将数据从一个模块传输到另一个模块,适用于需要高速数据传输的应用场景。是AXI协议中最简单的一种。本文主要介绍在FPGA中使用AXI-Stream协议进行数据流传输过程及FPGA仿真实践试验。
2 AXI-Stream适用场景
AXIS与AXI-FULL的主要区别:
•取消了Address Write/Address Read通道;
•取消了反馈响应信号Bresp和Rresp;
•半双工,仅能读或者写;
•不允许乱序;
•无最大突发传输长度;
•包含TID信号指示源,TDEST指示目的地;
•包括一个用于插入和溢出空字节的TKEEP信号;
适合使用AXIS协议设计高速数据传输处理的场合:
(1)视频摄像头数据流传输
(2)高速AD数据采集传输
(3)AXI-DMA数据传输
3 信号定义
3.1 接口信号及握手
信号 | 源 | 信号描述 |
ACLK | 时钟源 | 全局时钟,所有信号在时钟源上升沿采样 |
ARESTN | 复位源 | 全局复位,低电平有效 |
TVALID | 主 | 表示主设备数据有效,当TVALID和TREADY同时有效时完成数据传输 |
TREADY | 从 | 表示从设备准备可以,主设备可以发送数据,当TVALID和TREADY同时有效完成数据收发 |
TDATA[(8n-1):0] | 主 | AXI-Stream数据 |
TSTRB[(n-1):0] | 主 | TSTRB[n-1:0]对应的bit位为1代表对应的字节有效,否则无效,但是会占用这个数据位。 |
TKEEP[(n-1):0] | 主 | KEEP[n-1:0]对应的bit位为1代表对应的字节有效,否则为空,可以丢掉。 |
TLAST | 主 | 表示最后一个数据。 |
TID[(i-1):0] | 主 | 数据流的标识符,用来表明不同的数据流。 |
TDEST[(d-1):0] | 主 | 据流提供路由信息。 |
TUSER[(n-1):0] | 主 | 用于数据的同步,代表stream数据的开始。 |
使用 axi-stream协议,我们最关注的信号主要是:TVALID、TREADY、TLAST、TDATA。其中TDATA是数据物理总线。TVALID、TREADY表示了传输开始,TLAST标识了一次循环的最后一个数据,传输结束标志。
时序如下
3.2 Stream数据流
部分术语
(1)Transfer:基于TVALID和TREADY握手协议的传输,一次握手成功就是一次Transfer,代表一次最小粒度的数据传输发生;
(2)Packet:一组通过axi-stream传输的数据,所谓的Packet可能包含一个Transfer也有可能是多个Transfers。
(3)Frame:最大的Byte组合,包含整数个Packe。
(4) Data Stream:可以包含独立的字节传输,或者在Packet中组合在一起的一系列字节传输。
AXI-Stream数据流相关的信号。
• TDATA:为一次transfer传输的数据,一般强制要求为8的整数倍,以和其他信号相对应。
• TSTRB:其每一个bit和DATA的每一个字节相对应,用来表示DATA的数据是否有效。
• TSTRB:标识符,指示TDATA中的每个字节,是数据字节还是位置字节。
• TKEEP:标识符,指示TDATA中的每个字节,是否需要作为数据流的一部分被处理。
字节流
字节流是数据字节和空字节的传输,字节流传输可以传输任意数量的数据字节,这取决于数据宽度。
• Data byte:代表这个字节的数据是需要传输且有效的;
• Position byte:代表这个字节的数据是需要传输的,实际上是无效的,只不过需要用来占位置,大家就理解成补0那种操作即可;
• Null byte:完全没用,可以丢弃;
传输过程中需要通过TKEEP和TSTRB是要组合在一起使用,告知下游如何处理DATA数据,数据中各种其共有三种含义:
这里简单讨论占位字节的具体应用场景:
• 数据标识:比如在视频处理当中,可以使用Position Byte当做一帧的开头;
•错误检测:每过多少比特插入一个Position Byte用于检测错误。如果不符合规律说明丢数之类的问题;
• 数据分组:如一次传4个Byte的数据,但是有一组或者两组数据是无效的,这样就可以用Position Byte。让数据的Group是规律的,同时Slave也可以感知到某个数据是无效的。
4 仿真实践
4.1 AXI-STREAM MASTER
仿真设计Master主动发送固定32大小的数据,同时Slave接收数据形成回环测试,通过s_axis_tdata与m_axis_tdata数据进行对比,验证AXI-STREAM时序及数据发送接收是否正确。
AXI_stream_M00_AXIS 核心代码
`timescale 1 ns / 1 psmodule AXI_stream_v1_M00_AXIS #(// Users to add parameters here// User parameters ends// Do not modify the parameters beyond this line// 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)(// Users to add ports here// User ports ends// Do not modify the ports beyond this line// Global portsinput 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 = 32; // 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)