01signal.com

关于 clock period constraint的更多信息

此页面属于关于 timing的一系列页面。在简要介绍了 timing constraints 背后的理论和关于 clock period constraint的第一页之后,是时候看看这个 constraint的几个现实场景了。

下一步: 使用 PLL

上一页所示的示例中,外部 clock pin 直接连接到 logic。在大多数现实生活中的 designs中,某种 PLL 用于创建 logic使用的 clock 。这样做最明显的原因是 logic 需要与外部 clock不同的频率。但是使用 PLL 也可以帮助清除外部 clock 的缺陷,尤其是 jitter。

PLL 可以用 Verilog 代码添加到 design ,代码如下:

module top(
    input clk,
    input foo,
    output reg bar_reg
);
    reg foo_reg;
    reg bar;
    wire pll_clk;

   clk_wiz_0 pll_i
   (.clk_in1(clk),
    .clk_out1(pll_clk));

always @(posedge pll_clk)
  begin
    foo_reg <= foo;
    bar <= !foo_reg;
    bar_reg <= bar;
  end
endmodule

这和前面的例子一样,但是这次 flip-flops的 clock 是 @pll_clk 而不是 @clk。 PLL 由 Vivado的 Clocking Wizard IP生成,在 Verilog 代码中用作 module ,名称为 clk_wiz_0。

对于此示例, Clocking Wizard 已配置为接受 250 MHz reference clock,并在 output port (即 @clk_out1)上创建 125 MHz clock 。为了使示例保持简单, clk_wiz_0 没有 reset input 或 "locked" output。在大多数现实生活中的 designs 中,建议启用这些 ports 并使用它们。

clk_wiz_0 的另一件事是它启用了 phase alignment 选项,因此它将 @pll_clk的 clock edges 与 @clk的 clock edges 对齐。当 design 具有与外部 clock同步的 I/O ports 时,此选项很有用: 由于启用了 phase alignment,外部 clock 和内部 clock 之间的 timing 关系变得可预测。这对于必须满足与外部 clock相关的 timing 要求的 I/O ports 非常有用。

准确的说 Xilinx的术语, Xilinx的 FPGAs 有两种 PLLs: 一种称为 PLL ,第二种称为 MMCM。就此示例而言,差异无关紧要。 clk_wiz_0 是 MMCM,但为了清楚起见,我将使用术语 PLL来指代它。

再次值得一提的是,这里所说的 PLL ,适用于市面上所有的 FPGAs 。此示例使用 Vivado显示,但可以为所有 FPGAs生成与 clk_wiz_0 完全相同的 PLL 。

timing constraint 与 PLL

关于带有 PLL 的 timing constraints ,最重要的是要了解它没有什么特别之处。 timing constraint 是相对于外部 pin (本例中为@clk )编写的,如果 PLL 生成具有其他频率的 clock ,则工具的工作就是将其考虑在内。

值得再说一遍: 永远不需要编写额外的 timing constraint ,因为使用了 PLL 。如果您觉得有必要这样做,那么您的 design很有可能出现了问题,而使用额外的 timing constraint 来“修复”问题并不能解决真正的问题。

所以和以前一样, timing constraint 就是这样:

create_clock -period 4.000 -name clk [get_ports clk]

使用 Quartus 的人应该知道此页面上描述的陷阱。

timing report 与 PLL

我们现在将查看与上一页示例中相同的 path 的 timing report 。唯一不同的是增加了 PLL ,如上图。此处对相关 path 的分析显示顺序与 timing report中出现的顺序相同。首先,这是分析总结:

Slack (MET) :             7.288ns  (required time - arrival time)
  Source:                 foo_reg_reg/C
                            (rising edge-triggered cell FDRE clocked by clk_out1_clk_wiz_0  {rise@0.000ns fall@4.000ns period=8.000ns})
  Destination:            bar_reg__0/D
                            (rising edge-triggered cell FDRE clocked by clk_out1_clk_wiz_0  {rise@0.000ns fall@4.000ns period=8.000ns})
  Path Group:             clk_out1_clk_wiz_0
  Path Type:              Setup (Max at Slow Process Corner)
  Requirement:            8.000ns  (clk_out1_clk_wiz_0 rise@8.000ns - clk_out1_clk_wiz_0 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):    -0.715ns = ( 7.285 - 8.000 )
    Source Clock Delay      (SCD):    -0.616ns
    Clock Pessimism Removal (CPR):    0.051ns
  Clock Uncertainty:      0.062ns  ((TSJ^2 + DJ^2)^1/2) / 2 + PE
    Total System Jitter     (TSJ):    0.071ns
    Discrete Jitter          (DJ):    0.103ns
    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)

有几个显着差异。首先, Requirement 是 8 ns,而不是之前的 4 ns 。这是意料之中的,因为 PLL的 output 是 125 MHz。这些工具自动为此 output创建了一个额外的 timing constraint , clock period 等于 8 ns。由于 clock period 变长了 4 ns 而 data path 保持不变,因此 slack 增加了大约 4 ns。

自动 timing constraint 的另一个迹象是 Path Group 在这份报告中说“clk_out1_clk_wiz_0”。之前是“clk”。事实上,在这份报告中,之前是“clk”的所有地方都写着“clk_out1_clk_wiz_0”。下面在多个 clocks的上下文中讨论 timing report 中自动 timing constraints 的表示。

