01signal.com

Clock domains、 related clocks 和 unrelated clocks

此页面是有关 clock domains的系列中的三个中的第一个。

介绍

除了非常琐碎的 FPGA designs之外,不止一个 clock 与它的 synchronous elements 一起使用(flip-flops、 block RAMs、 shift registers 等)。 logic design 内部的大部分功能单元都是基于一个 clock 的,所以大多数时候,多个 clocks 的话题并不需要特别注意。当基于一个 clock 的 logic 与依赖于另一个 clock的 logic 连接时,事情变得更加困难。本系列页面讨论如何在 design中使用多个 clocks 。

在连接依赖于不同 clocks的 logic 时,首先要回答的也是最重要的问题是是否需要 resynchronization logic 。这相当于询问这两个 clocks 是不是 related clocks 。此页面解释了这个问题以及如何回答它,以及其他相关主题。下面的很多讨论都与 timing constraints 以及在 logic的某些元素上强制执行它们的可能性有关。出于这个原因,我将首先简要回顾一下 timing。

本系列页面的讨论仅限于 positive edge triggered flip-flops,即 flip-flops 对其 clock inputs的 rising edges 做出反应。当然也存在其他 synchronous elements ,即基于 clock采样和产生信号的 logic elements : Shift registers、 block RAMs 和一大堆其他功能元素。其中一些元素可能会对 clock的 falling edge 产生反应,甚至对两者都有反应。在这里的讨论中,为了简单起见,我忽略了所有这些。

另外,我将使用“X 与 Y同步”的表达方式来表示 synchronous element X的 clock input 连接到 clock Y。因此,这个 synchronous element 用这个 clock对其 input (或 inputs)进行采样,并用它更新它的 outputs 。

简述 timing的基础知识

这是 timing理论的简短总结。可以在单独的页面上找到更详细的解释。

考虑下图,它显示了 signal path 从一个 flip-flop 到另一个 LUT:

Crossing clock domains: Two flip-flops and a LUT between them

此图中的 LUT (Look-Up Table) 代表任意一组 combinatorial logic: I1、 I2、 I3 或 I4 的任何变化都会导致 output O立即发生变化,数量为 propagation delay。

因此 signal path 是这样的: 左边 flip-flop的 Q output,标有 @foo,在其 input clock、 @clk1上一个 rising edge 后变化。由于此 output 连接到 I1,因此 LUT的 output O 可能会在短暂延迟后发生变化。这进入右边 flip-flop的 data input,也就是 D。在 @clk2上的 rising edge 之后, flip-flop 将 D 复制到 Q (标记为 @bar)。

但这并不是那么简单。所有 flip-flops 都有时序要求: data input (D)在 @clk2的 rising edge之前必须是稳定的 tsu ( setup time),在 edge之后保持稳定的 thold ( hold time)。

FPGA 中的绝大多数 signal paths 都与单个 clock相关,因此 @clk1 和 @clk2 是完全相同的 clock 信号(我们将忽略 clock skew)。对于这样的 paths,可以计算这两个时序要求是否可以保证。

比如我们看上图和 tsu的时序要求: 思路是找出从 @clk1 的 rising edge 到右边 flip-flop 的 D input 更新稳定需要多少时间。这是 path上所有延迟的总和: 它从 @clk1 的 rising edge 到 @foo 更新(“clock to output”)的延迟开始,并继续所有延迟,直到右侧的 flip-flop 的 D input 。这包括 LUT 的延迟以及 logic elements (routing delays) 之间的布线延迟。

因为 @clk1 和 @clk2 是同一个 clock,所以我们知道两个 flip-flops 上的下一个 rising edge 什么时候是: 稍后是 clock period (例如 10 ns 用于 100 MHz clock)。所以 path的总延迟一定要低于 clock period,有 tsu的余量。如果可以保证这一点,它可以确保 tsu 需要什么: 右侧的 flip-flop 的 D input 在 @clk2的 rising edge 之前具有一定的时间余量 (tsu)。有关数字示例,请参阅有关 timing 理论的页面

