您现在的位置是:首页 >技术交流 >FPGA时序约束(四)主时钟、虚拟时钟和时钟特性的约束网站首页技术交流
FPGA时序约束(四)主时钟、虚拟时钟和时钟特性的约束
系列文章目录
FPGA时序约束(二)利用Quartus18对Altera进行时序约束
文章目录
前言
在读《FPGA时序约束与分析》吴厚航时记录的读书笔记,继续总结记录一些知识点,深入一点点。(很详细的一本时序约束的书,非常推荐)
主时钟约束
在《FPGA时序约束(二)利用Quartus18对Altera进行时序约束》中简单的介绍了几种约束,其中提到了主时钟约束
create_clock -name xxxx -period a -waveform {b c} [get_ports {xxx}]
定义名为xxxx的时钟,周期为a ns,上升沿b ns,下降沿c ns,来自端口xxx(FPGA引脚)
有几个注意的地方:
- 当输入时钟是一对差分信号,只需要约束正端(P端)那个输入引脚就行,负端会自动识别
- 如果b的值不为0,相当进行了相移(但是没搞懂一个输入时钟怎么能相移的,又不是衍生时钟,可能意思是时序约束能对该时钟进行相移)
- 如果是get_nets进行定义,取的是FPGA的内部网络作为时钟的物理节点
- -waveform {b c}可以不加,默认是0和50%的占空比
多频率约束:(对同一个输入管脚有多个频率的时钟进行约束)
create_clock -name xxxx1 -period a -waveform {b c} [get_ports {xxx}]
create_clock -name xxxx2 -period d -waveform {e f} [get_ports {xxx}] -add
对硬件原语约束(xilinx)(对Altera也是可以的)
对于一些硬件原语的输出时钟引脚,可以将这个硬件原语的输出引脚作为时钟源进行主时钟约束,如instA/OUT。
若此时还是指定BUFG0、BUFG1原语的输出端作为主时钟约束的根节点,就可能由于两条线的时钟偏斜差异而导致时序分析结果的误差。在这种情况下,只需要直接对源时钟 sysclk进行主时钟约束,就能覆盖该时钟所驱动的所有时序路径。(在Altera的quartus里面找了半天没找到,不知道能不能约束buffer后面的节点)
跨时钟域的时序分析
出现上图这样驱动时钟不同的情况:
时序分析工具会竭尽所能地寻找发射沿之后最近的一个锁存沿,以此作为最坏情况的建立时间关系。寻找与发射沿对齐或者在发射沿之前最近的一个锁存沿,以此作为最坏情况的保持时间关系。
会寻找建立时间关系的最坏情况,就是寻找发射沿之后最近的锁存沿(最小的正向时间)。保持时间关系的最坏情况,就是寻找发射沿之前(包括与发射沿对齐)最近的一个锁存沿(最小的负向时间)。
有下图几种情况:
虚拟时钟约束
一些引脚上的数据信号,其同步时钟只存在于外部芯片,并不存在于FPGA器件内。这种情况下必须定义一个时钟用于描述数据引脚,就称为虚拟时钟。定义时无须依附于任何设计中的实际物理节点。
虚拟时钟同样是以create_clock 命令进行约束定义的,但无须指定目标端口或网络。
虚拟时钟通常被用于以下一些情况中的输人或输出延时约束:
- 时序分析(一般是I/O引脚相关的时序路径)的参考时钟并不是FPGA内部的某个设计时钟(主时钟)。
- 与FPGA器件的I/О路径相关的内部驱动时钟与其板级驱动时钟并不是完全同步的。
- 设计者希望对I/O的驱动时钟指定一些特殊的抖动和延时值,但又不希望影响此时钟在FPGA内部的时钟传输特性。
虚拟时钟仅用作参考,以指定相对于该时钟的输入延迟和输出延迟。
例如,时钟周期为10ns,并且不依附于任何目标网络的时钟信号clk_virt,其约束定义时的目标网络属性就无须指定。其名称定义就是clk_virt,约束脚本如下。
create_clock - name clk_virt - period 10
虚拟时钟也必须在其被输入或输出延时约束引用前做好定义。
我现在不太懂,后来网上查了查,后面可能会根据这个clk_virt 来设置set_input_delay这些:
如:
set_input_delay 6 -clock clk_virt [get_ports dina]
系统同步:pin2reg
对于源寄存器reg1的时钟不会传入到FPGA,这个时候就要根据实际情况对VCLK进行虚拟时钟约束,以便时序分析。
create_clock - period 10.000 -name VIR_CLK -waveform {0.000 5.000}
create_clock - period 10.000 -name SYS_CLK -waveform {0.000 5.000} [ get_ports clk]
create_clock - period 10.000 -name VIR_CLK -waveform {2.000 7.000}
create_clock - period 10.000 -name SYS_CLK -waveform {0.000 5.000} [ get_ports clk]
系统同步:reg2pin
源寄存器reg1的驱动时钟是实际存在的,设计者可以对其进行主时钟约束,而目的寄存器的主时钟reg2并不会传输到FPGA器件,此时设计者就可以对其进行虚拟时钟约束,以便于时序分析。
create_clock - period 10.000 -name VIR_CLK -waveform {0.000 5.000}
create_clock - period 10.000 -name SYS_CLK -waveform {0.000 5.000} [ get_ports clk]
create_clock - period 10.000 -name VIR_CLK -waveform {2.000 7.000}
create_clock - period 10.000 -name SYS_CLK -waveform {0.000 5.000} [ get_ports clk]
时钟特性约束
在真实世界中,当时钟在FPGA器件内部传输时,会经过各种时钟缓冲器、时钟管理单元以及固有的时钟走线路径,加上各种不可避免的硬件噪声,都会引起时钟沿的延时和波形变化,称其为时钟的传输时延和时钟不确定性。
在FPGA中,时钟的偏差特性,主要通过时钟抖动(Clock Jitter)和时钟不确定性(Clock Uncertainty)进行约束。
时钟抖动(一些只适用于xilinx)
对于时钟抖动,一般推荐使用Vivado时序工具默认产生的时钟抖动值。
set_input_jitter:
-
更改某个时钟信号的默认时钟抖动值,指定这个时钟的峰峰(peak-to-peak)抖动值。
-
命令只能约束主时钟的抖动值,不能用于约束衍生时钟的抖动值。除了MMCM或PLL外,主时钟所设定的时钟抖动值将会传递给它的衍生时钟。(前面提到xilinx会自动时序约束这些ip核)
-
每条set_input_jitter命令只能约束一个主时钟。
set _system _jitter:
- 若系统电源存在较大噪声,如FPGA器件核压VCCINT由于大量节点的同时开关,串扰、温度突变等因素导致全局的时钟抖动,使用set_system_jitter命令对系统抖动(System Jitter)进行定义。
- Vivado时序工具自动使用set _system _jitter命令约束了0.050ns的默认系统抖动值。通常不建议用set_system_jitter命令去设定一个新的系统抖动值。
使用set_input_jitter命令和set_system_jitter命令约束的系统抖动,在Vivado 工具中进行时序分析时,都会作为时钟不确定性的一部分进行计算。
时钟的系统抖动值和输入抖动值通常都是符合高斯分布的一些随机值,因此以其均方值作为最坏情况进行计算:
Tsj=sqrt(SourceClockSystemJitter ^ 2+DestinationClockSystemJitter^2)
例如,使用默认的0.050ns的系统抖动值:Tsj=sqrt(0.050^ 2+0.050^2)=0.071ns=71ps
set_input_jitter
set_input_jitter [get_clocks <clock_name >]<jitter_in_ns>
get_clocks用于指定需要约束抖动值的主时钟名<clock_name>,这个主时钟必须是事先约束定义好的。
<jitter_in_ns>指定抖动值,取值必须大于或等于0,单位为ns。
例子:
set_input_jitter clk1 0.3
set_input_jitter clk2 0.3
set_system_jitter
set_system_jitter <jitter_in_ns >
<jitter_in_ns >指定所有时钟的系统抖动值,取值必须大于或等于0,单位为 ns。
例子;
create_clock -period 10 -name sysclk [get_ports clk]
set_system_jitter sysclk 0.1
时钟不确定性
除时钟抖动以外的所有可能影响时钟周期性偏差的因素,都可以使用set_clock_uncertainty命令进行约束。
set_clock_uncertainty -setup -from [get_clocks <clock0_name>] -to [get_clocks <clock1_name >]<uncertainty_value >
- -setup表示定义建立时间检查的时钟不确定性时间,也可以使用-hold表示保持时间的时钟不确定性,如果不指定-setup和-hold,则表示同时建立时间和保持时间的不确定性时间。
- -from指定源时钟,-to指定目标时钟,对于非跨时钟域的路径,一般不需要指定-from和-to。
- get_clocks用于指定实际的时钟物理节点名称<clock0_name>或<clockl_name >。
- <uncertainty_value >指定时钟不确定时间,单位为ns。
set_system_jitter和 set_input_jitter命令约束的抖动值都会计算到时钟不确定时间。
set_clock_uncertainty命令约束的时钟不确定性值不会影响set_system_jitter和 set_input_jitter命令约束的抖动值,而是额外增加约束值计算到时钟不确定时间。称set_clock_uncertainty命令约束的时钟不确定性值为用户不确定性(User Uncertainty,UU)时间。
是在计算建立时间余量或保持时间余量时,时钟不确定时间必须作为需要预留出来的一部分余量予以扣除。(最终公式中作为减数)
当希望时钟的时序路径增加时序余量时,也可以使用set_clock_uncertainty命令进行约束定义。相比提高时钟频率增加余量,这种约束方法不更改原有时钟的边沿变化特性和时钟相关性,是更安全稳妥的增加时序余量的约束设计方法。
如下图,vivado中的时序报告(什么都抖动和不确定性都没约束时)
例子:
- 给主时钟clk增加500ps(0.5ns)的余量
set_clock_uncertainty -from clk -to clk0 0.500
- 源时钟和目标时钟是两个不同的主时钟,且数据的传输是双向的,这个时候对主时钟clko和 clk1分别设定0.25ns的不确定性时间。
set_clock_uncertainty -from clk0 -to clk1 0.250 -setup
set_clock_uncertainty -from clk1 -to clk0 0.250 -setup
set _clock_latency/时钟偏斜
set_clock_latency [-clock<args>] [-rise] [-fall] [-min] [-max] [-source] <latency><objects >
- [-clock]后指定约束时钟(由指定)所相对的时钟名称。若不定义时钟,则时钟延时值将会应用于所有目标时钟所驱动的时序路径。
- [-rise][-fall]指定时钟延时的边沿。
- [-min][-max]指定时钟延时的最大值或最小值。只能指定其一,若不指定则延时值同时作为最大值和最小值。
- [-source]指定时钟延时的基本类型,[-source]即源延时,[-network]即网络延时。默认为[-network]类型。[-source]用于定义时序分析时实际使用的时钟相对于它的理想时钟波形的延时,例如外部晶振源经过PCB板级延时到达FPGA引脚的路径延时。[-network]用于定义时钟信号从设计中的某个指定节点传输到寄存器的时钟输入端口的延时。时钟到达寄存器输人端口的总延时包括了时钟源延时和时钟网络延时。
- < latency >指定时钟延时值,单位为ns。
- < objects >指定约束时钟的名称。
对于已经做过主时钟约束的时钟,时序分析时通常都会自动计算其时钟延时值并给出详细报告,设计者不需要额外约束这些内部时钟的延时。如下图:
对于FPGA外部输入的同步时钟信号,有时需要增加一些时钟延时约束以指定这些时钟在FPGA器件之外的一些时钟延时特性。在上一篇系列文章介绍的引脚到寄存器接口时序约束中,并未专门set _clock_latency,但也利用set_input_delay约束(是一样的),如下图:
例如:指定时钟CLK_A 的上升沿的时钟源延时为0.4ns。
set_clock_latency -source -rise 0.4 [get_ports CLK_A]
例如:vivado中,右击可以看到计算公式
分别是源时钟延时(Source Clock Delay,SCD)
目标时钟延时(Destination Clock Delay,DCD)
时钟悲观:这里时钟共同路径延时,Clock Pessimisim Removal(CPR)
DCD-SDC+CPR计算得到时钟偏斜值。