☰
AXI协议必知:Burst与Beat的区别、地址计算与总线调试要点
2026/10/19 10:57:04 网站建设 项目流程

在SoC设计里摸爬滚打这几年,AXI协议几乎是每天都要打交道的。之前带一个实习生调DMA搬运图像数据的用例,他对着波形图问我:“这明明是连续的几笔传输,为什么日志里写的是1个Burst,但波形上却有4个Beat?这两个到底啥关系?”这个问题看似基础,但确实把很多刚接触AXI的工程师绕晕了。Burst和Beat这两个词,在协议文档里反复出现,但如果你没在真实的总线波形里盯过它们,光看手册很容易把它们混为一谈。这篇就好好拆一拆这两个概念的区别,顺带把地址计算、边界判断、窄传输这些容易踩坑的细节一并捋清楚。

1. 先搞清楚两者的原始定义

1.1 从协议文档的字面意思看差距

AXI协议把一次完整的数据交换过程定义为一个交易(Transaction),而Burst就是构成这个交易的核心机制——它表示一次事务中,主设备连续发起的一组数据传输。Beat则更底层,它指的是一次单独的数据传输节拍,也就是在总线上完成一次握手(VALID和READY同时拉高)的那一拍。

换句话说,Burst描述的是“一组连续传输”的组织形式,Beat描述的是“一次实际数据搬移”的发生动作。一个Burst里可以有很多个Beat,比如AxLEN=3意味着这个Burst里有4个Beat。可以这么想:Burst像一列火车的整个班次,Beat就是这列火车里的一节车厢。火车班次决定起点站、终点站和有几个停靠点,而每一节车厢才是真正拉货的单元。

我见过有人把这两个词完全混着用,在代码注释里写“这个burst包含8个burst”,这种注释自己看着都别扭。协议文档明确区分了这三个层次:Transaction(事务)> Burst(突发传输)> Beat(节拍传输)。弄清这层包含关系,后面读任何AXI相关的IP文档、看总线波形、调性能计数器都会顺畅很多。

1.2 为什么协议要区分这两个概念

如果你只看功能,好像Beat才真正承载数据,Burst只是个“包装”。那协议为什么要单独定义Burst呢?因为总线不仅要传数据,还要传“关于数据的元信息”。

Burst这个层级携带了三个关键参数:长度(AxLEN,决定有几个Beat)、大小(AxSIZE,决定每个Beat传多少字节)、类型(AxBURST,决定地址怎么变化)。这三个参数组合起来,才能让从设备知道如何准备自己的存储空间,如何计算地址,如何校验接收完整性。

Beat这个层级则携带了实际的写数据信号WDATA、写数据有效信号WSTRB、读数据信号RDATA、还有最后的响应信号RESP。可以说Burst是“计划”,Beat是“执行”。没有计划,执行就是乱的;没有执行,计划就是空的。SoC设计里,你写总线主设备逻辑时,本质上是在规划Burst;写从设备接收逻辑时,本质上是处理一个个Beat。这两个视角必须同时把握,才不会出结构性bug。

2. Beat的细节:一次握手一次搬运

2.1 Beat里那些容易忽略的字段

一个Beat的读传输由AR握手和R握手共同定义。主设备发起AR通道的请求后,从设备在R通道上送回应数据,每个R通道的有效传输都算一个Beat。写传输则更复杂一些,分为写地址通道(AW)上的一个Burst请求,和写数据通道(W)上的多个数据节拍。关键点在于:一个Burst只在AW通道上出现一次地址请求,但在W通道上会出现AxLEN+1个数据节拍。

这里有一个特别容易误解的地方。很多人以为一个Burst里的多个Beat,每一拍都必须紧挨着,中间不能停。其实不是这样的。AXI协议允许每一拍之间有气泡(gap),只要VALID和READY没有同时拉高,总线就处于等待状态,不算完成一个Beat。所以从波形上看,一个Burst里的多个Beat不一定在时间上连续。但它要求地址变化逻辑上连续(固定、递增或回卷方式),数据通道的逻辑关系是连续的。

