set_multicycle_path
多周期路径
利用这一约束可以修改STA时序分析的建立和保持关系。
单周期路径
默认情况下Vivado执行单周期的检查。
- setup 一个周期
- hold零个周期
如下图所示:

建立
- 建立关系是发送沿和捕获沿的关系。
- 建立要求 = 捕获沿 - 发送沿
STA实际会找到所有的建立要求,在图中仅画出最严苛的情况,因为STA时序只计算最严苛的情况,也就是建立要求的最小值,我们知道正常情况下,setup是正数才对,而正得越多建立的松弛(建立后的余量,越容易达到建立条件)越多,对应数值越大,所以这里要选择小的,即建立松弛小的。
保持
这里有两个保持要求:
- hold1
- 保持关系的发送沿==(默认就是上图的发送沿)发的数据不能被到达沿(默认是上图捕获沿的前一个周期)==捕获。
- 保持要求 = 到达沿 - 保持关系发送沿。
- 保持关系是到达沿与保持关系发送沿的关系。
- 因为保持关系发送沿可以根据约束移动,所以不一定保持关系发送沿的下一个周期就是源时钟的下一个发送沿。
- hold2
- 保持关系的发送沿的下一个发送沿==(默认就是发送沿的下一个周期即上图的下一个发送沿)==发送的数据不能被捕获沿捕获。
- 保持要求 = 捕获沿 - 保持关系的发送沿的下一个发送沿。
- 保持关系是到达沿下一个周期==(默认是捕获沿)与保持关系的发送沿的下一个发送沿(默认就是发送沿的下一个周期即上图的下一个发送沿)==关系。
- 因为到达沿可以根据约束移动,所以不一定到达沿下一个周期就是目的时钟捕获沿。
STA时序只计算最严苛的情况,也就是两个保持要求的最大值,我们知道正常情况下,hold1和hold2都是负数才对,因此而负得越多保持的松弛(保持后的余量,越容易达到保持条件)越多,而对应数值越小,所以这里要选择大的,即保持松弛小的。实际上第二个保持关系与第一个保持关系是同一个意思,发送沿当作下个发送沿,则到达沿就是捕获沿。每个建立条件都有两个保持关系,而建立条件的最严苛不一定对应于保持关系的最严苛,STA是单独计算的。换句话就是STA会找一个公共周期(在0位置对齐的相位开始,还有相同的对齐相位)内的所有建立关系,并选择最小的为关注点,每一个建立关系都有两个保持关系,STA会选择最大的为关注点,最大关注点保持关系不一定对应于最小关注点的建立关系。
建立保持检查
默认的STA将执行以下的建立与保持关系检查。
-
建立检查
- TDatapath(max) < TCLK(t=Period) - TSetup
-
保持检查
- TDatapath(min) > TCLK(t=0) + THold
对于其他情况下,可能需要多个周期或者为了让终端接收到稳定的数据,需要多个时钟周期才能将数据稳定。
用法
set_multicycle_path <path_multiplier> [-setup|-hold] [-start|-end] [-from <startpoints>] [-to <endpoints>] [-through <pins|cells|nets>]
保持关系在大多数情况下跟着建立关系走,且有下面的公式,默认情况下 setup path multiplier = 1,hold path multiplier = 0
h
o
l
d
_
c
y
c
l
e
s
=
<
s
e
t
u
p
p
a
t
h
m
u
l
t
i
p
l
i
e
r
>
−
1
−
<
h
o
l
d
p
a
t
h
m
u
l
t
i
p
l
i
e
r
>
=
1
−
1
−
0
=
0
\begin{aligned} hold\_cycles &= <setup path multiplier> - 1 - <hold path multiplier>\\ &= 1 - 1 -0\\ &= 0 \end{aligned}
hold_cycles=<setuppathmultiplier>−1−<holdpathmultiplier>=1−1−0=0
因此 setup 1 周期,hold 0 周期。
<path_multiplier>
设置检查的周期的个数
[-setup|-hold]
修改建立或者保持关系
[-start|-end]
setup
建立关系默认是与目的时钟相关联的,在设置<path_multiplier>建立检查将会移动目的时钟的捕获沿。
set_multicycle_path <path_multiplier> -setup -end 等价于 set_multicycle_path <path_multiplier> -setup
想让建立关系与源时钟相关联的,则加上[-start]建立检查将会移动源时钟的发送沿。
set_multicycle_path <path_multiplier> -setup -start
hold
保持关系默认是与源时钟相关联的,在设置<path_multiplier>保持检查将会移动源时钟的发送沿。
set_multicycle_path <path_multiplier> -hold -start 等价于 set_multicycle_path <path_multiplier> -hold
想让保持关系与目的时钟相关联的,则加上[-end]保持检查移动目的时钟的到达沿(捕获沿的前一个周期)。
set_multicycle_path <path_multiplier> -hold -end
很绕口,随后有例子详细解释。
[-from <startpoints>] [-to <endpoints>]
设置一个合适的路径起点和终点
[-through <pins|cells|nets>]
或者所有通过这个节点(引脚/单元/网络)的所有路径
例子
单周期的多周期路径
模型如下:

