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]
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/296037.html
標籤:Verilog
下一篇:Verilog實體陣列
