4、总线协议基础:AMBA AHB/AXI协议简介、总线时序、读写操作流程

说到嵌入式系统,总线协议是个绕不开的话题。我刚开始做SoC设计那会儿,总觉得总线协议就是一堆时序图,看着就头疼。后来真正上手调了两次,才发现这东西说白了就是一套「握手规则」——谁先说话、谁先回应、数据怎么传,都约定好了。

今天咱们聊聊AMBA总线协议家族里最常用的两个成员:AHB和AXI。嗯,这两个你肯定会在项目中碰到。

4.1 为什么需要总线协议?

你想想看,一个芯片里可能有CPU、内存、外设、DMA控制器……这么多模块要互相通信。如果每个模块都自己搞一套通信方式,那设计就乱套了。总线协议就是给这些模块定了个「交通规则」。

AMBA(Advanced Microcontroller Bus Architecture)是ARM公司推出的总线标准。目前主流的就是AHB和AXI。我个人习惯把AHB看作「中速公路」,AXI则是「高速铁路」。

核心要点:总线协议定义了主设备(Master)和从设备(Slave)之间的通信方式。主设备发起请求,从设备响应请求。

4.2 AHB协议简介

AHB(Advanced High-performance Bus)是AMBA 2.0时代的主力。我在一个MCU项目里用过它,当时要挂接SRAM和Flash控制器,AHB完全够用。

4.2.1 AHB的主要特点

  • 单周期地址/数据相位:地址阶段和数据阶段是分开的,但可以流水
  • 支持突发传输:一次地址请求,后面连续传数据
  • 最多16个主设备:通过仲裁器决定谁占用总线
  • 三态总线:地址和数据共用一组总线

4.2.2 AHB的基本信号

信号名 方向 说明
HCLK 全局 总线时钟,所有操作同步于此
HRESETn 全局 复位信号,低有效
HADDR[31:0] Master→Slave 地址总线
HWDATA[31:0] Master→Slave 写数据总线
HRDATA[31:0] Slave→Master 读数据总线
HWRITE Master→Slave 写使能,1为写,0为读
HSEL Decoder→Slave 从设备选择信号
HREADY Slave→Master 传输完成信号,高有效
HRESP[1:0] Slave→Master 传输响应:OKAY、ERROR、RETRY、SPLIT

我的经验:调试AHB时,我最先看的就是HREADY信号。如果它一直拉低,说明从设备在「拖死」总线。我曾经遇到一个Flash控制器,读操作需要等待周期,结果HREADY没处理好,整个系统卡死。排查了整整一天……

4.2.3 AHB读写操作流程

AHB的读写操作分两个阶段:地址阶段和数据阶段。地址阶段只占一个时钟周期,数据阶段可能多个周期(如果从设备需要等待)。

单次读操作:

时钟周期:  T1    T2    T3    T4
HCLK:     ▁▁▂▂▁▁▂▂▁▁▂▂▁▁▂▂
HADDR:    ──  Addr ──────────
HWRITE:   ──  0  ────────────
HRDATA:   ──────────  Data ──
HREADY:   ──  1  ──  0  1 ──

你看,T1周期主设备发出地址,T2周期从设备拉低HREADY表示需要等待,T3周期数据才准备好。这就是典型的「等待周期」。

突发写操作:

时钟周期:  T1    T2    T3    T4    T5
HCLK:     ▁▁▂▂▁▁▂▂▁▁▂▂▁▁▂▂▁▁▂▂
HADDR:    ──  A1 ── A2 ── A3 ────
HWDATA:   ──────  D1 ── D2 ── D3
HWRITE:   ──  1  ────────────────
HREADY:   ──  1  ──  1  ──  1 ──

突发传输时,地址和数据可以流水。地址A1发出后,下一个周期就可以发地址A2,同时数据D1也出现在总线上。效率比单次传输高不少。

注意:AHB的突发长度是固定的,不能中途终止。我见过有人想用AHB做不定长传输,结果发现协议不支持,只能改用AXI。所以设计初期就要想清楚需求。

4.3 AXI协议简介