可以对 thold进行类似的计算。与 tsu不同,要求是右侧 flip-flop 的 D input 在 @clk2的 rising edge 之后保持稳定一段时间(thold)。因此, clock period 是无关紧要的,不予考虑(当 @clk1 和 @clk2 相同时)。重要的是在同一个 clock cycle上发生了什么,而不是下一个。

请注意,这种计算是可能的,因为我们知道 @clk1 的 rising edge 和 @clk2的 rising edge 之间的时间差。特别是如果 @clk1 和 @clk2 是同一个 clock,这个用来计算 tsu 的时间差就是那个 clock的 clock period 。但是如果这两个 clocks 的时间差不知道的话,就不能保证既不是 tsu 也不是 thold

每个 flip-flop都需要 tsu 和 thold 的要求。当然,这包括 FPGA上的所有 flip-flops ,但也包括外部 devices 上的 flip-flops (即从 FPGA 的 output pin 到外部 device ,它使用 clock对信号进行采样)。所以对于系统中的每一个 flip-flop ,我们都要问问自己,是否保证满足这两个要求。对于我们无法保证这一点的 flip-flops ,我们必须确保尽管如此(即 resynchronization logic)仍能确保可靠运行的机制。简而言之,这就是 crossing clock domains 的主题。

再说一遍: timing 什么时候有保证?

以防您在上一节中迷失了方向,以下是要点:

回想一下, FPGA design 始终包含 timing constraints,它会通知 design 工具有关 clocks频率的信息。基于此信息,这些工具可确保满足两个时序要求(tsu 和 thold) 得到满足。或者,如果工具无法满足这些要求,它们会报告此失败。

如上所述,可以保证 tsu 而 thold只有在知道 path 开头的 clock 的 rising edges 和 path结尾的 clock 的时间差的情况下。大多数情况下都是这种情况,因为 logic design 的大部分由 registers 组成, registers 依赖于与同一 clock同步的其他 registers 。

但是如果使用两个不同的 clocks 呢?如果一个 clock 在 path的开头连接到 flip-flop ,另一个 clock 在 path的末尾连接到 flip-flop ?换句话说,如果 @clk1 和 @clk2不一样呢?是否仍然可以进行时序计算并确保时序要求?这得看情况。这就是本页其余部分的内容。

Clock domains 和 clock domain crossing

clock domain 由与某个 clock signal同步的所有 synchronous elements (即 flip-flops 等)组成。

考虑这个简单的 Verilog 代码片段:

reg foo, bar;

always @(posedge clk1)
  foo <= !foo;

always @(posedge clk2)
  bar <= foo;

在本例中, @foo 与 @clk1同步, @bar 与 @clk2同步。很明显, @foo 和 @bar 属于不同的 clock domains (分别属于 @clk1 和 @clk2)。

@foo无需担心: 它只取决于它自己。但是 @bar 与 @clk2 同步,并且依赖于 @foo, @foo与 @clk1同步。那么 @bar 可以和任何 register一样使用吗?我们是否可以假设 @bar 总是以合法的时间获得 @foo 的值,所以它的行为是已知的和可重复的?

在尝试回答这个问题之前,让我们为刚刚发生的事情命名。这是 clock domain crossing: @foo 和 @bar 实现为两个 flip-flops ,它们与不同的 clocks同步。所以从 @foo 到 @bar 的 path 从一个 clock domain 到另一个。

更一般地, clock domain crossing 是指当属于一个 clock domain 的 synchronous element 的 output 结束于属于另一个 clock domain的 synchronous element 的 input 时。这两个 synchronous elements之间经常有 combinatorial logic 。

所以即使 @bar 被定义为

always @(posedge clk2)
  bar <= !foo || !bar;

这里还有一个 clock domain crossing 。在这种情况下,它会从 @foo开始,经过实现 logic function的 LUT ,并在 @bar结束,如上图所示。

Related clocks 与 unrelated clocks

术语 related clocks 指的是从相同的 reference clock 派生的 clocks ,以确保它们的 rising edges 和 falling edges 之间可预测的时间差(除了已知的不准确和 jitter)。

通常使用术语“synchronous clocks”代替“related clocks”。同样,通常使用“asynchronous clocks”代替“unrelated clocks”。

