FPGA时序约束之时钟约束(altera)

在quartus ii中,为了确保得到准确的静态时序分析结果,我们必须要对设计里所有的时钟进行约束。
quartus ii里的静态时序分析工具支持以下几种类型的时钟约束:
(1) Base clocks 基础时钟;
(2) Virtual clocks 虚拟时钟;
(3) Multifrequency clocks 多频率时钟;
(4) generated clocks 生成时钟。
在sdc里编写约束文件时,首先要对时钟进行约束,因为其他的约束都是参考时钟进行的。静态时序分析是从sdc的上面到下面依次读取你写的约束指令的。
1、创建 Base clocks 基础时钟 约束
基础时钟是输入fpga的主要时钟,基础时钟是由片外的晶振或者外部器件产生的,是整个设计的时钟源头,其余的generated clocks以及其它约束都是用base clocks作为参考时钟的。
用create_clock 指令 对输入时钟进行约束,下面的7-8是对一个输入的时钟作约束

-period 10 是指输入的时钟周期是10ns,即频率为100Mhz;
-waveform {2.5 7.5}是指时钟偏移2.5ns(周期/4),即相位偏移了90°;
-get_ports clk_sys 是指输入的时钟是从clk_sys这个管脚输入fpga的。
这里写图片描述

对同一个输入管脚有多个频率的时钟进行约束,在第二条指令后加 -add, 该约束命令表示从clk_sys管脚输入的时钟 有100M和200M两种频率。格式如下:
这里写图片描述

2、创建 Virtual clocks 虚拟时钟 约束
虚拟时钟并没有真正的输入源,是通过指令虚拟出来的。虚拟时钟主要是用在I/O输入输出约束上,用来代表与fpga相连的外部器件的时钟。比如源同步输入时,就可以通过创建虚拟时钟进行输入最大最小延迟约束。
下面是创建一个名称为 my_virt_clk,周期10ns的虚拟时钟。注意这里没有get_ports 项。
这里写图片描述

3、创建 Multifrequency clocks 多频率时钟 约束
指令格式如下,上面在2里已经讲过。
FPGA时序约束之时钟约束(altera)_第1张图片

4、创建 generated clocks 生成时钟 约束
generated clocks是指从PLL生成的时钟,或者由程序分频产生的时钟。在sdc里用create_generated_clock指令对生成时钟进行约束。Options 里有综括号的表示是可选的,不是必须的。格式如下:
FPGA时序约束之时钟约束(altera)_第2张图片
-name 用来指定通过create_generated_clock指令生成的时钟名称
-source 指用来生成时钟的源时钟,比如在PLL里,指输入PLL的源时钟
-master_clock 是指源时钟如果有几个不同的频率,该master_clock指示源时钟用的哪个频率的时钟作为source clock
-divide_by 时钟的分频值
-multipl_by 时钟的倍频值
-duty_cycle 生成时钟的占空比
-invert 生成时钟反相
-phase 生成时钟相位偏移值

下面是用程序进行分频产生时钟的例子
一个寄存器把输入的时钟CLK_IN进行二分频输出
FPGA时序约束之时钟约束(altera)_第3张图片
对其进行时钟约束,指令如下:
FPGA时序约束之时钟约束(altera)_第4张图片

再举一个PLL生成时钟约束的例子:
下面是在程序里例化的一个PLL,输入时钟CLK是 25Mhz,产生4个输出时钟
outclk_0 是125M,outclk_1是 25M,outclk_2 是2.5M,outclk_3 是50M

FPGA时序约束之时钟约束(altera)_第5张图片

首先对输入时钟CLK进行约束,指令如下:
这里写图片描述
其次,再对PLL生成的时钟进行约束,指令如下:
PLL为了生成输出的4个时钟,先产生了一个500Mhz的临时时钟,名称为pll_inst|pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|vcoph[0],后面输出的时钟都是以这个时钟作为源进行分频的。

FPGA时序约束之时钟约束(altera)_第6张图片
line160-164产生一个500Mhz的时钟
- name 名称为pll_inst|pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|vcoph[0]
-source 指该模块的输入时钟管脚名称为pll_inst|pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|refclkin
-duty_cycle 50 即生成时钟占空比为50%
-multiply_by 20 即倍频20 ,所以该时钟频率为 源输入时钟频率25M*20=500M
-master_clock {altera_tse_CLK} 即为输入该模块的时钟名称 是altera_tse_CLK
gen_pins 指该模块输出500Mhz时钟的管脚名称为pll_inst|pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|vcoph[0]

line166-170输出125Mhz时钟,名为 clk_125M_0deg
- name 名称为clk_125M_0deg
-source 指该模块的输入时钟管脚名称为pll_inst|pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|vco0ph[0]
-duty_cycle 50 即生成时钟占空比为50%
-multiply_by 1 即倍频1
-divide_by 4 分频4,所以该时钟频率为输入时钟频率500M*1/4=125Mhz
-master_clock即为输入该模块的时钟名称是 pll_inst|pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|vcoph[0] 该时钟就是line160-164产生的公共时钟
gen_pins 指该模块输出500Mhz时钟的管脚名称为pll_inst|pll_inst|altera_pll_i|general[0].gpll~PLL_OUTPUT_COUNTER|divclk

line172-176输出125Mhz时钟,名为 clk_25M_0deg

line178-182输出2.5Mhz时钟,名为 clk_2_5M_0deg

line184-188输出50Mhz时钟,名为 mm_clk

对于上面的那些输入时钟或者管脚的名称是怎么知道的?
我是先在sdc里输入 derive_pll_clocks 这条指令 进行全编译,编译后在 编译报告里的Timequest ->clocks里就有对应的名称了。然后在进行上面的约束,就行了。

5、derive_pll_clocks
该命令是将程序里所有的PLL生成的时钟都进行约束,生成约束时钟的名称不能修改。所以为了可以灵活地修改生成时钟的名称,很多时候都是用create_generated_clock 指令来对PLL生成时钟进行约束。
下面就是用两种方式对PLL生成的时钟进行约束
FPGA时序约束之时钟约束(altera)_第7张图片
用create_generated_clock指令生成的时钟名字是可以修改的,比如上面生成的时钟名称 c100,c200,c200_shift
而用derive_pll_clocks 生成的时钟名称是固定的 是PLL模块输出管脚的名称

6、derive_clock_uncertainty
对时钟的uncertainty 进行约束,时钟的uncertainty指的是时钟的jitter抖动和skew偏斜。 用derive_clock_uncertainty,静态时序分析工具会自动地去计算时钟的uncertainty,而不用手动去添加。

7、set_clock_groups 创建时钟分组 命令
由于静态时序分析工具 默认所有的时钟都是相关的,这样会把一些没有关联的信号进行分析,导致错误的分析结果,所有需要用该命令去把时钟进行分组。
set_clock_groups 有两个类型 :
-exclusive:表示所分的组是互斥的,不能同时存在。
-asynchronous:表示所分的组是异步的,即不相关的。
下面是创建两个互斥的时钟分组,时钟clk_A 和clk_B分在不同的组,是互斥的。两者不会在程序里同时存在。
这里写图片描述
下面是创建两个异步的时钟分组,时钟clk_A 和clk_B为一组,clk_C为另外一组,这样clk_A ,clk_B 与clk_C就是异步的,不相关的。
这里写图片描述

你可能感兴趣的:(fpga时序约束,fpga-时序约束)