FPGA 进阶 12:AXI4 完整与互联——burst、outstanding、ID 与 Crossbar
本文是
fpga/进阶层第 16 篇。进阶 14 讲了 AXI4-Stream(数据流)和 AXI4-Lite(寄存器配置),这篇补齐第三个子集 AXI4(Full)——真正用来在 DDR、DMA、CPU 之间高带宽搬运数据的内存映射协议。协议逐条规则见芯片设计进阶的 AXI4 完整协议,本篇侧重 FPGA 工程视角:burst/outstanding/ID 怎么影响带宽、Interconnect 怎么连、哪些接口根本不用自己手写。
本文要回答的问题
- AXI4 Full 的五个通道分别传什么,为什么读写要分开?
- burst 突发怎么描述?AWLEN/AWSIZE/AWBURST、WLAST、4KB 边界各是什么?
- outstanding 和 ID 怎么让总线并发?打满带宽要配多少?
- AXI Interconnect/SmartConnect 帮我做了哪些事?
- FPGA 里 AXI4 Full 的 master/slave 哪些要自己写、哪些直接用 IP?
一、三个子集再定位
| AXI4-Lite | AXI4-Stream | AXI4 Full(本篇) | |
|---|---|---|---|
| 用途 | 寄存器配置/状态 | 单向数据流 | 内存映射块传输 |
| 地址 | 有,单字 | 无 | 有,支持 burst |
| 突发 | 不支持 | 概念上连续流 | AWLEN 最多 255(256 beat) |
| 并发 | 无 | 反压 | outstanding + 多 ID |
| 典型角色 | PS 配 PL 寄存器 | DMA↔流水级 | DMA↔DDR、PS↔DDR |
一句话:Lite 管控制、Stream 管流水、Full 管带宽。Zynq 系统里三者同时在场,由 Interconnect 挂在一起。
二、五个独立通道
AXI4 Full 把读写拆成五个独立通道,各自有自己的 VALID/READY 握手,可以并行流水线:
| 通道 | 信号前缀 | 方向 | 传什么 |
|---|---|---|---|
| 写地址 | AW* | master→slave | 起始地址、burst 信息(LEN/SIZE/BURST/ID) |
| 写数据 | W* | master→slave | 数据 WDATA、字节使能 WSTRB、WLAST |
| 写响应 | B* | slave→master | BRESP(OKAY/SLVERR/DECERR)、BID |
| 读地址 | AR* | master→slave | 起始地址、burst 信息、ARID |
| 读数据 | R* | slave→master | RDATA、RRESP、RLAST、RID |
读写分离的好处:读和写可以同时进行(全双工),写通道里「地址」和「数据」也可以各自独立流动(W 数据可以比 AW 先到,Interconnect 内部有 FIFO 对齐)。握手规则和 valid/ready 握手 完全一致:VALID 一旦拉高,在握手成功前不许撤;VALID 不许组合依赖 READY(防环路);READY 可以等 VALID。
三、burst:一笔地址搬一串数据
Full 相比 Lite 的核心优势是 burst:发一次起始地址,连续传多个 beat(最多 256 个),省去每 beat 的地址握手。一笔 burst 由三个信号描述:
- AWLEN / ARLEN:beat 数 − 1(写 255 表示 256 个 beat);
- AWSIZE / ARSIZE:每个 beat 的大小,编码为
2^SIZE字节(0=1B、1=2B、2=4B、3=8B); - AWBURST / ARBURST:地址增长方式——
2'b00FIXED、2'b01INCR、2'b10WRAP。
| 模式 | 地址行为 | 典型用途 |
|---|---|---|
| FIXED | 所有 beat 同一地址 | 访问 FIFO/队列(地址不变、每次下一个数据) |
| INCR | 每 beat 地址 += beat 字节数 | DDR/BRAM 顺序访问、DMA 块传输(最常用) |
| WRAP | 递增到边界后回绕 | CPU cache line 回填,FPGA 逻辑几乎不用 |
两条硬规则,违反会死锁或取错数据:
- WLAST / RLAST:burst 的最后一个 beat 必须拉高——从机靠它知道「这一笔写完了、可以回 BRESP 了」。WLAST 漏拉是新手最常见的挂死:从机永远等不到最后一拍,B 通道不响应,DMA 卡死。
- 不能跨 4KB 边界:一笔 burst 的地址范围不许跨过 4KB 页边界(协议规定,保证 slave 译码一致)。DMA 描述符/地址生成器要按 4KB 拆分 burst。
写通道骨架(可综合,简化版):
// 状态机:发 AW 地址 -> 连续发 W 数据(最后拍拉 WLAST) -> 收 B 响应
localparam S_AW=0, S_W=1, S_B=2, S_DONE=3;
reg [1:0] state; reg [7:0] beat;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) state <= S_AW;
else case (state)
S_AW: if (awvalid && awready) state <= S_W; // 地址握手成功
S_W: if (wvalid && wready) begin
if (beat == aw_len) state <= S_B; // 最后一个 beat
end
S_B: if (bvalid && bready) state <= S_DONE; // 收到写响应
default: state <= S_AW;
endcase
end
assign awvalid = (state == S_AW);
assign aw_len = len_i - 8'd1; // beat 数-1
assign aw_size = 3'b010; // 4 字节/beat
assign aw_burst = 2'b01; // INCR
assign wvalid = (state == S_W);
assign wlast = (state == S_W) && (beat == aw_len); // 关键:最后拍拉高
assign bready = (state == S_B);读侧类似:AR 通道发地址和长度,然后在 R 通道收数、数到 RLAST 结束。
四、outstanding 与 ID:并发是带宽的来源
如果「发一笔 burst → 等它全部完成 → 再发下一笔」,总线在从机(尤其 DDR)的几十拍延迟里全程空转。AXI 允许 outstanding:发了地址还没收到数据/响应的传输可以有多笔同时在飞。
- 主机可以连续发多笔 AW/AR(每笔带一个 ID:AWID/ARID),不必等上一笔的 B/R;
- 从机各自完成后回 BRESP/RDATA,并带上 BID/RID 标明是哪一笔;
- 同 ID 保序:相同 ID 的传输按发出顺序完成;不同 ID 可乱序返回(谁快谁先回,用 ID 认领)。
打满从机带宽需要的在飞数据量 ≈ 从机延迟(拍)× 每拍数据量,换成 outstanding 笔数:
需要的 outstanding 笔数 ≈ 从机往返延迟(拍) ÷ 每笔 burst 的 beat 数例:DDR 往返延迟约 30 拍、每笔 burst 16 beat,则至少要 ~2 笔在飞;留余量配 8~32 outstanding、多开几个 ID 线程,就能把 DDR 有效带宽从「等延迟」的零头拉到峰值的八九成。AXI DMA、SmartConnect 里都有 Number of outstanding/Threads 参数,带宽不达标先查这里。
ID 位宽主从必须一致(Interconnect 会自动扩展/路由)。自定义 slave 若不做乱序,把所有响应的 ID 回填成收到的 ARID/AWID、严格按接收顺序回即可天然合规。
五、AXI Interconnect / SmartConnect:片上 crossbar
一个 Zynq 系统里通常有多个 master(PS、AXI DMA、可能还有自定义 master)和多个 slave(MIG DDR、BRAM 控制器、各种 AXI-Lite 寄存器块),不可能两两直连。AXI Interconnect / SmartConnect 就是这块片上交换网络(crossbar),帮你做:
- 多主多从路由 + 地址译码:按地址区间把每笔事务送到对应 slave(Block Design 里自动分配地址段);
- 多 master 仲裁:多个 master 同时访问一个 slave 时轮询/优先级仲裁;
- 位宽转换:32 位 master 访问 64/128 位 slave 自动拆/合 beat;
- 时钟域转换:不同时钟的 AXI 口之间内置异步 FIFO 跨域(省得自己做 CDC);
- 协议转换:AXI4 Full ↔ AXI4-Lite、AXI3 ↔ AXI4。
SmartConnect 是新一代推荐 IP:只支持 AXI4 内存映射、资源更少、转换更省、配置更简单,Vivado Block Design 里默认用它;只有需要 AXI3、locked 事务等老特性时才用旧的 AXI Interconnect。
六、FPGA 里谁该手写、谁直接用 IP
这是 FPGA 和写 ASIC RTL 的重要区别——AXI4 Full 几乎不用从零手写:
| 角色 | 常见做法 |
|---|---|
| AXI master(发起 DDR/DMA 读写) | 直接用 AXI DMA / AXI VDMA / SmartConnect 里的 PS M_AXI_HP;自定义算法要读写内存时,用 AXI DMA + AXI-Stream 接你的流水,而不是自己写 master |
| AXI slave(被读写) | 存储类用 MIG(DDR)/ AXI BRAM Controller;寄存器类用 AXI4-Lite(见进阶 14) |
| 协议/位宽/时钟粘合 | 全交给 SmartConnect |
真正需要自己写 AXI4-Full 接口的场景很少:自定义的高性能内存映射 slave、要绕过 DMA 直接发事务的 master 等。即便手写,也建议先复用 Xilinx AXI VIP/模板,把五通道握手、WLAST、ID 回填做对,再谈优化。绝大多数工程:DMA 当 master、MIG/BRAM 当 slave、SmartConnect 当交换,你只写 Stream 侧的算法。
七、上板常见死锁与坑
| 现象 | 根因 | 排查 |
|---|---|---|
| DMA 启动后整路卡死、不产生中断 | WLAST/RLAST 漏拉或拉错拍 | ILA 抓 W 通道,数 beat 数是否等于 LEN+1、最后拍 WLAST 是否为高 |
| 偶发取错地址/数据错乱 | burst 跨 4KB 边界 | 检查地址生成:起始 + LEN×SIZE 不跨 4KB,跨了就拆两笔 |
| 带宽远低于理论值 | outstanding 太小 / ID 线程太少 | DMA/SmartConnect 里调大 outstanding、多开线程 |
| 仿真过、上板挂 | VALID 组合依赖 READY 形成组合环路 | valid 用寄存器打一拍产生,ready 才可以组合 |
| 写后读回旧值 | 写完没等 BRESP 就发起读 | 写事务以 B 通道握手为完成标志 |
| 多 slave 访问不到 | Block Design 未分配地址段 | Address Editor 里确认每个 slave 有 offset/range |
相关与延伸
前置/配套:AXI4-Stream 与 AXI4-Lite(数据流与寄存器子集)、valid/ready 握手(握手底层规则)、协议逐条规则见 AXI4 完整协议、AXI4-Lite 从机。 AXI4 Full 的两大使用者就是后面的 DDR MIG(进阶 17) 和 AXI DMA / PCIe DMA(进阶 19);Zynq PS 怎么挂这些 IP 见后续「Zynq 数据交互 AXI DMA」篇。
一句话总结:AXI4 Full 用五个独立通道 + burst(LEN/SIZE/BURST、WLAST、不跨 4KB)+ outstanding/ID 并发来跑高带宽内存传输;FPGA 工程里 master 交给 DMA/PS、slave 交给 MIG/BRAM、交换交给 SmartConnect,自己手写只在少数高性能自定义接口场景,且务必把 WLAST、ID 回填、valid/ready 不组合环路这几条做对。