4. 突发传输:AXI突发传输的基本概念

突发传输,说白了就是一次握手,传一堆数据。我刚开始接触AXI时,总觉得这玩意儿有点绕。后来做项目多了,才发现它其实是总线效率的灵魂。

你想想看,如果没有突发传输,每次读写都要单独发地址、等握手,那效率得多低?AXI的突发机制,就是让你发一次地址,然后连续传多个数据。嗯,这里要注意,地址通道和数据通道是分开的,所以可以流水线操作。

4.1 什么是突发传输?

突发传输的核心思想很简单:一次地址请求,多次数据传输。

举个例子,你想从地址0x1000开始读4个32位的数据。如果没有突发,你得发4次读地址、等4次读数据。有了突发,你只需要发一次地址(0x1000),然后连续收4个数据回来。

我个人习惯把突发长度(Burst Length)和突发大小(Burst Size)放在一起看。突发长度就是一次传多少笔数据,突发大小就是每笔数据有多少字节。两者相乘,就是一次突发传输的总数据量。

关键参数:

  • ARLEN/AWLEN:突发长度,实际传输笔数 = ARLEN + 1
  • ARSIZE/AWSIZE:突发大小,每笔数据的字节数(1、2、4、8字节等)
  • ARBURST/AWBURST:突发类型,决定地址如何变化

我在项目中遇到过一个问题:有人把ARLEN设成了3,以为传3笔数据。结果只传了3笔,少了一笔。为什么?因为ARLEN=3表示传4笔(0、1、2、3)。这个坑我踩过,所以现在每次配置都会加1再检查一遍。

4.2 三种突发类型

AXI定义了三种突发类型,分别是FIXED、INCR和WRAP。它们决定了每次传输后地址怎么变。

突发类型 编码 地址变化方式 典型应用场景
FIXED 00 地址不变 FIFO、状态寄存器
INCR 01 地址递增 内存连续读写、DMA
WRAP 10 地址递增,到边界回绕 Cache line fill、缓存行操作

4.3 FIXED:固定地址突发

FIXED突发,地址从头到尾都不变。每次传输都访问同一个地址。

这玩意儿什么时候用?我告诉你,最典型的就是访问FIFO。FIFO的读端口只有一个地址,你读一次,数据出来,地址还是那个地址。再读一次,数据又出来,地址还是不变。

还有状态寄存器。比如你想连续读某个状态寄存器的值,用FIXED突发就很合适。每次读的都是同一个寄存器,但数据可能因为硬件状态变化而不同。

小技巧:FIXED突发时,数据顺序很重要。比如你写FIFO,第一笔数据是第一个字,第二笔是第二个字。如果顺序搞反了,数据就乱了。我一般会在RTL里加个计数器,确保数据顺序和预期一致。

4.4 INCR:增量地址突发

INCR突发是最常用的类型。每次传输后,地址增加一个突发大小(ARSIZE)。

比如你从0x1000开始,ARSIZE=4(4字节),突发长度=4。那么地址变化是:

第1笔:0x1000
第2笔:0x1004
第3笔:0x1008
第4笔:0x100C

说白了,就是连续的内存地址。DMA传数据、CPU读内存、写帧缓冲,基本都是INCR。我做过一个视频处理的项目,从DDR读图像数据,用的就是INCR突发。一次读64字节,效率比单次读写高了好几倍。

这里要注意,INCR突发的地址可以跨4KB边界吗?嗯,AXI协议允许,但很多从设备不支持。我建议你设计时尽量让突发不跨4KB边界,否则可能会触发从设备的地址对齐错误。

避坑指南:我曾经遇到一个bug,INCR突发的起始地址没有对齐到突发大小。比如ARSIZE=8(8字节),但起始地址是0x1004。结果从设备返回的数据全是乱的。后来查协议才发现,INCR突发的起始地址必须对齐到ARSIZE。这个坑,我劝你别踩。

4.5 WRAP:回绕地址突发

WRAP突发,名字就说明了它的特点:地址递增,但到了边界就绕回来。