PLL 的一个较小后果是 Clock Uncertainty 已经上升到 0.062 ns: 在前面的例子中是 0.035 ns 。这是因为 Discrete Jitter 现在是 0.103 ns,而不是零。

现在让我们继续讨论 timing analysis 本身。这一次, Source Clock Path、 Data Path 和 Destination Clock Path 一起展示,与它们在真实报告中出现的一模一样:

Location             Delay type                Incr(ns)  Path(ns)    Netlist Resource(s)
  -------------------------------------------------------------------    -------------------
                         (clock clk_out1_clk_wiz_0 rise edge)
                                                      0.000     0.000 r
    AG12                                              0.000     0.000 r  clk (IN)
                         net (fo=0)                   0.000     0.000    pll_i/inst/clkin1_ibuf/I
    AG12                 INBUF (Prop_INBUF_HRIO_PAD_O)
                                                      0.738     0.738 r  pll_i/inst/clkin1_ibuf/INBUF_INST/O
                         net (fo=1, routed)           0.105     0.843    pll_i/inst/clkin1_ibuf/OUT
    AG12                 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
                                                      0.049     0.892 r  pll_i/inst/clkin1_ibuf/IBUFCTRL_INST/O
                         net (fo=1, routed)           0.975     1.867    pll_i/inst/clk_in1_clk_wiz_0
    MMCME3_ADV_X1Y0      MMCME3_ADV (Prop_MMCME3_ADV_CLKIN1_CLKOUT0)
                                                     -4.474    -2.607 r  pll_i/inst/mmcme3_adv_inst/CLKOUT0
                         net (fo=1, routed)           0.501    -2.106    pll_i/inst/clk_out1_clk_wiz_0
    BUFGCE_X1Y0          BUFGCE (Prop_BUFCE_BUFGCE_I_O)
                                                      0.101    -2.005 r  pll_i/inst/clkout1_buf/O
    X2Y0 (CLOCK_ROOT)    net (fo=3, routed)           1.389    -0.616    pll_clk
    SLICE_X49Y58         FDRE                                         r  foo_reg_reg/C
  -------------------------------------------------------------------    -------------------
    SLICE_X49Y58         FDRE (Prop_EFF2_SLICEL_C_Q)
                                                      0.138    -0.478 f  foo_reg_reg/Q
                         net (fo=1, routed)           0.241    -0.237    foo_reg
    SLICE_X49Y58         LUT1 (Prop_D5LUT_SLICEL_I0_O)
                                                      0.244     0.007 r  bar__0_i_1/O
                         net (fo=1, routed)           0.046     0.053    p_0_in
    SLICE_X49Y58         FDRE                                         r  bar_reg__0/D
  -------------------------------------------------------------------    -------------------

                         (clock clk_out1_clk_wiz_0 rise edge)
                                                      8.000     8.000 r
    AG12                                              0.000     8.000 r  clk (IN)
                         net (fo=0)                   0.000     8.000    pll_i/inst/clkin1_ibuf/I
    AG12                 INBUF (Prop_INBUF_HRIO_PAD_O)
                                                      0.515     8.515 r  pll_i/inst/clkin1_ibuf/INBUF_INST/O
                         net (fo=1, routed)           0.066     8.581    pll_i/inst/clkin1_ibuf/OUT
    AG12                 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
                                                      0.034     8.615 r  pll_i/inst/clkin1_ibuf/IBUFCTRL_INST/O
                         net (fo=1, routed)           0.873     9.488    pll_i/inst/clk_in1_clk_wiz_0
    MMCME3_ADV_X1Y0      MMCME3_ADV (Prop_MMCME3_ADV_CLKIN1_CLKOUT0)
                                                     -3.934     5.554 r  pll_i/inst/mmcme3_adv_inst/CLKOUT0
                         net (fo=1, routed)           0.422     5.976    pll_i/inst/clk_out1_clk_wiz_0
    BUFGCE_X1Y0          BUFGCE (Prop_BUFCE_BUFGCE_I_O)
                                                      0.091     6.067 r  pll_i/inst/clkout1_buf/O
    X2Y0 (CLOCK_ROOT)    net (fo=3, routed)           1.218     7.285    pll_clk
    SLICE_X49Y58         FDRE                                         r  bar_reg__0/C
                         clock pessimism              0.051     7.336
                         clock uncertainty           -0.062     7.274
    SLICE_X49Y58         FDRE (Setup_DFF2_SLICEL_C_D)
                                                      0.067     7.341    bar_reg__0
  -------------------------------------------------------------------
                         required time                          7.341
                         arrival time                          -0.053
  -------------------------------------------------------------------
                         slack                                  7.288

paths与之前的例子相比,只有一处不同: PLL (在报告中显示为 MMCME3_ADV_X1Y0 )已插入外部 clock pin 和 global clock buffer之间。

这个 PLL 有一个戏剧性的效果: 在 source clock path中, PLL的 delay 是 −4.474 ns,在 destination clock path 中同样是 delay 是 −3.934 ns。这个负的 delay 代表 PLL 调整 clock edge 使得 global clock 在 input pin处比 clock 稍早。请注意, clock在 global clock buffer 的 output 处的总 delay 是 source clock path中的 −0.616 ns 。同样的 delay 就是 destination clock path中的 7.285 ns 。这是 0.715 ns ,早于第二个 clock edge (位于 8 ns)。

