2. AXI通道详解:读地址通道、读数据通道、写地址通道、写数据通道、写响应通道的信号与时序

AXI协议的核心,说白了就是五条独立通道。我刚开始接触时也觉得通道多、信号杂,但摸清规律后会发现——这五条通道就像五条并行的流水线,各干各的,互不干扰。

为什么这么设计?因为ARM要解决一个根本问题:高带宽、低延迟、乱序传输。你想想看,如果读写共用一条通道,那读请求就得等写请求完成,效率就下来了。AXI把地址、数据、响应全部分开,每个方向都有自己的专用通道。

五通道总览

  • 读地址通道(AR):Master发读请求,告诉Slave要读哪里、读多少
  • 读数据通道(R):Slave返回读数据,带响应状态
  • 写地址通道(AW):Master发写请求,告诉Slave写哪里、写多少
  • 写数据通道(W):Master发送要写的数据
  • 写响应通道(B):Slave返回写完成状态
AXI五通道结构图 AXI 五通道独立结构 Master (主设备) Slave (从设备) AR 读地址通道 R 读数据通道 AW 写地址通道 W 写数据通道 B 写响应通道 关键特点: • 五条通道完全独立,可并行工作 • 地址与数据分离,支持乱序传输 • 每个通道都有独立的握手信号(VALID/READY)

2.1 读地址通道(AR Channel)

读地址通道是Master发起读操作的起点。Master通过这个通道告诉Slave:我要读哪个地址,读多少数据。

我个人习惯把AR通道的信号分成两类:地址类和属性类。地址类决定"读哪里",属性类决定"怎么读"。

信号 位宽 描述
ARID 取决于系统 读事务ID,用于乱序标识
ARADDR 32/64 读起始地址
ARLEN 8 突发长度(实际传输次数 = ARLEN + 1)
ARSIZE 3 每拍数据字节数(2^ARSIZE)
ARBURST 2 突发类型:00=FIXED, 01=INCR, 10=WRAP
ARVALID 1 Master指示地址有效
ARREADY 1 Slave准备好接收地址

避坑提醒:我曾经在一个项目中,ARLEN设成了0,结果Slave只返回了一拍数据。后来查协议才发现,ARLEN=0表示只传输1次,ARLEN=7才表示传输8次。这个"减1"的坑,新手很容易踩。

握手时序很简单:Master拉高ARVALID,Slave拉高ARREADY,两者同时为高时,地址在时钟上升沿被采样。嗯,这里要注意——VALID不能依赖READY,但READY可以等VALID。

2.2 读数据通道(R Channel)

读数据通道是Slave返回数据的通道。和地址通道不同,数据通道是从Slave到Master的方向。

R通道的信号比AR通道多一个RLAST和RRESP。RLAST告诉Master"这是最后一拍",RRESP表示读操作的状态。

信号 位宽 描述
RID 同ARID 读事务ID,必须与ARID匹配
RDATA 8/16/32/64/128 读数据
RRESP 2 读响应:00=OKAY, 01=EXOKAY, 10=SLVERR, 11=DECERR
RLAST 1 最后一拍指示
RVALID 1 Slave指示数据有效
RREADY 1 Master准备好接收数据

读数据通道支持乱序返回。什么意思?就是Master发了两个读请求,Slave可以先返回第二个请求的数据。怎么区分?靠RID。RID必须和ARID一致,Master通过ID来匹配。

重要:RLAST信号只在突发传输的最后一拍拉高。如果ARLEN=3(4次传输),那么第4个R数据必须带RLAST=1。我曾经见过一个设计,RLAST在倒数第二拍就拉高了,结果Master只收了3拍数据就认为传输结束——数据丢了。

2.3 写地址通道(AW Channel)

写地址通道和读地址通道几乎一样,只是前缀从AR变成了AW。信号定义、位宽、握手方式完全一致。

为什么ARM要重复设计?说白了,就是为了让读写可以完全并行。你可以在同一个时钟周期内,通过AW通道发写请求,通过AR通道发读请求,Slave可以同时处理。