related clock 的一个常见示例是使用单个 FPGA PLL 生成多个 clocks,它们的频率之间具有已知的关系。在这种情况下, FPGA 工具通常会排列 clock buffers ,使 clock edges 尽可能对齐。

例如,当 reference clock 乘以 2 和 3 时:

Simple clock diagram with clock multiplication

在此示例中, x1 clk、 x2 clk 和 x3 clk 是 related clocks,因为每对 clocks 之间的 timing 是可预测的。

在一般情况下, reference clock 是与其他任何 clocks相关的 unrelated clock : reference clock与 edges 之间的 timing 相对于其他 clocks 可能会随温度和其他因素而变化。但是,如果 PLL 配置为确保 reference clock 和 PLL的 outputs之间的可预测对齐,那么即使 reference clock 也是 related clock。

clocks 之间的时间关系知识允许在 clock domains之间进行 paths 的时间计算。例如, x1 clk 的 domains 和 x2 clk 之间的 path 的时序计算与 x2 clk 和自身之间的 path 的要求相同。这是因为这两个 clocks 之间的最短时间差与 x2 clk的两个 rising edges 之间的时间相同。

同样,可以计算出 x2 clk 和 x3 clk 之间的 path ,但最短的时间差只是 x1 clk的 period的六分之一。因此,最坏情况下的时序要求对应于想象中的 x6 clk。原因是 x2 clk 的第二个 rising edge 和 x3 clk的第三个 rising edge 的时间差。

有关如何计算 timing 的更详细讨论,请参阅此页面

所以这个例子的重点是说一些即使在一般情况下也是正确的: 使用 related clocks,可以通过在这些 clocks之间在 paths 上强制执行 timing constraints 来保证时序,就像在同一个 clock domain中的 paths 一样。当 FPGA 工具有意确保 clock edges 对齐时,这是可能的。如示例中所示,时序要求通常比单独的每个 clocks 更严格,有时甚至更严格。

但是请注意,两个 clocks 派生自同一个 reference clock 的事实并不一定使它们成为 related clocks。特别是,如果这些 clocks 之间的 skew 不受控制或未知(除非 design 工具明确使用具有相同延迟的 clock distribution 资源,否则会出现这种情况),则应将它们视为 unrelated clocks。

甚至 clk x1 也不一定与其 reference clock相关,即使它们具有完全相同的频率。除非这些 clocks 故意相互对齐,否则它们的 phase relation 是未知的。

因为这个关于 phase的话题,我在上面对 clock domain 的定义中写了“某个 clock signal”,而不仅仅是“某个 clock”。例如,“某个 clock”可能意味着板上相同的 clock ,它连接到 FPGA的两个不同的 input pins 。而“某个 clock signal”则是指 Verilog 中的一个 wire 或者 design的 netlist 中代表一个 clock 信号,如上例中的 @clk1 和 @clk2 。它通过 ports 在 instantiations 中的连接或简单的“assign”语句分布在 Verilog design 中。

clock 与 Verilog 中的信号完全相同这一事实意味着这些工具将确保使用确保硬件上 clock skew 较低的资源。它还对这些工具是否将 clocks 视为 related clocks 有影响(更多内容见下文)。

Related clocks、 timing constraints 和 resynchronization logic

让我们回到最初的问题: 上例中的 @bar 可以像任何 register一样使用吗?或者更一般地说,如果 flip-flop 是从一个 clock domain 到另一个 clock domain 的 path 的目的地,我们能否像任何 flip-flop的 output一样可靠地使用它的 output ?当至少一个到达其 data input 的 path 与另一个 clock同步时,这与询问是否可以确保此 flip-flop的 setup time 和 hold time 相同。

答案很简单: 如果两边的 clocks (本例中的@clk1 和 @clk2 )都是 related clocks,那么目的地的 flip-flop的 output 就完全没问题了,可以像任何 register一样使用,前提是这个 path 的 timing constraint 合适。否则,无法确保目的地的 timing ,必须添加 resynchronization logic 来解决这个问题。

此页面显示了两个 related clocks之间的一个 path 的完整 timing analysis 。

