← 返回博客
FPGAZynqAXI总线协议Vivado嵌入式系统PL设计

Zynq 实战 05|AXI 协议深度解析:握手时序、Burst 对齐与 PS-PL 总线全通

Zynq 实战 05|AXI 协议深度解析

这是《Zynq FPGA 嵌入式系统设计实战》系列的第 5 篇。 板子:Pynq-Z2(XC7Z020)。工具链:Vivado / Vitis 2023.2。 上一篇:Zynq 实战 04|PetaLinux 2023.2 构建全流程


0. 这一篇要解决什么问题

前几篇我们多次提到 AXI——GP 端口、HP 端口、AXI Interconnect——但都是在”需要时捎带一句”。这篇把它单独拆开,原因很实际:

  • 我在设计第一个 DMA 加速器时,burst 效率极差,折腾了两天才发现原因是在 PS 侧 HP 端口上用了 AXI4 的 256 拍 burst——而 HP 端口是 AXI3,根本不支持超过 16 拍
  • 另一个坑:突发事务起始地址 0x40000FF0,按 32-bit 做 16 拍,结果跨越了 4KB 边界,AXI 总线报错,Vivado ILA 抓到一堆 SLVERR

这些坑不是”理解了原理就不会踩”,而是原理里有几个容易被略掉的细节。这篇要把这些细节说清楚。

读完这篇,你应该能做到:

  1. 看懂 AXI 时序图,知道 VALID/READY 握手怎么建立
  2. 写 AXI4-Lite slave IP 时不会搞混通道顺序
  3. 知道 HP 端口 burst length 的真实上限
  4. 规划 burst 事务时能手算 4KB 边界

这篇不讲的:AXI Coherency Extensions(ACE)的内部机制、CHI 协议——那是多核 SoC 内部互联层,跟 Zynq-7000 的 PL 侧设计没有直接关系。


1. AMBA 协议家族:AXI 在哪一层

ARM 的 AMBA 协议是一个分层体系,按复杂度和适用场景分出多条总线:

协议发布时间定位典型用途
AHB (AMBA 2)1999片上系统总线Cortex-M 系列外设互联,仍在广泛使用
AXI3 (AMBA 3)2003高带宽内存映射总线Zynq-7000 PS 内部!HP/GP 端口协议
AXI4 (AMBA 4)2010AXI3 增强版,burst 更长Zynq PL 侧自定义 IP,Vivado IP catalog 默认
AXI4-Lite2010AXI4 简化版,无 burst控制寄存器接口的标准选择
AXI4-Stream2010无地址的单向数据流视频流、ADC 数据、DMA 数据通路
ACE (AMBA 4)2011AXI + Cache Coherency多核 ARM big.LITTLE,Cortex-A53/A72
CHI (AMBA 5)2014环形拓扑一致性互联服务器级 Neoverse,和 Zynq-7000 无关

Zynq-7000 的现实:PS 侧(ARM 核心周围)跑的是 AXI3,不是 AXI4。这不是 Xilinx 的设计缺陷,2011 年流片的 7 系列 Zynq 用的就是当时的主流协议。AXI4 和 AXI3 的最大区别只有两点:burst length 上限(256 vs 16)和 AxQOS/AxREGION 扩展信号。对 Zynq-7000 的开发者来说,最重要的影响就是burst length

🚧 避坑:Vivado IP catalog 里所有新创建的 AXI IP(AXI DMA、VDMA、自定义 IP)默认生成 AXI4 接口。当你把这些 IP 的 master 口连接到 PS 的 HP 或 GP 端口时,AXI Interconnect IP 或 SmartConnect IP 会自动在中间做 AXI4→AXI3 协议转换,包括把超过 16 拍的 burst 拆分。但这个转换有开销,而且如果你在 DMA 代码里配置了 256 拍 burst 指望最大化带宽,实际效果会让你困惑——因为底层已经被拆成多个 16 拍事务。


2. AXI4 的五大独立通道

AXI 和 AHB/APB 最大的区别不是带宽,而是通道独立性:读和写完全分离,写地址、写数据、写响应三相也互不阻塞。

