第1章:突发传输基础 — 为什么你的AXI总线跑不快?

大家好,我是老李。做FPGA这行十几年了,调试过的AXI总线问题少说也有上百个。今天咱们聊聊突发传输,这是AXI协议最核心、也最容易踩坑的地方。

说白了,突发传输就是一次握手,传一堆数据。你想想看,如果每次传一个数据都要走一遍地址握手、数据握手,那效率得多低?AXI的设计哲学就是:地址通道只管发一次地址,数据通道哗啦啦地传一串数据。嗯,这就是突发传输的由来。

1.1 突发类型:三种玩法,各有千秋

AXI定义了三种突发类型,我习惯用「固定、递增、回绕」来记它们。咱们一个一个看。

FIXED(固定突发)

每次传输,地址都不变。说白了就是对着同一个地址反复读写。什么场景用?我举个例子:你在写一个FIFO,每次写数据都往同一个端口怼,地址不需要变。或者操作状态寄存器,也是固定地址。

核心要点:FIXED模式下,地址只发一次,后续传输地址不变。适合FIFO、寄存器这类操作。

INCR(递增突发)

这个最常用。每次传输后,地址自动加上一个步长。步长等于突发大小(后面会讲)。比如你从地址0x1000开始,突发大小是4字节,那地址就是0x1000、0x1004、0x1008……依次递增。

我在项目中遇到过一个问题:有个同事写DMA控制器,INCR突发的地址计算搞错了,结果数据写到一半全乱了。后来发现是突发大小没对齐,地址跳错了位置。嗯,这个坑咱们后面细说。

WRAP(回绕突发)

这个稍微复杂点。地址递增到某个边界后,自动回绕到起始地址。说白了就是在一个固定大小的缓存区里循环读写。典型场景:Cache line fill、环形缓冲区。

WRAP突发的边界计算有个规律:起始地址必须对齐到(突发长度 × 突发大小)这个边界。比如突发长度是4,突发大小是4字节,那总传输量是16字节,起始地址必须16字节对齐。我曾经见过有人用WRAP突发传数据,起始地址没对齐,结果仿真就报错了。

注意:WRAP突发的突发长度只能是2、4、8、16。其他值?协议不支持,别想了。

1.2 突发长度:一次传多少笔数据?

突发长度就是一次突发传输中,总共要传多少笔数据。协议规定:

  • INCR突发:长度可以是1~256
  • FIXED突发:长度可以是1~16
  • WRAP突发:长度只能是2、4、8、16

你可能会问:为什么INCR可以到256,WRAP只能到16?原因很简单:WRAP需要硬件维护回绕逻辑,长度太大,硬件开销受不了。我刚开始做设计时也觉得这个限制很烦,后来想想,Cache line一般也就16个word,够用了。

个人经验:实际项目中,INCR突发的长度我一般不超过64。为什么?因为总线仲裁粒度、FIFO深度、响应延迟这些因素会限制你。长度设太大,反而容易造成总线拥堵。你想想看,一个master占了总线传256笔数据,其他master得等到什么时候?

1.3 突发大小:每笔数据多大?

突发大小就是每笔传输的字节数。协议支持1、2、4、8、16、32、64、128字节。注意,这里说的是字节数,不是位宽。

举个例子:你的数据总线是64位(8字节),那突发大小可以设成8。如果总线是32位(4字节),突发大小设成4。当然,你也可以设成更小的值,比如总线64位但突发大小设成4,那每笔只传4字节,浪费了一半带宽。

数据总线位宽推荐突发大小说明
32位4字节刚好一个word
64位8字节刚好一个double word
128位16字节刚好一个quad word

嗯,这里要注意:突发大小不能超过数据总线的位宽。比如总线是32位,你设突发大小为8?协议不允许,因为一次传不了8字节。

1.4 地址计算:别算错了,否则数据全乱

地址计算是突发传输最容易出错的地方。咱们直接上公式:

第N笔传输的地址 = 起始地址 + N × 突发大小

对于WRAP突发:
  边界地址 = (起始地址 / (突发长度 × 突发大小)) × (突发长度 × 突发大小)
  第N笔地址 = 边界地址 + ((起始地址 - 边界地址 + N × 突发大小) % (突发长度 × 突发大小))

看着有点晕?我举个例子你就明白了。

例子:INCR突发

  • 起始地址:0x1000
  • 突发大小:4字节
  • 突发长度:8
  • 地址序列:0x1000, 0x1004, 0x1008, 0x100C, 0x1010, 0x1014, 0x1018, 0x101C

例子:WRAP突发

  • 起始地址:0x1004
  • 突发大小:4字节
  • 突发长度:4
  • 总传输量:16字节
  • 边界地址:0x1000(因为0x1004 / 16 = 100.25,取整后×16 = 0x1000)
  • 地址序列:0x1004, 0x1008, 0x100C, 0x1000(回绕了!)

我曾经踩过的坑:有一次做视频处理,用WRAP突发读行缓存。起始地址设成了0x1008,突发长度8,突发大小4。结果地址回绕后,读出来的数据全是乱的。查了半天才发现,起始地址没对齐到32字节边界(8×4=32)。从那以后,我写地址计算逻辑时都会加一个断言,检查对齐条件。

1.5 知识体系总览

下面这张图,把突发传输的核心知识点串起来了。我建议你保存下来,调试时对照着看。

AXI突发传输知识体系 突发类型 突发长度 突发大小 三种类型 • FIXED:地址不变 • INCR:地址递增 • WRAP:地址回绕 取值范围 • INCR:1~256 • FIXED:1~16 • WRAP:2/4/8/16 字节数 • 1/2/4/8/16/32/64/128 • 不能超过总线位宽 • 推荐与位宽一致 地址计算 = 起始地址 + N × 突发大小 ⚠ 常见陷阱 WRAP起始地址必须对齐到总传输量边界 | 突发大小不能超过总线位宽

1.6 实战建议

说了这么多,最后给几条实在的建议:

  1. 能用INCR就别用WRAP:WRAP的地址计算复杂,容易出错。除非你确实需要环形缓冲区,否则老老实实用INCR。
  2. 突发大小尽量等于总线位宽:这样带宽利用率最高。我见过有人用64位总线,突发大小设成1字节,结果带宽利用率只有1/8,惨不忍睹。
  3. 地址对齐检查不能省:在RTL代码里加断言,检查起始地址是否对齐到突发大小。这个习惯救过我很多次。
  4. 仿真时打印地址序列:我每次调试AXI,都会在仿真里把每笔传输的地址打印出来。肉眼扫一遍,地址对不对一目了然。

最后说一句:突发传输看着简单,但实际项目中80%的AXI问题都出在这里。地址算错、长度设错、类型用错,各种花式翻车。你把这章吃透了,后面学起来就轻松多了。

可可精品资料库