Verdvana

空持千百偈 不如吃茶去

时序约束之时钟组

24 Sep 2019 » FPGA, Digital IC Design

1 前言

        当设计中包含多个时钟时,时序不仅仅依赖于时钟频率,同样依赖于彼此之间的关联关系。

同步时钟是一种共享确定相位关系的时钟,同步时钟往往是同源的。
异步时钟不共享固定的相位关系

        如下图,如果C1和C2由不同的源生成,则它们是异步的:

1

        设计中每一部分都由每一个时钟形成的时钟域驱动。这些由异步时钟驱动时钟域连接的信号叫做跨越异步时钟域(CDC)。


2 建立和保持时序检查

        上图的电路里,启动触发器(F1)负责启动数据,捕获触发器(F2)负责捕获数据。这里需要确保F1有效沿上的数据可以被后续的F2的有效沿捕获,下图为时钟波形:

2

        假设tF为从市政到F1 Q引脚的延迟,tC为晕妆组合单元的延迟。这说明数据到达F2的时间为tF+tC。在假设时钟C1+C2的边沿完全是对齐的,并且F2的建立要求时间为tSetup。考虑下个时钟沿到达F2的时间,即tPeriod(时钟C2的周期),则从F1处被F2捕获的数据,在下一个F2的有效沿到达之前已到达的时间至少为tSetup。这种建立时序的检查对信号到达F2的时序要求给出了一个上限,其表示为:

tF + tC < tPeriod - tSteup

        满足建立要求后,为了能够正确地捕获数据还需要满足保持要求,这种情况可利用保持时序检查进行检测,它可确保保持时序同时满足启动时钟和捕获时钟的有效沿。对于同一个设计,tF+tC是数据到达触发器F2的时间,数据到达的时间必须大于F2的保持时间,所以当前的数据并不会干扰前一个数据。因此保持时序检查降低了时序上对信号到达F2的硬性要求,其表示为:

tF + tC > tHold

        以上是假设时钟C1和C2的时钟沿是完全对齐的。如果不对齐(仍是同源),就会稍微复杂一些。如果tL是时钟从源到F1的时间,tZ是时钟从源F2的时间,则建立和保持时序检查为:

tL + tF + tC < tZ + tPeriod - tSetup tL + tF + tC > tZ + tHold

        另外,如果两个交互时钟的频率不同,则根据各自的频率值得知,F1的有效沿和F2的有效沿在每个时钟周期都不同。

2.1 高速至低速时钟

        高速至低速的意思是,F1的周期小于F2的周期,进一步假设C1的周期为10ns,占空比为50%,C2的周期为15ns,占空比为50%,则时钟可以表示为:

create_clock    -period 10 -name C1 -waveform {0 5} [get_pins F1/CK]
create_clock    -period 15 -name C2 -waveform {0 7.5} [get_pins F2/CK]

        波形为下图:

3

        显然波形在30ns后会自动重复。因此任何分析必须只能在30ns内完成。对于建立时序检查,启动/捕获在窗口内重复出现在:

  • 0ns启动和15ns捕获;
  • 10ns启动和15ns捕获;
  • 20ns启动和30ns捕获。

        其中,第二条是约束性最强的,用于建立约束。在窗口内计算所有保持检查,会发现对于保持时序最坏的组合情况是启动沿和捕获沿都位于0ns处。所以两个沿都处于0时用于保持检查,这将确保在时间为0时位于F1的数据不会被F2寄存。

2.2 低速至高速时钟

        如果C1和C2的周期相反,再次考虑所有30ns以内的时钟边沿对组合,并应用约束性最强的一对。建立时序检查应当在15ns启动沿和20ns捕获沿之间完成。同样,约束性最强的保持检查仍应在两个时钟沿的时间为0处进行。下图为波形:

4

2.3 多个时钟于不同周期内同步

        如下图:

5

        时钟在几个周期后需要重新对齐。使C1的周期为6ns,C2的周期为10ns。假设时钟沿在t=0时对齐,则下一次边沿对齐在t=30,即两个时钟周期的最小公倍数。

        通过波形可以看出某些沿可以执行建立和保持检查。约束性最强的建立检查是18ns的启动沿和20ns的捕获沿。而约束性最强的保持检查是两个沿都处于0ns。