我在实际调试中见过一种情况:写通道的WVALID拉高后,从设备因为内部FIFO满了,把WREADY拉低,导致这一拍WVALID一直保持为高,直到WREADY重新拉高,握手成功才算这一Beat完成。这种情况下,这一个Beat可能被拉伸成很多个时钟周期。从功能仿真上看数据没错,但如果你用这个信号去做延迟估算,会得出完全错误的结论。

2.2 窄传输:Beat与Strobe的对应关系

再举一个Beat层面的经典细节——窄传输。假设数据总线是64位(8字节),但一个Beat只需要传输3个字节的有效数据。这时候数据总线并没有被全部占用,AXI通过WSTRB信号来表明哪几个字节通道是有效的。WSTRB是8 bit,每一位对应总线上一个字节,置1表示这一字节有效。

我调试过的一个图像缩放IP,输入像素格式是RGB888,一个像素3字节,但总线是128位。当时主设备发出的写请求,每个Beat的WSTRB都在不断跳变,有时候只写4个字节,有时候写8个字节。从设备的写FIFO必须严格按照WSTRB来拼接数据,一旦拼接逻辑没考虑strobe的边界,图像就会花屏。这个问题排查起来很折磨人,因为读回地址上的数据和写进去的期望数据对不上,但又不是每次都不对——只有行尾像素处理时才会错。

Beat层面的处理逻辑写起来琐碎,但恰恰是这些琐碎决定了一个总线IP能不能在真实场景里稳定运行。以后写RTL时,凡是处理写数据的模块,都要把WSTRB当成一等公民看待,不要只在地址对齐时才处理它。

3. Burst的核心机制:三个参数定乾坤

3.1 AxLEN、AxSIZE、AxBURST怎么配合

Burst这个层级最核心的就是三个信号:AxLEN(长度)、AxSIZE(大小)、AxBURST(类型)。AxLEN是8位,表示突发长度减1。AxSIZE是3位,表示每个Beat传输的字节数,以2的指数形式表达:000表示1字节,001表示2字节,010表示4字节,011表示8字节,以此类推。AxBURST是2位,决定地址如何变化,一共有三种类型:FIXED(固定地址)、INCR(递增地址)、WRAP(回卷地址)。

这三个参数之间的计算关系非常明确:

  • 一次Burst传输的总字节数 = (AxLEN + 1) × 2^AxSIZE
  • INCR类型的地址递增量 = 2^AxSIZE
  • FIXED类型的地址始终不变
  • WRAP类型有一个回卷上界,一旦地址到达上界,就回卷到起始地址对应的“基础地址”继续递增

举个实际例子:你要从某外设寄存器里连续读128字节数据,数据总线宽度设成64位,那么AxSIZE可以设成3(表示8字节),AxLEN设成15(表示16个Beat),这样总字节数 = 16 × 8 = 128字节。这个Burst走INCR类型,地址从起始位置开始,每个Beat增加8,连续增加16次。这个组合非常常见,几乎所有DMA搬数都是这类模式。

3.2 Burst边界与4KB保护

关于Burst边界,有一个资深工程师必须刻在脑子里的规则:任何Burst都不能跨越4KB地址边界。这是AXI协议的铁律,因为4KB正好是一个典型的内存页大小,也对应着大多数从设备(比如某些片上存储、外设寄存器区域)的地址窗口。如果让总线事务跨越4KB边界,就可能访问到完全不同的从设备区域,导致互联逻辑出大问题。

实操中,这意味着当你写DMA描述符或总线主设备逻辑时,必须做4KB边界检查。如果你的传输起始地址是0x1FF0,要给一个长度为128字节的Burst,那么0x1FF0到0x207F跨越了0x2000边界,这个Burst必须拆成两个:一个先从0x1FF0传到0x1FFF(16字节),另一个从0x2000传到0x207F(112字节)。不拆的话,很可能触发从设备报错或者数据错乱。

我记得有一次排查一个PCIe控制器下的DMA偶发卡死问题,最后定位到就是某个驱动配置的传输长度恰好让一次DMA跨过了4KB边界,从设备那边把这次访问当成了非法访问,直接不回应答,导致总线挂着。从那以后,我在所有DMA引擎的RTL前端都加了一个地址边界检测模块,逻辑不复杂,但能避免极难排查的死锁问题。

