2. 定義時鍾
2.1 關於時鍾
為了獲得最佳精度路徑覆蓋信息,必須正確定義時鍾。
- 時鍾要定義在時鍾樹的根 pin 或 port 上,稱為 source point。
- 時鍾的邊緣應該由周期和波形進行組合描述。
- 周期使用納秒做為單位進行定義。它對應於波形重復的時間。
- 波形是一系列的上升沿和下降沿絕對時間列表,單位為納秒,並且所有時間在一個時鍾周期內。列表必須包含偶數個值。第一個值始終對應於第一個上升邊緣。如果沒有指定波形,波形的默認占空比為 50%,相移為 0。
2.1.1 傳播時鍾
周期和波形屬性只展現出了時鍾的理想特性。當時鍾進入 FPGA 並通過時鍾樹傳播時,時鍾邊沿被延緩,並受噪聲和硬件行為引影響。這些特性稱為時鍾網絡延遲和時鍾不確定性。時鍾的不確定性包括:
- 時鍾抖動(clock jitter)
- 相位錯誤
- 用戶指定添加的不確定性
默認情況下,Vivado 在做時序分析時,始終將時鍾視為傳播時鍾,即非理想時鍾,以此提供准確的余量值,其中包括時鍾樹插入延遲和不確定性。
2.1.2 專用硬件資源
FPGA 有大量專用的時鍾管腳,這個管腳可以專門用來做時鍾的輸入。FPGA 內部包含有 MMCM、PLL 和 BUR 之類的時鍾資源。
2.2 基准時鍾(Primary Clock)
基准時鍾是通過 FPGA 輸入端口或千兆收發器輸出引腳(例如,恢復時鍾)進入設計的時鍾。基准時鍾只能通過 create_clock
指令進行定義。(為什么是千兆收發器?下面的話應該可以解釋,7 系列的 GT 恢復時鍾不能自動推導,必須手動定義。而 US 和 USP 系列的可以自動推導,不需要人為定義)
Primary clocks must be defined on a gigabit transceiver output only for Xilinx® 7 series FPGAs. For UltraScale and UltraScale+™ devices, the timer automatically derives clocks on the GT output ports.
基准時鍾必須附加到網表對象。該網表對象代表設計中的所有時鍾邊沿起點,並且是時鍾樹上向下游傳播的起點。換句話說,基准時鍾的源點定義了零時間點,這個點被 Vivado 用來計算余量方程時,作為時鍾延遲和不確定性的零起點。Vivado 會忽略來自定義基准時鍾點上游單元的所有時鍾樹延遲。如果基准時鍾錯誤的定義在了路徑中間的引腳上,則只有部分延遲用於時序分析。
這可能會引起問題,因為時鍾之間的偏斜和余量值會變得不准確。
2.2.1 基准時鍾示例
# 周期 10ns, 來源於外部,通過 sysclk 端口輸入,占空比 50%,相位為 0。
create_clock -period 10 [get_ports sysclk]
# 周期 10ns, 來源於外部,通過 ClkIn 端口輸入,占空比 25%,相位為 90。
create_clock -name devclk -period 10 -waveform {2.5 5} [get_ports ClkIn]
# GT 的恢復時鍾無法自動推導時,需要手動約束。Vivado 在計算余量時,會從RXOUTCLK開始。
create_clock -name rxclk -period 3.33 [get_pins gt0/RXOUTCLK]
# 對於差分時鍾,時鍾必須定義在 P 端上,N 端上不能有定義。如果 P 和 N 各自定義一次,會導致軟件認為是異步路徑。
create_clock -name sysclk -period 3.33 [get_ports SYS_CLK_clk_p]
2.3 虛擬時鍾(Virtual Clocks)
虛擬時鍾是一種沒有物理連接到設計中任何網表元素的時鍾。虛擬時鍾是通過 create_clock
指令定義的,但無需指定源對象。虛擬時鍾通常用於指定輸入和輸出延遲約束:
# 創建時鍾,但不指定時鍾源
create_clock -name clk_virt -period 10
2.4 衍生時鍾(Generated Clocks)
2.4.1 關於衍生時鍾
衍生時鍾產生於 FPGA 設計內部,通常由 MMCM 或用戶邏輯產生。衍生時鍾有一個關聯的主時鍾(master clock),指令 create_generated_clock
需要指定一個主時鍾,它可以是基准時鍾或者是另一個衍生時鍾。衍生時鍾屬性直接源自其主時鍾,定義衍生時鍾時,不是指定它們的周期或波形,而是描述如何轉換主時鍾到衍生時鍾。衍生時鍾和主時鍾之間的關系可以是以下任何一種:
- 簡單的分頻
- 簡單的倍頻
- 分頻和倍頻的組合,用來得到一個非整數比的分頻。
- 移相或反相
- 改變占空比
- 所有上面的組合
為了計算衍生時鍾的延遲,工具會跟蹤衍生時鍾的源引腳和主時鍾的源引腳之間的時序路徑和組合路徑。在某些情況下,可能需要僅跟蹤組合路徑以計算生成的時鍾延遲。可以使用
-combinational
行選項執行此操作。
2.4.2 用戶自定義的衍生時鍾
2.4.2.1 示例1:簡單的2分頻
create_clock -name clkin -period 10 [get_ports clkin]
# Option 1: master clock source is the primary clock source point
create_generated_clock -name clkdiv2 -source [get_ports clkin] -divide_by 2 [get_pins REGA/Q]
# Option 2: master clock source is the REGA clock pin
create_generated_clock -name clkdiv2 -source [get_pins REGA/C] -divide_by 2 [get_pins REGA/Q]
2.4.2.2 示例2:使用 -edge 選項進行2分頻
可以不使用 -divide_by 選項,而是使用 -edges 選項直接基於主時鍾邊沿描述衍生時鍾波形。該參數是一組主時鍾邊沿的序號,用來標記衍生時鍾的跳變沿的位置。從衍生時鍾的上升沿開始描述。
# waveform specified with -edges instead of -divide_by
create_generated_clock -name clkdiv2 -source [get_pins REGA/C] -edges {1 3 5} [get_pins REGA/Q]
2.4.2.3 示例3:使用 -edge 和 -edge_shift 選項改變占空比和相位
當需要做移相時,可以使用 -edge_shift
選項。衍生時鍾的每個邊沿都可以單獨的進行正向或負向移相。-edge_shift
選項 不能和以下選項同時使用:
- -divide_by
- -multiply_by
- -invert
假設主時鍾 clkin 的周期為 10 ns,占空比為 50% 。clkin 輸入到 mmcm0 后,衍生出一個時鍾,其占空比為 25%,移相 90 度。衍生時鍾定義基於主時鍾的第 1、2 和 3 邊沿。這些邊沿跳變分別發生在 0ns、5ns 和 10ns 上。要獲得所需的波形,將第一和第三邊沿移動 2.5ns。
create_clock -name clkin -period 10 [get_ports clkin]
# First rising edge: 0ns + 2.5ns = 2.5ns
# Falling edge: 5ns + 0ns = 5ns
# Second rising edge: 10ns + 2.5ns = 12.5ns
create_generated_clock -name clkshift -source [get_pins mmcm0/CLKIN] -edges {1 2 3} \
-edge_shift {2.5 0 2.5} [get_pins mmcm0/CLKOUT]
注意:
-edge_shift
的值可以為正數,也可以為負數。
2.4.2.4 示例4:同時使用 -divide_by 和 -multiply_by
Vivado 允許同時指定 -divide_by
和 -multiply_by
,這是對 SDC 的擴展。雖然這對於手動定義 MMCM 或 PLL 生成的時鍾特別方便,但是 Xilinx 建議讓軟件自動創建這些約束。如果手動定義了約束,必須確認約束的設置和鎖相環本身的配置是相匹配的。
# 假設 MMCM 生成的時鍾頻率為原主時鍾的 4/3。
create_generated_clock -name clk43 -source [get_pins mmcm0/CLKIN] -multiply_by 4 \
-divide_by 3 [get_pins mmcm0/CLKOUT]
2.4.2.5 示例5:追蹤主時鍾的組合邏輯路徑
在此示例中,假設主時鍾同時驅動基於寄存器的時2分頻器和時鍾多路復用器,時鍾多路復用器可從選擇主時鍾或2分頻時鍾。在此方案中,從主時鍾到生成的時鍾有兩條路徑,即時序邏輯路徑和組合邏輯路徑。我們希望在多路復用器輸出上創建一個衍生時鍾,該輸出反映了從主時鍾到多路復用器的組合路徑的延遲。這可以通過使用 -combinational
選項完成的:
create_generated_clock -name clkout -source [get_pins mmcm0/CLKIN] -combinational [get_pins MUX/O]
2.4.2.6 示例6:由 ODDR 驅動的轉發時鍾
在此示例中,由 ODDR 單元驅動的輸出端口上創建轉發時鍾。轉發時鍾參考驅動 ODDR/CLKDIV 引腳的主時鍾,並且與主時鍾(-divide_by 1) 具有相同的周期。
create_generated_clock -name ck_vsf_clk_2 -source [get_pins ODDRE1_vsfclk2_inst/CLKDIV] -divide_by 1 [get_ports vsf_clk_2]
2.4.3 自動推導出的衍生時鍾
自動推導的時鍾也稱為自動生成時鍾。Vivado 會自動在 CMB( Clock Modifying Blocks)的輸出引腳上創建這些約束,前提是相關的主時鍾已經定義。
- Xilinx 7 系列的 CMB 可以是:
- MMCM*/ PLL*
- BUFR
- PHASER*
- Xilinx UltraScale 系列的 CMB 可以是:
- MMCM* / PLL*
- BUFG_GT / BUFGCE_DIV
- GT* _COMMON / GT*_CHANNEL / IBUFDS_GTE3
- BITSLICE_CONTROL / RX*_BITSLICE
- ISERDESE3
如果用戶定義的時鍾(主時鍾或衍生時鍾)也在同一網列表對象(即在同一定義點(pin 或 net)上定義,Vivado 則不會自動創建衍生時鍾。
2.4.3.1 自動衍生時鍾示例
以下自動衍生時鍾示例是由 MMCM 生成的時鍾。 主時鍾 clkin 驅動 MMCME2 實例 clkip/mmcm0 的輸入 CLKIN。自動生成的時鍾的名稱是 cpuClk,其定義點是 clkip/mmcm0/CLKOUT。
使用
get_clocks -of_objects <pin/port/net>
命令在不知道其名稱的情況下查詢自動生成的時鍾。這使的約束或腳本相對通用,不用關心時鍾名稱是否有改動。
2.4.3.2 本地網名
如果 CMB 實例位於設計層次結構內,則生成的時鍾名稱將使用本地網名(即沒有父單元名的名稱)。例如,對於名稱為 clkip/cpuClk 的層次網線:
- 父單元名稱為 clkip 。
- 生成的時鍾名稱為 cpuClk。
2.4.3.3 名稱沖突
如果兩個自動生成的時鍾之間的名稱有沖突,Vivado 會添加獨有的后綴來區分它們,例如:
- usrclk
- usrclk_1
- usrclk_2
強制修改衍生時鍾的名稱:
- 在 RTL 中選擇獨特且相關的網名。
- 使用
create_generated_clock
強制使用指定的名稱。
2.4.4 重命名自動衍生時鍾
可以對工具自動創建的衍生時鍾進行重命名。重命名通過使用 create_generated_clock
指令和有限的參數完成。
create_generated_clock -name new_name [-source master_pin] [-master_clock master_clk] source_object
必須指定的參數有新生成的時鍾名稱和生成時鍾的源對象。生成時鍾的源對象是創建衍生時鍾的對象(CMB 的輸出引腳、UltraScale GT 的輸出引腳等)。只有當多個時鍾通過源引腳傳播時,才能使用源和主參數,以消除任何模糊性。當有多個時鍾通過源對象傳播時,必須指定 -source
和 -master
參數,以消除任何不明確的地方。
注意:如果有
-edges
/-edge_shift
/-divide_by
/-multiply_by
/-combinational
/-duty_cycle
/-invert
選項傳遞到create_generated_clock
指令,則自動生成衍生時鍾不會被重命名,相反會重新定義一個新的衍生時鍾。
注意:使用 OOC 模式的模塊在綜合時,模塊被當做黑盒,模塊內部引腳和時鍾名稱不可訪問。在這種情況下,用於綜合的頂層 XDC 約束不能指定時鍾名稱或重命名模塊內生成的自動衍生時鍾。可以使用一些查詢指令引用相關目標,如
get_clocks -of_objects [get_pins <OOC_MODULE_OUTPUT_CLOCK_PORT>]
。用於實現的 XDC 約束沒有此限制。
重命名的限制:
- 自動衍生時鍾只能在其源引腳上重命名,例如在 CMB(PLL、MMCM. .. ) 的輸出處。自動衍生時鍾不能在 BUFG 的輸出上重命名,即便時鍾是通過它傳播的。
- 無法重命名基准時鍾或用戶定義衍生時鍾。只有自動衍生時鍾才能使用此機制進行重命名。
- source_object 必須匹配創建自動衍生時鍾的對象。
- 如果工具無法重命名衍生時鍾,則會返回錯誤。重命名完成時,主時鍾也必須存在。
- 自動衍生時鍾可以在 XDC 內的任何時間重命名,即使已被某些時序約束引用。
2.5 時鍾組(Clock Groups)
2.5.1 關於時鍾組
默認情況下,Vivado 會對設計中所有時鍾之間的路徑進行時序收斂,除非使用了時鍾組或偽路徑進行約束。set_clock_groups
指令會讓 Vivado 不對時鍾組之間的路徑進行時序分析,而同一組內的時鍾之間的仍會進行時序收斂。與 set_false_path
約束不同,兩個時鍾之間的兩個方向的路徑都會被忽略。
可以多次使用 -group
選項指定多個時鍾組。如果組中的時鍾在設計中都不存在,則組將變為空。set_clock_groups
約束至少需要兩組,並且都不為空組時才有效。如果只有一個組有效,其他組都為空時,set_clock_groups
約束不會生效,並返回錯誤消息。
使用原理圖查看器(Schematic Viewer)或時鍾網絡報告(Clock Networks Report)查看可視化時鍾樹的拓撲,確定哪些時鍾不能一起進行收斂。您還可以使用時鍾交互報告來(Clock Interactions Report)查看兩個時鍾之間的現有約束,並確定它們是有相同的主時鍾(即它們具有已知的相位關系),或者判斷出周期沒有公倍數的時鍾(Unexpandable)。
謹慎!忽略兩個時鍾之間的時序分析並不意味着它們之間的路徑將在硬件上能正常工作。為了防止亞穩態,必須確認這些路徑是否具有適當的同步電路或異步數據傳輸協議。
2.5.2 時鍾分類
-
同步時鍾
當兩個時鍾的相對相位關系是已知的,它們就是是同步時鍾。通常它們的時鍾樹源頭來自網列表中的同一根,它們的周期有公倍數。例如,衍生時鍾和他的主時鍾的周期比率為 2,這兩個時鍾是同步的。因為它們有相同時鍾源點,並且周期為2倍關系。它們可以安全地一起進行時序收斂。 -
異步時鍾
當無法確定兩個時鍾的相對相位關系時,這兩個時鍾就是異步的。例如,由板上兩個獨立晶振生成的時鍾,通過不同輸入端口進入 FPGA,這兩個時鍾就是異步的。如果它們是由板上的同一晶振生成的,這兩個就不是異步時鍾。在大多數情況下,基准時鍾可以被視為異步時鍾。 -
不可擴展的時鍾(Unexpandable Clocks)
當時序引擎在 1000 個周期中無法找到兩個時鍾周期的公倍數時,則認為兩個時鍾無法擴展。在這種情況下,在時序分析時會使用 1000 周期中最小的相位關系,但時序引擎無法保證這是最差的情況。通常這兩個時鍾之間的周期比比較奇怪的情況。例如,兩個時鍾 clk0 和 clk1,由相同主時鍾的兩個 MMCM 生成,clk0 周期為 5.12 ns,clk1 周期為 6.66 ns。他們的上升沿在 1000 個周期內沒有對齊的時候,時序引擎會取最差的情況 0.01 ns 做時序收斂。與異步時鍾一樣,余量計算會正常進行,但其值是不可信的。因此,無可擴展的時鍾經常被處理為異步時鍾,必須用處理異步時鍾相同的方式對待這兩個時鍾,包括其約束和異步電路。
2.5.3 異步時鍾組
異步時鍾和不可擴展時鍾不能被時序收斂。使用 set_clock_groups
指令可以在時序分析時忽略它們之間的時序路徑。
注意:
set_clock_groups
比普通的時序例外的優先級要高,如果需要約束和報告異步時鍾間的路徑,那就不能使用set_clock_groups
,只能使用時序例外。
2.5.3.1 異步時鍾組示例
- 基准時鍾 clk0 定義在輸入管腳上,並連接到了 MMCM。MMCM 生成了 usrclk 和 itfclk 兩個時鍾 。
- 另一個基准時鍾 clk1 定義在了 GTP 輸出的恢復時鍾上,並連接到了另一個 MMCM。此 MMCM 生成了 gtclkrx 和 gtclktx 兩個時鍾。
使用 -asynchronous
選項創建異步時鍾組。
set_clock_groups -name async_clk0_clk1 -asynchronous -group {clk0 usrclk itfclk} \ -group {clk1 gtclkrx gtclktx}
如果衍生時鍾的名稱無法事先得知,可以使用 get_clocks -include_generated_clocks
動態獲取。所以上面的約束也可以寫成如下方式,其移植性更強。
set_clock_groups -name async_clk0_clk1 -asynchronous \ -group [get_clocks -include_generated_clocks clk0] \ -group [get_clocks -include_generated_clocks clk1]
注意:上面的約束中,異步是指組與組之間異步,組內各時鍾仍會進行時序分析和收斂。
2.5.4 獨占時鍾組(Exclusive Clock Groups)
有些設計擁有多種操作模式,在不同的模式下需要使用不同的時鍾。時鍾之間的選擇通常使用時鍾多路復用器完成,如 BUFGMUX 和 BUFGCTRL 或 LUT(盡量不使用LUT做時鍾選擇)。由於這些單元是組合邏輯,所這些時鍾都通過同一個時鍾樹傳播。這些時鍾會同時報告中呈現,但在硬件方面是不可能的,同一時刻只會有一個時鍾。這種不會同時工作的時鍾稱作獨占時鍾。
2.5.4.1 獨占時鍾組示例
獨占時鍾使用 set_clock_groups
的 -logically_exclusive
或 -physically_exclusive
選項進行定義。在 Vivado 中,這兩個選項的意義是相同的,任意使用一個即可。
假設一個 MMCM 輸出了 clk0 和 clk1,這兩個時鍾連接到了一個 BUFGMUX(實例名為clkmux),輸出 clkmux 驅動時鍾樹。默認情況下,Vivado 會分析 clk0 和 clk1 之間的路徑,即便兩個時鍾驅動同一個時鍾樹,並且兩個時鍾不可能同時使用。必須使用如下約束停止分析兩個時鍾之間的路徑。
set_clock_groups -name exclusive_clk0_clk1 -physically_exclusive -group clk0 -group clk1
2.6 時鍾延遲、抖動和不確定性
除了定義時鍾波形外,還必須指定與操作條件和環境相關的可預測變化和隨機變化。
2.6.1 時鍾延遲
時鍾在 PCB 板上和 FPGA 內部傳播后,時鍾沿會經過一段延時后到達目的地。此延時通常有:
- 源延時(通常在時鍾源點之前,在 FPGA 設備外部)。
- 網絡延時。
網絡延時(也稱為插入延時),其延時值要么是自動估算(pre-route design),要么是精確計算(post-route design)。
Xilinx FPGA 使用 set_clock_latency
指令主要是用來指定器件外部的延時。
# Minimum source latency value for clock sysClk (for both Slow and Fast corners)set_clock_latency -source -early 0.2 [get_clocks sysClk]# Maximum source latency value for clock sysClk (for both Slow and Fast corners)set_clock_latency -source -late 0.5 [get_clocks sysClk]
2.6.2 時鍾不確定性
2.6.2.1 時鍾抖動
對於 ASIC 設備,時鍾抖動通常表示在時鍾不確定性特征中。然而,對於 FPGA 來說,抖動特性是可以預知的。它們可以通過時序分析引擎自動計算,也可以單獨指定。
-
輸入抖動(Input Jitter)
輸入抖動是連續時鍾邊緣與理想時鍾到達時間的差別。輸入抖動是一個絕對值,表示時鍾邊緣兩側的變化。使用set_input_jitter
指令單獨指定每個基准時鍾的輸入抖動。衍生時鍾上的輸入抖動無法直接指定,Vivado 時序引擎會自動從主時鍾繼承的抖動到衍生時鍾。- 對於由 MMCM 或 PLL 生成的時鍾,輸入抖動被計算的不同的抖動替換。
- 對於由組合邏輯或時序邏輯生成的時鍾,生成時鍾抖動與其主時鍾抖動相同。
以下命令在通過輸入端口 clkin 傳播的基准時鍾上設置 +/-100 ps 抖動:
set_input_jitter [get_clocks -of_objects [get_ports clkin]] 0.1
-
系統拉動(System Jitter)
系統抖動是由於電源噪聲、板噪聲或系統的任何額外抖動而導致的整體抖動。使用set_system_jitter
指令只為整個設計設置一個值,即針對所有時鍾。
2.6.2.2 附加時鍾不確定性
使用 set_clock_uncertainty
指令定義不同角落、延時或特定時鍾關系所需的額外時鍾不確定性。這一種方便為設計增加額外余量的方法。
無論約束的順序如何,時鍾相互間的不確定性總是優先於簡單的時鍾不確定性。在下示例中,雖然時鍾 clk1 上最后定義了 1.0 ns 的簡單時鍾不確定性,但從時鍾 clk1 到時鍾 clk2 的計時路徑受到 2.0 ns 時鍾不確定性的限制。
set_clock_uncertainty 2.0 -from [get_clocks clk1] -to [get_clocks clk2]set_clock_uncertainty 1.0 [get_clocks clk1]