SDC时钟约束:logically_exclusive与physically_exclusive区别详解

发布时间:2026/9/28 23:45:08
SDC时钟约束:logically_exclusive与physically_exclusive区别详解 1. 时钟约束里最容易踩坑的两个概念做数字后端或者静态时序分析的朋友大概率在SDC里写过set_clock_groups这条约束。写起来简单一行命令的事但真正理解-logically_exclusive和-physically_exclusive区别的人说实话没那么多。我见过太多项目约束写得能跑通STA报告也干净但最后芯片回来发现某些路径根本没被正确检查或者被过度约束导致面积和功耗白白浪费。这篇文章就围绕这两个概念展开把它们的本质、适用场景、实操写法、以及我在实际项目中踩过的坑一次性讲透。不管你是刚接触SDC约束的新人还是做了几年后端但一直没深究过这两个选项的老手应该都能从中拿到一些可以直接用的东西。先给个最直观的结论logically_exclusive说的是这两个时钟在逻辑上不可能同时存在physically_exclusive说的是这两个时钟在物理上就不可能同时到达同一个点。前者是功能层面的互斥后者是结构层面的互斥。听起来差不多但它们在时序分析引擎里的处理方式完全不同用错了后果也不一样。核心关键词logically exclusive、physically exclusive、时钟约束、set_clock_groups、SDC这几个词会贯穿全文。下面我会从设计思路、核心细节、实操过程、问题排查四个维度来拆解。2. 为什么需要时钟组约束从时序分析的底层逻辑说起2.1 没有时钟组约束时STA工具在干什么默认情况下STA工具会对设计中所有时钟之间的路径都做时序检查。假设你的设计里有CLK_A和CLK_B两个时钟工具会检查CLK_A到CLK_A的路径同频同相正常检查CLK_B到CLK_B的路径同频同相正常检查CLK_A到CLK_B的路径跨时钟域按默认关系检查CLK_B到CLK_A的路径跨时钟域按默认关系检查问题就出在后两条。如果CLK_A和CLK_B之间根本没有功能上的数据交互或者它们永远不会同时工作那工具检查这些跨时钟路径就是在做无用功。更糟糕的是如果工具找不到这两个时钟之间的确定相位关系它会报出大量无法收敛的时序违例或者直接给一个悲观的默认约束让你的设计被过度约束。我刚开始做后端的时候就遇到过这种情况一个设计里有个测试时钟和一个功能时钟测试时钟只在扫描链测试时用功能模式下完全不工作。但STA工具不知道这件事它老老实实地检查了功能时钟到测试时钟的所有路径报了几百条违例。当时我一条一条去分析花了两天时间才发现这些路径根本不需要检查。2.2 set_clock_groups的基本语法与作用set_clock_groups就是用来告诉工具这些时钟之间的关系不用检查。基本语法长这样set_clock_groups -logically_exclusive \ -group {CLK_A} \ -group {CLK_B}这条命令的意思是CLK_A和CLK_B在逻辑上是互斥的它们之间的路径不需要做时序检查。注意这里用的是-group每个-group里可以放多个时钟同一个group内的时钟之间仍然会做检查不同group之间的时钟才会被排除。这里有个容易搞混的点-group不是-name。-name是给这个时钟组起个名字方便后续引用-group是定义组的成员。很多人第一次写的时候会把这两个搞混。2.3 两种互斥的本质区别回到核心问题logically_exclusive和physically_exclusive到底差在哪逻辑互斥的场景是这样的两个时钟在功能上不会同时活跃。比如一个芯片有正常功能模式和测试模式功能模式下用PLL输出的时钟测试模式下用外部直接输入的时钟。这两个时钟在任意时刻只有一个在工作它们之间的路径不需要检查。但它们在物理上是可能同时到达某个节点的——比如一个多路选择器的两个输入端只是选择信号保证了只有一个能通到输出。物理互斥的场景则是两个时钟在物理结构上就不可能同时到达同一个点。最典型的就是时钟MUX的两个输入。如果MUX的选择端是固定的比如被某个配置寄存器控制那么在任何时刻MUX的输出只会跟随其中一个输入。两个输入时钟在物理上被MUX隔开了它们不可能同时驱动MUX后面的逻辑。这个区别为什么重要因为STA工具在处理这两种情况时对时钟路径的传播方式不同。logically_exclusive只是告诉工具不要检查这些时钟之间的路径但工具仍然认为这些时钟可以传播到共同的节点。physically_exclusive则告诉工具这些时钟在物理上就被隔开了工具会据此调整时钟传播的模型。注意如果你的设计里有时钟MUX而且MUX的选择端是动态切换的那这两个时钟既不是逻辑互斥也不是物理互斥而是需要做时钟切换检查clock switching check。这种情况用set_clock_groups是解决不了的得用其他方法。3. 核心细节解析从工具行为反推约束写法3.1 工具如何处理logically_exclusive当你写下-logically_exclusive时STA工具会做以下几件事第一它会记录这两个时钟组之间的互斥关系。在后续的时序分析中任何从组A的时钟到组B的时钟的路径都会被标记为不需要检查。第二它仍然会计算这些时钟的到达时间arrival time仍然会做时钟树综合CTS时的时钟传播。换句话说工具在物理层面仍然认为这两个时钟都可能到达它们共同驱动的节点。第三如果这两个时钟组之间有组合逻辑路径工具会把这些路径的时序检查排除掉但不会改变这些路径的物理结构。这里有个关键点logically_exclusive不会影响时钟的传播。也就是说如果你有一个时钟MUX两个输入时钟分别来自不同的PLL你用logically_exclusive告诉工具它们互斥但工具在做时钟树综合时仍然会认为这两个时钟都可能通过MUX传播到后面的触发器。这可能导致CTS工具在MUX后面插入的缓冲器需要同时满足两个时钟的约束从而产生过度设计。3.2 工具如何处理physically_exclusive-physically_exclusive的处理方式则不同。工具不仅会排除这两个时钟组之间的路径检查还会在时钟传播模型中认为这两个时钟在物理上被隔开了。具体来说工具会认为这两个时钟不可能同时到达它们共同驱动的任何节点。这意味着在CTS阶段工具可以针对每个时钟分别优化时钟树而不需要考虑另一个时钟的影响。这个区别在时钟MUX的场景下特别明显。假设你有一个2选1的时钟MUX输入是CLK_A和CLK_B输出是CLK_OUT。如果你用logically_exclusive工具会认为CLK_A和CLK_B都可能传播到CLK_OUTCTS会尝试找一个折中的方案来满足两个时钟的约束。如果你用physically_exclusive工具会认为CLK_A和CLK_B在物理上互斥CTS可以分别针对CLK_A和CLK_B优化不需要折中。3.3 两种约束的适用场景对照为了更清楚地说明我整理了一个对照表场景推荐约束原因功能时钟与测试时钟logically_exclusive功能上不会同时工作但物理上可能同时到达时钟MUX的两个输入选择端固定physically_exclusive物理上被MUX隔开不可能同时到达时钟MUX的两个输入选择端动态切换需要clock switching check两个时钟可能同时活跃需要特殊处理不同频率的异步时钟域logically_exclusive功能上无数据交互不需要检查同一PLL输出的不同分频时钟通常不需要约束它们之间有确定的相位关系应该正常检查主时钟与备份时钟physically_exclusive物理上通过MUX切换不会同时工作这个表不是绝对的具体还要看设计的功能和结构。但大方向是这样的。3.4 一个容易被忽略的细节-group的顺序set_clock_groups命令中-group的顺序不影响结果。也就是说set_clock_groups -logically_exclusive -group {CLK_A} -group {CLK_B}和set_clock_groups -logically_exclusive -group {CLK_B} -group {CLK_A}是完全等价的。工具会把所有group之间的路径都排除掉。但要注意如果你有多个时钟组比如三个组A、B、C那么工具会排除A-B、A-C、B-C之间的所有路径。如果你只想排除A-B和A-C但保留B-C的检查那就需要分开写set_clock_groups -logically_exclusive -group {CLK_A} -group {CLK_B} set_clock_groups -logically_exclusive -group {CLK_A} -group {CLK_C}这样B和C之间的路径仍然会被检查。4. 实操过程从约束编写到验证的完整流程4.1 第一步识别设计中的时钟关系在写任何约束之前你得先搞清楚设计里有哪些时钟它们之间是什么关系。我通常的做法是从综合后的网表或者RTL里提取所有时钟定义画出时钟结构图标出每个时钟的来源、频率、相位关系标出时钟之间的交互点比如MUX、分频器、门控单元根据功能规格确定哪些时钟对之间不需要做时序检查这一步看起来简单但实际项目中经常被忽略。我见过有人直接复制粘贴别人的约束文件结果时钟名字都对不上约束根本没生效。4.2 第二步编写set_clock_groups约束假设你的设计里有以下时钟CLK_FUNC功能时钟来自PLL200MHzCLK_TEST测试时钟来自外部引脚50MHzCLK_RTC实时时钟32.768kHz功能规格说明正常工作时只用CLK_FUNC测试时只用CLK_TESTCLK_RTC始终工作但与另外两个时钟无数据交互。那么约束可以这样写# 功能时钟与测试时钟逻辑互斥 set_clock_groups -logically_exclusive \ -group {CLK_FUNC} \ -group {CLK_TEST} # RTC与功能时钟逻辑互斥 set_clock_groups -logically_exclusive \ -group {CLK_RTC} \ -group {CLK_FUNC} # RTC与测试时钟逻辑互斥 set_clock_groups -logically_exclusive \ -group {CLK_RTC} \ -group {CLK_TEST}如果你确定CLK_FUNC和CLK_TEST是通过一个固定选择的MUX切换的那可以用-physically_exclusiveset_clock_groups -physically_exclusive \ -group {CLK_FUNC} \ -group {CLK_TEST}4.3 第三步验证约束是否生效写完约束后一定要验证。我常用的验证方法有几种方法一检查STA报告中的路径跑一次时序分析看看报告里还有没有跨时钟域的路径。如果约束生效了这些路径应该被标记为excluded或者根本不出现。方法二用report_clock_groups命令很多STA工具支持report_clock_groups命令可以直接列出当前生效的时钟组约束。比如report_clock_groups这会输出所有已定义的时钟组及其互斥关系你可以对照检查是否有遗漏或错误。方法三手动检查关键路径挑几条你确定应该被排除的路径用report_timing命令单独检查report_timing -from [get_clocks CLK_FUNC] -to [get_clocks CLK_TEST]如果约束生效这条命令应该报出no paths或者类似的提示。4.4 第四步处理约束冲突实际项目中经常会出现约束冲突的情况。比如你写了logically_exclusive但工具报出警告说这两个时钟之间有路径被其他约束覆盖了。这时候需要检查是否有其他set_clock_groups命令定义了不同的互斥关系是否有set_false_path命令与时钟组约束重叠是否有set_max_delay或set_min_delay命令影响了这些路径我遇到过一次项目中同时存在set_clock_groups和set_false_path两者都试图排除同一组路径结果工具报了警告而且实际生效的是set_false_path导致时钟组约束被部分覆盖。后来把冗余的set_false_path删掉才恢复正常。提示set_clock_groups和set_false_path虽然都能排除路径检查但它们的语义不同。set_clock_groups是双向的排除两个时钟之间的所有路径set_false_path是单向的只排除指定方向的路径。优先使用set_clock_groups因为它更清晰、更易维护。4.5 第五步CTS阶段的注意事项时钟组约束不仅影响STA还影响CTS。在CTS阶段工具会根据时钟组约束来决定时钟树的综合策略。如果你用了physically_exclusiveCTS工具会认为两个时钟在物理上互斥可以分别优化。这通常能带来更好的时钟树质量因为工具不需要在两个时钟之间做折中。如果你用了logically_exclusiveCTS工具仍然会认为两个时钟可能同时到达需要在时钟树中做平衡。这可能导致时钟树插入更多的缓冲器面积和功耗都会增加。所以如果你的设计确实满足物理互斥的条件优先用physically_exclusive。但前提是你得确认物理互斥的条件真的成立否则可能导致时序问题被掩盖。5. 常见问题与排查技巧实录5.1 约束写了但没生效这是最常见的问题。可能的原因有时钟名字写错了。SDC里的时钟名字必须和create_clock或create_generated_clock定义的名字完全一致大小写敏感。时钟组约束被后面的约束覆盖了。SDC是按顺序执行的后面的约束可能覆盖前面的。工具版本不支持某些选项。不同工具对-physically_exclusive的支持程度不同有些老版本工具可能不支持。排查方法用report_clock_groups命令确认约束是否被工具识别。如果命令报错或者输出为空说明约束没生效。5.2 用了physically_exclusive但时序违例反而变多了这种情况通常是因为物理互斥的条件不成立。比如你有一个时钟MUX选择端是动态切换的但你用了physically_exclusive工具就认为两个时钟永远不会同时到达MUX后面的逻辑。但实际上在切换的瞬间两个时钟可能同时活跃导致时序问题被掩盖。排查方法检查时钟MUX的选择端控制逻辑。如果选择端是静态配置的比如来自寄存器且运行过程中不变那物理互斥成立。如果选择端是动态切换的那就不能用physically_exclusive。5.3 时钟组约束与false_path混用导致冲突前面提到过set_clock_groups和set_false_path可能冲突。具体表现是工具报出警告或者约束的实际效果与预期不符。排查方法用report_exceptions命令列出所有时序例外timing exception检查是否有重叠。如果有删掉冗余的约束只保留最清晰的那一个。5.4 常见问题速查表问题现象可能原因解决方法约束写了但STA报告仍有跨时钟路径时钟名字错误或约束被覆盖用report_clock_groups确认CTS后时钟树面积异常大用了logically_exclusive但实际可物理互斥改用physically_exclusive时序违例突然增多physically_exclusive条件不成立检查时钟MUX选择端逻辑工具报约束冲突警告set_clock_groups与set_false_path重叠删除冗余约束约束在综合阶段生效但PR阶段失效约束文件未正确传递给PR工具检查约束文件的加载顺序5.5 一个真实的踩坑案例去年做一个项目设计里有两个时钟CLK_MAIN和CLK_ALT通过一个MUX切换。MUX的选择端来自一个配置寄存器上电后由软件配置运行过程中不变。我一开始用了logically_exclusive结果CTS后时钟树面积比预期大了15%功耗也偏高。后来分析发现CTS工具认为两个时钟都可能到达MUX后面的逻辑所以在时钟树中做了平衡插入了额外的缓冲器。改成physically_exclusive后CTS工具分别针对两个时钟优化时钟树面积降下来了功耗也恢复正常。这个案例说明正确理解物理互斥和逻辑互斥的区别不仅能保证时序正确还能优化面积和功耗。6. 进阶话题时钟MUX约束与SDC API6.1 时钟MUX的约束策略时钟MUX是数字设计里最常见的结构之一。根据MUX选择端的控制方式约束策略也不同静态选择选择端由配置寄存器控制运行过程中不变。这种情况下两个输入时钟物理互斥用physically_exclusive。动态选择选择端由逻辑动态控制可能在运行过程中切换。这种情况下需要做时钟切换检查确保切换过程中不会产生毛刺或短脉冲。SDC里通常用set_clock_groups配合set_max_delay来处理。固定选择选择端直接接常量只有一个输入时钟能通过。这种情况下另一个时钟根本不会传播到MUX输出可以在综合阶段就优化掉。6.2 SDC API协议说明不同EDA工具对SDC命令的支持程度不同。以常见的工具为例set_clock_groups所有主流工具都支持但-physically_exclusive选项的支持情况不一。report_clock_groups部分工具支持用于报告当前生效的时钟组约束。set_clock_groups -name给时钟组命名方便后续引用。这个选项在大型设计中很有用因为时钟组可能很多命名后更容易管理。如果你用的是Holosens的SDC API建议查阅具体的API文档确认支持的选项和语法。不同版本的API可能有差异。6.3 大型设计中的时钟组管理在大型SoC设计中时钟可能有几十个甚至上百个。这时候时钟组约束的管理就很重要了。我的经验是给每个时钟组起一个有意义的名字比如grp_func_test、grp_rtc_func。把时钟组约束单独放在一个SDC文件里不要和其他约束混在一起。用脚本自动生成时钟组约束避免手动写错。定期用report_clock_groups检查约束的完整性。6.4 约束的版本管理SDC文件应该和RTL一起做版本管理。每次时钟结构有变化都要同步更新SDC。我见过太多项目RTL改了但SDC没改结果时序分析结果完全不可信。建议的做法是把SDC文件纳入Git管理每次修改都写清楚原因。在CI流程中加入SDC语法检查确保约束文件能正确加载。7. 一些实操心得关于logically_exclusive和physically_exclusive的选择我的经验是能用physically_exclusive就用physically_exclusive但前提是物理互斥的条件确实成立。物理互斥能给CTS工具更大的优化空间通常能带来更好的面积和功耗。但如果你不确定物理互斥是否成立那就用logically_exclusive。它更保守但更安全。宁可过度约束也不要漏掉该检查的路径。另外时钟组约束不是写完就完事了。每次时钟结构有变化都要重新审视这些约束。我习惯在项目的每个里程碑都跑一次report_clock_groups确认约束没有遗漏或错误。最后分享一个小技巧如果你不确定某个时钟对之间应该用哪种约束可以先不写约束跑一次STA看看工具报出多少跨时钟路径。如果路径数量很少而且你确认这些路径不需要检查那就加上约束。如果路径数量很多那可能说明你的时钟结构有问题需要先理清时钟关系再写约束。这个内容后续还可以这样扩展结合具体的EDA工具深入讲解set_clock_groups在不同工具中的实现差异以及如何用Tcl脚本自动化生成和管理时钟组约束。