AXI(Advanced eXtensible Interface)是AMBA 3.0引入的,后来在AMBA 4.0和5.0中不断演进。说白了,AXI就是AHB的「升级版」——更快、更灵活、更适合高性能系统。

我记得第一次用AXI是在一个视频处理芯片上,数据吞吐量要求很高。AHB根本跑不动,换成AXI后问题就解决了。

4.3.1 AXI的主要特点

  • 五个独立通道:读地址、读数据、写地址、写数据、写响应
  • 全双工通信:读和写可以同时进行
  • 乱序传输:支持Out-of-Order完成
  • 支持非对齐传输:地址不需要对齐到数据宽度
  • 突发长度可变:1到256次传输

4.3.2 AXI的通道结构

通道 信号组 方向 说明
读地址 ARADDR, ARVALID, ARREADY Master→Slave 发起读请求
读数据 RDATA, RRESP, RVALID, RREADY Slave→Master 返回读数据
写地址 AWADDR, AWVALID, AWREADY Master→Slave 发起写请求
写数据 WDATA, WSTRB, WVALID, WREADY Master→Slave 发送写数据
写响应 BRESP, BVALID, BREADY Slave→Master 返回写完成状态

关键区别:AHB只有一套地址/数据总线,读写不能同时进行。AXI有五个独立通道,读和写可以「并行跑」。你想想看,这性能差距有多大。

4.3.3 AXI的握手机制

AXI每个通道都用VALID/READY握手。主设备拉高VALID表示数据有效,从设备拉高READY表示可以接收。两者都拉高时,传输发生。

这里有个小细节:VALID不能依赖READY。也就是说,主设备拉高VALID后,必须保持直到握手成功。但READY可以随时拉高拉低。嗯,这个设计是为了防止死锁。

// AXI握手示例(Verilog风格)
always @(posedge clk) begin
    if (rst) begin
        arvalid <= 1'b0;
        araddr  <= 32'b0;
    end else begin
        // 当ARREADY为高且ARVALID为高时,地址被接收
        if (arvalid & arready) begin
            arvalid <= 1'b0;  // 传输完成,撤销请求
        end else if (need_read) begin
            arvalid <= 1'b1;
            araddr  <= read_addr;
        end
    end
end

避坑指南:我曾经在AXI接口上犯过一个低级错误——把VALID和READY的依赖关系搞反了。结果仿真时一切正常,上板后偶尔死机。后来发现是VALID在等待READY时才拉高,违反了协议规范。记住:VALID必须「主动拉高」,不能等READY。

4.3.4 AXI读写操作流程

读操作流程:

  1. 主设备在AR通道发出地址和突发信息
  2. 从设备接收后,开始准备数据
  3. 从设备在R通道返回数据,可以分多个周期
  4. 最后一个数据包带上RLAST信号

写操作流程:

  1. 主设备在AW通道发出地址
  2. 主设备在W通道发送数据,可以分多个周期
  3. 从设备接收完所有数据后,在B通道返回写响应
  4. 写响应表示数据已经写入,不是「准备写入」

你发现没有?AXI的读写流程是「解耦」的。地址和数据可以分开传输,甚至数据可以先于地址到达(只要从设备支持)。这种灵活性在高性能系统中非常有用。

4.4 AHB vs AXI:怎么选?

对比项 AHB AXI
最大频率 中等(通常≤200MHz) 高(可达1GHz+)
并发能力 半双工 全双工
乱序支持 不支持 支持
接口复杂度 简单(约20个信号) 复杂(约50个信号)
典型应用 MCU、低功耗设计 应用处理器、高速外设

我的建议:如果你的系统时钟低于100MHz,外设不多,用AHB就够了。如果要做高性能计算、视频处理、或者需要DMA频繁搬运数据,果断上AXI。别为了省事选AHB,后面性能不够再改架构,那代价就大了。

4.5 小结

总线协议这东西,光看文档是学不会的。我建议你找个开源的AHB或AXI接口代码,自己仿真跑一遍。看看波形,理解每个信号的变化。嗯,等你真正调通一次,就什么都明白了。

下一章咱们聊聊总线互联结构——怎么把多个主设备和从设备连起来,以及仲裁器、译码器这些「交通警察」是怎么工作的。