3.3 WRAP边界为什么让人犯晕

WRAP类型的Burst最容易被忽略,也最容易写错。它在图像处理领域很常用,典型场景就是cache line的填充或逐行处理。WRAP突发的特点是:地址曲线上有一个上界和一个下界,所有Beat的地址都约束在这个范围内,越界就回卷。

规定是这样:WRAP突发只能用在AxLEN为2、4、8、16等2的幂次的情况下,且突发的传输字节数不能超过这个“基础地址”的窗口大小。比如你设置AxSIZE=2(4字节),AxLEN=3(4个Beat),AxBURST=WRAP,那么这个Burst的总字节数是16字节,这16字节必须发生在16字节地址对齐边界内。起始地址可以是窗口内的任意4字节对齐位置,但如果地址算到窗口上界,下一个Beat就从窗口下界继续。

我踩过的一个坑是:在做图像行缓存操作时,给AXI从设备配置了WRAP突发,但起始地址设在了窗口的中间偏上位置,导致前面两个Beat正常,第三个Beat地址回卷后出现了一个很诡异的高位地址翻转。后来仔细看协议才知道,地址回卷不是简单的“回卷到窗口起点”,而是要在地址位宽内实现一种特定规则:如果窗口大小是16字节,地址的低4位到达0xF后再递增就变成0x0,而高位的地址保持不变。本质上这是低比特位的回卷,不是完整的地址回卷。搞清楚这个规则后,我又去检查了好几个WRAP相关的从设备实现,发现不少人在回卷逻辑上都有些小毛病。

4. 区别在哪里:Burst vs Beat的完整对照

4.1 一张表看清核心差异

为了让大家一目了然,我把这两个概念的核心差异整理成一张对照表:

对比维度Burst(突发传输)Beat(节拍传输)
层级事务层面的组织形式传输层面的单次动作
携带的核心信息传输长度、数据大小、地址增长方式实际数据、字节使能、握手信号
出现通道AW/AR通道(一个事务一次)W/R通道(一个事务多次)
地址变化决定整体增长策略每个Beat执行具体地址递进
波形特征对应一次完整的通道请求窗口对应一次VALID&READY同时拉高的时刻
寄存器状态通常由主设备状态机管理通常由从设备状态机逐拍处理
边界约束不得跨越4KB地址必须保持在Burst定义范围内
常见混淆点误以为一个Burst等于一拍误以为Beat之间必须无气泡

这张表我建议新手直接存下来,做总线级调试遇到概念混乱时,翻一翻就能快速定位自己到底是在说哪个层面的事情。比如你是看性能计数器的,那关注的永远是Burst的个数和Beat的总数;如果你是在看数据完整性,那就要逐Beat检查WSTRB和WDATA的匹配关系。

4.2 物理层、协议层、仿真层的三重理解

除了这张表,我更想强调的是三个不同视角下的理解。

在物理层的视角下,Burst并不真实存在于时序中,真实存在于时序里的只有一个个握手后的Beat。你拿逻辑分析仪抓总线波形时,看到的其实是一连串的VALID/READY握手,Burst只是你在事后通过地址变化规律反推出来的一个逻辑单位。用调试工具看波形时,那些标注为“Burst”的框,本质上是工具根据地址是否连续、通道请求是否相邻,把多个Beat聚合成了一个显示单位。

在协议层的视角下,Burst却是实实在在存在的事务单位。从设备处理完最后一个Beat之后,要么产生写响应(B通道),要么通过RLAST向主设备标出最后一个读Beat。RLAST这个信号值得注意:它在读数据通道上,标志着一个Burst的最后一个读Beat。也就是说,从设备需要知道自己当前处理的Beat是不是这个突发请求中的最后一拍,这直接影响它是否需要在B通道上给出响应,或者在R通道上完成最后一次数据返回。你处理一个锁页(lock)防护逻辑,也需要知道当前事务什么时候结束。这就是Burst在协议层发挥的作用。

