
做DFT这些年我越来越觉得工作重心已经变了。早年跑得最多的是一遍遍扫描链综合、ATPG找覆盖率现在拿到一颗复杂的SoC最烧脑的反而是测试数据怎么“送进去、收回来”。芯片内部几十个IP、上百个嵌入式仪器哪怕测试机再快引脚就那么多如果访问路径设计得不好测试时间会膨胀到完全不可接受。这也是为什么IEEE 1687也就是常说的IJTAG标准越来越受重视而Tessent工具里的SIB和TDR就是实现这套灵活可测性网络的两个核心节点。这篇文章想讲清楚三件事SIB和TDR到底在网络里扮演什么角色在Tessent里怎么把它们从建模做到网表生成以及我在实际项目中遇到的坑和绕坑方法。内容更适合已经接触过DFT、想深入理解和落地IJTAG的工程师如果你刚入行建议先了解扫描链和基本JTAG概念再看会顺很多。1. 从JTAG到IJTAG为什么“可测性网络”成了必选项1.1 传统JTAG在复杂SoC面前的两个死穴传统IEEE 1149.1 JTAG的初衷是板级测试它的数据寄存器DR链路上可以挂很多单元但访问方式很“粗放”。在一颗芯片里你要是把几十个IP的测试寄存器全部串在一条数据寄存器链路上第一个死穴就是配置时间爆炸——每次访问任何一个IP移位数据都要经过所有在线寄存器哪怕只读一个两位的状态寄存器也得把整条链拖一遍。第二个死穴是结构脆弱任何一个环节的连接错误整条链路就瘫痪很难定位。说到这里我第17个项目的教训很典型当时芯片里挂了40多个TDR顶层图省事全串接。结果每个IP都要做pattern回归一条链上任何改动都要重新生成全量pattern改一次跑一次每天等着编译结果痛苦不堪。1.2 IEEE 1687解决的是“访问控制”问题IJTAG不是为了替代JTAG而是在JTAG的框架上加了“访问控制”的能力。核心思路是让网络具有可重构性。它定义了TDR作为访问嵌入式仪器的数据寄存器又定义了SIB这种“段选择”节点让某个段要么被旁路、要么被激活。通过SIB的级联你可以把整条无限长的链路缩短成“按需访问”的短链路这就是灵活性的来源。可以这么理解JTAG标准解决的是“如何从芯片引脚访问边界扫描单元”而IEEE 1687解决的是“如何从边界扫描网络访问芯片内部任意一块嵌入式逻辑”。后者的对象不再是引脚而是芯片内部数不清的测试结构。SIB和TDR这两类节点的组合决定了这张访问网的形状和效率。1.3 先说清楚TDR不是时域反射计这个必须放在开头说清楚。做信号完整性的同事嘴里的TDR是Time Domain Reflectometry时域反射法用来测阻抗、测线长跟Sigrity仿真TDR那一套相关而DFT语境里的TDR是Test Data Register测试数据寄存器。我在跨部门评审的时候经常看到两边各说各的TDR最后发现聊的不是一回事方案都白对齐了。大家沟通时最好带全称或者直接说“IJTAG的TDR”能省掉很多误解。2. SIB的开关逻辑与TDR的通道职责2.1 TDR一个带“换乘站”的移位通道TDR本质上是一个移位寄存器段和JTAG里的DR寄存器相比没什么魔法但它的价值在于提供了标准化的连接点。每个IP内的测试逻辑比如BIST控制器、时钟控制单元、监控计数器都会通过一个TDR挂在IJTAG网络上。TDR的每个cell基本都有capture、shift、update三种动作这和边界扫描cell的工作方式同源。举个例子一个8位的TDR挂到UART IP上TCK每来一个沿数据从ScanIn移入一位移位完成后更新阶段把数据锁存到阴影寄存器shadow register里驱动IP内部的配置端口反过来IP内部的状态被capture到TDR的捕获级再通过移位移出芯片。这个机制和边界扫描cell很像区别在于它面向的是IP内部逻辑而不是芯片引脚。设计TDR时长度的选择很有讲究。太短带不了足够多的配置位太长访问这个IP本身的开销就大了。我在给一组数字IP设计TDR时通常会把同类的寄存器位合并尽量让TDR长度等于实际需要的配置和状态位数量不为了统一而硬凑。比如一个BIST控制寄存器需要10位我就建一个10位TDR而不是拿一个16位的标准TDR去套。2.2 SIB把串行链路变成可寻址网络没有SIB的时候所有TDR只能傻乎乎地串着。有了SIB链路就变成可寻址的了。SIB内部有一个选择位select bit和一个旁路复用器每个SIB占据一个固定的网络地址。当select bit为0时它控制的那段TDR整段被旁路数据只经过SIB本身——延迟1拍当select bit为1时它控制的TDR段被接入主扫描链数据可以流入TDR。SIB还可以级联这也是它叫“段插入位”的由来。多个SIB串在一起相当于形成了一条“层叠开关”你可以在顶层选一个SIB进入它内部的子网络再选下一层SIB一路选到目标TDR。这就是层次化访问的基本形态。我最早理解SIB是看了Tessent生成的结构图一个SIB单元输入是ScanIn、ScanOut和选择控制输出分两路一路走旁路一路走TDR。当一个SIB打开时数据路径延迟会多出“TDR长度1拍”关闭时只有1拍。这个行为差异是整个网络设计时需要时刻记在脑子里的。2.3 用办公楼门禁的类比理解网络行为如果类比一下可以把芯片比作一栋办公楼TDR是每个房间门口的“登记簿”SIB就是楼层间的“门禁闸机”。没有门禁时访客想进某个房间必须从一楼把每一层的走廊都走一遍路远、耗时、还容易错。有了门禁闸机访客按权限选择进入某层其他楼层直接跳过。SIB的旁路模式就是“快速通过”状态激活模式就是“进入该层”状态。这个类比虽然简化但对讲清楚网络行为很有帮助。尤其是跟后端同事、封装同事沟通的时候你一说“SIB就是按需开关的门禁”对方马上能get到网络的工作方式比我一开始直接扔给他们IEEE 1687协议文档有效得多。3. Tessent IJTAG实操从TDR定义到SIB网络生成3.1 输入准备哪些东西必须提前就位在使用Tessent做IJTAG网络前需要准备几类输入。第一是芯片或IP的RTL网表特别是包含边界扫描逻辑和IP内部测试逻辑的部分第二是TDR的模型描述既可以是工具自带的标准单元集合也可以是根据IP需求自定义的TDR第三是网络连接关系的约束比如哪些TDR放在同一个SIB下、哪些做顶层直连、复位信号的来源等。其中最容易忽略的是复位策略。我在早期几个项目中因为top-level的SIB复位信号没有单独拉出来做管理导致工具在生成网络时把复位依赖放在了功能逻辑上后面综合时序一塌糊涂。建议在设计输入阶段就给SIB和TDR预留独立的测试复位信号别省这一根线。一根线的成本换来的是整个网络复位行为的确定性这笔账非常划算。3.2 TDR建模长度、位序与属性设置Tessent IJTAG对TDR的建模比较灵活可以用标准单元TDR库也可以基于寄存器传输级描述来生成。一般我会先整理一份Excel或脚本形式的TDR清单列出每个IP要挂几个TDR、每个TDR的位宽、数据流向和capture/update属性再转成Tessent的命令脚本。一个示意性的脚本大概是这样的不同版本命令名略有差异以工具手册为准# TDR定义示意 create_tdr tdr_uart_cfg -width 8 set_tdr_property tdr_uart_cfg -scan_in uart_scan_in set_tdr_property tdr_uart_cfg -scan_out uart_scan_out set_tdr_property tdr_uart_cfg -update_clock uart_tck这里我习惯先定义一个基础TDR再把它的数据端口与IP引脚连接。重点是位序TDR的bit0是离ScanIn最近的位还是离ScanOut最近的位必须全网统一否则后面生成pattern时位序对不上定位错误会非常痛苦。我在一个加密IP项目上吃过这个亏TDR位序定义反了仿真怎么都不对最后一行一行对波形才追出来。3.3 SIB网络生成与验证步骤SIB网络的生成在Tessent里通常分为两步先定义SIB节点和包裹关系再执行网络生成。包裹关系是指哪个SIB管哪几个TDR、哪个SIB作为另一个SIB的下层节点。继续用示意命令# SIB网络生成示意 create_sib sib_uart_group -target { tdr_uart_cfg tdr_uart_status } create_sib sib_top -target { sib_uart_group sib_gpio_group } build_sib_network -top sib_top执行完build之后工具会给出网络报告包括每个SIB的层级、打开的bit位宽、总链路长度等。我会先看链路总长度是否符合预期再跑一遍内置DRC重点检查地址冲突、悬空端口和复位依赖。DRC过了不代表网络就完美但它能挡住大部分低级错误。每次新加一个SIB我都会重新看一遍网络报告确认总链路长度的变化在预期范围内。3.4 输出物网表、协议和pattern网络生成成功后Tessent会输出几个关键产物。一是IJTAG网络的网表可以用于综合、布局布线二是基于IJTAG协议的标准接口文件方便后续的SoC集成和仿真三是可以被TestKompress或第三方工具使用的pattern文件也就是通过网络访问TDR的测试向量模板。这步我特别提醒一句输出网表后务必做一次网表级仿真冒烟重点确认每个TDR在capture/update阶段的时序行为。很多人以为建模正确、DRC通过就万事大吉忽略网表仿真结果等到流片后端发现问题代价就大了。我自己的习惯是每个SIB树生成后至少跑一个“全旁路”冒烟和一个“全激活”冒烟确认网络在两种极端状态下都能正确移位。4. 测试访问链路的时序预算与测试时间账本4.1 全部串接的方案为什么不可行假设一颗芯片有40个TDR平均每个TDR 1000位。如果全部串在一条DR链上访问一次的总移位长度大概是40000位。对于每个IP你都要经过这条长链才能访问它。跑一遍测试所有IP的pattern加一起移位操作占了绝大部分时间直接导致测试成本飙升。在量产的语境里测试时间就是成本。哪怕一个pattern少省20毫秒乘上一百万片出货量收益都很可观。SIB的价值说白了就是在测试时间账本上做减法。更麻烦的是传统串接下单独访问一个IP时其他IP的TDR也必须在链上这会让capture阶段产生很多不必要的翻转增加动态功耗甚至可能干扰某些模拟IP的工作状态。SIB的旁路机制顺带把这个问题也缓解了。4.2 一套可以手算的测试时间模型我们可以做一个简单的估算。TCK频率常见的是20MHz到50MHz也就是每周期50ns到20ns。如果没有SIB全链访问一次的最小移位时间为40000×TCK。如果TCK20MHz那就是2ms。而有了SIB之后访问单个TDR的移位长度为“SIB路径上的select bit数 目标TDR长度 1”大概在几十到一千出头。同样是20MHz如果一次访问需要1024位就只用约51.2us时间缩短了几十倍。我把这个模型做成了一张简单表格方便在项目评审时快速估算网络形态访问单个TDR的移位长度示例值TCK20MHz全部串接所有TDR长度之和40000位 ≈ 2.0ms一层SIB顶层SIB位 目标TDR长度 11024位 ≈ 51.2us三层SIB三层路径上SIB位 目标TDR长度1100位 ≈ 55us当然这不是说SIB能让所有测试时间都缩小到这个比例——因为配置SIB本身也需要时间。但当一个IP需要反复访问、而其他IP并不需要同时访问时按需访问的优势非常明显。如果多个IP确实需要并行访问就要考虑共享总线类的DFT架构这个后面再展开。4.3 面积开销与控制深度的取舍SIB不是免费的每个SIB大概等效于两到四个触发器加上旁路mux逻辑和一部分控制逻辑。一片规模较大的SoC里部署几百个SIB并不少见但对应的面积开销在总芯片面积里通常占比很小基本可以接受。真正需要权衡的是网络深度。层级越深访问底层叶子TDR前需要先逐级打开SIB配置延迟会累积。所以设计上要避免“一根SIB链吊到底”的结构尽量让中高层SIB分布合理叶子SIB尽量靠近它控制的TDR。总的来说SIB层级控制在三到五层是比较稳妥的实践。太浅了顶层扇出过大太深了路径延迟和配置时间都吃亏。5. 实战中遇到的五个高频问题与处理办法5.1 配置冲突导致的链路“假锁定”第一次做多个SIB配置的时候我以为只要把select bit按顺序移进去就行结果在仿真里发现链路像被锁死一样怎么都切不到目标TDR。后来查下来是因为网络里两个SIB使用了重叠的配置地址第二个SIB的配置信号把前一个SIB的选择状态意外覆盖了链路就“假锁定”在某个非预期状态。现在我的做法是在Tessent里对SIB的地址分配做全局唯一性检查并且每次新增SIB后把网络地址表导出核对一遍确认每个选择位有唯一的归宿。工具本身有DRC但DRC通过不等于语义正确人工review地址表仍然值得做。尤其是那种由不同工程师分别维护的IP域合并时很容易出现地址重叠。5.2 异步IP的TDR采集时序不稳定做过一个挂在异步时钟域下的状态监控TDRcapture阶段数据总是出现亚稳态表现为仿真时好时坏。典型原因是TDR的shift时钟和IP内部功能时钟不同源capture发生在功能时钟沿附近建立时间不够锁存到不确定值。解决办法有两类。一是给TDR增加同步器在capture路径上加两级同步后再锁存二是在pattern生成时约束capture窗口避免紧贴时钟沿。我在这个项目里选了方案一效果稳定但代价是TDR面积多了一点。对于对时序敏感的TDR建议从建模阶段就把同步器预留出来别等跑到RTL仿真再补后期补同步器牵扯的时序分析和物理实现改动都不小。5.3 复位状态未定义带来的默认链路异常SIB的select bit如果复位值没有定义上电后可能是随机状态。一旦某个深层SIB默认选中整条默认访问链就会比预期长很多甚至导致配置序列错位。这个坑比较隐蔽因为功能仿真里复位通常被固定为0而真实硅片上电时行为并不可控。规避方法给SIB的select bit显式指定复位值通常复位到0旁路。同时在测试pattern的开头加入一条网络初始化序列先清空所有SIB选择位再做任何具体访问。这条初始化序列的成本很低但能换来确定性我一直坚持保留。后面在ATE上调试时这条初始化序列帮我排掉了至少三成和网络状态相关的怪问题。5.4 深层SIB级联与配置时间膨胀当我第一次把SIB做成了六层嵌套的时候访问最底层TDR的配置时间开始变得难看。每进一层就要在链上多移入这一层的SIB配置位如果网络还很长累计延时比想象中大得多。有个调试类TDR在六层SIB之下光打开路径就要上百拍再加上TDR本身的长度每轮访问的开销已经失去了SIB的意义。后来我优化网络结构把热路径上的叶子TDR尽量上提把不需要频繁访问的调试类SIB放深层同时在中层做了并行SIB控制让几个同层SIB可以一起配置。优化后原来动不动上千拍的配置时间压缩到几百拍以内。这个教训告诉我SIB层级设计不能只画结构图一定要结合访问频率来排布。5.5 仿真模型与实际网表的行为不一致有一次工具生成的IJTAG网表和手写RTL行为模型在特定场景下的仿真结果对不上查了整整一天最后发现是模型里没有考虑SIB旁路时的1拍延迟而网表里旁路路径确实占了一拍。这个差异在大多数场景下不显眼但在连续配置多个SIB的场景下一拍偏差就会导致后续所有配置错位。从那之后我要求所有IJTAG相关仿真模型必须直接从Tessent输出产物生成不再手写——省掉“我以为模型对了”的幻觉。如果要手写模型也要先和工具输出去跑一致性比对确认移位行为、旁路延迟、capture窗口完全一致后再投入使用。6. 从芯片到系统SIB网络的可扩展设计思路6.1 分层SIB树的设计原则做过几个项目后我对SIB网络的布局形成了一套默认设计原则顶层SIB只做全局分段不直接挂TDR中间层SIB按功能域划分比如处理器域、通信域、模拟域叶子SIB直接挂TDR并且尽量和IP物理位置靠近。这种分层方式的好处是测试访问路径和物理布局大致对应后端布线时不容易出现一根长线横穿芯片的情况。同时系统集成的时候某个功能域的SIB子树可以整体替换、升级不影响其他域。另外我还会给每个SIB命名都加上功能域前缀比如proc_sib_top、comm_sib_top、ana_sib_top。这样在几千行的网络报告里定位问题比看SIB_001这种编号高效得多。命名规范看似小事在项目后期调试时能省下好几个小时。6.2 与其他Tessent工具链的衔接SIB网络不是孤岛它要跟Tessent的扫描链流程、TestKompress的ATPG、以及封装级测试流程衔接。实际项目中我通常先把IJTAG网络和TDR定义好然后在TestKompress里把需要访问的BIST控制寄存器当作“嵌入式仪器”来调用生成对应的访问pattern。Tessent对这类流程已经有成熟的集成方法关键是你在建模阶段要保证TDR和IP内部信号命名的一致性否则后面映射非常费劲。另外Tessent环境里也存在基于共享总线shared bus的DFT架构它的思路和SIB网络不同——SIB是串行的按需旁路shared bus是并行的多目标访问。两者没有绝对的高下之分取决于IP类型、时钟域和测试并发需求。我一般在有大量同质化IP需要并发配置时倾向shared bus而在IP类型复杂、访问路径需要隔离时倾向SIB网络。两种架构各有一个擅长的主场。6.3 升级方向诊断、Yield与系统级测试SIB网络带来的灵活访问能力在量产阶段的好处远不止测试时间。比如你可以通过SIB动态打开某个失效IP的TDR读取诊断信息定位失效模式也可以配合Yield Insight类的工具做系统级数据挖掘。在SLT系统级测试阶段SIB网络同样可以让测试程序在板级灵活访问多个芯片的内部网络。这个能力对系统级故障定位特别有用——板子出了失效可以先通过SIB把各个芯片内部的诊断寄存器依次打开把故障范围从板级缩小到芯片级、再到模块级。从长远看IEEE 1687体系里还有更多特性可以扩展比如通过SIB做动态时钟控制、通过TDR做嵌入式仪器的多路复用访问。如果项目预算和时间允许建议在架构阶段就预留好SIB的层次和访问能力而不是等项目后期再补。后期补网络结构牵扯的往往是已经冻结的RTL和物理约束改动成本完全不是一个量级。最后分享一点个人经验。刚开始接触IJTAG时我也纠结过“SIB到底要多少层、TDR位宽是不是越短越好”这类问题。后来发现脱离实际访问场景谈参数都是空的。最好的办法是先把手头所有IP的测试访问需求列一张表包括访问频率、数据量、时钟域和并发要求在这张表的基础上设计SIB层级和TDR长度才能做出又省时间又很好维护的网络。Tessent的SIB和TDR说到底只是工具真正决定网络质量的是你能不能把芯片的测试访问需求想清楚。