ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

DC时序分析实战:读懂SDC约束与关键路径,让时序收敛少走弯路

DC时序分析实战:读懂SDC约束与关键路径,让时序收敛少走弯路 简介DC时序分析是数字集成电路设计流程中的核心步骤这份90页PPT重点面向数字IC前端与后端工程师、FPGA开发者及微电子专业学生系统讲解综合工具DC下的时序分析与优化方法。内容涵盖建立时间与保持时间、扇入扇出、时钟偏斜、时钟延迟、抖动与时间裕量等关键参数并介绍设计中常用的时序约束、区域与位置约束以及静态时序分析STA与动态时序仿真之间的区别。资源包内仅1个文件为PPT格式整包2.24MB90页内容从同步电路数据传输模型出发延伸至最小时钟周期与最高频率计算、DC中set_clock_uncertainty设置等实践议题帮助读者理解实际工程中的时序收敛思路。结合具体讲解可理清启动边沿与捕获边沿在时序路径中的作用识别负裕量违规并调整约束适合作为数字IC时序概念的入门指南与查阅手册。已有1430人学习便于快速建立完整的时序分析知识体系。1. DC时序分析是什么综合阶段就要面对的那道坎DC时序分析是逻辑综合工具在做门级网表综合时对电路时序路径进行建立时间和保持时间检查的过程。90页PPT的体量拆开来看核心就一句话在网表还没变成版图之前先把时序问题暴露出来而不是等后端跑完 floorplan 再面对一片红色违例。很多团队把时序收敛押在后端优化上这是最贵的赌法。这个分析的现实价值在于它能回答三个问题综合出来的网表在目标频率下能不能跑起来哪些路径真正限制了频率为了修时序面积和功耗多花了多少。它服务的对象是数字IC前端工程师、做SoC集成的开发者以及刚接触flow、被时序报告吓住的初学者。读完这90页内容并动手跑过一轮你会形成一个习惯看任何一条路径的时序报告先找startpoint和endpoint再判断这条路径该不该存在——这个习惯比记住任何一条命令都值钱。2. DC时序分析到底在看什么建立时间、保持时间与时序路径2.1 为什么综合工具要内建时序引擎逻辑综合的本质是把RTL代码映射到标准单元库这个过程不能只做逻辑等价必须在映射的同时评估时序。原因很具体一个加法器可以用行波进位结构也可以用进位选择结构前者面积小但路径深后者速度快但面积大。如果综合工具没有时序引擎它就无法在面积和延迟之间做权衡最后只能给你一个最保守、最慢的电路。时序引擎在这里承担两个职责。第一是对当前映射结果做静态时序分析算出每条路径的slack第二是把slack作为优化目标指导工具替换单元、重组逻辑结构。这两件事在DC里是交替执行的不是先综合再分析的两段式流程。所以你会发现同样的RTL约束松和约束紧综合出来的网表结构差别很大这就是时序引擎导向的结果。DC的时序引擎建立在延迟计算之上。标准单元库里的每个单元、每根引脚之间的延迟都来自.lib文件里的查找表查找表按输入转换时间和输出负载两个维度索引。互连线的延迟在综合阶段只有估算模型因为此时没有实际版图。这个估算和最终signoff值之间的偏差是后面所有时序收敛问题的根源之一。2.2 setup和hold两条决定芯片能否跑起来的时间约束建立时间要求数据在时钟有效沿之前稳定下来。公式是数据路径总延迟加上时钟偏斜的修正要小于时钟周期减去建立时间。DC在综合阶段以setup作为主要优化目标因为setup违例直接影响最高工作频率而芯片能不能在目标频率下工作是流片前就要确认的事。保持时间要求数据在时钟有效沿之后继续稳定一段时间。它和时钟周期无关只和数据路径最短延迟、时钟偏斜有关。在综合阶段保持时间检查依赖的时钟树信息还不存在DC只能按理想时钟模型做估算加上set_clock_uncertainty来预留裕量。真实时钟树建成后保持时间违例主要由后端通过插buffer修复。这个分工新手要尽早理解不要在综合阶段为了hold零违例去堆buffer那是拿面积换一个后端迟早要重做的结果。setup和hold是一对矛盾。修setup要缩短数据路径通常是把长组合逻辑拆开、插入寄存器修hold要加长最短数据路径通常是插buffer。一个让路径变短一个让路径变长后端的时钟树综合会再次打破平衡。这就是为什么时序收敛是个反复迭代的过程而不是跑一次工具就能完成的任务。2.3 DC眼里的一条时序路径长什么样DC把时序路径分成四大类输入到寄存器、寄存器到寄存器、寄存器到输出、输入到输出。每一条路径都有明确的起点和终点。起点是时序单元的时钟引脚或输入端口终点是时序单元的数据引脚或输出端口。路径本身由组合逻辑单元串联而成延迟等于所有单元延迟和连线延迟之和。关键在时钟路径的处理方式。DC将时钟从时钟源到触发器时钟引脚这一段单独计算称为时钟路径延迟。数据路径上每个触发器的到达时间都要根据各自的时钟到达时间做调整。这就是为什么时钟uncertainty、时钟延迟会进入每条路径的计算——它们是路径的公共部分但影响每个触发器的方式不同。理解路径的分类对读报告至关重要。report_timing默认只报寄存器到寄存器的路径如果你想看输入到寄存器的路径必须用-from显式指定起点。很多新手看到默认报告里没有违例就以为时序收敛了其实IO路径可能已经烂到没法看。所以拿到DC生成的时序报告第一步不是看slack而是确认报告的路径类型覆盖了哪些起点终点。3. SDC约束90页PPT里真正值钱的部分3.1 先把时钟说清楚create_clock与时钟分组时钟是时序分析的基准。没有完整的时钟定义DC的时序引擎只能靠猜测猜测的结果就是一堆无意义的报告。创建时钟的基本命令是create_clock它定义时钟周期、波形、时钟源端口或引脚。一个设计如果有多个时钟必须逐个定义并考虑时钟之间的关系。create_clock -name clk_sys -period 10.0 -waveform {0 5} [get_ports clk_sys] set_clock_uncertainty 0.2 [get_clocks clk_sys]这里-period 10.0表示周期10纳秒对应100MHz-waveform {0 5}定义上升沿在0ns、下降沿在5ns也就是50%占空比。set_clock_uncertainty用于预留时钟抖动和偏斜的裕量综合阶段一般设周期的一定比例比如0.1到0.3纳秒。这个值不是拍脑袋定的要参考目标工艺下PLL的输出抖动规格和后端时钟树综合的偏斜预算。时钟定义完成后用set_clock_groups声明跨时钟域的异步关系。如果两个时钟来自不同PLL且没有同步机制就应该设为异步。这个声明直接影响DC是否分析跨时钟域路径漏了会导致大量伪违例多了会掩盖真实问题。set_clock_groups -asynchronous -group {clk_sys} -group {clk_periph}常见做法是为每个功能模块的时钟单独建分组。比如系统总线时钟和外围接口时钟通常频率不同、相位不同但存在真实的数据交互。这时候不能简单设为异步需要根据同步器的设计决定是否分析路径。我的习惯是只要有同步器就保留路径分析靠set_false_path只屏蔽同步器本身的时序要求而不是一刀切设异步。3.2 派生时钟分频、倍频和相位关系真实设计里大部分内部时钟不是独立生成的而是由一个主时钟经过分频或倍频产生。DC里用create_generated_clock定义这类时钟关键是要声明它相对主时钟的边沿关系这样工具才能正确处理跨时钟域的路径。create_generated_clock -name clk_div2 -source [get_pins u_pll/clk_out] \ -divide_by 2 [get_pins u_div/clk_div2]-source指定源时钟所在的引脚或端口-divide_by 2表示二分频get_pins u_div/clk_div2是生成时钟的引脚位置。DC会从源时钟的波形推导出分频时钟的波形不需要手动指定周期。派生时钟定义里最容易被忽略的是-master_clock。当源引脚上有多个时钟穿过时需要指定generated clock参考哪个master clock否则DC会按默认规则选一个选错就导致相位关系错误。还有一个常见问题是-combinational选项它用于定义经过组合逻辑后相位不变的时钟路径比如时钟经过MUX选择。这种情况如果漏定义DC会把MUX后面的时钟网络当普通数据路径分析约束会全部错乱。倍频时钟用-multiply_by相位调整用-edges加-edge_shift。这些参数组合起来可以描述任意分频倍频关系但每加一个选项约束的复杂度就上升一截。我的建议是能用简单选项就不用复杂选项-divide_by和-multiply_by能解决的问题不要用-edges手写边沿。3.3 IO路径约束input/output delay的两种参考方式IO路径的约束是整个SDC里最容易被胡乱设置的部分。input delay表示外部数据相对于参考时钟的到达时间output delay表示外部电路对输出数据的要求到达时间。两者的单位都是纳秒但语义正好相反。set_input_delay -max 3.0 -clock clk_sys [get_ports data_in] set_output_delay -max 2.5 -clock clk_sys [get_ports data_out]-max对应setup分析-min对应hold分析。外部器件的输出延迟、PCB走线延迟都要折算进input delay接收芯片的建立时间、PCB走线延迟折算进output delay。合理的做法是参照芯片数据手册的时序参数逐项累加而不是随便填一个值。时序约束的精度直接决定综合结果的面积——约束过紧工具会用更多逻辑去加速IO路径面积暴涨约束过松后端布线后IO时序翻车。IO约束还有一个容易漏掉的关键点对外部数据总线的位宽和方向要确认每一个端口都设置到了。总线里漏掉一个位DC会把它当未约束路径处理报告里不会显示违例流片后这个位就可能在边界上出问题。我会在写约束后用report_ports检查所有IO端口是否都有约束覆盖确保没有端口处于未约束状态。3.4 时序例外false_path、multi_cycle_path、max_delay时序例外是SDC里最强大也最容易滥用的部分。set_false_path用于声明某些路径不需要时序检查典型场景是跨时钟域的同步器路径、测试模式下的扫描路径。set_multicycle_path用于声明某些路径允许跨越多个时钟周期典型场景是握手信号、大规模存储器读写。set_false_path -from [get_cells u_sync*/r1] -to [get_cells u_sync*/r2] set_multicycle_path -setup 2 -from [get_clocks clk_a] -to [get_clocks clk_b]set_multicycle_path -setup 2告诉DC这条路径允许两个周期完成常用于两个时钟频率成整数倍的跨时钟域路径。设了setup的multicycle后hold约束也需要对应调整——默认情况下工具的hold检查是基于setup检查沿的前一个沿多周期路径不显式设hold会导致hold约束被错误地放松或收紧。时序例外的本质是对设计者意图的声明声明错了工具不会报错它会安静地给出一个满足错误约束的结果。所以我倾向于在设计文档里单独维护一份时序例外清单写清楚每条例外的原因和依据。review阶段拿着这份清单逐条讨论比在SDC文件里翻注释高效得多。这也正是那90页PPT里反复强调的事情约束不是写给工具看的是写给下一个接手的人看的。4. 读完一份DC时序报告从时序违反到关键路径定位4.1 报告结构slack、data arrival/required、时钟沿DC的时序报告有固定结构。报告头部给出路径类型、起点终点、时钟信息中间部分是数据到达时间和要求时间的逐项展开最下面是slack的计算结果。slack为负表示违例为正表示满足零是临界状态。对设计者来说最需要关注的是data arrival和data required两项各自由什么组成。clock clk_sys (rise edge) 10.000 clock network delay (propagated) 0.300 clock uncertainty -0.200 clk_sys (rise edge) 9.900 data required time 9.900 ----------------------------------------------------------- clock clk_sys (rise edge) 10.000 clock network delay (propagated) 0.300 clock uncertainty -0.200 u_reg1/CK (rise edge) 10.100 ... combinational path delay 8.300 data arrival time 18.400 ----------------------------------------------------------- slack (MET) 0.200报告里的每一项都有具体含义。data required time是目标触发器的建立要求data arrival time是数据从源触发器时钟沿到目标触发器数据端的实际传播延迟slack是两者之差。你不需要记住所有字段但必须能快速定位是数据路径延迟过大还是时钟偏斜把裕量吃掉了。这个区分决定了是改逻辑还是改约束。报告中有两处最容易引起误解。一是clock uncertainty出现在两端但符号相反它同时扣减数据路径裕量和增加数据路径延迟实际影响要按公式逐项算。二是clock network delay的值如果用的是ideal时钟模型这个值是估算的不必为它的精确度纠结如果用的是propagated模型这个值来自时钟树综合结果可靠性高得多。4.2 从report_timing的文本定位瓶颈拿到一份大design的时序报告有几千条违例路径逐条看是不现实的。正确做法是先按路径类型分类再按slack值排序最后针对最差的几十条做详细分析。DC提供了一些选项来组织报告的输出方式。report_timing -max_paths 100 -nworst 1 -path_type full -delay_type max-max_paths 100表示报告100条最差的路径-nworst 1表示每条路径只报最差的一条避免同一路径因为路径分析上升沿下降沿不同而重复出现-delay_type max对应setup检查。这个组合是定位setup违例最常用的命令形态。report_timing -from [get_pins u_core/u_alu/a[15]] -to [get_pins u_core/u_alu/y[7]]指定起点终点后报告会只显示这两点之间的路径。这在分析特定逻辑模块的延迟时很有用。检查一条路径是不是true critical path通常做法是看路径上有没有RTL级别知道的核心逻辑以及路径的单元级数是否和预判一致。如果一条路径的级数远大于预期问题往往出在逻辑结构上——比如综合器把一个多位比较器展开成了串行结构而不是树形结构。报告路径里还有个经常被忽视的信息路径经过的每一级单元的延迟占比。一个单元延迟占路径总延迟超过30%就需要确认这个单元是不是该换一种结构。比如一个18位加法器进位链上的延迟通常占比很高此时考虑用超前进位结构重新综合比在约束里加裕量更本质。4.3 面积与关键路径的权衡怎么判断一个违例能不能收每一条时序违例都有两种处理方向改逻辑或者放约束。改逻辑意味着面积、功耗上升放约束则意味着该路径的时序风险和不确定性转移到后端。DC的时序报告里面积和时序的关系通过另一个命令体现。report_qorreport_qor汇总了整个设计的WNS、TNS和总面积。WNS是最差负裕量代表单条路径的最差情况TNS是所有负裕量的总和代表整体违例的严重程度。这两个指标是判断设计是否可收敛的关键依据。WNS差但TNS小说明问题集中在少数路径可以定向优化WNS和TNS都差说明约束整体过紧或设计本身存在大量长路径需要从架构层面调整。判断一条违例路径能不能收看它的约束构成。用report_constraint -all_violators检查违例类型分布如果大量违例来自false_path该处理而没有处理的路径先清理约束如果违例集中在真正的高频数据通路才考虑改逻辑。DC的compile_ultra已经在优化逻辑结构你手动改RTL的效果比在约束里盲目加压可预测得多。一条路径的耗时和面积收益的权衡有固定套路先缩短组合逻辑级数用并行结构替代串行结构不行再考虑调整寄存器的位置把组合逻辑拆到两级最后才考虑加约束放宽松。反过来调大概率是浪费一轮迭代。5. 时序分析避坑DC里最容易翻车的五个细节5.1 时钟网络没有完整约束导致报告大面积空白现象report_timing没有输出或者只有零星几条路径而设计里明明有几千个触发器。原因时钟端口没有用create_clock定义或者定义时使用了通配符但没有匹配到任何引脚。DC不会告诉你时钟没找到它只会安静地不分析相关路径。解决跑report_clock检查所有时钟是否定义特别是内部PLL输出和分频节点。我习惯在综合脚本里加断言检查时钟数量是否符合预期。5.2 set_false_path滥用真实路径被掩盖现象时序报告全绿但芯片回来后功能在特定场景下失效。原因把带跨时钟域同步器的路径直接设了false_path而同步器本身深度不够二拍同步器在极端相位关系下仍然存在亚稳态传播可能。解决跨时钟域的路径要区分对待。有同步器的路径只对同步器的第一级寄存器设false_path后面的路径保留分析。没有同步器的跨时钟域路径必须用set_clock_groups声明异步并且RTL里要保证数据稳定性。用false_path掩盖设计缺陷是引线最深的坑。5.3 set_clock_uncertainty当成周期裕量的提款机现象为了给后端留余量把uncertainty从0.1加到0.5结果综合出的面积暴涨功耗也超了。原因uncertainty直接同时影响setup和hold的预算每增加0.1ns工具就要在数据路径上多压缩0.1ns压缩的手段只能是换更快的单元或拆逻辑代价是面积。解决区分对待jitter和skew。jitter由时钟源决定skew由后端时钟树决定。综合阶段不确定的部分留0.1到0.2ns足够更多余量留给后端在CTS后根据真实值收紧。在综合阶段过度加压等于花两倍面积买个保险。5.4 综合阶段追求hold零违例现象综合后的hold报告全是负的有人试图在综合阶段加约束修到正数。原因hold时序在综合阶段用的是理想时钟模型时钟树还没生成偏斜全是估算。此时修的平衡在CTS之后会被真实的时钟树延迟彻底打破。解决综合阶段只要确认hold违例的量级在合理范围一般几皮秒到几十皮秒直接留给后端修。在综合阶段为了hold去加buffer会造成面积浪费而且修完也是白修。正确做法是在CTS之后回到DC或直接用PT做post-CTS hold检查再决定是否修。5.5 忽略IO端口约束状态检查现象综合报告里没有IO违例但PCB回来后板上数据采样出错。原因input/output delay没有被正确设置IO路径处于未约束状态。DC对未约束路径的默认处理是不检查所以报告里当然看不到违例。解决约束写完后跑report_ports检查每个端口是否都被定义了input/output delay和驱动/负载信息。未约束的端口会以unconstrained的形式列出来。这个习惯比看时序报告本身更重要因为未约束路径不产生任何报告项是纯粹的黑匣子。6. 把DC时序换算成流片前的底气敲定DC与signoff工具的一致性DC分析完时序不意味着设计就稳了。综合阶段用的是互连线估算模型和理想时钟而流片前签核用的是提取后的真实寄生参数。所以真正要紧的动作是拿DC的时序结果和签核级工具的结果做交叉验证。两者之间的偏差如果控制不住综合阶段做的一切都是盲人摸象。我常用的一套验证流程是同一个网表先让DC跑一遍时序报告记录WNS和TNS再用后端的寄生参数文件跑一遍静态时序分析比较两份报告的关键路径和slack。偏差主要来自三个来源时钟模型差异、互连线模型差异、单元延迟计算方法差异。如果把两者差异缩小到可控范围靠的是约束一致性。SDC文件必须完全一致任何一边改动都要同步这是最基本的要求。其次是时钟处理方式DC里用ideal时钟后端工具用propagated时钟这两者的差异是可以提前估算的。常见做法是在SDC里保留合理的时钟uncertainty等CTS后把uncertainty更新为实际值再跑一轮确认。我的一次血泪教训是DC时序报告里有个寄存器的setup slack是0.05ns看着是满足的就没在意。后端跑完时钟树拿到传播时钟的实际偏斜这一条路径变成了负1.2ns。根因是DC里时钟uncertainty没给够而我信了那个0.05的假绿。从那以后我养成了检查关键路径时一定同时看数据路径延迟和时钟偏斜构成的习惯不再被slack的符号麻痹。希望这一点对正在被DC时序报告折磨的你有用。验证这一轮还有个具体的技巧。比较DC和签核工具输出的关键路径如果排序前20的路径重合度低于70%说明两边的时序模型偏差较大要优先排查时钟约束的一致性而不是急着在综合阶段调逻辑。路径重合度高再去看每条路径的slack偏差逐个分析偏差来源。这个流程能在综合早期就把后端的风险压下来至少一半。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进