FPGA基礎學習(12) -- 多週期路徑約束
在我實際涉及的專案中,基本沒有遇到多週期路徑約束的情況,所以之前關注的不多,為了鞏固基本知識,藉此梳理這個約束。
1. 目的
目的就是說什麼時候需要用到多週期約束?
Vivado、TimeQuest等時序引擎預設是按照單週期關係分析資料關係的,即資料在發起沿傳送,在捕獲被捕獲,發起沿和捕獲沿相差一個週期。
但是很多情況是,資料路徑邏輯較為複雜,導致延時較大,使得資料無法在一個時鐘週期內穩定下來, 或者資料可以在一個時鐘週期內穩定下來,但是在資料傳送幾個週期之後才使用;在這些情況中,設計者的意圖都是使資料的有效期從發起沿為起始直至數個週期之後的捕獲沿,這樣的意圖無法被時序分析工具猜度出來,必須由設計者在時序約束中指明;否則時序分析工具會按照單週期路徑檢查的方式執行,往往會誤報出時序違規;
說白了,就是根據用於設計需求,改變原有的時序檢查機制,從而避免非真實的時序違例或者時序過緊導致的資源浪費。
2. 單週期時序檢查
如上圖所示,為時序引擎預設的單週期檢查機制。確定建立時間路徑和保持時間路徑規則如下:
建立時間路徑
以第一個傳送沿為基準(current launch),再向後尋找距此傳送沿最近的一個捕獲沿(current capture),並將兩者的setup定為1個週期。
保持時間路徑
每確定一個建立路徑,都會檢查兩個保持時間路徑:1)確保當前傳送沿推出的資料不被上一個捕獲沿給捕獲,即hold1;2)確保下一個傳送沿推出的資料不被當前捕獲沿給捕獲,即hold2。對這描述,為了便於分析記憶,簡而言之,1)previous capture與current launch 構成一組檢查;2)current capture與next launch 構成一組檢查。
對於兩條保持時間的檢查,時序報告最終只會給出裕量最小的一條。此外,還需要記住:
一旦確定建立時間路徑,保持時間路徑會自動根據規則做調整。
3. 使用方法
對於多週期路徑的約束語法,就一條指令:
set_multicycle_path
set_multicycle_path
[-from ] [-to ] [-through
引數名稱
含義
在預設的情況下,set_multicycle_path
對建立時間的分析是設定目的時鐘為多週期,即-setup 與-end 搭配使用;
對保持時間的分析是設定源時鐘為多週期,即-hold與-start搭配使用;
注意,上述是預設情況,-end和-start可以省略。根據場景不同會有所不同,並且數週期個數是往前還是往後也會不同,下面會介紹。
知道了命令引數的含義,結合第2節中的路徑規則的文字描述,那麼預設檢查機制就應該是下面的表達:
set_multicycle_path 1 -setup -end -from [get_clocks s_clk] -to [get_clocks d_clk]
set_multicycle_path 0 -hold -start -from [get_clocks s_clk] -to [get_clocks d_clk]
實際上這個約束的意義,就是
使引擎按照設計者的邏輯來重新定義路徑分析的規則
。如果沒有深刻理解多週期路徑,是不知道怎麼使用的。為什麼有的時候只需要setup,有的時候又需要setup和hold,怎麼加-start和-end又不清楚。所以結合文件給出的4中案例來加深對多週期路徑的理解,並且學會約束語句的使用。
4. 案例
4.1 同一時鐘域
在同一時鐘域下,有的時候,我們希望第一個傳送沿推出資料,經過N各週期才被被第二個暫存器的捕獲沿給捕獲。最常見的就是,時鐘使能控制資料捕獲的情形。
如上圖所示,假設使能訊號週期為驅動時鐘的2倍,顯然如果按照預設的規則進行時序檢查,就會發生錯誤。
首先,修改建立時間路徑,使用語句
set_multicycle_path 2 -setup -from [get_pins data0_reg/C] -to [get_pins data1_reg/D]
表示
以目的時鐘為基準,往前數,第2個沿作為捕獲沿
。
根據預設規則,保持路徑會自動調整,如圖AFTER。顯然這個時候的捕獲沿的確定是不合適的,會導致保持時序過緊(實現工具會透過增加資料延遲的方式,來最佳化時序,從而導致資源浪費,功耗增加)。所以增加修改hold規則語句:
set_multicycle_path 1 -hold -end -from [get_pins data0_reg/C] \
-to [get_pins data1_reg/D]
表示
以目的時鐘為基準,相較於預設的捕獲沿,往後數1個週期的沿作為實際的捕獲沿
。
綜上,得到最終的路徑關係,如下圖所示:
同理,針對setup延遲5個週期的情況,修改setup規則:
set_multicycle_path 5 -setup -from [get_pins data0_reg/C] -to [get_pins data1_reg/D]
隨著hold關係的自動變化,得到如下圖所示的情形。
修改hold規則,約束語句如下:
set_multicycle_path 4 -hold -end -from [get_pins data0_reg/C] -to [get_pins data1_reg/D]
表示以目的時鐘為基準,相較於預設的捕獲沿,往後數4個週期的沿作為實際的捕獲沿,如下圖所示
還有一種修改hold的方式,將-end改為-start,對應的關係如下圖所示。
那麼上面兩種情況有什麼區別?實際上,是一樣的,因為兩時鐘為同一時鐘域。所以
針對同一時鐘域,可以不考慮基準,即約束語句可以忽略-end或-start。
但是設計者一定要心裡清楚。
針對同一時鐘域的多週期路徑,一般語句可表示為:
set_multicycle_path N -setup -from [get_pins data0_reg/C] -to [get_pins data1_reg/D]
set_multicycle_path N-1 -hold -from [get_pins data0_reg/C] -to [get_pins data1_reg/D]
4.2 兩時鐘同一週期,但有相移
對於傳送和捕獲的兩時鐘是同週期,但存在相移。有兩種情況:clk2較clk1,正相移;clk2較clk1,負相移。
4.2.1 正相移
如下圖所示,clk2較clk1偏移+0。3ns。根據預設的檢查規則,建立和保持路徑已經在圖中表示出來。
可見,資料要在0。3ns之內滿足建立時間,這太緊了。反之,資料給的保持時間卻是-3。7ns,對於時序檢查又太寬鬆。先對建立時間放寬一些,使捕獲沿往後沿一個週期,約束如下:
set_multicycle_path 2 -setup -from [get_clocks CLK1] -to [get_clocks CLK2]
隨著建立路徑的修改,自動判斷新的保持路徑,如上圖所示。此時不需要在對保持路徑進行調整了,所以
這種情況只需要修改建立路徑規則即可
。
4.2.2 負相移
如下圖所示,clk2較clk1偏移-0。3ns。可見,此時的建立路徑和保持路徑即不太緊又不太鬆,可不進行多週期約束。
綜上,對於同週期不同相位的兩時鐘分析,必須要考慮相移方向和相移量。對於負相移,也不是絕對的不用新增約束,如果負相移量太大,實際上就可視為正相移,同樣需要新增約束。所以視情況而定。
4.3 從慢時鐘到快時鐘
假設捕獲時鐘為傳送時鐘頻率的3倍,預設的檢測機制如上圖所示。在實際設計中,捕獲暫存器肯定需要一個使能訊號,才能合理捕獲資料,這個時候會用到多週期路徑約束。同樣先修改建立路徑規則:
set_multicycle_path 3 -setup -from [get_clocks CLK1] -to [get_clocks CLK2]
隨著建立路徑的修改,自動判斷新的保持路徑,如上圖所示。這個時候的保持路徑檢查,
會導致消耗過多的資源,增加面積,增加功耗
,所以對保持路徑進行修改:
set_multicycle_path 2 -hold -end -from [get_clocks CLK1] -to [get_clocks CLK2]
注意,這種情況和同週期時鐘的多週期路徑約束有相似的地方。但是
此時-hold一定要增加-end
,表示
以目的時鐘為基準,較預設路徑,往回數2個週期作為捕獲沿
。
綜上,對於慢時鐘到快時鐘的情況,一般約束如下:
set_multicycle_path N -setup -from [get_pins data0_reg/C] -to [get_pins data1_reg/D]
set_multicycle_path N-1 -hold -end -from [get_pins data0_reg/C] -to [get_pins data1_reg/D]
4.4 從快時鐘到慢時鐘
如上圖所示,clk1是clk2頻率的3倍。原本預設檢查規則,滿足setup檢查的有3條路徑(有兩條是紅線補充),因為最終時序報告只會給出最苛刻的一條,所以只保留黑色這條setup路徑。
針對這種情況,需要同時修改建立路徑和保持路徑:
set_multicycle_path 3 -setup -start -from [get_clocks CLK1] -to [get_clocks CLK2]
set_multicycle_path 2 -hold -from [get_clocks CLK1] -to [get_clocks CLK2]
分析這兩條約束語句:首先,
-setup必須搭配-start,因為必須要以源時鐘為基準,再往後數;
然後,根據預設規則,保持路徑自動調整為紅色的路徑;最後,約束hold,因為hold預設搭配-start,所以以源時鐘為基準,往前數了2個時鐘沿。
綜上,對於快時鐘到慢時鐘的情況,一般約束如下:
set_multicycle_path N -setup -start -from [get_clocks CLK1] -to [get_clocks CLK2]
set_multicycle_path N-1 -hold -from [get_clocks CLK1] -to [get_clocks CLK2]
綜上所有案例,可總結到下圖中:
5. 補充說明
關於setup 和hold 搭配start和end之後,是往前數還是往後數週期個數
一開始被高老師的《vivado從此開始》中有關多週期路徑約束講述的一點誤導了,在對-hold引數描述時,是這樣寫的
-hold 表示分析保持時間時,相對於預設的捕獲沿實際捕獲沿應回撥的時鐘週期個數
“回撥”二字我理解偏了,以為有關hold,不論-start還是-end都往回數週期,結果始終分析不出正確的結果。最後細讀UG903,才看到下面一圖。
所以,
不論是setup還是hold,都可能往前數或者往後數,看具體搭配的是-start還是-end
。
時序過鬆、過緊?資源又過渡消耗?
對於多週期路徑約束的使用,我們無非就是要解決由於預設的規則導致時序誤判。但是什麼時候覺得過鬆或者過緊呢?實際上要深刻理解時序分析原理之後,靈活應用於多週期路徑分析。
如下圖所示,預設的檢查規則:
建立時間和保持時間裕量計算公式如下:
setup slack = (current latch edge - current launch edge ) + Tskew - (Tdelay + Tco + Tsu)
= T + Tskew - (Tdelay + Tco + Tsu)
hold slack = Tdelay + Tco - (Th + previous latch edge - current launch edge)
= Tdelay + Tco - Th
以4。1節兩時鐘是同一時鐘域的情況舉例,建立路徑延後1個週期,如下圖所示:
代入公式得到:
setup slack = (current latch edge - current launch edge ) + Tskew - (Tdelay + Tco + Tsu)
= 2*T + Tskew - (Tdelay + Tco + Tsu)
hold slack = Tdelay + Tco - (Th + previout latch edge - current launch edge)
= Tdelay+Tco - (T+Th)
可見,建立時間裕量增加了(多加了一個週期T),而保持時間裕量減少了(多減了一個週期T),這就導致保持時間過緊,實現的過程中需要儘可能增加Tdelay,這樣又會導致資源過度消耗,所以需要調整保持時間。
另一種情況,4。2。1 正相移那節中,如果hold路徑為負-3。7ns,根據公式,我的理解是保持裕量增加太多(減掉一個負數),導致時序太寬鬆。定性的理解就是,由於上一個捕獲沿在當前傳送沿的左邊(正相移導致),所以當前推送的資料,不太可能被上一個捕獲沿所捕獲。
上一篇:高併發架構設計漫談