也就是说,外接的 clock pin 和 global clock (即交付给 logic)在两个 clock paths上的时间差几乎是一样的。尽管一个 clock path 是用最大的 delays计算的,第二个 clock path 是用最小的 delays计算的,但总的结果几乎是一样的。

这不是巧合: PLL 把 global clock output 当作 reference使用,所以调整 global clock buffer的 input 的 phase ,保证与 clock input pin的关系。最小 delays 和最大 delays 之间的差异由 PLL补偿。 timing 计算反映了这一点,因为最快和最慢情况之间的差异只是 0.1 ns。由于没有 PLL (0.575 ns,请参阅上一页的“Clock pessimism removal”),因此前一示例中的差异要大得多。

为什么 global clock 在外置 input之前调整到 0.6 ns 左右,而不是任何其他值是另一回事。这使得在许多情况下更容易实现与 I/O pins 相关的 timing constraints ,因此工具会自动做出此选择。尽管如此,所有 FPGAs 都可以选择操纵此 delay。

两个 related clocks

通常,一个 logic design 需要多个 clock。 FPGA design 中多个 clocks 的存在是它自己的话题,在 clock domains的介绍中讨论。 clock domains 和 timing这两个主题是密不可分的,因此建议在继续阅读之前通读该介绍(可能是简短的)。由于这两个主题之间的密切关系,该介绍与本系列页面之间存在一些重叠。

在下面的讨论中,我会经常使用“ signal X 与 @clk同步”这样的表述。这意味着 X 是 flip-flop 的 output ,它仅响应名称为“clk”的 clock 的 rising edge 更改值( asynchronous resets除外,但这无关紧要)。自然地,如果两个 signals 是 flip-flops 的 outputs 响应同一个 clock,那么这两个 signals 就是“同步同一个 clock”。

我们现在将查看由同一个 PLL生成的两个 clocks 。这很有趣,因为在大多数情况下,这两个 clocks 被认为是 related clocks。要理解为什么这很有趣,假设有一个 flip-flop 与其中一个 clocks同步,另一个 flip-flop 与第二个 clock同步。在这种情况下,在这两个 flip-flops 之间连接 signals 就可以了,就好像它们与同一个 clock同步一样。 FPGA 工具确保在这种情况下满足 timing 要求。

为了更好地了解如何使用多个 clocks,有一个关于 related clocks 和 unrelated clocks的单独页面。那一页是 clock domain crossing的介绍。在这里,我们重点关注 related clocks的 timing 方面,特别是与此类 clocks相关的 timing report 。

为了生成下面的 timing reports ,示例中使用了不同的 PLL (即 Clocking Wizard IP)。这个新的 PLL 的名字是 clk_wiz_1。使用了以下 Verilog 代码:

module top(
    input clk,
    input foo,
    output reg bar_reg
);
    reg foo_reg;
    reg bar;
    wire pll_clk_8, pll_clk_6;

   clk_wiz_1 pll_i
   (.clk_in1(clk),
    .clk_out1(pll_clk_8),
    .clk_out2(pll_clk_6));

always @(posedge pll_clk_8)
  foo_reg <= foo;

always @(posedge pll_clk_6)
  begin
    bar <= !foo_reg;
    bar_reg <= bar;
  end

和之前一样,这个 PLL (即 @clk)的 input 是 250 MHz,但是它有两个 outputs: 一个连接到 @pll_clk_8,它运行在 125 MHz (即 clock period 是 8 ns,因此是 signal的名称)。这与前面示例的 @pll_clk完全一样。第二个 output 连接到 @pll_clk_6,它有一个 clock period 等于 6 ns,大约是 166.67 MHz。

因为 @pll_clk_8 和 @pll_clk_6 是由同一个 PLL生成的,所以是 related clocks。

clk_wiz_1 也启用了 phase alignment 选项,特别是为了与前面的示例保持一致。如果对此有任何疑问: timing constraint依然只有一颗,和之前一样:

create_clock -period 4.000 -name clk [get_ports clk]

了解 clock summary

所有 clocks 的信息汇总在 timing report的开头。我现在才提出这个问题,因为当有多个 clock时, clock summary 更有趣。所有 FPGA 工具都会在报告中生成此类摘要,查看这一部分总是一个好主意:

-------------------------------------------------------------------------
| Clock Summary
| -------------
-------------------------------------------------------------------------

Clock                 Waveform(ns)         Period(ns)      Frequency(MHz)
-----                 ------------         ----------      --------------
clk                   {0.000 2.000}        4.000           250.000
  clk_out1_clk_wiz_1  {0.000 4.000}        8.000           125.000
  clk_out2_clk_wiz_1  {0.000 3.000}        6.000           166.667
  clkfbout_clk_wiz_1  {0.000 2.000}        4.000           250.000

这部分的主要优点是它很容易理解,也很容易检查关于 timing constraints的最常见错误: 如果 clock 具有正确的频率。

此 clock summary 表明 timing constraint 已被正确解释: 有一个外部 clock 定义为 clk,其 clock period 为 4 ns。除此之外, clocks还有三款衍生品: clk_out1_clk_wiz_1、 clk_out2_clk_wiz_1 和 clkfbout_clk_wiz_1。顾名思义,它们是由于 PLL 自动生成的,名称为 clk_wiz_1。

前两个 clocks (clk_out1_clk_wiz_1 和 clk_out2_clk_wiz_1)是 PLL的两个 outputs 。第三个 clock (clkfbout_clk_wiz_1)是 PLL 用来将 global clocks 的 phase 调整为外置的 clock。 clkfbout_clk_wiz_1 与 @clk具有相同的频率。