AXI4 五大独立通道(写 3 通道 + 读 2 通道) Master (PS DMA / PL IP) Slave (DDR Ctrl / 自定义 IP) AW 写地址通道 AWADDR · AWLEN · AWSIZE · AWBURST · AWVALID · AWREADY W 写数据通道 WDATA · WSTRB · WLAST · WVALID · WREADY B 写响应通道 ← BRESP · BVALID · BREADY AR 读地址通道 ARADDR · ARLEN · ARSIZE · ARBURST · ARVALID · ARREADY R 读数据通道 ← RDATA · RRESP · RLAST · RVALID · RREADY
图 1. AXI4 五大独立通道,写用三条(AW/W/B),读用两条(AR/R)

为什么要”独立”?:因为写地址可以提前发出,数据可以延迟到来,响应可以更晚确认——三条通道各自用 VALID/READY 握手,互不阻塞。相比 AHB 的”地址+数据串行”,AXI 在高延迟内存(DDR)访问时能 pipeline 多个事务,这才是实质好处。

2.1 VALID / READY 握手机制

每条通道都用同一套握手协议:传输在 VALID=1READY=1 同时出现在时钟上升沿时完成。两者顺序无所谓——可以先 VALID 等 READY,也可以先 READY 等 VALID,或者同一个时钟周期一起拉高。

AXI4 写事务握手时序(AWLEN=2,3 拍 INCR burst) T0 T1 T2 T3 T4 T5 T6 T7 ACLK AWVALID AWREADY WVALID WREADY WDATA WLAST BVALID BREADY D0 D1 D2 AW 握手 W done B 握手 (slave 始终 ready) (master 始终 ready)
图 2. AXI4 写事务时序(AWLEN=2 即 3 拍)——AW/W/B 三通道异步握手,互不阻塞

几个从时序图里读出来的关键事实:

  1. AW 和 W 通道独立:这里的例子里 W 通道在 T2 才开始(等 AW 握手完),但协议上允许 W 数据提前放上通道等地址——具体看 slave 是否支持写交织(interleaved writes,AXI4 已删除)
  2. WLAST 是软件对 burst 长度的”确认”:它让 slave 知道哪一拍是最后一拍,不用 slave 自己计数 AWLEN
  3. BVALID 可以在 WLAST 之后任意时刻发:slave 处理完才回响应——写操作本质是”发出去不等完成”,响应是异步的
  4. BREADY 如果一直 HIGH(master 总是 ready 接收响应):则响应延迟就取决于 slave,不取决于 master

🚧 避坑:写 AXI4-Lite slave 时,B 通道响应必须等 W 通道握手完成后才能拉高 BVALID——有些学习代码里把 BVALID 和 WVALID 同时拉高,导致协议违例。正确顺序:W 握手(WVALID & WREADY 同时 HIGH)→ 处理 → 拉 BVALID。


3. 关键事实:Zynq-7000 PS 端是 AXI3,不是 AXI4

这是这篇文章最重要的一个澄清。

协议版本对照(来自 UG585 Chapter 9 AXI Interconnect):

端口位置协议最大 burst length数据宽度
M_AXI_GP0/1PS master,控制 PLAXI316 拍32-bit
S_AXI_GP0/1PS slave,PL 访问 PSAXI316 拍32-bit
S_AXI_HP0/1/2/3PS slave,PL 高速访问 DDRAXI316 拍64-bit
S_AXI_ACPPS slave,Cache 一致AXI316 拍64-bit
PL 自定义 IP(Vivado生成)PL 侧AXI4256 拍可变

两者之间是 AXI Interconnect IP(PG059)或新版 AXI SmartConnect IP(PG247)负责协议转换。

burst length 差异的实际影响

假设你要用 DMA 搬 1MB 数据到 DDR,AXI 数据宽度 64-bit(8 字节),目标尽可能减少事务数量:

AXI4 端 burst length 最大 256 拍:
  每次事务传输 = 256 × 8B = 2KB
  1MB 需要事务数 = 1024KB / 2KB = 512 次事务

AXI3 端(HP 端口)burst length 最大 16 拍:
  每次事务传输 = 16 × 8B = 128B
  1MB 需要事务数 = 1024KB / 128B = 8192 次事务

