
做FPGA設(shè)計的人總有一天會被“時鐘資源”這四個字卡住。尤其是當(dāng)你把工程從仿真搬到板子上發(fā)現(xiàn)時序收斂不了、采樣老出錯、PLL怎么都鎖不上翻來覆去排查半天根子往往就在時鐘資源的規(guī)劃和使用上。這篇文章想圍繞FPGA時鐘資源這個主題把時鐘網(wǎng)絡(luò)、時鐘管理模塊、時鐘約束、時序質(zhì)量這些事從頭到尾捋一遍聊清楚它們是什么、為什么重要、怎么用、怎么避坑。適合正準(zhǔn)備開始做時序收斂的FPGA開發(fā)者也適合被“時鐘偏斜”“BUFG不夠用”“時鐘域亂跳”折磨過但沒時間翻手冊的工程師。1. 先把時鐘資源家族認全FPGA里面負責(zé)時鐘的硬件資源不是一個東西而是一整套體系。很多人只聽說過“PLL”以為時鐘資源就是PLL其實PLL只是其中一個環(huán)節(jié)。真正重要的是后面那棵“時鐘樹”以及連接時鐘進入FPGA的專用引腳。這套體系可以粗略分成三大類全局時鐘網(wǎng)絡(luò)、區(qū)域時鐘與IO時鐘、時鐘管理模塊。每一類管的事不一樣用錯了后面的時序報告就會給你顏色看。1.1 全局時鐘網(wǎng)絡(luò)芯片里的“城市主干道”全局時鐘網(wǎng)絡(luò)也就是常說的長線時鐘資源是FPGA里最穩(wěn)定、覆蓋范圍最大、偏斜最小的時鐘通路。你可以把它理解成一座城市的環(huán)形主干道所有關(guān)鍵街區(qū)都能快速到達而且紅綠燈設(shè)置得很均勻。普通邏輯互連資源則是小巷子走通能通但每條巷子的長度、彎道都不一樣信號到達時間自然千差萬別。時鐘信號如果走在普通互連上每個寄存器收到的時鐘邊沿會有明顯差異這就是偏斜。全局時鐘網(wǎng)絡(luò)從專門的時鐘引腳進入FPGA后會經(jīng)由全局緩沖器再分往整個芯片。這個緩沖器就是BUFG——GA緩沖器。BUFG的延遲通常是固定的而且網(wǎng)絡(luò)內(nèi)部做了負載均衡所以芯片左上角寄存器和右下角寄存器收到同一個時鐘邊沿的時間差可以壓得很低只有幾百皮秒甚至更低。它對全局的高扇出信號特別友好所以不只是時鐘復(fù)位信號、高扇出的控制使能信號也經(jīng)常借用全局時鐘網(wǎng)絡(luò)來驅(qū)動。我見過不少剛上手的工程師FPGA里明明有全局時鐘網(wǎng)絡(luò)因為不熟悉直接把內(nèi)部邏輯產(chǎn)生的一個信號當(dāng)“時鐘”接到寄存器時鐘端結(jié)果工具也不吭聲最后就是時序報告一堆違例跑起來偶發(fā)出錯。記住一個原則真正決定系統(tǒng)節(jié)拍的時鐘特別是外部引腳進來的參考時鐘一定要想辦法接到BUFG讓工具把它放到全局時鐘布線上。1.2 區(qū)域時鐘與IO時鐘特定范圍內(nèi)的專用通道不是所有信號都需要滿芯片范圍內(nèi)都拉一條低偏斜時鐘線。器件大了以后全局時鐘網(wǎng)絡(luò)覆蓋的路徑更長占用資源也多。為了兼顧靈活和效率FPGA內(nèi)部還會劃分為多個時鐘區(qū)域每個區(qū)域有獨立的區(qū)域時鐘緩沖器一般叫BUFH之類。區(qū)域時鐘只能驅(qū)動本區(qū)域的邏輯延遲更短、資源開銷更小適用于那些只影響一小片局部的同步邏輯。還有一類是專門為輸入輸出寄存器準(zhǔn)備的IO時鐘它有著更強的驅(qū)動能力和特殊的加速路徑用來做高速源同步接口的采集時鐘。比如你接一塊外部ADC數(shù)據(jù)線帶一個隨路時鐘DCODCO進來后通常不應(yīng)該直接送全局時鐘網(wǎng)絡(luò)繞一圈而是就近接到區(qū)域時鐘或者IO時鐘鏈路這樣數(shù)據(jù)引腳和時鐘引腳之間的走線延遲關(guān)系更容易控制采樣窗口更好。這里需要特別留意區(qū)域時鐘不是“隨便一個普通IO都能進”的你得用器件手冊上標(biāo)明的專用時鐘引腳區(qū)域。換句話說外部時鐘信號進入FPGA的位置是有講究的。如果你的PCB原理圖上時鐘信號接到了普通數(shù)據(jù)引腳上就算邏輯上能功能仿真通過實際時序也大概率做不好甚至工具直接提示這條路徑?jīng)]有足夠的時鐘布線資源。1.3 時鐘管理模塊給時鐘做“整形”和變頻接下來是大家最熟悉的時鐘管理模塊PLL是鎖相環(huán)MMCM是混合模式時鐘管理器很多中高端FPGA上配的是MMCM早期器件則常用DCM這類延遲鎖定環(huán)。功能上它們差不多對外部輸入時鐘做倍頻、分頻、相移、占空比調(diào)整有的還能把輸入的差分時鐘轉(zhuǎn)成單端時鐘順便過濾一部分抖動。PLL內(nèi)部的VCO壓控振蕩器工作范圍是有講究的。比如一個輸入時鐘是50MHz邏輯需要200MHz看起來倍頻系數(shù)是4就夠了。但很多器件PLL要求VCO頻率在某個范圍內(nèi)比如400MHz到800MHz那你不能在200MHz頻率點直接讓VCO停住而是要讓VCO先跑到中段頻率比如600MHz再分頻三次得到200MHz。配置工具通常會自動算但理解這個機制很重要否則你換一顆器件PLL配置評估就會報“頻率超出范圍”或者“找不到合適的VCO頻率”。PLL輸出的時鐘如果是要發(fā)給全芯片邏輯用的一般還需要再過一級BUFG才能真正到全局網(wǎng)絡(luò)。很多工程軟件會自動幫你插入這級緩沖但如果你的工程里手動例化了PLL又沒合理設(shè)置時鐘資源屬性就可能會出現(xiàn)“PLL輸出時鐘沒有到全局布線資源上”這種隱蔽問題表現(xiàn)為時序分析里局部路徑偏斜特別大。所以看資源報告時不光要看PLL鎖沒鎖上還要看它的輸出到底走了哪一類時鐘布線。2. 時鐘方案怎么選不是越“高級”越好拿到一個項目需求外部時鐘頻率多少、需要產(chǎn)生幾路內(nèi)部時鐘、每路時鐘要用在哪里這些信息直接決定你選哪類資源。別看到一個“全局時鐘網(wǎng)絡(luò)”就覺得什么都往上放也別覺得PLL萬能。合理的方案往往是把不同種類的資源組合起來用。2.1 從使用場景倒推資源選擇我習(xí)慣把FPGA里的時鐘需求分成四類每類對應(yīng)一種默認資源主時鐘也就是系統(tǒng)同步邏輯的節(jié)拍通常來自外部晶振或參考時鐘頻率比較高扇出非常大所有寄存器都用它。這種一定要走全局時鐘網(wǎng)絡(luò)。如果主時鐘頻率由PLL產(chǎn)生那PLL輸出再配一級全局緩沖就是最常見的標(biāo)準(zhǔn)結(jié)構(gòu)。局部功能模塊的時鐘比如某個接口模塊內(nèi)部用到的同步時鐘只影響模塊內(nèi)幾百個寄存器用一個區(qū)域時鐘就夠了。區(qū)域時鐘延遲更短而且不占用寶貴的主時鐘通路。高速源同步接口的采集時鐘比如DDR接口或者高速ADC/DAC數(shù)據(jù)流帶隨路時鐘這種時鐘往往直接送到IO時鐘入口讓數(shù)據(jù)和時鐘在IO寄存器處保持精確相位關(guān)系。把這種慢速使用的時鐘繞進全局網(wǎng)絡(luò)反而會增加采樣不確定性。特殊用途的時鐘比如調(diào)試時用的觸發(fā)器信號、外部輸入中斷脈沖扇出不大對偏斜不那么敏感如果直接拿普通互連資源驅(qū)動也不算致命。但需要注意任何作為“異步事件”的信號本來就不應(yīng)該出現(xiàn)在時鐘路徑上更合適的是當(dāng)成普通數(shù)據(jù)做同步。為方便對比我把常見資源、覆蓋范圍和典型用途整理成了下面這張表資源類型覆蓋范圍延遲與偏斜特點最典型用途全局時鐘網(wǎng)絡(luò)整個芯片延遲固定偏斜極低系統(tǒng)主時鐘、全局復(fù)位區(qū)域時鐘單個或相鄰時鐘區(qū)域延遲短局部偏斜低局部模塊時鐘IO時鐘IO寄存器周邊與數(shù)據(jù)引腳時序緊密對齊DDR接口、源同步采集PLL/MMCM頻率變換與相位調(diào)整鎖定后輸出穩(wěn)定倍頻、分頻、相移這里有一點要注意區(qū)域時鐘和IO時鐘的可用數(shù)量、連接關(guān)系與具體器件強相關(guān)同一個工程換器件型號時鐘方案很可能要重新審核。2.2 時鐘樹規(guī)劃的提前量畫板前就要想時鐘方案的規(guī)劃最忌諱在PCB畫完、甚至貼片完才做。外部時鐘信號進入FPGA用的是專用時鐘引腳不同位置的引腳對應(yīng)到不同的全局時鐘入口、區(qū)域時鐘區(qū)域。如果你把外部時鐘隨便接了一個普通引腳后期就算內(nèi)部邏輯想給它接BUFG也很難布線因為你繞不開管腳本身的位置約束。我自己吃過一次虧。某個小項目里原理圖把外部時鐘接到了一個全能IO功能是可以的但布局布線跑到全局時鐘網(wǎng)絡(luò)延遲偏大區(qū)域時鐘資源又進不去。當(dāng)時改了一版PCB多花了兩周。所以現(xiàn)在做方案我一定會提前確認外部時鐘引腳是否可直達全局緩沖差分時鐘是否走了專用差分對復(fù)位按鍵信號要不要上全局網(wǎng)絡(luò)這些在FPGA管腳分配階段就要定好。另一個提前量是PLL輸入和輸出的數(shù)量。FPGA的時鐘管理模塊不是很多每個PLL能接的參考時鐘也有限。如果一個模塊接了多個PLL而每個PLL又都在做不同頻率變換那么規(guī)劃時就要核對功耗和資源余量。尤其是多路視頻或通信項目動輒需要五六組內(nèi)部時鐘可能要做PLL級聯(lián)先用一路主PLL產(chǎn)生基頻再分配給第二級PLL或分頻器。2.3 別輕易使用門控時鐘寫RTL時很容易圖省事把某個使能信號和時鐘做一個與門得到一個“只在使能時跳變的時鐘”然后把門控時鐘接到寄存器上。這種糊口式寫法在仿真階段完全沒問題甚至看起來功耗還低因為不工作時時鐘不翻轉(zhuǎn)。但在FPGA實現(xiàn)階段門控時鐘會帶來兩類非常麻煩的問題。第一是毛刺風(fēng)險。與門的兩個輸入如果存在競爭冒險輸出時鐘上可能蹦出窄脈沖如果這個窄脈沖正好被寄存器采到數(shù)據(jù)就可能寫壞。第二是靜時序分析困難。工具默認把時鐘當(dāng)作周期信號來推導(dǎo)約束你的門控時鐘讓時序分析器很難定義時鐘邊沿要么你得寫復(fù)雜的約束要么干脆標(biāo)記成虛假路徑收斂質(zhì)量大打折扣。推薦的做法是保留時鐘一直翻轉(zhuǎn)用時鐘使能信號配合寄存器。比如一個計數(shù)器只有在數(shù)據(jù)有效的周期才計數(shù)就讓使能信號進到時鐘域內(nèi)同步后再控制計數(shù)器而不是在時鐘路徑上插入門控。這幾乎可以省掉一大類“偶發(fā)數(shù)據(jù)錯誤”。除非你有極強的低功耗設(shè)計需求且對毛刺做過專門分析否則盡量不要直接門控時鐘。3. 實操把時鐘資源真正用起來講完理論說說在工程里怎么把時鐘資源配置出來。我以一個真實的工程片段為例外部提供50MHz晶振系統(tǒng)邏輯需要200MHz的主時鐘另外一路接口需要75MHz參考時鐘還有一路外部ADC需要50MHz、相位滯后90度的采樣時鐘。3.1 從50MHz晶振到三組輸出時鐘先算頻率方案。主流FPGA里配置PLL時輸入50MHz要得到200MHz單純倍頻系數(shù)是4。但許多PLL的VCO范圍有下限比如最低400MHz那VCO就不能直接鎖在200MHz點。這時要讓VCO在600MHz附近工作再通過分頻器得到200MHz。75MHz可以由600MHz除以8得到50MHz帶90度相移則是在600MHz分頻配相移后得到。整個配置界面里會要求你填入輸入時鐘、輸出時鐘頻率、相移數(shù)值工具自動給出M、D、O乘數(shù)分頻關(guān)系。實操時我一般會先把VCO頻率挑在器件標(biāo)稱范圍的中段附近這樣留有余量對溫度變化更穩(wěn)。配置完成后工具會生成一個時鐘模塊的IP核接口大致長這樣clk_gen u_clk_gen ( .clk_in (clk_in_50m), .clk_out_200m (clk_200m), .clk_out_75m (clk_75m), .clk_out_50m_90(clk_50m_90), .locked (pll_locked) );這里clk_in_50m是從專用時鐘引腳進來的外部時鐘信號locked是PLL鎖定指示復(fù)位邏輯一定要等它拉高后再釋放不然早期時鐘還沒穩(wěn)定寄存器可能被寫入未知狀態(tài)。有一點值得提醒如果只是借用某個廠商工程向?qū)傻腎P接口名可能略有差異但關(guān)鍵信號基本都長這樣。真正需要關(guān)心的是例化后綜合的資源報告看你生成了幾個PLL、幾個全局緩沖。如果工具報了“全局時鐘緩沖不足”往往不是真的不夠用而是你把這個IP例化了很多份每份都帶一個全局緩沖。3.2 時鐘約束書寫讓時序分析器知道你的時鐘長什么樣有了時鐘網(wǎng)絡(luò)還要在時序約束里把你“希望工具認為的時鐘”告訴它。常見工具支持SDC約束最基礎(chǔ)的就是創(chuàng)建時鐘。以外部100MHz輸入為例create_clock -name sys_clk -period 10.000 [get_ports clk_in_100m]period 10.000表示時鐘周期10納秒也就是100MHz。這條約束告訴時序分析器從clk_in_100m引腳進來的信號是系統(tǒng)主時鐘周期10ns。PLL內(nèi)部生成的時鐘工具會根據(jù)IP配置自動往后推衍不需要你手動再定義只要時鐘源被正確約束了就行。實際項目里我通常還會跟上時鐘不確定度約束set_clock_uncertainty -setup 0.150 -hold 0.050 [get_clocks sys_clk]setup不確定度設(shè)得比hold大是因為它要包含時鐘抖動、板級噪聲、PLL相位噪聲等影響而hold相對更偏靜態(tài)。不確定度設(shè)置需要根據(jù)硬件質(zhì)量來別拍腦袋設(shè)太大余量太大容易把自己逼進“時序永遠收斂不了”的死胡同設(shè)太小又會讓工具盲樂觀板子上跑起來就可能翻車。另外要提到跨時鐘域約束。如果你有多個主時鐘而且彼此之間沒有確定相位關(guān)系就要用時鐘分組把它們設(shè)為“異步”的set_clock_groups -asynchronous \ -group [get_clocks sys_clk] \ -group [get_clocks pcie_refclk]這段約束的意思是兩個時鐘域之間的路徑時序分析器不需要檢查因為設(shè)計里已經(jīng)有跨時鐘域同步策略了。沒有這條約束工具默認去約束兩個異步時鐘之間的路徑會產(chǎn)生大量假違例。3.3 手動插入BUFG的時機與方法多數(shù)情況下工具會在綜合和布局布線階段自動插入全局緩沖不需要你手動干預(yù)。但有幾類場景需要手動指定比如復(fù)位的同步釋放邏輯你想確保復(fù)位釋放沿在全芯片內(nèi)基本同時到達又比如某個內(nèi)部生成的時鐘你想強制它上全局網(wǎng)絡(luò)再比如從GTP/Serdes恢復(fù)出來的時鐘跨時鐘域之前希望先走一遍全局緩沖整形。手動指定的一般方法是設(shè)置網(wǎng)絡(luò)屬性。以復(fù)位網(wǎng)絡(luò)為例可以在綜合工具里把復(fù)位網(wǎng)絡(luò)指定為全局緩沖set_property CLOCK_BUFFER_TYPE BUFG [get_nets rst_sync]注意這里的屬性名只是示意不同工具可能叫法不同但思路一致命名一個高扇出的網(wǎng)把它分配到全局時鐘緩沖器。手動指定時我會先查一下網(wǎng)絡(luò)扇出如果扇出不到幾百個觸發(fā)器根本沒必要上BUFG用了反而浪費全局時鐘資源。某些低端FPGA上全局緩沖數(shù)量少一個核心模塊用一個別每個復(fù)位都搞一個全局緩沖否則后續(xù)工程擴展時資源會卡脖子。4. 時鐘質(zhì)量與時序收斂的關(guān)系時鐘資源選好、配好之后接下來的問題就是怎么去衡量這套時鐘系統(tǒng)到底好不好。很多工程師覺得PLL能鎖定、輸出頻率夠了就行直到時序分析報告里出現(xiàn)“clock skew”特別大的路徑才醒悟。時序收斂這件事本質(zhì)上就是和時鐘的偏斜、抖動、延遲賽跑。4.1 偏斜、抖動和延遲一個一個算明白延遲latency好理解時鐘從源頭到寄存器時鐘端的傳輸時間。偏斜skew是同一個時鐘到達兩個不同寄存器時鐘端的時間差。抖動jitter是時鐘邊沿在時間軸上的不確定性PLL的抖動通常比外部晶振直接進來要小但也不是零。假設(shè)一條數(shù)據(jù)路徑時鐘周期10ns寄存器輸出延遲Tco是2ns組合邏輯延遲5ns建立時間0.5ns。如果不考慮偏斜時序余量是10-2-5-0.5等于2.5ns還挺寬裕。但如果這時時鐘偏斜是1.5ns余量直接被吃掉大半變成1ns偏斜到2.5ns余量只剩0超過2.5ns時序就violate了。這就是為什么全局時鐘網(wǎng)絡(luò)如此重要。普通邏輯繞線傳時鐘不同位置的走線長度差異可能是3納秒級別這足以讓一個本可以收時序的設(shè)計徹底崩潰。而全局時鐘網(wǎng)絡(luò)把偏斜壓到幾百皮秒反而讓數(shù)據(jù)路徑有了足夠的設(shè)計空間。jitter的影響則體現(xiàn)在時序余量計算里通常歸到時鐘不確定度里。一個非常臟的參考時鐘哪怕FPGA內(nèi)部PLL嘗試去過濾輸出jitter也可能達到幾百個皮秒如果通信接口本來就只有0.5ns的建立余量那必然是偶發(fā)錯誤不斷。這種問題單純加大約束余量沒有意義要從源頭換晶振或者加一個干凈的時鐘緩沖器。4.2 同源時鐘與異步時鐘域先識別再處理做多時鐘設(shè)計時最大的坑不是“有多個時鐘”而是“不知道哪些時鐘是相關(guān)的”。兩個時鐘如果來自同一個PLL它們的相位關(guān)系是確定的工具可以推導(dǎo)出它們之間的路徑時序這種叫同步相關(guān)時鐘。比如PLL輸出的200MHz和75MHz如果都鎖定在同一個VCO上它們邊沿之間是有固定相位關(guān)系的??鐣r鐘域時可以直接用打拍同步來處理。但如果是兩個完全獨立的外部時鐘源比如一路來自板載晶振另一路來自PCIe參考時鐘源二者之間頻率和相位都沒有確定性關(guān)系這兩個時鐘域之間就必須用異步FIFO、握手同步再加回環(huán)測試等手段。這類時鐘之間要記得在約束里做異步分組否則時序分析器會去分析一堆不存在的路徑產(chǎn)生好幾千條假違例你修三天三夜也修不完。我遇到過最隱蔽的情況設(shè)計里兩個PLL的輸入來自同一個50MHz晶振但由于每個PLL內(nèi)部VCO相噪特性不同兩個PLL輸出之間并不嚴格同相它們不是完全同步的時鐘。從名字上看一個叫clk_pll_a一個叫clk_pll_b低級工程師可能想當(dāng)然認為它們相關(guān)。處理這類問題我會直接打開時鐘樹報告看兩個時鐘的根節(jié)點是否同源、是否經(jīng)過同一個PLL共用的VCO而不是看名字長不長得像。4.3 復(fù)位與時鐘的配合細節(jié)時鐘資源的問題是“時鐘本身”但復(fù)位和時鐘的配合也經(jīng)常出幺蛾子。最常見的錯誤是把復(fù)位信號直接接到寄存器異步復(fù)位端而復(fù)位釋放時刻沒有和時鐘對齊。舉個例子PLL鎖定后locked信號拉高你把這個信號直接拿來作為寄存器異步復(fù)位釋放時候看起來沒問題但locked信號本身既不是同步信號也未必和主時鐘邊沿對齊。如果恰好某個寄存器在復(fù)位釋放的瞬間時鐘邊沿到來它可能被寫入一個半穩(wěn)定狀態(tài)后面所有邏輯全亂。解決方式是用同步復(fù)位釋放電路reg rst_n_meta, rst_n_sync; always (posedge clk_200m or negedge global_rst_n) begin if (!global_rst_n) begin rst_n_meta 1b0; rst_n_sync 1b0; end else begin rst_n_meta pll_locked; rst_n_sync rst_n_meta; end end assign rst_n rst_n_sync;這樣就把PLL鎖定信號同步到主時鐘域再釋放復(fù)位。這類電路看起來簡單但很多人不做導(dǎo)致上板后偶發(fā)啟動失敗。經(jīng)驗是任何標(biāo)記為“異步復(fù)位同步釋放”的電路都要放在主時鐘域里仔細驗證并且不要讓復(fù)位信號走普通邏輯資源到處漂必要時加一級BUFG。5. 常見問題排查時鐘相關(guān)的坑我基本都踩過最后聊幾個我在實際項目里反復(fù)見過的問題每個都伴隨過不少調(diào)試工時。整理成可檢索的形式希望對你有直接幫助。5.1 “BUFG不夠用”到底該怎么解報錯信息可能是“全局時鐘緩沖資源不足”或者“無法分配時鐘網(wǎng)絡(luò)資源”。遇到這個先別急著刪PLL或換器件我通常按以下順序排查。先檢查是不是同一個時鐘被例化成了多個網(wǎng)絡(luò)尤其是多個PLL輸出同一頻率同一相位時工具可能給它們各分配了一個全局緩沖。正確的做法是讓它們合并或者主動指定其中一個作為主時鐘網(wǎng)絡(luò)其他模塊直接借用。再檢查是不是復(fù)位網(wǎng)絡(luò)占了太多BUFG很多組件各自綜合一套復(fù)位同步邏輯每套都會嘗試用BUFG??梢园阉凶幽K的復(fù)位邏輯收斂到一個總復(fù)位模塊全系統(tǒng)共用一條全局復(fù)位網(wǎng)絡(luò)。最后檢查有沒有超大扇出的低優(yōu)先級信號也被自動全局化了可以通過綜合選項里把全局緩沖插入閾值調(diào)大讓工具只在扇出超過一定數(shù)量時才使用全局緩沖。如果這三步都做完還缺緩沖那才需要考慮改用區(qū)域時鐘把不影響全局時序的局部時鐘挪到區(qū)域時鐘網(wǎng)絡(luò)。大部分情況下“不夠用”不是真不夠用而是資源分配不合理。5.2 PLL鎖不住或輸出時鐘不穩(wěn)PLL鎖定失敗首先要確認參考輸入時鐘確實到了PLL引腳。示波器鉤不到FPGA內(nèi)部就看PLL的配置寄存器有沒有讀到locked信號拉高。如果locked一直拉不高看硬件輸入晶振是否起振、電平幅度是否滿足VMIN/VMAX、是不是誤把差分輸入接成了單端。再看配置輸入頻率是否在PLL允許范圍里輸出頻率計算是否超出了VCO范圍。有一種比較隱蔽的原因PLL的輸入?yún)⒖紩r鐘本身不穩(wěn)定。比如時鐘信號經(jīng)過了普通IO引腳再繞到PLL或者前端有沒做好的分頻器導(dǎo)致時鐘邊沿抖動特別大PLL反復(fù)處于鎖定和失鎖狀態(tài)。排查時可以用一個已知干凈的外部信號做替換驗證。如果換了干凈時鐘就能鎖定問題就在前端硬件而不是PLL配置。輸出時鐘不穩(wěn)還有一種表現(xiàn)是鎖定時序報告里顯示PLL輸出jitter很大。這個要么是參考源不干凈要么是配置里選的帶寬模式不對。低帶寬模式對輸入jitter過濾更好但鎖定時間更長高帶寬模式鎖定快但對輸入噪聲敏感。溫度變化劇烈的環(huán)境中調(diào)試優(yōu)先考慮低帶寬模式。5.3 時序報告里偏斜大得離譜布局布線后如果某一組時序路徑slack很緊打開時序報告看到clock skew那一列數(shù)值特別夸張多半是時鐘路徑走了“歪路”。常見原因有時鐘源沒進專用時鐘引腳PLL輸出沒有接到全局緩沖局部邏輯處于一個離全局時鐘入口很遠的區(qū)域時鐘繞了大半個芯片才到達。修復(fù)思路就是回到第2章講的資源規(guī)劃第一條是確認觸發(fā)器陣列都放在離各自時鐘源較近的時鐘區(qū)域不要讓PLL在芯片左下角而一百個關(guān)鍵觸發(fā)器在右上角。第二條是確認路徑上的時鐘有沒有真正使用全局網(wǎng)絡(luò)可以打開時鐘布線報告看一下時鐘網(wǎng)絡(luò)用的布線類型。第三條就是加約束在綜合階段把關(guān)鍵時鐘明確指定到某個全局緩沖不要完全依賴工具自動選擇。5.4 現(xiàn)場避坑清單速查現(xiàn)象可能原因優(yōu)先排查動作時鐘上出現(xiàn)毛刺門控時鐘或組合邏輯時鐘改成時鐘使能禁止組合邏輯輸出直接驅(qū)動時鐘端仿真通過上電偶發(fā)錯亂復(fù)位釋放太早locked未同步增加異步復(fù)位同步釋放電路等locked穩(wěn)定后再釋放BUFG資源不足高扇出信號各自上全局緩沖合并同頻同相時鐘復(fù)位網(wǎng)絡(luò)收斂到一條全局網(wǎng)絡(luò)PLL鎖定失敗輸入頻率范圍越界或參考時鐘抖動核對輸入頻率可達性換干凈時鐘源時序報告出現(xiàn)大量違例時鐘域兩個異步時鐘域沒做時鐘分組增加set_clock_groups -asynchronous約束溫度一高就出錯時鐘不確定度余量過小增加setup/hold不確定度檢查晶振溫度漂移這份清單不是萬能的但能覆蓋多數(shù)時鐘資源相關(guān)的低頻但麻煩的故障。排查時鐘問題最重要的是保持“先看時鐘再看邏輯”的順序。一個信號出問題如果我確認它所在時鐘域和時鐘樹質(zhì)量沒問題那多半是邏輯問題如果時鐘樹本身就偏斜大、抖動高那再怎么改邏輯都只是打補丁。最后自留地。我做時鐘資源規(guī)劃多年最大的體會是“規(guī)劃永遠比修補省錢”。畫板之前花一天把時鐘引腳、PLL資源、全局緩沖數(shù)量核對清楚比后期為了把一個時鐘引到某個區(qū)域而重新布板要省幾周時間。另一個習(xí)慣是每次改動時鐘樹或PLL配置后我不只跑增量實現(xiàn)而是從頭跑一遍嚴格完整的時序分析因為時鐘改動會影響全芯片的每一個寄存器的時序關(guān)系。希望這篇能幫你少踩幾個坑把調(diào)試精力留給真正值得調(diào)的功能邏輯。