Xilinx OFFSET偏移约束略谈

-=c00s19n=-

coosign#sohu.com

2011年5月29日

 

Xilinx ISE约束除了Period约束,最基本的应该就是OFFSET约束(偏移约束)了。

下面分条目简单说一下OFFSET如何应用(下文主要围绕OFFSET IN展开讨论)。

(1)OFFSET约束基本概念

可以概括为三大注意点:

(a)OFFSET约束是用来约束数据和时钟之间的时延关系。

(b)它只能用于与FPGA管脚(PAD)相连的信号,不能用于内部信号。

(c)它告诉ISE布局布线工具,外部时钟和数据输入输出管脚之间的时序关系。

Xilinx OFFSET偏移约束略谈_第1张图片

 

当然,如果我只是简单的列出上面三条,不解释的话,仍然会给读者带来重大误解。

 

先给出UCF文件中的约束代码:

TIMEGRP "data" OFFSET = IN 2ns BEFORE "sysclk";

其中"data"是一组输入信号的组名,sysclk是输入时钟管脚名字。

这个2ns究竟是什么含义呢?

请看下图:

Xilinx OFFSET偏移约束略谈_第2张图片

 

2ns的含义,就是告诉ISE,在时钟信号和数据信号进入FPGA之前,它们之间的时延是2ns。用一句拗口的话来说就是:在时钟信号沿来之前的2ns,数据准备好。说的事情就是上图给出的时序图。因此,OFFSET约束并不是叫ISE布线工具在FPGA内部给你实现一个2ns的时延。那么ISE布线工具知道了输入时钟、数据信号之间的时延之后,能干什么呢?

 

(2)OFFSET约束的作用

OFFSET约束作用有3个,

(a)计算信号、时钟在FPGA内部的时延,给出准确的时序报告

(b)根据UCF中指定的时延关系,去调整输入信号到达同步单元的时间。

(c) b是针对Offset In而言,同理针对Offset Out,会调整输出信号到达输出管脚的时间。

 

仍然以上图为例说明,综合实现工具将努力使得数据信号、时钟信号到达同步单元的相对延迟+FPGA外部本来的延时,不会超过一个时钟周期。并在布线完后会给出数据路径和精确时延报告。

例如,经过FPGA内部到达同步单元的时序关系变为:

Xilinx OFFSET偏移约束略谈_第3张图片

 

 

这样就会出现时序错误了。

 

那么,很自然地会想到:我怎么知道信号进入FPGA之前的时延呢?

 

(3)如何准确地知道时钟和数据之间的时延关系?

以ADC+FPGA为例,FPGA作为ADC信号的接口,接收ADC采集的数据。这时候需要看ADC芯片手册查找相关参数,ADC芯片手册会给出其输出时钟和数据之间的相对关系。

下面以国半的ADC16DV160为例,假定它的输出数据和输出时钟都连接到FPGA上,而且在PCB板上的走线等长(实际工程师在设计PCB时,肯定是这么做的)。

 

Xilinx OFFSET偏移约束略谈_第4张图片

 

 

 

当采样频率是160MHz的时候,Tsu=1.57ns, Th=1.55ns。

看它的时序图也能看出来,输出的时钟对应着数据的中间位置。

因此,对于上升沿采样的数据而言,其OFFSET约束应该这么写:

NET "adc_clk_p" TNM_NET = adc_clk_p;

TIMESPEC TS_adc_clk_p = PERIOD "adc_clk_p" 160 MHz HIGH 50%;

 

##OFFSET IN

NET "adc_data <*>" TNM = " data";  ##adc_data<0>等等表示输入管脚名

 

TIMEGRP " data " OFFSET = IN 1.57ns BEFORE "adc_clk_p";

 

写上这些约束,大家要养成查看时序报告的习惯。时序报告会告诉你这些时序满足或者不满足。在实际中,如果ISE的时序报告告诉你能够满足你的时序约束,然而FPGA程序在实际运行的时候却发现存在时序问题(例如ADC采集信号有毛刺等),这说明你在UCF中指定的时延关系并不正确!

