由于该系列文章阅读有顺序性,所以请跳转至该系列文章第一篇从头开始阅读,并按照文章末尾指示按顺序阅读,否则会云里雾里,传送门在此: https://blog.csdn.net/qq_33486907/article/details/89380368 《TIMING_01 时序约束与时序分析引导篇》
目录
1. 基本时钟周期约束
1.1 时钟周期约束的性质
1.2 Primary Clocks主时钟
1.3 Generated Clocks生成时钟
1.4 时钟分组约束
从本篇文章开始,正式进入时序约束,本文以XILINX VIVADO环境进行讲解,包括后续的时序分析。在时序约束约束环节VIVADO和Quaetuse II两大平台是一致的,都是基于SDC标准的约束,所以学习时序约束环节时,不必为了采用何种开发环境困扰。
基本时钟周期约束的作用有两个:(1)告诉VIVADO需要在FPGA中运行时钟的特性,主要用于约束FPGA内部寄存器之间所需要达到的时序性能;(2)可能以此基本时钟周期约束为基础进行其他的约束,作为其他约束的基础;
约束所覆盖的路径如下:
基本时钟周期约束的性质包含:时钟周期、占空比以及相位;
主时钟(Primary Clocks)一般是FPGA外部芯片,如晶振提供的时钟,通过FPGA引脚输入,Vivado进行时序分析时,以主时钟的源端点作为延时计算起始点(0ns点)。
示例1:从外部引脚引入的时钟
约束如下:
create_clock -period 10.000 -name sysclk -waveform {0.000 5.000} [get_ports sysclk]
对于主时钟的利用不要局限于一个驱动绝大多数资源的时钟,对于只驱动部分资源的时钟也属于该类,同样适用于这条约束,例如:ADC的采样随路时钟;
对于差分输入形式的时钟,只需要对P脚使用约束即可;
示例2:高速收发器提供的时钟
约束如下:
create_clock -period 3.330 -name rxclk -waveform {0.000 1.660} [get_pins gt0/RXOUTCLK]
生成时钟的种类:(1)用户定义的时钟;(2)由MMCMx/PLL or BUFR、ODDR等推断出的时钟;
示例1:用户定义的时钟
方法1:
约束如下:
(1)首先这类约束要先指定源时钟
create_clock -period 10.000 -name clkin -waveform {0.000 5.000} [get_ports clkin]
(2)然后对生成时钟进行约束
方法1:将主时钟端点作为源
create_generated_clock -name clkdiv2 -source [get_ports clkin] -divide_by 2\[get_pins REGA/Q
方法2:将REGA时钟作为源
create_generated_clock -name clkdiv2 -source [get_pins REGA/C] -divide_by 2 \[get_pins REGA/Q]
方法2:
对于与源时钟有固定相位关系的生成时钟也可以这样约束:
create_generated_clock -name clkdiv2 -source [get_pins REGA/C] \-edges {1 3 5} [get_pins REGA/Q]
示例2:由MMCMx/PLL or BUFR /ODDR的推断出的时钟
推断时钟案例1:MMCMx推断的时钟
对于这类时钟在不需要使用它作为其余约束源时,可以不进行约束,只需要约束primary clock,VIVADO后会自动推导生成时钟的约束;
但是要使用这类约束时就需要重新对生成时钟进行重新命名,其意义在于便于后续约束的引用;
约束如下:
(1)首先对源时钟进行约束
create_clock -period 10.000 -name clkin -waveform {0.000 5.000} [get_ports clkin]
(2)对CLKOUT的时钟进行重命名
create_generated_clock -name clkout [gee_pins clkip/mmcm0/CLKOUT]
这样以后以此生成时钟为基础的约束即可使用clkout为源时钟名称进行约束了;但是这种做法有局限性,如果自动生成的时钟已被重新命名,且后续约束采用了该名称,那么更改时钟名称则会报错;因此,为了保持约束的独立性,使时钟不受命名干扰可采用如下方式,但显然这样略显繁琐,不便于书写阅读;
get_clocks –of_objects [get_pins clkip/mmcm0/CLKOUT]
get_clocks –of_objects [get_nets clkip/cpuclk]
这种不便SDC提供了另外一种方式“虚拟时钟”来解决这个问题,后面单独一个章节来讲解;
推断时钟案例2:ODDR生成的随路时钟
在源同步应用中,时钟由源端(发送数据端)重新生成,并随同步数据传送给目的端(捕获数据端)。这个时钟称为随路时钟,通常由ODDR 或 OSERDES生成,需要通过create_generated_clock对该时钟约束,以便创建输出延迟约束(set_output_delay)时将器作为参考时钟使用,如图:
约束如下:
create_generated_clock -name fwd_clk –multiply_by 1 -source [get_pins ODDR_inst/C] \[get_ports clkout]
在源同步设计中,还有一种情形也较为常见,即输出时钟与发送数据时钟相反,而这种反向也是通过ODDR实现的,此时ODDR的D1端口为“0”,而D2端口为“1”,如图:
输出时钟域发送数据时钟相反,约束如下:
(1)约束源时钟
create_clock -period 10.000 -name clk -waveform {0.000 5.000} [get_ports clk]
(2)约束生成时钟
create_generated_clock –name fwd_clk –invert –divide_by 1 -source [get_ports clk] \[get_ports fwd_clk]
–invert表明了输出时钟与源时钟反向,其中使用–divide_by而非–multiply_by,意在说明两者的默认值为1,–divide_by、–multiply_by和-edges三者必须存在其一;
VIVADO时序分析工具是默认设计中的所有时钟是同步的,对于异步时钟我们需要做出以下约束,告诉VIVADO这些时钟是异步的。
create_clock -period 10.000 -name clka -waveform {0.000 5.000} [get_ports clka]
create_clock -period 14.000 -name clkb -waveform {0.000 7.000} [get_ports clkb]
set_clock_groups -asynchronous -group [get_clocks clka] -group [get_clocks clkb]
对于使用了CLKMUX的统一路径上不同频率的时钟也采用该方法,如图所示:
create_clock -period 10.000 -name clk0 -waveform {0.000 5.000} [get_ports clk0]
create_clock -period 14.000 -name clk1 -waveform {0.000 7.000} [get_ports clk1]
set_clock_groups –logically_exclusive \ -group [get_clocks clk0] -group [get_clocks clk1]
不要急着跑,干货在后面,下一篇文章传送门在此:
https://blog.csdn.net/qq_33486907/article/details/94429887
本系列博客对应的完整《时序约束手册》传送在此,扫一扫获取下载链接:
或直接点击下载链接:https://item.taobao.com/item.htm?spm=a1z38n.10677092.0.0.22131debncNwzA&id=588531553802