时序约束搜集整理

搜了几个相关博文,选有用的截取了些,侵删。

http://xilinx.eetrend.com/content/2019/100046350.htmlVivado约束技巧——XDC时钟约束

1.XDC的时钟约束

XDC的基本语法可以分为时钟约束、I/O约束以及时序例外约束三大类。端口进来的主时钟以及GT的输出RXCLK/TX CLK都必须由用户使用create_clock自主创建。而衍生时钟 MMCM/PLL/BUFR的输出时钟都可以由Vivado自动推导

 

I/O约束(一般最后加)

XDC中的I/O约束有以下几点需要注意:

① 不加任何I/O约束的端口时序要求被视作无穷大。

② XDC中的set_input_delay / set_output_delay对应于UCF中OFFSET IN / OFFSET OUT,但视角相反。OFFSET IN / OFFSET OUT是从FPGA内部延时的角度来约束端口时序,set_input_de lay / set_output_ delay则是从系统角度来约束。

 

时序例外约束(三种)

时序约束搜集整理

 

 

时序的零起点。用create_clock定义的主时钟的起点即时序的零起点” , 注,用引脚进入的sysclk,和经过bufgsysclk_bufg,是会造成不同的结果的。(虽然你可能觉得同频,只有sysclk才是最准确的,用其他的都会差出前面一段延时)

 

重叠时钟 ,例如两个时钟经过一个MUX选择后输出的时钟两个重叠的衍生钟,并将其时钟关系约束为-physically_exclusive 表示不可能同时通过。这样做可以最大化约束覆盖率,也是ISEUCF中无法做到的

 

不同于UCF约束,在XDC中,所有的时钟都会被缺省认为是相关的,也就是说,网表中所有存在的时序路径都会被Vivado分析。这也意味着FPGA设计人员必须通过约束告诉工具,哪些路径是无需分析的,哪些时钟域之间是异步的。

 

///////////////////////////////////////////////////////////////////////////////////////////////////////

https://blog.csdn.net/Times_poem/article/details/80002336 vivado xdc约束基础知识5XDC约束技巧——CDC

2.CDC的约束(XDC语法)

1、安全的CDC路径: 所谓安全的CDC路径是指那些源时钟和目标时钟拥有相同的来源。

2、不安全的CDC路径:不安全的CDC路径则表示源时钟和目标时钟不同,且由不同的端口进入FPGA,在芯片内部不共享时钟网络。这种情况下,Vivado的报告也只是基于端口处创建的主时钟在约束文件中所描述的相位和频率关系来分析,并不能代表时钟之间真实的关系。

ISE中想要快速定位那些需要关注的CDC路径并不容易,特别是要找到不安全的CDC时,因为ISE缺省认为所有来源不同的时钟都不相关且不做分析,要报告出这类路径,需要使用ISE Timing Analyzer TRCE ,并加上 “-u” (表示unconstrained)这个选项。

Vivado中则容易许多,我们可以使用report_clock_interaction命令(GUI支持)来鉴别和报告设计中所有的时钟关系。执行命令后会生成一个矩阵图,其中对角线上的路径表示源时钟与目标时钟相同的时钟内部路径,其余都是CDC路径(可以看链接里有具体vivado操作)

CDC的设计与约束(2种CDC:1、两拍同步器 2、FIFO)

1简单同步器打两拍

可以手动布局(当然这不算时序约束,类似于手动分配MMCMBUFR),把用作简单同步器的多个寄存器放入同一个SLICE

set_property ASYNC_REG TRUE [get_cells [list sync0_reg sync1_reg]]

XDC中,对于此类设计的CDC路径,可以采用set_clock_groups来约束。

set_clock_groups -asynchronous -group [get_clocks -include_generated_clocks clk_oxo ] \-group [get_clocks -include_generated_clocks clk_core ]

2FIFO

