这一篇在干嘛?

总览三连的第 2 篇,覆盖原书第 4~5 章及第 9 章的约束与策略部分:约束是”你告诉工具的要求”,编译流程是”工具兑现要求的过程”,时序报告是”工具交回来的成绩单”。上一篇工程管理与 IP 生成器在这里,下一篇仿真下载、调试工具与报错排查在这里。

两类约束:物理约束与时序约束

HDL2Bit 编译流程:从综合到位流

时序报告:用 Timing Report 判定收敛

两类约束:物理约束与时序约束

TD 里约束分两个文件体系,别混:ADC(Anlogic Design Constraint,物理约束)管”信号落在芯片哪里”,SDC(Synopsys Design Constraint,时序约束)管”信号跑多快”。两者都挂在工程 Constrains 分组下,综合前就要添加好。

ADC:引脚与物理约束

ADC 文件最常用的命令是引脚分配和实例位置约束:

# .adc 文件示例:引脚分配
set_pin_assignment	{ sys_clk }	{ location = PIN_43;	iostandard = LVCMOS33; }
set_pin_assignment	{ key[0] }	{ location = PIN_66;	iostandard = LVCMOS33; }
set_pin_assignment	{ led[7:0] }	{ location = { PIN_10 PIN_11 PIN_12 PIN_13 PIN_14 PIN_15 PIN_16 PIN_17 }; }

不想手写也可以走图形界面:打开 IO Constraint(Tools → IO Constraint),界面中间是端口表格,直接在下拉框里选引脚号和电平标准,保存后自动写回 ADC 文件。界面和文本两种方式等价,改哪个都会同步。

IO Constraint 图形界面分配引脚

ADC 文件要先挂进工程才生效:在 FPGA Flow 窗口或工程管理里把 .adc 添加到 Constrains 分组,编译时综合器会读取它。

在 FPGA Flow 中添加 ADC 约束文件

set_inst_assignment 是进阶玩法

除了引脚,ADC 还能把指定实例约束到芯片的某个物理区域(区域约束的文本形式),做模块级布局规划时用。初学阶段先掌握 set_pin_assignment 即可。

SDC:时序约束

SDC 回答的问题是”工具该按什么标准去满足时序”。你不写 create_clock,工具就不知道哪个是时钟、周期多少,布局布线只能瞎跑——跑完报告里也全是” unconstrained “路径,等于没有质检标准。TD 提供 Timing Wizard(Tools → Timing Wizard)图形化生成 SDC:选时钟端口、填周期、标例外路径,向导自动拼出命令。

Timing Wizard 图形化生成时序约束

等价的手写 SDC 长这样:

# .sdc 文件示例
create_clock -name sys_clk -period 20.000 [get_ports {sys_clk}]
create_clock -name clk_pix -period 40.000 [get_ports {clk_pix}]

# 异步时钟域之间不做时序分析(前提:跨域已用同步器/异步FIFO处理)
set_clock_groups -asynchronous -group {sys_clk} -group {clk_pix}

# 静态配置信号、复位等不有时序要求
set_false_path -from [get_ports {rst_n}]

常用命令速查:

命令作用什么时候用
create_clock声明时钟与周期每个输入时钟必写
create_generated_clock声明 PLL/分频派生时钟用了 PLL IP 时
set_false_path声明不需要分析的路径真异步路径、静态信号
set_multicycle_path放宽到多个周期多周期握手逻辑
set_clock_groups -asynchronous整组时钟互不分析已妥善跨域的时钟组
set_input_delay / set_output_delay描述片外时序对外部芯片有接口时序要求时

常见坑:

① 忘写 create_clock → 报告”没有违例”是假象,工具根本没检查; ② 把真正的跨域路径全用 set_false_path 掩盖 → 时序”干净”了但板上必炸,假路径只能用于确实不需要同步的信号; ③ 引脚号抄开发板原理图抄错列 → 板上现象诡异(键反、灯乱闪),先查 ADC; ④ iostandard 漏写或与 BANK 供电不符 → 引脚分配报错或电气损坏风险。

