正反器的兩個要求:時脈邊緣周圍的一扇窗
在第 1 階,你認識了時序路徑:發射端正反器在某個時脈邊緣射出資料,資料一路衝過一些邏輯閘,一個時脈滴答之後,捕捉端正反器必須讀到一個穩定的值。那個說法帶著一種令人安心的含糊——「資料必須及時抵達」。這一階要把它講清楚。真實的正反器並不是在時脈上升的那一瞬間就採樣;採樣是一個微小的物理動作,是把電子捕進一個迴授環路裡,而這個動作需要資料在邊緣的兩側都靜止一小段時間。
這兩小段都有名字。建立時間(t_su)是資料在時脈邊緣之前就必須已經穩定多久——也就是助跑。保持時間(t_h)是資料在邊緣之後還必須維持穩定多久——也就是收尾。兩者一起,在每個上升邊緣周圍劃出一塊禁區:一扇窗,在這扇窗之內,資料輸入根本不准改變。一旦違反,正反器可能捕到一個成形到一半的值、一個毛刺,或者最糟的——飄進亞穩態,一個懸在 0 與 1 之間、遲遲未決的狀態,要花多久才解開無法預測,有時甚至是災難性的。
THE FORBIDDEN WINDOW AROUND ONE CLOCK EDGE
CLK ____________|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
^ capture edge (rising)
|
<-- t_su -->|<-- t_h -->
___________|___________
D XXXXXXXXXXX|‾‾‾‾‾‾‾‾‾‾‾XXXXXXXXX
valid & | valid & may change
stable | stable again here
|
|<<<<<< must NOT change >>>>>>|
(the setup/hold window)
Inside the window the data MUST be steady.
Break the left edge of it -> SETUP problem (data too late).
Break the right edge of it -> HOLD problem (data too early).建立檢查:資料必須夠早抵達
想像一場接力賽,棒子必須在哨音響起之前交出去,而且還要留一點餘裕。發射端正反器在某個時脈邊緣射出棒子(資料);棒子跑過邏輯;它必須抵達捕捉端正反器的門口,並且在下一個時脈邊緣抵達之前,至少 t_su 就先站定不動。建立檢查只問一個問題:資料及時抵達了嗎?而且還留有建立餘裕?如果路徑太慢,哨音響起時棒子還在半空中——那就是建立違規。
讓我們用晶片的視角把它寫出來。資料在捕捉端正反器的抵達時間,等於發射邊緣時刻,加上發射端正反器的時脈到輸出延遲(t_cq,也就是發射端在自己的邊緣之後過多久才真正驅動輸出),再加上路徑上的組合邏輯延遲(t_logic)。要求時間——也就是截止期限——則是捕捉邊緣(晚一個時脈週期 T)減去我們必須預留的建立時間。建立檢查就只是一句抵達 ≤ 要求。
SETUP CHECK (the LATE / slow-path check)
arrival_time = T_launch + t_cq + t_logic(MAX)
required_time = T_capture - t_su = T_launch + T - t_su
PASS if: arrival_time <= required_time
i.e. t_cq + t_logic(MAX) <= T - t_su
Read it in words:
"clock-to-Q + worst-case logic delay
must fit inside one clock period,
minus the setup time we owe the capture flop."
Note: setup uses the MAXIMUM (slowest) path delay,
because the worst enemy of a deadline is slowness.保持檢查:資料不可太快改變
現在把擔憂反過來。建立檢查害怕資料對*這個*時脈邊緣來說太晚抵達。保持檢查則害怕資料太早抵達——早到它破壞了捕捉端正反器正想在棒子被射出的同一個邊緣所抓取的那個值。微妙之處在這裡:發射端與捕捉端共用時脈,所以當一個邊緣觸發發射端時,*同一個*邊緣也正是捕捉端用來採樣的那個。如果新資料衝過邏輯衝得太快,在舊資料還沒被安全鎖住之前就抵達捕捉端的門口,捕捉端就會抓到錯的值。
所以保持檢查守的是那扇禁窗的右緣。新資料至少要在捕捉邊緣之後 t_h 才能抵達。它的抵達時間是*同一個*發射邊緣,加上 t_cq,再加上最小邏輯延遲(最快、最短的路徑——因為這裡的危險是資料太快)。要求時間則是捕捉邊緣加上保持時間。保持檢查是抵達 ≥ 要求——和建立不等式相反的方向。
HOLD CHECK (the EARLY / fast-path check)
Both flops sample on the SAME edge here (no +T !):
arrival_time = T_launch + t_cq + t_logic(MIN)
required_time = T_launch + t_h
PASS if: arrival_time >= required_time
i.e. t_cq + t_logic(MIN) >= t_h
Read it in words:
"new data must take LONGER to arrive than the
hold time, so the OLD data is safely captured
before the new data overwrites it."
Note: hold uses the MINIMUM (fastest) path delay,
and the clock period T does NOT appear at all.一個實際算例:看兩條規則互鬥
用數字會更具體。取一條介於兩個正反器之間的路徑,時脈為 1 GHz,所以週期 T = 1000 ps。從元件庫拿到:時脈到輸出 t_cq = 80 ps、建立時間 t_su = 50 ps、保持時間 t_h = 40 ps。兩個正反器之間的邏輯,最壞情況(max)延遲為 t_logic(max) = 700 ps,而由於某些輸入會抄近路只經過單一閘極,最佳情況(min)延遲為 t_logic(min) = 30 ps。讓我們把兩道檢查都跑一遍。
GIVEN: T = 1000 ps t_cq = 80 t_su = 50 t_h = 40
t_logic(max) = 700 t_logic(min) = 30 (all ps)
-- SETUP (late check, uses MAX logic) --------------------
arrival = t_cq + t_logic(max) = 80 + 700 = 780 ps
required = T - t_su = 1000 - 50 = 950 ps
slack = required - arrival = 950 - 780 = +170 ps PASS
"Data lands 170 ps before its deadline." Comfortable.
-- HOLD (early check, uses MIN logic, NO T) --------------
arrival = t_cq + t_logic(min) = 80 + 30 = 110 ps
required = t_h = 40 ps
slack = arrival - required = 110 - 40 = +70 ps PASS
"New data is 70 ps slower than the hold needs." Safe.
Both pass -> this path is clean at 1 GHz.現在看它們互鬥。假設這條路徑建立失敗了——比方說邏輯其實是 1000 ps,抵達 1080 ps 對上要求 950 ps,建立裕度為 −130 ps。直覺是把邏輯加快。但如果一位資淺工程師改用插入緩衝器來「*放慢時脈在發射端的抵達*」來「修」它,或者更糟,如果有人把邏輯削得太狠,讓短路徑掉到 0 ps 呢?那麼保持抵達就變成 80 + 0 = 80 ps 對上要求 40 ps——這裡還算沒事,但你能感覺到那股張力:任何你為了加快長路徑所做的事,都有可能連帶加快短路徑,吃掉保持裕度。
兩種違規,兩種截然不同的修法
因為這兩道檢查住在窗的兩側、各自用路徑延遲的相反極端,所以它們的解藥也是相反的——而把它們搞混,正是新手最常犯的錯誤之一。建立違規意味著長路徑太慢,趕不上截止期限。你靠買時間來修它:加快邏輯,或放寬期限。
- 修建立違規靠把長路徑變快——把閘極換成更大、驅動更強的;用更好的合成減少邏輯層數;在關鍵路徑上改用低臨界電壓(更快、漏電更多)的元件;或用管線化把路徑切開。
- 或者靠放寬期限來修建立——降低時脈頻率(更長的週期 T),這是一個用性能換裕度的、最暴力的逃生口。
- 修保持違規則用相反的方法——把短路徑變*慢*。標準工具是緩衝器(延遲)插入:在那條太快的路徑上放進額外的元件,純粹為了加上幾皮秒,好讓新資料不再贏過保持時間。
保持違規意味著短路徑太*快*——新資料在舊資料被安全抓住之前就把它覆蓋掉了。第一次遇到時,這帖解藥幾乎像個悖論:你刻意對一條邏輯上已經沒問題的路徑加上延遲,靠插入緩衝器把它放慢,而這些緩衝器唯一的工作就是浪費幾皮秒。你不是在加邏輯;你是在跑道上加長度,好讓跑者沒辦法太早衝過終點線。
從兩條規則到一個數字
退一步看,整個時序分析就只是這兩道不等式,同時套用到晶片上的每一條路徑。建立:最慢的資料必須在 T − t_su 之前抵達。保持:最快的資料必須在 t_h 之後抵達。一個防遲到,一個防早到;一個在意時脈週期,另一個完全無視它;一個用速度治,另一個用延遲治。掌握了這個差別,你就握住了靜態時序分析的概念核心——後面所有的東西(時脈偏斜、角點、串擾)都只是在精修,精修我們在這同樣兩道檢查裡,*多精確地*算出抵達時間與要求時間。
還有一步,能把這些通過/失敗的不等式,變成工程師真正天天打交道的那個單一數字。在每道檢查裡,取要求時間與抵達時間的差——那道縫隙就是時序裕度(slack)。正裕度代表還有餘裕;負裕度代表違規,而且就差那麼多。在我們的算例裡,建立裕度是 +170 ps、保持裕度是 +70 ps:兩個都是正的、都安全。在第 3 階,我們會讓裕度當主角,學著從一份真實的時序報告上逐行讀它,並用它找出那一條——關鍵路徑——為整顆晶片定下速度上限的路徑。