4、AXI总线协议(上):AXI通道介绍与握手规则

各位同学,今天我们来聊聊AXI总线协议。说实话,AXI是我在项目中打交道最多的总线协议之一。从早期的简单SoC到现在的服务器芯片,几乎每个项目都离不开它。我个人习惯把AXI看作是一套精密的"通信协议",它定义了主设备和从设备之间如何高效地传递数据。

嗯,咱们先从最基础的开始——AXI的五个独立通道。

4.1 AXI的五个独立通道

AXI协议最大的特点,就是采用了通道分离的设计。什么意思呢?就是把读操作和写操作完全分开,各自拥有独立的地址通道和数据通道。我刚开始接触时也觉得有点复杂,但用久了你会发现,这种设计对提升总线效率帮助巨大。

具体来说,AXI有五个通道:

  • 读地址通道(AR):发送读请求的地址和控制信息
  • 读数据通道(R):返回读取的数据和响应信号
  • 写地址通道(AW):发送写请求的地址和控制信息
  • 写数据通道(W):发送要写入的数据
  • 写响应通道(B):返回写操作的完成状态

关键点:读操作只需要两个通道(AR + R),写操作需要三个通道(AW + W + B)。为什么写多一个?因为写操作需要确认数据是否成功写入,这个确认信号就是通过B通道返回的。

你想想看,如果读和写混在一起,总线就得排队等待。现在分开了,读操作和写操作可以同时进行,互不干扰。我在项目中遇到过这样的情况:一个DMA控制器同时进行内存读和写,如果总线不支持分离通道,性能直接砍半。

4.2 读地址通道(AR)详解

读地址通道,说白了就是告诉从设备:"嘿,我想读这个地址的数据。"

AR通道的主要信号包括:

信号名 位宽 描述
ARADDR 32/64位 读操作的起始地址
ARLEN 8位 突发传输长度(实际传输次数 = ARLEN + 1)
ARSIZE 3位 每次传输的数据字节数(2^ARSIZE)
ARBURST 2位 突发类型:FIXED、INCR、WRAP
ARID 可配置 读事务ID,用于乱序返回
ARVALID 1位 主设备驱动,表示地址有效
ARREADY 1位 从设备驱动,表示可以接收地址

这里有个容易踩坑的地方——ARLEN。我记得刚做第一个AXI项目时,想发4次传输,结果ARLEN设成了4,实际发了5次。后来才反应过来,ARLEN的值是"传输次数减1"。你设成0就是1次传输,设成3就是4次传输。这个细节,我建议你记牢。

4.3 读数据通道(R)详解

读数据通道是从设备返回数据的通道。它和读地址通道是配对的——你发一个读请求,从设备就会通过R通道把数据送回来。

R通道的主要信号:

信号名 描述
RDATA 读取的数据,位宽与数据总线一致
RRESP 读响应状态:OKAY、EXOKAY、SLVERR、DECERR
RLAST 最后一次传输的指示信号
RID 与ARID匹配,用于识别属于哪个读事务
RVALID 从设备驱动,表示数据有效
RREADY 主设备驱动,表示可以接收数据

个人经验:RLAST信号非常关键。在突发传输中,RLAST拉高表示这是本次突发的最后一个数据。我曾经在调试一个DDR控制器时,发现读数据总是少一个,最后查出来是从设备没有正确拉高RLAST。嗯,这种问题用逻辑分析仪一抓就能看到。

4.4 写地址通道(AW)与写数据通道(W)

写操作比读操作多了一个通道,因为写数据需要和地址一起发送。但有意思的是,AW和W通道是独立的,它们可以同时发送,也可以先后发送。

AW通道的信号和AR通道几乎一样,只是前缀从AR变成了AW:

  • AWADDR:写操作的起始地址
  • AWLEN:写突发长度
  • AWSIZE:每次写的数据字节数
  • AWBURST:突发类型
  • AWID:写事务ID
  • AWVALID / AWREADY:握手信号

W通道则负责传输实际数据:

信号名 描述
WDATA 要写入的数据
WSTRB 写选通信号,每个bit对应一个字节,1表示该字节有效
WLAST 最后一次数据传输的指示
WVALID 主设备驱动,表示数据有效
WREADY 从设备驱动,表示可以接收数据

这里我要特别提一下WSTRB。这个信号很多人一开始不太在意,但它在实际项目中非常有用。比如你想写一个32位数据中的某个字节,WSTRB就可以精确控制哪些字节被写入。我曾经在调试一个PCIe控制器时,发现写数据总是错位,最后查出来是WSTRB的位宽配置错了。你想想看,如果WSTRB搞错了,数据写进去就是乱的。

4.5 写响应通道(B)

写响应通道是AXI写操作的最后一步。当从设备完成写操作后,会通过B通道返回一个响应状态。

B通道的信号很简单:

  • BRESP:写响应状态(OKAY、EXOKAY、SLVERR、DECERR)
  • BID:与AWID匹配
  • BVALID:从设备驱动,表示响应有效
  • BREADY:主设备驱动,表示可以接收响应

注意:写响应通道只返回一次,而不是每个数据返回一次。也就是说,一个突发写操作(比如4次传输),只会在最后返回一个B响应。这个和读操作不同,读操作每个数据都带RRESP。

为什么会这样设计?我个人理解是:写操作的数据是主设备主动发送的,从设备只需要在全部接收完后给个总结性的反馈。而读操作的数据是从设备返回的,每个数据都可能出错,所以需要逐个响应。

4.6 通道握手规则

AXI的每个通道都使用VALID-READY握手机制。这个机制说白了就是:发送方说"我有数据要发"(VALID拉高),接收方说"我准备好了"(READY拉高),双方一拍即合,数据就传过去了。

握手有三种情况:

  1. VALID先有效,READY后有效:发送方先准备好数据,等待接收方。这是最常见的情况。
  2. READY先有效,VALID后有效:接收方提前准备好,发送方数据就绪后立即传输。
  3. VALID和READY同时有效:双方同时准备好,一拍即合,效率最高。

这里有个重要的规则:VALID信号一旦拉高,必须保持到握手完成。也就是说,发送方不能随意撤销数据。而READY信号可以随时拉高或拉低,没有这个限制。

避坑指南:我曾经在一个项目中,设计了一个AXI从设备,它的READY信号在VALID到来之前就拉高了,但后来因为内部处理不过来,又把READY拉低了。结果主设备看到READY拉高就认为可以传输,数据发过来后发现READY又没了,导致数据丢失。嗯,从那以后我设计握手逻辑时,都会加一个状态机来保证READY的稳定性。

另外,AXI协议还支持依赖握手。什么意思呢?比如写操作中,W通道的数据必须在AW通道的地址之后发送,但协议允许它们同时发送。读操作中,R通道的数据必须在AR通道的地址之后返回。这些依赖关系是协议层面的约束,设计时一定要遵守。

4.7 通道间的依赖关系

最后,我们总结一下五个通道之间的依赖关系:

操作类型 依赖关系
读操作 R通道必须在AR通道握手完成后才能开始传输数据
写操作 W通道可以在AW通道之前或之后发送,但B通道必须在W通道的WLAST之后返回
跨事务 不同ID的事务之间没有依赖关系,可以乱序执行

你想想看,这种依赖关系设计得非常巧妙。它既保证了数据的一致性,又给了设计者足够的灵活性。比如写操作中,你可以先发地址再发数据,也可以先发数据再发地址,甚至同时发。这种灵活性在复杂系统中非常有用。

好了,这一章我们介绍了AXI的五个通道和握手规则。下一章我们会深入讲解AXI的突发传输、乱序传输和原子操作,这些都是服务器芯片设计中经常用到的特性。到时候我会结合一个实际的DMA控制器设计案例,带大家一步步实现一个完整的AXI接口。

课后思考:如果你要设计一个AXI从设备,当收到一个读请求时,从设备需要等待几个周期才能返回数据。你会如何设计VALID和READY的时序?是让ARREADY立即拉高,还是等数据准备好再拉高?这两种方式各有什么优缺点?