信号 位宽 描述
AWID 取决于系统 写事务ID
AWADDR 32/64 写起始地址
AWLEN 8 突发长度(实际传输次数 = AWLEN + 1)
AWSIZE 3 每拍数据字节数
AWBURST 2 突发类型
AWVALID 1 Master指示地址有效
AWREADY 1 Slave准备好接收地址

2.4 写数据通道(W Channel)

写数据通道是Master发送数据的通道。和读数据通道不同,W通道多了一个WSTRB信号——字节选通信号。

WSTRB是干嘛用的?举个例子:你想写一个32位数据,但只想修改低8位。WSTRB[3:0]中,WSTRB[0]=1表示第0字节有效,其他字节不变。这个功能在寄存器配置时特别有用。

信号 位宽 描述
WDATA 8/16/32/64/128 写数据
WSTRB WDATA/8 字节选通,每bit对应一个字节
WLAST 1 最后一拍指示
WVALID 1 Master指示数据有效
WREADY 1 Slave准备好接收数据

写数据通道的关键规则:

  • WLAST必须在最后一拍拉高,和RLAST类似
  • WSTRB为全0时,数据不会被写入——但传输仍然进行
  • 写数据可以和写地址同时发送,也可以先发地址再发数据

2.5 写响应通道(B Channel)

写响应通道是Slave告诉Master"写完了,结果如何"的通道。它只有三个信号:BID、BRESP、BVALID和BREADY。

信号 位宽 描述
BID 同AWID 写事务ID,必须与AWID匹配
BRESP 2 写响应:00=OKAY, 01=EXOKAY, 10=SLVERR, 11=DECERR
BVALID 1 Slave指示响应有效
BREADY 1 Master准备好接收响应

写响应通道只有一个响应,对应整个突发传输。也就是说,你发了8拍写数据,Slave只在最后返回一个B响应。这和读数据通道不同——读数据每拍都有RRESP。

个人经验:我调试过一个DMA控制器,写响应总是SLVERR。查了半天发现是地址越界了——DMA配置的地址超出了Slave的地址范围。BRESP=10(SLVERR)就是告诉你"地址不对,写失败了"。所以调试时,先检查BRESP,能省很多时间。

2.6 通道间的依赖关系

五条通道虽然独立,但存在逻辑依赖。我画个简单的依赖关系:

  • 读操作:AR通道 → R通道(必须先有地址,才有数据)
  • 写操作:AW通道 + W通道 → B通道(地址和数据都到了,才能返回响应)

注意,AW和W通道之间没有顺序要求。你可以先发地址再发数据,也可以先发数据再发地址,甚至可以同时发。Slave必须能处理这两种情况。

容易踩的坑:有些Slave设计假设地址先到,数据后到。如果Master先发了数据,这个Slave可能把数据丢掉。所以设计Slave时,一定要支持地址和数据乱序到达。我见过一个IP,因为没处理好这个顺序,导致系统跑着跑着就死机了。

2.7 握手协议:VALID/READY机制

所有通道都使用相同的握手协议:VALID/READY。这个机制保证了Master和Slave可以以各自的速度工作。

握手有三种情况:

  1. VALID先到,READY后到:Master先拉高VALID,Slave准备好后拉高READY,下一个时钟上升沿传输完成
  2. READY先到,VALID后到:Slave提前准备好,Master准备好后拉高VALID,立即传输
  3. 同时到达:VALID和READY在同一时钟周期拉高,立即传输

我个人习惯用第一种——Master先发请求,Slave慢慢处理。这样逻辑简单,不容易出错。

握手规则总结:

  • VALID拉高后,必须保持到握手完成(READY拉高)
  • READY可以提前拉高,也可以等VALID来了再拉高
  • 握手完成后,VALID和READY都可以拉低
  • 不允许VALID依赖READY——这是死锁的根源

好了,五条通道的信号和时序就讲到这里。记住一个核心思想:地址通道负责"说清楚要干什么",数据通道负责"把数据传过去",响应通道负责"告诉结果"。三条写通道配合完成写操作,两条读通道配合完成读操作,互不干扰。