如下图,由于使能时钟的作用,两个时钟周期data1_reg才寄存data0_reg的数据。

默认建立保持关系

建立关系修改
使用约束改变建立周期为2。
set_multicycle_path 2 -setup -from [get_pins data0_reg/C] -to [get_pins data1_reg/D]
增加建立周期约束是2后的建立保持关系:

在未修改保持关系的时候,保持关系是跟着建立关系走,(目的时钟捕获沿前一个周期是到达沿)
h
o
l
d
_
c
y
c
l
e
s
=
<
s
e
t
u
p
p
a
t
h
m
u
l
t
i
p
l
i
e
r
>
−
1
−
<
h
o
l
d
p
a
t
h
m
u
l
t
i
p
l
i
e
r
>
=
2
−
1
−
0
=
1
\begin{aligned} hold\_cycles &= <setup path multiplier> - 1 - <hold path multiplier>\\ &= 2 - 1 -0\\ &= 1 \end{aligned}
hold_cycles=<setuppathmultiplier>−1−<holdpathmultiplier>=2−1−0=1
保持关系修改
为了满足保持关系的要求,那么发送沿发的数据必须延迟一个周期以上才能保证发送沿不被到达沿捕获。而实际上这里有时钟使能信号,不需要担心这个问题,因此可以修改保持关系,以免多余的逻辑用来延时。
set_multicycle_path 1 -hold -end -from [get_pins data0_reg/C] \ -to [get_pins data1_reg/D]
这样将会移动目的时钟的到达沿向左一个周期。最终的STA时序将会按照如下进行建立和保持检查。
- -hold -end

保持关系发送沿未移动,因此发送沿就是保持关系发送沿。
-
hold1:保持关系发送沿与到达沿的关系。
-
hold2:保持关系发送沿下一个发送沿与到达沿的下一个周期关系。
保持关系与上文所说的一致
- -hold -start,未加[-end]将会使得保持关系发送沿向右移动1个周期。也是-hlod默认的选项。

到达沿未移动,因此到达沿的下一个周期就是捕获沿。
-
hold1:保持关系发送沿与到达沿的关系。
-
hold2:保持关系发送沿下一个发送沿与到达沿的下一个周期关系。
对于目的和源时钟一致的情况下,-start]与[-end]效果是一致的,因为它们的保持检查的相对关系是一致的。
这里其实很绕口,但是只要记住保持关系是保持关系发送沿,保持关系发送沿下一个发送沿、到达沿、到达沿下一个周期的关系,建立关系是发送沿与捕获沿的关系
多周期慢时钟域到快时钟域
模型如下:

- CLK2是CLK1时钟频率的2倍。
- 在时钟使能的情况下,使得采样能够正确,需要正确约束。
默认建立保持关系
默认建立保持检查情况如下:

- hold1:
- 0 - 0 = 0ns
- hold2:
- 4 - 8 = -4ns
前面说了这里只考虑最严苛的情况下,这里只需要考虑hold1。
建立关系修改
假设在时钟使能的情况下,为了正确约束:
set_multicycle_path 4 -setup -from [get_clocks CLK1] -to [get_clocks CLK2]
这相当于移动捕获沿4个周期,此时的建立保持检查如下:

- hold1:
- 12 - 0 = 12 ns
- hold2:
- 16 - 8 = 8 ns
这里的保持要求时间为12ns,但由于时钟的使能存在,因此不需要为了满足保持关系,额外增加逻辑来满足延时,我们选择移动目的时钟的到达沿。
保持关系修改
set_multicycle_path 3 -hold -end -from [get_clocks CLK1] -to [get_clocks CLK2]

- hold1:
- 0 - 0 = 0 ns
- hold2:
- 4 - 8 = -4 ns
STA只选择最严苛的,因此这里的保持要求时间为0ns,符合正确情况。
多周期快时钟域到慢时钟域
模型如下:

- CLK1是CLK2时钟的频率2倍。
- 在时钟使能的情况下,使得采样能够正确,需要正确约束。
默认建立保持关系
默认建立保持检查情况如下:

建立检查
- setup1:
- 8 - 0 = 8
- setup2:
- 8 - 4 = 4
STA建立检查要求4ns。即step2。
保持检查
setup1对应的保持关系
- 1hold1:
- 0 - 0 = 0ns
- 1hold2:
- 8 - 4 = 4ns
setup2对应的保持关系
- 2hold1:
- 0 - 4 = -4ns
- 2hold2:
- 8 - 8 = 0ns
STA建立检查要求4ns。即1hold2。最终如下图:

建立关系修改
这并不符合我们的要求,因此我们希望建立要求的路径是step1,因此要求对建立检查在目的时钟向左移动发送沿。需要加[-start],确保向左移动发送沿。
set_multicycle_path 2 -setup -start -from [get_clocks CLK1] -to [get_clocks CLK2]

建立检查
- setup:
- 8 - 0 = 8
STA建立检查要求8ns。
保持检查
setup对应的保持关系
- hold1:
- 0 - 0 = 0ns
- hold2:
- 8 - 4 = 4ns
STA保持检查要求4ns。
同样由于时钟使能的情况下,没有必要因为要满足hold2的保持要求,将数据延迟,增加额外延时逻辑,这里我们继续修改保持检查
保持关系修改
保持关系默认是相对源时钟的,因此默认移动发送沿,将保持关系发送沿向右移动一个周期。
set_multicycle_path 1 -hold -start -from [get_clocks CLK1] -to [get_clocks CLK2]
set_multicycle_path 1 -hold -from [get_clocks CLK1] -to [get_clocks CLK2]
这两个约束是一样的

保持检查
此时的保持关系如下
- hold1:
- 0 - 4 = -4 ns
- hold2:
- 0 - 0= 0ns
STA保持检查要求0ns。因此不需要额外的延时了。
总结
-
保持关系总是默认跟随着建立关系走,因此仅仅修改建立关系,保持关系也跟着变。
-
在某些情况下,需要释放保持关系的要求,需要额外对保持关系修改。
-
注意保持关系发送沿、保持关系下一个发送沿、到达沿、捕获沿、发送沿、下一个发送沿。未修改保持关系,保持关系发送沿 = 发送沿 保持关系下一个发送沿 = 下一个发送沿
-
捕获沿是通过以STA找到的建立关系确定,到达沿是捕获沿的前一个周期。
关系表
-start -end -setup -hold 关系如下
| - start(源时钟)发送沿移动 | -stop(目的时钟)捕获沿移动 | |
|---|---|---|
| -setup | (<—)(向左移动) | (–>)(向右移动)(默认移动方向) |
| -hold | (—>)(向右移动)(默认移动方向) | (<—)(向左移动 |
。
关系表
-start -end -setup -hold 关系如下
| - start(源时钟)发送沿移动 | -stop(目的时钟)捕获沿移动 | |
|---|---|---|
| -setup | (<—)(向左移动) | (–>)(向右移动)(默认移动方向) |
| -hold | (—>)(向右移动)(默认移动方向) | (<—)(向左移动 |