DC综合之CDC篇

简单的同步器:使用set_clock_groups命令就可以了,或者设置成set_flase_path,

但是对于格雷码的同步不行,false_path的优先级最高,很显然这么做会导致所有跨读写时钟域的路径全部不做时序分析,读写指针和相关控制逻辑也就失去了存在的意义。

之前组内讨论时发现,每回PT工具报出来的STA报告都会有很多异步时钟的path出现violation,这些path都做过CDC同步,因此在function上没有问题,有问题的是对于报出的violation该怎么样设置STA约束。

以前的做法是,对于报出来的path设置multicycle 2,因为既然是异步时钟域,那么就无法确定源寄存器Q端何时有效,designer自然就不能指望目的寄存器一个T内完成采样,设置multicycle必然是合理的但是有时即使multicycle 2也解决不了violation,又得设置得更大,比如multicycle 3。如此迭代,浪费不少时间。于是引发了一个讨论:能不能直接设置false path,一举屏蔽掉这种path的violation。

以下图异步fifo为例:

方框表示寄存器,A域时钟为clka。周期为Ta;B域时钟为clkb,周期为Tb。A域有pointer和data两个信息,B域需要根据A域的pointer(与B域的pointer相比较)来判断fifo中是否有了data,并将data采集到b域。由于A域中的pointer和data共域,所以必然在同一个Ta内ready。但是如果设置flase path,那么STA工具将不对AB域间的组合逻辑时序做任何限制,有可能布线非常长,时序很差,就会带来这样一种可能性:图中的控制path和数据path完全有可能不在同一个Tb内到达B域的寄存器,这样就会出错,比如控制path先到,B域认为fifo有了数据,但是因为数据path非常长,B域采到的是旧的data,而非新写进去的data。

CDC的设计与约束
CDC路径在FPGA设计中普遍存在,在设置相应的约束前,必须了解设计中采取了怎样的方法来处理跨时钟域路径。

简单同步器
对于单根跨时钟域路径,一般采用简单同步器(Simple Synchronizer),就是由至少两级CE端和Reset/Clear端接死的寄存器序列来处理。

这种情况下,为了更长的平均无故障时间MTBF(Mean Time Between Failures),需要配合一个ASYNC_REG的约束,把用作简单同步器的多个寄存器放入同一个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 ]

用FIFO隔离CDC
在总线跨时钟域的设计中,通常会使用异步FIFO来隔离。根据FIFO的实现方式不同,需要加入不同的XDC约束。

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

带有格雷码控制的FIFO
为了在亚稳态下做读写指针抽样也能正确判断空满状态,设计中也常用一种带有格雷码控制的FIFO来实现异步时钟域的隔离。计数器和读写指针等需要用 BRAM外部的逻辑搭建,这样的结构就不能简单约束set_clock_groups,还要考虑这些外部逻辑如何约束。

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

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

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

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

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


set_max_delay -from [get_cells …../rd_pntr_gc_reg[*]] -to [get_cells …../Q_reg_reg[*]] \
-datapath_only [get_property PERIOD $rd_clock]
set_max_delay -from [get_cells …../wr_pntr_gc_reg[*]] -to [get_cells …../Q_reg_reg[*]] \
-datapath_only [get_property PERIOD $wr_clock]

自2013.4开始,Vivado中还提供一个称作methodology_checks的DRC检查,其中包含有对此类异步FIFO的max delay约束与时钟域clock groups约束的冲突检查。

CDC约束方案的对比
CDC路径在FPGA设计中普遍存在,不少公司和研发人员都有自己偏爱的约束方式,这些方式通常有各自适用的环境,当然也各有利弊。

全部忽略的约束
最大化全部忽略CDC路径的约束,即采用set_clock_groups 或是set_false_path对时钟关系进行约束,从而对跨时钟域的路径全部忽略。
示例:set_clock_groups -asynchronous -group clkA -group clkB
优势:简单、快速、执行效率高。
劣势:会掩盖时序报告中所有的跨时钟域路径,容易误伤,不利于时序分析。

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

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

优势:简便、执行效率较高。

劣势:1) 需要特别留意是否设置了过于严格的约束,因为使用者经常会使用较快的时钟周期来约束跨时钟域路径 。2) 注意约束优先级的关系,是否跟设计中其它的约束有冲突。3) set_max_delay而没有配套设置set_min_delay的情况下,同一路径只做setup分析而不做hold分析。

逐条进行时序例外约束
对设计中的CDC路径分组或逐条分析,采用不同的时序例外约束,如set_false_path,set_max_delay和set_multicycle_path等来约束。
示例:set_false_path -from [get_cells a/b/c/*_meta*] -to [get_cells a/b/c/*_sync*]
优势:灵活、针对性好、便于时序分析和调试。

劣势:1) 逐条约束会占用大量时间来调试和分析,效率低下。2) 时序例外的优先级比较复杂,多种时序例外约束共存的情况下,很容易产生意想不到的冲突,进一步增加调试时间,降低效率。3) 这么做极容易产生臃肿的XDC约束文件,而且时序例外的执行更耗内存,直接导致工具运行时间变长。

我觉得如果是top level的话直接设一个set_max_delay就可以了,set_min_delay一般是后端中实现的时候出现的,可以暂时不考虑。具体要怎么设置set_max_delay要看你的specification,如果没有specification,就是想让他尽量快的话可以大致看一下你的关键路径里都有多少东西,根据这个选择一个合适的值。

猜你喜欢

转载自blog.csdn.net/fengxiaocheng/article/details/82120103
今日推荐