2.4 异步时钟

        异步时钟之间并不共享相位关系,那么启动时钟和捕获时钟彼此之间没有固定的联系。这意味着建立和保持时序要求在每个周期内都可能不同。这在分析异步时钟时是一个很严重的时序问题。若用此类交互时钟驱动数据路径上的信号,则会造成跨越异步时钟域,这有可能导致亚稳态的问题,需要用同步器来解决。

        跨越异步时钟域的问题为:因为每对时钟沿的时序要求不同,所以,某些时候可能会存在漏洞。尽管检查的约束性可用于大多数时钟沿,但总有一些是违规的。

        为了避免实现工具满足这类路径的时序要求进而造成不必要的时间开销,通常建议单独设定这种跨时钟域操作,可以利用“get_clock_groups”来实现。


3 逻辑和物理独立时钟

        某些情况下时钟并不交互,这取决于设计架构。

        下图中,尽管两个时钟在设计中共存,但除了它们的源以外彼此之间并不交互,这些时钟认为是逻辑独立的:

6

        下图中的时钟C1和C2是逻辑独立的。两个生成时钟GC1和GC2也是独立的,但他们并不共存于同一个网络下,因此GC1和GC2认为是物理独立的。

7


4 串扰

        尽管始终相互独立并不交互,但信号之间的干扰可能导致不利影响。比如较高的布线密度、设备之间或信号之间耦合电容的相互影响。这种现象称为串扰。

        由于串扰影响时序,所以对其建立和保持时序时序检查也有直接的影响。受扰信号因串扰而压摆率变低,如下图所示:

8

        如果干扰源网络的转换方向与受扰网络相反,那么受扰网络的斜率会变低,从而增加了延迟,这会影响建立时序。同样如果干扰源网络的转换方向与受扰网络相同时,相邻受扰网络的斜率变高,从而减少了延迟,这会影响保持时序。

        从信号完整性的角度来说,如果互斥时钟直接没有串扰问题,那么可以认为它们之间是物理独立的。

        大多数STA工具在设计框架内提供测量信号完整性的方法。


5 set_clock_groups

        根据之前说的,正确的建立和保持要求可以确保捕获可靠数据的时序,然而对于异步时钟来说是很麻烦的,因为无法满足不确定的时钟相位关系的要求。对于互斥时钟试图满足这些要求毫无意义,因为时钟并不交互。为了让时序工具能忽略任何异步时钟或互斥时钟之间的时序路径或串扰分析,SDC提供了“set_clock_groups”命令,该命令的BNF为:

set_clock_groups    [-name group_name]
                    [-group clock_list]
                    [-logically_exclusive]
                    [-physically_exclusive]
                    [-asynchronous]
                    [-allow_paths]
                    [-comments comment_string]

        “-name”选项用于提供时钟组唯一的名称。

        “-group”选项可将时钟分入各组。

        “-logically_exclusive”选项可以用于互斥但具有耦合关系的时钟。如前面逻辑独立的两个时钟的分组可以表示为:

create_clock            -period 10 -name C1 -waveform {0 5} [get_ports C1]
create_clock            -period 20 -name C2 -waveform {0 12} [get_ports C2]
set_clock_groups        -logically_exclusive -group C1 -group C2

        而前面的物理独立的两个时钟在另一部分(F3和F4中)产生了交互,修改为:

create_clock            -period 10 -name C1 -waveform {0 5} [get_ports C1]
create_clock            -period 20 -name C2 -waveform {0 12} [get_ports C2]
create_generated_clock  -name GC1 -source [get_ports C1] [get_pins mux1/A] -combinational
create_generated_clock  -name GC2 -source [get_ports C2] [get_pins mux1/B] -combinational
set_clock_groups        -logically_exclusive -group CG1 -group CG2

        时钟并不共存时可以使用“-physically_exclusive”选项。前面物理独立的两个时钟的分组可表示为:

