片上总线与 AMBA 协议:AXI、AHB、APB 怎么把 CPU、DDR、外设连成一颗 SoC
更新时间:2026-09-04。本篇接在 RTL 设计 之后,讲"模块都设计验证完了,怎么把 CPU、缓存、DDR 控制器、UART/GPIO 这些 IP 拼成一颗能协同工作的芯片"。IP 复用与集成的概念在 FPGA 侧也通用,可对照 FPGA IP 核。
一颗现代 SoC 里有几十上百个模块:CPU 集群、GPU、DDR/PCIe/USB 控制器、UART、I2C、GPIO、DMA、各种加速器……它们不可能用线直接两两相连(N 个模块全互联要 N² 根连接,布线爆炸)。于是需要一套标准化的片上通信骨架——谁都按同一套"对话规则"收发数据,挂到同一套互连上就能互通。这套规则就是片上总线协议,事实标准是 ARM 的 AMBA(Advanced Microcontroller Bus Architecture)。
本文要回答的问题
- 为什么 SoC 里需要总线?直接连、用一个大 mux 行不行?
- AMBA 家族里 AXI、AHB、APB 各自定位是什么?为什么高速用 AXI、配置寄存器用 APB?
- AXI 为什么分成五个独立通道?VALID/READY 握手机制怎么实现"反压"?
- 突发(burst)传输、outstanding、out-of-order、ID 标记分别解决什么问题?
- AXI、AXI-Lite、AXI-Stream 三个变体怎么选?
- 多个主设备同时访问一个从设备时,谁来仲裁?地址怎么译码到正确的外设?
- 模块太多、连线太长时,为什么进化出片上网络(NoC)?
一、为什么需要片上总线
先看问题规模。假设 SoC 里有 4 个主设备(CPU0、CPU1、DMA、GPU)和 6 个从设备(DDR、SRAM、UART、I2C、SPI、GPIO)。如果全直连,需要 4×6=24 组地址/数据/控制接口,每组几十上百根线,且每加一个模块就要改所有连接——完全不可维护。
总线/互联的本质是:定义一套标准化接口 + 一个交换结构,让任意主设备能按地址访问任意从设备,而彼此无需知道对方的内部实现。
标准化接口带来的最大红利是 IP 复用:只要一个 IP 带标准 AXI/APB 接口,就能挂到任何用 AMBA 的 SoC 上,不用为每颗芯片重做接口。这就是 AMBA 成为事实标准的根本原因。
二、AMBA 协议家族全景:AXI / AHB / APB
AMBA 不是一个协议,而是一族,按带宽/复杂度分层。现代设计主要用 AXI(高速) 和 APB(低速配置),AHB 是较早的一代、现已基本被 AXI 取代但仍常见于老 IP 和教材。
| 协议 | 定位 | 位宽/频率 | 通道结构 | 典型用途 |
|---|---|---|---|---|
| AXI(3/4/5,含 AXI-Lite/Stream) | 高带宽、高性能 | 数据 32~512bit,高频 | 5 个独立通道,支持突发、多 outstanding | CPU↔DDR、缓存、GPU、DMA、高速 IP |
| AHB(AMBA 2/3) | 中高速(上一代) | 32/64bit | 单组地址/数据,流水线 | 老 SoC 骨干、遗留 IP,已被 AXI 取代 |
| APB(AMBA 3/4) | 低速、低功耗、简单 | 8/16/32bit | 单通道、无突发、两阶段访问 | 配置寄存器、UART/I2C/SPI/Timer/GPIO |
AXI 的三个变体(名字相近,用途不同,极易混):
| 变体 | 特点 | 用途 |
|---|---|---|
| AXI(Full,AXI3/4/5) | 完整突发、最多 256 拍/突发、多 ID | 内存映射的高带宽数据搬运:DDR、DMA、缓存 |
| AXI-Lite | 单拍传输(突发长度 1)、简化逻辑、面积小 | 访问控制/状态寄存器:配置某个 IP 的寄存器 |
| AXI-Stream(AXIS) | 只有数据流,没有地址、可无限拍、点到点 | 数据流管道:ADC→FPGA→DAC、视频/网络包流、DSP 链路 |
一句话记忆:AXI-Full 搬大块数据、AXI-Lite 配寄存器、AXI-Stream 传连续数据流。低速外设配置则再降一级用 APB(经 AXI-to-APB 桥挂到 AXI 上)。
典型 SoC 的分层:CPU/高速 IP 跑 AXI → AXI 互联 → 一路接 DDR/SRAM(AXI),另一路经 AXI-to-APB 桥接到 APB 低速外设岛。这样高速路径不被慢速外设拖累,低速外设又能用最简单省面积的接口。
三、AXI 五通道:把"地址、数据、响应"彻底解耦
AXI 相比老协议最大的设计升级是:读和写各自独立,且地址、数据、响应分成独立通道,可以并行流水。一共 5 个通道,每个通道都是单向的:
| 通道 | 方向 | 传什么 |
|---|---|---|
| AW(Address Write) | 主 → 从 | 写事务的地址、突发长度/大小、ID |
| W(Write data) | 主 → 从 | 写数据(+ strobe 字节使能),可与地址分开到达 |
| B(Write response) | 从 → 主 | 写完成响应(OKAY/EXOKAY/SLVERR/DECERR) |
| AR(Address Read) | 主 → 从 | 读事务的地址、突发信息、 ID |
| R(Read data) | 从 → 主 | 读数据 + 响应,一拍一拍返回 |
关键解耦:写地址 AW 和写数据 W 是两条通道,主设备可以先把所有数据发出、地址稍后到(反之亦然),从设备靠 ID 把它们归到同一事务;读只有地址通道(AR)进去、数据通道(R)出来。这种设计让多个事务可以同时在途、深度流水,带宽远高于"发地址→等数据→再发下一个"的老式阻塞总线。
VALID / READY 握手:天然支持反压
AXI 每个通道都用同一对握手信号:发送方置 VALID=1(表示"我这拍的数据/地址有效"),接收方置 READY=1(表示"我这拍能收下")。只有 VALID 和 READY 在同一时钟周期都为 1,传输才真正发生(一拍 transfer)。
时钟: 1 2 3 4 5
VALID: 0 1 1 1 1 ← 源在第2拍起就有数据
READY: 0 0 0 1 1 ← 目的第4拍才腾出手
└─── 传输发生在 VALID&READY 都为1的拍 (第4、5拍)这套双向握手的精髓是反压(back-pressure):接收方忙不过来就把 READY 拉低,发送方必须保持 VALID 和数据不变、原地等待,数据绝不会丢。它不规定谁必须先举手——VALID 可先于 READY、READY 可先于 VALID、或同拍相遇,都合法(但一旦 VALID 拉高,在握手完成前不允许撤下)。这让任意两个速度不匹配的模块都能安全对接,是 RTL 设计里最基础也最容易写错的时序逻辑之一(见 Verilog 基础 的时序/握手设计)。
四、突发传输、outstanding 与乱序
突发(burst):一次地址、连续传多拍数据,而不是每拍数据都重发一次地址。AXI 用 AWLEN/ARLEN 给出拍数(AXI4 最多 256 拍)、AWSIZE 给每拍字节数、AWBURST 给地址递增方式(INCR 顺序递增最常见,用于内存;WRAP 环形用于缓存行;FIXED 固定地址用于 FIFO)。这样搬一整块内存只要发一次起始地址,带宽利用率大幅提高。
- outstanding(多事务在途):主设备不必等上一个事务的响应回来就能发下一个事务的地址/数据。比如发 10 个读请求后,从设备可以陆续返回数据。在途事务越多,越能掩盖内存访问延迟,但需要更多缓冲资源。
- out-of-order(乱序返回):不同 ID 的事务允许后发的先返回(从设备可以先响应准备好的那个);同一 ID 的事务则必须按顺序完成。主设备靠每笔事务的 ID 标签把回来的数据对号入座。这让慢请求(如 DDR 未命中)不必堵住后面的快请求。
- 写交织/原子操作:AXI5 还支持原子事务(Atomic)、QoS 优先级、缓存一致性信号等,服务多核共享内存场景。
这些机制全是为了一个目标:在高频宽总线上把延迟藏起来、把带宽喂满。代价是接口逻辑复杂、验证难度高——AXI 协议的断言验证(protocol checker)是 SoC 验证的常见重点。
五、互联内部:地址译码、仲裁与从设备选择
主设备只管"发出地址 + 读写",真正把事务送到正确从设备、并在多个竞争者间排顺序的,是中间的互联(interconnect)。它内部做三件事:
- 地址译码(decode):看事务地址落在哪个从设备的地址区间(memory map)。例如
0x0000_0000~0x7FFF_FFFF映射 DDR、0x4000_0000~0x4000_FFFF映射 UART。译码不中返回 DECERR(decode error)。 - 多路选择(mux / crossbar):把选中的从设备接口连到发起事务的主设备。简单互联用共享总线(同一时刻只能一对通信),高性能用 crossbar(交叉开关)——多对主从可并行通信,只要访问的不是同一个从设备。
- 仲裁(arbitration):多个主设备同时要访问同一个从设备时,按优先级/轮询(round-robin)/QoS 决定谁先用,输的一方被反压(READY 拉低)排队。
从总线到片上网络(NoC)
当芯片上有几十上百个主从、且分布在很大的硅片面积上时,单级 crossbar 也扛不住——连线太长、时序收敛困难、功耗高。于是大型 SoC(服务器 CPU、高端手机 SoC、GPU)借鉴计算机网络,把互联做成片上网络(Network on Chip,NoC):
- 数据被打成包(packet),带"源/目的地址",在一张由路由节点(router)+ 链路组成的网格(mesh)上逐跳转发,像城市路网而不是一条直总线;
- 好处:布线规整、易收敛时序、可扩展到几百节点、不同路径可并行;
- 代价:每跳有延迟、有路由缓冲开销,协议更复杂。
中小规模 MCU/嵌入式 SoC 仍用 AXI 总线 + crossbar 就够;NoC 是大规模 SoC 的答案。
六、APB:低速外设的"最后一公里"
UART、I2C、SPI、Timer、GPIO 这类外设数据量极小(主要是读写一堆配置/状态寄存器),让它们挂完整 AXI 既浪费面积又没必要。APB 就是为它们设计的极简协议:
- 单通道、无突发、无 ID、无 outstanding——一次访问就是"给地址 → 等一两拍 → 读/写一个寄存器";
- 两个核心阶段:SETUP(放地址/选择)→ ENABLE(使能传输),逻辑极简单,外设接口面积小、功耗低;
- 不能自己当骨干,通常挂在 AXI-to-APB 桥后面:桥在 AXI 侧当一个从设备,把收到的 AXI-Lite 访问翻译成 APB 时序,再由 APB 上的外设地址译码分发到各外设。
AXI 侧(高速) APB 侧(低速外设岛)
CPU ──AXI──→ [AXI-to-APB 桥] ──APB──→ ┬─ UART (0x4000_1000)
├─ I2C (0x4000_2000)
├─ SPI (0x4000_3000)
└─ GPIO (0x4000_4000)
桥:把 AXI-Lite 单拍访问翻译成 APB 的 SETUP→ENABLE 两拍时序七、怎么选:一张选型对照表
| 需求 | 选什么 | 理由 |
|---|---|---|
| CPU 读 DDR、DMA 搬大块数据 | AXI-Full | 高带宽、突发、多 outstanding、乱序 |
| 配置某个 IP 的控制/状态寄存器 | AXI-Lite | 单拍、逻辑小,比 Full 省面积 |
| 连续数据流(视频、采样、DSP 流水线) | AXI-Stream | 无地址、无限拍、点到点,专走数据流 |
| UART/I2C/GPIO 等低速外设 | APB(经桥) | 极简、低功耗、省面积 |
| 老 IP / 遗留系统对接 | AHB | 兼容老协议,新设计不建议 |
| 上百节点的超大 SoC | NoC(AXI 打包在 NoC 上跑) | 可扩展、时序易收敛 |
常见误区与工程提醒
| 误区/错误 | 后果 | 对策 |
|---|---|---|
| VALID 拉高后、握手前又撤下/改数据 | 接收方可能已采样,协议违规、数据错乱 | VALID 一旦置位,保持到 VALID&READY 握手完成 |
| 用组合逻辑产生 VALID/READY 形成长组合环 | 时序收敛失败、死锁 | 握手信号打拍,用 skid buffer 切断组合路径 |
| 给低速外设硬挂 AXI-Full | 面积/功耗浪费、验证复杂 | 寄存器配置用 AXI-Lite 或 APB |
| 忽略 ID 宽度/乱序,假设响应一定按发的顺序回 | 多 outstanding 时数据对号入座错误 | 用 ID 匹配事务;依赖顺序时同 ID 或加排序逻辑 |
| 地址译码区间重叠/留洞 | 访问落到错误从设备或 DECERR | 明确 memory map,译码表评审,留空区间返回 DECERR |
| 数据流场景硬用内存映射 AXI | 每拍都带地址,效率低 | 连续流用 AXI-Stream |
相关与延伸
本篇讲"模块怎么连成 SoC":模块本身怎么写见 RTL 设计;握手/状态机/同步设计的 RTL 基本功见 Verilog 基础;复用现成模块(含 AXI 接口 IP)见 FPGA IP 核;协议是否被正确实现靠 功能验证(AXI protocol checker 断言);总线/IP 综合后的时序收敛见 时序分析 STA;工具链见 EDA 工具链地图。
一句话总结
片上总线与 AMBA:SoC 里几十上百个模块不能全直连,需要标准化互联让主设备按地址访问从设备、IP 即插即用,事实标准是 ARM AMBA;高速骨干用 AXI——它拆成 AW/W/B(写地址/数据/响应)+ AR/R(读地址/数据)五个独立通道,读写分离、可深度流水,用 VALID/READY 双向握手天然支持反压(两者同拍为 1 才传输,VALID 一旦拉高握手前不能撤),用突发(一次地址传多拍)、outstanding(多事务在途藏延迟)、ID 乱序返回把带宽喂满;三个变体分工明确——AXI-Full 搬大块内存数据、AXI-Lite 配寄存器、AXI-Stream 传无地址连续数据流;低速外设(UART/I2C/GPIO)用极简的 APB(SETUP→ENABLE 两拍、无突发),经 AXI-to-APB 桥挂到骨干;互联内部靠地址译码(memory map)+ crossbar(多对并行)+ 仲裁(优先级/轮询)工作,上百节点的超大芯片则把数据打包成片上网络 NoC逐跳路由。