)
FPGA时序约束分享02_时钟约束作者潘文明上一篇《FPGA时序约束分享01_约束四大步骤》一文中介绍了时序约束的四大步骤。上图是四大步骤并且每个步骤都分别展开了各种情况后续可以参考对照分别添加时序约束。本文讲述上图中的第1点时钟约束。时钟约束分三种情况输入时钟、PLL等衍生时钟以及自己分频的时钟。而其中输入时钟又可再分三种第一种是输入管脚是CLK的第二种是差分时钟最后一种是GT或恢复的一个时钟。下面分别展开描述。1.1输入时钟输入时钟根据管脚情况有三种三种第一种是输入管脚是CLK的第二种是差分时钟最后一种是GT或恢复的一个时钟。1.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.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.1.3GT或恢复的时钟第三种是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模块再仔细辨识出时钟信号是哪个非常考验设计师的经验。1.2PLL等衍生时钟上图是时钟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]1.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来指定频率因为工具无法从您的代码中推导出频率的。强烈建议分频时钟一定要约束经验之谈没有约束的话时钟是不稳定的会产生莫名其妙的问题的这方面我们已经吃过亏的。1.4总结与建议好了我们在这里再总结一下。首先本文将时钟约束分了好几种情况制成了一个表。您可以根据实际情况对照步骤表从而制定自己需要在我约束。其次注意一下约束的优先级。自定义约束覆盖工具推导的约束。前面讲过有些约束工具是可以推导出来的。如果自己又定义了该对象的约束那么这个约束将覆盖工具推导出来的约束即定义的约束有效推导出来的约束无效。后定义的约束覆盖先定义的约束。例如在开始的时候定义了一个对CLK的约束定义为100M后面又有一个对CLK的约束定义为200M那么以哪个为准呢那就以后面的为准约束为200M。但有时候需要对多个约束同时有效即多个约束共存那么可以在约束后面加上-add以此表明不要覆盖前面约束而是共同有效。下一篇文章我们将具体探讨“input delays约束”的内容讲解各种情况下的时序约束方法。需要更多更详细的资料可以找作者了解。明德扬官网明德扬 FPGA 产品中心官网 - 核心板、开发板、资料支持