FPGA设计之时序约束

第一章 fpga时序约束分享02_时钟约束 作者:潘文明
上一篇《fpga时序约束分享01_约束四大步骤》一文中,介绍了时序约束的四大步骤。
上图是四大步骤,并且每个步骤都分别展开了各种情况,后续可以参考对照,分别添加时序约束。本文讲述上图中的第1点:时钟约束。
   时钟约束分三种情况:输入时钟、pll等衍生时钟以及自己分频的时钟。而其中输入时钟又可再分三种,第一种是输入管脚是clk的,第二种是差分时钟,最后一种是gt或 恢复的一个时钟。下面分别展开描述。
第1节 输入时钟
输入时钟根据管脚情况,有三种三种,第一种是输入管脚是clk的,第二种是差分时钟,最后一种是gt或 恢复的一个时钟。
1.1 输入管脚clk     时钟直接从管脚输入,如上图所示。这种是最常见的一个情况,包括明德扬的mp603、mp801学习板,其时钟都是由外部的晶振产生,然后直接输入管脚进来的,这种情况的生成时钟约束是最简单的,其格式如下:
   create_clock -name sysclk -period 10 -waveform {0 5} [get_ports clk]
   create_clock是生成约束约束命令。
   name后面表示给这个时钟命名,这里命名为sysclk,您可以命为其他您所想要的名字,即使跟代码中的时钟名不同,都是可以的。
   period后面表示约定该时钟的周期,默认单位为纳秒。
   waveform后面表示该时钟在一个周期内的上升沿和下降沿时间点。{0 5}表示时钟在第0时刻上升,在第5时钟下降。通过这个,设置了时钟的占空比。
   get_ports这里指定了约束的对象,即对应代码中的哪个信号,get_ports clk,表示这个时钟就是代码或上图中的clk。
  这个时钟约束是最常用的,只要参照这种格式生成晚就可以了。
假设说该时钟输入后经过了一个内部的pll或者mmcm(时钟管理单元)后,再作为工作时钟,此种情况下,仍然是要对clk约束,其约束方法跟前面是一样的。注意,这里说的是约束上面的时钟clk,而不是mmcm的输出时钟。
1.2 差分时钟
差分时钟是指通过管脚的p端和n端共同进来的,通常应该到高频或者精度 很高的场合,例如明德扬的mp802、mp5620,以及各种核心板,基本上外面都有差分晶振,有差分时钟的输入。
如果是差分时钟,又是如何约束呢?
注意下,差分信号在芯片上,肯定是占用了两个管脚位置,但在代码中不一定。在xilinx的顶层接口代码中,差分时钟会对应两个接口信号,分别 p端和n端;而对于altera,顶层接口信号只有一个,不用区分出p端和n端,在管脚定义时,再来区分出p和n。
对于altera的差分时钟约束,其与单端输入约束方法完全一样。
对于xilinx的差分时钟约束,只需要约束p端就可以了,即:
create_clock -name sysclk -period 10 -waveform {0 5} [get_ports clk_p]
1.3 gt或恢复的时钟
第三种是gt或恢复的时钟,即使用了高速收发器的情形,最常见的就是光纤接口了。
在高速收发器管脚中,是没有时钟的,时钟已经嵌入到数据里面。接收的时候,我们使用高速收发器如gtx、gty ip核接收数据,并且从数据时提取出时钟。这个恢复出来的时钟就是此种情形,例如上图中的gt模块,就是fpga内部使用的一个ip核,其输出了时钟txclk。
在这种情况下,我们需要约束这个恢复出来的时钟。按前面方式,同样也是使用create_clock,定义时钟周期、占空比等,但约束对象需要注意一下,不是通过get_ports,而是通过get_pins找到对象,该对象是恢复出的时钟,如上图中的gt/txoutclk,即:
    create_clock -name txclk -period 6.667-waveform {0 5} [get_pins gt/txoutclk]
   上面产生了一个名为txclk的约束,其对象为gt/txoutclk,周期为6.667,即133m。
   对于get_ports和get_pins的区别,可以简单认为,get_ports是fpga顶层的接口,该接口是要连到fpga芯片管脚上的;get_pins是模块内的输出管脚。如果大家不清楚是用哪个,可以使用工具,工具会提醒您怎么找出这个信号来的。
   注意上面找到的是gt/txoutclk,而不是图中的txclk。这是因为txclk是例化的信号,有时候是找不出来的。这个时候,需要设计者找到gt模块,再仔细辨识出时钟信号是哪个,非常考验设计师的经验。
第2节 pll等衍生时钟  
   上图是时钟clk经过内部的mmcm时钟管理单元,该时钟管理单元在此基础上倍频或者分频等,产生输出时钟clkout0,该时钟用于驱动rega和regb。在前面的介绍里,我们知道需要对clk进行约束,使用的是create_clock命令。那么上图中的clkout0要不要约束呢?
   对于pll和mmcm,一般vividao、ise和quartus工具是可以推导出该时钟约束的,因为我们在生成ip核的时候,已经设置了该时钟的输入和输出 时钟频率、相位等信息,通过这些信息,工具就可以推导出时钟约束。
   因此,对于xilinx可以不用约束pll和mmcm产生的时钟;对于altera,也可以自动推导的,但需要添加如下命令,才会自动推导:
derive_pll_clocks
   虽然工具可以自动推导pll和mmcm产生的时钟约束,但是其约束时钟名是不受设计师控制或预见的。这会带来什么问题呢?
   我们产生时钟约束后,通常还会在基于此时钟产生其他约束,例如下面是input delay的约束:
set_input_delay -clock sysclk -max 4 [get_ports ain]
   上面是input delay的约束,对象是ain,但注意看,-clock后面的sysclk是时钟约束产生的时钟名(注意是约束名,不是代码中的时钟信号),这说明input delay约束时,是依赖时钟约束名的。
   如果由工具自动推导pll和mmcm产生时钟约束,那么名字就不知道,或者虽然知道了,但可能稍微改下代码名称又变了。这样会导致依赖于此名字的其他约束,会存在失效而不知道的风险。
   因此,明德扬建议对pll和mmcm产生时钟添加约束,确定时钟名。
例如上面的电路,添加如下约束
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
首先通过create_clock命令对输入管脚clk约束,周期为5,命名为clk_200。然后通过create_geneated_clock对mmcm产生的clkout0约束,命名为my_clk;约束对象为mmcm/clkout0;通过-source表明来源于mmcm/clkin,即mmcm的输入管脚;通过-master_clock表明其主时钟是clk_200。
通过上面方法,就可以确定mmcm的时钟名,已经固定为my_clk,不会再变了。前面提及的input delay约束,就会变为如下:
set_input_delay -clock my_clk -max 4 [get_ports ain]
第3节 自己分频的时钟
第三种就是自己分频的时钟。如上图所示,clk1经过一个d触发器,通过该触发器二分频产生了时钟clk2。
首先说明,明德扬不推荐使用此方法来产生时钟,我们建议全部使用pll等来产生时钟。如果确实要用到分频时钟时,那就要记得做时钟约束。这种情况下要怎么进行约束呢?下面是推荐的约束方法。
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
首先通过create_clock产生对管脚ckp1的时钟约束,周期定为5,名字为clk1。
然后通过create_generated_clock产生二分频后的时钟约束,对象是rega/q,即d触发器的输出信号;然后要指示该时钟来自于ckp1,通过-source来指定;最后还要说明频率,通过-divide_by来说明几分频,-divide_by 2是表示二分频,即ckp1时钟的一半频率。
注意的是,一定要通过-divide_by来指定频率,因为工具无法从您的代码中推导出频率的。
强烈建议,分频时钟一定要约束,经验之谈,没有约束的话,时钟是不稳定的,会产生莫名其妙的问题的,这方面我们已经吃过亏的。
第4节 总结与建议 好了,我们在这里再总结一下。
首先,本文将时钟约束分了好几种情况,制成了一个表。您可以根据实际情况,对照步骤表,从而制定自己需要在我约束。
其次,注意一下约束的优先级。
自定义约束覆盖工具推导的约束。前面讲过,有些约束工具是可以推导出来的。如果自己又定义了该对象的约束,那么这个约束将覆盖工具推导出来的约束,即定义的约束有效,推导出来的约束无效。
后定义的约束覆盖先定义的约束。例如,在开始的时候定义了一个对clk的约束,定义为100m,后面又有一个对clk的约束,定义为200m,那么以哪个为准呢?那就以后面的为准,约束为200m。
但有时候需要对多个约束同时有效,即多个约束共存,那么可以在约束后面加上-add,以此表明不要覆盖前面约束,而是共同有效。
下一篇文章,我们将具体探讨“input delays约束”的内容,讲解各种情况下的时序约束方法。需要更多更详细的资料,可以找作者了解。


基于IP协议的LTE和WiMAX两种技术的对比
将智能魔镜显示器融入到智慧家庭中会是怎么样
射频识别芯片在汽车智能防盗报警装置中的应用
高通物联网最新发布,从入门级到顶级的豪华全家桶,瞄准细分市场
韦尔股份上市三年股价增涨30多倍
FPGA设计之时序约束
如何才能最小化SEPIC转换器的辐射干扰?
要送给LoRa一首《凉凉》?
基于IRS2540的Buck转换器实现高亮度LED驱动器的设计优化
Zytronic 为小屏幕带来多点触控
东大金智科技10G SFP+光模块特征
阻抗性能深入剖析
GGII:2023H1国内锂电主材三大变动
C语言中int的使用方法 关于数组的复合型表述详解
我国工业互联网的七大短板解析
苹果发布iPhone XS、XS Max和XR智能电池壳 支持Qi无线充电
华为公开“量子密钥”相关技术专利,降低量子密钥分发的复杂性和降低成本
Cyclone V SoC FPGA系列主要优势和特性以及架构图
中国无线电运动协会章程
如何提高用于赛道安全的视频监控系统性能