在上面冗长的讨论之后,是时候将其总结为一些简单的规则了:

  1. 在属于 unrelated clocks的 clock domains 之间对 paths 强制执行 timing constraints 是不可能的。
  2. 如果两个 clock domains之间的所有 paths 上都有 resynchronization logic ,则无需对这些 paths强制执行 timing constraints 。
  3. 如果两个 clock domains之间的 path 上没有 resynchronization logic ,则必须在此 path上强制执行 timing constraints 。

第一条规则是最简单的: 如果您不能确定两个 clocks 是 related clocks,请确保在 clock domains 之间的所有 paths 上都有 resynchronization logic (下页说明如何)。还要确保在这些 paths上没有强制执行 timing constraints ,因为根据第二条规则这是可以的。不必要的 timing constraints 只会让 FPGA 工具变得更难。

这些规则的另一个结果是,即使 clocks 是 related clocks,也可以将它们视为 unrelated clocks。如前所述,通过确保在所有 paths上安装 resynchronization logic 并关闭 timing constraints 的执行来做到这一点(更多内容见下文)。

最后,如果您确定 clocks 是 related clocks,则不需要 resynchronization logic,但必须在 clock domains之间的所有 paths 上正确执行 timing constraints 。

此表总结了本节。表格的行是关于 path的末尾是否有 resynchronization logic ,它的列是关于 clocks 是否是 related clocks 。表格中间表示 path 是否需要 timing constraints 。

clocks 是
related clocks unrelated clocks

Resynch-
ronization logic:

没有申请 path需要Timing constraints 这是个错误
应用 path不需要Timing constraints

常见错误

在复杂的 design中,信号通过不同的 modules连接,很容易忽略哪个信号与哪个 clock同步,从而在不知不觉中从一个 clock domain 移动到另一个 clock domain 。

有害错误有两种选择: 第一个是在 clock domains 和 unrelated clocks 之间创建一个 path ,没有任何 resynchronization logic。这意味着这些 paths的目的地偶尔可能会违反时序。就像所有时间错误一样,可见的问题可能非常具有误导性。如果这些工具从 timing constraints 推断出两个 clocks 是 related clocks,那么这些工具可能会增加混乱,因此不必要地将 timing constraints 应用于 paths。这些 timing constraints 在 unrelated clocks之间的 paths 上没有任何意义,但是这些 paths 会出现在报告中,就好像它们已经被正确处理了一样。这可能会使 timing reports 的人类读者误以为一切都很好,或者甚至可能认为 clocks 真的是 related clocks。

第二个有害错误是当两个 clocks 是 related clocks 并被 logic视为这样,但工具不认为它们是这样的。因此,在 clock domains之间的 paths 上没有强制执行 timing constraints 。因此,无法保证在目的地满足时序要求。再一次,这可能导致不可靠的行为。但是,在 design的时序验证检查中可能会发现此类错误。

没有注意到 clock domain crossing 真正无害的唯一情况是在 related clocks之间,并且 FPGA 工具也认为它们是这样的(因此将 timing constraints 强制执行到相关的 paths)。如果 clocks 有不同的频率,仍然可能存在功能错误,而 logic 没有考虑到这一点,但这就像 logic中的任何错误一样。

避免不必要的 constraining

很多时候,单个 PLL 用于创建具有不同频率的 clocks ,供不同功能单元使用。从设计者的角度来看,它们是 unrelated clocks,但实际上它们是 related clocks,工具通常认为它们是 related clocks。

例如,假设一个 PLL 从一个 reference clock 和一个 10 MHz生成两个 clocks 。一个 clock 是 90 MHz ,第二个 clock 是 100 MHz。目的是将这些 clocks 用于项目的不同部分,因此在概念上它们是 unrelated clocks。但是如果两台 flip-flops之间有连接,一台 flip-flop 与一台 clock同步,另一台 flip-flop 与另一台 clock同步呢?