在仿真层的视角下,两者的意义又不同。写testbench时,我们通常按照Burst来生成激励,比如用UVM的sequence发起一个“ INCR 长度16 ”的burst请求,但在scoreboard检查数据时,必须按照Beat来逐拍比对,特别是要处理乱序返回(out-of-order)的情况。如果不搞清楚这两个层级,连testbench里的回调函数都写不对——你会不知道该在哪个回调里比对地址、在哪个回调里比对数据。

5. 实战中的经验与踩坑记录

5.1 地址计算的经验法则与4KB拆分技巧

先分享一个我在项目中反复使用的地址计算流程。当你要发起一次性搬运N字节的DMA请求时,不要直接设一个大Burst完事,而是要分三步走:

第一步,对齐检查。计算起始地址和传输长度的边界对齐情况。如果起始地址不是AxSIZE所代表字节数的整倍数,就得拆分。比如AxSIZE=3表示每个Beat 8字节,起始地址必须是8字节对齐。不对齐就会出问题,没有例外。

第二步,4KB检查。估算总传输字节数,看从起始地址开始是否会跨4KB边界。如果跨了,按4KB边界拆成两个Burst,并重新计算第二个Burst的AxLEN。

第三步,算AxLEN。每个Burst的剩余字节数除以每个Beat的字节数,再减1,得到AxLEN。举个例子,假设64位总线,起始地址0x2018,搬运128字节,AxSIZE=3。检查发现第一个Burst从0x2018到0x2FFF,跨了4KB边界,所以第一个Burst只能传0x2018到0x2FFF,这刚好是8字节对齐的(0x2018到0x2FFF是0xFE8字节,不对齐?其实0x2018的8字节对齐点就是0x2018本身,后面每步8字节,到0x2FF0+7=0x2FF7之间,下一个8字节就跨边界了,所以传多少个Beat取决于从0x2018开始到0x2FF7有多少个8字节窗口——精确说,是从0x2018递增8,直到不超过0x2FFF。也就是 (0x2FFF - 0x2018 + 1) / 8 = 0x7E8 / 8 = 0xFD = 253个Beat。不过实际上0x2FFF不是对齐端,所以搬完253个Beat后,最后一个地址是0x2018 + 252×8 = 0x2018 + 1260 = 0x2FCC,超过0x2FFF了吗?0x2018+1260=0x2FCC,没有超过0x2FFF,但下一个Beat地址是0x2FD4,还是没超过?0x2FD4小于0x3000但是距离0x3000还差0x2C字节,等等,我需要仔细算一下。0x2FFF到0x3000边界,从0x2018开始的8字节窗口,序号n,地址=0x2018+8n,需要小于0x3000,即0x2018+8n < 0x3000,所以8n < 0xFE8,n < 0x1FD/8? 0xFE8/8 = 0x1FD = 509,所以n最大508,也就是509个Beat。最后一个Beat地址是0x2018+8×508 = 0x2018+0xFE0 = 0x2FF8,传输8字节到0x2FFF,恰好不跨边界。所以第一个Burst AxLEN=508,传了508×8=4064字节?不对,509个Beat就是 AxLEN=508,传509×8 = 4072字节。从0x2018到0x2FFF总共0xFE8=4072字节。这才第一个Burst。第二Burst从0x3000开始,总长度128字节的剩余呢?如果总共只要搬128字节,其实就不需要拆了!啊,我举的例子数字有点大。重新来:起始地址0x2018,搬运128字节,64位总线,AxSIZE=3,AxLEN=(128/8)-1=15。4KB检查:0x2018+128=0x2098,小于0x3000,没有跨4KB边界,所以一个Burst就够了。我需要一个真正跨边界的例子,比如起始地址0x2FF0,搬运128字节,那0x2FF0+128=0x3070,跨了0x3000。那么从0x2FF0到0x2FFF只有16字节,所以第一个Burst AxLEN=1,传2个Beat共16字节。第二个Burst从0x3000开始,剩余112字节,AxLEN=(112/8)-1=13,传14个Beat共112字节。这个例子更干净。)

