4. AHB协议详解(上):AHB总线架构、AHB主从设备、AHB传输类型(SINGLE/INCR/WRAP)、AHB流水线操作

各位同学,欢迎来到AHB协议的深度解析。这一章我们重点聊聊AHB总线——AMBA家族里最核心、最常用的高性能总线。说实话,我做了十几年SoC设计,接触最多的就是AHB。无论是CPU访问内存,还是DMA搬运数据,背后都是AHB在默默工作。

AHB的全称是Advanced High-performance Bus。你想想看,为什么叫“高性能”?因为它支持流水线操作、突发传输,还能同时处理多个主设备。嗯,咱们一个一个来拆解。

4.1 AHB总线架构

AHB总线架构其实不复杂。我习惯把它想象成一个“中央枢纽”——所有高速设备都挂在这个枢纽上。典型的AHB系统包含以下几个部分:

  • AHB主设备(Master):发起传输的模块,比如CPU、DMA控制器
  • AHB从设备(Slave):响应传输的模块,比如SRAM、Flash、外设寄存器
  • AHB仲裁器(Arbiter):决定哪个主设备获得总线控制权
  • AHB译码器(Decoder):根据地址选择对应的从设备
  • AHB多路选择器(Mux):将选中的从设备数据路由回主设备

说白了,主设备想读写数据,先向仲裁器申请总线。仲裁器批准后,主设备发出地址和控制信号。译码器根据地址选中对应的从设备,然后数据就在主从设备之间流动。整个过程就像一场精心编排的交通调度。

核心要点:AHB总线采用共享总线架构,所有主从设备共用地址总线和数据总线。这意味着同一时刻只能有一个主设备占用总线。

我在项目中遇到过一个问题:两个高性能主设备同时请求总线,如果仲裁策略设计不好,低优先级的设备可能会被“饿死”。所以仲裁器的设计非常关键,后面我们会专门讲。

AHB总线架构示意图 Master 1 (CPU) Master 2 (DMA) Master 3 (GPU) 仲裁器 Arbiter 地址总线 (HADDR) + 控制信号 数据总线 (HWDATA/HRDATA) 译码器 Decoder Slave 1 (SRAM) Slave 2 (Flash) Slave 3 (Periph) 多路选择器 Mux 图例: 主设备 仲裁器 地址/数据总线 译码器 从设备 多路选择器

4.2 AHB主从设备

咱们来聊聊主设备和从设备的具体行为。我刚开始学AHB时,总觉得主设备和从设备就是“谁发起谁响应”这么简单。但实际项目中,细节远比想象中多。

4.2.1 主设备(Master)

主设备是总线的“发起者”。它负责:

  • 发起读写请求
  • 提供地址和控制信号
  • 写操作时提供数据
  • 响应从设备的等待和错误信号

主设备通过一组信号与总线交互:

信号名 方向 描述
HCLK 输入 总线时钟,所有操作同步于此
HRESETn 输入 复位信号,低电平有效
HADDR[31:0] 输出 32位地址总线
HWDATA[31:0] 输出 写数据总线
HRDATA[31:0] 输入 读数据总线
HWRITE 输出 写使能:1=写,0=读
HSIZE[2:0] 输出 传输大小:字节、半字、字等
HBURST[2:0] 输出 突发类型:SINGLE、INCR、WRAP等
HTRANS[1:0] 输出 传输类型:IDLE、BUSY、NONSEQ、SEQ
HREADY 输入 从设备准备好信号
HRESP[1:0] 输入 从设备响应:OKAY、ERROR、RETRY、SPLIT

个人经验:我习惯在设计主设备状态机时,把HREADY作为关键判断条件。如果HREADY为低,主设备必须保持当前地址和控制信号不变,直到从设备准备好。这个细节很容易被忽略,但一旦出错,整个总线就会乱套。

4.2.2 从设备(Slave)

从设备是总线的“响应者”。它负责:

  • 根据地址译码判断是否被选中
  • 执行读写操作
  • 通过HREADY控制传输节奏
  • 通过HRESP返回传输状态

从设备的核心信号包括:

  • HSELx:片选信号,由译码器产生
  • HREADYOUT:从设备输出的准备好信号
  • HRESP:响应信号

我曾经踩过一个坑:从设备的HREADY信号在复位后必须为高,否则总线会死锁。因为主设备在等待HREADY为高才能继续,如果从设备一直拉低HREADY,整个系统就卡住了。

4.3 AHB传输类型

AHB支持三种基本的传输类型:SINGLE、INCR和WRAP。这三种类型对应不同的应用场景。我个人觉得,理解它们的关键在于“地址变化规律”。

4.3.1 SINGLE传输

SINGLE就是单次传输。一次只传一个数据,地址不递增。说白了就是“点对点”的读写。