因为第一个 clock 的 period 是 11.11 ns ,第二个 clock 的 period 是 10 ns,所以 rising edges 之间的最坏情况时间差是 1.11 ns (考虑到所有可能的 phase 组合)。那相当于 900 MHz的 clock period 。因此,这两个 flip-flops 之间的 path 的 timing 是紧的,即使能达到这个要求,也给工具带来了困难,特别是如果有很多这样的 paths。

这不是理论上的情况: 一个常见的陷阱是使用 dual-clock FIFO 与 clock domains接口,而不注意 clocks 是不是 related clocks 。这个错误没有功能问题,但由于 dual-clock FIFOs 总是有 resynchronization logic,所以强制工具在两个 clock domains之间的 paths 上强制执行 timing constraints 是没有意义的。这些工具可能无法毫无目的地实现这些 timing constraints 。

因此,重要的是要注意不是这样使用的 related clocks ,特别是来自同一个 PLL的 clocks : 奇怪的是, timing constraints 在 paths 上从一个 clock domains 强制执行到另一个 clock domains 。这种强制措施没有任何好处,因为 resynchronization logic 可以防止时序违规。另一方面,该工具在这些 paths 上实现 timing constraints 的努力可能会导致在整个 design上实现 timing constraints 的困难。

要解决此问题,请添加将 clocks 声明为 unrelated clocks的 timing constraints 。或者,为这些 paths定义false paths 或 maximal delays 。但是,在某些情况下,这可能不是必需的,因此在对这些 paths 进行任何操作之前,有必要检查 timing report 是否适合这些 paths 。例如,当使用 FPGA 工具提供的 dual-clock FIFO 时,通常会自动为 clock domains之间连接的 paths 添加足够的 timing constraints 。

误导 timing constraints

需要强调的是, FPGA tools 通常会在 unrelated clocks之间接受并强制执行 timing constraints 。这样的 constraints 毫无意义且令人困惑,尤其是因为相关的 paths 出现在 timing report 中,就好像它们的时序要求得到了保证一样。正如已经讨论过的,不可能在属于 unrelated clocks的 clock domains 之间保证 path 的时序。

请务必记住, timing constraints 只是向 FPGA tools 提供有关 design信息的一种方式。如果一个 design 达到了 timing constraints,那只有在 timing constraints 是正确的情况下才有意义。因此,如果您不确定 clocks 是否为 related clocks,请不要尝试仅通过添加 timing constraint 来解决 clock domain crossing 。

再一次,当它相关时,添加将 clocks 定义为 unrelated clocks或定义 false paths的 timing constraints 是一个好主意。这不仅使 FPGA 工具更容易使用,而且还避免了混淆。

确保正确通知工具

出于上述所有原因, FPGA design 工具具有关于哪些 clocks 是 related clocks哪些不是 related clocks的正确信息至关重要。或者更准确地说,FPGA 工具将 timing constraints 应用于所有不受 resynchronization logic 保护的 paths (包括 clock domains内部的 paths ,但这与此处无关)。

然而,确保这些工具与 logic design 具有相同的感知可能很困难: 每个 FPGA design software 都有自己的方式来自动假设 clocks之间的关系。所有工具的唯一共同点是,如果使用该工具的专用 clocking IP 生成两个或更多具有相同 PLL的 clocks ,该工具会将这些 clocks 视为 related clocks。因此,相关 clock domains 之间的 paths 将被计时,并且 timing constraints 将在这些 paths上强制执行。此实施通常基于为 reference clock提供的 timing constraint 。但不要认为这是理所当然的。

除此之外,每个工具都有自己的方式来推断 clocks之间的关系,甚至来自同一 FPGA 供应商的不同工具在某些情况下可能会做出不同的决定。最值得注意的是,与 Xilinx之前的旗舰工具 ISE相比, Xilinx的 Vivado 更倾向于假设 clocks 是 related clocks。

因此,没有适用于所有 FPGA design 工具的通用原则,即使是特定工具也可以做出令人惊讶的决定。真正解决这个问题的唯一方法是检查 timing reports,并为特定的 path groups 生成 timing reports ,以确保时序要求在必要时是正确的,而在不必要时则不存在。这是一项艰巨的任务,但值得付出努力。

本系列的第一页到此结束。下一页介绍 crossing clock domains的基础知识。

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