事务数差 16 倍。每次事务都有地址握手的开销(几个时钟周期),所以 HP 端口的 DMA 效率实际上受限于 AXI3 的 16 拍上限,哪怕你的 PL DMA IP 支持 256 拍 burst,到了 HP 端口这里都会被 AXI Interconnect 拆开。

实际工程建议

  • 给 HP 端口用的 DMA,burst length 配 16(别浪费时间配 128/256,底层会拆)
  • 多并发事务(多个 HP 端口同时 DMA)比拉长单个事务 burst 更有效

🚧 避坑:Xilinx AXI DMA IP(PG021)里的 Max Burst Length 参数,如果你接的是 HP 端口,配超过 16 不会报错,Vivado 也不会提示,但运行时会自动被 protocol converter 拆成 16 拍。设成 16 明确表达设计意图,也省掉 protocol converter 的额外资源。


4. AXI4-Lite / AXI4-Full / AXI4-Stream 的真实差异

这三个”AXI4”变体常被混用,它们实际上是三种完全不同的使用场景:

特性AXI4-LiteAXI4-FullAXI4-Stream
通道数5(简化版)5(完整)1(只有数据)
Burst 支持❌ 固定 1 拍✅ 最大 256 拍N/A(流式)
地址通道✅ 每次传输都有地址✅ 每次 burst 发一次地址❌ 没有地址
WSTRB(写字节使能)✅ 有,但常忽略✅ 有,DMA 必须正确设置❌ 不适用
RLAST / WLAST❌ 无(只有 1 拍)✅ 有TLAST(包边界)
数据宽度32 or 64-bit32~1024-bit任意,常见 8/64/128/256-bit
典型用途IP 控制寄存器读写DDR DMA、视频帧搬运视频像素流、ADC 数据、CNN 中间结果
Vivado 自定义 IP 默认AXI4-Lite slaveAXI4 master(DMA 用)AXI4-Stream(数据路径用)

一个实用判断口诀

  • 你要配置 IP(写寄存器、读状态)→ AXI4-Lite,简单、够用
  • 你要搬大块数据(DMA 到 DDR、视频帧 buffer)→ AXI4-Full,burst 减少总线开销
  • 你要流式数据(一拍接一拍,不关心内存地址)→ AXI4-Stream,最简单,吞吐最大

不要用 AXI4-Full 去做寄存器访问(杀鸡用牛刀,逻辑资源浪费),也不要用 AXI4-Lite 去做 DMA(没有 burst,每字节都要发一次地址,性能灾难)。


5. AXI Interconnect IP 配置要点

Vivado 里有两个 IP 可以做 AXI 路由:

  • AXI Interconnect(PG059,老版):稳定,资源消耗可预测
  • AXI SmartConnect(PG247,2018 年起推荐):自动优化,更省 FF/LUT,支持异步时钟转换

两者核心功能:

5.1 拓扑:Crossbar vs Shared

拓扑适用场景资源特点
Crossbar(交叉开关)多 master 同时访问不同 slave较多真并行,无竞争时零开销
Shared(共享)1 master 多 slave,或低并发较少同一时刻只有 1 个 master 活跃

Zynq 实际场景

  • Pynq-Z2 上,PS 的 M_AXI_GP0 接多个 PL slave IP:用 Crossbar 允许地址仲裁,各 slave 独立响应
  • 多个 PL DMA master 同时写不同地址 → Crossbar,吞吐量更高
  • 只有一个 DMA 在用 → Shared 省资源

5.2 异步时钟交叉(Clock Domain Crossing)

什么时候需要:PL 里的自定义 IP 跑 200MHz,但 HP 端口 AXI clock 是 150MHz,或者你有两个不同频率的 IP 模块互联。

怎么配:在 AXI Interconnect(或 SmartConnect)的 Block Design 配置里:

  • 给 master 端口和 slave 端口分配不同 aclkS_AXI_ACLKM_AXI_ACLK 可以不同)
  • IP 内部自动插入异步 FIFO(基于握手的 CDC)

注意事项

  • 异步 Clock Crossing 有延迟开销(通常 2-3 个目标时钟周期的同步延迟)
  • 如果时钟是同步关系(同一 PLL 输出,整数倍关系),可以不用 CDC,用 SHARED_CLOCK 模式更高效
  • Pynq-Z2 上 PL 时钟来自 FCLK_CLK0(通常 100MHz),如果你另开了 MMCM 给某些 IP 用 200MHz,连 HP 端口时必须在 AXI 路径上加 Clock Crossing

