4. AXI4接口协议:AXI4-Full与AXI4-Stream的区别、握手信号、突发传输

大家好,我是你们的FPGA实战讲师。今天我们来聊聊AXI4协议,这是DDR读写和卷积加速里绕不开的核心。说实话,很多新手一看到AXI的波形图就头大,各种通道、握手、突发,感觉像天书。别急,我用实战经验帮你拆开揉碎了讲。

4.1 AXI4-Full vs AXI4-Stream:到底差在哪?

先问个问题:为什么要有两种AXI4?

我个人习惯把AXI4-Full想象成「带地址的总线快递」。你想从DDR里读数据,得先告诉它地址:我要读地址0x1000开始的256字节。然后DDR控制器找到数据,再打包送回来。整个过程有地址通道、读数据通道、写数据通道,各走各的,互不干扰。

而AXI4-Stream呢?说白了就是「流水线传送带」。没有地址,没有握手之外的任何控制。数据从上游流到下游,一拍一拍往前推。我在做图像处理加速时,像素数据就是典型的Stream流——一个时钟进来一个像素,处理完再流出去,根本不需要地址。

对比项 AXI4-Full AXI4-Stream
地址通道 有(读地址/写地址) 无
数据通道 读数据/写数据分开 单一数据流
握手信号 VALID/READY + 其他控制 VALID/READY + TLAST/TKEEP等
典型应用 DDR读写、寄存器配置 视频流、DMA数据搬运

嗯,这里要注意:AXI4-Stream其实可以看作是AXI4-Full的简化版。如果你只需要搬数据,不需要随机访问,那就用Stream。我在卷积加速项目里,输入特征图走Stream,权重走Stream,但DDR的读写必须走Full——因为你要告诉DDR「从哪个地址开始读」。

4.2 握手信号:VALID和READY的默契配合

AXI的握手,核心就两个信号:VALID和READY。但很多人在这个地方翻过车。

简单说:发送方拉高VALID,表示「我这拍数据有效」;接收方拉高READY,表示「我这拍能收数据」。数据在VALID和READY同时为高的时钟上升沿传输。

我曾经在一个项目里,因为没处理好READY的时序,导致数据丢了一拍。排查了整整两天,最后发现是READY信号在组合逻辑里产生了毛刺。从那以后,我养成了一个习惯:所有READY信号必须用寄存器打一拍,哪怕多一个时钟延迟,也比丢数据强。

握手传输的三种情况:

  • 情况A:VALID先高,READY后高——发送方准备好,等接收方。最常见。
  • 情况B:READY先高,VALID后高——接收方准备好,等数据来。比如FIFO非满时。
  • 情况C:同时拉高——一拍传输,效率最高。理想情况。

你想想看,如果发送方一直拉高VALID,接收方偶尔拉高READY,那数据就是「断断续续地流」。这在Stream里很常见——上游像素源源不断,但下游卷积计算单元偶尔忙不过来,就拉低READY让上游等一等。

4.3 突发传输:为什么DDR读写离不开它?

突发传输(Burst)是AXI4-Full的精髓。没有突发,DDR的带宽利用率会惨不忍睹。

为什么?因为DDR每次访问都有「行激活」和「列选通」的开销。如果你一次只读一个32位数据,那大部分时间都浪费在地址切换上了。突发传输允许你一次发起地址,连续传输多个数据,就像你告诉快递员「把整条街的包裹都取了」,而不是「取一个,回来,再取下一个」。

AXI4-Full的突发有三个关键参数:

  • ARLEN/AWLEN:突发长度,表示一次传输多少个数据。比如ARLEN=7表示传8个数据(长度+1)。
  • ARSIZE/AWSIZE:每个数据多少字节。2'b010表示4字节,2'b011表示8字节。
  • ARBURST/AWBURST:突发类型。固定地址(FIXED)、递增地址(INCR)、回绕地址(WRAP)。

我在DDR读写控制器里,最常用的是INCR模式。比如从地址0x1000开始,突发长度16,每次4字节,那地址就是0x1000、0x1004、0x1008……直到0x103C。DDR控制器会自动递增地址,你只需要在第一个时钟给出起始地址和突发参数,后面就等着收数据就行了。

实战小技巧:突发长度不要设得太大。虽然理论上可以设到256,但DDR控制器内部有FIFO深度限制。我一般设16或32,既能充分利用带宽,又不会让控制器溢出。具体值要看你的DDR IP核手册。

4.4 核心逻辑:一张图看懂AXI4-Full读写流程

下面这张图是我自己画的,把AXI4-Full的读操作流程画清楚了。写操作类似,只是多了写响应通道。

主设备 (Master) 从设备 (Slave) 读地址通道(AR) ARVALID, ARREADY, ARADDR, ARLEN... 读数据通道(R) RVALID, RREADY, RDATA, RLAST, RRESP 读操作时序流程 1. 主设备发送地址(ARVALID=1, ARADDR=目标地址) 2. 从设备接收地址(ARREADY=1),开始内部读取 3. 从设备返回数据(RVALID=1, RDATA=数据, RLAST=1表示最后一拍) 4. 主设备接收数据(RREADY=1),完成一次突发传输

这张图里,读地址通道和读数据通道是分开的。主设备先发地址,从设备收到后开始准备数据,然后通过读数据通道返回。注意RLAST信号——它在最后一拍数据时拉高,告诉主设备「这次突发结束了」。

避坑指南:我曾经在写AXI4-Full从机时,忘了处理RLAST信号。结果主设备一直等下一拍数据,系统死锁。记住:突发传输必须有RLAST(读)或WLAST(写)来标记结束,否则对方不知道什么时候该停。

4.5 Stream的握手:更简单,但别大意

AXI4-Stream的握手和Full一样,也是VALID/READY。但Stream多了一个TLAST信号——它标记帧的结束。比如一帧图像有1920个像素,那第1920个像素传输时,TLAST必须拉高。

我在做卷积加速时,输入特征图是Stream流,但卷积核是3x3的滑动窗口。这时候TLAST就很重要——它告诉卷积控制器「这一行结束了,下一行要开始了」。如果没有TLAST,控制器就不知道什么时候该换行,卷积结果会完全错乱。

Stream还有一个TKEEP信号,用来标记哪些字节是有效的。比如你传的数据宽度是64位,但最后一拍只有32位有效,那就用TKEEP来指示。不过说实话,大部分场景下TKEEP可以固定为全1,除非你做数据打包解包。

4.6 实战经验总结

最后,我把自己踩过的坑和心得列出来,希望对你有帮助:

  • 握手信号必须寄存:组合逻辑的READY容易出毛刺,用寄存器打一拍,稳如老狗。
  • 突发长度别贪大:16或32是黄金值,既能利用带宽,又不会撑爆FIFO。
  • RLAST/WLAST不能忘:没有结束标记,总线会一直等,系统死锁。
  • Stream的TLAST一定要对齐:帧结束标记错位,数据流就全乱了。
  • 仿真时多检查握手时序:用$display打印VALID和READY的波形,一眼就能看出问题。

嗯,AXI4协议就讲到这里。记住一句话:Full负责「去哪拿」,Stream负责「流过去」。搞懂了这两个的区别和握手细节,DDR读写和卷积加速的接口设计就成功了一半。