当启用 phase alignment 选项时, PLL的 feedback clock (clkfbout_clk_wiz_1) 连接到 global clock buffer。由于 PLLs 始终在其 input clock 和 feedback clock 之间同步(通过对齐这些 clocks,或在它们之间保持固定的 delay ), clkfbout_clk_wiz_1 是 global clock 的事实也确保了 input clock 和另一个 output clocks之间的已知 delay 。

需要注意的是, clk_out1_clk_wiz_1、 clk_out2_clk_wiz_1 和 clkfbout_clk_wiz_1 并没有定义现实中存在的 clocks 。这些只是软件用于 timing 计算的 clocks 符号。表明这些 clocks 是理论上的一件事是它们的 waveforms,它们在 clock summary中显示: 这些 waveforms 反映了这些 clocks中的每一个的 duty cycle 。但这并不意味着所有四个 clocks (clk 和三个理论上的 clocks)都有一个 rising edge 正好是 0 ns。特别是,这并不意味着这四个 clocks 是完美对齐的。即使它们对齐,通过 timing 计算也是可见的,真正的对齐并不完美。

下面将讨论如何使用这些理论 clocks ,以及涉及其中两个 clocks的 timing 计算。

这些理论上的 clocks 的另一个重要之处在于,它们的创建没有明确的 timing constraint : clk_out1_clk_wiz_* 的创建不存在于 design的 sources 或由工具创建的文件中。在大多数情况下,尝试编写这样的 timing constraint是不正确的,因为这样将无法正确计算 clock path 的 delays 。如果这样写 constraints , clocks 之间的相对 timing 将被工具计算错误, related clock domains 之间的 paths 将无法正确计算。

所以再一次,只有一个 timing constraint 应该自动为所有 PLL的 output clocks生成 timing constraints 。

timing report 与两个 related clocks

从上面的 Verilog 代码可以看出, @foo_reg 与 @pll_clk_8同步, @bar 与 @pll_clk_6同步。因此,更新 @bar 的语句涉及 clock domain crossing:

bar <= !foo_reg;

两个 clocks 是 related clocks,因此工具确保通过此计算满足 @bar的 timing 要求(对于 tsu):

Slack (MET) :             0.475ns  (required time - arrival time)
  Source:                 foo_reg_reg/C
                            (rising edge-triggered cell FDRE clocked by clk_out1_clk_wiz_1  {rise@0.000ns fall@4.000ns period=8.000ns})
  Destination:            bar_reg__0/D
                            (rising edge-triggered cell FDRE clocked by clk_out2_clk_wiz_1  {rise@0.000ns fall@3.000ns period=6.000ns})
  Path Group:             clk_out2_clk_wiz_1
  Path Type:              Setup (Max at Slow Process Corner)
  Requirement:            2.000ns  (clk_out2_clk_wiz_1 rise@18.000ns - clk_out1_clk_wiz_1 rise@16.000ns)
  Data Path Delay:        1.160ns  (logic 0.307ns (26.466%)  route 0.853ns (73.534%))
  Logic Levels:           1  (LUT1=1)
  Clock Path Skew:        -0.250ns (DCD - SCD + CPR)
    Destination Clock Delay (DCD):    -0.681ns = ( 17.319 - 18.000 )
    Source Clock Delay      (SCD):    -0.600ns = ( 15.400 - 16.000 )
    Clock Pessimism Removal (CPR):    -0.169ns
  Clock Uncertainty:      0.182ns  ((TSJ^2 + DJ^2)^1/2) / 2 + PE
    Total System Jitter     (TSJ):    0.071ns
    Discrete Jitter          (DJ):    0.103ns
    Phase Error              (PE):    0.120ns
  Clock Net Delay (Source):      1.369ns (routing 0.002ns, distribution 1.367ns)
  Clock Net Delay (Destination): 1.208ns (routing 0.002ns, distribution 1.206ns)

    Location             Delay type                Incr(ns)  Path(ns)    Netlist Resource(s)
  -------------------------------------------------------------------    -------------------
                         (clock clk_out1_clk_wiz_1 rise edge)
                                                     16.000    16.000 r
    AG12                                              0.000    16.000 r  clk (IN)
                         net (fo=0)                   0.000    16.000    pll_i/inst/clkin1_ibuf/I
    AG12                 INBUF (Prop_INBUF_HRIO_PAD_O)
                                                      0.738    16.738 r  pll_i/inst/clkin1_ibuf/INBUF_INST/O
                         net (fo=1, routed)           0.105    16.843    pll_i/inst/clkin1_ibuf/OUT
    AG12                 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
                                                      0.049    16.892 r  pll_i/inst/clkin1_ibuf/IBUFCTRL_INST/O
                         net (fo=1, routed)           0.975    17.867    pll_i/inst/clk_in1_clk_wiz_1
    MMCME3_ADV_X1Y0      MMCME3_ADV (Prop_MMCME3_ADV_CLKIN1_CLKOUT0)
                                                     -4.438    13.429 r  pll_i/inst/mmcme3_adv_inst/CLKOUT0
                         net (fo=1, routed)           0.501    13.930    pll_i/inst/clk_out1_clk_wiz_1
    BUFGCE_X1Y1          BUFGCE (Prop_BUFCE_BUFGCE_I_O)
                                                      0.101    14.031 r  pll_i/inst/clkout1_buf/O
    X2Y0 (CLOCK_ROOT)    net (fo=1, routed)           1.369    15.400    pll_clk_8
    SLICE_X49Y58         FDRE                                         r  foo_reg_reg/C
  -------------------------------------------------------------------    -------------------
    SLICE_X49Y58         FDRE (Prop_EFF_SLICEL_C_Q)
                                                      0.139    15.539 f  foo_reg_reg/Q
                         net (fo=1, routed)           0.807    16.346    foo_reg
    SLICE_X49Y58         LUT1 (Prop_D5LUT_SLICEL_I0_O)
                                                      0.168    16.514 r  bar__0_i_1/O
                         net (fo=1, routed)           0.046    16.560    p_0_in
    SLICE_X49Y58         FDRE                                         r  bar_reg__0/D
  -------------------------------------------------------------------    -------------------

                         (clock clk_out2_clk_wiz_1 rise edge)
                                                     18.000    18.000 r
    AG12                                              0.000    18.000 r  clk (IN)
                         net (fo=0)                   0.000    18.000    pll_i/inst/clkin1_ibuf/I
    AG12                 INBUF (Prop_INBUF_HRIO_PAD_O)
                                                      0.515    18.515 r  pll_i/inst/clkin1_ibuf/INBUF_INST/O
                         net (fo=1, routed)           0.066    18.581    pll_i/inst/clkin1_ibuf/OUT
    AG12                 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
                                                      0.034    18.615 r  pll_i/inst/clkin1_ibuf/IBUFCTRL_INST/O
                         net (fo=1, routed)           0.873    19.488    pll_i/inst/clk_in1_clk_wiz_1
    MMCME3_ADV_X1Y0      MMCME3_ADV (Prop_MMCME3_ADV_CLKIN1_CLKOUT1)
                                                     -3.890    15.598 r  pll_i/inst/mmcme3_adv_inst/CLKOUT1
                         net (fo=1, routed)           0.422    16.020    pll_i/inst/clk_out2_clk_wiz_1
    BUFGCE_X1Y0          BUFGCE (Prop_BUFCE_BUFGCE_I_O)
                                                      0.091    16.111 r  pll_i/inst/clkout2_buf/O
    X2Y0 (CLOCK_ROOT)    net (fo=2, routed)           1.208    17.319    pll_clk_6
    SLICE_X49Y58         FDRE                                         r  bar_reg__0/C
                         clock pessimism             -0.169    17.150
                         clock uncertainty           -0.182    16.967
    SLICE_X49Y58         FDRE (Setup_DFF2_SLICEL_C_D)
                                                      0.067    17.034    bar_reg__0
  -------------------------------------------------------------------
                         required time                         17.034
                         arrival time                         -16.560
  -------------------------------------------------------------------
                         slack                                  0.475

