3. AXI总线协议详解:AXI4、AXI4-Lite、AXI4-Stream协议对比、握手信号与时序、在Zynq中的实际应用

AXI总线,说白了就是Zynq里PS和PL之间沟通的“高速公路”。我刚接触Zynq时,总觉得协议细节太多,后来踩了几个坑才明白——搞懂AXI,硬件加速就成功了一半。

本章咱们把三种AXI协议掰开揉碎,看看它们到底有什么区别,握手怎么握,以及在Zynq里怎么用。

3.1 三种AXI协议:各司其职

AXI家族有三个成员,每个都有自己的定位。我习惯这么记:AXI4是“大卡车”,拉得多跑得快;AXI4-Lite是“自行车”,轻便但载重小;AXI4-Stream是“传送带”,只管流数据不管地址。

特性 AXI4 AXI4-Lite AXI4-Stream
数据宽度 8~1024位,支持突发 固定32位,不支持突发 任意宽度,流式传输
地址通道 有,支持多地址 有,单地址 无地址
典型场景 DDR读写、大数据块传输 寄存器配置、状态读取 视频流、数据流处理
握手复杂度 高(5个独立通道) 中(5个通道但简化) 低(仅数据通道)

核心区别一句话:AXI4面向高性能内存映射传输,AXI4-Lite面向控制寄存器访问,AXI4-Stream面向连续数据流处理。

3.2 握手信号与时序:VALID/READY机制

三种AXI协议都使用相同的握手方式——VALID/READY。这个机制其实很简单:发送方说“我有数据”(VALID拉高),接收方说“我能接收”(READY拉高),两者同时有效时,数据就传过去了。

我曾经在调试一个视频加速器时,发现数据总是丢帧。查了两天才找到原因——发送端的VALID信号在READY没准备好时就撤回了。嗯,这里要注意:VALID一旦拉高,必须等到握手成功才能拉低,这是协议的铁律。

握手有三种典型时序:

  • READY先于VALID:接收方提前准备好,发送方随时可以发起传输
  • VALID先于READY:发送方准备好数据,等待接收方就绪
  • 同时有效:一拍完成传输,效率最高

我的设计习惯:在写AXI从机逻辑时,我会让READY默认拉高(除非内部FIFO满),这样只要VALID有效就能立即握手,减少等待周期。

3.3 AXI4:高性能内存映射传输

AXI4有5个独立通道:读地址、读数据、写地址、写数据、写响应。每个通道都有自己的VALID/READY握手。

突发传输是AXI4的精髓。你可以一次发起一个突发,指定起始地址和长度(1~256拍),然后连续传输数据。我做过一个图像处理加速器,用AXI4从DDR读取一帧图像,突发长度设为256,带宽利用率能达到90%以上。

// AXI4写事务示例(Verilog伪代码)
always @(posedge clk) begin
    if (awvalid & awready) begin
        // 写地址握手成功,记录起始地址和突发长度
        addr_q <= awaddr;
        burst_len_q <= awlen;  // 实际长度 = awlen + 1
    end
    
    if (wvalid & wready) begin
        // 写数据握手成功,数据写入内部FIFO
        fifo_wr_data <= wdata;
        wstrb_q <= wstrb;      // 字节使能,用于部分写入
        beat_cnt <= beat_cnt + 1;
    end
    
    if (beat_cnt == burst_len_q & wlast) begin
        // 最后一拍数据,发送写响应
        bvalid <= 1'b1;
        bresp <= 2'b00;        // OKAY响应
    end
end

避坑指南:我曾经在AXI4写响应通道上吃过亏——主机发出写数据后,从机必须在有限拍内返回写响应。如果从机处理不及时,主机可能挂死。所以,写响应逻辑一定要用状态机独立处理,别跟数据通路混在一起。

3.4 AXI4-Lite:轻量级控制通道

AXI4-Lite是AXI4的简化版。它不支持突发,每次只能读写一个32位数据。但正因为简单,它特别适合做寄存器配置。

在Zynq里,PS通过AXI4-Lite访问PL中的控制寄存器。我一般这样分配地址空间:

  • 基地址+0x00:控制寄存器(启动/停止加速器)
  • 基地址+0x04:状态寄存器(忙/完成/错误标志)
  • 基地址+0x08~0x1C:参数寄存器(图像尺寸、阈值等)

AXI4-Lite的时序比AXI4简单得多。写事务只需要地址握手、数据握手、响应握手三步。读事务则是地址握手后,从机在数据通道返回数据。

实用技巧:AXI4-Lite的地址通道和数据通道可以并行处理。我习惯让地址通道先握手,数据通道在下一拍再握手,这样时序更容易收敛。

3.5 AXI4-Stream:无地址的流式传输

AXI4-Stream是三种协议里最特殊的——它没有地址通道,只有数据通道。数据从上游流到下游,每个时钟周期可以传输一拍数据。

它的核心信号只有几个:

信号 宽度 说明
TVALID 1 发送方数据有效
TREADY 1 接收方可以接收
TDATA 8/16/32/64/128... 数据总线
TLAST 1 数据包结束标志
TKEEP TDATA/8 字节有效标志

我在做视频处理时,AXI4-Stream用得最多。摄像头采集的数据通过Stream流入,经过滤波、缩放等处理,再通过Stream流出。整个过程不需要地址,数据像流水一样自动推进。

设计经验:AXI4-Stream的TLAST信号很容易被忽略。我建议在数据包的第一拍就确定包长,并在最后一拍拉高TLAST。如果包长不确定,可以用TKEEP来标记有效字节。

3.6 在Zynq中的实际应用

Zynq里,三种AXI协议各司其职,配合使用:

  • PS→PL:通过AXI4-Lite配置加速器参数,通过AXI4传输大数据块
  • PL内部:模块之间用AXI4-Stream连接,形成流水线
  • PL→PS:处理结果通过AXI4写回DDR,状态通过AXI4-Lite上报

下面这张图展示了典型的硬件加速系统架构:

Zynq AXI总线应用架构 Zynq AXI总线应用架构 PS (处理系统) ARM Cortex-A9 DDR控制器 中断控制器 PL (可编程逻辑) 加速器核心 FIFO/BRAM DMA引擎 AXI4-Lite 配置寄存器 AXI4 DDR数据读写 模块A 模块B AXI4-Stream 中断信号 说明: • PS通过AXI4-Lite配置PL中的加速器寄存器(如启动/停止、参数设置) • PS通过AXI4将待处理数据从DDR传输到PL,或将结果写回DDR • PL内部模块之间通过AXI4-Stream连接,形成流水线处理 • 加速完成后,PL通过中断通知PS读取结果

实际项目案例:我做过一个实时边缘检测加速器。PS通过AXI4-Lite配置阈值参数,通过AXI4将图像帧从DDR搬入PL。PL内部用AXI4-Stream连接Sobel算子模块和阈值模块。处理完一帧后,PL通过AXI4将结果写回DDR,并触发中断通知PS。整个流水线延迟只有几微秒。

3.7 协议选择指南

总结一下,在Zynq项目里怎么选:

  • 控制通路:用AXI4-Lite,简单可靠,时序容易收敛
  • 数据通路(大块传输):用AXI4,突发传输效率高
  • 数据通路(流式处理):用AXI4-Stream,无地址开销,适合流水线

最后提醒:AXI4-Stream虽然简单,但要注意TLAST和TKEEP的正确使用。我见过有人把TLAST漏掉,结果下游模块永远不知道数据包什么时候结束,整个系统卡死。嗯,这种bug最难查,因为波形上看不出明显错误。