AXI-Stream TSTRB TKEEP 区别:空字节与位置字节语义、末拍用法与互操作坑
更新时间:2026-09-28。本文是「集成电路大类 · 芯片设计」接口主题簇里的一篇长尾文。AXI-Stream 帧结构:TLAST、TKEEP 与 TUSER 建立了一帧数据由多个拍(beat)组成、末拍用
TLAST封顶的整体模型,但把一对极易混淆的信号留给了本篇:TSTRB和TKEEP。两个都是按字节的位掩码,宽度相同、波形上经常一起变化,很多工程师干脆把它们当成一回事——直到对接第三方 IP 时数据被悄悄丢掉。
本文要回答的问题
TKEEP和TSTRB各自的位掩码语义是什么,null byte 与 position byte 差在哪?- 一帧的末拍(
TLAST=1)上TKEEP应该怎么打,中间拍能不能拉低? - 两个信号取值的合法组合有哪些,规约为什么说 TSTRB 为 1 时 TKEEP 必须为 1?
- 只实现了 TKEEP 的 IP 和只用 TSTRB 的 IP 对接时会出什么错?
- 数据宽度转换、DMA 搬运场景下这两个信号怎么处理?
一、位掩码语义:null byte 与 position byte
AXI-Stream 的数据总线 TDATA 按 8 位一个字节划分成若干字节车道(byte lane),TKEEP 和 TSTRB 都是每车道 1 位的掩码,宽度等于 TDATA 字节数。32 位数据总线对应 TKEEP[3:0]、TSTRB[3:0],位 i 管数据线 [8i+7 : 8i] 这条车道。两者区别的核心,在于它们回答的是两个不同的问题:
| 信号 | 回答的问题 | 掩码为 0 的字节叫 | 语义 |
|---|---|---|---|
TKEEP | 这个字节存在吗?是否属于本拍数据的一部分 | null byte(空字节) | 0 = 该车道没有任何数据,接收方必须整个忽略 |
TSTRB | 这个存在的字节内容是有效信息还是占位 | position byte(位置字节) | 0 = 字节存在、占住位置,但内容本身不携带信息 |
一句话版本:TKEEP 管「有没有」,TSTRB 管「算不算数」。null byte 是「这个槽位是空的」,position byte 是「槽位有东西,但只是个占位符,别当真」。
position byte 的典型用途是稀疏数据:发送方想表达「第 0 和第 3 字节是有效载荷,中间两个字节只是为了让第 3 字节落在车道 3 上」,就打 TKEEP=4'b1111、TSTRB=4'b1001。接收方知道中间两字节要跳过,但它们在流里占据的位置是有意义的——比如表示样本之间的间隔。null byte 则连位置都不占,TKEEP=4'b1001 表示这一拍只有两个真实字节。绝大多数工程实现(DMA、以太网 MAC、视频流)从不产生 position byte,固定 TSTRB=TKEEP,这就是混淆的温床。
上图是「中间打孔」的典型例子:四条车道的 TKEEP 全为 1,说明这拍有四个字节占用流中的位置;但 TSTRB 只有两端为 1,接收方处理时只取车道 0 和车道 3 的内容,车道 1、2 的数据要当作填充丢弃。如果把 TSTRB 误当 TKEEP 用,这一拍会被错误地理解成「只有两个稀疏字节」,位置语义就丢了。
二、末拍 TKEEP:流打包最常用的一处
规约对两个信号的使用范围有明确分工:TSTRB 可以在任何拍上自由打 position byte;而 TKEEP 拉低(制造 null byte)只允许出现在一帧的末拍——也就是 TLAST=1 的那一拍。中间拍必须 TKEEP 全 1,数据流是紧密排列、不允许中间空洞的。
末拍拉低 TKEEP 解决的是「帧长不是总线宽整数倍」的打包问题。32 位总线上发 10 字节的一帧:前两拍各 4 字节、TKEEP=4'b1111;第三拍只剩 2 字节,TLAST=1 同时 TKEEP=4'b0011,高两条车道为 null byte,接收方据此知道帧在第 3 拍第 2 字节处结束。这与 AXI-Stream 帧结构 里的打包示例一致:TLAST 定帧边界,TKEEP 定末拍的有效字节数。
中间拍出现 null byte 是非法的,理由很实际:流接口没有地址,字节全靠顺序排列,中间挖洞会让「第 n 个有效字节对应帧内第几字节」失去唯一定义。验证环境应加断言:TLAST=0 时 TKEEP 必须全 1;TLAST=1 时 TKEEP 的 1 必须连续从低位起(多数实现约定,如 4'b0111 合法、4'b1011 是畸形)。还有一点容易漏:规约允许发送方在末拍把 null 车道的 TDATA 驱动成任意值,接收方不得依赖其内容——测试里把末拍高车道填随机数,能揪出接收端误读 null 字节的 bug。
三、合法组合与一致性约束
两个信号按位组合,每车道只有三种合法状态:
| TKEEP | TSTRB | 含义 | 是否合法 |
|---|---|---|---|
| 1 | 1 | 有效数据字节 | 合法 |
| 1 | 0 | position byte(占位) | 合法 |
| 0 | 0 | null byte(不存在) | 合法 |
| 0 | 1 | 不存在却有效 | 非法,自相矛盾 |
规约的硬约束是 TSTRB[i]=1 蕴含 TKEEP[i]=1,即 TSTRB 是 TKEEP 的子集。违反它的发送方是畸形实现,接收方行为未定义。记分板检查可以把这条写成一行断言:(TSTRB & ~TKEEP) == 0。
上图是接收端/验证检查的处理顺序:先做子集一致性检查,再按是否末拍分流——非末拍要求 TKEEP 全 1,末拍检查低位连续,最后才进入正常的数据解释。这个顺序很重要,一致性检查不过的数据根本不该进入帧重组逻辑。
四、互操作坑:只实现一半的信号
AXI-Stream 允许两个信号都省略:不实现的信号视为恒 1。坑出在一方「省略了但对方用了」:
- 发送方不用 TKEEP、接收方按 TKEEP 解帧:发送方帧长非对齐时末拍只能拿无效数据填满,接收方按全 1 的 TKEEP 会把填充字节当成帧内容,帧变长。对接前必须确认发送方要么帧长恒定对齐,要么确实有 TKEEP。
- 发送方用 TSTRB 打 position byte、接收方只认 TKEEP:接收方把 position byte 当有效数据处理,稀疏语义丢失。好在工程上几乎没人用 position byte,真正的风险场景是穿过只透传 TKEEP 的第三方数据通路 IP——TSTRB 被它丢掉或强制跟随 TKEEP。
- 宽度转换器对两个信号的处理不对称:做 32 位到 64 位的宽度拼接时,下游一拍的 TKEEP/TSTRB 是上游两拍的拼接结果,末拍半填充的场景最容易错位,详见 AXI-Stream 位宽转换。带 null 的末拍不允许与下一帧拼接,转换器必须把末拍单独对齐输出。
与 AXI 内存映射接口对照能加深理解:AXI4 的 WSTRB 是显式字节写使能,语义接近 TSTRB 的「内容有效」,但没有 TKEEP 这种「字节是否存在」的概念,因为内存传输有地址、有拍数,不需要用 null byte 表达短帧,见 AXI4 WSTRB 字节使能。流接口无地址,才需要 TKEEP 和 TLAST 配合表达「帧到这里结束、且末拍只有这几个字节」。
五、验证与调试建议
定向用例至少覆盖:帧长等于、差 1、差一半总线宽的对齐/非对齐末拍;连续多帧背靠背时末拍 TKEEP 与下一帧首拍的切换;末拍 null 车道驱动随机值。随机用例里约束 TSTRB 恒等于 TKEEP(工程常态),另开少量带 position byte 的用例确认接收端行为符合约定。波形调试时先看末拍:帧内容错位八成是末拍 TKEEP 的 1 的个数不对,或 TLAST 与 TKEEP 不在同一拍。背压场景下 TKEEP/TSTRB 必须随 TDATA 一起保持稳定,详见 AXI-Stream 背压与时序。
再把两种位掩码的组合关系捋一遍帮助记忆:TKEEP=1 且 TSTRB=1 是正常数据字节;TKEEP=1 且 TSTRB=0 是位置字节,占位置但内容无意义;TKEEP=0 的字节根本不属于当前传输,应被完全忽略,此时 TSTRB 的值约定也必须是 0。也就是说合法组合只有三种,「TKEEP=0 且 TSTRB=1」是协议明确禁止的,接收端可以(也应该)用断言直接抓这种违例。很多 IP 把 TSTRB 恒绑成全 1,此时它退化为「所有 TKEEP 置位的字节都是有效数据」,和只实现 TKEEP 的接口天然兼容——这正是互操作讨论的基础。
这一篇在知识体系里的位置
协议全貌见 AMBA 入门 与 AXI-Stream 帧结构:TLAST、TKEEP 与 TUSER;握手稳定性见 AXI-Stream 背压与时序;跨位宽场景见 AXI-Stream 位宽转换;对照内存映射接口的字节使能见 AXI4 WSTRB 字节使能;路由类边带信号见 AXI-Stream TDEST/TID 路由。
总结
AXI-Stream TSTRB TKEEP 区别一句话讲清:TKEEP 按字节回答「存不存在」,为 0 是 null byte、只允许出现在 TLAST=1 的末拍用来表达短帧;TSTRB 回答「内容算不算数」,为 0 是 position byte、字节占位但内容无效;硬约束是 TSTRB 为 1 蕴含 TKEEP 为 1,工程常态是两者恒等;互操作的最大坑是一方省略 TKEEP 导致末拍填充字节被当成帧内容,或穿过不透传 TSTRB 的 IP 丢失 position 语义,对接前逐项确认两个信号的实现范围即可避开。