ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

set_dft_signal实战指南:从扫描链配置到DRC检查的DFT关键技巧

set_dft_signal实战指南:从扫描链配置到DRC检查的DFT关键技巧 DC综合里set_dft_signal这条命令用得好不好直接决定你插入的扫描链干不干净、DRC能不能一次过、芯片回片后测试能不能顺利跑下去。我在做DFT集成的时候见过太多因为这条命令配置得太随意导致后面花几周时间在ATPG和良率分析上还债的案例。这篇我就把这几年在set_dft_signal实战配置上踩过的坑、总结出的经验一次性全部分享出来。1. set_dft_signal在DFT流程里到底扮演什么角色1.1 DFT设计与set_dft_signal的职责边界很多刚从功能验证转来做DFT的工程师第一个接触的命令往往就是set_dft_signal但大多数人对它的理解停留在“给扫描链指定一下时钟和复位信号”这个层面。实际上这条命令是DFT设计意图design intent的核心载体它负责告诉Design Compiler哪些信号在测试模式下扮演什么角色、极性如何、从哪个端口进来、驱动哪一类内部节点。打个比方功能综合阶段你写的create_clock和set_input_delay是给芯片的“正常工作”定规矩而set_dft_signal是给芯片的“体检模式”定规矩。体检模式下芯片要把内部寄存器串成链条把测试激励灌进去再把响应吐出来。这个过程中哪些信号是体检专用的比如scan_enable、哪些信号是复用功能引脚的比如scan_in打到功能IO上都要通过set_dft_signal提前交代清楚。如果你漏配了某个信号或者配置的顺序不对DC在dft_drc阶段就会报出一堆错误扫描链插入后也可能出现时序收敛不了、覆盖率上不去的问题。这些问题的根源往往不在逻辑本身而在信号配置阶段就埋下了雷。1.2 “先声明后使用”的原则有多重要我用一个真实经历来说明。之前做过一个MCU项目测试时钟复用的是PLL分频后的功能时钟。功能模式下时钟树是由create_clock定义的但测试模式我们希望直接从外部引脚灌时钟。结果有同事在set_dft_signal里只配了-type ScanClock没配-port对应的测试时钟端口也没有指定-usage_clockDC在插入扫描链时默认走了功能时钟路径。看起来也没什么大问题仿真也能过。但到了ATE上测试时PLL在低频下锁定时间偏长导致首条测试向量加载前时钟还没稳整片芯片的测试结果都是FAIL。后来加了测试时钟的外部旁路配置问题才消失。原因不复杂——set_dft_signal没有完整声明测试时钟来源DC默认选择了更复杂的路径而测试环境里我们只希望用最简单、最可控的时钟来源。所以我现在带团队做DFT第一条规定就是set_dft_signal必须在compile之前全部完成声明配置的顺序、信号的完整度、极性的正确性都要做一次专项review不允许边综合边补。2. set_dft_signal核心语法与信号类型逐一拆解2.1 基本语法与常用选项set_dft_signal的标准语法是set_dft_signal -view spec | existing_dft \ -type signal_type \ -port port_list | -pin pin_list \ [-active_state 0|1] \ [-usage_clock clock_name] \ [-hookup_pin pin_name] \ [-timing options]这里有几个容易混淆的关键点。第一个是-view选项它决定这条声明是“设计意图”还是“已存在的事实”。在compile之前你写-view spec表示“希望DFT插入后实现成这样”如果读入的网表里已经插好了扫描链你要做增量约束或验证就需要用-view existing_dft来告诉DC“这些信号现在是这么用的”。第二个重点是-type它支持很多值ScanClock、ScanEnable、ScanIn、ScanOut、ScanDataIn、ScanDataOut、Reset、Constant、TestMode等等。不同type直接影响DC对信号的处理方式。比如TestMode信号平时功能模式下必须处于使测试逻辑无效的状态测试模式下才拉高或拉低如果你把这个信号声明成ConstantDC可能就不会在测试模式下做特殊处理导致测试逻辑在功能模式下处于不确定状态。第三个容易忽略的是-active_state。这个选项指定信号的当前有效电平。大多数工程师只记得给低有效复位配-active_state 0却忘了给测试模式信号反着配。比如你的test_mode信号是1有效就必须写-active_state 1否则DC在分析测试模式下的约束传播时可能把关键路径算错。2.2 五大核心信号类型详解扫了一圈实际工程里的用法我把最常用的信号类型整理成一张表希望对初学者指个方向。信号类型典型用途常见配置要点易踩的坑ScanClock扫描链移位时的时钟时钟端口或内部时钟 pin需指定-usage_clock只配了时钟端口没指定时钟名DRC 分不清捕获时钟和移位时钟ScanEnable扫描移位/捕获模式切换同步高有效信号通常来自外部端口忘记约束为-active_state 1导致移位模式进不去ScanIn / ScanOut扫描链的数据输入输出可直接绑定到顶层输入输出端口与功能IO复用但没设set_dft_drc_configurationDRC报IO约束冲突Reset异步复位信号必须声明为Reset测试模式下需要可控只用了Constant声明导致复位树的测试覆盖率为0TestMode测试模式使能信号用于区分功能/测试模式通常高有效没接内部测试模式逻辑综合时被优化掉了2.3 配置时钟、复位与异步信号的实战要点时钟在DFT里的地位不用多说但很多人不知道set_dft_signal里时钟的配置有一个细节-usage_clock的值必须是create_clock里定义过的时钟对象或者是dc_shell能够从端口追溯到的一个时钟。如果这个时钟名写错了DC在插入扫描链时虽然不会报错但在生成测试协议时会发现找不到正确的时钟定义导致dft_drc出现S-203类错误。我建议的时钟配置姿势是在set_dft_signal之前先把所有需要用到的时钟都通过create_clock定义好包括测试时钟端口上的虚拟时钟。然后一条一条写# 定义测试时钟端口上的虚拟时钟 create_clock -name tck -period 100 [get_ports tck] # 声明测试时钟属于扫描时钟 set_dft_signal -view spec -type ScanClock \ -port [get_ports tck] -usage_clock tck -active_state 1这样DC就能把外部tck端口和测试时钟完整对应起来后面做insert_dft时就不会在时钟识别上出幺蛾子。至于复位信号我踩过一个非常典型的坑。有个项目复位信号是低有效功能逻辑里采用异步复位设计。我在SDC里写了set_dft_signal -view spec -type Reset -port rst_n -active_state 0看起来没问题。但综合时发现复位树上插了很多不必要的测试点覆盖率报告里复位故障点数量异常低。排查后发现DC把复位信号和普通数据信号进行了等价替换测试模式下复位不会进入可控状态。后来我加了一行set_dft_signal -view spec -type Constant -port rst_n -active_state 1来表示测试模式下复位信号是被强制释放的不复位DRC就干净了。这个样例很典型也说明了set_dft_signal配置的精细程度不是随便写写就能完事的。3. 从零搭建一个可跑的DFT综合脚本3.1 脚本结构设计与配置顺序我DFT综合脚本的顺序一般是这样读入design设置顶层。定义所有时钟功能时钟、测试时钟、虚拟时钟。set_dft_signal声明所有测试相关信号。set_scan_configuration设置扫描链相关参数。dft_drc跑DRC检查。修改和补约束直到DRC干净。insert_dft插入扫描链。再次dft_drc验证插入后的网表。compile -scan继续优化时序。输出网表、SDC、测试协议文件。set_dft_signal之所以要放在set_scan_configuration前面原因是set_scan_configuration里的很多选项比如-chain_count、-clock_mixing会参考当前已经声明的ScanClock和ScanEnable信号。如果你顺序倒过来DC可能会用默认值为你创建一堆不必要的扫描时钟后面再改就得remove_dft_signal重来白折腾。3.2 扫描链插入与set_dft_signal联动扫描链插入时DC会根据你声明的ScanClock数量、ScanEnable的极性和ScanIn/ScanOut的端口数量自动做链的划分和IO的绑定。这个自动过程看起来省事但实际项目里几乎都要介入控制。举个例子一个设计有4个时钟域但扫描输出IO只有2个。DC默认会尝试把4个时钟域的信号链分配到2个输出上这就会导致跨时钟域的扫描链混链。如果没做任何干预ATPG覆盖率会掉得很厉害因为跨时钟域的捕获时序很难满足。我一般的做法是利用set_scan_configuration的-clock_mixing mix_clocks或no_mix明确指定是否可以混时钟。如果是做测试质量要求高的车规芯片我倾向no_mix每个时钟域独立成链配合set_dft_signal把时钟和扫描链对应关系固定下来。另外set_scan_path也可以和set_dft_signal配合使用。如果公司有既定的扫描链连接顺序比如为了后端布线方便要求某些寄存器前后连接可以先用set_scan_path显式定义链的顺序再用set_dft_signal声明对应的端口信号。这样DFT的意图会非常明确不会受DC自动化逻辑的干扰。3.3 DRC检查与报告解读配置完成后dft_drc是检验配置正确性的第一道关卡。我通常不看最终的报告摘要而是抓中间的错误和警告信息一条一条排查。DC的DFT DRC错误码数量不少但高频出现的问题其实就那么几类。S-003: 找不到某个引脚的时钟通常是set_dft_signal里-port写错或create_clock没有覆盖到。S-011: 扫描使能信号在测试模式下无法固定为有效值。检查ScanEnable的-active_state也要看周边逻辑是不是被set_dft_signal -type Constant误约束了。S-016: 存在未被约束的异步复位/置位。这时候set_dft_signal -type Reset或-type Constant的配置就很重要了。S-202/S-203: 时钟信号问题大概率是-usage_clock没写对。报告里的每一条信息都值得仔细读一遍不要急着往脚本里盲目加set_dft_signal去“堵”错误。搞明白DC为什么报错才是把这些配置吃透的关键。比如S-016报了某个寄存器的异步复位不受控正确的做法是检查这个复位信号是不是被功能逻辑驱动了而不是简单加一条Constant约束。如果复位是内部逻辑产生的比如一个上电复位电路那就要考虑是否在测试模式下把这个内部生成的外部可控点断掉。4. 进阶优化策略让DFT结果更干净4.1 复用功能时钟与创建测试时钟的取舍项目里做DFT最常面临一个选择扫描时钟到底直接复用功能时钟还是单独拉一个测试时钟端口两者的优劣势很明显。复用功能时钟的好处是节约IO和功耗且与功能时序完全一致。但坏处是功能时钟树上的逻辑PLL、分频器、门控单元在测试模式下可能存在不确定性低频下锁不住高频下沿的精度也不好控制。单独拉测试时钟的话测试时序干净、确定代价是IO贵、封装和板子的测试约束更重。我个人的经验是消费电子里如果芯片容量不大、测试频率要求不高比如10MHz以内复用功能时钟加上一个测试旁路bypass寄存器就够了。这个旁路寄存器在测试模式下把PLL的反馈断开用外部晶振或低频时钟替代。这种方案的set_dft_signal配置里要把旁路控制信号声明为TestMode或者Constant类型并且保证在扫描移位时整个时钟路径是稳定的。高性能或车规设计尽量单独拉测试时钟端口。即使IO紧张我见过的很多项目也会用复用IO的方式但连接关系会被严格指定。set_dft_signal方面测试时钟端口要显式配-type ScanClock并且把功能时钟和测试时钟的关系在SDC里用set_case_analysis固定防止综合工具在两个时钟间做不合理的优化。4.2 减少测试功耗与冲突的配置技巧扫描链插入后测试模式下所有寄存器同时翻转功耗经常是功能模式的几倍。这不仅是功耗预算问题还可能造成电压压降过大测试良率直接腰斩。降低测试功耗除了在set_scan_configuration里把链数增加、链长缩短之外set_dft_signal的配置也有技巧。一个常用的方法是为测试模式设置一个独立的TestMode使能信号在综合阶段利用这个信号做set_case_analysis让DC在测试模式下优化出不必要翻转的路径。具体来说# 声明测试模式信号 set_dft_signal -view spec -type TestMode -port test_mode -active_state 1 # 在综合约束时固定测试模式状态 set_case_analysis 1 [get_ports test_mode]这样做的好处是DC在时序优化时会把测试模式下不会激活的逻辑路径比如功能模式下的时钟门控单元视为静态不再为其插入不必要的缓冲器从而抑制测试模式下这些节点的翻转。很多人忽略了这个联动导致测试功耗比预期高不少。另一个技巧是处理“测试模式下要置为常值的控制信号”。例如功能模式下某个模块的算术使能信号来自一个计数器测试模式下我们希望它固定在0模块不工作降低翻转。可以这样写set_dft_signal -view spec -type Constant -port [get_pins u_alu/enable] \ -active_state 0这样DC在测试模式下把该引脚强行置0ATPG生成时的约束也自动带上这个条件不用后续额外处理。4.3 与后端流程协同的约束传递别忘了set_dft_signal是综合阶段的配置但它的影响远不止于综合。扫描链插入后DC会输出带有DFT约束的SDC这个SDC会传递到后端布局布线。如果set_dft_signal配置得不对或不完整SDC里的测试模式约束就是残缺的后端的CTS时钟树综合和布线就会沿用错误的前提最后芯片回来后测试模式根本跑不起来。一个比较容易被忽略的协同点是时钟树的构建。如果你在set_dft_signal里声明了测试时钟端口后端在CTS时通常会把这个测试时钟和功能时钟设为同一个时钟组。但如果你没有显式设置set_clock_groups或set_false_path来隔离测试时钟和功能时钟CTS可能为了拉齐两者插入一堆不必要的缓冲器面积和功耗双双上升测试时钟沿还变得不确定。我的做法是在输出SDC前额外加一段测试模式约束# 测试时钟与功能时钟互斥 set_clock_groups -logically_exclusive \ -group [get_clocks {tck}] \ -group [get_clocks {clk_pll_out}]然后把这个约束和DFT网表一起交付给后端。有了这层约束后端CTS和布线会同时考虑两种模式下的优雅状态不会为了其中一个模式牺牲另一个。5. 实战排错set_dft_signal相关的典型问题与排查5.1 常见错误信息速查表很多刚接触set_dft_signal的人一跑dft_drc看到满屏的error就慌了。我把这些年高频遇到的错误和对应的排查思路整理成了速查表。报错信息根本原因排查与修复建议Cannot find port/pin xxx端口名拼写错误或未在顶层用get_ports查端口是否存在注意大小写No clock specified for ...时钟未通过create_clock定义补上虚拟时钟或检查时钟端口连接ScanEnable must be active high/low ...扫描使能极性配置有误核对-active_state与RTL逻辑保持一致Conflict of constant value ...Constant类型的信号逻辑值冲突检查是否有多个set_dft_signal声明了同一个信号ScanIn port also used as ScanOut扫描输入输出端口复用冲突在set_scan_configuration中检查-input和-outputIllegal test mode signal ...TestMode信号状态与约束矛盾检查set_case_analysis中的值与-active_state是否匹配Unconstrained reset signal ...复位信号未声明为Reset或Constant补上-type Reset或-type Constant声明5.2 两个典型调试案例聊一个我印象特别深的案例。某次给一个无线SoC做DFT扫描链插完dft_drc报了S-016说一组寄存器的复位不受约束。我打开寄存器看异步复位端接的是一个内部逻辑产生的power-on-reset信号而这个信号没有拉到顶层。功能模式下没问题但测试模式下复位状态未知ATPG根本没法保证初始状态。当时我第一反应是把这个复位当作-type Constant处理因为测试模式下我们希望复位无效。但这样写完后ATPG覆盖率还是不对。研究半天发现那个内部复位信号在测试模式下不是恒定的它和某个时钟域有依赖关系在scan shift阶段会周期性翻转。最后我的处理是在RTL里把测试模式信号接入复位生成逻辑测试模式下把内部POR强制无效同时set_dft_signal -type Reset声明它。这样测试模式下复位完全可控ATPG覆盖率恢复正常。另一个案例是扫描链混时钟域。一个设计里有5个时钟域但我只配置了2个ScanIn/ScanOut端口。DC自动生成了跨时钟域的混合链dft_drc没报错但ATPG的shift故障覆盖率只有83%。我查了覆盖率损失定位到的都是跨时钟域捕获时序违例。于是我在set_scan_configuration里显式指定-clock_mixing no_mix同时用set_scan_path手动把5个时钟域分为5条链每条链独立走各自时钟最终覆盖率回到96%以上。这两个案例的共同点是DFT问题不能单纯靠工具报错来发现错误提示只是表面症状真正的根因往往在逻辑交互层面。set_dft_signal配置的意义就是强迫你在综合之前把测试模式的整体状态想清楚而不是等结果出来再修补。5.3 我的几条独家避坑经验最后分享几条平时文档里不写但实际项目里价值很高的经验。第一是把所有set_dft_signal声明集中到一个专门的tcl文件里并配上注释。这样第一review方便第二万一某个版本综合结果不对可以快速用git diff看哪些信号配置变了。在实际项目里这种“配置即代码”的管理方式帮我省了很多时间。第二是写完set_dft_signal后立刻跑report_dft_signal把最终的signal table打出来看一眼。不要嫌麻烦。这个报告能直观看到每条信号的类型、端口、极性、时钟关联很多配置错误在这一步就能发现不必等到dft_drc报错。第三是善用-hookup_pin。有些时候扫描链的输入输出不能直接绑定到顶层IO而是经过了一个多路选择器后才能连到IO。这种情况可以直接指定-hookup_pin告诉DC扫描链数据的实际连接点是那个mux的输出端。这个选项用得好可以省掉大量手工net连接也避免后续ECO时把扫描链路径改错。还有一条是关于“不要随意用-type Constant”。很多人在DRC报错后为了快速消错会把不确定的信号声明为Constant。这确实能让DRC快速通过但代价可能是ATPG覆盖率下降甚至某些测试向量根本无法生成。我的建议是每写一条-type Constant之前先确认这个信号在测试模式下是不是真的恒定并且要跟时钟、复位的配置联动检查不要孤立地消错。set_dft_signal这条命令通过合理的配置和策略能让整个DFT流程少走很多弯路。结合团队多年的项目经历我越来越觉得DFT做得好不好重点不在于工具跑得多快而在于前期对测试模式状态的定义是否精准。方向一旦确认了后面的道路就会顺畅很多。
返回列表