FPGA時序分析—vivado篇

                                                                              FPGA時序分析—vivado篇

最近看了看了一篇《vivado使用誤區與進階》的文章,覺得寫得挺不錯了,看完後自己對時序分析又有了更深一層的理解,故記錄下來。可能排版有些亂,有些圖都是直接從文章中截取,但是不影響閱讀。

時序分析的基本步驟:

一個合理的時序約束可以分爲以下步驟:

時序約束整體的思路與之前我說的方法基本一致。整體的思路如下:

  1. 先是約束時鐘,讓軟件先解決內部時序問題;(在這一步驟中可以適當加入時序例外,以便時序通過)
  2. 然後再加入IO的延遲約束;
  3. 最後針對沒有過的時序,添加時序例外。

在《vivado使用誤區與進階》中,提到了一種叫 UltraFAST 的設計方法。針對下圖中所說的根據迭代結果添加必要的例外約束(步驟1),爲什麼是添加必要的呢?是因爲雖然是跨時鐘域,但是有時候就算不約束,時序也能過。當碰到時序不過的時候,現階段可以去針對該部分路徑進行時序例外約束,以便後續繼續分析。需要注意的是,就算沒有報時序爲例,現階段也一定要去留意那些跨時鐘的路徑(通過clock_interaction),確認代碼有沒有做相應的跨時鐘域處理。針對跨時鐘域的代碼處理後面會提到。

 

 

 

定義時鐘約束

時鐘主要可以分爲主時鐘以及衍生時鐘。

  • 創建主時鐘。典型的主時鐘根包括有以下幾種情況:輸入端口、千兆位收發器輸出引腳以及某些硬件原語輸出管腳。

約束實例 :

create_clock -name SysClk -period 10 -waveform {0 5} [get_ports sysclk]

 

GT 收發器輸入引腳,例如已恢復的時鐘,

 

約束實例 :

create_clock -name txclk -period 6.667 [get_pin gt0/TXOUTCLK]

 

  • 創建生成時鐘。

自動衍生時鐘

大部分生成時鐘都由 Vivado 設計套件時序引擎自動衍生獲得,該引擎可識別時鐘修改模塊 (CMB)及其對主時鐘所執行的變換。賽靈思 7 系列器件中,CMB 是 :

• MMCM*/ PLL*

• BUFR

• PHASER*

如果 Vivado 設計套件時序引擎所選擇的自動衍生時鐘名稱並不合適,您可以使用 create_generated_clock 命令強行定義自己的名稱,此時無需指定波形轉換。該約束應剛好位於約束文件中定義主時鐘的約束之後。例如,由 MMCM 實例生成的時鐘的默認名稱是 net0,您可以添加如下約束強制將其設定爲自己的名稱(例如fftClk):

create_generated_clock -name fftClk [get_pins mmcm_i/CLKOUT0]

 

生成時鐘源自另一個現有時鐘(主時鐘)。通常用來描述由邏輯模塊在主時鐘上執行的波形變換。由於生成時鐘的定義取決於主時鐘特性,因此必須首先定義主時鐘。要明確定義生成時鐘,必須使用 create_generated_clock 命令。

 

create_generated_clock -name GC1 -source [get_pins gen_clk_reg/C] -divide_by 2 [get_

pins gen_clk_reg/Q]

 

跨時終域處理

跨時鐘域處理,主要是爲了避免亞穩態的傳播(注意亞穩態不能消除,但是可以採用一定的方式,降低其傳播的風險)。觸發器進入亞穩態的時間可以用參數MTBF(Mean Time Between Failures)來描述,MTBF即觸發器採樣失敗的時間間隔,表示爲:

  http://www.ofweek.com/Upload/plainimages/Kevin/images/img6/w79.JPG

例如針對單bit數據的跨時鐘域處理,是爲了讓MTBF增大,使得進入一個可接受範圍。

*跟大家探討一個問題,爲什麼打兩拍就可以降低亞穩態的傳播呢?

我想到的一個場景如下:

信號a,經過跨時鐘處理後變成了a’;這樣就可以確保在時序滿足的前提下,同一個時鐘域中的1、2、3模塊接收到的a’的值是一致的,如果不做跨時鐘域處理,由於佈局佈線的延遲不一樣,不能確保到達1、2、3模塊的值是一致的,從而導致邏輯混亂,引起系統的不穩定現象。

 

