关于这个电路图时序约束的理解:
# ========== 主时钟 ==========
create_clock -name CLK -period 10 [get_ports CLK]
# ========== 分频器生成时钟 ==========
create_generated_clock -name FFdiv2_clk -source [get_ports CLK] \
-divide_by 2 [get_pins FFdiv2/Q]
create_generated_clock -name FFdiv4_clk -source [get_ports CLK] \
-divide_by 4 [get_pins FFdiv4/Q]
# ========== UMUX多源生成时钟 ==========
# 覆盖所有可能的输入源(CLK、FFdiv2/Q、FFdiv4/Q)
create_generated_clock -name UMUX_clk -source [get_ports CLK] \
-combinational [get_pins UMUX/out] -add
create_generated_clock -name UMUX_clk -source [get_pins FFdiv2/Q] \
-combinational [get_pins UMUX/out] -add
create_generated_clock -name UMUX_clk -source [get_pins FFdiv4/Q] \
-combinational [get_pins UMUX/out] -add
# ========== FFdiv3生成时钟 ==========
create_generated_clock -name FFdiv3_clk -source [get_pins UMUX/out] \
-divide_by 3 [get_pins FFdiv3/Q]
# ========== FF1和FF2生成时钟 ==========
create_generated_clock -name FF1_clk -source [get_pins FFdiv3/Q] \
-divide_by 1 [get_pins FF1/Q]
create_generated_clock -name FF2_clk -source [get_pins FFdiv3/Q] \
-divide_by 1 [get_pins FF2/Q]
# n2节点可能的分频/门控时钟(假设二分频)
create_generated_clock -name n2_clk -source [get_ports CLK] \
-divide_by 2 [get_pins n2]
源时钟的选择取决于物理连接关系而非逻辑功能。若FF1/FF2的时钟端由UMUX驱动,则必须将-source
指向UMUX的输出,否则时序分析会错误计算时钟延迟和偏移。UMUX的约束需覆盖所有可能的输入源以确保完整性。
源节点必须在设计网表中存在,并且不能是之前定义的时钟名称,而必须是实际的物理节点。例如,“source of the generated clock must be a node in your design netlist, and not the name of a clock you previously define” ()。这表明用户不能直接使用时钟名称,而必须选择网表中的节点。
关键说明:
-
主时钟:假设
CLK
为原始时钟源,周期设为10ns(需根据实际调整)。 -
FFdiv系列:命名暗示分频逻辑,约束到触发器输出端(Q引脚)。
-
UMUX:作为多路时钟选择器,需为每个可能的输入时钟源添加独立约束,并用
-add
合并。 -
n2节点:假设为二分频逻辑,若实际为门控时钟需改用
-gate
选项。 -
FF1/FF2:若其输出驱动其他时钟引脚,需约束为生成时钟(假设源为上游分频时钟)。
-
所有驱动其他模块时钟输入的节点均需约束为生成时钟。
注:实际分频系数、引脚层级路径和选择逻辑需根据设计具体调整。若存在反馈路径或复杂时钟结构,需补充set_clock_groups
隔离异步时钟域。
-master_clock的使用
- 功能需求:通过控制信号
sel
,动态选择MUX_OUT
输出的时钟源为clkA
或clkB
; - 设计目标:为
MUX_OUT
节点定义两个生成时钟,分别关联到clkA
和clkB
。
错误约束示例(未使用-master_clock
)
create_generated_clock -name clk_mux -source [get_pins MUX/OUT] [get_pins MUX/OUT]
问题:工具无法区分MUX_OUT
的时钟源是clkA
还是clkB
,导致:
- 时序路径误判:工具可能默认关联到任意一个主时钟,忽略另一个时钟的路径;
- 跨时钟域错误:若
clkA
和clkB
频率差异大,时序分析可能错误计算建立/保持时间; - 时钟传播失效:生成时钟无法正确继承宿主时钟属性(如抖动、延迟)
正确约束示例(使用-master_clock
)
# 定义主时钟
create_clock -name clkA -period 10 [get_ports clkA] # 100MHz
create_clock -name clkB -period 20 [get_ports clkB] # 50MHz
# 为MUX_OUT定义两个生成时钟(关联不同宿主时钟)
create_generated_clock -name clk_muxA \
-source [get_pins MUX/clkA] \ # 物理源节点为MUX的clkA输入引脚
-master_clock clkA \ # 关联宿主时钟clkA
-add \ # 允许共存
[get_pins MUX/OUT] # 目标节点为MUX输出
create_generated_clock -name clk_muxB \
-source [get_pins MUX/clkB] \
-master_clock clkB \
-add \
[get_pins MUX/OUT]
-source
参数:分别指向MUX的输入引脚MUX/clkA
和MUX/clkB
,明确物理路径起点;-master_clock
参数:声明生成时钟与宿主时钟的关联关系,避免工具混淆时钟源。
-edges:
create_clock -period 10 [get_ports CLK]
create_generated_clock -name gen_clk \
-source [get_pins clk_IBUF_BUFG_inst/O] \
-edges {1 3 5} \
-edge_shift {2.0 0.0 1.0} \
[get_pins div/Q]
使用-edges {1 3 5},那么生成时钟的第一个上升沿在边沿1(0ns),下降沿在边沿3(10ns),第二个上升沿在边沿5(20ns),这样周期是20ns,占空比为(10ns高电平,10ns低电平),即50%占空比。不过,这可能和宿主时钟的占空比无关,因为只是用边沿来定义生成时钟的波形。
但用户可能需要不同的占空比,比如,如果使用-edges {1 2 5},那么上升沿在0ns,下降沿在5ns(宿主下降沿),然后再上升沿在20ns,这样周期是20ns,占空比为(5ns高,15ns低),即25%占空比。
然后,结合-edge_shift参数,可以进一步调整每个边沿的位置。-edge_shift {2.0 0.0 1.0},意味着每个对应边沿的时间偏移。比如,第一个边沿(宿主边沿1)偏移+2ns,所以生成时钟的上升沿在0+2=2ns;第二个边沿(宿主边沿3)偏移0,所以下降沿在10ns;第三个边沿(宿主边沿4)偏移+1ns,所以下一个上升沿在20+1=21ns。时钟周期是21 - 2 = 19ns,工具会自动扩展为完整周期 20ns。扩展为20ns的原因如下:
-
生成时钟的边沿必须与宿主时钟边沿索引严格对齐。若用户通过
-edges
或-edge_shift
偏移导致周期非整数倍,工具会强制修正为宿主周期的整数倍。 -
宿主时钟周期(10ns)是生成时钟周期推导的 绝对基准。工具始终以宿主时钟的边沿间隔为周期推导的起点