create_clock            -period 10 -name C1 -waveform {0 5} [get_ports C1]
create_clock            -period 20 -name C2 -waveform {0 12} [get_ports C2]
create_generated_clock  -name GC1 -divide_by 1 -source [get_pins mux1/A] [get_pins mux1/Z] -combinational
create_generated_clock  -name GC2 -divide_by 1 -source [get_pins mux1/B] [get_pins mux1/Z] -combinational -add
set_clock_groups        -physically_exclusive -group CG1 -group CG2

        可以看出,F1和F2之间的时序无需考虑C1是否驱动F1和C2是否驱动F2(反之亦然),但C1和C2同样可以驱动触发器F3和F4,所以我们还不能简单的应用:

set_clock_groups    -logically_exclusive -group C1 -group C2

        这个命令会禁用C1和C2与F3和F4之间的时序电路路径。通过在多路复用器的输出处定义一个组合生成时钟,时序工具会禁用触发器F1和F2之间相关时钟的本地时序电路路径分析,而不影响触发器F3和F4。

        如果在同一个对象上定义了多个时钟(利用“-add”选项),那么它们应当是物理独立的。另一种情况是当系统时钟和测试时钟位于同一端口时,这两类时钟也是物理独立的。

        时钟彼此不共享相位关系时可用“-asynchronous”选项。跨越异步域也需要同步器,这仅仅是为了功能的可靠。

        “-logically_exclusive”、“-physically_exclusive”和“-asynchronous”是互斥的。在“set_clock_groups”命令中只能使用其中一个选项。但是可以通过各种不同的命令设定时钟之间的关系。

        这三个选项表面时钟组之间的时序电路路径是不必考虑的。然而,对于串扰分析,它们的意义就不一样了。如果时钟组设置为“-logically_exclusive”,则时钟组之间的串扰分析就像两个同步时钟一样。如果时钟组设置为“-physically_exclusive”,则无法完成串扰分析。如果时钟组设置为“-asynchronous”,则假设干扰源和受扰者同在一个无限时序窗口中。

        当时钟组定义为异步,并且用户希望执行串扰分析而不禁用时钟之间的时序电路路径时,可以利用“”选项实现。这个选项仅可与“”选项一起使用。这个选项通常用于信号完整性检查而不是静态时序分析。

        可以在一个“set_clock_groups”命令中设定多个组,这个时钟组列表意味着一族始终要与其他组的时钟保持逻辑独立、物理独立或异步关系。重要的是,这个指令仅用于设定不同时钟组之间的关系,与同组内的时钟关系无关。例如:

set_clock_groups    -asynchronous -group [get_clocks {clk1 clk2 clk3}] -group [get_clocks {clk4 clk5 clk6}]

        这个指令表示:

  • clk1异步于clk4、clk5和clk6;
  • clk2异步于clk4、clk5和clk6;
  • clk3异步于clk4、clk5和clk6;
  • clk1、clk2和clk3之间没有假设关系;
  • clk4、clk5和clk6之间没有假设关系。

6 时钟组相关的注意事项

        在设定时钟组时,应注意以下几点:

  • 尽管可能定义了一个时钟组,但并不意味着它们是同步的,组内时钟之间的关系可另外定义(利用set_clock_group指令或工具默认的设置);
  • 使用错误的选项(-physically_exclusive、、)定义时钟组可能不会影响时序,因为所有受影响的时序电路路径都被忽略了,但这会影响信号完整性分析。
  • 即便定义了主时钟和其它时钟之间的时钟组关系,这种关系也不会被主时钟派生出的生成时钟所继承,所有的关系都应当明确的设定;
  • 时钟分组最好的办法是:
    • 如果设计中共存多个时钟,却没有相位关系,则应在“set_clock_group”中设定“-asynchronous”;
    • 如果设计中共存多个时钟,并且电路仅选择其中一个,则应在“set_clock_group”中设定“-logically_exclusive”;
    • 如果设计中不能共存多个时钟,则应在“set_clock_group”中设定“-physically_exclusive”。

        告辞。