第8章 多时钟

 8.1 多时钟的序列和属性

几乎没有任何设计只能在单个时钟域上工作。到目前为止,我们已经看到属于单一时钟的属性。但是,如果您需要检查跨越时钟边界的时域条件,该怎么办?所谓的CDC(时钟域交叉)问题可以通过多个时钟断言来解决。

我们将彻底检查属性/序列如何跨越时钟边界。这两个时钟之间的关系是什么?一旦跨越时钟域,采样边如何评估?请注意,在单时钟系统中,采样沿始终为一个,即时钟的上升沿或下降沿。由于在多时钟系统中有两个(或更多)时钟,我们需要了解采样边沿如何跨越一个时钟到另一个时钟的边界。我认为最好在写实际的应用程序之前完全理解基础知识。

请注意,“序列”对多时钟的行为方式和属性对多时钟的行为方式存在差异。继续阅读...

图8.1显示了一个简单的多时钟序列。它说在(posedge clk0)A是真的,并且下一个最接近的严格(posedge clk1)B是真实的。请注意“非常接近的下一个”。这是因为当您连接两个子序列时,每个子序列都运行在不同的时钟上,因此只能从一个时钟域转换到下一个时钟域的下一个可用采样沿。当我们稍微深入一些细节时,这将会更加清晰。

向前跳一点,这个“非常接近下一个最接近的边缘”的语义就是为什么我们使用##1跨越时钟边界。那么,你可以在跨越时钟边界时使用##2吗?在学习多时钟序列和属性的基础知识时,记住这个问题。


                                                        图8.1 多时钟序列 - 基础

 8.1.1 多时钟序列

 图8.1中的时序图显示在(posedge clk0)时,'A'为真。时钟不同相,所以clk1的下一个时钟沿比posedge clk0延迟半个时钟。在posedge clk1'B '被采样为真,序列'mcloks'将通过。这里的要点是'## 1 @(posedge clk1)'只等于1/2 clk1而不是一个完整的周期,因为下一个最接近的严格posedge clk1在1/2时钟周期内到达。下一个时钟可以在时钟0之后的任何时间出现,并且将作为该子序列的采样边的 '非常接近的下一个'  边。

重要提示:两个子序列之间## 1的要求已从1800_2009中删除,我在这里留给那些正在使用1800-2005并且还没有转移到1800-2009的人。

 那么,如果clk0和clk1同相会发生什么?见下面的图8.2。解释在图中。不言而喻,在采样'B'之前,该序列将等待一个完整的时钟。但更重要的是要注意,如果时钟交叉边界上的时钟是相同的(在相位和相同周期内),则以下情况为真:

@ (posedge clk0) A ##1 @ (posedge clk1) B; is identical to
@ (posedge clk0) A ##1 @ (posedge clk0) B; is identical to
@ (posedge clk0) A ##1 B;

为了重申前面的概念,上述内容是相同的,因为## 1 @(posedge xxx )并不意味着2个时钟边缘。它只是意味着下一个clk的下一个边缘。


                                             图8.2 多时钟序列 - 相同的时钟

 8.1.2 多时钟序列:合法序列和非法序列

 在我们进入多时钟属性并基于我们的观察结果之前,让我们快速检查多时钟序列的合法和非法情况。同样,这些情况只适用于序列而不适用于属性。

 底线是,你只能在具有不同时钟的两个子序列之间有## 1。如果两边的时钟相同,那么就没有这种限制。图8.3明确表示。

 

       图8.3 多时钟序列 - 非法条件 - 仅适用于1800-2005。从1800-2009年取消限制

 注意重申一下,上述限制只适用于IEEE 1800-2005标准。 1800年至2009年这一限制已被删除。如果您使用的是1800-2005并且尚未转移到1800-2009,我仍然在此描述限制。

 8.1.3 多时钟的属性 - 'and'运算符

 之前已经讨论过两个序列的'与'的概念。但是如果序列中的时钟不同呢?上面要注意的重要一点是非常接下来严格的后续边缘的概念。在图8.4中,在clk0的posedge处,'a'被采样为高电平。这触发了结果是'b'和'c'的'与'。请注意,'b'预计在clk1的下一个边缘处(在clk0的posedge之后)为真。换句话说,即使在属性中有一个不重叠的运算符,我们也不会等待1个时钟。我们只是等待clk1的下一个posedge检查'b'是否为真。同样的故事适用于'c'。如图8.4所示,如果'b'和'c'都出现,则属性会通过。就像单个时钟的'and'一样,断言在最长(如此说)序列'c'的匹配后通过。

 

                                    图8.4 多时钟属性 - 两个不同时钟之间'与'运算符

 图8.5显示了另一种巩固多时钟断言的'与'概念的场景。 '与'在两个使用相同时钟的子序列之间。这种行为显而易见,但很有趣。这是因为(@(posedge clk1)b和@(posedge clk1)c)的作用基本上类似于‘@(posedge clk1)b and c’。因此,'b'和'c'现在都必须出现在clk1的下一个边界。

 总之,正如我们之前所见,‘@(posedge clk1)b和@(posedge clk1)c’与‘@(posedge clk1)b and c’相同。


                                     图8.5 多时钟属性 - 相同时钟之间'与'运算符

 8.1.4 多时钟的属性 - 'or'操作符

