文章目前大部分参考明德扬时序约束,只是一个学习总结,侵权删
原文链接:FPGA时序约束分享04_output delay 约束
一、建立时间和保持时间是什么?
时序逻辑电路的基础是触发器FF:
建立时间:Setup Time,缩写是 Tsu,即在时钟上升沿之前数据必须稳定的最短时间
保持时间:Hold Time,缩写是 Th,即在时钟上升沿之后数据必须稳定的最短时间
亚稳态;semi-stable state,在数据的建立时间和保持时间中对信号进行采样,导致输出无法预测的状态。
建立时间和保持时间是触发器的固定属性,也就是说同一FPGA型号其所有的FF的建立时间和保持时间都是相同的。
关于FPGA对应的建立时间和保持时间可以通过手册来查询,也可以用vivado做时序分析时查询。
高级的FPGA芯片其建立时间和保持时间会比低级的FPGA芯片较小,这也是其能运行频率更高的原因。
二、时序分析分类
时序分析的目的就是检查设计中所有的 D 触发器的同步端口(数据输入端口)的变化是否满足建立时间要求 (Setup)和保持时间要求(Hold);检查 D 触发器的异步端口(异步复位端口)的变化是否满足恢复时间要求(Recovery)和移除时间要求(Removal)。
动态时序分析:将布局布线生成的布线延迟信息反标注到门级网表中进行仿真,检查是否存在时序违例。此时的仿真包括门延迟和布线延迟信息,能够较好反应芯片的实际工作情 况。因为不可能产生完备的测试向量,覆盖门级网表中的每一条路径。因此在动态时序分析 中,无法暴露一些路径上可能存在的时序问题。
静态时序分析:遍历提取出整个电路存在的所有时序路径,计算信号的传播延时,检查建立和保持时间是否满足时序要求,通过对最大路径延时和最小路径延时的分析,找出违背时序约束的错误。运行速度很快、占用内存较少,不仅可以全面的时序检查,而且还可利用时序分析的结果来优化设计,因此静态时序分析应用多。
三、时钟约束方法
主要分为四部分:时钟约束、输入延时约束、输出延时约束、时序例外。
3.1 时钟约束
时钟约束有三种情况:输入时钟、PLL等衍生时钟、自己分频的时钟。
- 输入时钟就是时钟从FPGA管脚进来的,可分为单端、差分、GT或恢复时钟。
- 单端:普通低速晶振,单端信号
生成时钟约束,名字叫SysClk(随意命名)周期为10ns(单位默认ns),在第0时刻上升,在第5时钟下降(占空比),约束对象(get_ports)是代码中的Clk信号。
如果Clk经过了内部的PLL或者MMCM(时钟管理单元),约束对象还是Clk
- 差分:高速晶振、LDVS接口
ALTER:接口信号只有一个,管脚定义有P和N
约束方法和单端一样
XILINX:顶层接口中,差分时钟有两个接口信号P和N
只对P端约束:
create_clock -name SysClk -period 10 -waveform {0 5} [get_ports Clk_p]
- GT或恢复时钟,使用了告诉的收发器,在高速收发器管脚中,是没有时钟的,时钟已经嵌入到数据里面,使用FPGA的GTX IP核接收数据,并且从数据恢复出时钟。这个恢复出来的时钟就是此种情形。最常见的就是光纤接口。
使用GTX、GTY IP核来接受数据并且提取时钟,就像图中的GT模块
这里注意约束对象的语法不同,不是通过get_ports,而是通过get_pins找到对象(ports是输入管脚端口,这里是一个模块的pins),/前面是模块,后面是pins的名字,这里的名字不能是例化后的名字了,需要找到GT模块的输出时钟名字
- 一般PLL时钟由FPGA自行推导,无需约束,但是实际中强烈建议约束
输出时钟是CLKOUT0。
一般这些在生成IP核的时候,就设置了输入输出的时钟频率,相位等信息。XILINX可以不用约束,但是ALTER需要添加命令:derive_pll_clocks(约束起的时钟名看不到 -name后面那个),这种可能导致失效
所以还是自己添加约束:
create_clcok –name clk_200 –period 5 [get_ports Clk]
create_generated_clock -name my_clk [get_pins MMCM/CLKOUT0] \
-source [get_pins MMCM/CLKIN]
-master_clock clk_200
对输入管脚Clk约束,之后create_geneated_clock对MMCM产生的CLKOUT0约束,-source表明来源于MMCM/CLKIN,即MMCM的输入管脚。通过-master_clock表明其主时钟是clk_200。
- 不建议自己分频时钟,如果用到了,要记得约束
建议利用PLL的IP核来产生分频,如果自己分频了,如下
create_clcok –name CLK1 –period 5 [get_ports CKP1]
create_generated_clock -name CLK2 [get_pins REGA/Q] \
-source [get_ports CKP1] –divide_by 2
对输入管脚CKP1的时钟约束,周期定为5,名字为CLK1。
通过create_generated_clock(生成时钟约束)产生二分频后的时钟约束,对象是REGA/Q,即D触发器的输出信号;然后要指示该时钟来自于CKP1,通过-source来指定;最后还要说明频率,通过-divide_by来说明几分频,-divide_by 2是表示二分频,即CKP1时钟的一半频率。一定要通过-divide_by来指定频率,因为工具无法从您的代码中推导出频率的。
强烈建议,分频时钟一定要约束,经验之谈,没有约束的话,时钟是不稳定的,会产生莫名其妙的问题的,这方面我们已经吃过亏的。
3.2 输入延时约束
主要包括了系统同步、源同步和有数据无时钟
FPGA接收到的数据(Din)是由上游器件产生的,理想情况下,输入数据的变化应该在时钟的上升沿对齐,但是由于器件和传输延时
每次延时都是不确定的,相位差在不断变化
所以需要把延时确定在最大和最小值之间,就是上面中间的灰色划分区域,上图就是FPGA接收的数据和时钟
输入延时(input delay)的定义:数据相对于时钟的延时,即数据时间-时钟上升沿时间。当延时在时钟右边时,输入延时是正的,当延时变化点在时钟上升沿左边时,输入延时是负的。
set_input_delay -clock <clock_name>
设置输入延时约束,<clock_name> 时钟名(之前已经约束好的,可以是真实时钟也可以是虚拟时钟),是想要设定input约束的端口名,可以是一个或数个port(数据输入端口)。
-max ,输入的最大延时,用于建立时间setup的分析
-min ,输入的最小延时,用于保持时间hold的分析
例如:
set_input_delay -clock [get_clocks clk0] -min 0.5 [get_ports Din[*]]
set_input_delay -clock [get_clocks clk0] -max 1.5[get_ports Din]*]]
上面约束了信号Din相对于时钟域clk0,有最小延时0.5和最大延时1.5ns。(clk0是之前已近约束好的名字)
综合工具发现不满足条件的时候,就会自动调整内部延时,例如增加一些BUF,或者增加线长等方式,使得信号最终到达D触发器时,能够满足建立时间和保持时间的要求。所以需要知道输入的延时才能调整。
参数来源:
这个延时时间通常在数据手册会清楚地标明输出数据和时钟的延时范围,通常是寄存器延时TCKO等,走线延时需要根据长度计算,第二种就需要用示波器测量了,如眼图模式测量
眼图模式:
眼图,是由于示波器的余晖作用,将扫描所得的每一个码元波形重叠在一起,从而形成眼图。
- 系统同步:整个电路板上FPGA以及上游器件都共用一个时钟,并且相位严格相同。板级走线也要对齐。主要是所有器件一个时钟,大部分也只是用在SDR。
时钟到各个器件的延时是一样的,这意味着设置输入延时时,不需要考虑时钟的延时,可以认为时钟延时是0,我们只需要考虑数据延时。
假设通过查阅数据手册,得到TCKO最小是1ns,最大是2ns;通过计算布线长度,得到线延时最小是0.3ns,最大是0.4ns。由此可计算得到,输入最小延时:最小的TCKO+最小的线延时,即1.3ns;输入最大延时:最大的TCKO+最大的线延时,即2.4ns。
set_input_delay -clock sysclk -min 1.3 [get_ports Din]
set_input_delay -clock sysclk -max 2.4 [get_ports Din]
利用示波器看:
这里选A为时钟的上升沿,我猜:因为要估计延时,所以时钟选已经稳定的时候,B和C是数据变化最近和最远的地方(或者因为A是数据中心,此时离边界最远,估算的最保险?时钟也不知道接进示波器没,采用中心对齐方式?应该是中心对齐方式)
- 源同步:上游器件把数据和时钟信号一起送到FPGA上:
- 2.1 SDR:SDR是指时钟是单沿有效的方式,比如只用上升延采集数据。SDR约束的参数,其获取的方法有两种:查看上游器件手册(通过查看上游器的数据手册,获取参数)以及通过示波器测量(通过示波器测量信号的相位差,获取参数)。
通过示波器观察:(还是中心对齐方式)
A是时钟上升沿处,B是眼图的左侧,定义为DV(befre),C处是眼图的右侧,定义为DV(altera)
这个最小延时应该是AC之间吧,AB应该就是负数了。
-
2.2 DDR:DDR是时钟双沿有效。也就说上升延和下降延都采集。例如说我们的DDR2、DDR3的时钟,都是上下降沿一直采数据的;包括千兆网的RGMII接口,也是通过双沿的方式。
-
中心对齐方式指时钟边沿始终在数据的中间,时钟上升沿的左右两边,数据都是稳定的。
-
边沿对齐指时钟和数据边沿对齐的,在时钟变化沿两边,其数据是不稳定的。
下面介绍的是中心对齐
上升沿:
最小延时:B到A的时间,dv_are
最大延时:C到A,半个时钟周期-dv_bfe。
下降沿:
最小延时:B到A的时间,dv_are
最大延时:C到A,根据周期性,上图中的C和D是相同的点。
假设:时钟的频率为:100M,即周期为10ns;
数据data的dv_bre:0.4ns
数据data的dv_are:0.6ns
数据data的dv_bfe:0.7ns
数据data的dv_afe:0.2ns
前两个上升沿的约束,后面的下降沿的约束,使用-clock_fall表示下降沿;使用-add_delay表示与前面的约束一起生效。
set_input_delay -clock clk -max 4.3 [get_ports data]
set_input_delay -clock clk -min 0.6 [get_ports data]
set_input_delay -clock clk -max 4.6 [get_ports data] -clock_fall -add_delay
set_input_delay -clock clk -min 0.2 [get_ports data] -clock_fall -add_delay
边沿对齐:
最小延时:B到A的时间
最大延时:C到A
输入延时的定义,是“产生的数据”到“产生该数据的时钟沿”的距离。Fall_data是由A产生的,B到C区域,都是Fall_Data的变化区域,所以应该看的是B和C到A的距离 。这个时候,B在A的左边,说明该值是负数。
时钟的频率为:100M,即周期为10ns;
数据data的skew_bre:0.6ns
数据data的skew_are:0.4ns
数据data的skew_bfe:0.3ns
数据data的skew_afe:0.7ns
set_input_delay -clock clk -max 0.4 [get_ports data]
set_input_delay -clock clk -min -0.6 [get_ports data]
set_input_delay -clock clk -max 0.7 [get_ports data] -clock_fall -add_delay
set_input_delay -clock clk -min -0.3 [get_ports data] -clock_fall -add_delay
- 有数据无时钟:例如串口这种,根据波特率匹配采集数据。这就要做好同步化和处理好亚稳态(参考之前的文章)
这里也要做时钟约束,不是为了调整延时,是为了不产生警告,防止遗漏。
一般构造一个虚拟时钟,随意频率,同时输入延时也是随意设置的
create_clock -period 20 -name clk_50_virtua
set_input_delay -max 5.2 -clock clk_50_virtual [get_ports i_data]
3.3输出延时约束
主要包括系统同步和源同步
- 系统同步:FPGA往下游器件发送数据,这时候只传送数据线就可以了。而时钟跟FPGA共用一个的,不需要传时钟。
- 源同步:同上
3.4时序例外
一般用在clock与IO都约束后,还是不满足时序要求的情况下。主要包括多周期路径、不需要检查的路径和组合电路延时等三种情况。
- 多周期路径:完成一个运算需要超过1个时钟周期的情形,多周期路径在IC设计领域运用较多,但在FPGA里应用较少。
- 常量或伪常量信号、互斥路径和异步时钟不需要分析。常量一般不会变。互斥路径简单认为是双向端口。异步时钟一般会进行同步化操作。
- 组合电路延时就是说我从这个管脚到另一个管脚之间,另一个管脚进来,这个管脚出去中间没有任何一个时钟,这是组合电路给延时的一种情况。
四、时序约束语法补充
1.从所有输入端口中去除时钟clk:
[ remove_from_collection [ all_inptus ] [ get_ports clk ] ]
2.移除多个时钟:
[remove_from_collection [all_inptus] [get_ports “clk1 clk2”]]
3.对除时钟外的所有输入端口设置约束:
set_input_delay 3.5 -clock clk -max [remove_from_collection [all_inputs] [get_ports clk]]
4.输出延时:
set_output_delay -max 5 -clock clk [get_ports B]
5.时钟不需要输入延迟约束:
remove_input_delay [get ports clk]
6.对时钟的偏移和抖动进行建模,通常只约束建立时间:
建立时间的偏移:set_clock_uncertainty -setup 0.5 [get_clocks clk]
保持时间的偏移:set_clock_uncertainty -hold 0.5 [get_clocks clk]
上升沿和下降沿的偏移:set_clock_uncertainty -rise 0.2 -fall -0.5 [get_clocks clk]
7.约束最大的转换时间(升转换时间为电压的20%上升至80%的时间,下降的转换时间为电压的80%下降至20%的时间):
set_clock_transition -max 0.2 [get_clocks clk]
8.时钟延迟建模:
对时钟源延时进行约束:set_clock_latency -source 3 [get_clocks clk]
布局布线前对network latency的约束:set_clock_latency 3 [get_clocks clk]
在布局布线后可以计算实际的network latency,使用该命令代替上述命令:set_propagated_clock 2 [get_clocks clk]文章来源:https://www.toymoban.com/news/detail-778612.html
参考链接:DC(三)——时钟约束文章来源地址https://www.toymoban.com/news/detail-778612.html
到了这里,关于FPGA时序约束(一)基本概念入门及简单语法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!