如前所述, timing 计算是一个假想的实验,假想的秒表与 clock edges一起开始。在前面的示例中,此秒表从 0 ns开始。但在这个计算中是从 clock edge 开始于 16 ns。这是因为两个 clocks 的 clock periods 不相等。计算基于第一个 clock 和第二个 clock之间的最坏情况组合。

首款 clock的 rising edges 分别为 0 ns、 8 ns、 16 ns、 24 ns 等。第二个 clock的 rising edges 分别是 0 ns、 6 ns、 12 ns、 18 ns、 24 ns 等等。所以第一个 clock 和第二个 clock 的时间间隔最小的就是第一个 clock的 16 ns 和第二个 clock的 18 ns。这就是本 timing 计算检验的情况。

这意味着 data path 被限制在大约 2 ns,就像 500 MHz。这是一个非常严格的要求,但由于 data path中只有一个 LUT ,而两个 flip-flops 都在同一个 slice上,所以很容易达到这个目的。但是,此示例说明了为什么选择适合 related clocks的频率非常重要。通常选择一个 clock的频率作为另一个 clock频率的倍数。这样做可以避免像本示例的 2 ns 间隙这样的情况。

顺便说一下,如果无法选择协同工作的频率,解决方案是将 clocks 视为 unrelated clocks

衍生的 clocks

我前面提到 clk_out1_clk_wiz_1 和 clk_out2_clk_wiz_1 理论上是 clocks,而这个事实在 timing report上的体现是这样的: 请注意,两个 paths 都是以外部 pin (AG12) 作为起点计算的。这怎么说得通?实际上,这个 pin 上的 signal 是 reference clock,而不是这两个 clocks中的任何一个。

那么我们以 clk_out1_clk_wiz_1 为例: 计算背后的想法是假设在外部 pin处有一个 clock 和 125 MHz 。实际上, clock 与 125 MHz 只存在于 PLL的 output ,即 MMCME3_ADV_X1Y0的 output 。但不是在 timing 计算中涉及 PLL的频率操纵,而是使用理论上的 clock 。这个 clock 有一个从 0 ns开始的理想 waveform 。 PLL 被视为没有改变任何 clock的频率,而只是增加了 delays。

所以理论上的 clock (例如 clk_out1_clk_wiz_1)定义了 clock (频率、 duty cycle、 jitter 等)的 waveform 。但是,这个理论上的 clock 没有定义 timing 与其他 clocks 的关系,这些 clocks 在 FPGA上作为真实的 signals 存在。