初学者常犯的一个错误,时序报告告诉你OFFSET IN约束无法满足,会去修改OFFSET IN的时延值,使得布线工具不再报时序错误;另一种错误是,以为把这个时延值写的越小,FPGA程序的时钟频率能跑的越快。

因此,当我们清楚地知道OFFSET约束语句中这个时延值代表的真正含义时,就不会再做这两种无用功了(PS:当然,既然改了时延值,就会更改FPGA布线,也有瞎猫碰到死耗子——碰巧解决了实际问题的事情发生。但我们必须知道那是不对滴)。

 

(4)OFFSET约束怎么之前还加上周期约束

上面的例子中,约束了adc_clk_p时钟信号的周期。

这是必须的。如果你不告诉ISE综合布线工具关于时钟周期的信息,OFFSET约束会被忽略。

很自然的,布线工具需要知道时钟信号的周期,这样它才能努力使得数据信号、时钟信号到达同步单元的相对延迟+FPGA外部本来的延时,不会超过一个时钟周期。

此外,说明一下:

TIMESPEC TS_adc_clk_p = PERIOD "adc_clk_p" 160 MHz HIGH 50%;

High 50%,High表明了ISE在计算时延值时,是以时钟上升沿作为时间0点,50%也是用于计算时延时用的(双沿时用得着)。并不是说要去约束FPGA内部这个时钟要达到50%的占空比,约束第一个进入的时钟是上升沿,并不是这个意思。

因此,定义了时间0点,也就存在Before和After之说了,也就存在时延的正值、负值之说了。 

 

(5)双沿输入的情况下怎么约束

在第3条中的例子,就是这种情况,ADC16DV160输出的数据是DDR的,作为16bit的ADC,其上升沿输出偶数bit数据,下降沿输出奇数bit数据;这样可以节省ADC输出的位宽。

由于OFFSET IN的约束随着ISE版本的升级,语法也不断的发生变化。针对目前我用的ISE12,Xilinx推荐的规范写法如下:

NET "adc_clk_p" TNM_NET = adc_clk_p;

TIMESPEC TS_adc_clk_p = PERIOD "adc_clk_p" 160 MHz HIGH 50%;

 

##OFFSET IN

NET "adc_data_I_p<*>" TNM = "adc_data";  

NET "adc_data_Q_p<*>" TNM = "adc_data";

NET "adc_data_I_n<*>" TNM = "adc_data";

NET "adc_data_Q_n<*>" TNM = "adc_data";

 

TIMEGRP "adc_data" OFFSET = IN 1.57ns VALID 1.55ns  BEFORE "adc_clk_p" RISING;

TIMEGRP "adc_data" OFFSET = IN 1.57ns VALID 1.55ns  BEFORE "adc_clk_p" FALLING;

 

注意:使用了RISING和FALLING的关键字。此外,差分时钟输入,我只选择了其中P管脚信号adc_clk_p进行约束。ISE能够把这个约束传递到BUFG和DCM。

关于双沿的讨论,还可以参考如下链接的信息:

http://myfpgablog.blogspot.com/2009/10/ddr-offset-inout-constraints-with-dcm.html

http://forums.xilinx.com/t5/Timing-Analysis/OFFSET-IN-DDR-timing-constraints-again/td-p/54507

 

(6)OFFSET约束时序不满足怎么办?

经常会碰到这种问题。

解决方法有两种:

(a)使用DCM的移相功能

(b)使用IDELAY

Xilinx自带的IP Core,诸如RocketIO/MIG等等,都会用上IODELAY。对于一般用户,自己写的代码,最常用的应该是采用DCM。相位的设置可以根据布线结果给出的时序余量来确定。相位值如果采用Fixed,可能无论怎么调都不一定能满足要求,毕竟修改了代码,每一次布线的结果并一定只改动了DCM部分。

DCM有动态调整相位的功能,可以派上用场。

DCM动态调相用到了PSEN,PSINCDEC,PSCLK,PSDONE这几个信号。

这些端口默认是灰色的,要选中VARIABLE_POSITIVE/CENTER等之后,才会出现。

控制很简单,出一个PSEN单周期信号,如果PSINCDEC为低,则相位增加1个;反之,降低一个相位。