HDL2Bit 编译流程:从综合到位流

Design Flow 里从综合到出位流的整条流水线,官方叫 HDL2Bit 流程,分解开是:

Synthesize(综合 Read Design → Optimize Gate)
→ Syn Opt(逻辑优化)
→ Phy Opt(物理优化 Optimize Routing)
→ Place & Route(布局布线)
→ Bitstream Generation(位流生成)

综合阶段把 RTL 变成门级网表,关心资源与逻辑深度;布局布线把网表塞进 EG4S20 的真实 LUT/ERAM/PLL 位置并连线,关心时序与拥塞。两个阶段各自有大量选项(优化力度、BRAM 推断方式、寄存器复制等),Options 对话框里逐项可调。

Multi-Run 与策略包

逐项调选项太琐碎,TD 提供两个提效武器:

  1. 策略包(Strategy):预设的选项组合。在 Design Flow 相应步骤的右键菜单或 Options 对话框里直接选内置策略包,比如偏时序、偏面积、偏功耗的套餐,一次切换一组参数。 编译选项中选择内置策略包
  2. Multi-Run:在流程节点上右键选择 Multi-Run(或 Setup Multi-Seed),让综合/布局布线按多组配置或多个随机种子各跑一遍,最后挑结果最好的一次。布局布线本质是带随机性的搜索,换个 seed 时序结果可能差很多——“跑一遍不过就再跑一遍换个 seed”是合法且常规的收敛手段。 Multi-Run 右键启动多配置运行 Setup Multi-Seed 配置多种子并行尝试

综合阶段还有两个高频选项值得认识:Keep(防止综合器把调试要看的信号优化掉,配合 ChipProbe 在线抓信号用)与 Directive(优化方向指示,如偏向时序还是面积)。这些在更细的选项文档里有完整表格,总览阶段记住”它们存在、在 Options 里能找到”即可。

编译顺序可以只跑一段

改了 RTL → 从 Synthesize 重跑;只改了 ADC/SDC → 可以只重跑 Place & Route 之后的环节;什么都不改只想出位流 → 直接跑 Bitstream Generation。善用增量能省大量等待时间。

时序报告:用 Timing Report 判定收敛

布局布线跑完,双击流程里的 Timing Report(或查看 log)得到成绩单。主界面按摘要分层:RTL Summary(综合前估算)、Gate Summary(综合后)、Physical Summary(布局布线后,这才是真相)以及 Timing Summary。看时序只需要盯两个指标:

  • WNS(Worst Negative Slack):最差路径的余量,正数 = 全部达标,负数 = 有违例;
  • TNS(Total Negative Slack):所有违例路径的负余量总和,衡量违例规模。

Timing Report 报告主界面

多时钟工程必看 Clock Intersection 方格图:行和列都是时钟,格子标出两个时钟之间是否存在需要检查的路径。用它可以一眼发现”工具在分析一对根本不该同步的时钟”(该 set_clock_groups 却没写),或者反过来漏掉了该查的跨域。

Clock Intersection 时钟交叉路径方格图

时序违例的标准处理顺序:

1. 查 SDC 是否写全(漏 create_clock / 误设 false_path)——先排除约束问题
2. 看 WNS 最差路径报告 → 违例在综合后就有还是布线后才出现
3. 综合后就有 → 加大综合优化力度/换偏时序策略包,或改 RTL 打断长组合链
4. 布线后才出现 → Multi-Seed 换种子重跑、加流水寄存器、必要时区域约束

通关标准:

① 能给 EG4S20 工程写全 ADC(所有输入输出引脚 + 电平标准)和 SDC(create_clock + 必要的例外路径),编译零约束告警; ② 能说出 WNS/TNS 的含义,并指出自己工程布局布线后的 WNS 数值; ③ 遇到时序违例时,会按”查约束 → 查路径 → 换策略包/seed → 改 RTL”的顺序收敛。