本文是对网上时序约束相关文章进行学习记录;
主要来源公众号:科学计算Tech
目录
1.IO约束
2.时钟周期约束
3.多周期约束
4.伪路径
5.XDC约束优先级
1
IO约束
1.1管脚约束
管脚约束指管脚分配,我们要指定管脚的位置PACKAGE_PIN和管脚对应的电平标准IOSTANDARD两个属性的值;
set_property PACKAGE_PIN AD8 [get_ports srio_rxp0]
1.2延迟约束
延迟约束用的是set_input_delay和set_output_delay,分别用于input端和output端,其时钟源可以是时钟输入管脚,也可以是虚拟时钟。
set_input_delay
从图中可以得到:T_inputdelay = Tco + TD
从图中可以得到:上游器件和FPGA的时钟沿是同时到达的,但是上游器件发送的数据在到达接收端的时候比时钟沿要延迟1-2ns之间,当满足图中的时序时,最大延迟为2ns,最小延迟为1ns。
设置方式为:
create_clock -name sysclk -period 10 [get_ports clkin]set_input_delay 2 -max -clock sysclk [get_ports Datain]set_input_delay 1 -min -clock sysclk [get_ports Datain]
set_output_delay
set_output_delay的用法跟set_input_delay相似;
02
时钟周期约束
2.1 Create_clock
在Vivado中使用create_clock来创建时钟周期约束。使用方法为:
create_clock -period 8.333 -name jesd_refclk_p [get_ports jesd_refclk_p]
如何确定主时钟是时钟周期约束的关键,可以借助Tcl脚本判断;
在Open Synthesized Design或者Open Implementation Design之后,并通过以下两种方式查看主时钟。
方式一
运行tcl指令report_clock_networks -name mainclock,显示结果如下:
方式二
运行tcl指令check_timing -override_defaults no_clock,显示结果如下:
使用report_clocks指令可以查看约束是否生效。执行report_clocks后,如下所示:
一般来讲,我们的输入时钟都是差分的,此时我们只对P端进行约束即可。如果同时约束了P端和N端,通过report_clock_interaction命令可以看到提示unsafe。这样既会增加内存开销,也会延长编译时间。
2.2 create_generated_clock 衍生时钟
设置方式为:
create_generated_clock -name -source -multiply_by -divide_by -master_clock
此外可以重新设置Vivado自动生成的衍生时钟的名字,只需设置name和source参数即可,其中这个source可以直接从report_clocks中得到;
设置方式为:
create_generated_clock -name clk_out60 -source [get_pins clk_60_inst/inst/mmcm_adv_inst/CLKIN1] [get_pins clk_60_inst/inst/mmcm_adv_inst/CLKOUT0]
2.3 set_clock_groups时钟分组
常用方法三种:
1.当两个主时钟是异步关系时,使用asynchronous来指定
设置方式为:
create_clock -period 2.083 -name sys_clk_p [get_ports sys_clk_p]create_clock -period 10.000 -name board_clk_p [get_ports board_clk_p]set_clock_groups -name board_sys_async -asynchronous -group [get_clocks -include_generated_clocks sys_clk_p] -group [get_clocks -include_generated_clocks board_clk_p]
2.第二种用法是当我们需要验证同一个时钟端口在不同时钟频率下能否获得时序收敛时使用。比如有两个异步主时钟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] -addcreate_clock -name clk1C -period 5.0 [get_ports clk1] -addcreate_clock -name clk2 -period 10.0 [get_ports clk2]set_clock_groups -physically_exclusive -group clk1A -group clk1B -group clk1C //-physically_exclusive在物理上不会同时存在set_clock_groups -asynchronous -group "clk1A clk1B clk1C" -group clk2
3.第三种用法就是当我们使用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]]
2.4虚拟时钟
虚拟时钟主要应用:
外部IO的参考时钟并不是设计中的时钟
FPGA I/O路径参考时钟来源于内部衍生时钟,但与主时钟的频率关系并不是整数倍
针对I/O指定不同的jitter和latency
设置方式为:
create_clock -name sysclk -period 10 [get_ports clkin]create_clock -name virclk -period 6.4set_input_delay 2 -clock sysclk [get_ports A]set_input_delay 2 -clock virclk[get_ports B]
可以看到,创建虚拟时钟用的也是create_clock约束,但后面并没有加get_ports参数,因此被称为虚拟时钟。
2.5最大最小延迟约束
设置路径的max/min delay,主要应用场景有两个:
输入管脚的信号经过组合逻辑后直接输出到管脚
异步电路之间的最大最小延迟
设置方式为:
set_max_delay [-datapath_only] [-from][-to][-through]set_min_delay [-from] [-to][-through]
max/min delay的约束平时用的相对少一些,因为在跨异步时钟域时,往往会设置asynchronous 或者 false_path。对于异步时钟,一般通过设计来保证时序能够收敛,而不是通过时序约束来保证。
03
多周期约束
数据被发起后,由于路径过长或者逻辑延迟过长要经过多个时钟周期才能到达捕获寄存器;又或者在数据发起的几个周期后,后续逻辑才能使用。这时如果按照单周期路径进行时序检查,就会报出时序违规。因此就需要多周期路径约束。
设置方式为:
set_multicycle_path [-setup|-hold] [-start|-end][-from] [-to ] [-through ]
对于建立时间,num_cycles是指多周期路径所需的时钟周期个数;
对于保持时间,num_cycles是指相对于默认的捕获沿,实际捕获沿应回调的周期个数。
发起沿和捕获沿可能是同一个时钟,也可能是两个时钟,参数start和end就是选择参考时钟是发送端还是接收端。
start表示参考时钟为发送端(发端)所用时钟,对于保持时间的分析,若后面没有指定start或end,则默认为为-start;
end表示参考时钟为捕获端(收端)所用时钟,对于建立时间的分析,若后面没有指定start或end,则默认为为-end;
上面这两句话也不难理解,因为setup-time是在下一个时钟沿进行捕获时的约束,因此默认是对接收端的约束;而hold-up-time是对同一个时钟沿的约束,目的是发送端不能太快,是对发送端的约束。
对于单周期路径来说,setup的num_cycles为1,hold的num_cycles为0.
多周期路径要分以下几种情况进行分析
3.1单时钟域
即发起时钟和捕获时钟是同一个时钟,其多周期路径模型如下图所示。
在单时钟域下,若数据经过N个周期到达,则约束示例如下:
set_multicycle_path N -setup -from [get_pins CLK1] -to [get_pins CLK2]set_multicycle_path N-1 -hold-from [get_pins CLK1] -to [get_pins CLK2]
3.2时钟相移
如果在单时钟域下,发送端和接收端时钟两个时钟同频不同相?
如上图所示,时钟周期为4ns,接收端的时钟沿比发送端晚了0.3ns,若不进行约束,建立时间只有0.3ns,时序基本不可能收敛;而保持时 间则为3.7ns,过于丰富。可能有的同学对保持时间会有疑惑,3.7ns是怎么来的?还记得我们上面讲的保持时间的定义么,在0ns时刻,接收端 捕获到发送的数据后,要再过3.7ns的时间发送端才会发出下一个数据,因此本次捕获的数据最短可持续3.7ns,即保持时间为3.7ns。
因此,在这种情况下,我们应把捕获沿向后移一个周期,约束如下:
set_multicycle_path 2 -setup -from [get_pins CLK1] -to [get_pins CLK2]
对setup约束后,hold会自动向后移动一个周期,此时的建立保持时间检查如下:
那如果接收端的时钟比发送端的时钟超前了怎么处理?
同样的,时钟周期为4ns,但接收端时钟超前了0.3ns,从图中可以看出,此时setup是3.7ns,而保持时间是0.3ns。这两个时间基本已经满足了Xilinx器件的要求,因此无需进行约束。
3.3慢时钟到快时钟的多周期
若数据经过N个周期到达,通过约束让建立时间的要求更容易满足,即
set_multicycle_path N -setup -from [get_clocks CLK1] -to [get_clocks CLK2]set_multicycle_path N-1 -hold -end -from [get_clocks CLK1] -to [get_clocks CLK2]
3.4快时钟到慢时钟的多周期
若数据经过N个周期到达,可以通过约束,让时序条件更加宽裕。
set_multicycle_path N -setup -start -from [get_clocks CLK1] -to [get_clocks CLK2]set_multicycle_path N-1 -hold -from [get_clocks CLK1] -to [get_clocks CLK2]
04
伪路径
什么是伪路径?伪路径指的是该路径存在,但该路径的电路功能不会发生或者无须时序约束。如果路径上的电路不会发生,那Vivado综合后会自动优化掉,因此我们无需考虑这种情况。
为什么要创建伪路径?创建伪路径可以减少工具运行优化时间,增强实现结果,避免在不需要进行时序约束的地方花较多时间而忽略了真正需要进行优化的地方。
伪路径一般用于:
跨时钟域
一上电就被写入数据的寄存器
异步复位或测试逻辑
异步双端口RAM
可以看出,伪路径主要就是用在异步时钟的处理上;
设置方式为:
set_false_path [-setup] [-hold] [-from ] [-to ] [-through ]
需要注意的是,-through是有先后顺序的,下面的两个约束是不同的约束:
set_false_path -through cell1/pin1 -through cell2/pin2set_false_path -through cell2/pin2 -through cell1/pin1
因为它们经过的先后顺序不同,伪路径的约束是单向的,并非双向的,若两个时钟域相互之间都有数据传输,则应采用如下约束:
set_false_path -from [get_clocks clk1] -to [get_clocks clk2]set_false_path -from [get_clocks clk2] -to [get_clocks clk1]
也可以直接采用如下的方式,与上述两行约束等效:
set_clock_groups -async -group [get_clocks clk1] -to [get_clocks clk2]
05
XDC约束优先级
时序例外的优先级从高到低为:
1. Clock Groups (set_clock_groups)
2. False Path (set_false_path)
3. Maximum Delay Path (set_max_delay) and Minimum Delay Path (set_min_delay)
4. Multicycle Paths (set_multicycle_path)