IO的延遲約束

輸入延遲

外部器件發送數據到FPGA系統模型如下圖所示。對FPGAIO口進行輸入最大最小延時約束是爲了讓FPGA設計工具能夠儘可能的優化從輸入端口到第一級寄存器之間的路徑延遲,使其能夠保證系統時鐘可靠的採到從外部芯片到FPGA的信號。

輸入延時即爲從外部器件發出數據到FPGA輸入端口的延時時間。其中包括時鐘源到FPGA延時和到外部器件延時之差、經過外部器件的數據發送Tco,再加上PCB板上的走線延時。如下圖所示,爲外部器件和FPGA接口時序。

最大輸入延時(input delay max)爲當從數據發送時鐘沿(lanuch edge)經過最大外部器件時鐘偏斜(Tclk1),最大的器件數據輸出延時(Tco),再加上最大的PCB走線延時(Tpcb),減去最小的FPGA時鐘偏移(FTsu)的情況下還能保證時序滿足的延時。這樣才能保證FPGA的建立時間,準確採集到本次數據值,即爲setup slack必須爲正,計算公式如下式所示:

    Setup slack =Tclk + Tclk2(min)Tclk1(max) +Tco(max) +Tpcb(max) +FTsu≥0    1

最小輸入延時(input delay min)爲當從數據發送時鐘沿(lanuch edge)經過最小外部器件時鐘偏斜(Tclk1),最小器件數據輸出延時(Tco),再加上最小PCB走線延時(Tpcb),此時的時間總延時值一定要大於FPGA的最大時鐘延時和建立時間之和,這樣才能不破壞FPGA上一次數據的保持時間,即爲hold slack必須爲正,計算公式如下式所示:

    Hold slack = Tclk1(min) + Tco(min) + Tpcb(min)FTh + Tclk2(max)≥ 0     2

 

我們很容易就可以從公式(1)和(2),推到出(3)

Tclk – Ftsu ≥Tclk1  - Tclk2 + Tco + Tpcb ≥ FTh     3

在公式(3)中,我們發現Tclk Ftsu以及FTh,對於工具來說是已知的,而Tclk1  - Tclk2 + Tco + Tpcb正是我們需要告知綜合工具的延遲量。

從我們推到出的公式,我們可以得到

Input_delay_max = Tclk – Ftsu;     Input_delay_min = FTh ;        

 

輸出延遲

FPGA輸出數據給外部器件模型如下圖所示。對FPGAIO口進行輸出最大最小延時約束是爲了讓FPGA設計工具能夠儘可能的優化從第一級寄存器到輸出端口之間的路徑延遲,使其能夠保證讓外部器件能準確的採集到FPGA的輸出數據。

輸出延時即爲從FPGA輸出數據後到達外部器件的延時時間。其中包括時鐘源到FPGA延時和到外部器件延時之差、PCB板上的走線延時以及外部器件的數據建立和保持時間。如所示,爲FPGA和外部器件接口時序圖。

最大輸出延時(output delay max)爲當從FPGA數據發出後經過最大的PCB延時、最小的FPGA和器件時鐘偏斜,再加上外部器件的建立時間。約束最大輸出延時,是爲了約束IO口輸出,從而使外部器件的數據建立時間,即爲setup slack必須爲正,計算公式如下式所示:

Setup slack =Tclk + Tclk2(min)Tclk1(max) +FTco(max) +Tpcb(max) +Tsu≥0 4

最小輸出延時(output delay min)爲當從FPGA數據發出後經過最小的PCB延時、最大的FPGA和器件時鐘偏斜,再減去外部器件的建立時間。約束最小輸出延時,是爲了約束IO口輸出,從而使IO口輸出有個最小延時值,防止輸出過快,破壞了外部器件上一個時鐘的數據保持時間,導致hlod slack爲負值,不能正確的鎖存到數據,最小輸出延時的推導計算公式如下式所示:

    Hold slack = Tclk1(min) + FTco(min) + Tpcb(min)Th + Tclk2(max)≥ 0  5