这种拆分逻辑在写RTL时就是一段纯粹的地址计算状态机,但很多人图省事只在软件层做,硬件上不做防护,一旦软件配置出错,硬件不会自动拆,总线就崩了。我现在写的DMA引擎,都会在硬件里内置这个拆分逻辑,软件侧只管发大请求,硬件侧自动拆成多个合规的Burst,这才叫靠谱的设计。

5.2 波形图怎么看,怎么对照代码排查

看总线波形是每个SoC工程师的基础功,但怎么快速从波形里识别出Burst和Beat的区别,是有技巧的。我分享一个我自己习惯的读波顺序:

先找到AWVALID和AWREADY同时拉高的时刻,这是Burst的起点。记录此时的AWADDR和AWLEN,这是整个Burst的“计划书”。然后切到写数据通道(W),数一下从现在开始,WVALID和WREADY同时拉高的次数。这个次数必须等于AWLEN + 1。在波形工具里,通常会给对齐的握手画上一个小记号,这些记号就是Beat的完成点。

读通道稍有不同,因为读请求在AR通道上发起,但数据返回在R通道。要找RVALID和RREADY的同时拉高,并观察RLAST信号:当RLAST为高且握手完成时,意味着这是这个Burst的最后一个Beat。很多初学者以为读通道的burst也是通过AWLEN来判断结束,实际上在读通道里你要关注RLAST而不是AWLEN。AWLEN只是用来知道你“期望”多少个Beat,真正告诉你读数据流结束的是RLAST信号。

有一次我排查一个AXI从设备返回数据多拍的问题:主设备发起了一个AxLEN=3的读Burst,期望收到4个Beat的数据,但R通道上多返回了2个Beat。最终发现是从设备的读状态机在生成RLAST时,错误地以“FIFO里的数据数量”为准来拉高RLAST信号,而不是以AxLEN为准。不过这种错误还算好查,因为波形上RLAST和AxLEN期望值不一致非常明显;反倒是那些“少拍”的bug,比如RLAST提前拉高,剩下的数据就挂在那边,会带来难缠的hang问题。

5.3 关于Burst类型选择的建议

关于该用INCR还是WRAP,或者FIXED,很多场景里其实已经是大半个默认选择。一般DMA、普通读写都用INCR,因为内存地址是线性的;访问固定外设状态寄存器用FIXED,因为寄存器地址不变;Cache操作、块填充这类场景用WRAP,因为它能让地址被约束在特定对齐窗口内,方便和Cache内的地址tag做比较。

但我想特别提醒:不要过度使用WRAP。很多工程师觉得WRAP“更先进”,会给普通的数据搬运也用WRAP。从功能上看,WRAP没有错,但它限制了你一个Burst里最多传的字节数——它必须是一个对齐窗口的大小。这意味着如果你想用一个WRAP Burst搬一个大块数据,你得拆成很多个WRAP窗口来搬,传输管理和地址恢复都变得麻烦。用INCR一把梭通常最省心。

还有个细节:FIXED类型虽然地址不变,但每一个Beat的WSTRB可以不同。也就是说,你可以对一个固定的32位寄存器端口连续写4次,每次只写其中1个字节。这是FIXED标准用法,经常用于写在同一个地址上的多个位域配置。如果你从设备逻辑里把所有Beat都当成整字写,那位域配置就会错乱——我见过好几个这样的小模块在一个大系统里造成过配置错误,查起来真的很伤。

5.4 窄总线到宽总线的转换陷阱

在一个多主多从的SoC里,主设备和从设备的数据总线宽度往往不一致。比如CPU侧AXI总线是128位,而你挂的一个外设总线是32位,中间需要有一个宽度转换桥。此时,一个128位总线上的Beat,在32位总线上可能对应4个Beat。这里Burst和Beat的关系就变得更加微妙——从这里也能看出,Beat这个概念并不是绝对物理上的“一拍”,它还取决于你观察的是哪一段总线。

