4. 突发传输:FIXED/INCR/WRAP三种突发类型、地址计算、突发长度与大小

好,咱们今天聊聊AXI总线里最核心的一个概念——突发传输。

说白了,突发传输就是一次握手,传一堆数据。你想想看,如果每次传一个数据都要重新走一遍地址握手,那效率得多低?我早年做第一个DMA控制器的时候,就因为没用好突发,性能直接腰斩。嗯,从那以后,我对突发传输就格外上心。

4.1 三种突发类型:FIXED、INCR、WRAP

AXI协议定义了三种突发模式。我个人习惯把它们叫做“原地踏步”、“步步高升”和“循环往复”。

4.1.1 FIXED 突发(固定地址)

FIXED模式,每次传输都访问同一个地址。听起来有点奇怪对吧?

其实它很有用。我在项目中遇到过FIFO的读写场景——你往同一个地址写数据,数据自动压入FIFO。这时候用FIXED突发就非常合适。

特点: 地址不变,每次传输都打在同一个点上。
我的经验: 配置寄存器时也可以用FIXED。但要注意,有些从机不支持FIXED模式,用之前一定要看手册。

4.1.2 INCR 突发(递增地址)

INCR是最常用的模式。地址依次递增,递增步长就是传输大小(Size)。

比如你从地址0x1000开始,每次传4字节(Size=4),那么地址就是0x1000、0x1004、0x1008……

我做过一个图像处理加速器,从DDR里读一帧图像,用的就是INCR突发。一次突发读一整行,效率非常高。

地址计算公式:
Address_N = Start_Address + N * (2^Size)
其中N从0开始,到Burst_Length-1结束。

4.1.3 WRAP 突发(回环地址)

WRAP模式,说白了就是INCR的“循环版”。地址递增到某个边界后,自动跳回起始地址。

为什么会这样?因为缓存行(Cache Line)的填充就是典型应用。比如一个64字节的缓存行,你从偏移0x30开始读,读到0x3C后,下一个地址应该是0x40,但WRAP模式会把它拉回0x00。

我曾经踩过的坑: WRAP突发的地址必须对齐到“总传输大小”。总传输大小 = Burst_Length × (2^Size)。比如长度4、大小4字节,总大小16字节,起始地址必须是16字节对齐的。否则,从机可能直接给你返回错误。

4.2 突发长度与突发大小

这两个参数决定了你一次突发能传多少数据。

参数 含义 取值范围
Burst Length 一次突发中传输的数据拍数 1~16(INCR/WRAP),1~16(FIXED)
Burst Size 每拍传输的字节数 1、2、4、8、16、32、64、128字节

注意,INCR模式支持更长的突发(最高256拍),但FIXED和WRAP最多16拍。我建议你设计时尽量控制在16拍以内,兼容性最好。

小技巧: 突发大小不能超过数据总线的宽度。比如64位总线,最大Size就是8字节。你非要用16字节,从机只能给你返回DECERR。

4.3 地址计算实战

咱们直接看代码。下面是一个地址计算的示例,用C语言风格写的。

// 假设:起始地址 0x1000,突发长度 4,突发大小 4字节
uint64_t start_addr = 0x1000;
uint8_t  burst_len  = 4;    // 4拍
uint8_t  burst_size = 2;    // 2^2 = 4字节

// INCR模式地址计算
for (int i = 0; i < burst_len; i++) {
    uint64_t addr = start_addr + (i << burst_size);
    printf("Beat %d: 0x%lx\n", i, addr);
}
// 输出:
// Beat 0: 0x1000
// Beat 1: 0x1004
// Beat 2: 0x1008
// Beat 3: 0x100c

// WRAP模式地址计算
uint64_t wrap_boundary = burst_len << burst_size;  // 16字节
uint64_t wrap_mask = wrap_boundary - 1;             // 0xF
for (int i = 0; i < burst_len; i++) {
    uint64_t offset = i << burst_size;
    uint64_t wrapped_offset = (offset + (start_addr & wrap_mask)) & wrap_mask;
    uint64_t addr = (start_addr & ~wrap_mask) | wrapped_offset;
    printf("Beat %d: 0x%lx\n", i, addr);
}
// 输出(假设起始地址0x100C):
// Beat 0: 0x100C
// Beat 1: 0x1000
// Beat 2: 0x1004
// Beat 3: 0x1008
核心要点: WRAP模式的关键是“边界对齐”。起始地址的低位决定了你在环内的起始位置,高位决定了环的基地址。

4.4 知识体系图

下面我用一张SVG图来总结本章的核心逻辑。

AXI突发传输知识体系 FIXED 突发 地址固定不变 INCR 突发 地址递增 WRAP 突发 地址回环 核心参数 突发长度 (Burst Length) | 突发大小 (Burst Size) | 地址计算 地址计算 INCR: Start + N*Size | WRAP: 边界对齐 + 环内偏移 典型应用:FIFO访问 | 图像行读取 | Cache Line填充

4.5 避坑指南

最后,我总结几个实战中容易踩的坑。

  • 地址对齐: 起始地址必须对齐到传输大小。比如Size=8字节,地址必须是8的倍数。否则,从机可能直接给你返回SLVERR。
  • WRAP边界: 总传输大小必须是2的幂次,且起始地址对齐到总大小。我当年做缓存控制器时,就因为地址没对齐,调试了整整两天。
  • 突发长度限制: FIXED和WRAP最多16拍。如果你需要更长的突发,考虑拆分成多个。
  • 从机能力: 不是所有从机都支持FIXED模式。用之前一定要看从机的数据手册。
我曾经犯过的错: 有一次做视频处理加速器,我用INCR突发读图像数据,突发长度设成了256。结果从机(DDR控制器)只支持16拍,直接给我返回了DECERR。从那以后,我设计时都会把突发长度控制在16以内,兼容性最好。

嗯,突发传输的内容就这些。记住,FIXED用于FIFO,INCR用于顺序访问,WRAP用于缓存行。地址计算时注意对齐和边界。把这些搞明白了,AXI总线就算入门了。

可可精品资料库