简介:AMBA总线协议中文版面向嵌入式硬件与SoC设计方向的工程师、学生及技术爱好者,帮助读者跨越英文原版文档的语言门槛,系统理解ARM高级微控制器总线体系结构。资源为单个PDF文件,压缩包约1.2MB,内容涵盖AMBA总线概况、信号定义、AHB高级高性能总线、ASB高级系统总线、APB高级外设总线以及测试方法等章节,并配有排版与时序图惯例说明,便于对照规范理解读写操作、地址与数据信号等关键概念。目前已有1224人学习下载,适合作为总线协议入门与查阅的参考材料。通过这份中文规范,读者可掌握三类总线的分工与典型微控制器连接方式,理清控制信号与数据信号的时序关系,为后续接口设计、模块验证与协议调试打下基础。
1. 从一份 1999 年的中文规范说起:AMBA 到底解决了什么问题
1999 年 5 月 13 日,ARM 发布了 AMBA 总线规范 V2.0 的第一次公开版本,这份文档后来被翻译成中文,成了国内很多 SoC 团队入门的“第一本总线手册”。它要解决的核心问题很朴素:一颗芯片里 CPU、DMA、片上 SRAM、UART、SPI、定时器这些模块的时钟频率、数据位宽、响应延迟差异巨大,如果每个模块都点对点连线,互连会迅速失控。AMBA 给出的答案是分层——高速主设备走 AHB,系统级设备走 ASB,低速外设挂 APB,中间用桥接器过渡。这份中文版把信号列表、时序图、仲裁、分块传输、位宽转换这些内容逐条译出,适合正在写 AHB 从机、调 APB 寄存器、或者要给自研 IP 做总线接口的硬件与固件工程师。它不教你 Verilog 语法,但能让你看懂波形里 HREADY、HRESP、HGRANT 为什么在某个周期翻转。
2. AMBA 三层总线选型:AHB、ASB、APB 的边界与信号前缀
2.1 三种总线的定位差异
规范把 AMBA 拆成三条总线,不是随便分的。AHB 面向高带宽、高时钟频率的主设备,支持突发传输、流水线地址、多主机仲裁,典型挂载 CPU、DMA、片上 RAM 控制器。ASB 是 AHB 之前的系统总线方案,传输协议更简单,不支持 AHB 那种地址数据流水,现在新设计基本不再选它,但读老 IP 或维护旧项目时会遇到。APB 则是典型的外设总线,协议极简,无流水、无突发,一次传输至少两个周期,适合 UART、GPIO、SPI 这类对带宽不敏感的模块。
选型时我一般按这个顺序判断:设备是否需要突发和流水?是则 AHB;设备是否只是寄存器读写、频率低?是则 APB;如果项目里已有 ASB 遗留模块,才考虑 ASB 并规划桥接。
2.2 信号前缀与命名规则
规范第 2 章给出了信号前缀约定,这是读时序图和写接口时最容易混淆的地方:
| 总线 | 前缀 | 示例信号 | 含义 |
|---|---|---|---|
| AHB | H | HREADY、HRESP、HGRANT | 高性能总线信号 |
| ASB | B | BTRAN、BA、BWRITE | 系统总线信号 |
| APB | P | PSEL、PENABLE、PWRITE | 外设总线信号 |
| 全局 | 无 | HCLK、HRESETn | 时钟与复位 |
记住前缀,看波形时就能一眼判断这条线属于哪层总线。比如HREADY是 AHB 从机告诉主机“上一拍传输已完成”,而PREADY是 APB 从机的对应信号,两者语义相似但时序位置完全不同。
2.3 用一段 APB 时序代码理解握手
APB 的传输过程可以用下面这段伪代码描述,它对应规范第 5 章的 APB 状态机:
// APB 从机响应逻辑(简化) // PSEL: 从机选中,PENABLE: 使能阶段标志 always @(posedge PCLK or negedge PRESETn) begin if (!PRESETn) begin PREADY <= 1'b0; PRDATA <= 32'h0; end else begin // 建立阶段:PSEL 拉高,PENABLE 为低 // 访问阶段:PSEL 和 PENABLE 同时为高 if (PSEL && PENABLE) begin PREADY <= 1'b1; // 表示本次传输完成 if (PWRITE) reg_file[PADDR] <= PWDATA; // 写操作 else PRDATA <= reg_file[PADDR]; // 读操作 end else begin PREADY <= 1'b0; end end end这段逻辑的关键点在于:APB 没有流水线,PSEL拉高后的第一个周期是建立阶段,第二个周期PENABLE拉高才真正采样数据。PREADY可以由从机拉低来插入等待周期,但规范建议 APB 从机尽量单周期完成,否则会拖慢整个外设访问。参数上,PADDR位宽通常与 APB 桥的地址译码范围一致,常见 12 到 16 位,PWDATA/PRDATA在 V2.0 里是 32 位。
注意:APB 的
PENABLE必须在PSEL之后至少一个周期拉高,直接同时拉高会被部分综合工具报时序违例。
3. AHB 传输机制:突发、流水线与从机响应
3.1 基本传输与流水线地址
AHB 的核心特征是地址与数据分离的流水线。一个基本传输分地址阶段和数据阶段:地址阶段主机给出HADDR、HTRANS、HSIZE等,数据阶段才出现HWDATA或HRDATA。因为流水,当前传输的数据阶段可以和下一笔传输的地址阶段重叠,这是 AHB 能跑高频的原因。
HTRANS的取值决定传输类型:00空闲、01忙、10非连续、11连续。连续传输用于突发,地址由从机根据HSIZE自动递增,主机不必每拍都给新地址。
3.2 突发操作与提前终止
突发由HBURST定义长度和回绕方式,常见有 SINGLE、INCR、INCR4、INCR8、INCR16、WRAP4、WRAP8、WRAP16。INCR 是地址递增不回头,WRAP 是到边界后回绕,常用于 Cache line 填充。
突发可以被提前终止,两种情况:主机拉低HTRANS为忙或空闲,或者从机拉高HREADY为低并给出HRESP非 OKAY。规范第 3.6.1 节特别强调,从机在突发中途插入等待时,主机必须保持地址和控制信号不变,否则从机会采样到错误地址。
3.3 从机响应 HRESP 与双周期
HRESP配合HREADY表达四种响应:
| HRESP | HREADY | 响应类型 | 含义 |
|---|---|---|---|
| 00 | 1 | OKAY | 传输成功 |
| 01 | 1 | ERROR | 传输错误 |
| 10 | 0 | RETRY | 从机忙,稍后重试 |
| 11 | 0 | SPLIT | 分块,从机暂时释放总线 |
ERROR、RETRY、SPLIT 都是双周期响应:第一周期HREADY为低、HRESP给出对应值,第二周期HREADY拉高、HRESP保持,主机在第二周期末才确认。写从机时如果漏掉第二周期,主机会把错误响应当成 OKAY。
3.4 仲裁与 HGRANT 时序
多主机场景下,仲裁器通过HBUSREQx接收请求,用HGRANTx授权。规范要求HGRANT在地址阶段之前有效,主机在采样到HGRANT且HREADY为高后,才能在下一拍发起传输。HMASTER信号告诉从机当前是哪个主机在访问,SPLIT 响应时从机靠它记住该唤醒谁。
// 简化的 AHB 仲裁器授权逻辑 // HBUSREQ: 各主机请求,HGRANT: 授权输出 always @(posedge HCLK or negedge HRESETn) begin if (!HRESETn) HGRANT <= 4'b0001; // 复位后默认主机 0 else if (HREADY) begin // 当前主机传输结束,按优先级轮询 if (HBUSREQ[1]) HGRANT <= 4'b0010; else if (HBUSREQ[2]) HGRANT <= 4'b0100; else HGRANT <= 4'b0001; // 默认主机 end end这段逻辑说明HGRANT只在HREADY为高时切换,保证授权变化不会打断正在进行的传输。参数上,HGRANT位宽等于主机数量,HMASTER通常用 4 位编码,支持最多 16 个主机。
注意:默认总线主机必须在所有其他主机都不请求时获得授权,否则总线会死锁。
4. 位宽转换、分块传输与死锁预防
4.1 宽总线挂窄从机的实现
规范第 3.15 节讲了一个实际项目中高频出现的问题:32 位 AHB 总线上挂一个 16 位从机。做法是把HADDR[1]作为从机的地址最低位,HWDATA的高 16 位和低 16 位根据HADDR[1]选择性地写入从机。读方向则要把从机返回的 16 位数据复制到HRDATA的对应半字位置。
// 32 位主机访问 16 位从机的数据选择 // HADDR[1] 决定访问高半字还是低半字 assign slave_wdata = HADDR[1] ? HWDATA[31:16] : HWDATA[15:0]; assign HRDATA = HADDR[1] ? {slave_rdata, 16'h0} : {16'h0, slave_rdata};参数说明:HSIZE此时应设为01(半字),如果主机发HSIZE=10(字)访问 16 位从机,从机需要返回 ERROR 或由桥接器拆分。实际项目中更常见的做法是加一个 AHB-to-APB 桥,由桥统一处理位宽和协议转换。
4.2 分块传输 SPLIT 的顺序与死锁
SPLIT 响应让从机在不能立即完成传输时释放总线,等准备好后再通过HSPLITx请求仲裁器重新授权。规范第 3.12 节给出了严格顺序:从机先给出 SPLIT 双周期响应,仲裁器记录该主机被分块,从机准备好后拉高对应的HSPLITx,仲裁器在HREADY为高时重新授权。
死锁预防的关键规则:从机不能对同一个主机连续发 SPLIT 而不给任何其他主机机会;仲裁器必须保证被分块的主机在从机释放后能重新获得授权。我见过一个项目因为仲裁器优先级固定,低优先级主机被反复分块,最终看门狗超时复位。
4.3 复位与退出复位时序
HRESETn是低有效复位,规范要求复位期间所有主机必须驱动HTRANS为空闲,从机HREADY拉高。退出复位后,第一个传输必须是空闲或非连续,不能直接发突发。APB 侧PRESETn同理,且PSEL、PENABLE在复位期间必须为低。
| 信号 | 复位值 | 退出复位后要求 |
|---|---|---|
| HTRANS | 00 | 首拍空闲或非连续 |
| HREADY | 1 | 从机就绪 |
| HBURST | 000 | 单次传输 |
| PSEL/PENABLE | 0 | 等待桥发起 |
5. 用仿真波形验证 AHB 从机:一个可复现的检查清单
写完 AHB 从机后,光看代码很难确认时序对不对。我一般会跑一组定向仿真,重点看下面几个检查点。第一,地址阶段HTRANS为10或11时,HREADY是否为高,从机是否在下一拍给出HRESP。第二,突发传输中从机插入等待时,主机地址和控制信号是否保持不变。第三,ERROR 响应是否完整走了两个周期。第四,SPLIT 后HSPLITx是否在从机准备好后才拉高。
可以用下面这段 SystemVerilog 断言快速挂到仿真里:
// AHB 从机关键时序断言 // 检查 ERROR 响应必须持续两个周期 property p_error_two_cycle; @(posedge HCLK) disable iff (!HRESETn) (HRESP == 2'b01 && HREADY == 1'b0) |=> (HRESP == 2'b01 && HREADY == 1'b1); endproperty assert property (p_error_two_cycle) else $error("ERROR response not two cycles"); // 检查突发期间地址在等待时不变 property p_addr_stable_during_wait; @(posedge HCLK) disable iff (!HRESETn) (HTRANS inside {2'b10, 2'b11} && HREADY == 1'b0) |=> $stable(HADDR); endproperty assert property (p_addr_stable_during_wait) else $error("HADDR changed during wait");断言里的|=>表示下一拍,$stable检查信号保持不变。跑仿真时如果这两条断言频繁报错,基本可以定位到从机状态机在等待周期里错误地更新了地址,或者 ERROR 响应只给了一个周期。另一个实用技巧是把HMASTER和HSPLITx一起抓进波形,SPLIT 场景下能直观看到仲裁器何时重新授权。最后,APB 侧可以用PENABLE和PREADY的握手做覆盖率点,确保建立阶段和访问阶段都被覆盖到,避免只测了单周期完成而漏掉等待插入的分支。
本文还有配套的精品资源,点击获取