// SINGLE传输示例
// 地址:0x1000,传输一个字
HADDR = 0x1000;
HWRITE = 1;      // 写操作
HSIZE = 0b010;   // 字传输(4字节)
HBURST = 0b000;  // SINGLE
HTRANS = NONSEQ; // 非连续传输
// 一个时钟周期后,数据写入0x1000

SINGLE传输适用于访问寄存器、状态寄存器等不需要连续地址的场景。

4.3.2 INCR传输(增量突发)

INCR是增量突发传输。地址在每个节拍后递增,递增步长由HSIZE决定。INCR又分为INCR4、INCR8、INCR16和未指定长度的INCR。

HBURST[2:0] 类型 长度 地址变化
000 SINGLE 1 不变
001 INCR 未指定 递增,直到主设备停止
010 WRAP4 4 回环
011 INCR4 4 递增
100 WRAP8 8 回环
101 INCR8 8 递增
110 WRAP16 16 回环
111 INCR16 16 递增
// INCR4传输示例(字传输)
// 起始地址:0x1000
// 传输4个字:0x1000, 0x1004, 0x1008, 0x100C
HADDR = 0x1000;  // 第一个节拍
HADDR = 0x1004;  // 第二个节拍
HADDR = 0x1008;  // 第三个节拍
HADDR = 0x100C;  // 第四个节拍

INCR传输非常适合访问连续内存区域,比如DMA搬运数据、CPU执行代码等。

4.3.3 WRAP传输(回环突发)

WRAP是回环突发传输。地址递增到边界后,自动回绕到起始地址。边界由突发长度和传输大小决定。

举个例子:WRAP4传输,字传输(4字节),起始地址0x100C。边界计算如下:

  • 突发长度=4,传输大小=4字节,所以边界=4*4=16字节
  • 起始地址0x100C,对齐到16字节边界是0x1000
  • 地址序列:0x100C → 0x1010 → 0x1014 → 0x1000(回环)
// WRAP4传输示例
// 起始地址:0x100C
// 传输4个字:0x100C, 0x1010, 0x1014, 0x1000
HADDR = 0x100C;  // 第一个节拍
HADDR = 0x1010;  // 第二个节拍
HADDR = 0x1014;  // 第三个节拍
HADDR = 0x1000;  // 第四个节拍(回环)

注意:WRAP传输的起始地址必须与边界对齐。如果起始地址不对齐,从设备的行为是未定义的。我曾经在项目中因为地址计算错误,导致WRAP传输读回了错误的数据,排查了整整两天才发现是地址对齐的问题。

WRAP传输常用于Cache line fill操作。Cache一次加载一整行数据,地址回环正好符合Cache的行结构。

4.4 AHB流水线操作

AHB最牛的地方就是流水线操作。它把地址阶段和数据阶段分开,让总线可以同时处理多个传输。你想想看,这就像工厂的流水线——上一个产品还在组装,下一个产品的零件已经开始准备了。

AHB的流水线分为两个阶段:

  • 地址阶段(Address Phase):主设备输出地址和控制信号
  • 数据阶段(Data Phase):从设备返回数据或接收数据

关键点:地址阶段和数据阶段相差一个时钟周期。也就是说,当前传输的数据阶段,正好是下一个传输的地址阶段。

// AHB流水线时序示例
// 时钟周期1:传输A的地址阶段
// 时钟周期2:传输A的数据阶段 + 传输B的地址阶段
// 时钟周期3:传输B的数据阶段 + 传输C的地址阶段

// 伪代码表示
always @(posedge HCLK) begin
  if (HREADY) begin
    // 当前传输完成,准备下一个
    current_addr <= next_addr;
    current_data <= next_data;
  end
end

流水线操作的好处是提高了总线利用率。如果没有流水线,每个传输需要两个时钟周期(一个地址+一个数据)。有了流水线,平均每个传输只需要一个时钟周期(地址和数据重叠)。

核心要点:流水线操作依赖于HREADY信号。如果从设备需要插入等待周期,它会在数据阶段拉低HREADY。此时,地址阶段也会被冻结——下一个传输的地址必须保持,直到当前传输完成。

我记得有一次调试一个AHB接口的IP,发现总线吞吐率上不去。后来用示波器抓波形,发现从设备的HREADY经常被拉低,导致流水线被打断。优化了从设备的响应速度后,吞吐率提升了30%。

嗯,这一章的内容就到这里。AHB协议还有很多细节,比如仲裁机制、SPLIT传输、错误处理等,我们下一章继续聊。

避坑指南:我曾经在设计AHB从设备时,忘记处理HTRANS=BUSY的情况。结果主设备插入BUSY周期时,从设备误以为传输结束,导致数据丢失。记住:从设备必须正确处理所有HTRANS类型,包括IDLE和BUSY。


公众号:蓝海资料掘金营,微信deep3321