2.1 Build-in硬核FIFO (我平时用FIFO,选的是Independent clocks block ram 而不是Independent clocks build-in ram

这种FIFO实际上就是用FPGA内部的BRAM来搭建,所有控制逻辑都在BRAM内部,是推荐的FIFO实现方式。其所需的XDC也相对简单,只要像上述简单同步器的时钟关系约束一样用set_clock_groups将读写时钟约束为异步即可。

2.2带有格雷码控制的FIFO

时序约束搜集整理

如上图所示FIFO,在存储器外部有一些用FPGA逻辑搭建的写指针和读指针控制,分属不同的时钟域,存在跨时钟域的时序路径。

此时如果仅将读写时钟用set_clock_groups约束为异步时钟,相当于设置从AB和从BA的路径全部为false pathfalse path的优先级最高,很显然这么做会导致所有跨读写时钟域的路径全部不做时序分析,读写指针和相关控制逻辑也就失去了存在的意义

所以建议的做法是不设set_clock_groups约束,转而采用set_max_delay来约束这些跨时钟域路径。以写入侧举例,一个基本的原则就是约束从cell1cell2的路径之间的延时等于或略小于cell2的驱动时钟一个周期的值。读出侧的约束同理。

set_max_delay $delay –from [get_cells cell1] –to [get_cells cell2] –datapath_only

 

 (set_max_delay而没有配套设置set_min_delay的情况下,同一路径只做setup分析而不做hold分析。)

datapath_only是从ISE时代的UCF中继承过来的约束,在XDC中必须作为一个选项跟set_max_delay配合使用,可以约束在时钟之间,也可以对具体路径进行约束。

示例:set_max_delay 10 -datapath_only -from clkA -to clkB

如果用户使用VivadoIP Catalog来产生此类FIFO,这样的XDC会随IP的源代码一起输出(如下所示),使用者仅需注意确保这个FIFO的读写时钟域没有被用户自己的XDC约束为false path或是异步clock groups

 

 

 

另一篇更吊的博客,是分别从三种时序例外的用法来讲的。https://blog.csdn.net/FPGADesigner/java/article/details/82898024 Vivado使用技巧(33):时序异常

3.时序例外的约束(false_path和max_delay)

三种时序异常

命令       功能

set_multicycle_path     设置路径上从起点到终点传递数据需要的时钟周期数

set_false_path      指示设计中的某条逻辑路径不进行时序分析

set_max_delayset_min_delay 设置最小与最大路径延迟值,会重写默认的建立与保持约束

3.1、虚假路径false path

什么时候要用到FALSE PATH 1. 从逻辑上考虑,与电路正常工作不相关的那些路径,比如测试逻辑,静态或准静态逻辑。2. 从时序上考虑,我们在综合时不需要分析的那些路径,比如跨越异步时钟域的路径。下面这些情况都属于虚假路径:

  1. 在有双同步器逻辑的地方有时钟域交叉
  2. 可能只在上电时写入一次的寄存器
  3. 复位或测试逻辑
  4. 异步分布式RAM的写端口于异步读时钟之间的路径

举个具体的例子加深对虚假路径的理解,如下图:

 

时序约束搜集整理

两个多路选择器MUX控制两个寄存器间的数据传输,但是两个MUX采用同一个选择信号。仔细分析会发现,无论如何Q端数据都无法传递到D端。虽然结构图上看起来QD之间存在一条路径,但是没有起到任何功能,因此应该定义为虚假路径。

下图和这个是一个道理,只是用的set_clock_groups -asynchronous,更简洁(set_false_path得用两句,ABBA。我的理解是这样)

时序约束搜集整理

 

再来2个例子

时序约束搜集整理

set_false_path –from [get_pins reg1|clk]–to [get_pins reg2|datain]

(这里博客里就只写了一条,也不是很好理解哈)

时序约束搜集整理

set_false_paths –from [get_clocks clk_100] –to [get_clocks clk_66]

set_false_paths –from [get_clocks clk_66] –to [get_clocks clk_100]

(这两条FALSE PATH可以用一条命令来代替: set_clock_groups –exclusive –group {clk_100} \ –group {clk_66} –group

   set_clock_groups [-asynchronous] [-exclusive] –group <names> 

-asynchronous :顾名思义,时钟是异步不相关的,时钟有完全不同的时钟源

   -exclusive :时钟是互斥的,即时钟不会再同一时刻同时有效

 实际上,这两个选项的效果是完全一样的。

但是set_clock_groups -async不可以完全代替set_false_path。因为伪路径并不一定的跨时钟域路径。

此外,对于reset,如果在工作时,reset信号有效时,时钟信号不翻转,用set_false_path

但是,如果reset信号有动作,时钟同时也有动作,则不能set_false_path

一般异步复位可以设置false path,但是用某个clk抓过之后的异步复位,再在这个clk域下使用时,不要设置false path

 

为何要在时序分析中设置掉虚假路径?理由如下:

一些情况下,不设置FALSE PATH也可以,工具会去分析相关时序路径,但是肯定会有setup或者hold不满足,这个时候就需要去确认这些路径是否有问题了

减少运行时间:工具不需要为这些虚假路径计时和做优化,可以减少很多运行时间。

增加结果质量:移除虚假路径可以极大增加结果质量QORQuality of Results)。综合、布局和优化设计的质量很大程度上受到时序问题的影响,因为工具总会尝试解决这些问题,包含虚假路径会导致不理想的结果(比如工具将过多注意力放在解决虚假路径的时序违背上,而忽视了真正需要解决的问题)。

set_false_path该命令模板如下

set_false_path [-setup] [-hold] [-from <node_list>] [-to <node_list>] [-through <node_list>]

几个节点列表选项的含义如下:

  1. -from:一组合法的起点列表,包括时钟对象、时序元素的时钟管脚、输入主端口或双向主端口。
  2. -to:一组合法的终点列表,包括时钟对象、时序元素的数据输入管脚、输出主端口或双向主端口。
  3. -through:一组合法的管脚或端口,注意节点的顺序很重要。如果约束中仅使用了-through,没有使用-from-to选项,Vivado会从时序分析中移除所有通过该列表的路径,使用时要特别小心。

几个定义虚假路径的例子

#-through的顺序表示路径穿过节点的顺序,因此下面是两条不同的约束

set_false_path -through cell1/pin1 -through cell2/pin2

set_false_path -through cell2/pin2 -through cell1/pin1

 

#上图中的虚假路径应该用下面这条命令约束

set_false_path -through [get_pins MUX1/a0] -through [get_pins MUX2/a1]

#使用-through而不用-from-to的好处是可以确保所有通过此节点的路径都会被移除,而不用考虑起点和终点

 

#移除复位端口到所有寄存器间的时序路径

set_false_path -from [get_port reset] -to [all_registers]

 

#禁用两个异步时钟域间的时序路径,从CLKACLKB

set_false_path -from [get_clocks CLKA] -to [get_clocks CLKB]

#注意,上述命令并没有禁用从CLKBCLKA的路径,还需要补充如下约束

set_false_path -from [get_clocks CLKB] -to [get_clocks CLKA]

 

从最后一个例子可知,我们需要双向地禁用时序路径,但是如果设计中有多个异步时钟域,编写起来就非常麻烦。这种情况最好其实应该使用set_clock_groups设置不同的异步时钟组。就是说

使用set_false_path

set_false_path -from [get_clocks clk1] -to [get_clocks clk2]

set_false_path -from [get_clocks clk2] -to [get_clocks clk1]

使用set_clock_group

set_clock_group -name asyn_clocks -asynchronous -group clk1 -group -clk2

 

上面还说到了异步分布式RAM的情况,这里也举一个约束例子。假设一个异步双口分布式RAM,其写操作与RAM时钟同步,但是读操作是异步的,这种情况下应该在写和读时钟间设置一个虚假路径。约束如下:

#RAM前的写寄存器和RAM后的读寄存器间设置虚假路径

set_false_path -from [get_cells <write_registers>] -to [get_cells <read_registers>]

 

3.2最小/最大延迟max_delay

最大延迟约束set_max_delay用于改写路径的默认建立时间(或恢复时间)需求;最小延迟约束set_min_delay用于改写路径的默认保持时间(或移除时间)。两条约束命令的语法模板如下:

set_max_delay <delay> [-datapath_only] [-from <node_list>] [-to <node_list>] [-through <node_list>]

set_min_delay <delay> [-from <node_list>] [-to <node_list>] [-through <node_list>]

-from-to-through和虚假路径中的用法相同。set_max_delay命令中如果添加了-datapath_only,那么计算裕量时便不会考虑时钟斜率。使用最小/最大延迟约束要注意如下三点:

  1. 路径上仅设置最大延迟约束(不使用-datapath_only选项),不会修改该路径上的最小延迟需求,保持时间检查仍采用默认值,相反也成立。但如果加入了-datapath_only,就会导致该路径上的保持时间需求被忽略。
  2. 通常输入端口到第一级寄存器间的约束用set_input_delay命令;最后一级寄存器到输出端口之间的约束用set_output_delay命令(详情见第32篇)。但输入端口到输出端口之间的纯组合逻辑路径可以用set_max_delayset_min_delay命令进行约束(通常称为in-to-out I/O路径)。
  3. 某些异步信号间没有时钟关系,但是需要最大延迟约束。比如我们通常用set_clock_groups划分两个异步时钟域,但有时我们需要确保两个时钟域之间的路径延迟不要太高。这种情况下,我们就要用set_max_delayset_false_path的命令组合(因为set_clock_groups的优先级更高,会取代set_max_delay,因此不能和其一块使用)

 另外在约束最小延迟和最大延迟时,如果-from-to中的节点选择不合理,会出现路径分割(Path Segmentation)现象。

 

https://blog.csdn.net/wordwarwordwar/article/details/80188856?utm_source=blogxgwz4

另一篇里面 关于false pathmax delay 如何选择的论述。

1、两个异步时钟域设置false path是可以的,

2、设置max delay是保证总线类的跨时钟信号在被采样的时候是采的同一拍的数据,约束上一般是目的时钟的一个或者半个周期,最严格的是源和目的的最快时钟周期的一半。比如总线跨时钟,假设是3bit信号,如果仅仅设置异步,那么1bit可能是1cycle到达,1bit可能是2cycle到达,还有1bit可能是3cycle到达,这个时候跨时钟采样的就不是源端同一拍的数据,如果设计容忍度很高,比如是静态的,那么没有问题,

3、当然一般多比特跨时钟域, 都直接用异步FIFO,生成IP核时据说,自带格雷码同步信号pathset_max_delay $source_clk_period, 的约束。

4、如果只set_false_path, 那么综合工具不会把对应的CDC路径看成所谓的“timing path”,会认为这条路径的timing无所谓,会可能预先插入很多不必要的cell。更重要的是,当后端的人实际layout的时候,也会认为这是false path,因此可能会因为芯片P/R空间不够,或者走线不够balance 或者局部power没法收敛等等原因,最终把所关注的这些CDC path拉的很长或者很散,甚至能在layout里面走多层或者对角线。你可以在相关的PT setup timing report里会见到drive强度很大(比如D16D32 etc)的一坨BUF,或冷不丁蹦出几个延时很长(好几百ps)的delay cell。对于false path,会导致工具理解设计时有误,因此才用set_max_delay做显式的延时约束

5、我觉得是在整个封装好的FIFO外的两侧是可以直接设置为set_false_path。在FIFO内部格雷码地址信号跨时钟域两侧是最好设置为set_max_delay