3. AXI握手协议:VALID/READY机制、握手依赖关系、传输完成条件
AXI总线最核心的机制,就是VALID和READY这对握手信号。说白了,它们就像两个人打电话——一个人说“我有话要说”(VALID),另一个人说“我准备好了听”(READY)。只有两边都准备好了,信息才能传过去。
我在项目中见过不少新手,上来就写AXI代码,结果仿真死活不通。最后发现,都是握手协议没搞明白。嗯,今天我们就把它彻底讲清楚。
3.1 VALID/READY基本握手规则
AXI的每个通道(地址、数据、写响应)都遵循同样的握手规则。规则其实就三条:
- VALID不能依赖READY:发送方可以随时拉高VALID,不需要等接收方准备好。这是协议明确规定的。
- READY可以等VALID:接收方可以在VALID拉高后再拉高READY,也可以提前拉高。两种都合法。
- 传输只在VALID和READY同时为高时发生:这是铁律,没有例外。
重要:一旦VALID拉高,就不能再拉低,直到握手成功。这是很多新手容易犯的错——以为可以反悔。不行!VALID必须保持稳定,直到READY也拉高,传输完成。
3.2 三种握手场景
实际项目中,握手有三种常见场景。我习惯把它们画成时序图来理解:
| 场景 | 描述 | 典型应用 |
|---|---|---|
| VALID先到 | 发送方先拉高VALID,接收方稍后拉高READY | 从设备处理速度慢于主设备时 |
| READY先到 | 接收方提前拉高READY,等待发送方拉高VALID | 从设备始终准备好接收数据时 |
| 同时到达 | VALID和READY在同一时钟沿同时拉高 | 零等待传输,性能最优 |
你想想看,第三种场景是不是最理想?没错,零等待传输是性能调优的目标之一。但实际中,从设备往往需要几个周期才能准备好,所以第一种场景更常见。
3.3 握手依赖关系——这个坑我踩过
AXI协议里有个容易忽略的点:通道间的握手依赖关系。说白了,就是不同通道的VALID和READY之间,存在隐形的先后顺序。
我曾经在一个项目中,设计了一个写数据通道,结果仿真时发现数据总是丢。查了两天才发现,是写地址通道和写数据通道的握手顺序搞反了。
避坑指南:我曾经在调试一个DMA控制器时,让写数据通道的VALID等写地址通道的READY。结果协议分析仪报错——这违反了AXI的依赖规则。正确的做法是:写地址和写数据通道可以独立握手,但写响应通道必须等写数据通道完成后才能开始。
具体来说,依赖关系是这样的:
- 读地址通道:独立,不依赖其他通道
- 读数据通道:必须等读地址通道握手完成后才能开始
- 写地址通道:独立,不依赖其他通道
- 写数据通道:独立,不依赖其他通道
- 写响应通道:必须等写地址和写数据通道都完成后才能开始
嗯,这里要注意:写地址和写数据通道是独立并行的。它们可以同时握手,也可以一先一后。但写响应必须等两者都完成。
3.4 传输完成条件
一个AXI传输什么时候算完成?很多人以为只要数据过去了就行。其实没那么简单。
一个完整的AXI传输,需要满足三个条件:
- 地址通道握手成功:地址和控制信息已经传递给从设备
- 数据通道握手成功:所有数据(包括最后的last信号)已经传递完成
- 响应通道握手成功:从设备返回了BRESP或RRESP响应
对于突发传输(burst),数据通道的传输完成条件更严格:
- 每个数据节拍(beat)都需要VALID和READY同时为高
- 最后一个数据节拍必须同时拉高LAST信号
- 所有数据节拍完成后,才能开始响应通道的握手
小技巧:我习惯在验证环境中加一个断言,检查LAST信号是否在最后一个数据节拍时拉高。这个断言帮我抓到了至少三个bug。你可以在自己的testbench里试试。
3.5 握手协议的核心逻辑图
下面我用一张流程图,把整个握手协议的知识体系串起来。这张图是我自己总结的,每次带新人时都会拿出来讲一遍。
这张图的核心逻辑很简单:VALID和READY必须同时为高,传输才能发生。但实际项目中,你还要考虑通道间的依赖关系。我建议你在写RTL代码时,先把这张图的逻辑理清楚,再动手写代码。
3.6 实战中的几个要点
最后,分享几个我在项目中总结的要点:
- 不要用组合逻辑产生VALID:VALID应该由寄存器输出,否则时序容易出问题。我见过有人用组合逻辑,结果后仿时一堆setup违例。
- READY可以提前拉高:如果从设备始终能接收数据,READY可以一直拉高。这样主设备发数据时就能零等待传输。
- 小心死锁:如果两个模块互相等待对方的VALID和READY,就会死锁。我曾经在一个多主设备系统中遇到过,最后加了一个超时机制才解决。
- 验证时覆盖所有握手场景:三种握手场景都要验证到。我习惯在testbench里用约束随机,确保三种场景都能覆盖。
个人习惯:我写AXI从设备时,会先让READY默认拉高,然后根据内部状态再拉低。这样大部分传输都能零等待,性能最好。只有在FIFO快满时,才拉低READY进行反压。
好了,AXI握手协议就讲到这里。记住三条规则、三种场景、五个依赖关系,你就能搞定大部分AXI设计问题了。