4. AXI传输事务:突发传输、非对齐传输、窄传输与原子访问
各位同学,今天我们来啃一块硬骨头——AXI总线的传输事务。说实话,我刚接触AXI协议那会儿,看到这些术语头都大了。什么INCR、WRAP、窄传输、原子访问……感觉像在看天书。但后来在实际项目中踩过几次坑,才真正理解这些设计背后的用意。
这一节,我会把我在项目中积累的经验揉碎了讲给你听。咱们不搞那些虚的,直接上干货。
4.1 突发传输:INCR、FIXED、WRAP
突发传输,说白了就是一次握手传一批数据。你想想看,如果每次传一个数据都要重新走一遍地址握手,那效率得多低?AXI协议设计了三种突发模式,我一个个说。
4.1.1 INCR(递增突发)
这是最常用的模式。每次传输后,地址自动递增。比如你从地址0x1000开始,传4个32位的数据,那地址就是0x1000、0x1004、0x1008、0x100C。
关键参数:
- ARLEN/AWLEN:突发长度(实际传输次数 = 长度 + 1)
- ARSIZE/AWSIZE:每次传输的字节数(2的幂次)
- ARBURST/AWBURST:突发类型(2'b01 表示 INCR)
我在项目中遇到过一个问题:有个同事把ARLEN设成了3,以为能传3个数据,结果只传了2个。为什么?因为ARLEN=3表示传4个数据(0到3共4次)。这个坑我踩过一次就再也没忘过。
4.1.2 FIXED(固定突发)
FIXED模式很有意思——地址不变。每次传输都访问同一个地址。你可能会问:这有什么用?
嗯,我举个例子。你在做DMA搬运数据时,如果源地址是FIFO,那每次读FIFO都会弹出新数据,但地址始终是同一个。这时候用FIXED就对了。
我的经验:FIXED模式在访问外设寄存器时特别有用。比如你要连续写一个控制寄存器的多个位域,用FIXED突发可以省去重复发送地址的开销。
4.1.3 WRAP(回卷突发)
WRAP模式是INCR的变种。当地址递增到边界时,它会自动回卷到起始地址。这个边界由突发长度和传输大小决定。
举个例子:你从地址0x1004开始,做4次32位传输(每次4字节),边界就是0x1000 + 4*4 = 0x1010。地址序列是:0x1004、0x1008、0x100C、0x1000。
注意:WRAP模式的起始地址必须对齐到边界。比如上面例子中,边界是0x1010,起始地址0x1004是合法的。但如果起始地址是0x1002,那就非法了。我曾经在调试一个Cache控制器时,就因为起始地址没对齐,导致WRAP行为完全乱套。
4.2 非对齐传输
AXI协议支持非对齐传输,也就是说起始地址不一定要对齐到传输大小。比如你从地址0x1001开始读4个字节,这在AXI上是允许的。
但要注意,非对齐传输会带来额外的复杂性。硬件需要把这次传输拆成多个对齐的传输。比如上面那个例子,实际会被拆成:
- 从0x1001读1个字节
- 从0x1002读2个字节
- 从0x1004读1个字节
我个人建议:除非必要,尽量使用对齐传输。非对齐传输不仅增加硬件复杂度,还可能影响性能。我在做视频处理加速器时,就因为非对齐访问导致带宽利用率下降了不少。
4.3 窄传输
窄传输,就是实际传输的数据宽度小于数据总线的宽度。比如你的数据总线是64位,但你只想传8位数据。
AXI通过WSTRB(写选通)信号来控制哪些字节是有效的。每个bit对应一个字节:
| WSTRB[7:0] | 有效字节 |
|---|---|
| 8'b00000001 | Byte 0 |
| 8'b00000011 | Byte 0-1 |
| 8'b11110000 | Byte 4-7 |
窄传输在访问外设时很常见。比如你有一个UART寄存器,它只有8位宽,但你用64位总线去访问它。这时候就要用窄传输,并且正确设置WSTRB。
避坑指南:我曾经在调试一个DMA控制器时,发现写数据总是出错。查了两天才发现,是WSTRB信号没有正确生成。记住:窄传输时,WSTRB必须精确指示哪些字节是有效的,不能多也不能少。
4.4 原子访问:独占访问与锁定访问
原子访问,说白了就是保证一组操作要么全部完成,要么全部不做。在多核系统中,这玩意儿特别重要。
4.4.1 独占访问(Exclusive Access)
独占访问通过一对操作实现:Load Exclusive(读独占)和Store Exclusive(写独占)。
流程是这样的:
- 主设备发送读独占请求(ARLOCK = 2'b01)
- 从设备返回数据,并记录这个地址被"监视"了
- 主设备发送写独占请求(AWLOCK = 2'b01)
- 从设备检查这个地址是否被其他主设备修改过
- 如果没被修改,写操作成功(RRESP = OKAY)
- 如果被修改了,写操作失败(RRESP = EXOKAY)
我在做多核处理器互连时,就大量使用了独占访问。比如实现自旋锁(spinlock),就是靠这个机制。
我的经验:独占访问失败后,软件需要重新执行整个读-修改-写流程。所以设计时要注意,不要让独占访问的临界区太长,否则性能会受影响。
4.4.2 锁定访问(Locked Access)
锁定访问比独占访问更"霸道"。它通过ARLOCK/AWLOCK = 2'b10来表示。一旦发起锁定访问,总线仲裁器会保证这个主设备连续完成一组传输,中间不会被其他主设备打断。
但说实话,我在实际项目中很少用锁定访问。为什么?因为它会阻塞总线,影响其他主设备的访问。而且很多现代系统设计更倾向于用独占访问来实现原子操作。
注意:锁定访问在AXI4中已经被标记为"不推荐使用"。如果你在做新设计,建议用独占访问替代锁定访问。我见过一些老代码还在用锁定访问,结果在AXI4互连上跑出了问题。
4.5 本章小结
好了,这一节的内容就到这里。我们讲了AXI传输事务的几个核心概念:
- 三种突发模式:INCR最常用,FIXED适合FIFO,WRAP适合Cache行填充
- 非对齐传输:能用但尽量别用
- 窄传输:注意WSTRB的正确设置
- 原子访问:独占访问是主流,锁定访问已过时
这些知识点,你在做AXI总线调试时一定会遇到。记住我踩过的那些坑,能帮你少走不少弯路。
可可精品资料库