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⾥已经讲过。
4、创建 generated clocks ⽣成时钟 约束
generated clocks是指从PLL⽣成的时钟,或者由程序分频产⽣的时钟。在sdc⾥⽤create_generated_clock指令对⽣成时钟进⾏约束。Options ⾥有综括号的表⽰是可选的,不是必须的。格式如下:
-name ⽤来指定通过create_generated_clock指令⽣成的时钟名称
-source 指⽤来⽣成时钟的源时钟,⽐如在PLL⾥,指输⼊PLL的源时钟
-master_clock 是指源时钟如果有⼏个不同的频率,该master_clock指⽰源时钟⽤的哪个频率的时钟作为source clock
-divide_by 时钟的分频值
-multipl_by 时钟的倍频值
现代伊兰特油耗-duty_cycle ⽣成时钟的占空⽐
-invert ⽣成时钟反相
-phase ⽣成时钟相位偏移值
下⾯是⽤程序进⾏分频产⽣时钟的例⼦
⼀个寄存器把输⼊的时钟CLK_IN进⾏⼆分频输出
对其进⾏时钟约束,指令如下:
鲁b是哪里的车牌
再举⼀个PLL⽣成时钟约束的例⼦:
下⾯是在程序⾥例化的⼀个PLL,输⼊时钟CLK是 25Mhz,产⽣4个输出时钟
outclk_0 是125M,outclk_1是 25M,outclk_2 是2.5M,outclk_3 是50M
⾸先对输⼊时钟CLK进⾏约束,指令如下:
其次,再对PLL⽣成的时钟进⾏约束,指令如下:
PLL为了⽣成输出的4个时钟,先产⽣了⼀个500Mhz的临时时钟,名称为
pll_inst|pll_inst|altera_pll_i|general[0].gpll~FRACTIONAL_PLL|vcoph[0],后⾯输出的时钟都是以这个时钟作为源进⾏分频的。
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⽣成的时钟进⾏约束
⽤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就是异步的,不相关的。