这个边界怎么算?边界 = 突发长度 × 突发大小。比如突发长度=4,突发大小=4字节,那么边界就是16字节。地址从起始地址开始,递增到边界-1,然后绕回起始地址。

举个例子,起始地址0x100C,突发长度=4,突发大小=4字节:

第1笔:0x100C
第2笔:0x1010  (注意,这里到了边界?不,边界是0x100C + 16 = 0x101C)
第3笔:0x1014
第4笔:0x1018
等等,不对。让我重新算一下。

正确示例:
起始地址:0x100C
突发长度:4(传4笔)
突发大小:4字节
边界 = 4 × 4 = 16字节
地址范围:0x100C ~ 0x101B(共16字节)

第1笔:0x100C
第2笔:0x1010
第3笔:0x1014
第4笔:0x1018
没有回绕?嗯,因为起始地址0x100C + 16 = 0x101C,而0x1018还没到边界。

再换个例子:
起始地址:0x101C
突发长度:4
突发大小:4字节
边界 = 16字节
地址范围:0x101C ~ 0x102B

第1笔:0x101C
第2笔:0x1020
第3笔:0x1024
第4笔:0x1028
还是没有回绕?哦,我明白了。WRAP的回绕发生在地址达到边界时,但边界是起始地址对齐到突发总大小的结果。

让我重新说清楚:
WRAP的边界 = 起始地址对齐到(突发长度 × 突发大小)的地址。
比如起始地址0x101C,突发长度=4,突发大小=4,那么对齐到16字节边界就是0x1010。
地址范围:0x1010 ~ 0x101F(共16字节)

第1笔:0x101C
第2笔:0x1020 → 超过0x101F,回绕到0x1010
第3笔:0x1014
第4笔:0x1018

WRAP突发最常见的应用场景是Cache line fill。CPU从内存读一个缓存行,比如64字节。如果缓存行起始地址是0x1000,但CPU只想要0x101C开始的16字节,那就用WRAP突发,从0x101C开始读,绕回0x1000,正好读完整个缓存行。

核心区别总结:

  • FIXED:地址不变,适合FIFO、寄存器
  • INCR:地址递增,适合连续内存
  • WRAP:地址递增后回绕,适合缓存操作

4.6 如何选择突发类型?

我个人的经验是:

  • 如果访问的是FIFO或状态寄存器,用FIXED。别用INCR,否则地址会跑飞。
  • 如果访问的是连续内存(DDR、SRAM),用INCR。这是最通用的选择。
  • 如果做Cache控制器,用WRAP。但要注意,WRAP的突发长度只能是2、4、8、16,不能是其他值。

还有一个细节:INCR和WRAP的地址变化步长都是突发大小(ARSIZE),但WRAP多了边界回绕的逻辑。设计从设备时,WRAP的处理比INCR复杂一些,因为你要判断地址是否到了回绕点。

4.7 知识体系图

下面这张图展示了突发传输的核心概念和三种类型的区别:

AXI突发传输知识体系 突发传输核心 突发长度 (ARLEN) 突发大小 (ARSIZE) 突发类型 (ARBURST) FIXED (00) 地址不变 FIFO / 寄存器 INCR (01) 地址递增 内存连续读写 WRAP (10) 地址递增后回绕 Cache line fill 应用场景对比 FIXED → FIFO、状态寄存器、硬件加速器控制接口 INCR → DDR/SRAM读写、DMA传输、帧缓冲操作 WRAP → Cache line fill、缓存行预取、对齐数据块操作

这张图把突发传输的核心参数和三种类型的关系画清楚了。你设计时,先确定用哪种类型,再配好长度和大小,基本就稳了。

最后说一句:突发传输是AXI的精髓。我见过很多新手,一上来就只用INCR,遇到FIFO也硬上INCR,结果地址乱飞。其实FIXED和WRAP各有各的用处,选对了,性能能翻倍。选错了,debug能让你怀疑人生。

可可精品资料库