那么我们如何才能看出 @pll_clk_6 和 @pll_clk_8 实际上是对齐的呢?答案在于这些 clocks的实际 timing 和理想的 timing 之间的比较。比如 clk_out1_clk_wiz_1的理论 clock edge 在上面的计算中就是 16 ns 。另一方面, clk_out2_clk_wiz_1的 clock edge 在 18 ns,后来是 2 ns。下面我们来对比一下 global clock tree的 outputs 的 clock edges : 根据 timing report,第一个 clock的 clock edge 到达 15.400 ns。对于第二个 clock edge,报告称 17.319 ns。所以根据计算,时间差是 1.919 ns 而不是 2 ns。这仅比理想差异小 0.081 ns 。所以 clocks 绝对对齐。

让我们与之前只有一个 clock的示例进行比较: 两个 clock edges 之间的理想时间差是 clock period,即 8 ns。但是根据相关的 timing report (见上),第一个 clock edge 到达 −0.616 ns,第二个 clock edge 到达 7.285 ns。理想的时差是 8 ns,但实际上是 7.901 ns。所以第二个 clock edge 比 0.099 ns预期的要早。

所以用两个 related clocks,从理想的时间差分流是 0.081 ns。只有一台 clock,这个分流也差不多, 0.099 ns。在这两种情况下,这种转移的原因是第一个 clock edge 的计算是用最大的 delays进行的,而最小的 delays 用于第二个 clock edge。

因此,结论是 @pll_clk_6 和 @pll_clk_8 的对齐精度与 clock大致相同。

请注意,即使没有启用 PLL的 phase alignment的选项,这些 clocks 也会相互对齐: PLL 的 outputs 通常是对齐的。通过使用具有几乎相同 delays的 global clock buffers 来确保这种对齐,而不管它们的 fanout。换句话说,不管这些 clock buffers 分别连接了多少个 logic elements ,从 PLL的 output 到目的地的 delay 是大致相同的。

我们对 related clocks的了解

对这个 timing report 的分析可以看出,两个 related clock domains 之间的一个 path 大致相当于一个 clock domain里面的一个 path 。然而,它并不完全相同。尤其是 Clock Uncertainty ,从 0.062 ns 升级到 0.182 ns,因为每个 clock 都有自己的 jitter,而且对齐也不是很完美。

这个 timing report 还展示了两个 clocks 的对齐如何反映在 timing 的计算中。

当 FPGA design中有 clock domain crossings 时,最好检查 timing report中这些 clocks 之间的交互。目的是确保工具能够像我们预期的那样处理 clocks 。这些是要检查的两个最重要的事情:

Vivado 可以创建一个 Clock Interaction Report,它以图形方式显示 design的 clock domain crossings,以及工具如何处理每个这样的 crossing 。其他 FPGA 工具也有类似的功能,例如 Quartus Pro的 CDC Viewer。如果可能,建议创建并检查此报告。

另一件要看的事情是 clocks 是否对齐。如果 design 误用了未对齐的 clock,可能会给 timing constraints的实现造成不必要的困难。例如,如果 @clk 和 @pll_clk_8之间有一个 path ,工具将强制执行 timing constraints,从而确保这个 path 可靠地工作。但请注意, @clk 是进入 PLL的 reference clock ,而 @pll_clk_8 是此 PLL的 output 。因此这两个 clocks 没有对齐。因此,为了实现 path的 timing constraints ,这些工具可能会付出不必要的努力。由于这种不必要的努力,其他 paths 可能无法实现其 timing constraints 。

再一次, clock domains 的主题包含在本系列页面中。

thold 也很重要

到目前为止,我展示的所有 timing 计算都与 tsu 要求相关。关注这个要求是很自然的,因为当工具无法实现 timing constraints时,几乎总是因为至少有一个 path 无法实现 tsu的要求。

牢记 thold 仍然很重要: 为了满足此要求,工具有时会通过添加 routing delay来人为地降低 data path 的速度。因此,尽管 thold 要求很少被提及作为实现 timing constraints失败的原因,但该要求可能是失败的隐藏原因。

事实上,连接两个 flip-flops的线的 routing delay 发生了一些相关的事情: 在所有只涉及一个 clock的 timing reports 中,这根线在同一个 slice (SLICE_X49Y58)内。因此,在所有这些报告中,该电线的 delay 都是 0.241 ns 。但是当两个 clocks 牵涉到 path的时候,这个 delay 就上去了 0.807 ns。

解释是 0.241 ns 是放在同一个 slice中的两个 flip-flops 之间可以实现的最小 delay 。较长的 delay (0.807 ns) 是此线的不同 routing 的结果。这不是偶然发生的: 为了满足 thold 的要求,工具特意把 routing 加长了。这也反映在报告中的“Data Path Delay”行中: logic 的 delay 就是 26.5%,其余的就是 routing。仅此一项就表明发生了某些事情。更多关于下面的内容。

thold 需求分析

从本系列页面的理论页面回想一下, thold 是第二个 flip-flop 上的 data input 在 clock edge之后必须稳定的时间量。下面描述一下违反 thold 的情况: 一个 clock edge 到达第一个 flip-flop,第二个 flip-flop 也几乎同时收到一个 clock edge (请注意,这些 clock edges 可以来自同一个 clock ,也可以来自不同的 clocks)。为了响应其 clock edge,第一款 flip-flop 在 delay (clock-to-output)之后更新了其 output 。但更新值过早到达第二个 flip-flop 。因此,此 flip-flop 无法可靠地对之前的值进行采样: 新值在第二个 flip-flop 有时间完成对其 clock edge的反应之前到达。换句话说,违反了 thold 要求。

