試?yán)鱅LA:從HDL實例化到Block Design的5個實戰(zhàn)技巧)
搞FPGA調(diào)試的人對ILA這個名字基本都不陌生。Vivado里的集成邏輯分析儀Integrated Logic Analyzer說白了就是把一個邏輯分析儀塞進(jìn)FPGA片內(nèi)靠BRAM、觸發(fā)器和LUT把你要看的信號給抓回來再通過JTAG送回電腦上顯示波形。真正上了板子之后仿真里面再完美的代碼也可能在最樸素的接口時序上翻車這種時候ILA幾乎是排查硬件問題的第一選擇。很多人一開始接觸ILA要么是直接在RTL里例化IP要么是在Block Design里拖一個核進(jìn)來兩條路我都走過。今天這篇就是把我實際跟蹤過的ILA調(diào)試過程整理出來從HDL實例化到Block Design配合5個實戰(zhàn)技巧講清楚怎么配、怎么連、怎么排查適合剛開始用Vivado調(diào)試硬件的新手也適合那種正被“抓不到信號”折磨的開發(fā)者。1. 從宏觀到微觀用ILA之前先把機(jī)制弄明白1.1 嵌入式邏輯分析儀到底在FPGA內(nèi)部干了什么ILA在Vivado里屬于Debug IP核它不是一個獨(dú)立的軟件工具而是被綜合進(jìn)你的設(shè)計里的一段硬件邏輯。你可以把它想象成在FPGA內(nèi)部裝了一個帶觸發(fā)功能的記錄儀它會按照某個時鐘節(jié)拍把連接到probe端口上的信號采樣下來然后寫進(jìn)片內(nèi)的BRAM。當(dāng)觸發(fā)條件滿足時它會根據(jù)你設(shè)置的時間位置把一段連續(xù)的波形數(shù)據(jù)保留下來最后通過JTAG鏈路回傳到電腦上的Hardware Manager窗口展示。理解這一點(diǎn)很重要因為很多人以為ILA是在“實時顯示”信號其實它更像一個黑匣子。它工作在循環(huán)記錄模式一邊采一邊丟只有觸發(fā)發(fā)生后才會把觸發(fā)點(diǎn)前后的有效數(shù)據(jù)鎖存住。這也是為什么觸發(fā)器配置對不對會直接影響你能不能看到想要的波形。ILA核在FPGA內(nèi)部主要包括三塊東西用于采樣輸入的寄存器鏈、用于觸發(fā)條件判斷的比較器邏輯、以及用于存儲數(shù)據(jù)的BRAM。采樣時鐘、probe寬度、采樣深度這幾個參數(shù)在創(chuàng)建IP的時候就必須定下來因為這會直接決定BRAM和LUT的消耗。一個常見誤區(qū)是“ILA是免費(fèi)的隨便加多少路都行”實際上一不小心就能把BRAM耗盡導(dǎo)致implementation跑不過去。1.2 一條信號從片內(nèi)到波形窗口的完整旅程我曾經(jīng)帶過一個學(xué)生他以為ILA是通過USB直接把信號“透傳”回電腦的所以一直搞不明白為什么下載完bitstream后還要再開Hardware Manager連接。實際上ILA的數(shù)據(jù)回傳路徑是這樣的目標(biāo)信號進(jìn)入probe端口在ILA核內(nèi)部被采樣并寫入BRAM然后通過JTAG接口送到Vivado的硬件服務(wù)器hw_server最終由Hardware Manager解析并顯示成波形。所以整個調(diào)試鏈路里除了ILA核本身還涉及三樣?xùn)|西JTAG連接器比如Digilent FTDI芯片或者Xilinx Platform Cable USB、硬件服務(wù)器進(jìn)程、以及Vivado里的硬件管理界面。只要其中一環(huán)斷掉你都會遇到“看不到ILA核”或者“抓不了信號”的問題。后面我會重點(diǎn)講硬件連接排查因為這是實操中翻車最多的地方。1.3 ILA的代價資源、時序和編譯時間ILA不是白嫖的它占用的資源往往是工程里被低估的一塊。以一個常見的配置為例采樣深度1024、probe寬度32bitILA大概要占用1到2個BRAM和不少觸發(fā)器。如果把probe寬度加到128bit、深度拉到8192BRAM消耗會成倍往上翻綜合面積也會明顯增加。更麻煩的是對高速時鐘域里加ILA如果插入邏輯帶來了額外的布線擁塞時序收斂可能直接從綠燈變紅。我個人的經(jīng)驗是調(diào)試階段可以暫時放開時序約束去抓信號但確認(rèn)問題后一定要把多余的ILA核移除或者裁剪掉。這不僅是省資源的問題更是為了避免“加了ILA之后功能正常去掉ILA反而出bug”這種莫名其妙的現(xiàn)象。因為ILA接在信號上會引入額外的負(fù)載對時序敏感的設(shè)計會產(chǎn)生肉眼可見的影響。2. 技巧一HDL實例化ILA老思路解決新問題2.1 哪些場景更適合在RTL里直接例化剛開始學(xué)Vivado的時候我喜歡在Block Design里通過右鍵菜單加ILA因為不用寫代碼鼠標(biāo)點(diǎn)幾下就完事。但后來做了一些純HDL工程之后發(fā)現(xiàn)RTL實例化其實有它不可替代的優(yōu)勢。第一種場景是工程本身沒有BD只有純verilog或者VHDL源碼為了一個調(diào)試核去建一個Block Design再加個wrapper反而折騰。第二種場景是你只想觀察某個模塊內(nèi)部的中間信號而這些信號沒有引到頂層端口用Set Up Debug又容易被綜合優(yōu)化掉直接在模塊內(nèi)部例化ILA最直接。第三種場景是你在做別人維護(hù)過的舊工程里面已經(jīng)有ILA例化代碼你只需要照著格式改個名字、改幾個probe就行不需要重新走一遍IP配置流程。RTL實例化ILA最大的好處是“所見即所得”信號連到哪里一眼就看得清。缺點(diǎn)是每次改probe寬度或者采樣深度都要重新生成IP并改例化代碼不能像Set Up Debug那樣在布局布線后半自動調(diào)整。2.2 從IP Catalog創(chuàng)建ILA核并配置參數(shù)先走一遍標(biāo)準(zhǔn)流程。打開Vivado工程后點(diǎn)擊左側(cè)IP Catalog在搜索欄輸入ILA找到“Integrated Logic Analyzer (ILA)”雙擊打開配置界面。Configuration頁面里最常用的是這樣幾項Component Name給ILA核起個名字比如ila_top生成后你會在IP Sources里看到這個核。Number of Probes你要連接的probe端口數(shù)量。這里的probe指的不是一個信號而是一組信號比如一個32bit的數(shù)據(jù)總線就是一個probe一個1bit的復(fù)位信號也是一個probe。Probe Width每個probe的信號寬度。需要注意probe的寬度是在例化時固定下來的改動后需要重新生成IP。Sample Data Depth這是采樣深度通常可選項有1024、4096、8192等。這個值決定BRAM中能存多少個時鐘周期的數(shù)據(jù)。Number of Trigger Conditions觸發(fā)條件數(shù)量很多入門用戶會忽略這個選項默認(rèn)1個就行但如果你需要多條件觸發(fā)可以提前配置為2或者4。配置完成后點(diǎn)Generate。此時Vivado會生成一個名為ila_top的IP核里面包括一份例化模板。你可以在Sources面板里找到該IP的HDL源文件打開后能看到“Instancing Template”的注釋塊直接復(fù)制到你的RTL代碼里把probe端口連上目標(biāo)信號就行。2.3 RTL例化的標(biāo)準(zhǔn)寫法和保持信號技巧舉一個最簡單的例子。假設(shè)我的設(shè)計里有一個32bit的數(shù)據(jù)總線data_in一個寫使能wr_en一個時鐘clk想在RTL里直接觀察這三路信號。那么我可以把ILA核配置成兩個probeprobe0連wr_en寬度1probe1連data_in寬度32。例化代碼類似這樣ila_top u_ila_top ( .clk (clk), .probe0 (wr_en), .probe1 (data_in) );注意clk必須是真實存在的時鐘信號不能是某個邏輯生成的臨時脈沖因為ILA需要穩(wěn)定的時鐘做采樣。另外一個非常關(guān)鍵的點(diǎn)是如果你連的信號在綜合時被優(yōu)化掉了ILA就抓不到有效數(shù)據(jù)。這種情況下要做兩件事一是在信號聲明處加(* mark_debug true *)綜合屬性二是確認(rèn)在綜合設(shè)置里沒有把ILA相關(guān)的優(yōu)化開得過激。比如一個在verilog里定義但最后沒被使用的中間變量綜合器很可能直接優(yōu)化掉你在ILA里看到的就是恒定的0或者根本沒有這個信號可以選擇。(* mark_debug true *) wire [31:0] debug_data;加了mark_debug之后就算這個信號不接到任何輸出端口綜合器也會盡力保留它供調(diào)試使用。配合IP核里的“Include debug attributes in core”選項Vivado會在綜合時自動把標(biāo)記信號關(guān)聯(lián)到已有的ILA核上這就是Set Up Debug能實現(xiàn)的基礎(chǔ)邏輯。3. 技巧二Block Design圖形化插入ILA上手最快但坑也不少3.1 在BD里手動添加ILA核并連接信號使用Block Design做IP集成時插入ILA的流程很簡單。打開BD后在Diagram空白處雙擊輸入ILA搜索單擊添加IP。添加后你會看到一個小方塊上面只暴露了clk和probe端口。此時你需要手動把想要觀察的信號連線到probe上。這里有個容易踩的坑BD中的信號類型多種多樣有寄存器總線也有AXI接口、GPIO接口等。ILA的probe端口是普通wire類型所以你沒法直接把它拖到AXI總線上只能連接到像gpio_io_t、data[31:0]這種明確的bit或vector端口。如果你想抓AXI通道里的信號得先把總線拆成單個信號或者用IP Integrator里的“Slice”功能把總線的某一段引出來再接ILA。連接完成后雙擊ILA核可以重新配置probe數(shù)量、寬度和深度。此時你不需要手動改例化代碼ILA的通道會自動更新。不過要注意手動連接的方式在一些舊版本的Vivado里存在了一個限制當(dāng)你修改上游模塊名稱或信號名時ILA的連接有可能出現(xiàn)懸空重新生成后常常會報“probe0 is not connected”的警告。解決方案是每次改完BD后運(yùn)行Validate Design確認(rèn)所有probe都有實際的連接。3.2 利用Set Up Debug自動插入ILA除了手動在BD里拖ILA核還有一個在工程后期非常實用的操作Set Up Debug。這個方式的前提是你的RTL代碼里已經(jīng)給某些信號加上了(* mark_debug true *)屬性。做過一次完整的流程之后你會發(fā)現(xiàn)這個方式非常適合調(diào)試階段頻繁改探測信號的場景。具體操作是先完成綜合打開綜合后的Design在菜單欄里選“Set Up Debug”。此時Vivado會掃描所有帶mark_debug屬性的信號把它們列在一個表中。你可以勾選要觀察的信號然后選擇是創(chuàng)建一個新的ILA核還是把信號附加到已有的ILA核上。配置好采樣深度和時鐘域后Vivado會自動完成ILA連接并重新綜合。Set Up Debug最大的好處是它省去了手寫例化代碼和手動畫線的麻煩而且可以非常自由地決定“這次只抓哪幾個信號”。壞處是它只適用于綜合后還能看到的信號。如果你的某個內(nèi)部信號因為綜合優(yōu)化被刪掉了那么在Set Up Debug列表里根本找不到它。所以回到第一章節(jié)說的把關(guān)鍵信號加上mark_debug屬性這件事越早做越好。3.3 HDL實例化與Block Design方式怎么取舍我把兩種方式放在一張表里對比方便你在實際項目中快速決定用哪種對比項HDL實例化Block Design手動連接/Set Up Debug工程要求純HDL或任意工程均可必須有Block Design或用綜合后流程改probe寬度需重新生成IP和改例化代碼BD中改配置比較直觀對綜合優(yōu)化容忍度RTL級聲明mark_debug后較穩(wěn)Set Up Debug依賴綜合后信號仍在可讀性代碼里一眼看出連了什么圖形界面直觀但層次復(fù)雜后容易亂集成自動化低高典型場景小模塊快速調(diào)試、舊工程維護(hù)IP集成設(shè)計、大規(guī)模SoC調(diào)試我自己的經(jīng)驗是小工程用HDL實例化最舒服因為你很少需要反復(fù)改動配置大工程特別是用了Zynq或者M(jìn)icroBlaze的我更喜歡BD里配合Set Up Debug因為很多AXI外設(shè)的內(nèi)部信號用鼠標(biāo)點(diǎn)選比翻代碼定位快得多。兩種方式不沖突甚至可以在一個工程里混合使用只要注意不同ILA名字不要重復(fù)就行。4. 技巧三觸發(fā)條件怎么設(shè)才不浪費(fèi)每次抓取窗口4.1 觸發(fā)條件決定了你能看到什么很多人把ILA抓信號失敗的原因歸結(jié)為連接問題實際上有相當(dāng)一部分情況是觸發(fā)條件設(shè)置得不合理。ILA不是從頭到尾把信號錄像然后全量傳給電腦它是在循環(huán)采樣一旦觸發(fā)條件滿足就把觸發(fā)點(diǎn)前后的一段數(shù)據(jù)保留下來。所以如果你觸發(fā)條件設(shè)得太寬采樣緩沖里存的全是無關(guān)數(shù)據(jù)設(shè)得太嚴(yán)又可能永遠(yuǎn)等不到觸發(fā)。一個最簡單的例子你想抓一個讀FIFO的時序關(guān)心的是fifo_rd_en拉高之后數(shù)據(jù)線上出現(xiàn)了什么。那么觸發(fā)條件就應(yīng)該設(shè)置為“fifo_rd_en 1”而不是“fifo_rd_en 0”或者在某個不相關(guān)的計數(shù)器上觸發(fā)。這一點(diǎn)聽起來像是廢話但我在實際調(diào)試中見過太多人把觸發(fā)信號選錯導(dǎo)致Hardware Manager里波形就是不動。4.2 多條件觸發(fā)與、或、比較器和計數(shù)器Vivado ILA支持在每個probe上設(shè)置觸發(fā)條件包括等于、不等于、大于、小于、變化沿等。比如probe0設(shè)置為“上升沿”觸發(fā)probe1設(shè)置為“等于某個特定值”。在Trigger Condition配置里可以添加多個條件并通過AND或者OR連接它們。這里有一個實用技巧如果你要抓一個突發(fā)傳輸?shù)拈_始你可以在寫數(shù)據(jù)總線上設(shè)置“data_out 8hA5”作為觸發(fā)條件。但更穩(wěn)的做法是同時加上寫使能信號作為“等于1”的條件兩個條件用AND連接。因為光靠數(shù)據(jù)總線上的一個特定值可能在非預(yù)期時刻也出現(xiàn)了同樣的值導(dǎo)致你抓到一堆誤觸發(fā)波形。如果你需要等原信號出現(xiàn)一定次數(shù)后才觸發(fā)ILA還支持在觸發(fā)條件里加計數(shù)器。這個功能在抓“第N個中斷”或者“第N次FIFO半滿”時特別有用。配置界面里設(shè)置“Trigger Condition Counter”為某個值即可硬件邏輯會自動計數(shù)滿足次數(shù)后才給出觸發(fā)信號。4.3 存儲位置Begin/Center/End的選擇訣竅ILA的存儲位置有三個選項Begin、Center、End。它們決定了觸發(fā)點(diǎn)相對于存儲窗口的位置。Begin模式觸發(fā)點(diǎn)保存的是觸發(fā)事件之后的數(shù)據(jù)適合觀察“觸發(fā)之后發(fā)生了什么”。Center模式觸發(fā)點(diǎn)前后各保存一半數(shù)據(jù)適合觀察一個事件的完整上下文。End模式保存的是觸發(fā)事件之前的數(shù)據(jù)適合觀察“出事之前發(fā)生了什么”。我個人在排查故障時最喜歡用Center模式因為你可以同時看到原因和結(jié)果。但如果你是在捕捉一個偶發(fā)性的毛刺想了解毛刺之前的狀態(tài)End模式更合適。Begin模式則更常用于確認(rèn)某個功能是否被正確觸發(fā)比如你想看啟動狀態(tài)機(jī)之后到底走了哪幾步。這里有個會被新手忽略的點(diǎn)如果采樣深度只有1024而你要觀察的波形跨越了幾千個周期那么無論用哪種存儲位置你看到的都只是其中一小段。這時候要么加大采樣深度要么把觸發(fā)條件設(shè)置得更加精準(zhǔn)一次只看關(guān)鍵的一小段這樣還能減少BRAM占用。5. 技巧四采樣頻率范圍和采樣深度的取舍5.1 ILA沒有采樣頻率設(shè)置關(guān)鍵是采樣時鐘網(wǎng)上經(jīng)常有人問“Vivado中ILA的采樣頻率是不是有范圍限制”其實ILA核本身并不提供一個可選的采樣頻率參數(shù)。它只有一個clk端口采樣頻率完全取決于你接進(jìn)來的時鐘信號。你想抓100MHz的DDR接口邏輯那就用這個域里的100MHz時鐘給ILA采樣你想抓1MHz的UART信號也同樣可以用這個1MHz時鐘。所以“采樣頻率范圍”這個說法對ILA來說并不成立真正限制你的是FPGA內(nèi)部所能達(dá)到的工作時鐘頻率也就是時序約束約束下來的Fmax。如果你的目標(biāo)是觀察一個很慢的信號但你只有一個100MHz的系統(tǒng)時鐘可用那ILA會按100MHz去采樣這個慢信號。只要慢信號相對于100MHz不是變化那么快你依然能看清它的高低電平變化。反過來如果你用1MHz時鐘去采樣一個10MHz的信號那就會產(chǎn)生混疊看到的波形完全是錯誤的。所以在設(shè)計調(diào)試方案時應(yīng)該先明確待測信號所在的時鐘域。如果設(shè)計里面有好幾個時鐘域而且你想觀察的信號跨越了不同時鐘最合理的做法是分別在每個時鐘域里創(chuàng)建一個ILA核而不是指望一個ILA把所有域的波形都采回來??鐣r鐘域的信號如果送到某個時鐘域ILA里采樣可能出現(xiàn)亞穩(wěn)態(tài)采樣出來的值可能不是穩(wěn)定的0或者1。補(bǔ)充一句ILA能工作的最高頻率和FPGA器件的速度等級、布局布線質(zhì)量都有關(guān)系。曾經(jīng)在某個工程里我加了ILA后時序報告顯示這個調(diào)試核對系統(tǒng)時鐘造成了明顯惡化最后通過降低探測信號數(shù)量和縮小采樣深度才把這條路徑的時序修回去。所以它確實有一個實際的“頻率上限”但這個上限不是ILA核自己規(guī)定的而是你的整體實現(xiàn)結(jié)果決定的。5.2 跨時鐘域信號抓取的注意事項抓跨時鐘域信號是FPGA調(diào)試?yán)镒钊菀追嚨膱鼍?。比如你的設(shè)計里有一個31.25MHz的Ethernet GMII時鐘還有一個125MHz的接口時鐘。GMII的rx_clk上升沿采到的數(shù)據(jù)如果接到125MHz時鐘域的ILA里采樣點(diǎn)可能落在數(shù)據(jù)變化窗口中間導(dǎo)致讀回來的值不穩(wěn)定波形在Vivado里看起來就是毛刺亂跳。這里有三種常見做法在目標(biāo)域里先對信號做兩級同步再送進(jìn)ILA。這樣在ILA上看到的信號雖然比真實信號晚一到兩個時鐘但至少是穩(wěn)定可讀的。直接在該信號自己的時鐘域里建ILA確保采樣時鐘和數(shù)據(jù)同步變化。對需要跨多個時鐘域觀察的總線信號用異步FIFO先把數(shù)據(jù)緩存成單一時鐘域的格式再接ILA。很多人在ILA里看到波形“時不時跳出一個毛刺”第一反應(yīng)是設(shè)計邏輯有問題其實大概率是采樣方式不合理。先檢查ILA使用的時鐘域是否和信號一致往往能省下半天排查時間。5.3 采樣深度與BRAM資源的換算采樣深度1024意味著SRAM能存1024個采樣周期的數(shù)據(jù)4096就是存4096拍。這個深度和probe寬度相互作用共同決定BRAM的使用量。一個粗略的估算公式可以這么理解如果probe總位寬是32bit采樣深度是1024那么存儲總量就是32 × 1024 32768bit約等于4KB。FPGA里的BRAM通常一塊是36Kb左右所以這個配置大約占用不到一塊BRAM。但如果位寬加到128bit深度加到8192就變成128 × 8192 1Mbit也就是約30塊BRAM。對于某些資源緊張的器件這足以讓實現(xiàn)階段爆出資源錯誤。我的習(xí)慣是在調(diào)試初期先用較低采樣深度把關(guān)鍵波形看個大概確認(rèn)問題范圍之后再決定要不要加大深度。不要說“既然都加ILA了就弄大一點(diǎn)”因為深度越大不僅BRAM越緊數(shù)據(jù)回傳時間也越長一個8192深度的ILA在JTAG 30MHz頻率下回傳數(shù)據(jù)會有可感知的延遲體驗并不好。6. 技巧五硬件連接與“沒反應(yīng)”的完整排查思路6.1 從板卡上電到在Vivado看到ILA的全流程硬件調(diào)試和仿真不一樣仿真里你跑測試平臺結(jié)果幾乎是“確定性”的。硬件調(diào)試第一步就是連接這塊流程一旦不順后面全是空白。標(biāo)準(zhǔn)的流程是給FPGA板卡上電用JTAG線連接板卡調(diào)試接口和電腦。如果你的開發(fā)板是Digilent做的通常插上USB線電腦就能識別出一個串口號和一個JTAG設(shè)備。然后打開Vivado在左下角Flow Navigator里選擇“Open Hardware Manager”點(diǎn)擊“Open Target”后選擇“Auto Connect”。如果一切正常Hardware窗口里會列出你的FPGA器件右鍵點(diǎn)擊器件后選擇“Program Device”加載bitstream。加載完成后ILA核會自動出現(xiàn)在Hardware窗口的列表里。雙擊某個ILA核就能打開波形界面在Trigger Setup窗口配置觸發(fā)條件最后點(diǎn)擊運(yùn)行按鈕開始等待觸發(fā)。這一步看似簡單實際遇到的問題相當(dāng)多。最常見的一種就是插上USB線后電腦根本沒有反應(yīng)設(shè)備管理器里是黃色感嘆號。還有一種情況是Vivado能識別到JTAG鏈但打開device后一直停留在“Loading device information”此時往往是硬件服務(wù)器進(jìn)程死掉了。6.2 驅(qū)動識別不了板子怎么辦“Vivado安裝驅(qū)動無法識別板子”是我見過頻率極高的問題。大多數(shù)Zynq和Artix開發(fā)板用的都是FTDI芯片比如FT2232H。在Windows下第一次插上板子時系統(tǒng)有可能把它識別為“USB Serial Port”而不是JTAG設(shè)備。Vivado自帶的驅(qū)動安裝程序不一定能自動關(guān)聯(lián)到正確驅(qū)動。此時不要忙著換線換板子先在設(shè)備管理器里找到帶感嘆號的設(shè)備右鍵更新驅(qū)動選擇手動查找驅(qū)動“瀏覽計算機(jī)以查找驅(qū)動程序”路徑指向Vivado安裝目錄里的data\xicom\cable_drivers\nt64\dlc10_win7或者對應(yīng)版本目錄一般能解決FTDI識別問題。對于部分平臺還需要使用Zadig工具把驅(qū)動替換為WinUSB驅(qū)動這個方式對很多第三方JTAG調(diào)試器都很管用。如果驅(qū)動都裝好了但Vivado仍舊報“Cannot find cable”可以嘗試在Hardware Manager里點(diǎn)“Open Target”下的“Open New Target”手動選擇Cable類型而不是Auto Connect。Auto Connect有時會選錯設(shè)備手動指定后常常就好了。還有一個容易被忽略的點(diǎn)是如果有多個Vivado版本共存后臺可能會有多個hw_server進(jìn)程搶占同一個JTAG口把所有hw_server進(jìn)程全部結(jié)束重新連接一次是最快的修復(fù)方式。6.3 ILA抓不到信號的8個常見原因先說結(jié)論ILA“抓信號沒反應(yīng)”大概能歸結(jié)為下面幾類原因。我按出現(xiàn)概率從高到低排了個序你可以直接對照排查現(xiàn)象可能原因解決思路波形窗口始終全0或全1probe連了信號但信號本身恒值檢查RTL邏輯確認(rèn)是否真的發(fā)生跳變點(diǎn)擊Run之后狀態(tài)一直Waiting觸發(fā)條件沒有滿足檢查觸發(fā)條件降低觸發(fā)門檻ILA核在Hardware Manager里根本不顯示bitstream沒有下載成功或ILA被優(yōu)化掉了看Program Device時有無報錯檢查mark_debug屬性波形出現(xiàn)但不更新觸發(fā)窗口只有一段采樣緩沖滿了重新點(diǎn)擊Run或者修改觸發(fā)條件數(shù)據(jù)明顯錯亂采樣時鐘跨域、信號沒同步換到信號所在時鐘域采樣抓到的信號少了一些bitprobe寬度配置不匹配核對IP配置和例化代碼下載bitstream后板卡功能異常ILA加了過多負(fù)載或影響了布局布線裁剪ILA、換低采樣深度Vivado一直連不上目標(biāo)JTAG驅(qū)動或hw_server問題重裝驅(qū)動、結(jié)束hw_server進(jìn)程這里特別提醒一點(diǎn)如果你在ILA里看到的信號一直保持一個固定值先不要懷疑ILA壞了先懷疑是不是觸發(fā)條件設(shè)錯了。比如你想觸發(fā)“data 8h80”但實際數(shù)據(jù)總線上一直從來沒出現(xiàn)過這個值那當(dāng)然永遠(yuǎn)等不到。你不妨先把觸發(fā)條件改成“不等于某個值”或者干脆設(shè)為“always true”看能不能抓到數(shù)據(jù)。如果設(shè)為always true還是抓不到那再往連接和硬件方向排查。7. 實戰(zhàn)報錯速查Vivado調(diào)試中常見問題復(fù)盤7.1 implement design變紅還能救嗎很多人一看到implement design變紅就頭大。實際上這個紅色信息有兩類一類是綜合或?qū)崿F(xiàn)的error彈窗這種通常是代碼或者IP配置有硬錯誤另一類是工程狀態(tài)欄上的紅叉多半是某一步?jīng)]有成功運(yùn)行或者運(yùn)行結(jié)果里存在嚴(yán)重的時序失敗。ILA調(diào)試場景里最常見的implement失敗原因是資源不夠。加了一堆ILA之后BRAM占滿實現(xiàn)工具直接報resource utilization exceeded。這種情況的應(yīng)急處理是砍掉不用的ILA核或者降低采樣深度。如果是時序失敗可以先打開Implementation的Timing Summary看看是哪些路徑超了。很多時候是ILA所在的采樣時鐘路徑太長導(dǎo)致關(guān)鍵路徑變差。一個實用的做法是把ILA核的采樣時鐘引腳改成來自BUFG的高速時鐘避免用普通邏輯出來的時鐘。還有一個低級但常見的錯誤在Block Design里加了ILA但忘記把ILA的s_axi控制接口連接到Zynq或者JTAG調(diào)試鏈路。此時ILA在硬件管理器里就不可見。BD里使用ILA時通常需要把S_AXI和S_AXI_ACLK做相應(yīng)連接NoC和AXI接口的版本還會涉及更多配置。出現(xiàn)這種問題時檢查一下ILA核的s_axi接口是否處于未連接懸空狀態(tài)。7.2 生成比特流失敗與WinPcap的坑生成比特流失敗往往出現(xiàn)在步驟3實現(xiàn)和步驟4生成比特流之間。有時候提示信息是“route_design failed”有時候是“DRC failed”。DRC失敗中我遇到過比較多的項是“AVAL-47”或“LUTLP-1”這類關(guān)于未連接管腳或布線的檢查。做了ILA調(diào)試之后一定記得檢查是否把probe信號接到了不合理的時鐘網(wǎng)絡(luò)上這會在DRC階段直接攔下來。另一個高度相關(guān)的話題是WinPcap。很多人會把WinPcap和Vivado混到一起其實WinPcap主要用于仿真和網(wǎng)絡(luò)抓包但某些版本的Vivado安裝程序會在安裝界面勾選安裝WinPcap如果安裝失敗會導(dǎo)致后續(xù)部分網(wǎng)絡(luò)相關(guān)功能異常。對于純ILA調(diào)試來說WinPcap安裝失敗一般不影響JTAG調(diào)試因為硬件服務(wù)器走的是USB/JTAG鏈路不依賴WinPcap。所以如果你在Vivado安裝時提示W(wǎng)inPcap失敗不必太焦慮最壞情況只是個別以太網(wǎng)相關(guān)的仿真功能受影響。真正影響ILA連接的是前面說過的FTDI驅(qū)動和hw_server服務(wù)。7.3 串口調(diào)試助手與ILA配合的混合調(diào)試技巧在嵌入式FPGA項目里除了ILA這種寄存器級觀測手段UART串口打印依然是快速確認(rèn)系統(tǒng)狀態(tài)的好幫手。比如在Zynq上跑軟核或者在一個小規(guī)模的FPGA設(shè)計里通過UART輸出一些狀態(tài)碼你完全可以同時開兩個工具一邊用ILA看總線時序細(xì)節(jié)一邊用串口調(diào)試助手確認(rèn)上層的狀態(tài)切換是否符合預(yù)期。我的習(xí)慣是先用串口打印把問題定位到某個模塊再用ILA去精確抓該模塊的接口波形。這樣能避免一開始就把幾十路信號塞進(jìn)ILA導(dǎo)致BRAM和調(diào)試時間雙雙失控。串口調(diào)試助手的波特率、數(shù)據(jù)位、校驗位一定提前確認(rèn)否則看到亂碼會誤以為邏輯本身有問題。ILA抓到的是芯片內(nèi)部的真實硬件行為串口打印出來的是CPU或狀態(tài)機(jī)處理后“認(rèn)為”自己看到的兩者結(jié)合時如果結(jié)果不一致那往往意味著接口時序上存在隱患這是最有價值的排查線索。7.4 一次完整的問題定位演示說一個我印象很深的案例。某個FPGA工程里用AXI接口讀寫外部SRAM仿真全通過上板后讀回來的數(shù)據(jù)偶爾會錯幾個字節(jié)。一開始我用串口調(diào)試助手把讀回的數(shù)據(jù)打印出來發(fā)現(xiàn)錯誤看起來沒有明顯規(guī)律有時連續(xù)讀一千次錯兩三次有時又完全正常。這時候單純靠打印很難定位因為錯誤已經(jīng)發(fā)生了你并不知道是控制器發(fā)錯地址還是總線時序出了問題。于是我打開Hardware Manager創(chuàng)建了一個ILA掛在AXI接口的地址、數(shù)據(jù)和寫使能信號上采樣深度設(shè)成4096觸發(fā)條件設(shè)為“寫操作發(fā)生且數(shù)據(jù)等于某個壞值”。第一次運(yùn)行等了很長時間沒反應(yīng)。我把觸發(fā)條件放寬到“只要寫請求拉高就觸發(fā)”很快抓到了一段寫時序。對比IP手冊里的波形后發(fā)現(xiàn)問題出在片選使能信號上CE拉低的時機(jī)比數(shù)據(jù)有效時間晚了半個時鐘周期導(dǎo)致在特定時鐘頻率和布線延遲組合下偶發(fā)讀錯。最后在RTL里對CE加了一級寄存器問題消失。這個案例很有代表性仿真沒有暴露問題是因為仿真環(huán)境里沒有體現(xiàn)實際的PCB走線延遲和時序抖動ILA抓不到信號則是因為最初的觸發(fā)條件設(shè)得太苛刻。把這個過程寫出來是想強(qiáng)調(diào)兩件事第一ILA的調(diào)試思路要像偵探一樣先放寬條件找線索再逐步收緊確認(rèn)原因第二不要把ILA當(dāng)成萬能的示波器它只能看到你加在probe上的信號信號沒引出來一切都是白搭。在真正接觸ILA之前我也以為調(diào)試FPGA就是“跑仿真、看波形”兩件事直到在板級調(diào)試?yán)锉桓鞣N時序問題教訓(xùn)過之后我才明白ILA最值錢的不是它能采樣而是它能把代碼運(yùn)行時的真實行為暴露出來。這里再分享一個個人經(jīng)驗每次在大工程里加ILA之前都先花幾分鐘確認(rèn)自己的采樣時鐘是哪個域的、觸發(fā)條件設(shè)的是什么、深度夠不夠看完整一段傳輸。這三個問題想清楚了基本能避免大多數(shù)“抓不到信號”的尷尬。調(diào)試嘛本來就是一個不斷縮小懷疑范圍的過程ILA用得好整個過程的效率能提升一個量級。