時鐘的基礎知識
數字設計中,“時鐘”表示在寄存器間可靠地傳輸數據所需的參考時間。Vivado的時序引擎通過時鐘特征來計算時序路徑需求,通過計算裕量(Slack)的方法報告設計時序空余。時鐘必須有合適的定義,包含如下特性:
-
定義時鐘樹的驅動管腳或端口,通常稱作根或源點。
-
通過周期和波形屬性來描述時鐘邊沿。
-
周期(period)以ns為單位進行設定,與波形重復率相關。
-
波形(waveform)以列表的形式給出,表中包含上升沿和下降沿在周期中的絕對時間,以ns為單位。
如下圖給出了兩個時鐘Clk0: period=10, waveform={0 5}、Clk1: period=8, waveform = {2 8}。
上述給出的只是時鐘的理想特征。當時鐘進入了FPGA器件,通過時鐘樹傳遞時,時鐘邊沿會有延時,通常稱作時鐘網絡延遲;噪聲或硬件表現會導致時鐘隨時可能發生變化,通常稱作時鐘不確定性,包括時鐘抖動、相位錯位等等。Vivado在時序分析時會考慮這些非理想因素以得到精確的時序裕量。
Xilinx FPGA器件內部有專用的硬件資源,支持大量設計時鐘的使用。通常板子上有一個外部組件(如有源晶振)產生時鐘信號,通過輸入端口進入器件內部。外部時鐘可以通過MMCM、PLL、BUFR等特殊原語生成其它時鐘,也可以由LUT、寄存器等常規單元進行轉換(通常稱作門控時鐘)。本文將講述如何根據應用情況定義時鐘。
主時鐘Primary Clock
主時鐘通常由兩個來源:(1).板級時鐘通過輸入端口進入設計;(2).GT收發器的輸出管腳(如恢復時鐘)。主時鐘必須與一個網表對象相連,該對象代表了所有時鐘邊沿的開始點,并且在時鐘樹中向下傳遞。也可以說,主時鐘的源點定義了0時刻,Vivado靠此來計算時鐘延遲和不確定性。
主時鐘只能通過create_clock命令來定義,且必須放在約束的開始,這是因為其它時序約束幾乎都要參考主時鐘。下面給出兩個主時鐘的例子。第一個例子如下圖所示,采用單端時鐘輸入:
板級時鐘通過sysclk端口進入FPGA,通過一個輸入緩沖器和一個時鐘緩沖器后到達寄存器。使用如下命令定義:
-
create_clock -period 10 [get_ports sysclk] #10ns周期,50%占空比,無相移
-
create_clock -name devclk -period 10 -wavefor {2.5 5} [get_ports sysclk] #板級時鐘名稱devclk,10ns周期,25%占空比,90°相移
第二個例子如下圖所示,采用差分時鐘輸入,這也是高速時鐘的輸入方式:
上圖中差分時鐘驅動一個PLL,定義主時鐘時必須只創建差分緩沖器的正極輸入。如果同時創建了正極、負極輸入,將會導致錯誤的CDC路徑。如“create_clock -name sysclk -period 3.33 [get_ports SYS_CLK_clk_p]”。
虛擬時鐘Virtual Clock
這種類型的時鐘對于初學者來說用的可能很少,虛擬時鐘通常用于設定輸入和輸出的延遲約束。之所以稱為“虛擬”,是因為這種時鐘在物理上沒有與設計中的任何網表對象相連。定義時使用create_clock命令,但無需指定源對象。在下列情況需要用到虛擬時鐘:
-
所有設計時鐘都不是外部器件I/O的參考時鐘。
-
FPGA的I/O路徑與一個內部生成的時鐘相關,但是該時鐘不能合適地通過對板級時鐘計時來生成(如兩個周期的比不是整數)。
-
希望為與I/O延遲約束相關的時鐘設定不同的抖動和延遲,但是不希望修改內部時鐘的特征。
比如時鐘clk_virt的周期為10ns,且不與任何網表對象相連,可以這樣定義“create_clock -name clk_virt –period 10”,沒有指定objects參數。注意,虛擬時鐘必須在使用之前便定義好。
生成時鐘Generated Clock
生成時鐘是指在設計內部由特殊單元(如MMCM、PLL)或用戶邏輯驅動的時鐘。生成時鐘與一個上級時鐘(注:官方稱作master clock,為與primary clock作區分,這里稱作上級時鐘)相關,其屬性也是直接由上級時鐘派生而來。上級時鐘可以是一個主時鐘,也可以是另一個生成時鐘。
生成時鐘使用create_generated_clock命令定義,該命令不是設定周期或波形,而是描述時鐘電路如何對上級時鐘進行轉換。這種轉換可以是下面的關系:
-
-
簡單的頻率分頻
-
簡單的頻率倍頻
-
頻率倍頻與分頻的組合,獲得一個非整數的比例,通常由MMCM或PLL完成
-
相移或波形反相
-
占空比改變
-
上述所有關系的組合
Vivado計算生成時鐘的延遲時,會追蹤生成時鐘的源管腳與上級時鐘的源管腳之間的所有組合和時序路徑。某些情況下可能只希望考慮組合邏輯路徑,在命令行后添加-combinational選項即可。
這里先解釋一下本文甚至本系列大量使用的兩個詞,端口(Port)和管腳(Pin)。端口通常用get_ports命令獲取,管腳使用get_pins命令獲取。二者的含義是不同的,但管腳的范圍更廣泛,比如設計中用到的一個寄存器都有3個管腳:clk、D和Q。下面給出幾個定義生成時鐘的例子:
1.簡單的2分頻
下圖中,主時鐘clkin通過端口進入FPGA,使用一個寄存器REGA對其2分頻,得到的生成時鐘clkdiv2驅動其它的寄存器管腳。
可以采用如下兩種方法對生成時鐘進行約束:
-
#定義主時鐘,周期10ns,50%占空比
-
create_clock -name clkin -period 10 [get_ports clkin]
-
#約束方法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]
約束命令中使用**-source選項來設定上級時鐘,但如上所示,該選項只能設定為一個端口或管腳類型的網表對象,不能直接設置為時鐘類型對象。上面約束使用-divide_by選項設置分頻系數,此外還可以使用-edges**選項,如下所示:
-
該約束與上面等效
-
create_generated_clock -name clkdiv2 -source [get_pins REGA/C] -eedges {1 3 5} [get_pins REGA/Q]
-edges的參數為一個列表,該列表通過主時鐘的邊沿來描述生成時鐘的波形。列表中的值為主時鐘邊沿的序號(注意觀察上圖),由時鐘上升沿開始,定義了生成時鐘邊沿的時間點。
2.改變占空比與相移
如果僅需要改變時鐘的相移,使用**-edge_shift**選項可以正向或反向設定每一個生成時鐘波形的相移量。注意,-edge_shift選項不能與-devide_by、-multiply_by、-invert選項同時使用。下圖中上級時鐘為clkin,進入mmcm0單元,產生一個25%占空比、相移90°的時鐘:
可以采用如下方法對生成時鐘進行約束。使用上級時鐘的1、2、3標號邊沿(即0ns、5ns、10ns)定義生成時鐘,為了得到預期波形,1和3標號邊沿要分別移動2.5ns,得到2.5ns、5ns、12.5ns的波形。
-
#定義主時鐘,周期10ns,50%占空比
-
create_clock -name clkin -period 10 [get_ports clkin]
-
#定義生成時鐘,周期10ns,25%占空比,90°相移
-
create_generated_clock -name clkshifit -source [get_pins mmcm0/CLKIN] -edges {1 2 3} -edge_shift {2.5 0 2.5} [get_pins mmcm0/CLKOUT]
3.同時倍頻與分頻
這種情況通常用于定義MMCM或PLL的輸出,一般使用這些IP核時會自動創建相應約束。考慮上例中的圖,假設MMCM將上級時鐘倍頻到4/3倍,無法直接倍頻,需要同時使用-divede_by和-multiply_by選項來實現:
-
create_clock -name clkin -period 10 [get_ports clkin] #定義主時鐘
-
#定義生成時鐘,4/3倍頻
-
create_generated_clock -name clk43 -source [get_pins mmcm0/CLKIN] -multiply_by 4 -divide_by 3 [get_pins mmcm0/CLKOUT]
4.僅通過組合路徑追蹤上級時鐘
前面簡單介紹了-combinational選項的使用,為了更好理解,這里舉一個具體例子。下圖中,上級時鐘同時傳遞到寄存器和多路選擇器中,寄存器對時鐘進行2分頻。多路選擇器從寄存器的2分頻時鐘和上級時鐘中選擇一個作為生成時鐘輸出。
顯而易見,從上級時鐘到生成時鐘有兩條路徑,一條為時序路徑,一條為組合路徑。如果我們只希望考慮組合路徑上的延遲時,定義生成時鐘時就需要使用-combinational選項。
自動生成時鐘
這種類型時鐘算是生成時鐘的一種特例,“自動”是指在已經定義了上級時鐘的情況下,Vivado會自動為時鐘管理單元CMBs(Clock Modifying Blocks)的輸出管腳創建約束。官方稱作Automatically Derived Clocks或Auto-generated Clock。
7系列FPGA的CMB單元包括MMCM、PLL、BUFR、PHASER;UltraScale系列FPGA的CMB單元種類與數量更多,這里不陳列。如果約束中已經存在用戶在某一網表對象上定義的時鐘,則不會創建相同對象上的自動生成時鐘。
下面給出一個具體例子。下圖中上級時鐘clkin驅動clkip/mmcm0單元的CLKIN輸入,該單元是一個MMCME2資源的實例。則自動生成時鐘的定義源點為clkip/mmcm0/CLKOUT,頂層與此源點連接的網絡名為clkip/cpuClk,自動生成時鐘的名字便是cpuClk。
如上所述,Vivado會自動創建自動生成時鐘的名稱(Name),如果兩個名稱發生沖突也會自動添加后綴,如usrclk、usrclk_1等等。Vivado也支持對已經創建好的自動生成時鐘重新命名,但很少用到,這里不做介紹。
時鐘組Clock Group
很多初學者應該也沒有接觸過時鐘組這個概念。默認情況下,Vivado會測量設計中所有時鐘之間的路徑時序。添加如下兩種約束可以控制該功能:
-
set_clock_groups:建立時鐘組,Vivado不會對不同時鐘組的時鐘之間進行時序分析。
-
set_false_path:將兩個時鐘之間的路徑設置為false path后,不會對該路徑進行任何時序分析。
劃分時鐘組通常有兩個依據:(1).原理圖或時鐘網絡報告中的時鐘樹拓撲圖,判斷哪些時鐘不應該放在一起做時序分析;(2).時鐘交互報告查看兩個時鐘間存在的約束,判斷它們是否有共享的主時鐘(代表是否有已知的相位關系)或者是否有公共周期。
但要明白,我們設定時鐘組的目的還是為了保證設計在硬件中能正常工作,因此我們必須確保這些忽略了時序分析的路徑有合適的再同步電路或異步數據傳輸協議。根據時鐘間的關系,可以做如下分類:
-
同步時鐘:即兩個時鐘間有可預知的相對相位,通常它們的時鐘樹源自網表中的同一個根,且有一個公共周期。
-
異步時鐘:兩個時鐘間有無法預知的相對相位。比如兩個獨立的晶振信號通過兩個輸入端口進入FPGA中,生成兩個時鐘。由于兩個主時鐘沒有明確的相位關系,兩個生成時鐘間便是異步的。
-
不可擴展時鐘:官方稱作Unexpandable Clocks,是指時序引擎在1000個周期內無法判斷兩個時鐘是否有公共周期。這種情況通常發生在兩個時鐘周期比是一個特殊的分數,比如一個主時鐘通過MMCM生成一個周期為5.125ns的時鐘clk1和一個周期為6.666ns的時鐘clk2,盡管它們在時鐘樹的根上有一個確定的相位關系,但是在1000個周期內時鐘上升沿無法再次對齊。
1.異步時鐘組
同步時鐘可以安全地進行時序分析。異步時鐘和不可擴展時鐘雖然通過時序分析也會得到一個裕量值,但這個值不可作為可靠結果。從這個角度出發,不可擴展時鐘也可以視作一種特殊的異步時鐘。這就需要通過設置時鐘組來忽略異步時鐘的時序路徑上的時序分析。
這里舉個例子,一個主時鐘clk0通過MMCM生成兩個時鐘usrclk和itfclk;另一個主時鐘clk1通過另一個MMCM生成兩個時鐘clkrx和clktx。用如下命令創建異步時鐘組:
-
set_clock_groups -name async_clk0_clk1 -asynchronous -group {clk0 usrclk itfclk} -group {clk1 clkrx clktx}
-
#如果時鐘名稱事先不知道,可以用如下寫法
-
set_clock_groups -name async_clk0_clk1 -asynchronous -group [get_clocks -include_generated_clocks clk0] -group [get_clocks -include_generated_clocks clk1]
2.互斥時鐘組
下面再介紹另一種會用到時鐘組的情況。某些設計會有幾個操作模式,不同操作模式使用不同的時鐘。這些時鐘通常由專用的時鐘選擇器進行選擇,如BUFGMUX和BUFGCTRL,最好不要用LUT作時鐘選擇器。
這些單元都是組合邏輯單元,Vivado會將所有輸入傳遞到輸出。在Vivado IDE中,幾個時序時鐘可以同時存在時鐘樹上,方便地同時報告所有操作模式。但是在硬件中這是不可能的,它們之間是互斥的,這些時鐘便稱作互斥時鐘。
舉個例子,一個MMCM實例生成的兩個時鐘clk0和clk1,與一BUFGMUX實例clkmux相連,clkmux的輸出驅動設計時鐘樹。默認情況下,雖然clk0和clk1共享同一時鐘樹,且不能同時存在,Vivado還是會分析clk0和clk1之間的路徑。這個問題要通過設置互斥時鐘組來解決,達到禁止分析這兩個時鐘間路徑 的目的。約束如下:
set_clock_groups -name exclusive_clk0_clk1 -physically_exclusive -group clk0 -group clk1
在ASIC工藝中使用-physically_exclusive和-logically_exclusive代表不同的信號完整性分析模式,但對于Xilinx FPGA而言,二者是等價的,都可以使用。
時鐘延遲、抖動與不確定性
本文的上述約束可以說都是對時鐘的理想特征進行約束,為了更精確地進行時序分析,設計者還必須設定一些與運行環境相關的可預測變量和隨機變量。這部分也稱作時鐘的不確定性特征。
1.時鐘延遲latency
經過板子上和FPGA器件內部的傳輸,時鐘邊沿到達目的地后會有一個確定的延遲。這個延遲可以分為兩個部分看待:
網絡延遲:也稱作插入延遲,指再FPGA內部傳輸帶來的延遲。Vivado會自動分析計算該延遲,布線過程前只是一個粗略的估計,布線后便可以得到一個精確的值。對于生成時鐘,包含其本身的網絡延遲和上級時鐘的網絡延遲兩部分。
源端延遲:通常指FPGA器件外,時鐘進入源點前的傳輸延遲,這部分延遲與PCB設計相關,需要用set_clock_latency命令進行約束。
下面給出一個約束源端時鐘延遲的例子:
#設定最小源端延遲值
set_clock_latency -source -early 0.2 [get_clocks sysclk]
#設定最大源端延遲值
set_clock_latency -source -late 0.5 [get_clocks sysclk]
2.時鐘抖動jitter
對于ASIC器件來說,時鐘抖動通常代表了時鐘不確定性特征;但對于Xilinx FPGA而言,抖動屬性被當作可預測變量看待。抖動有的需要單獨設置,有的在時序分析過程中自動計算。抖動分為兩種:
輸入抖動:指實際時鐘邊沿與理想時鐘邊沿到達時刻之間的差值,使用set_iput_jitter命令為每個主時鐘單獨設置輸入抖動。但是不能直接為生成時鐘設置輸入抖動,這部分由工具自動計算,如果(1).生成時鐘由一個組合或時序單元創建,生成時鐘的抖動與上級時鐘相同;(2).生成時鐘由 MMCM或PLL驅動,生成時鐘的抖動為一個自動計算的值。
系統抖動:指電源噪聲、板級噪聲或其它原因引起的整體的抖動,對于整個設計,使用set_system_jitter命令設置一個值即可,會應用到所有時鐘。
下面給出一個約束輸入抖動的例子:
#主時鐘傳輸過程中有±100ps的抖動
set_input_jitter [get_clocks -of_objects [get_clocks sysclk]] 0.1
不過,時鐘抖動對整個時鐘不確定性計算的影響不是太大。計算時鐘不確定性時對每條路徑都是獨立的,且主要依賴于時鐘拓撲結構、路徑上的時鐘對、時鐘樹上是否存在MMCM/PLL單元等其它因素。
3.附加的時鐘不確定性
使用set_clock_uncertainty命令可以根據需要為特定的時鐘關系定義附加的時鐘不確定性,這樣在時序分析時,可以為設計中的某些部分增加額外裕量。
前面文章說過XDC約束帶有順序性,后面的約束會重寫前面的約束。但在這里,時鐘間的不確定性總是優先于單個時鐘的不確定性,不管約束順序如何。看下面的例子:
set_clock_uncertainty 2.0 -from [get_clocks clk1] -to [get_clocks clk2]
set_clock_uncertainty 1.0 [get_clocks clk1]
這里首先約束從clk1到clk2有一個2ns的時鐘不確定性,接著又約束clk1有1ns的時鐘不確定性,但是后面這條約束不會改動從clk1到clk2之間的關系。
原文標題:FPGA學習-Vivado時鐘的約束方法
文章出處:【微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。
-
FPGA
+關注
關注
1626文章
21667瀏覽量
601864 -
時鐘
+關注
關注
10文章
1720瀏覽量
131364 -
Vivado
+關注
關注
19文章
808瀏覽量
66328
原文標題:FPGA學習-Vivado時鐘的約束方法
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論