当同一个 clock 与两个 flip-flops一起使用时,会发生这种情况主要是因为 clock skew: 如果 clock edge 比第一个 flip-flop更早到达,则第一个 flip-flop 可能会过早地更改其 output 。这为更新的 signal 到达第二个 flip-flop 的速度足以违反 thold 要求的可能性打开了大门。请注意,到达两个 flip-flops的是同一个 clock edge ,因此 clock的频率或 clock jitter的数量都没有意义。只有不同的 delay (即 clock skew)起作用。

但下面对 timing 的分析,还是以最后一个例子为主,涉及两台 clocks: @pll_clk_8 和 @pll_clk_6。一个 timing analysis 和一个 clock 会很相似,但没那么有趣,因为用一个 clock很容易满足 thold 的要求。

所以我们要看的 timing report 是为两个 related clocks设计的。这两台 clocks 频率不同,和之前一样,第一台 clock的 clock edge 和第二台 clock的 clock edge的时间有不同的组合。但与 tsu的计算不同, thold 的最坏情况是两个 clock edges 都在 0 ns时: 当两个 clock edges 几乎同时发生时,就会发生 thold 违规,因此没有比这更糟糕的组合了。

因此,有了这些手头的见解,让我们看看 timing report:

Slack (MET) :             0.093ns  (arrival time - required time)
  Source:                 foo_reg_reg/C
                            (rising edge-triggered cell FDRE clocked by clk_out1_clk_wiz_1  {rise@0.000ns fall@4.000ns period=8.000ns})
  Destination:            bar_reg__0/D
                            (rising edge-triggered cell FDRE clocked by clk_out2_clk_wiz_1  {rise@0.000ns fall@3.000ns period=6.000ns})
  Path Group:             clk_out2_clk_wiz_1
  Path Type:              Hold (Min at Fast Process Corner)
  Requirement:            0.000ns  (clk_out2_clk_wiz_1 rise@0.000ns - clk_out1_clk_wiz_1 rise@0.000ns)
  Data Path Delay:        0.458ns  (logic 0.104ns (22.707%)  route 0.354ns (77.293%))
  Logic Levels:           1  (LUT1=1)
  Clock Path Skew:        0.127ns (DCD - SCD - CPR)
    Destination Clock Delay (DCD):    -0.542ns
    Source Clock Delay      (SCD):    -0.248ns
    Clock Pessimism Removal (CPR):    -0.421ns
  Clock Uncertainty:      0.182ns  ((TSJ^2 + DJ^2)^1/2) / 2 + PE
    Total System Jitter     (TSJ):    0.071ns
    Discrete Jitter          (DJ):    0.103ns
    Phase Error              (PE):    0.120ns
  Clock Net Delay (Source):      0.495ns (routing 0.002ns, distribution 0.493ns)
  Clock Net Delay (Destination): 0.576ns (routing 0.002ns, distribution 0.574ns)

    Location             Delay type                Incr(ns)  Path(ns)    Netlist Resource(s)
  -------------------------------------------------------------------    -------------------
                         (clock clk_out1_clk_wiz_1 rise edge)
                                                      0.000     0.000 r
    AG12                                              0.000     0.000 r  clk (IN)
                         net (fo=0)                   0.000     0.000    pll_i/inst/clkin1_ibuf/I
    AG12                 INBUF (Prop_INBUF_HRIO_PAD_O)
                                                      0.339     0.339 r  pll_i/inst/clkin1_ibuf/INBUF_INST/O
                         net (fo=1, routed)           0.025     0.364    pll_i/inst/clkin1_ibuf/OUT
    AG12                 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
                                                      0.015     0.379 r  pll_i/inst/clkin1_ibuf/IBUFCTRL_INST/O
                         net (fo=1, routed)           0.405     0.784    pll_i/inst/clk_in1_clk_wiz_1
    MMCME3_ADV_X1Y0      MMCME3_ADV (Prop_MMCME3_ADV_CLKIN1_CLKOUT0)
                                                     -1.721    -0.937 r  pll_i/inst/mmcme3_adv_inst/CLKOUT0
                         net (fo=1, routed)           0.167    -0.770    pll_i/inst/clk_out1_clk_wiz_1
    BUFGCE_X1Y1          BUFGCE (Prop_BUFCE_BUFGCE_I_O)
                                                      0.027    -0.743 r  pll_i/inst/clkout1_buf/O
    X2Y0 (CLOCK_ROOT)    net (fo=1, routed)           0.495    -0.248    pll_clk_8
    SLICE_X49Y58         FDRE                                         r  foo_reg_reg/C
  -------------------------------------------------------------------    -------------------
    SLICE_X49Y58         FDRE (Prop_EFF_SLICEL_C_Q)
                                                      0.049    -0.199 f  foo_reg_reg/Q
                         net (fo=1, routed)           0.343     0.144    foo_reg
    SLICE_X49Y58         LUT1 (Prop_D5LUT_SLICEL_I0_O)
                                                      0.055     0.199 r  bar__0_i_1/O
                         net (fo=1, routed)           0.011     0.210    p_0_in
    SLICE_X49Y58         FDRE                                         r  bar_reg__0/D
  -------------------------------------------------------------------    -------------------

                         (clock clk_out2_clk_wiz_1 rise edge)
                                                      0.000     0.000 r
    AG12                                              0.000     0.000 r  clk (IN)
                         net (fo=0)                   0.000     0.000    pll_i/inst/clkin1_ibuf/I
    AG12                 INBUF (Prop_INBUF_HRIO_PAD_O)
                                                      0.595     0.595 r  pll_i/inst/clkin1_ibuf/INBUF_INST/O
                         net (fo=1, routed)           0.042     0.637    pll_i/inst/clkin1_ibuf/OUT
    AG12                 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O)
                                                      0.022     0.659 r  pll_i/inst/clkin1_ibuf/IBUFCTRL_INST/O
                         net (fo=1, routed)           0.457     1.116    pll_i/inst/clk_in1_clk_wiz_1
    MMCME3_ADV_X1Y0      MMCME3_ADV (Prop_MMCME3_ADV_CLKIN1_CLKOUT1)
                                                     -2.474    -1.358 r  pll_i/inst/mmcme3_adv_inst/CLKOUT1
                         net (fo=1, routed)           0.209    -1.149    pll_i/inst/clk_out2_clk_wiz_1
    BUFGCE_X1Y0          BUFGCE (Prop_BUFCE_BUFGCE_I_O)
                                                      0.031    -1.118 r  pll_i/inst/clkout2_buf/O
    X2Y0 (CLOCK_ROOT)    net (fo=2, routed)           0.576    -0.542    pll_clk_6
    SLICE_X49Y58         FDRE                                         r  bar_reg__0/C
                         clock pessimism              0.421    -0.121
                         clock uncertainty            0.182     0.061
    SLICE_X49Y58         FDRE (Hold_DFF2_SLICEL_C_D)
                                                      0.056     0.117    bar_reg__0
  -------------------------------------------------------------------
                         required time                         -0.117
                         arrival time                           0.210
  -------------------------------------------------------------------
                         slack                                  0.093

