草庐IT

FPGA时序约束分享02_时钟约束(实用分享)

MDYFPGA 2024-01-01 原文
    • 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.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]

​​​​​​​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时序约束分享02_时钟约束(实用分享)的更多相关文章

  1. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  2. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  3. 牛客网专项练习30天Pytnon篇第02天 - 2

    1.在Python3中,下列关于数学运算结果正确的是:(B)a=10b=3print(a//b)print(a%b)print(a/b)A.3,3,3.3333...B.3,1,3.3333...C.3.3333...,3.3333...,3D.3.3333...,1,3.3333...解析:    在Python中,//表示地板除(向下取整),%表示取余,/表示除(Python2向下取整返回3)2.如下程序Python2会打印多少个数:(D)k=1000whilek>1:    print(k)k=k/2A.1000 B.10C.11D.9解析:    按照题意每次循环K/2,直到K值小于等

  4. 软约束、硬约束、Minimum Snap的轨迹优化方法 - 2

    文章目录前言约束硬约束的轨迹优化Corridor-BasedTrajectoryOptimizationBezierCurveOptimizationOtherOptions软约束的轨迹优化Distance-BasedTrajectoryOptimization优化方法前言可以看看我的这几篇Blog1,Blog2,Blog3。上次基于MinimumSnap的轨迹生成,有许多优点,比如:轨迹让机器人可以在某个时间点抵达某个航点。任何一个时刻,都能数学上求出期望的机器人的位置、速度、加速度、导数。MinimumSnap可以把问题转换为凸优化问题。缺点:MnimumSnap可以控制轨迹一定经过中间的

  5. FPGA 之 时钟,时钟域, 以及复位系统的设计 - 2

    FPGA时钟和时钟域时钟树所谓时钟树为FPGA内部资源,分:全局时钟树,区域时钟树,IO时钟树原则上优先使用全局时钟树,在GT接口上使用IO时钟树,一般工具也会对GT时钟加以限制;时钟树使用方式正确的物理连接FPGA会由物理管脚专门用于全局时钟设置,通过查询数据手册可以在PCB设计阶段进行确认,当外部时钟接入此管脚时,工具会自动占有全局时钟树资源,当接入普通信号时不会分配时钟树资源;恰当的代码描述原语的使用,即BUFG的使用,可以将PLL的输出等内部时钟进行全局时钟资源的分配;IO时钟资源需要参考相应接口手册,以ultrascale的GTH为例,其JESD204的时钟方案针对不同的子类会由不同

  6. ruby-on-rails - 子域约束并排除某些子域 - 2

    在我的routes.rb文件中,我想使用rails3中的子域约束功能,但是我想从catchall路由中排除某些域。我不想在特定的子域中有特定的Controller。这样做的最佳做法是什么。#thissubdomainidontwantallofthecatchallroutesconstraints:subdomain=>"signup"doresources:usersend#hereIwanttocatchallbutexcludethe"signup"subdomainconstraints:subdomain=>/.+/doresources:carsresources:sta

  7. 连续3天3场分享,KubeVela@KubeCon EU 2023 抢鲜看! - 2

    自从2019年OpenApplicationModel诞生以来,KubeVela已经经历了几十个版本的变化,并向现代应用程序交付先进功能的方向不断发展。最近,KubeVela完成了向CNCF孵化项目的晋升,标志着社区的发展来到一个新的里程碑。今天,KubeVela社区内活跃着大量来自全球的开发者,共同推动KubeVela项目的落地和发展。在即将开幕的KubeCon+CloudNatvieConEurope2023上,我们惊喜地发现,连续3天,KubeVela项目的贡献者、企业用户和来自阿里云的核心维护者,将从不同角度展对KubeVela项目的分享。让我们先睹为快!🎙️BuildingaPlat

  8. MicroBlaze在纯FPGA下 Xilinx SDK固化程序到外部SPI FLASH - 2

    外部SPIFLASH:MicronN25Q128A13ESE40G(128Mbit(16MByte))FPGA:XC7A100T CPU:Microblaze第一种情况:Microblaze在简单的应用,比如运行LED,IIC,SPI,UART之类的低俗接口驱动,或做一些简单的辅助型工作时,一般生成的applicationelf文件都不大,在10几KB或者几十,百几KB,此时使用FPGA内部的BRAM资源已经足够。XC7A100T本身就有600几KB的BRAM资源。这种情况下直接将硬件流文件和elf文件合并为download.bit文件,在直接烧录到外部SPIFLAH即可。1.Xilinx--

  9. ruby-on-rails - 在 Facebook、转推等上分享直接 Ruby gem 中的按钮? - 2

    注意http://techcrunch.com/2010/04/04/he-even-makes-coldplay-sound-fun/顶部的那些按钮在社交网络上分享网址?我想为我正在构建的网站做一些非常相似的事情。ShareThis提供了一个可以做同样事情的小部件,但它是品牌化的和外部的。我正在寻找纯Ruby解决方案。包含可包含在RailsApplicationHelper类中的模块的gem将是完美的。在我重新发明轮子之前,感谢您的建议!想象一下: 最佳答案 我能找到的最好的是:http://www.addthis.com/这里有

  10. ruby-on-rails - 在rails中创建一个表并添加外键约束 - 2

    我有一个表students,字段为ward_id,我必须创建一个名为guardian_users的表,字段为id,ward_id,email,guardian_id,hashed_pa​​ssword等现在我必须添加约束外键。学生中的任何更新/删除/编辑/插入应该对guardian_users具有相同的效果。我如何在Rails2.3.5中做到这一点?students表存在,但其他表还不存在。 最佳答案 您要么需要foreign_key_migrations插件或#execute方法。假设您使用插件:classCreateGuardi

随机推荐