1. 时钟周期约束: 时钟周期约束,顾名思义,就是我们对时钟的周期进行约束,这个约束是我们用的最多的约束了,也是最重要的约束。
2. vivado中时钟约束指令:
create_clock
使用create_clock来创建时钟周期约束,使用方法:
create_clock -name
值得注意的是,这里的时钟必须是主时钟 primary clock。主时钟通常有两种情况:一种是由外部时钟源提供,另外一种是告诉收发器的时钟提供。
如何查看主时钟?
综合、布局布线之后
打开综合设计或者布局布线设计
两种方式查看主时钟:第一种,report_clock_networks -name mainclock,可以直接查看主时钟。第二种,check_timing -override_defaults no_clock,可以查看没有被约束的主时钟
当主时钟之间的相位关系确定时,则通过-waveform参数进行约束
如上图所示的两个主时钟,进行如下约束:
create_clock -name clk0 -period 10.0 -waveform {0 5} [get_ports clk0]
create_clock -name clk1 -period 8.0 -waveform {2 8} [get_ports clk1]
数字单位默认是ns。如果不写waveform参数,则默认占空比是50%且第一个上升沿在0时刻。
一般来说,如果输入时钟是差分的,只需要对P端进行约束即可。
create_generated_clock
约束在FPGA内部产生的衍生时钟,使用方法如下:
create_generated_clock -name
-source
-multiply_by
-divide_by
-master_clock
因为是衍生时钟,所以有-source参数,指明衍生时钟从哪里来的,后面就是源时钟名字,master clock,叫上一级时钟,区别于primary clock。它可以是primary clock 也可以是其他衍生时钟。
这个命令并不是设定周期和波形,而是描述时钟电路如何对上级时钟的转换:
简单的频率分频、倍频
频率和分频组合,获得非整数的比例,通常由MMCM或PLL完成
相移或波形反相
占空比改变
set_clock_groups
使用方法:
set_clock_groups -asynchronous -group
set_clock_groups -physically_exclusive -group
第一种用法:来指定两个主时钟是异步关系,使用asynchronous。
create_clock -period 10 -name clk1 [get_ports clk1]
create_clock -period 8 -name clk2 [get_ports clk2]
set_clock_groups -asynchronous -group clk1 -group clk2
第二种用法:当我们需要验证同一个时钟端口在不同时钟频率下能否获得时序收敛时使用。 比如有两个异步主时钟clk1和clk2,需要验证在clk2频率为100MHz,clk1频率分别为50MHz、100MHz和200MHz下的时序收敛情况,我们就可以这样写。
create_clock -name clk1A -period 20.0 [get_ports clk1]
create_clock -name clk1B -period 10.0 [get_ports clk1] -add
create_clock -name clk1C -period 5.0 [get_ports clk1] -add
create_clock -name clk2 -period 10.0 [get_ports clk2]
set_clock_groups -physically_exclusive -group clk1A -group clk1B -group clk1C
set_clock_groups -asynchronous -group "clk1A clk1B clk1C" -group clk2
第三种用法:当我们使用BUFGMUX时,会有两个输入时钟,但只会有一个时钟被使用。 比如MMCM输入100MHz时钟,两个输出分别为50MHz和200MHz,这两个时钟进入了BUFGMUX。在这种情况下,我们需要设置的时序约束如下:
set_clock_groups -logically_exclusive
-group [get_clocks -of [get_pins inst_mmcm/inst/mmcm_adv_inst/CLKOUT0]]
-group [get_clocks -of [get_pins inst_mmcm/inst/mmcm_adv_inst/CLKOUT1]]
虚拟时钟
虚拟时钟通常用于设定对输入和输出的延迟约束,这个约束其实是属于IO约束中的延迟约束。虚拟时钟和前面讲的延迟约束的使用场景不太相同。顾名思义,虚拟时钟,就是没有与之绑定的物理管脚。
虚拟时钟主要用于以下三个场景:
外部IO的参考时钟并不是设计中的时钟
FPGA I/O路径参考时钟来源于内部衍生时钟,但与主时钟的频率关系并不是整数倍
针对I/O指定不同的jitter和latency
简而言之,之所以要创建虚拟时钟,对于输入来说,是因为输入到FPGA数据的捕获时钟是FPGA内部产生的,与主时钟频率不同;或者PCB上有Clock Buffer导致时钟延迟不同。对于输出来说,下游器件只接收到FPGA发送过去的数据,并没有随路时钟,用自己内部的时钟去捕获数据。
比如:如下图所示,在FPGA的A和B端口分别有两个输入,其中捕获A端口的时钟是主时钟,而捕获B端口的时钟是MMCM输出的衍生时钟,而且该衍生时钟与主时钟的频率不是整数倍关系。
这种情况下时序约束如下:
create_clock -name sysclk -period 10 [get_ports clkin]
create_clock -name virclk -period 6.4
set_input_delay 2 -clock sysclk [get_ports A]
set_input_delay 2 -clock virclk [get_ports B]
可以看到,创建虚拟时钟用的也是create_clock约束,但后面并没有加get_ports参数,因此被称为虚拟时钟。
再举个输出的例子,我们常用的UART和SPI,当FPGA通过串口向下游器件发送数据时,仅仅发过去了uart_tx这个数据,下游器件通过自己内部的时钟去捕获uart_tx上的数据,这就需要通过虚拟时钟来约束;而当FPGA通过SPI向下游器件发送数据时,会发送sclk/sda/csn三个信号,其中sclk就是sda的随路时钟,下游器件通过sclk去捕获sda的数据,而不是用自己内部的时钟,这是就不需要虚拟时钟,直接使用set_output_delay即可。
注意,虚拟时钟必须在约束I/O延迟之前被定义。
max/min delay的约束平时用的相对少一些,因为在跨异步时钟域时,我们往往会设置asynchronous或者false_path。对于异步时钟,我们一般都会通过设计来保证时序能够收敛,而不是通过时序约束来保证。
审核编辑:汤梓红
全部0条评论
快来发表一下你的评论吧 !