🚧 避坑:忘记设置 Clock Crossing 是 Vivado Block Design 里最常见的时序违例原因之一。症状是布线后时序 timing summary 里出现大量 timing path through CDC pins 的 warning,甚至 Failing Path。如果你的 PL AXI master 时钟和 HP 端口时钟不是同一个 aclk一定要在 Interconnect 里启用 CDC,或在 IP 内部自己处理。


6. Pynq-Z2 上的 AXI 端口映射

Zynq-7000 的地址空间设计来自 UG585 Table 2-2,下面是 Pynq-Z2 开发中最常用的那部分:

端口地址范围大小说明
M_AXI_GP00x4000_0000 – 0x7FFF_FFFF1 GBPS 访问 PL slave IP 的默认区域
M_AXI_GP10x8000_0000 – 0xBFFF_FFFF1 GB第二个 GP master,常用于第二组 PL IP
DDR(PS 主控)0x0000_0000 – 0x3FFF_FFFF1 GBPynq-Z2 板载 512MB,实际用前 512MB
OCM(高地址映射)0xFFFC_0000 – 0xFFFF_FFFF256 KBLinux 启动后可用于 PS-PL 低延迟共享

在 Vivado Block Design 里,当你把自定义 IP 连接到 M_AXI_GP0,在 Address Editor 里会自动分配一个地址,默认是 0x4000_0000,范围 64KB(0x4000_0000 – 0x4000_FFFF

驱动里对应的读写就是:

// 在 Linux 里用 /dev/mem(或 mmap)访问 PL IP 寄存器
#include <sys/mman.h>
#include <fcntl.h>

#define PL_IP_BASE  0x40000000
#define REG_CTRL    0x00
#define REG_STATUS  0x04

int fd = open("/dev/mem", O_RDWR | O_SYNC);
volatile uint32_t *ip = (uint32_t *)mmap(
    NULL, 0x1000, PROT_READ | PROT_WRITE,
    MAP_SHARED, fd, PL_IP_BASE);

ip[REG_CTRL / 4]   = 0x1;           // 写控制寄存器
uint32_t st = ip[REG_STATUS / 4];   // 读状态

如果用 Pynq Python 框架(Pynq-Z2 默认环境):

from pynq import MMIO
ip = MMIO(0x40000000, 0x10000)  # base, size
ip.write(0x00, 0x1)             # 写 ctrl
status = ip.read(0x04)          # 读 status

7. 设计要点:Burst 对齐、4KB 边界、WRAP Burst

7.1 Burst 地址对齐

AXI 要求:每次传输地址必须对齐到传输宽度(AxSIZE)

AxSIZE传输宽度地址必须对齐到
2’b001 Byte1 字节(无要求)
2’b012 Bytes2 字节(地址 bit[0]=0)
2’b104 Bytes4 字节(地址 bit[1:0]=0)
2’b118 Bytes8 字节(地址 bit[2:0]=0)

如果你的 burst 起始地址没对齐(比如 64-bit 传输起始于 0x40000006),AXI 协议违例,slave 行为 undefined。

7.2 4KB 边界约束

这是 AXI 规范(ARM IHI0022F Section A3.4)里的硬规则:

一次 burst 事务不能跨越 4KB(0x1000)地址边界。

原因:AXI 设计上允许地址解码只看高位(>12 位),4KB 以内的地址由 offset 处理,跨 4KB 意味着可能跨越 slave 的地址空间边界。

手算方法

end_addr = start_addr + (AWLEN + 1) × (1 << AWSIZE) - 1

如果 (start_addr & ~0xFFF) != (end_addr & ~0xFFF):
    → 跨越 4KB 边界!必须拆分事务

例子

start_addr = 0x40000FF0
AWLEN = 7  (8 拍)
AWSIZE = 2 (4 字节 / 拍)

end_addr = 0x40000FF0 + 8×4 - 1 = 0x4000100F

0x40000FF0 在 4KB block: 0x40000000
0x4000100F 在 4KB block: 0x40001000  ← 不同!

→ 这个 burst 违反 4KB 边界规则
→ 必须拆成两个事务:
   ① 0x40000FF0,4 拍(到 0x40000FFF,对齐到边界)
   ② 0x40001000,4 拍(从边界开始)

做 DMA 的时候,如果 buffer 地址是动态分配的(kmalloc / dma_alloc_coherent),4KB 对齐分配(用 get_free_pagesdma_alloc_coherent 的 4KB 对齐特性)可以彻底回避这个问题。

7.3 WRAP Burst 的真实用途:Cache Line Fill

WRAP burst(AWBURST = 2'b10)在教程里经常一笔带过。它的实际设计目的很具体:CPU Cache Line Fill(缺失填充)

当 CPU 访问某个地址发生 Cache Miss 时,Cache Controller 需要从内存填充整条 cache line(Cortex-A9 的 L1 cache line = 32 字节 = 8 个 32-bit 字)。但填充顺序有讲究:先填 critical word(触发 Miss 的那个字),然后绕回来填剩余部分

Cache line: 0x40001000 ~ 0x4000101F(32字节,8个32-bit word)
CPU 访问了 0x40001008(critical word,第3个word)

WRAP burst 配置:
  ARADDR = 0x40001008  (critical word 起始)
  ARLEN  = 7           (8 拍)
  ARSIZE = 2           (4 字节 / 拍)
  ARBURST = 2'b10      (WRAP)

传输顺序:
  0x1008 → 0x100C → 0x1010 → 0x1014 → 0x1018 → 0x101C → 0x1000 → 0x1004
  (到 cache line 末尾后,wrap 回 cache line 起始)

你在 PL 设计里几乎不需要主动生成 WRAP burst——只有实现软 CPU 的 Cache Controller 才需要。但理解它有助于你在 ILA 波形里看到 ARBURST=10 时不慌,知道那是 cache fill 在走。

WRAP burst 的约束:burst length 必须是 2、4、8、16 之一,起始地址必须自然对齐到整个 burst 长度。


8. 本篇你应该带走的几个判断

  • Zynq-7000 PS 侧 HP 端口是 AXI3,burst 最大 16 拍,配 DMA IP 时 burst length 不要超过 16
  • PL 侧 Vivado 生成的 IP 是 AXI4,连接到 PS 端口时 AXI Interconnect / SmartConnect 自动做协议转换
  • 看到 AWBURST=10 不要怕,那是 WRAP burst,Cache line fill 专用
  • 写 AXI4-Lite slave:B 通道响应必须在 W 握手完成之后才能发
  • 做 DMA burst 规划:先算 end_addr = start + (len+1)×size,看是否跨 4KB;如果跨了必须拆分
  • PL IP 和 HP 端口时钟不同时:AXI 路径上必须启用 Clock Domain Crossing

9. 下一篇预告

下一篇 《Zynq 实战 06|AXI DMA 实战:从 PL IP 搬数据到 DDR,端到端打通》,我们会动手:

  • 在 Vivado 里配置 AXI DMA IP(PG021),连接 HP0 端口
  • 写一个 AXI4-Stream 数据源 IP(PL 侧计数器),模拟 ADC 数据
  • Linux 驱动侧用 dmaengine API 触发 DMA 传输
  • ILA 抓 HP0 上的真实 burst 波形,验证 16 拍上限

参考资料

文档号名称用途
UG585Zynq-7000 SoC Technical Reference ManualChapter 9(AXI 端口)、Table 2-2(地址映射)
ARM IHI0022FAMBA AXI and ACE Protocol SpecificationAXI3/4 完整协议规范,4KB 规则在 Section A3.4
PG059AXI Interconnect Product Guide (v2.1)Crossbar / Shared 配置、Clock Crossing 参数
PG247AXI SmartConnect Product Guide新版 Interconnect,推荐用于 2020.1+ 工程
PG021AXI DMA Product GuideMax Burst Length 参数,HP 端口连接注意事项
DS190Zynq-7000 SoC Data Sheet: OverviewAXI 端口带宽数字来源

这是《Zynq FPGA 嵌入式系统设计实战》系列第 5 篇。 如果你在 HP 端口 burst 效率或 4KB 边界这两个坑上卡过,欢迎留言交流——这两个问题折腾过很多人。