宽度转换桥的核心逻辑是:把宽总线侧的一个Beat拆成多个窄总线侧的Beat,同时保持地址递增的连续性;或者反过来,把多个窄侧Beat积累成宽侧的一个Beat。这里最容易出错的地方是WSTRB的展开。宽侧写一个Beat,32位有效数据,WSTRB=0xF,但这是在128位总线的最高或最低32位字节通道上。转到窄侧时,需要把宽侧总线上的哪个字节通道对应到窄侧总线的位置上搞清楚,否则数据就会错位。

我记得有一次做视频输出接口,主设备是128位AXI,VGA控制器是32位接口,中间桥接了几个月,总有小概率的花屏。最后就看到底是窄侧字节通道的映射在少量场景下反了。而且这种问题还不是每次必现,只有在像素行末地址不对齐时才出现。调试这类问题,建议在桥两侧同时拉出波形,把“宽侧Beat”和“窄侧Beat”的地址做一次映射检查,对不上再往下查。

6. 仿真验证时如何正确构造Burst与检查Beat

6.1 写Testbench时的推荐做法

仿真层面,我推荐的做法是:把Burst当成一个transaction对象来产生,把Beat当成stream item来处理。UVM里通常定义一个总线传输对象(比如称为axi_transaction),里面包含addr、len、size、burst等字段,再定义一个数据对象对应每个Beat。发起激励时,先生成一个完整的burst事务,然后通过sequence把它拆解成一个一个beat发送到driver。

Driver在驱动总线时,按协议要求把每一个Beat的握手信号严格拉高,直到双方都ready。这里最容易错的一个点是:握手信号不能只靠延时对齐,必须等双方都ready才算完成,绝不能自说自话地推进到下一个Beat。否则你的验证环境就是带病工作,后面所有数据比对都可能是错的。

我见过一个验证工程师,在driver里写了一个非常理想化的模型:每拍都假设slave一定ready,结果真实系统的slave内部有FIFO半满时要stall,导致系统的时序行为和模型预期完全不符。也就是说,至少在随机测试里,必须让slave时不时拉低READY,这样才能验证主设备对反压(back-pressure)的处理是否完善。

6.2 断言与计分的监控点设置

如果要在验证环境中加入监控和计分,我的建议是设置三类监控点:

第一类是事务级监控点,在AW/AR通道上捕获Burst请求。记录地址、长度、大小、类型,这些是后续一切检查的基础。

第二类是数据级监控点,在W/R通道上逐Beat检查数据流。包括数据是否按照协议出现在合适的通道上、写数据的WSTRB是否和地址对齐规则匹配、读数据的RLAST是否出现在最后一个Beat。

第三类是协议违例监控点。常见的检查项包括:INCR突发是否跨越4KB边界、WRAP突发是否设置了非2幂次的len、AXSIZE超过总线宽度、FIXED+WRAP混用等。这些断言一旦触发,就说明主设备端代码或激励有bug。

计分板的比对逻辑,建议也按Beat粒度做。对于写通道,每个Beat的WSTRB决定了有效字节的位置,比对时先根据WSTRB生成有效字节掩码,再和期望数据比对。对于读通道,则要根据RID和RLAST来匹配事务的返回,特别是有多个outstanding读请求时,读回的数据可能是乱序的,不能按返回顺序直接比对。这个经验我觉得值得单独说一下:out-of-order在读通道是允许的,所以你的scoreboard必须支持按ID分组、乱序返回的数据比对,否则仿真会报一堆莫名其妙的误报。

7. 最后的一个实操小建议

如果你刚开始接触AXI,或者正在被一堆总线相关的概念绕晕,我的建议是不要苦背手册,而是动手做一个小实验:搭一个最小验证环境,主设备发一个INCR类型的Burst,AxLEN=3、AxSIZE=2,从设备侧做一个简单的FIFO,然后拉出波形图。在波形图上,你先找到AR/AW通道上的Burst请求,再去R/W通道上数出4个Beat,观察地址递增的方式,观察RLAST的位置,观察如果从设备拉低READY时,Beat如何被拉伸。

这个过程走一遍,你对Burst和Beat的区别就不再停留在概念层面,而是真正长在了手上。后面再去调真芯片、看总线协议分析仪的数据,就能一眼看出工具上面标注的“Burst Start”和“Beat N”到底是什么关系了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询