第4章:AXI4-Stream接口详解

各位同学,今天我们来聊聊AXI4-Stream。说实话,这个接口在图像采集里太常用了。我刚开始接触Vitis时,被TVALID和TREADY的握手搞得晕头转向。后来做项目多了,才真正理解它的精髓。

4.1 AXI4-Stream协议基础

AXI4-Stream,说白了就是一条数据管道。它不像AXI4-Full那样有地址线,也不管数据从哪里来、到哪里去。它只关心一件事:把数据从A点搬到B点。

为什么图像采集要用它?你想想看,摄像头输出的像素数据是一串连续的流。每一帧图像就是一大包数据,不需要地址,只需要按顺序传。AXI4-Stream正好干这个。

核心特点:

  • 无地址总线——只管数据流动
  • 支持任意数据宽度——8位到1024位都行
  • 单方向传输——从主设备到从设备
  • 支持突发传输——适合图像这种大数据块

我在项目中遇到过一个问题:用AXI4-Stream传1080p图像时,数据量大概每秒3Gbps。如果不用流式接口,用AXI4-Full带地址的,每次传输都要发地址,效率低很多。AXI4-Stream没有地址开销,带宽利用率高。

4.2 TVALID/TREADY握手

这是AXI4-Stream最核心的机制。我刚开始学的时候,总觉得这两个信号很绕。其实很简单:

  • TVALID:发送方说「我准备好了,数据在线上」
  • TREADY:接收方说「我准备好了,可以收数据」
  • 两者同时为高时,数据才真正传输

握手有三种情况:

场景 TVALID TREADY 数据传输
正常传输 高 高 ✅ 传输
发送方等待 低 高 ❌ 等待
接收方忙 高 低 ❌ 等待

我的经验:设计时一定要处理TREADY拉低的情况。我曾经有个项目,接收方处理不过来时没拉低TREADY,结果数据丢了,图像出现花屏。查了两天才找到原因。

为什么会这样?因为接收方处理速度可能跟不上发送方。比如摄像头输出60fps,但DDR写带宽不够,这时候接收方必须拉低TREADY,让发送方等一等。

4.3 数据包格式

AXI4-Stream的数据包有几个关键信号:

  • TDATA:数据总线,宽度可配
  • TKEEP:字节使能,告诉接收方哪些字节有效
  • TLAST:包结束标志,一帧图像的最后一次传输
  • TUSER:用户自定义信号,我常用它传帧同步信息

图像采集时,数据包格式一般是这样的:

// 一帧图像的数据包结构
// TUSER 拉高表示帧开始
// TDATA 传输像素数据
// TLAST 拉高表示帧结束

// 举个例子:640x480灰度图像
// 每行640个像素,每个像素8位
// 一帧共480行

// 帧开始:TUSER = 1
// 第1行:640个TDATA传输,TLAST在行尾=0
// 第2行:640个TDATA传输,TLAST在行尾=0
// ...
// 第480行:640个TDATA传输,TLAST在行尾=1
// 帧结束:TUSER = 0

注意:TLAST必须在最后一拍数据有效时拉高。我见过有人提前一拍拉高TLAST,结果接收方少收了一个像素,整帧图像偏移了。

4.4 在Vitis中配置IP

Vitis里配置AXI4-Stream IP其实不复杂。我常用的几个IP:

  • AXI4-Stream Data FIFO:缓存数据,解决时钟域问题
  • AXI4-Stream Subset Converter:改变数据宽度
  • Video In to AXI4-Stream:把视频信号转成流
  • AXI4-Stream to Video Out:把流转成视频信号

配置步骤:

  1. 打开Vivado的IP Catalog
  2. 搜索"AXI4-Stream"找到需要的IP
  3. 双击添加,配置参数
  4. 连接时钟、复位、数据接口

我个人习惯在配置FIFO时,深度设大一点。比如处理1080p图像,FIFO深度至少设4096。为什么?因为DDR写操作可能有延迟,FIFO太小容易溢出。

避坑指南:我曾经在配置Video In to AXI4-Stream时,忘了勾选"Enable TLAST"。结果图像数据一直传,没有结束标志。接收方永远收不到帧结束信号,系统卡死。嗯,这个坑我踩过,你们别踩。

配置完成后,Vitis会自动生成驱动代码。你只需要调用API就能读写数据。比如:

// 初始化IP
XAxiStreamFifo_Initialize(&Fifo, XPAR_AXI_STREAM_FIFO_0_DEVICE_ID);

// 发送数据
XAxiStreamFifo_Write(&Fifo, DataBuffer, Length);

// 接收数据
XAxiStreamFifo_Read(&Fifo, RecvBuffer, Length);

是不是很简单?但要注意,这些API是阻塞的。如果FIFO空了,读操作会一直等。所以最好用中断或轮询方式。

4.5 本章小结

AXI4-Stream是图像采集的基石。TVALID/TREADY握手保证了数据可靠传输,TLAST标记了包边界,TUSER可以传自定义信息。在Vitis里配置IP时,注意FIFO深度和TLAST使能。

嗯,这一章就到这里。记住我说的那几个坑,做项目时能省不少时间。

可可精品资料库