第4章:AHB总线握手机制详解

各位同学,今天我们来聊聊AHB总线的握手机制。说实话,AHB的握手协议是我在项目中打交道最多的,也是很多新人容易踩坑的地方。你想想看,一个SoC里那么多master和slave,它们怎么协调工作?靠的就是这套握手信号。

4.1 核心信号概览

AHB的传输过程,说白了就是master和slave之间的一场「对话」。master负责发起请求,slave负责响应。我习惯把信号分成两组来看:

  • 控制信号组:HADDR、HWRITE、HTRANS、HSIZE、HBURST等
  • 握手信号组:HREADY、HRESP、HCLK

嗯,这里要注意,HREADY这个信号比较特殊——它既是master的输入,也是slave的输出。我刚开始做设计时,就因为这个双向理解不到位,吃过不少苦头。

4.2 地址相位与数据相位

AHB的传输分为两个阶段:

阶段 信号 说明
地址相位 HADDR, HWRITE, HTRANS master在时钟上升沿发出地址和控制信息
数据相位 HWDATA, HRDATA, HREADY slave通过HREADY控制数据是否被采样

我个人习惯把地址相位看作「敲门」,数据相位看作「进门」。你敲了门,但主人不一定马上开门——这就是HREADY的作用。

4.3 HREADY的握手逻辑

HREADY是AHB握手的核心。它由slave驱动,告诉master:

  • HREADY=1:当前传输完成,可以继续下一笔
  • HREADY=0:请等待,我还没准备好

我在项目中遇到过这样一个案例:一个外设的读操作需要3个时钟周期才能返回数据。如果HREADY一直拉高,master会认为数据已经有效,结果采到的全是垃圾。正确的做法是:

// 伪代码示例:slave的HREADY生成逻辑
always @(posedge HCLK or negedge HRESETn) begin
  if (!HRESETn)
    HREADY <= 1'b1;
  else if (HSEL && HTRANS != IDLE)
    // 需要等待3个周期
    HREADY <= (wait_cnt == 2'd3) ? 1'b1 : 1'b0;
  else
    HREADY <= 1'b1;
end

你想想看,如果这里处理不好,整个总线的时序都会乱掉。我曾经调试过一个bug,就是slave的HREADY在复位后没有及时拉高,导致第一个传输永远无法完成。

4.4 HRESP响应机制

HRESP只有两位,但含义丰富:

HRESP[1:0] 含义 说明
00 OKAY 传输正常完成
01 ERROR 传输出错
10 RETRY 重试(slave忙,但未占用总线)
11 SPLIT 拆分(slave忙,且释放总线)

这里有个容易混淆的点:RETRY和SPLIT的区别。说白了,RETRY是slave说「我现在没空,你过会儿再来问」,而SPLIT是「我现在没空,你先去干别的,我好了通知你」。我建议初学者先掌握OKAY和ERROR,RETRY和SPLIT可以后面再深入。

4.5 握手时序图

下面我用一张SVG图来展示典型的AHB握手过程。这张图我画了很多遍,每次给新人讲都靠它。

AHB总线握手时序图 HCLK T1 T2 T3 T4 T5 HADDR Addr1 Addr2 HWRITE Read Write HTRANS NONSEQ NONSEQ HREADY 1 0 1 HRESP OKAY OKAY Data Data1 Data2 地址相位 等待 地址相位 数据相位

从这张图你能看到:第一笔传输的地址在T1发出,但slave在T2把HREADY拉低了,所以数据相位被延长到T3。第二笔传输的地址在T3发出,数据在T4完成。这就是AHB的流水线特性——地址相位和数据相位可以重叠。

4.6 常见问题与避坑指南

⚠️ 我曾经踩过的坑:
  • HREADY默认值:复位后HREADY必须为1,否则第一个传输永远无法开始
  • IDLE传输:当HTRANS为IDLE时,slave必须无条件返回OKAY,不能插入等待
  • ERROR响应:slave返回ERROR时,HREADY必须同时为1,否则master会一直等待
💡 我的调试技巧:

在仿真时,我习惯把HREADY和HRESP放到波形的最上面。如果发现传输卡住了,先看HREADY是不是被某个slave拉低了,再看HRESP是不是返回了ERROR。80%的握手问题都能通过这两个信号定位。

4.7 多slave的仲裁与握手

当多个slave挂在总线上时,握手逻辑会复杂一些。每个slave都有自己的HREADY输出,但最终需要经过一个多路选择器:

// 多slave的HREADY合并逻辑
assign HREADY = (HSEL_slave0) ? HREADY_slave0 :
                (HSEL_slave1) ? HREADY_slave1 :
                (HSEL_slave2) ? HREADY_slave2 :
                1'b1;  // 未选中时默认拉高

这里有个细节:如果某个slave被选中但返回了ERROR,仲裁器需要知道这个错误来自哪个slave。我建议在设计中给每个slave分配一个唯一的ID,这样调试时能快速定位问题。

4.8 总结

AHB的握手机制,说白了就是master和slave之间的一套「礼仪规范」。master负责发起请求,slave通过HREADY控制节奏,通过HRESP反馈状态。掌握了这套机制,你就能理解为什么AHB能做到高吞吐、低延迟。

嗯,最后说一句:如果你在项目中遇到握手相关的问题,不妨先画一张时序图,把每个时钟周期的信号状态标出来。这个方法我用了十年,屡试不爽。

核心要点回顾:

  • HREADY=1表示传输完成,HREADY=0表示等待
  • HRESP=00表示OKAY,01表示ERROR
  • 地址相位和数据相位可以流水线重叠
  • 多slave时注意HREADY的合并逻辑

可可精品资料库