2.3 时钟设计思想
2.3.1 工作时钟模型
无论是用离散逻辑、可编程逻辑,还是用全定制硅器件实现的任何数字设计,为了成功地操作,可靠的时钟是非常关键的。设计不良的时钟在极限的温度、电压或制造工艺的偏差情况下将导致错误的行为,并且调试困难、花销很大。在设计FPGA/CPLD时通常采用几种时钟类型。时钟可分为如下4种类型:全局时钟、门控时钟、多级逻辑时钟和波动式时钟。多时钟系统能够包括上述4种时钟类型的任意组合。
无论采用何种方式,电路中真实的时钟树也无法达到假定的理想时钟,因此必须依据理想时钟,建立一个实际工作时钟模型来分析电路,这样才可以使电路的实际工作效果和预期的一样。在实际的时钟模型中,要考虑时钟树传播中的偏斜、跳变和绝对垂直的偏差,以及其他一些不确定因素。
对于寄存器而言,当时钟工作沿到来时,它的数据端应该已经稳定,这样才能保证时钟工作沿采样到数据的正确性,这段数据的预备时间称为建立时间(setup time)。
采样应该在时钟工作沿过去后保持一段时间,这段时间称为保持时间(hold time),具体的时钟如图2-18所示。其中网络延迟是指时钟的传播延时,以及电平跳变不理想导致的延时。保持时间和建立时间都是相对于实际时钟跳变而言的,因此在确定电路时序时,必须要考虑到这些因素,使建立时间和保持时间符合要求。
图2-18 工作时钟模型
为了使电路正常工作,建立时间和保持时间应该分别满足:
其中,tclock Q max是时钟沿变化到数据输出端变化的最慢变化时间,tlogic max是寄存器间组合逻辑的最大可能延时,tclock Q min和tlogic min表示最快情况时的可能延时。在考虑建立保持时间时,应该考虑时钟树向后偏斜的情况,在考虑建立时间时应该考虑时钟树向前偏斜的情况。在进行仿真时,最大延时用来检查建立时间,最小延时用来检查保持时间。
2.3.2 全局时钟
对于一个设计项目来说,全局时钟(或同步时钟)是最简单和最可预测的时钟。在PLD/FPGA设计中最好的时钟方案是由专用的全局时钟输入引脚驱动的单个主时钟去钟控设计项目中的每一个触发器。只要可能就应尽量在设计项目中采用全局时钟。PLD/FPGA都具有专门的全局时钟引脚,它直接连到器件中的每一个寄存器。这种全局时钟提供器件中最短的时钟到输出的延时。
如图2-19 所示为全局时钟的实例。图2-19 中的定时波形表示触发器的数据输入D[1,…,3]应遵守建立时间和保持时间的约束条件。建立时间和保持时间的数值在PLD数据手册中给出,也可用软件的定时分析器计算出来。如果在应用中不能满足建立时间和保持时间的要求,则必须用时钟同步输入信号。
图2-19 全局时钟
2.3.3 门控时钟
在许多应用中,整个设计项目都采用外部的全局时钟是不可能或不实际的。PLD具有乘积项逻辑阵列时钟(即时钟是由逻辑产生的),允许任意函数单独地钟控各个触发器。然而,当用阵列时钟时,应仔细地分析时钟函数,以避免毛刺。
通常用阵列时钟构成门控时钟。门控时钟常常同微处理器接口有关,用地址线去控制写脉冲。然而,每当用组合函数钟控触发器时,通常都存在着门控时钟。如果符合下述条件,门控时钟可以像全局时钟一样可靠地工作。
(1)驱动时钟的逻辑必须只包含一个“与”门或一个“或”门。如果采用任何附加逻辑在某些工作状态下,则会出现因竞争产生的毛刺。
(2)逻辑门的一个输入作为实际的时钟,而该逻辑门的所有其他输入必须当成地址或控制线,它们遵守相对于时钟的建立时间和保持时间的约束。
图2-20和图2-21 是可靠的门控时钟的实例。在图2-20 中,用一个“与”门产生门控时钟;在图2-21中,用一个“或”门产生门控时钟。在这两个实例中,引脚nWR和nWE为时钟引脚,引脚ADD[0,…,3]是地址引脚,两个触发器的数据是信号D[1,…,n]经随机逻辑产生的。
图2-20 “与”门门控时钟
图2-20的波形图显示出有关的建立时间和保持时间的要求。这两个设计项目的地址线必须在时钟保持有效的整个期间内保持稳定(nWR和nWE是低电平有效)。如果地址线在规定的时间内未保持稳定,则在时钟上会出现毛刺,造成触发器发生错误的状态变化。另一方面,数据引脚D[1,…,n]只要求在nWR和nWE的有效边沿处满足标准的建立时间和保持时间的规定。
往往可以将门控时钟转换成全局时钟以改善设计项目的可靠性。如图2-21所示为如何用全局时钟重新设计图2-20 的电路。地址线控制D触发器的使能输入,许多PLD设计软件,如MAX+plusII软件都提供这种带使能端的D触发器。当ENA为高电平时,D输入端的值被钟控到触发器中;当ENA为低电平时,维持现在的状态。
图2-21 “或”门门控时钟
图2-22中重新设计的电路的定时波形表明地址线不需要在nWR有效的整个期间内保持稳定,而只要求它们和数据引脚一样符合同样的建立时间和保持时间,这样对地址线的要求就少很多。
图2-22 “与”门门控时钟转化为全局时钟
图2-23给出一个不可靠的门控时钟的例子。3位同步加法计数器的RCO输出用来钟控触发器。然而,计数器给出的多个输入起到时钟的作用,这违反了可靠门控时钟所需的条件之一。在产生RCO信号的触发器中,没有一个能考虑为实际的时钟线,这是因为所有触发器在几乎相同的时刻发生翻转。而我们并不能保证在PLD/FPGA内部QA、QB、QC到D触发器的布线长短一致,因此如图2-23的时间波形所示,在计数器从3计到4时,RCO线上会出现毛刺(假设QC到D触发器的路径较短,即QC的输出先翻转)。
图2-23 不可靠的门控时钟
(定时波形示出在计数器从3到4改变时,RCO信号出现毛刺过程)
图2-24给出一种可靠的全局钟控的电路,它是图2-23不可靠计数器电路的改进,RCO控制D触发器的使能输入。这个改进不需要增加FPGA的逻辑单元。
图2-24 不可靠的门控时钟转换为全局时钟
2.3.4 多级逻辑时钟
当产生门控时钟的组合逻辑超过一级(即超过单个的“与”门或“或”门)时,设计项目的可靠性变得很困难。即使样机或仿真结果没有显示出静态险象,但实际上仍然可能存在着危险。通常,不应该用多级组合逻辑去钟控FPGA设计中的触发器。
图2-25给出一个含有险象的多级时钟的例子。时钟是由SEL引脚控制的多路选择器输出的。多路选择器的输入是时钟(CLK)和该时钟的2 分频(DIV2)。由图2-25 的定时波形图看出,在两个时钟均为逻辑1的情况下,当SEL线的状态改变时,存在静态险象。险象的程度取决于工作的条件。多级逻辑的险象是可以去除的,如可以插入“冗余逻辑”到设计项目中。然而,PLD/FPGA编译器在逻辑综合时会去掉这些冗余逻辑,使验证险象是否真正被去除变得困难。为此,必须应寻求其他方法来实现电路的功能。
图2-25 有静态风险的多级时钟
图2-26给出图2-25 电路的一种单级时钟的替代方案。图中SEL引脚和DIV2信号用于使能D触发器的使能输入端,而不是用于该触发器的时钟引脚。采用这个电路并不需要附加FPGA的逻辑单元,但工作却可靠多了。不同的系统需要采用不同的方法去除多级时钟,并没有固定的模式。
图2-26 无静态风险的多级时钟
(该电路逻辑上等效于图2-25,但却可靠得多)
2.3.5 行波时钟
另一种流行的时钟电路是采用行波时钟,即一个触发器的输出用做另一个触发器的时钟输入。如果仔细地设计,行波时钟可以像全局时钟一样可靠工作。然而,行波时钟使与电路有关的定时计算变得很复杂。行波时钟在行波链上各触发器的时钟之间产生较大的时间偏移,并且会超出最坏情况下的建立时间、保持时间和电路中时钟到输出的延时,使系统的实际速度下降。
用计数翻转型触发器构成异步计数器时常采用行波时钟,一个触发器的输出钟控下一个触发器的输入,如图2-27所示。同步计数器通常是代替异步计数器的更好方案,这是因为两者需要同样多的宏单元,而同步计数器有更短的时钟输入到输出延时。图2-28给出具有全局时钟的同步计数器,它和图2-27功能相同,用了同样多的逻辑单元实现,却有较快的时钟输入到输出的时间。几乎所有PLD开发软件都提供多种多样的同步计数器。
图2-27 行波时钟
图2-28 行波时钟转换成全局时钟
2.3.6 多时钟系统
许多系统要求在同一个FPGA内采用多时钟。最常见的例子是两个异步微处理器之间的接口,或微处理器和异步通信通道的接口。由于两个时钟信号之间要求一定的建立时间和保持时间,所以上述应用引进了附加的定时约束条件。它们也会要求将某些异步信号同步化。
图2-29给出一个多时钟系统的实例。CLK A用以钟控REG A,CLK B用于钟控REG B,由于REG A驱动着进入REG B的组合逻辑,故CLK A的上升沿相对于CLK B的上升沿有建立时间和保持时间的要求。由于REG B不驱动馈送到REG A的逻辑,CLK B的上升沿相对于CLK A没有建立时间的要求。此外,由于时钟的下降沿不影响触发器的状态,所以CLK A和CLK B的下降沿之间没有时间上的要求。如图2-30所示,电路中有两个独立的时钟,可是在它们之间的建立时间和保持时间的要求是不能保证的。在这种情况下,必须将电路同步化。图2-30 给出REG A的值(如何在使用前)与CLK B同步化。新的触发器REG C由CLK B触控,保证REG C的输出符合REG B的建立时间。然而,这个方法使输出延时了一个时钟周期。
图2-29 多时钟系统
(定时波形示出CLK A的上升沿相对于CLK B的上升沿有建立时间和保持时间的约束条件)
图2-30 具有同步寄存器输出的多时钟系统
(如果CLK A和CLK B是相互独立的,则REG A的输出必须在它馈送到REG B之前,用REG C同步化)
在许多应用中只将异步信号同步化还是不够的,当系统中有两个或两个以上非同源时钟的时候,数据的建立时间和保持时间很难得到保证,人们将面临复杂的时间问题。最好的方法是将所有非同源时钟同步化。
2.3.7 Xilinx FPGA中的时钟资源
1. 时钟资源
全局时钟布线资源一般使用特殊工艺实现,并设计了专用时钟缓冲与驱动结构,从而使全局时钟到达芯片内部的所有可配置单元、I/O 单元和块RAM 的时延和抖动一致。目前,大多数FPGA内部都集成了硬DLL(Delay-Locked Loop)或PLL(Phase-Locked Loop),用以完成时钟的高精度、低抖动的倍频、分频、占空比调整和移相等。其中,Xilinx FPGA主要集成DLL,而Atlera FPGA集成的是PLL。Xilinx芯片中时钟相关硬核有IBUFG、IBUFGDS、BUFG、BUFGP、BUFGCE、BUFGMUX、DCM等。
(1)IBUFG:即输入全局缓冲,是与专用全局时钟输入引脚相连接的首级全局缓冲。所有从全局时钟引脚输入的信号必须经过IBUFG单元,否则在布局布线时会报错。IBUFG支持AGP、CTT、GTL、GTLP、HSTL、LVCMOS、LVDCI、LVDS、LVPECL、LVTTL、PCI、PCIX等多种I/O标准。IBUFG原语例化方式如下。
-- IBUFG :In order to incorporate this function into the design, -- VHDL :the following instance declaration needs to be placed -- instance :in the architecture body of the design code. The -- declaration :instance name (IBUFG inst)and/or the port declarations -- code :after the "=>"assignment maybe changed to properly -- :reference and connect this function to the design. -- :All inputs and outputs must be connected. -- Library :In addition to adding the instance declaration,a use -- declaration :statement for the UNISIM.vcomponents library needs to be -- for :added before the entity declaration. This library -- Xilinx :contains the component declarations for all Xilinx -- primitives :primitives and points to the models that will be used -- :for simulation. -- Copy the following two statements and paste them before the -- Entity declaration,unless they already exist. Library UNISIM; use UNISIM.vcomponents.all; --<-----Cut code below this line and paste into the architecture body----> -- IBUFG:Global Clock Buffer (sourced by an external pin) -- Xilinx HDL Language Template,version 10.1 IBUFG inst :IBUFG
generic map ( IOSTANDARD=>"DEFAULT") port map ( O=>O,-- Clock buffer output I=>I -- Clock buffer input (connect directly to top-level port) ); -- End of IBUFG inst instantiation
(2)IBUFGDS:是IBUFG的差分形式。当信号从一堆差分全局时钟引脚输入时,必须使用IBUFGDS 作为全局时钟输入缓冲。IBUFGDS 支持 BLVDS、LDT、LVDSEXT、LVDS、LVPECL、ULVDS等多种I/O标准。IBUFGDS原语例化方式如下。
-- IBUFGDS :In order to incorporate this function into the design, -- VHDL :the following instance declaration needs to be placed -- instance :in the architecture body of the design code. The -- declaration :instance name (IBUFGDS inst)and/or the port declarations -- code :after the "=>"assignment maybe changed to properly -- :reference and connect this function to the design. -- :All inputs and outputs must be connected. -- Library :In addition to adding the instance declaration,a use -- declaration :statement for the UNISIM.vcomponents library needs to be -- for :added before the entity declaration. This library -- Xilinx :contains the component declarations for all Xilinx -- primitives :primitives and points to the models that will be used -- :for simulation. -- Copy the following two statements and paste them before the -- Entity declaration,unless they already exist. Library UNISIM; use UNISIM.vcomponents.all; --<-----Cut code below this line and paste into the architecture body----> -- IBUFGDS:Differential Global Clock Buffer(sourced by an external pin) -- Virtex-II/II-Pro/4/5,Spartan-3/3E/3A -- Xilinx HDL Language Template,version 10.1 IBUFGDS inst :IBUFGDS generic map ( IOSTANDARD=>"DEFAULT")
port map ( O=>O,-- Clock buffer output I=>I,-- Diff p clock buffer input IB=>IB -- Diff n clock buffer input ); -- End of IBUFGDS inst instantiation
(3)BUFG:即全局缓冲,它的输入是IBUFG的输出,BUFG的输出到大FPGA内部的IOB、CLB、Block SelectRAM的时钟延迟和抖动最小。BUFG原语例化方式如下。
-- BUFG :In order to incorporate this function into the design, -- VHDL :the following instance declaration needs to be placed -- instance :in the architecture body of the design code. The -- declaration :instance name (BUFG inst)and/or the port declarations -- code :after the "=>"assignment maybe changed to properly -- :reference and connect this function to the design. -- :All inputs and outputs must be connected. -- Library :In addition to adding the instance declaration,a use -- declaration :statement for the UNISIM.vcomponents library needs to be -- for :added before the entity declaration. This library -- Xilinx :contains the component declarations for all Xilinx -- primitives :primitives and points to the models that will be used -- :for simulation. -- Copy the following two statements and paste them before the -- Entity declaration,unless they already exist. Library UNISIM; use UNISIM.vcomponents.all; --<-----Cut code below this line and paste into the architecture body----> -- BUFG:Global Clock Buffer (source by an internal signal) -- All Devices -- Xilinx HDL Language Template,version 10.1 BUFG inst :BUFG port map ( O=>O,-- Clock buffer output I=>I -- Clock buffer input
);
(4)BUFGCE:即带有时钟使能端的全局缓冲。它有一个输入端I、一个使能端CE、一个输出端O。仅当BUFGCE的使能端CE有效(高电平)时,BUFGCE才有输出。BUFGCE原语例化方式如下。
-- BUFGCE :In order to incorporate this function into the design, -- VHDL :the following instance declaration needs to be placed -- instance :in the architecture body of the design code. The -- declaration :instance name (BUFGCE inst)and/or the port declarations -- code :after the "=>"assignment maybe changed to properly -- :reference and connect this function to the design. -- :All inputs and outputs must be connected. -- Library :In addition to adding the instance declaration,a use -- declaration :statement for the UNISIM.vcomponents library needs to be -- for :added before the entity declaration. This library -- Xilinx :contains the component declarations for all Xilinx -- primitives :primitives and points to the models that will be used -- :for simulation. -- Copy the following two statements and paste them before the -- Entity declaration,unless they already exist. Library UNISIM; use UNISIM.vcomponents.all; --<-----Cut code below this line and paste into the architecture body----> -- BUFGCE:Global Clock Buffer with Clock Enable (active high) -- Virtex-II/II-Pro/4/5,Spartan-3/3E/3A -- Xilinx HDL Language Template,version 10.1 BUFGCE inst :BUFGCE port map ( O=>O,-- Clock buffer ouptput CE=>CE,-- Clock enable input I=>I -- Clock buffer input ); -- End of BUFGCE inst instantiation
(5)BUFGMUX:即全局时钟选择缓冲,它有两个输入端I0和I1,一个控制端S,一个控制端O。当S为低电平时,输出时钟为I0,反之为I1。需要指出的是,BUFGMUX的应用十分灵活,I0和I1两个输入时钟甚至可以为异步关系。BUFGMUX原语例化方式如下。
-- BUFGMUX :In order to incorporate this function into the design, -- VHDL :the following instance declaration needs to be placed -- instance :in the architecture body of the design code. The -- declaration :instance name (BUFGMUX inst)and/or the port declarations -- code :after the "=>"assignment maybe changed to properly -- :reference and connect this function to the design. -- :All inputs and outputs must be connected. -- Library :In addition to adding the instance declaration,a use -- declaration :statement for the UNISIM.vcomponents library needs to be -- for :added before the entity declaration. This library -- Xilinx :contains the component declarations for all Xilinx -- primitives :primitives and points to the models that will be used -- :for simulation. -- Copy the following two statements and paste them before the -- Entity declaration,unless they already exist. Library UNISIM; use UNISIM.vcomponents.all; --<-----Cut code below this line and paste into the architecture body----> -- BUFGMUX:Global Clock Buffer 2-to-1 MUX -- Virtex-II/II-Pro/4/5,Spartan-3/3E/3A -- Xilinx HDL Language Template,version 10.1 BUFGMUX inst :BUFGMUX port map ( O=>O,-- Clock MUX output I0=>I0,-- Clock0 input I1=>I1,-- Clock1 input S=>S -- Clock select input ); -- End of BUFGMUX inst instantiation
(6)BUFGP:相当于IBUFG加上BUFG。
(7)BUFGDLL:即全局缓冲延迟锁相环,相当于BUFG与DLL的结合。在早期的设计中经常使用,用以完成全局时钟的同步、驱动等功能。随着数字时钟管理单元(DCM)的普及应用,目前BUFGDLL的应用已经逐渐被DCM所取代。
(8)DCM:即数字时钟管理单元,主要完成时钟的同步、移相、分频、倍频、去抖动等。DCM与全局时钟有着密不可分的联系,为了达到最小的延迟和抖动,几乎所有的DCM应用都要使用全局缓冲资源。DCM 也可以用Xilinx ISE 软件中的Architecture Wizard 生成。DCM原语例化方式如下。
-- DCM BASE :In order to incorporate this function into the design, -- VHDL :the following instance declaration needs to be placed -- instance :in the body of the design code. The instance name -- declaration :(DCM BASE inst)and/or the port declarations after the -- code :"=>"declaration maybe changed to properly reference and -- :connect this function to the design. All inputs -- :must be connected. -- Library :In addition to adding the instance declaration,a use -- declaration :statement for the UNISIM.vcomponents library needs to be -- for :added before the entity declaration. This library -- Xilinx :contains the component declarations for all Xilinx -- primitives :primitives and points to the models that will be used -- :for simulation. -- Copy the following two statements and paste them before the -- Entity declaration,unless they already exist. Library UNISIM; use UNISIM.vcomponents.all; --<-----Cut code below this line and paste into the architecture body----> -- DCM BASE:Base Digital Clock Manager Circuit -- Virtex-4/5 -- Xilinx HDL Language Template,version 10.1 DCM BASE inst :DCM BASE generic map ( CLKDV DIVIDE=>2.0, -- Divide by:1.5,2.0,2.5,3.0,3.5,4.0,4.5,5.0,5.5,6.0,6.5 -- 7.0,7.5,8.0,9.0,10.0,11.0,12.0,13.0,14.0,15.0 or 16.0 CLKFX DIVIDE=>1,-- Can be any integer from 1 to 32 CLKFX MULTIPLY=>4,-- Can be any integer from 2 to 32
CLKIN DIVIDE BY 2 =>FALSE,-- TRUE/FALSE to enable CLKIN divide by two feature CLKIN PERIOD=>10.0,-- Specify period of input clock in ns from 1.25 to 1000.00 CLKOUT PHASE SHIFT =>"NONE",-- Specify phase shift mode of NONE or FIXED CLK FEEDBACK=>"1X",-- Specify clock feedback of NONE or 1X DCM AUTOCALIBRATION=>TRUE,-- DCM calibration circuitry TRUE/FALSE DCM PERFORMANCE MODE=>"MAX SPEED",-- Can be MAX SPEED or MAX RANGE DESKEW ADJUST=>"SYSTEM SYNCHRONOUS",-- SOURCE SYNCHRONOUS,SYSTEM SYNCHRONOUS or -- an integer from 0 to 15 DFS FREQUENCY MODE =>"LOW",-- LOW or HIGH frequency mode for fre- quency synthesis DLL FREQUENCY MODE=>"LOW",-- LOW,HIGH,or HIGH SER frequency mode for DLL DUTY CYCLE CORRECTION = > TRUE,- - Duty cycle correction,TRUE or FALSE FACTORY JF=>X"F0F0",-- FACTORY JF Values Suggested to be set to X" F0F0" PHASE SHIFT=>0,-- Amount of fixed phase shift from -255 to 1023 STARTUP WAIT =>FALSE) -- Delay configuration DONE until DCM LOCK, TRUE/FALSE port map ( CLK0=>CLK0, -- 0 degree DCM CLK ouptput CLK180=>CLK180, -- 180 degree DCM CLK output CLK270=>CLK270, -- 270 degree DCM CLK output CLK2X=>CLK2X, -- 2X DCM CLK output CLK2X180=>CLK2X180,-- 2X,180 degree DCM CLK out CLK90=>CLK90, -- 90 degree DCM CLK output CLKDV=>CLKDV, -- Divided DCM CLK out (CLKDV DIVIDE) CLKFX=>CLKFX, -- DCM CLK synthesis out (M/D) CLKFX180=>CLKFX180,-- 180 degree CLK synthesis out LOCKED=>LOCKED, -- DCM LOCK status output CLKFB=>CLKFB, -- DCM clock feedback CLKIN=>CLKIN, -- Clock input (from IBUFG,BUFG or DCM) RST=>RST -- DCM asynchronous reset input ); -- End of DCM BASE inst instantiation
2. 全局时钟资源使用方法
Xilinx芯片全局时钟资源的使用方法主要有以下5种,如图2-31所示。
图2-31 Xilinx全局时钟资源的5中常用方法
(1)IBUFG+BUFG。IBUFG后面连接BUFG的方法是最基本的全局时钟资源的使用方法,由于IBUFG组合BUFG相当于BUFGP,所以这种使用方法也称为BUFGP方法。
(2)IBUFGDS+BUFG。当输入时钟信号为差分信号时,需要使用IBUFGDS代替IBUFG。
(3)IBUFG+DCM+BUFG。这种使用方法最灵活,对全局时钟的控制更加有效。通过DCM模块不仅能对时钟进行同步、移相、分频、倍频等变换,而且可以使全局时钟的输出达到无抖动延迟。
(4)Logic+BUFG。BUFG不但可以驱动IBUFG的输出,还可以驱动其他普通信号的输出。当某个信号(时钟、使能、快速路径)的扇出非常大,并且要求抖动延迟最小时,可以使用BUFG驱动该信号,使该信号利用全局时钟资源。但需要注意的是,普通I/O的输入或普通片内信号进入全局时钟布线层有一个固定的延时,也就是说普通I/O和普通片内信号从输入到 BUFG 输出有一个固定延时,但是 BUFG 的输出到片内所有单元(IOB、CLB、BRAM、DSP)的延时可以忽略不计。
(5)Logic+DCM+BUFG。DCM同样也可以控制并变换普通时钟信号。也就是说DCM的输入可以是普通片内信号。
3. 全局时钟资源使用原则
Xilinx全局时钟资源必须满足的原则是使用IBUFG或IBUFGDS的必要条件是信号从专用全局时钟引脚输入。换句话说,当某个信号从全局引脚输入时,不论它是否为时钟信号,都必须使用IBUFG或IBUFGDS;如果对某个信号使用了IBUFG或IBUFGDS硬件原语,则这个信号必定是从全局时钟引脚输入的。如果违反了该原则,那么在布局布线时会报错。这是由Xilinx的FPGA内部结构决定的:IBUFG和IBUFGDS的输入端仅与芯片的专用全局输入引脚有物理连接,与普通I/O和其他内部CLB等没有物理连接。
另外,由于BUFGP相当于IBUFG和BUFG的组合,所以BUFGP的使用也必须遵循上述原则。
全局时钟资源的例化方式分为两种:一是在设计中直接例化全局时钟资源;二是通过综合阶段的约束或实现阶段的约束实现对全局时钟资源的使用。
第一种方法比较简单,用户只需按照前面叙述的5种全局时钟资源的基本使用方法例化即可。第二种方法是通过综合阶段约束或实现阶段的约束完成对全局时钟资源的使用。这种方法根据综合工具和布局布线工具的不同而变化。另外,大多数综合工具会自动分析时钟信号的扇出数目,在全局时钟资源富裕的情况下,使扇出数目最大的信号自动指定使用全局时钟资源。这时必须保证满足IBUFG、IBUFGDS和BUFGP的使用原则,如果不满足从专用全局时钟引脚输入,在布局布线时会报错,这时应该添加综合约束“NET "CLK" CLOCK DEDICATED ROUTE=FALSE;”指定该信号不使用全局时钟资源。
2.3.8 时序约束
在给FPGA做逻辑综合和布局布线时,需要在工具中设定时序的约束。通常,在FPGA设计工具中包含4 种路径:从输入端口到寄存器,从寄存器到寄存器,从寄存器到输出端口,从输入端口到输出端口的纯组合逻辑。通常,需要对这几种路径分别进行约束,以便使设计工具能够得到最优化的结果。下面对这几种路径分别进行讨论。
1. 从输入端口到寄存器
这种路径的约束是为了让FPGA设计工具能够尽可能地优化从输入端口到第一级寄存器之间的路径延迟,使其能够保证系统时钟可靠地收到从外部芯片到FPGA的信号。约束名称为input delay。约束条件的影响主要有4 个因素:外部芯片的Tco、电路板上信号延迟Tpd、FPGA的Tsu、时钟延迟Tclk。Tco的参数通常需要查外部芯片的数据手册。计算公式为input delay=Tco +Tpd +Tsu -Tclk。FPGA的Tsu也需要查FPGA芯片的手册。FPGA速度等级不同,这个参数也不同。Tpd和Tclk需要根据电路板实际的参数来计算。通常,每10cm的线长可以按照1ns来计算。例如,系统时钟100MHz,电路板上最大延迟2ns,时钟最大延迟 1.7ns,Tco为3ns,FPGA的Tsu为0.2ns,那么输入延迟的值为max Input delay=2 +3 +0.2 -1.7 =3.5(ns)。这个参数的含义是指让FPGA的设计工具把FPGA的输入端口到第一级寄存器之间的路径延迟(包括门延迟和线延迟)控制在10ns-3.5ns=6.5ns 以内。
2. 从寄存器到寄存器
这种路径的约束是为了让FPGA设计工具能够优化FPGA内寄存器与寄存器之间的路径,使其延迟时间必须小于时钟周期,这样才能确保信号被可靠地传递。由于这种路径只存在于FPGA内部,因此通过设定时钟频率的方式就可以对其进行约束。对于更深入的优化方法,还可以对寄存器的输入和寄存器的输出加以适当的约束,以使逻辑综合器和布线器能够对某条路径进行特别的优化。还可以通过设定最大扇出数来迫使工具对其进行逻辑复制,减少扇出数量,提高性能。
3. 从寄存器到输出端口
这种路径的约束是为了让FPGA设计工具能够优化FPGA内部从最后一级寄存器到输出端口的路径,确保其输出的信号能够被下一级芯片正确收到。约束的名称为output delay。约束条件的影响主要有3个因素:外部芯片的Tsu、电路板上信号延迟Tpd、时钟延迟Tclk。Tsu的参数通常需要查外部芯片的数据手册。计算公式为output delay=Tsu +Tpd -Tclk。例如,系统时钟100MHz,电路板上最大延迟2ns,时钟最大延迟1.7ns,Tsu为1ns,输出延迟的值为max output delay=1+2-1.7=1.3(ns)。这个参数的含义是指让FPGA的设计工具把最后一级寄存器与输出端口之间的路径延迟(包括门延迟和线延迟)控制在10ns-1.3ns=8.7ns以内。
4. 从输入端口到输出端口
这种路径是指组合逻辑的延迟,指信号从输入到输出没有经过任何寄存器。给这种路径加约束条件,需要虚拟一个时钟,然后通过约束来指定哪些路径是要受该虚拟时钟的约束。在Synplifypro和Precision中都有相应的约束来处理这种路径。
5. 基于Synopsys的SDC格式的时序约束
关于输入、输出延迟的一些参数,如果要把这些参数和Xilinx的软件结合起来,也不是一件容易的事情。以前似乎大家也不太看重约束条件的设定,大多时候都是无论如何先上板,然后通过Signaltap和ChipScope来调试。当FPGA规模扩大之后,一次布线需要很长时间,这种方法的弊端越来越严重了。实际上可以借鉴ASIC的设计方法:加比较完善的约束条件,然后通过RTL仿真和时序分析来解决问题,尽量避免在FPGA电路板上调试。Synop-sys的SDC格式也得到了逻辑综合器的支持,而且设定方法比较容易掌握,下面主要讨论这种格式的约束设定方法。
时钟分成两种,一种是从端口上直接输入的时钟,另一种是在FPGA内部产生的时钟。内部产生的时钟又分成两种,从锁相环出来的(包括Altera的PLL和Xilinx的DLL)和从逻辑单元出来的,如一般的计数器分频就是这种情况。从锁相环出来的时钟可以通过端口直接加,因为一般的综合工具和布线工具都能够自动把端口的时钟约束传递到锁相环,并且根据锁相环的倍频关系自动施加到下一级。而从逻辑单元出来的时钟就需要单独对其进行约束。
在SDC格式中,创建时钟的命令 create clock后面要带3 个参数:name、period、wave-form。name的含义是指创建这个时钟约束的名字,而不是时钟本身的名字。要把这个约束和时钟信号关联起来,还需要在后面加些东西。period的单位默认为ns。waveform用来指定占空比。除了这3个参数以外,常常还要加 get ports命令,用来指定时钟的输入端口。下面是一个较为完整的设定时钟的例子:
create clock-name clk1-period 10.000-waveform{2.000 8.000}[get ports sysclk]
这个例子表示,有一个clk1的约束,在这个约束中设定了时钟的周期为10ns,占空比为2ns低电平,8ns高电平。这个叫做clk1的约束是针对sysclk这个端口的。如果利用内部锁相环分频出来很多其他时钟的约束,可以不再另外施加其他约束,逻辑综合器和布线器都能根据锁相环的参数自动计算。如果是利用内部的逻辑单元分频出来的信号,则必须利用get registers指定分频的寄存器名。例如上例:
create clock-name clk1-period 10.000-waveform{2.000 8.000}[get registers cnt clk]
对于逻辑单元分频的时钟信号,采用命令create generated clock会更加精确。举例如下:
create generated clk-name clk2-source [getports sysclk]-div 4 [get registers cnt clk]
这个约束命令描述了一个clk2的约束,约束的对象是由sysclk分频4次得到的时钟,这个时钟是由cnt clk这个寄存器产生的。
在高速系统中,对时钟的描述可能会要求得更多,更加细致。例如,会要求对时钟的抖动和时钟的延迟进行描述。在SDC的文件格式中,可以通过两个命令来描述:set clock un-certainty 和 set clock latency。
时钟的延迟相对来讲比较简单,一般分为外部延迟和内部时钟线网的延迟。通常在约束时只对外部延迟做约束,在set clock latency命令后带-source参数就可以了。例如:
set clock latency-source 2 [get clocks {clk in}]
时钟的抖动要稍微复杂一些。因为这个值不但会影响到对Tsu的分析,也会影响到对Thold的分析。因此,采用set clock uncertainty参数要多一些。如果要理解这个命令对系统时序分析的影响,就需要对Altera的延时计算的概念做更多说明。对于set clock uncertainty的情况稍微复杂一些。因为set clock uncertainty的值既影响建立时间的计算,也影响保持时间的计算,因此需要在设定时分别指明:
set clock undertainty-setup 0.500-from clkA-to clkA set clock uncertainty-hold 0.300-from clkA-to clkA
前面的内容提供了输入、输出延迟的计算方法。输出延迟的命令是set output delay,有几个参数要加:参考时钟、最大/最小值和端口的名称。如下面例子中的描述:
set output delay-clock CLK-max 1.200 [get ports OUT] set output delay-clock CLK-min 0.800 [get ports OUT]
输入延迟的命令类似:
set input delay-clock CLK-max 2.000 [get ports IN] set input delay-clock CLK-min 1.600 [get ports IN]
对一些特殊的设计要求,如不关心的数据传递路径和多拍路径,还需要增加false path和multicycle的设定。这两个约束比较简单,容易设定,但是非常关键,如果设定不好,系统性能会大打折扣。false path是指在时序分析中不考虑其延迟计算的路径,如有些跨越时钟域的电路等。设定的方法:
set false path-from [get clocks clkA]-to [get clocks clkB] set false path-from regA-to regB
第一条命令设定了从时钟域clkA到时钟域clkB的所有路径都为false path。第二条命令设定了从 regA到regB的路径为false path。这两条路径在做时序分析时都会被忽略。multicy-cle的设定和false path的设定方法差不多。
为了让逻辑综合器和布局布线器能够根据时序的约束条件找到真正需要优化的路径,还要对时序报告进行分析,结合逻辑综合器的时序报告和布线器的时序报告,通过分析可以看出芯片的潜能是否已经被完全挖掘出来。