跨时钟域时序约束

在一个FPGA设计里面,经常会用到多个全局时钟,而这些全局时钟是通过几个外部时钟晶振从全局时钟管脚(GC)输入后,再经过一些时钟管理模块产生的(如DCM、PLL、MMCM等)。一般来说,小型设计只需要一个外部晶振作为时钟输入即可,大型设计也很少超过5个外部晶振输入。一个外部时钟输入到FPGA的时钟管理模块以后,通过倍频、分频、相位偏移等手段,可以产生多个内部时钟,这些时钟在频率或相位上互不相同,但又有一定的关联。不同管脚输入的时钟经过时钟管理模块处理之后,尽管不是同源时钟,也有可能频率上存在一定的关系。

对于Xilinx FPGA,如果内部时钟是通过时钟管理模块产生的,那么只要约束输入时钟的周期(用关键字PERIOD),ISE在Implement(实现)的时候,会自动将输入时钟的周期约束传递到时钟管理模块的输出时钟,不需要用户自己定义每个输出时钟的频率。同时,ISE会自动识别同一时钟管理模块输出的各个时钟之间频率与相位关系,并且在Implement完成后分析各个时钟域之间的走线是否满足时序。这个功能可以省去我们对每一个输出时钟进行约束的辛苦。当然,如果输入时钟有除了周期约束之外的其他约束,ISE就不会自动的将时钟管理模块的输入时钟约束传递到各个输出时钟,各个输出时钟必须分别约束各自的时钟周期。

使用ISE自动根据输入时钟对同一个时钟管理模块输出的时钟进行时钟约束时,如果设计中不同输出时钟之间有大量的跨时钟域布线(异步线路),ISE会对每一条异步线路进行分析。例如,一个40M的时钟域和一个200M的时钟域,当从40M时钟域跨域到200M时钟域时,异步线路的总延时(包括时序逻辑的内部响应时间、布线延迟以及LUT的响应时间)限制在5ns以内;当从200M时钟域跨越到40M时钟域时,异步线路的总延时为25ns。实际上,从40M时钟域跨越到200M时钟域,异步线路的总延迟只要限制在25ns之内即可,因为处于40M时钟域的时序逻辑(如FF、Block RAM等),每25ns才会更新一次。由此可见,ISE自动生成的时钟约束过于苛刻,上例中如果存在大量的从40M时钟域跨越到200M时钟域的线路,那么给MAP和PAR实现过程的压力会很大。在大型的、资源占用率比较高的设计里面,时序的过约束会造成设计很难实现。

因此,如果同一个时钟管理模块输出的多个异步时钟时间之间有大量的跨时钟域布线,那么博主强烈建议,不要使用由输入时钟衍生出来的输出时钟时序约束,改为手动的对每一个输出时钟进行约束。当然,如果输出时钟之间的确是有关系的,如同频不同相且相位关系固定,那么就需要在时序约束中指定它们的关系。对于那些没有直接关系的输出时钟(频率或相位无关),需要约束两两之间的最大布线延迟,可以用两者中时钟周期比较大的作为它们的总线路延迟,如40M和200M时钟,用25ns作为它们的总线路延迟。

对于从不同时钟管理模块输出的异步时钟,ISE不会自动产生两两之间的时序约束。如果两个不同时钟管理模块输出的时钟在频率和相位上有关系,例如其中一个时钟的频率是另一个时钟频率的一半,且两者相位相同,那么这种相互关系就需要在两者的时序约束中体现出来。如果两个不同时钟管理模块输出的时钟在时钟和频率上毫不相干,为了保证这种异步时钟之间的走线不会太长,也需要约束两两之间的最大布线延迟。最大布线延迟的取值同样是去取两者之间最大的那个时钟周期。

设定两个不相关的异步时钟的最大延迟时,不管异步时钟是不是由同一个时钟管理模块产生,都只需约束异步线路的最大布线延迟,而不需将异步线路中时序逻辑与LUT的响应时间纳入时序约束的范围。最大布线延迟约束使用From-To时序指定方式,再添加DATAPATHONLY关键字表明只约束布线延迟。

以下给出一个不相关异步时钟之间的时序约束的例子:
下图中时钟CLKA和CLKB为不相关的异步时钟,CLKA为源时钟,时钟周期为25ns,CLKB为目的时钟,时钟周期为8ns。CLKA与CLKB之间的路径Data_A_B为异步路径,为了约束Data_A_B的布线延迟,需要在ucf文件中添加以下跨时钟约束:

图一.跨时钟域路径

NET "CLKA" TNM_NET = "GRP_A";
NET "CLKB" TNM_NET = "GRP_B";
TIMESPEC TS_Path_A_B = FROM "GRP_A" TO "GRP_B" 5 ns DATAPATHONLY;

设定两个相关的异步时钟的时序约束时,一般是先指定主时钟的频率和占空比,然后另一个时钟的频率和相位以主时钟的频率和相位作为参考。以下给出一个相关异步时钟时序约束的例子:
Clk1X的时钟周期为5ns,Clk2X180的时钟周期为Clk1X的一半,Clk2X180的时钟相位与Clk1X的时钟相位的偏差为1.25ns。需要在ucf文件中添加这两个异步时钟的时序约束,如下:
NET "Clk1X" TNM_NET = "Clk1X";
NET "Clk2X180" TNM_NET = "Clk2X180";
TIMESPEC "TS_Clk1X" = PERIOD "Clk1X" 5 ns;
TIMESPEC "TS_Clk2X180" = PERIOD "Clk2X180" TS_Clk1X/2 PHASE + 1.25 ns;

文章出自: http://blog.163.com/fpga_ip/blog/static/204443024201241182735568/