一、AXI4-Stream协议:从零开始理解
大家好,我是你们的FPGA讲师。今天我们来聊聊AXI4-Stream协议。
说实话,我刚接触这个协议时,觉得它比AXI-Full简单太多了。没有地址线,没有握手协议那么复杂,说白了就是一条数据管道。但越用越发现,里面的门道还真不少。
我个人习惯把AXI4-Stream比作「流水线传送带」。数据就像一个个包裹,在传送带上依次通过。你只需要控制好什么时候放包裹、什么时候拿走包裹就行。
1.1 接口信号定义
先看最基本的信号。AXI4-Stream接口的信号其实不多,我列个表给大家看:
| 信号名 | 方向 | 宽度 | 描述 |
|---|---|---|---|
| ACLK | 输入 | 1 | 时钟信号,所有操作同步于此 |
| ARESETn | 输入 | 1 | 异步复位,低电平有效 |
| TVALID | 输出 | 1 | 发送端有效信号 |
| TREADY | 输入 | 1 | 接收端准备好信号 |
| TDATA | 输出 | 8/16/32/64/... | 数据总线 |
| TLAST | 输出 | 1 | 数据包结束标志 |
| TKEEP | 输出 | TDATA/8 | 字节有效标志 |
| TSTRB | 输出 | TDATA/8 | 字节位置标志(可选) |
| TID | 输出 | 自定义 | 数据流标识(可选) |
| TDEST | 输出 | 自定义 | 目的地标识(可选) |
| TUSER | 输出 | 自定义 | 用户自定义信号(可选) |
嗯,这里要注意:TVALID和TREADY是核心握手信号。没有它们,数据传输就无从谈起。
1.2 数据传输机制
数据传输的规则其实很简单。我总结成一句话:TVALID和TREADY同时为高时,数据才被传输。
为什么会这样?你想想看,发送端说「我有数据」(TVALID=1),接收端说「我准备好了」(TREADY=1),这时候一拍即合,数据就传过去了。
有三种握手情况:
- 情况一:发送端先准备好(TVALID先高,TREADY后高)—— 数据在TREADY拉高时传输
- 情况二:接收端先准备好(TREADY先高,TVALID后高)—— 数据在TVALID拉高时传输
- 情况三:同时准备好(两者同时拉高)—— 数据立即传输
我在项目中遇到过一种情况:接收端处理速度跟不上发送端。这时候TREADY会周期性拉低,形成背压。说白了就是「你慢点发,我消化不了」。
核心要点:AXI4-Stream的传输是基于握手的流控制。发送端不能假设接收端永远准备好,必须等TREADY为高才能发送。
1.3 TLAST的作用
TLAST这个信号,我刚开始觉得它可有可无。直到做视频流处理时才发现,没有它简直寸步难行。
TLAST的作用:标记一个数据包的结束。
举个例子:你要传输一帧1280x720的图像。每个像素是24位RGB数据。如果数据总线是32位,那么一帧图像需要传输1280x720=921600个像素。但接收端怎么知道什么时候一帧结束?
答案就是TLAST。当最后一个像素传输时,TLAST拉高,告诉接收端:「这帧结束了,准备处理吧」。
我的经验:在视频处理项目中,TLAST通常与帧同步信号绑定。我曾经因为TLAST时序没处理好,导致接收端把两帧数据混在一起,画面出现撕裂。后来加了一个状态机专门处理TLAST,问题就解决了。
1.4 TKEEP的作用
TKEEP这个信号,很多人容易忽略。但它其实非常实用。
TKEEP的作用:指示哪些字节是有效的。
假设数据总线是32位(4字节)。你传输的数据可能不是4字节对齐的。比如你只传3个有效字节,最后一个字节是无效的。这时候TKEEP就派上用场了。
TKEEP的每一位对应一个字节:
- TKEEP[0] = 1 表示字节0有效
- TKEEP[1] = 1 表示字节1有效
- TKEEP[2] = 1 表示字节2有效
- TKEEP[3] = 1 表示字节3有效
如果TKEEP=4'b0111,表示字节0、1、2有效,字节3无效。
注意:TKEEP和TSTRB容易混淆。TKEEP表示字节是否有效,TSTRB表示字节位置是否正确。在大多数应用中,TKEEP就够用了。TSTRB一般用于特殊协议,比如PCIe。
1.5 知识体系结构图
下面我用一张SVG图来总结AXI4-Stream的核心知识体系:
1.6 实战小贴士
最后,分享几个我在项目中积累的经验:
- TVALID不能依赖TREADY:发送端应该独立产生TVALID,不能等TREADY来了才拉高。否则会造成死锁。
- TLAST必须与最后一个数据对齐:TLAST必须在最后一个数据传输的那个时钟周期拉高,不能早也不能晚。
- TKEEP在数据包中间不能变化:除非是特殊协议,否则TKEEP在一个数据包内应该保持不变。
- 复位时TVALID必须拉低:这是新手容易犯的错误。复位期间,发送端必须把TVALID置为0。
避坑指南:我曾经在一个项目中,因为TKEEP处理不当,导致接收端把无效字节当成有效数据,结果整个数据流都乱了。后来加了一个状态机,在数据包开始和结束时检查TKEEP,问题才解决。
好了,AXI4-Stream协议的基础知识就讲到这里。记住一句话:TVALID和TREADY是核心,TLAST标记边界,TKEEP控制字节有效性。掌握了这三个要点,你就掌握了AXI4-Stream的精髓。