首先,有一些明显的区别: Path Type 是 Hold,而不是之前的 Setup 。这是预期的。然后它说“Min at Fast Process Corner”,这与它对 setup path所说的相反: 此计算使用最小的 delays,而不是 data path的最大 delays 。这适用于 data input 变化过早的情况的最坏情况计算。

Requirement 是 0 ns,这是典型的 hold path。 clocks 的频率在这里不起作用: 检查的场景是两个 clocks 同时有一个 rising edge 。

至于 clock paths,请注意 source clock path 上每个组件的 delays 始终比 destination clock path 的相同 delays 短(但不会更长)。再次说明,这与本次计算的目的是一致的,因为最坏的情况是 data 变化过早,相对于 clock edge 到第二个 flip-flop的到来。 Multi-corner timing analysis 已在上一页进行了说明。

但这款 timing report 最重要的是 slack 体积小: 只有 0.093 ns。这通常表明工具必须做出努力才能满足要求。但是,请注意,小型 slack 并不一定表示存在需要解决的问题。

当 timing analysis 是为 thold制造时,小型 slack 非常常见。那么这台 path 为什么可疑呢?主要是因为同一个 slice (SLICE_X49Y58)上的两个 flip-flops 之间的 routing delay 更大,如上所述。很可能是在 place and route的早期阶段,软件检测到这两个 flip-flops之间无法满足 thold 的要求。那么这是如何纠正的呢?

未能满足 thold 要求意味着 data signal 相对于第二个 flip-flop的 clock edge 到货太早。这是通过人为地将 delay 添加到 data path来纠正的。结果, data input 在第二个 flip-flop上稍晚更改了它的值。这些工具可能使两个 flip-flops 之间的布线变长了。这样增加了 routing delay,解决了 thold的问题。 delay 的这种增加可能会产生问题以满足 tsu 的要求,但在这种情况下没有这样的问题: timing constraint 是为这个 path实现的。 (即满足 tsu 和 thold 的要求)。

尽管如此,此示例显示了解决 thold 问题的需要如何可能会产生看似与 tsu无关的问题。当 path在 logic delay 和 routing delay 之间的比率非常低时,请记住这一点。当然还有其他可能的原因导致 routing delay较大,尤其是较高的 fan-out。但是当 fan-out 较低时(如本例中, fan-out 为 1),值得一问的是,工具是否故意插入了较大的 routing delay 以解决 thold 问题。

但是为什么有两个 clocks的时候只有 thold 有问题呢?答案是两台 clocks, clock edges 什么时候到两台 flip-flops都有较大的不确定性。有几个因素导致了这种不确定性,尤其是 clock skew 和 jitter。由于 thold 的计算是从 0 ns 到 0 ns,因此该计算对 clock edges 何时到达的小不确定性更为敏感。

因此,与两个 related clocks 相关的不确定性通常需要纠正措施以满足 thold 的要求。当然,这些更正是由工具自动进行的。但在实现 timing constraints时遇到问题时,了解这些更正仍然很重要。

概括

本系列的最后两页显示了几个 timing reports 示例,这些示例都是一个特定 timing constraint的结果。所有这些 timing reports 也都与 logic的一个具体而简单的例子有关。希望这些示例有助于建立对 timing基础知识的理解。

此时,建议查看您自己的 design的 timing reports ,以了解相同的原理如何适用于包含多个 LUT的 paths 。

下一页开始讨论 timing 问题以及如何解决这些问题。

此页面由英文自动翻译。 如果有不清楚的地方,请参考原始页面
Copyright © 2021-2024. All rights reserved. (6f913017)