'与'的所有规则适用于'或' - 除非在单个时钟的属性中 - 当任一序列(即操作符的LHS或RHS)通过断言会通过。 '下一个严格的后续时钟沿'的概念与'and'相同。

请参考图8.6以更好地理解多时钟序列的'或'。当@(posedge clk1)b或@(posedge clk2)c发生时,属性通过。换句话说,如果@(posedge clk2)c在@(posedge clk1)b之前出现,则属性将在@(posedge clk2)c处pass。

 

                                                图8.6 多时钟属性 - '或'运算符

 8.1.5 多时钟的属性 - 'not'运算符

'not'是一个有趣的运算符,当涉及到多时钟断言。

 图8.7中的断言工作如下。在posedge clk0,'a'是真实的,它触发了随后的mclocks。属性mclocks指定@posedge clk1'b'必须为true,'c'不应该为true @ posedge clk2。时序图显示'a'在posedge clk0为真。在clk1的后面的边缘,'b'应该是真实的,并且因为它确实是真实的,所以属性移动。由于'与'它寻找'c'在下一个(换句话说,在clk0的边界之后的第一个后面的posedge clk2)是clk2的边缘。那么,'c'确实如此,但由于我们在@(posedgeclk2)前面有'not',属性将失败。 'not'的概念与单时钟的属性的概念相同,除了评估时钟的边缘。仿真日志阐明了这个概念。

 

                                        图8.7 多时钟属性 - 'not'操作符

 8.1.6 多时钟属性 - 时钟分辨率

 

                                            图8.8 多时钟属性 - 时钟分辨率

 这些规则在处理多时钟属性时很重要。重要的规则是非法规则。当前面和后面表达式的时钟不同时,不能使用重叠运算符。对于不同的时钟,你必须使用一个非重叠的蕴涵算子(图8.8)。

 图8.9和8.10说明了其他重要概念。时钟如何应用(或流动)从序列的一部分到另一部分?图中的描述解释了这是如何工作的。

  1.  在图8.9中,属性'mclocks'(posedge clk0)适用于'A'以及'B',因为'B'没有明确的时钟。到现在为止还挺好。
  2. 然后(posedgeclk1)适用于'C'。这也是有道理的。
  3.  但是,由于'D'没有显式指定自己的时钟,那么在'D'中应用了什么时钟?
  4.  根据1800-2005LRM,'D'将继承(posedge clk0)而不是(posedge clk1)。这不太直观。但是LRM非常清楚地表明时钟事件的范围不会从封闭的圆括号中流出。
  5.  在我们的案例中 “'B'## 1 @(posedge clk1)C”在括号内。所以一旦我们离开括号(posedge clk1)不会向前流动,但(posedge clk0)会前进到后续的'D'。


                                             图8.9 多时钟属性 - 时钟分辨率-II

 类似地,图8.9中的底部示例显示了当我们有多个子序列,每个子序列都有它自己的时钟时,时钟将如何“流动”。请注意,在这个序列中有三个不同的时钟。 (posedge clk)流过'a'。然后's1'和's2'使用它们自己的时钟作为其序列的采样边沿(时钟)。但是一旦出了's2',(posedge clk)被应用于'f'而不是's2'的(posedge clk1)。

 

                                        图8.10 多时钟属性 - 时钟分辨率-III

 图8.10显示了另一个有趣的属性。在检查表达式/序列之前,如果您需要从一个时钟转换到另一个时钟,会发生什么?那么,你不能这样做。在图8.10中,我们表明(posedge clk1)紧接着是(posedge clk0)。这并不意味着该属性将首先等待(posedge clk1),然后等待(posedge clk0),然后将(posedge clk0)应用于'a'。它将简单地用(posedge clk0)覆盖(posedge clk1),并直接应用(posedge clk0)到'a'。这显示在图的底部等效属性中。

 8.1.7 多时钟属性 - 合法和非法条件

 

                                    图8.11 多时钟属性 - 合法和非法条件

 图8.11是对多时钟属性的合法和非法语义的简单参考。

 最上面的例子表明,只要蕴含运算符不重叠,就可以在左侧表达式和右侧表达式(|=>)之间有不同的时钟。

第二个例子表明,如果蕴涵运算符两边的时钟不同并且蕴涵运算符是重叠蕴涵运算符(|->),则这将是非法的。

但是如第三个例子所示,如果重叠算子两边的时钟相同,重叠算子是完全合法的。

最后一个例子非常直观,因为=>相当于|  - > ## 1。因此,你可以在重叠运算符的每一边有不同的时钟。

猜你喜欢

转载自blog.csdn.net/zhajio/article/details/80169482