我們很容易就可以從公式(4)和(5),發現這兩條公式與前面推導輸入延遲如出一轍。只不過現在FPGA變成了輸出器件,而TsuTh是下游器件的參數,綜合工具並不知情,需要我們告訴他。除了FTco以外,其他參數都需要我們告訴工具。

由公式(4)我們可以推導出:

FTco(max) + Tpcb(max) Tclk2(min) – Tclk1(max)+Tsu ≤Tclk

那麼output delay max = Tpcb(max) Tclk2(min) – Tclk1(max)+Tsu

同理我們由公式(5)可以推導出:

FTco(min) + Tpcb(min) Tclk2(max) – Tclk1(min)– Th ≥ 0

那麼output delay min = Tpcb(min) Tclk2(max) – Tclk1(min)– Th

 

時鐘爲例的一些處理方法

下面是我收集到的一些針對時序爲例的常規處理辦法,也記錄下來與大家分享一下:

 

下面介紹主要面對的兩個時序問題的處理技巧。

 

1)setup time 建立時間問題

 

建立時間是工程設計中最常遇到的問題了。一般說來,導致建立時間違例主要有兩個原因:邏輯級數太大或者扇出太大。

 

打開Report Timing Summary界面查看路徑延遲信息。

Levels指的是邏輯級數logic level,一個logic level的延遲對應的是一個LUT和一個Net的延遲,對於不同的器件,不同頻率的設計能容納的logic level是不同的。假設7系列的-2速度等級250MHz的設計,電路設計的大部分levels最好不要超過8,否則會造成時序收斂困難。

 

Logic level太大的處理方法就是重定時(Retiming)了,典型的重定時方法就是流水線,將過於冗長的組合邏輯增加寄存器進行打拍。

 

High Fanout指的是扇出,同樣和器件、設計頻率等有關,如下圖所示:

 

 

降低扇出最好不要在綜合設置中指定,過低的扇出限制會造成設計堵塞反而不利於時序收斂,最好的方法是根據設計中時序最差路徑的扇出進行針對性的優化。如果是寄存器的輸出扇出很大,可以使用max_fanout屬性標記寄存器聲明,也可以手動複製寄存器,具體可參考:https://blog.csdn.net/shshine/article/details/52451997

 

如果不是關鍵時序路徑,而且高扇出網絡直接連接到觸發器,對扇出超過25K的net插入BUFG:

 

set_property CLOCK_BUFFER_TYPE BUFG [get_nets netName]

當然,也可以在後期Implementation的物理優化設置中優化扇出。

 

2)hold time 保持時間問題

在實踐中,我發現保持時間問題的問題往往是異步處理的問題。

對於一個信號的跨時鐘域問題,一般使用雙寄存器法(對於慢採快的結繩法這裏不討論)。爲了降低MTBF(Mean Time Between Failures,平均無障礙時間),這兩個寄存器最好位於同一個slice中。可以使用tcl語言指定,如:

set_property ASYNC_REG TRUE [get_cells [list sync0_reg sync1_reg]]

也可以直接在代碼中指定:

(* ASYNC_REG = "TRUE" *) (* keep = "true" *)reg sync0_reg, sysnc1_reg;

也可以參考代碼模板使用XPM模板進行處理。

 

 

 

 

 

**注意:

  1. 在發現同一個時鐘域中,時序還不滿足要求,那應該怎麼處理呢?

(這時候只能在修改代碼方向努力了,回到Chipplanner中,分析關鍵路徑,看佈線後的路徑是否過長,導致影響時序。還是由於高扇出導致時序爲例。針對不同的原因,修改代碼。比如說,路徑過長,通常檢測是否代碼中嵌套的if語句級數太多?(可以嘗試case語句替代),又或者if的判斷中有表達式(if(a>b)之類的,看能否用電平替代,if(en)等,)對於有些邏輯融合起來一個大的模塊,看能否將大的邏輯塊劃分爲若干個小邏輯塊實現。

針對高扇出問題,上述已提到相應的處理方式。

       寫到最後想說的是,調時序是一個比較難啃的活,有時候你增加了約束可能時序還會變的更差了,所以說一個良好的代碼風格很重要。假如上述的方法都已經試過了,時序還是很難滿足,可能器件已經快到達極限了,尤其是資源佔用率比較高的時候。這時候只能降低時鐘或者替換更高性能的器件啦。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章