Yosys 时钟约束缺失速查:No constraints 与未声明时钟的排查主线
更新时间:2026-10-23。FAQ 速查页,属于 FPGA 工具报错排错系列。开源链路(yosys 综合 + nextpnr 布局布线)里「时钟约束缺失」的坑与商业工具长得很不一样:yosys 综合阶段根本不消费 SDC,约束文件是 nextpnr 在读——于是出现了「SDC 明明写了、yosys 一路绿灯、nextpnr 却报没有约束」或「约束被读了但按默认频率分析」这类迷惑现象。本篇给出真实风格报错、病因速查表与逐条补齐动作;同样开源链路上「综合结果偶发不一致」的问题见 Yosys 偶发不确定速查,与本篇互补。
本文要回答的问题
- nextpnr 报
Warning: No constraints时第一眼看哪里? - SDC 文件明明写了,为什么像没被读到一样?
- yosys 阶段有哪些地方(clk2fflogic、formal)需要正确的时钟声明?
- SDC 里的端口名为什么和综合后的 netlist 对不上?
- 多时钟域的假违例在 nextpnr 里怎么豁免?
一、报错原文与现象
nextpnr 日志里的典型原文(对象为示意):
Warning: No constraints found, defaulting to 12 MHz target frequency.
Info: [ 12.0, 24.0) MHz: frequency achieved
Warning: Max frequency for clock 'clk': 34.2 MHz (FAIL at 50.0 MHz)
ERROR: failed to find port 'sys_clk' in design (from SDC constraint)
Warning: constraint on 'top.pll_inst.clkout' did not match any objectyosys 侧相关的提示(跑 clk2fflogic 或 formal 流程时):
Warning: replacing memory... (clk2fflogic: no clock domain info)
ERROR: smtbmc: multiple clocks detected but no clock hierarchy given肉眼可见的四种表征:一是 nextpnr 日志开头就一行 No constraints,之后整个时序分析按默认目标频率(依器件不同常见 12/24/25 MHz 量级)跑——你的 100 MHz 设计「通过」了,上板根本不工作;二是时序报告里的频率要求莫名其妙地松,slack 大得离谱;三是 SDC 里某条 create_clock 因对象名失配被静默跳过,只有一行 Warning 就继续,布线图照常生成,留下一个半约束设计;四是 yosys 跑 formal(sby)时因时钟没声明清楚,多时钟设计直接 ERROR 退出。
二、排查决策流程图
先确认 SDC 是否真被 nextpnr 读进来,再按「对象名对拍 → 时钟源头 → 跨域豁免」的顺序补,这是唯一不绕路的顺序。
读这张图抓住主线:红色是入口现象,蓝色是两条「约束到底读没读、读到哪个对象」的诊断动作,橙色是按层的修复动作,绿色是复查通过的判决点,紫色是防复发沉淀。核心纪律只有一条——每改一处都重跑 nextpnr 看频率目标行与 Warning 清单,不要凭「脚本里写了」收尾。
三、病因速查表
| 现象 / 报错锚点 | 根因 | 一判据 | 处置方向 |
|---|---|---|---|
| Warning: No constraints found | SDC 没传给 nextpnr | 命令行里没有 --sdc 参数 | Makefile / 脚本补 --sdc timing.sdc |
| SDC 传了仍按默认频率跑 | 文件路径错或读取失败被降级 | 日志无 read_sdc 痕迹 | 用绝对路径试跑,看是否报文件不存在 |
| failed to find port 类 ERROR | SDC 写的名字在 netlist 里不存在 | 报错行直接点出对象名 | 按综合后层次名改写约束 |
| did not match any object Warning | 层次分隔符或位宽后缀失配 | 约束行被静默跳过 | 用 json netlist 搜真实名字 |
| 主时钟在但 PLL 输出没约束 | 派生时钟未声明 | 时序报告只有输入时钟域 | 补派生时钟约束或改用 PLL 输出名 |
| 多时钟域之间满屏违例 | 异步域未豁免 | 违例路径跨两个时钟域 | 按工具支持的路径豁免语法切掉 |
| formal / sby 报多时钟 ERROR | 时钟与域归属没声明 | ERROR 信息点名 clock | 在 formal 脚本显式给出时钟描述 |
| clk2fflogic 后仿真行为怪 | 时钟使能转换前时钟域不明 | 转换后新增逻辑无约束覆盖 | 转换前先读平设计并声明时钟 |
四、逐条排查
SDC 根本没传给 nextpnr。 开源链路第一大坑:约束文件躺在工程目录里,但构建脚本调用 nextpnr 时没带 --sdc timing.sdc(依目标架构参数名略有差异,ice40/ecp5/xilinx 系各看 nextpnr 帮助),nextpnr 完全不读它,日志里的 No constraints found 就是铁证,随后整条时序分析按默认目标频率走。修法:在 Makefile 或构建脚本里显式补上约束参数,并重跑布局布线——只改约束不重跑,结果不会变。
对象名与综合后 netlist 对不上。 这是与 Quartus 侧 Quartus 时钟约束缺失速查 同构但更容易踩的坑:yosys 综合会打平层次、重命名信号,RTL 里的 clk 综合后可能还在,但子模块里的 pll_inst/clkout 在 netlist 里已经变成层次化扁平名(如 pll_inst.clkout)或被优化合并。SDC 写的是综合前名字,约束行就被静默跳过(did not match any object)。判据:把 yosys 输出的 json netlist 拿来 yosys -p "read_json top.json; select -list" 或 grep 搜真实名字,逐字符比对大小写、层次分隔符、总线位宽后缀。稳妥做法是在 yosys 脚本里对要约束的时钟信号加 keep 属性(( * keep * )),保证综合后名字稳定。
派生时钟没声明。 主时钟约束上了,但 PLL 输出时钟没有对应声明,nextpnr 只按输入时钟域分析,PLL 后面的逻辑实际处于半约束状态。开源链路没有商业工具那种一行自动派生全部 PLL 时钟的便利命令,通常要对 PLL 输出显式补约束,名字以综合后 netlist 里的真实对象为准;部分架构的 nextpnr 变体支持频率参数直接指定,按其帮助文档写法来。
多时钟域假违例。 时钟都齐了之后最常见的「红」是 CDC 路径:异步时钟域之间的路径被按同步关系分析,slack 必然离谱。商业工具用时钟分组整组切断,开源链路各 nextpnr 架构对豁免语法支持不一——有的吃 SDC 风格的 false path,有的要在命令行或工程配置里指定。原则是:先把已知的异步域路径按工具支持的方式显式豁免,剩下的负 slack 才是真时序问题。
formal 与 clk2fflogic 的时钟声明。 跑 yosys formal(sby/smtbmc)时,多时钟设计必须在脚本里显式描述时钟与域归属,否则 smtbmc 直接 ERROR 退出;clk2fflogic 把带时钟使能的触发器展开成数据通路逻辑后,原本「一个时钟 + 使能」的结构变成纯组合反馈,如果转换前没把时钟域理清楚,转换后的设计在仿真和形式验证里都会出现难以理解的行为。顺序是:先在 yosys 里完成时钟相关的读平与声明,再做这类结构性转换。
约束文件「在工程里登记」但没真正被读。 类 GUI 前端(如某些封装脚本或 IDE)里 SDC 显示在文件列表中,实际调用 nextpnr 的命令行并没有带上它——与「没传参」同病,但更具迷惑性。判据永远是看真实执行的命令行(开 verbose 或 dry-run),而不是看文件列表。
五、防复发
- SDC 与 RTL 同等地位进版本管理;构建脚本里约束参数与 RTL 文件列表放在相邻行,改一个必看另一个。
- CI 里把 nextpnr 日志 grep
No constraints与did not match做成失败项——这两类出现即判构建不通过,不许带约束病出比特流。 - 每次出比特流前固定核对时序报告里的目标频率与设计规格一致,把报告归档;频率行是约束是否生效的一眼判据。
- 要约束的时钟与关键接口信号在 RTL 里加 keep 属性,防止 yosys 综合改名或优化掉导致约束失配。
- 换器件或改顶层端口名时全局搜一遍 SDC 引用,端口改名是约束失效的高发触发点。
- 约束补齐后结果仍忽好忽坏的情形,先按 Yosys 偶发不确定速查 排除综合随机性,再谈时序本身。
这一篇在知识体系里的位置
本篇是 FPGA 工具排错速查簇中「时序约束层」的开源链路分流页:与商业工具侧的 Quartus 时钟约束缺失速查 同构但坑位不同(yosys 不吃 SDC、nextpnr 默认频率降级、netlist 改名);约束补齐后结果仍不稳定时走 Yosys 偶发不确定速查 的随机性主线;yosys 前端解析类报错见 Yosys 语法解析失败速查。四篇合看可覆盖开源链路「约束缺失」与「综合噪声」这两类最易混淆的时序异常。
一句话总结
Yosys 时钟约束缺失的核心认知是分工:yosys 综合不消费 SDC,约束全由 nextpnr 读取——报 No constraints 先查命令行有没有把 SDC 传进去;传了却像没读,就用 json netlist 对拍综合后的层次化对象名并给时钟信号加 keep 属性;PLL 派生时钟显式补约束,多时钟域假违例按工具支持的语法豁免;formal 与 clk2fflogic 流程在转换前声明时钟;最后以时序报告目标频率与设计一致、Warning 清零为签收线,把 No constraints 的 grep 检查固化进 CI。