此页面属于关于时序(timing)的一系列页面。上一页介绍了时序约束(timing constraints)背后的理论基础。下一步是看看这个理论是如何应用的。
概述
本页介绍了最重要的时序约束,它定义了时钟的频率。接下来是时序报告(timing report)对路径(path)分析的详细示例。
时序报告的分析细节似乎是一个高级话题,但事实并非如此: 时序约束的目的是控制工具对设计的时序分析,设置必须满足的准确要求。因此,为了了解时序约束,有必要研究时序分析。时序分析显示在时序报告中。
此外,仅编写时序约束是远远不够的。能够验证这些约束(constraints)在设计上是否正常工作非常重要。只有深入了解时序报告才能进行这样的验证。如果没有这样的理解,很容易误以为时序约束没有达到他们的目的,然后想知道为什么逻辑设计不能正常工作。
所有 FPGA 工具都会将时序报告生成为文本文件,这里显示的就是报告(reports)。这些工具还具有图形界面,用于查看完全相同的信息。这个图形界面有时很有用,有时又很令人困惑,因此使用文本报告是重要的第一步。
period 约束
最有用的时序约束是 period 约束: 它通知工具有关时钟信号的频率。
例如,假设逻辑设计仅由这个 Verilog 模块组成:
module top(
input clk,
input foo,
output reg bar_reg);
reg foo_reg;
reg bar;
always @(posedge clk)
begin
foo_reg <= foo;
bar <= !foo_reg;
bar_reg <= bar;
end
endmodule
从 Verilog 可以看出 @clk 是作为时钟使用的,而这个信号是外接的端口(即 FPGA上接了一个物理引脚)。
如果 @clk的频率是 250 MHz (4 ns),则需要如下所示的时序约束:
create_clock -period 4 -name clk [get_ports clk]
这个命令含义如下: “ I/O 端口处有一个时钟叫 @clk。这个时钟的 period 是 4 ns。如果有其他时序约束会引用这个时钟,他们会为此使用名称'clk'”。
笔记:
- “period”参数的值应该是时钟的时钟周期(clock period)。不要为“额外安全”(overconstraining)选择较小的值。永远不应该有这样做的理由。如果这样做有帮助,那么还有一个不同的问题需要解决。
- 如果使用异步复位(asynchronous reset), create_clock 可能无法保护触发器(flip-flop)免受违反复位信号(reset signal)上的时序要求的影响。这在不同的页面上有解释。
时序分析
现在,我们将查看 Vivado的时序分析,以了解路径的 setup 要求,该要求始于 @foo_reg ,止于 @bar。换句话说,这是 Verilog 表达式的结果路径:
bar <= !foo_reg;
这里展示的时序分析由三部分组成,在时序报告中出现的顺序是这样的:
- 一 header,里面包含了路径的时序分析的总结,以及一些额外的信息。
- 计算从时钟边沿(clock edge)到第二个触发器(本例中为@bar )的输入出现稳定的逻辑状态所花费的时间。
- 计算发现第二个触发器(flip-flop)的输入何时必须稳定才能满足时序要求。
这三个部分在下面分别显示和描述。请注意,在时序报告中,这些部分之间没有可见的分隔符。特别是,从时序报告上看不出第二部分在哪里结束,第三部分在哪里开始。这本报告的读者需要从其内容中识别出第三部分的开头。
尽管这里显示的是 Vivado的时序报告,但 Quartus 和其他几种 FPGA 工具也采用了相同的方法。其他工具的时序报告中写的信息通常略有不同。但是,这些报告背后的理论是相同的。因此,通过这个例子对其他 FPGA 工具也有帮助。
我们将跳过时序报告的第一部分,在讨论完前两部分后再回到这一部分。按此顺序解释报告比较容易。但首先,先说几句一般性的话。
时序分析的攻略
与上一页显示的简单静态时序分析(static timing analysis)不同,真正的时序分析需要考虑到时钟的缺陷。为此,时延(delay)计算从时钟的原点开始,例如时钟的物理输入引脚。这不同于简单的数据路径时延(data path delay)计算(如前一页所示),后者只考虑数据路径(data path)的时延。
所以现在理论实验如下: 在时钟的原点用时钟边沿启动秒表。让这个秒表继续,因为这个时钟边沿(clock edge)行进到第一个触发器并激活它。继续测量此触发器更新其输出(output)的时间,并跟随更新的信号到达目的地。当这个信号到达第二个触发器时停止秒表。
下一步是检查结果是否良好。对于 tsu 要求,这意味着信号相对于下一个时钟边沿来得足够快。
但这是第二个触发器上的时钟边沿。什么时候到?
为了查明这一点,秒表再次启动,同时启动时钟原点的下一个时钟边沿。当第二个时钟边沿到达第二个触发器时秒表停止。所以起点是一样的,只是时钟边沿晚了,时钟边沿的终点不一样了。
经过这个理论实验,我们知道时钟边沿何时到达第二个触发器。为了满足 tsu 的要求,这个触发器的输入相对于这个时钟边沿必须要足够早的稳定。
第一个理论实验的秒表显示数据(data)何时稳定在第二个触发器。第二个实验的秒表显示时钟边沿到达同一触发器的时间。剩下的就是比较这两个数字,并检查差异是否大于 tsu的要求。
使用此方法可以考虑与时钟相关的不确定性,因为它允许在两个理论实验中应用最坏情况。对于 setup time 计算,所有时延的上限用于秒表第一次实验的计算。结果,计算显示信号可以到达第二个触发器的输入的最晚可能时间。但是对于秒表的第二次实验,使用了所有时延的下限。结果是第二个时钟边沿到达第二个触发器的最早可能时间。
所以针对信号尽量晚到,时钟边沿尽量早到的场景进行计算。如果在这些条件下满足 setup time 要求,则毫无疑问始终满足此要求。
对于 hold time 计算,则相反: 第一个实验使用最小时延,第二个实验使用最大时延。
源路径(source path)计算
如上所述,时序报告的第一部分稍后展示。所以我们现在来看时序分析的第二部分: 源路径计算。它由两个段组成:
- 源时钟路径(Source Clock Path)开始于 FPGA的时钟输入引脚(clock input pin)的上升沿(rising edge),结束于这个上升沿(rising edge)到达 @foo_reg的时钟输入。
- 数据路径继续旅程,直到 @bar的数据输入(data input)处的信号更新为新值。这个段对应于上一页中显示的简单静态时序分析。
这两个段一起计算从上升沿在 FPGA的外部时钟引脚到数据到达第二个触发器的时间。
这是时序报告中的相关部分:
Location Delay type Incr(ns) Path(ns) Netlist Resource(s) ------------------------------------------------------------------- ------------------- (clock clk rise edge) 0.000 0.000 r AG12 0.000 0.000 r clk (IN) net (fo=0) 0.000 0.000 clk_IBUF_inst/I AG12 INBUF (Prop_INBUF_HRIO_PAD_O) 0.738 0.738 r clk_IBUF_inst/INBUF_INST/O net (fo=1, routed) 0.105 0.843 clk_IBUF_inst/OUT AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O) 0.049 0.892 r clk_IBUF_inst/IBUFCTRL_INST/O net (fo=1, routed) 0.839 1.731 clk_IBUF BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O) 0.101 1.832 r clk_IBUF_BUFG_inst/O X2Y0 (CLOCK_ROOT) net (fo=3, routed) 1.389 3.221 clk_IBUF_BUFG SLICE_X49Y58 FDRE r foo_reg_reg/C ------------------------------------------------------------------- ------------------- SLICE_X49Y58 FDRE (Prop_EFF2_SLICEL_C_Q) 0.138 3.359 f foo_reg_reg/Q net (fo=1, routed) 0.241 3.600 foo_reg SLICE_X49Y58 LUT1 (Prop_D5LUT_SLICEL_I0_O) 0.244 3.844 r bar__0_i_1/O net (fo=1, routed) 0.046 3.890 p_0_in SLICE_X49Y58 FDRE r bar_reg__0/D ------------------------------------------------------------------- -------------------
此部分中的每一行代表一个逻辑单元(logic element)或一根线(wire)。当“时延 type(Delay type)”为“网络(net)”时,该行对应于一根线。所有此类时延均为布线时延(routing delays),即信号从一个逻辑单元传播到另一个逻辑单元所需的时间。
名为“Incr”的列显示路径中的每个元素贡献了多少时延。 “路径”列显示了到那时为止的总时延。
中间的水平线标志着源时钟路径的结束和数据路径的开始。下面我们就来详细了解一下这两款路径中的时延。
前七个时延(delays)对应着输入引脚,也就是 AG12 (这个是这个引脚的物理位置),再根据这个报告(report),跟这个引脚对应的输入引脚以及逻辑共同贡献了 1.731 ns这个一共时延。
全局时钟缓冲器(global clock buffer)从其输入到输出贡献了另一 0.101 ns 。接下来是全局时钟的布线时延,数量比较多: 1.389 ns。这是时钟信号达到 @foo_reg的时钟输入所需的时间。之所以用这么大的时延,是因为用了一个全局时钟缓冲器(global clock buffer)和一个时钟树来配这个信号。这些布线资源(routing resources)旨在将时钟分配到 FPGA 的大部分,同时将相同的时延分配到所有目的地。因此有一个大的时延,即使时钟只到达几个目的地,就像在这个例子中(时钟的扇出(fan-out)只是 3)。
此时,时钟终于到达了包含触发器的 slice ,在本例中为 SLICE_X49Y58 。所以这是源时钟路径的结尾。报告中的水平线表示数据路径的开始。在上一页的示例中,这是简单的静态时序分析的开始。
在右侧的网表资源(Netlist Resources)列中,它在水平线上方的行中显示“foo_reg_reg/C”,并在该行之后显示“foo_reg_reg/Q”。所以横线后面的那一行肯定是 @foo_reg的触发器的时钟 to output delay (clock to output delay)(从 C 到 Q)。这个时延就是 0.138 ns。 “FDRE”表示触发器、数据、复位(Reset)、使能(Enable)。
接下来是布线时延到 LUT (0.241 ns), LUT (0.244 ns) 内的传播延迟(propagation delay)和布线时延到第二个触发器(0.046 ns)。布线时延非常小,因为所有东西都装在一 slice中。
总结这部分,时钟边沿从外部引脚到第一个触发器的时钟输入花费了 3.221 ns 。然后使用 0.669 ns ,直到更新的信号到达第二个触发器的输入(3.890 − 3.221 = 0.669 ns)。总的来说,从外部引脚上的时钟边沿到最终目的地稳定的信号(第二个触发器的数据输入)的时间是 3.890 ns (最多,这是最坏情况的计算)。
所以现在是时候问问这是否足够快了。是否满足 setup time 要求?
目的地时钟路径(Destination Clock Path)
第二次计算的目的是找出时钟边沿从外部引脚移动到第二个触发器的时钟输入的速度。
请注意,时钟路径(clock path)的目的地是第二个触发器。这不应与之前计算的时钟路径混淆,其中目的地是第一个触发器。
还有其他显着差异:
- 仅计算时钟路径。也就是说,与之前的计算相比,只考虑了段直到水平线。
- 理论上,秒表从 4 ns开始,而不是从零开始。这是因为此计算的目的是确定数据信号(data signal)是否足够早到达以满足 setup time 的要求。因此,计算从第二个时钟边沿开始,根据时序约束对应 clk (即上面显示的 create_clock 命令),它是 4 ns 。
- 这个段上的各个元件时延都比较小。这在这个具体的例子中很容易看出,因为两个触发器都在同一 slice上,所以时钟路径在两个计算中是完全一样的(通常不是这样)。更多关于下面的内容。
- 此计算中的最后三行(时钟 pessimism(clock pessimism)、时钟 uncertainty (clock uncertainty)和 Setup_DFF2_SLICEL_C_D)不是逻辑组件,而是时序参数(timing parameters)。
时序分析(目的地时钟路径)的第三部分如下:
(clock clk rise edge) 4.000 4.000 r AG12 0.000 4.000 r clk (IN) net (fo=0) 0.000 4.000 clk_IBUF_inst/I AG12 INBUF (Prop_INBUF_HRIO_PAD_O) 0.515 4.515 r clk_IBUF_inst/INBUF_INST/O net (fo=1, routed) 0.066 4.581 clk_IBUF_inst/OUT AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O) 0.034 4.615 r clk_IBUF_inst/IBUFCTRL_INST/O net (fo=1, routed) 0.722 5.337 clk_IBUF BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O) 0.091 5.428 r clk_IBUF_BUFG_inst/O X2Y0 (CLOCK_ROOT) net (fo=3, routed) 1.218 6.646 clk_IBUF_BUFG SLICE_X49Y58 FDRE r bar_reg__0/C clock pessimism 0.527 7.173 clock uncertainty -0.035 7.138 SLICE_X49Y58 FDRE (Setup_DFF2_SLICEL_C_D) 0.067 7.205 bar_reg__0 ------------------------------------------------------------------- required time 7.205 arrival time -3.890 ------------------------------------------------------------------- slack 3.315
工具选择将 @foo_reg 和 @bar 放在同一 slice上,所以在这个具体案例中,本次分析的时钟路径与第一个分析相同。据此不难看出,逻辑单元(logic elements)的顺序和前面分析的完全一样,一直到横线。在这个序列之后,有两个时序参数(timing parameters)对计算进行调整: 时钟 pessimism 和时钟 uncertainty。这些将在本页底部单独讨论。
在最后一次计算的前一行,我们有第二个时钟边沿可以到达的最早时间: 先时钟边沿后 7.138 ns 。 setup time 的要求是数据信号必须在这个时钟边沿之前稳定。 tsu 指定多少。所以为了得到数据必须稳定的最晚时间,时钟的到达时间减去 tsu 。
在上例中, tsu 为负,等于 −0.067 ns。因此,最终结果是 7.138 − (−0.067) = 7.205 ns。换句话说,数据必须稳定在第一个时钟边沿之后的第二个触发器,不迟于 7.205 ns 。
在之前的计算中,结果是数据稳定在这个时钟边沿之后的 3.890 ns ,最差。所以这已经足够好了,有余量: 要求和保证之间的区别是 7.205 − 3.890 = 3.315 ns。也就是说, slack 就是 3.315 ns。
时序分析总结
现在是时候回到路径的时序报告的第一部分了。这部分出现在上面显示的计算之前,它总结了主要结果。此外,本次 header 明确了此次计算中出现的几个数值。
所以请记住,这是路径的时序分析的开始方式:
Slack (MET) : 3.315ns (required time - arrival time) Source: foo_reg_reg/C (rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns}) Destination: bar_reg__0/D (rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns}) Path Group: clk Path Type: Setup (Max at Slow Process Corner) Requirement: 4.000ns (clk rise@4.000ns - clk rise@0.000ns) Data Path Delay: 0.669ns (logic 0.382ns (57.100%) route 0.287ns (42.900%)) Logic Levels: 1 (LUT1=1) Clock Path Skew: -0.048ns (DCD - SCD + CPR) Destination Clock Delay (DCD): 2.646ns = ( 6.646 - 4.000 ) Source Clock Delay (SCD): 3.221ns Clock Pessimism Removal (CPR): 0.527ns Clock Uncertainty: 0.035ns ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE Total System Jitter (TSJ): 0.071ns Total Input Jitter (TIJ): 0.000ns Discrete Jitter (DJ): 0.000ns Phase Error (PE): 0.000ns Clock Net Delay (Source): 1.389ns (routing 0.002ns, distribution 1.387ns) Clock Net Delay (Destination): 1.218ns (routing 0.002ns, distribution 1.216ns)
这部分由许多不同的信息组成,所以我将一一介绍。所以从第一行开始:
Slack (MET) : 3.315ns (required time - arrival time)
这表示已实现时序约束(met),还有剩余时间 (slack), 3.315 ns。
Source: foo_reg_reg/C (rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns}) Destination: bar_reg__0/D (rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns})
这些行说明检查了哪条数据路径(data path)。这是由该路径(源(Source)和目的地(Destination))的开始位置和结束位置定义的。数据路径起始于 foo_reg_reg/C,也就是 @foo_reg的时钟输入。这条路径(path)结束于 bar_reg__0/D的数据输入。
另一件事是提到了“clk”,并描述了它的波形。请注意,“clk”指的是时钟和 create_clock的名称。在此示例中,“clk”也是时钟信号的名称。但是,如果在时序约束的 "-name" 参数中使用了另一个名称,则该名称会出现在时序报告中,而不管信号的名称如何。对于此时序报告示例中所有提到“clk”的地方都是如此。
Path Group: clk
这里的路径 Group (Path Group)是“clk”,说明之所以考察这条路径是同名的时序约束。
Path Type: Setup (Max at Slow Process Corner)
路径 Type (Path Type)是 Setup。这意味着检查了 setup time 要求。 “Max at Slow Process Corner”表示最大时延用于数据路径的计算(第一次计算)。 Corner 在本文中的含义解释如下。
Requirement: 4.000ns (clk rise@4.000ns - clk rise@0.000ns)
回想一下,上面描述的两个理论实验中的每一个都启动了一个假想的秒表。 “Requirement”是秒表启动时的时差。在这种情况下,时序约束需要时钟周期,即 4 ns。
Data Path Delay: 0.669ns (logic 0.382ns (57.100%) route 0.287ns (42.900%))
数据路径时延是第一次计算横线后所有时延的总和(即数据路径的时延)。
在这一行中,时延也分别显示为逻辑和 route。这显示了在这两个逻辑单元之间,逻辑单元上花费了多少时间,线(wires)上花费了多少时间。常见的经验法则是,时延中的大约 60% 应该在逻辑上,其余的在布线(routing)上。因此,本例中的路径显示的是正常情况。
如果布线的时延所占比例明显更大,则可能表明存在问题,特别是如果路径未能达到时序约束。下一页在讨论 thold分析的部分对此有更多介绍。
Logic Levels: 1 (LUT1=1)
数据路径由单 LUT组成,因此逻辑级(logic levels)的数量为 1。
Clock Path Skew: -0.048ns (DCD - SCD + CPR) Destination Clock Delay (DCD): 2.646ns = ( 6.646 - 4.000 ) Source Clock Delay (SCD): 3.221ns Clock Pessimism Removal (CPR): 0.527ns
时钟路径偏移(Clock Path Skew)是同一个时钟边沿到达两个触发器的时间差。这是计算得出的最坏情况,其中包括在一条时钟路径(clock path)中使用最大的时延,在另一条时钟路径中使用最小的时延。请参阅下面名为“时钟 pessimism removal(Clock pessimism removal)”的部分,其中解释了这些行背后的算法。
Clock Uncertainty: 0.035ns ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE Total System Jitter (TSJ): 0.071ns Total Input Jitter (TIJ): 0.000ns Discrete Jitter (DJ): 0.000ns Phase Error (PE): 0.000ns
请参阅下面名为“时钟 uncertainty”的部分。这些行显示了时钟 uncertainty 的计算方式。这个计算的结果, 0.035 ns,是不切实际的乐观。发生这种情况是因为在时序约束中没有指定抖动(jitter),因此工具假定抖动为零。除此之外,直接使用外部时钟(即 FPGA内部没有锁相环(PLL)),所以几乎没有抖动的来源可以解释。
尽管在时序约束中不指定外部时钟的抖动是错误的,但通常都是这样做的。这很少是问题的根源,因为与时序计算中考虑的其他因素相比,抖动通常较小。
Clock Net Delay (Source): 1.389ns (routing 0.002ns, distribution 1.387ns) Clock Net Delay (Destination): 1.218ns (routing 0.002ns, distribution 1.216ns)
这些是时钟信号本身的时延,从时钟缓冲器(clock buffer)的输出到触发器的时钟输入。在这个例子中,没有太多信息可以从这些数字中获取。
Multi-corner 时序分析
所有逻辑单元的时延取决于一些未知参数,例如温度和 supply 电压。此外,术语“process”用于指代 FPGA生产过程中的错误。尽管每 FPGA 都经过测试以确保它符合数据手册(datasheet),但每个逻辑单元的行为仍然存在一些不确定性。
FPGA 工具在几个极端场景中为每条路径执行时序分析,称为“corners”。例如,一种情况可以是允许的最低温度,结合最快的 process (即当 FPGA 恰好是用低时延制造的)。第二种情况可能是最高温度与最快的 process相结合。第三和第四种情况使用最慢的 process重复此操作。
所以在这个例子中,时序分析是针对两个参数的极端条件进行的: 温度和 process。这称为 four-corner 时序分析。但这只是执行 multi-corner 时序分析的众多可能性之一。每 FPGA 工具都以不同的方式执行时序分析。
但无论工具选择检查哪 corners ,最坏的情况始终被认为是时序分析的结果。换句话说,这些工具会为每 corner计算 slack ,并且计算的是最低的 slack 。
这些工具经过编程,可以为每 FPGA执行足够的 multi-corner 时序分析,因此无需深入了解该主题。但是在读取时序报告时,重要的是要检查它是否与单 corner相关,或者它是否是所有 corners 的汇总(即最坏情况)。存在混淆的可能性,尤其是 Quartus 。
接下来讨论时钟 pessimism removal 和时钟 uncertainty 。这些都是比较高级的话题。如果您对时序计算的更详细信息不感兴趣,可以跳到本系列的下一页。
时钟 pessimism removal
由于两个触发器在同一 slice上的巧合,因此可以比较时钟路径时延(clock path delays)的计算(即时钟边沿到达 slice的时间)。第二次计算,这次是 2.646 ns,因为计算从 4 ns 开始,到 6.646 ns结束,所以 6.646 − 4 = 2.646 ns。在前面的计算中,结果是 3.221 ns。 0.575 ns的这个区别。
造成这种差异的原因是第一次计算使用了最大的时延,第二次计算使用了最小的时延。最小的时延和最大的时延之间的差异代表了一个事实,即由于制造过程中的自然误差,时延并不准确。因此,如果时钟路径到第一个触发器与时钟路径到第二个触发器完全不同,则必须考虑最坏的情况。这种最坏的情况是第一条路径的所有时延都是允许的最大值,而第二条路径的所有时延都是允许的最小值。这就是所谓的 clock pessimism。
请注意,这与温度或一个物理 FPGA 与另一个物理 FPGA 之间的差异无关: 两种计算都是针对相同的温度和制造过程进行的。这种差异是因为段中的每个时延都有一个符合 FPGA规格的 tolerance 。
但是,当两条路径中的时钟路径相同时,为什么时钟 pessimism 是计算的一部分?答案是这样做是错误的。这就是为什么在目的地时钟路径中有一行标题为“时钟 pessimism”的原因。此行将 0.527 ns 添加到时延以补偿此错误。标题实际上应该是“时钟 pessimism removal”(CPR)。
因此,时钟 pessimism removal 背后的想法是消除时钟路径的最小时延和最大时延之间不必要的差异,这些差异在两种计算中都是相同的。该工具比较了两个计算的时钟路径,并找到了两条路径共有的段。时延(在共享的段中)中所有差异的总和是应该删除的时钟 pessimism 。
如上所述,时钟路径的区别在于 0.575 ns。但是应用的时钟 pessimism 只是 0.527 ns。因此 0.048 ns的减少幅度较小。原因是在 slice 内部有一条时钟路径的小段,这对两种计算都不常见: slice 里面的一根线接第一个触发器,第二根线接第二个触发器,这两根线里面的时延可以不一样。
时钟 uncertainty
在时序计算中, 0.035 ns 从时钟路径的计算中减去。这使得时序计算更加严格。
时钟 uncertainty 解释了每两个时钟边沿之间的随机时间。这种随机性称为时钟抖动(clock jitter),是各种噪声源和电子设备随机行为的结果。
从计算中减少 0.035 ns 表示即使时钟周期在时序约束(create_clock) 中定义为 4 ns ,但实际上这个时钟周期(clock period)是随机的。因此,两个时钟边沿之间的时间可以更短。短了多少?在此计算中,假设两个时钟边沿之间的时间永远不会小于 3.965 ns (4−0.035 = 3.965 ns)。
这个假设是否成立?这是一个很难回答的问题,因为时钟抖动的估计是一个复杂的主题,远远超出了关于时序约束的讨论范围。尽管如此,还是建议进一步研究这个主题,因为时钟抖动可能是逻辑设计中各种问题的根源,而与时序约束无关。
关于时钟周期约束的两页中的第一页到此结束。下一页还有更多内容需要学习...