ARTICLE DETAIL

资讯详情

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

芯片后端时序路径分析入门:从SDC约束到时序收敛

芯片后端时序路径分析入门:从SDC约束到时序收敛 做过芯片后端的人应该都有过这样的经历RTL仿真明明全绿综合和布局布线也没报错结果芯片回来后跑到目标频率就随机死机、偶尔出乱码查来查去最后定位到时序路径收敛不彻底。时序路径分析说到底是芯片能不能在你承诺的频率下稳定运行的基石。这篇先聊基础——什么是时序路径、它有哪几类、slack公式背后的物理含义以及从SDC约束到时序报告的一次完整分析流程。适合刚接触芯片后端、或者从验证/前端转向后端的工程师把这些吃透了后面再看修复手段和时序收敛技巧会顺很多。1. 为什么时序路径分析是芯片能否跑起来的胜负手先说个直观的理解。芯片里几十亿个晶体管本质上干的活就是依据时钟节拍把数据从一个寄存器搬到下一个寄存器中间经过组合逻辑做各种运算。所谓时序路径就是一条数据从“发射端”出发经过组合逻辑到达“捕获端”的完整物理链路。1.1 一个时钟周期里的三方赛跑每个时钟周期芯片都在进行一场三方赛跑发射沿Launch Edge源寄存器的时钟沿把数据推出来数据从Q端出发。数据通路Data Path数据经过组合逻辑一路赶往目的寄存器的D端。捕获沿Capture Edge目的寄存器的下一个时钟沿到来把D端数据锁存进去。这三者的时间关系如果出了偏差捕获端就可能采到上一拍的数据、采到中间态、甚至采到亚稳态。功能仿真为什么发现不了因为仿真默认所有逻辑都没有延迟数据“瞬间”到位但你手里的芯片不是这样的。每一级门都有延迟每一段绕线都有RC延迟这些延迟叠加起来就是数据通路真实的到达时间。1.2 时序分析在芯片设计流程里的位置时序路径分析贯穿整个后端流程只是在不同阶段干活的精度不一样逻辑综合阶段用线负载模型估算延迟检查时序大致是否收敛。这个阶段的核心目标是别让架构上有硬伤。布局布线阶段每一级绕线的实际RC参数出来了时序分析越来越贴近真实。这里要反复做增量优化处理setup violation和hold violation。签核Signoff阶段用寄生参数提取后的最精确网表做STAStatic Timing Analysis结合工艺库的PVT corner确认所有路径在最恶劣条件下依然满足时序要求。很多刚入行的朋友会问时序分析名字里带“静态”是不是就不用仿真激励了对STA跟动态仿真最大的区别就在这——它不需要输入向量而是把所有可能的路径全部枚举一遍按最悲观条件检查。这既保证了覆盖率也避免了向量不完备漏掉关键路径。1.3 为什么说它决定产品命运芯片设计是个成本极高的行当一颗SoC从架构到回片动辄千万级投入。时序分析如果不到位最轻的后果是芯片只能降频使用标称1.8GHz只能跑1.2GHz产品竞争力直接打折。严重的情况下芯片在特定电压、温度下出现偶发功能错误这种问题在现场极难复现往往要折腾几个月才能定位到是时序问题。所以在物理设计里时序收敛是比面积、功耗更靠前的硬指标——面积大点还能接受功耗高点还能优化时序不过什么都白搭。2. 四条基本路径从端口到寄存器的完整地图拿到一个设计第一步不是急着看报告而是先把设计里的时序路径分好类。STA工具把所有路径归成四大类每一类的起点终点不同约束方式也不同。2.1 寄存器到寄存器Reg-to-Reg这是最常见、也最关键的一类路径。起点是某个寄存器的时钟引脚终点是另一个寄存器的数据输入引脚。中间穿过组合逻辑网络。芯片内部绝大部分关键路径都出在这里因为寄存器数量最多、逻辑层级最深。这类路径的分析重点在于发射沿和捕获沿分别由哪个时钟控制两个时钟是不是同源组合逻辑延迟有多大。如果设计和约束都正确工具会严格按这两个寄存器的时钟关系计算setup和hold。常见问题是跨时钟域CDC路径没做好同步处理此时工具会按异步关系处理或者需要显式声明。2.2 输入端口到寄存器Input-to-Reg这类路径从芯片的输入引脚开始经过片内组合逻辑终止于寄存器。因为起点在芯片外部工具没法知道外部信号什么时候到达引脚必须靠你通过set_input_delay告诉它。打个比方芯片像一家餐厅外部器件像送食材的供应商。你得告诉厨师食材每天早上8点送到门口厨师才能安排几点开火。set_input_delay就是这个“供应商到达时间”承诺书。设置时要区分最大值和最小值——最大值用于setup检查最小值用于hold检查。2.3 寄存器到输出端口Reg-to-Output这类路径从内部寄存器出发经过组合逻辑终止于输出引脚。终点是芯片外部工具不知道外部器件什么时候来取数据于是需要set_output_delay。set_output_delay描述的是外部器件在时钟沿之后多久需要看到稳定数据本质上是给内部数据到达时间划了一条线。这里的坑在于外部延迟要按外部芯片的真实时序参数来填不能拍脑袋。填大了内部过度优化填小了流片后接口数据采不稳。2.4 输入端口到输出端口In-to-Out纯组合逻辑路径起点和终点都是芯片引脚不经过寄存器。这类路径在同步设计里数量不多但也不能完全忽视。由于没有时钟捕获工具不会做setup/hold检查通常用set_max_delay或set_min_delay来约束或者声明为false path。我个人的经验是新设计里如果出现大量这类路径最好先反问一句设计架构是不是合理的——现代SoC设计原则上应该尽量把组合逻辑封在寄存器之间让时序边界清晰可控。纯组合输入输出路径太多会给时序收敛和DFT都带来额外负担。路径类型起点终点典型约束检查方式Reg-to-Reg源寄存器时钟脚目的寄存器数据脚create_clocksetup/holdInput-to-Reg输入端口寄存器数据脚set_input_delaysetup/holdReg-to-Output寄存器时钟脚输出端口set_output_delaysetup/holdIn-to-Out输入端口输出端口set_max_delay / false path延迟检查3. 建立时间与保持时间slack公式背后的物理逻辑时序路径分析最核心的两个检查就是建立时间Setup Time和保持时间Hold Time。理解这两个概念不能只背定义要把它们的物理逻辑吃透。3.1 建立时间数据必须在时钟沿前“稳住”建立时间指的是在捕获时钟沿到来之前D端数据必须保持稳定的最小时间。如果数据到得太晚D端还在变化寄存器就会采到一个不确定的状态。用个生活中的例子上课铃声是捕获沿建立时间就是铃响之前你必须坐好并翻开课本的那段时间。如果你踩着铃声冲进教室、还没坐稳老师寄存器看到的你就是一个“没准备好”的状态。套到公式上data arrival time T_launch T_ck2q T_comb data required time T_capture T_clk_period - T_setup - T_uncertainty setup slack data required time - data arrival time所有延迟在STA工具里都换算成相对于某个基准时刻的绝对时间。slack为正说明路径满足建立时间要求即数据到达时间早于最晚允许时间slack为负就是建立时间违反。3.2 保持时间数据在时钟沿之后“不能马上变”保持时间是指在捕获时钟沿到来之后D端数据还必须继续保持稳定的最小时间。这防止的是数据变化太快导致上一拍还没锁存完整就被新数据冲掉。回到教室的类比保持时间是铃响之后你还得在位子上多坐一会儿不能铃一响就立刻蹿出去。如果上一拍数据刚被采进去下一拍的数据已经冲到D端寄存器就会把新旧数据混在一起。hold slack T_launch T_ck2q T_comb - T_capture - T_hold - T_uncertainty注意这个公式里没有时钟周期。为什么因为保持时间检查的是同一个时钟沿附近的行为跟周期长短无关。所以一个很反直觉的结论是降频可以解决setup violation但解决不了hold violation。哪怕时钟降到1Hz只要数据在捕获沿之后太快变化hold照样违反。3.3 时钟偏斜对两条路径的相反作用时钟偏斜Clock Skew是指同一个时钟信号到达不同寄存器的时间差。它对setup和hold的影响正好相反对setup如果捕获时钟到达得晚相当于给数据多争取了一点时间setup更宽松。对hold如果捕获时钟到达得晚捕获动作也变晚数据在这段时间里可能会变化hold更紧张。这就是为什么后端要做时钟树综合CTS目的就是尽量平衡各个寄存器的时钟到达时间让偏斜可控。有些工程师为了修setup故意给捕获端加延迟useful skew但这是在给hold挖坑。做的时候一定要整套分析跑一遍不能拆开看。4. 从SDC到时序报告一次完整STA的实操拆解理论说完了进到实操层面。一次标准的时序分析至少要经历三步写SDC约束、跑STA工具、解读报告。三步里每一步都有容易翻车的细节。4.1 SDC约束时钟定义是第一块地基SDCSynopsys Design Constraints是整个时序分析的地基约束错了后面所有报告都是空中楼阁。最基础也是最重要的几条# 定义主时钟周期10ns占空比50% create_clock -name clk -period 10 -waveform {0 5} [get_ports clk] # 虚拟时钟用于约束和外部器件的接口 create_clock -name vclk -period 10 # 输入端口的延迟约束 set_input_delay -max 3 -clock vclk [get_ports data_in] set_input_delay -min 1 -clock vclk [get_ports data_in] # 输出端口的延迟约束 set_output_delay -max 4 -clock vclk [get_ports data_out] set_output_delay -min 1 -clock vclk [get_ports data_out] # 时钟不确定性包含时钟抖动、余量等 set_clock_uncertainty 0.2 [get_clocks clk] # 跨时钟域路径声明 set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b]create_clock是第一步其他约束很多都依赖时钟才能写。这里有个常见错误有人图省事把input delay直接挂在内部时钟上结果外部器件的时序参考和实际不符接口时序全乱。正确做法是配套定义一个虚拟时钟让外部接口的时序参考关系清晰独立。set_input_delay的max和min分别对应外部器件在最慢和最快情况下的到达时间。max大了内部压力大min小了hold检查可能放松。这两个值都应该从外部器件的数据手册里查或者跟系统集成工程师确认不能拍脑袋。4.2 解读一份真实的时序报告工具跑完以后会生成大量报告很多人一上来就盯着slack看这个习惯得改。正确顺序是先看路径类型再看时钟域最后看违反值。拿一段典型的setup violation报告举例关键字段按顺序读Path Group说明这条路径属于哪个时钟组先判断是不是跨时钟域的误报。Startpoint / Endpoint起点和终点帮助你快速判断是内部路径还是IO路径。Launch Clock / Capture Clock发射时钟和捕获时钟确认是同一时钟域。Data Arrival Time数据实际到达的时刻。报告会把它拆成时钟源延迟、寄存器CK-to-Q延迟、组合逻辑延迟、绕线延迟等。Data Required Time数据最晚必须到达的时刻。它由捕获时钟沿、setup时间、时钟偏斜综合算出。Slack两者之差负值就是violation。我常用的排查套路是这样的如果slack是负的先展开数据到达时间那一列看是组合逻辑延迟大还是绕线延迟大。组合逻辑大说明逻辑层级太深需要用retiming或者插流水绕线延迟大多半是布局太分散需要去看物理位置。如果数据到达时间不大、required time却很小那问题可能出在时钟偏斜或uncertainty设置上。4.3 约束质量决定报告可信度STA有个铁律garbage in, garbage out。SDC约束的质量直接决定报告的可信度。我见过最典型的反面案例是一个设计忘了给某条异步路径设false path跑出来的violation有上千条整个团队花了一周时间对着报告折腾最后才发现是约束漏了。浪费的时间比重新写约束多得多。所以我的建议是在跑全芯片STA之前先做约束质量检查Constraint Quality Check。逐条核对时钟定义、时钟域划分、input/output delay的合理性、有没有缺失的false path、有没有重复约束。工具本身有几个内建检查命令比如report_clock -skew、report_timing -path_type full多花十分钟查约束比事后对着几千条violation发愁要划算得多。5. 时序收敛中最容易翻车的几个误区最后聊几个我在实际项目里见过很多次的翻车场景。这些坑书上不会明写但在团队里几乎代代相传。5.1 false path乱设等于给自己埋雷set_false_path是个好工具但也是一把双刃剑。正确用途是声明那些不需要检查时序的路径比如测试模式下的逻辑、静态配置信号。错误用法是为了让报告好看把难收敛的路径直接声明成false path跳过检查。我见过一个项目后端工程师嫌一条跨时钟域路径烦直接设了false path结果芯片回来后那个模块在特定场景下随机出错最后花了一个多月才定位到是CDC路径没有做同步处理数据跨时钟域采样出现了亚稳态。记住一句话set_false_path不能替代设计修复它只能告诉工具“这条路径不需要检查”。如果这条路径实际上需要正确工作你就是在拿芯片良率开玩笑。5.2 hold violation不是小事很多新手对hold不敏感因为hold违反不像setup那么直观——它不是“跑不到频率”而是“数据变化太快”。但正因如此它在芯片上极难诊断。芯片回来如果hold违规严重表现通常是无论怎么降频都还是会出错只能靠加电压或者碰运气。相比之下setup违规降频往往还能用hold违规几乎无解。为什么hold这么难搞因为hold跟时钟周期无关只跟数据通路的短路径延迟和时钟偏斜有关。修复手段主要靠插入延迟缓冲器delay buffer或者调整时钟树但这些操作会影响别的路径牵一发动全身。所以业界普遍做法是先修hold再修setup或者至少分开两轮跑不要混在一起。5.3 只看worst path不看整体分布还有一个常见操作偏差有些人盯着report_timing的第一条worst path把这条修好了就觉得万事大吉。但时序收敛看的是整体分布。worst path修好了第二差、第三差可能仍然违反。而且工具在修路径时是有连锁反应的修好一条可能破坏另外几条。我的习惯是跑完report_timing -max_paths 1000然后用脚本统计一下violation的斜率分布。如果只有几条负slack小的路径说明是局部修一修就行的程度如果有大量负slack大的路径那说明要么是约束问题要么是架构上的逻辑层级太深需要动大手术。5.4 关于uncertainty多一点比少一点好set_clock_uncertainty是拿来吸收时钟抖动、电路噪声和预测误差的余量。很多工程师为了报告好看把uncertainty设得特别小。我不建议这么干。真实芯片的时钟受电源噪声、温度变化、工艺偏差影响永远不可能像工具算的那么精确。如果设计阶段不留够余量流片后时序余量不足的路径会在某些PVT corner下出问题。宁可前端多留一点uncertainty多修几条violation也好过片子在现场随机出错。我个人的经验是uncertainty通常按时钟周期的百分之二到百分之五起步再根据时钟源的质量和PLL的抖动指标调整。激进不是本事稳才是。回到开头那个例子——那批芯片最后定位下来其实问题不在逻辑功能而是一条IO路径的input delay设置比真实情况乐观了0.5ns导致芯片在高温低压环境下接口数据采样偶发错误。后来我们把约束修正、重新收敛同一版GDSII再流片回来就完全正常了。时序路径分析这个东西基础概念看着不难但每一条细节都可能决定芯片的生死。这篇把路径分类、setup/hold原理和分析流程梳理完了下一篇我会接着聊实际项目里常用的时序修复手段——插缓冲器、retiming、useful skew、以及怎么在功耗和时序之间做取舍。
返回列表