指南)
簡介思朗科技2022年提前批數字IC驗證筆試題的完整復盤資料圍繞異步FIFO的UVM驗證環(huán)境搭建與驗證展開。資源面向2023屆及后續(xù)目標IC驗證崗位的求職者尤其適合希望鞏固UVM方法學、練習覆蓋率收集與錯誤定位的在校生或初級工程師。壓縮包為7z格式共193個文件大小約5.13MB。其中包含7個SystemVerilog源碼文件對應輸入驅動、監(jiān)測、驅動器、sequencer、agent等UVM組件、5個Verilog設計文件以及大量覆蓋率收集后生成的HTML/PNG/JS/CSS報告文件方便對照驗證結果查看功能覆蓋率與代碼覆蓋率。當前已有6214人學習下載可見該題目在IC驗證求職圈中具有較高參考價值。資料不僅給出可運行的UVM環(huán)境源碼還通過Questa Sim仿真后的覆蓋率報告、日志及UCDB數據庫完整呈現(xiàn)了從激勵發(fā)送、端口監(jiān)測到覆蓋率收斂的驗證流程能幫助讀者理解異步FIFO驗證的關鍵點和筆試題的答題思路。 今年數字IC驗證崗的筆試面試有一個鐵打的組合UVM、異步FIFO、八股。無論你投的是芯片設計公司、IP公司還是驗證服務團隊這三樣東西幾乎輪流出現(xiàn)在筆試題和面試官的追問里。異步FIFO既能考設計又能考驗證還能順帶看你對跨時鐘域的理解UVM則幾乎是驗證工程師的通用語言不問phase機制和寄存器模型基本說不過去。這篇文章就圍繞這三塊把我備考時整理的高頻考點、異步FIFO驗證環(huán)境的搭建思路、以及筆試中容易踩的坑一次性擺出來適合正在準備數字IC驗證崗位面試的同學也適合剛入行想補全知識框架的工程師。1. 筆試面試總覽驗證崗到底在考什么1.1 驗證崗的核心技能地圖數字IC驗證的日常工作說白了就是三件事理解設計規(guī)格、搭建驗證環(huán)境、把bug撈出來。筆試面試圍繞的也是這三件事但表達方式變成了UVM機制、斷言、覆蓋率、以及異步FIFO這類典型模塊的驗證方案。我見過不少同學把大量精力花在背八股上結果面試官隨口一問“你為什么要在這個場景用virtual sequence”就卡殼。八股只能幫你進門真正拉開差距的是你能不能把機制和場景對應起來。技能地圖大概可以分成四層第一層是SystemVerilog語法和硬件思維第二層是UVM框架的組件結構與phase機制第三層是跨時鐘域、復位、低功耗等通用知識的驗證方法第四層才是具體的項目實戰(zhàn)比如異步FIFO、串口、I2C、AHB總線協(xié)議的驗證環(huán)境搭建。筆試通常覆蓋第一層到第三層面試則會追著第四層問細節(jié)。1.2 異步FIFO為什么是必考題異步FIFO幾乎是一個完美的考察載體。它同時牽涉三塊硬知識跨時鐘域同步、格雷碼編碼、空滿判斷。設計端可以考你“多一比特”的指針比較法怎么寫驗證端可以考你“兩個driver分別驅動讀寫時鐘域怎么做”筆試還能考你“突發(fā)寫入時FIFO深度怎么算”。串口模塊里也常常用到小深度的異步FIFO做收發(fā)緩沖所以面試官還會順手問“異步FIFO深度一般選多大為什么”。我以前覺得異步FIFO很簡單不就是讀指針寫指針加格雷碼嘛。后來自己動手搭驗證環(huán)境才發(fā)現(xiàn)真正的坑全在邊界條件復位釋放瞬間的空滿標志、同步器延遲導致的保守空滿、以及scoreboard比對時讀寫側時間差的處理。這些問題理解透了筆試面試基本就穩(wěn)了。2. UVM核心機制速覽面試八股里最值得深挖的四個點2.1 phase機制為什么環(huán)境能跑起來又能跑得完UVM的phase機制是面試必問但很多人只背了名字。build_phase自頂向下執(zhí)行connect_phase自底向上執(zhí)行run_phase是唯一消耗仿真時間的phase。這里的關鍵不是背誦而是理解為什么這樣設計。build_phase要自頂向下是因為父組件要先new子組件子組件才能接著build自己的內容connect_phase要自底向上是因為只有所有組件的build都完成port和export才能安全連接。run_phase里真正坑人的是objection機制。很多人寫測試用例時只記得在sequence里調用start忘記在test里raise_objection仿真直接跑零時間退出或者出現(xiàn)“run phase就結束了但sequence還沒執(zhí)行完”的詭異現(xiàn)象。我自己的習慣是在test的run_phase里先raise_objection等所有sequence跑完再drop_objection并且用uvm_info把關鍵節(jié)點的objection計數打出來。如果某個用例異常提前結束第一件事就是查objection計數是不是提前歸零了。關于phase還有幾個容易被追問的點reset/configure/main等run_time phase和run_phase的關系以及UVM 1.2之后deprecated的uvm_sequence_item宏改成什么了。這些細節(jié)有時候比機制本身更能體現(xiàn)你是否真的用過UVM。2.2 寄存器模型鏡像值mirror value到底怎么維護寄存器模型里有一個概念叫鏡像值mirror value它代表軟件視角下寄存器的當前硬件值。很多人忽略這個概念但面試官特別喜歡追問“如果你用寄存器模型寫了一個寄存器再讀回來為什么值不對”答案往往出在鏡像值的預期值上。寫入操作通過reg.write()完成寄存器模型會自動更新鏡像值但如果硬件在寫之后又改變了寄存器的值而你沒有調用reg.mirror()或重新read模型里的鏡像值就和硬件不一致。反過來如果你只對寄存器做了reg.update()它會比較鏡像值和當前期望值有差異才發(fā)起寫操作。理解了這些你自然能回答“為什么要用mirror機制來檢查硬件是否正確更新了寄存器”這類問題。構造用例時我通常會在測試結束前對關鍵控制寄存器做一次mirror比對先讀硬件值再和期望值比較不一致就報FAIL。這個操作比單純打印寄存器值可靠得多因為鏡像值機制會自動幫你完成一致性檢查。2.3 最終pass/fail醒目顯示的關鍵代碼有些同學問我能不能在仿真結束的時候打印一行特別醒目的PASS或者FAIL。當然可以。UVM里最樸素也最好用的方式是在test的report_phase里根據錯誤計數打印一個占滿屏幕的橫幅。我的實現(xiàn)大概是這樣的function void report_phase(uvm_phase phase); super.report_phase(phase); if (uvm_report_server::get_server().get_severity_count(UVM_ERROR) 0) begin $display(\n); $display( **** TEST PASSED ****); $display(\n); end else begin $display(\n); $display( ###### TEST FAILED ######); $display(\n); end endfunction這個寫法有幾個好處第一不需要額外引入任何宏隨便一個test都能用第二在仿真日志里搜索PASS或FAIL非??旎貧w大量用例時掃一眼就知道結果第三因為用了uvm_report_server的計數它能準確反映整個UVM環(huán)境里的所有error包括sequence里的uvm_error和driver里的uvm_fatal。如果你用腳本跑回歸還可以在同一個位置把最終的pass/fail狀態(tài)寫入一個文本文件方便CI系統(tǒng)解析。我個人習慣把$display和文件寫入同時做這樣既能在波形里看到又能讓回歸腳本穩(wěn)定判據。2.4 sequence與sequencer握手的常見細節(jié)關于sequence機制面試官常問的問題集中在start一個sequence發(fā)生了什么以及item_done和finish_item的關系。實際上執(zhí)行一個sequence item時sequence調用start_item會先請求sequencer授權拿到授權后finish_item把item交給driverdriver側的seq_item_port.get_next_item()拿到item后驅動到DUT最后調用item_done通知sequence。很多人不知道的是finish_item會阻塞sequence直到driver調用item_done或get()這是流控的關鍵。如果你在sequence里發(fā)了item但driver沒有及時getsequence會阻塞在那里整個用例就像“卡住”一樣。遇到這種現(xiàn)象先檢查driver的run_phase是否在正常工作再看seq_item_port的連接是否沒連上。3. 異步FIFO設計驗證實戰(zhàn)從RTL到UVM環(huán)境3.1 設計要點格雷碼、兩級同步器與空滿判斷異步FIFO的經典實現(xiàn)有幾個繞不開的點。寫指針和讀指針各自在本地時鐘域遞增但跨時鐘域比較時不能直接用二進制指針因為多位信號同時變化時可能出現(xiàn)采樣到中間態(tài)的風險。格雷碼的優(yōu)勢在于相鄰兩個值只有一位變化跨時鐘域采樣時頂多采到“舊值”或“新值”不會出現(xiàn)錯誤的新值。這就是為什么面試官總問“為什么要用格雷碼”??諠M判斷的標準做法是“最高位不同其余位相同”判滿“完全相等”判空。也就是說比較指針時把指針位寬擴展一位寫指針比讀指針多跑一整圈時判滿。要注意的是寫側看到的滿信號是用同步到寫時鐘域的讀指針格雷碼比較出來的因為同步器有延遲這個滿信號實際上是一個保守的滿信號。換句話說FIFO真實滿了之后寫側可能要過幾個周期才能看到滿標志但這不影響正確性因為寫側在滿標志拉高之前寫入的數據量一定小于FIFO深度不會造成覆蓋。設計里還有一個細節(jié)同步器打兩拍是在FIFO外部由RTL完成驗證環(huán)境里不需要也不能去模擬同步器的行為只需要給足時間讓同步器收斂通常用時鐘沿對齊斷言或延時檢查來保證。3.2 UVM驗證環(huán)境搭建思路異步FIFO的DUT有兩個時鐘域寫側有寫時鐘、寫使能、寫數據讀側有讀時鐘、讀使能、讀數據外加復位和空滿標志。這種結構最自然的驗證環(huán)境是搭兩個agent寫agent和讀agent各自包含driver和monitor然后通過virtual sequencer在頂層協(xié)調兩個agent同時發(fā)激勵。我見過不少新手把讀寫driver合并成一個導致讀寫激勵互相牽制后來為了模擬并發(fā)讀寫又給代碼加一堆分支邏輯極難維護。正確的做法是兩個driver完全獨立各自只負責自己時鐘域的信號。要構造“幾乎同時的讀寫”可以用virtual sequence同時start兩個子sequence靠調度器的并行性來逼近真實時序。環(huán)境里核心的scoreboard用一個隊列來模擬FIFO行為寫側monitor收到有效寫時往隊列push數據讀側monitor收到有效讀時從隊列pop數據并和DUT輸出比對。因為寫讀共用同一個隊列天然就避免了跨時鐘域比對的時間差問題。最后覆蓋率主要收集寫滿、讀空、同時讀寫、back-to-back突發(fā)、指針回繞等關鍵場景的覆蓋率。3.3 異步FIFO時序圖和典型用例設計筆試和面試常用的異步FIFO時序圖關注點是寫時鐘域產生寫數據寫使能拉高在寫時鐘上升沿采樣寫入讀時鐘域相同。空滿標志的變化滯后于實際空滿狀態(tài)因為同步器需要兩個周期。面試官有時會畫一條寫指針和讀指針的關系曲線讓你標出滿標志實際拉高的位置。我的典型用例設計大概分這么幾組用例組場景檢查點基礎讀寫復位后先寫后讀讀出數據與寫入一致連續(xù)寫突發(fā)持續(xù)寫入超過FIFO深度滿標志拉高寫入不覆蓋連續(xù)讀突發(fā)持續(xù)讀空空標志拉高同時讀寫讀寫速率不同交替進行scoreboard隊列始終一致背靠背寫滿后立刻讀空再寫滿指針回繞正確復位干擾寫讀過程中隨機復位標志位復位后恢復無X態(tài)3.4 常見斷言與比對策略異步FIFO驗證里最重要的斷言是寫滿時不能繼續(xù)寫讀空時不能繼續(xù)讀。這兩個斷言直接對應FIFO設計的兩條安全底線我會在寫agent和讀agent的monitor里寫成immediate assertion一旦違反馬上報error。另一個容易漏的檢查是“復位后的空標志必須在復位釋放后有限周期內拉高”。異步FIFO復位后讀指針和寫指針都歸零空標志理論上立即有效但由于復位信號跨時鐘域的存在需要檢查兩個時鐘域各自的復位釋放是否干凈。我在一個項目里遇到過復位釋放順序不對導致的空標志不定態(tài)后來加了一條斷言專門檢查空標志在復位釋放后5個讀時鐘周期內穩(wěn)定為1。scoreboard比對方面除了隊列比對我還會對FIFO的滿標志和空標志做“允許延遲”的時序檢查。因為讀側看到的空標志滯后于真實狀態(tài)scoreboard需要留出同步器延遲窗口不能要求即時相等否則會產生大量偽錯。4. 筆試題目實錄與排查技巧4.1 一道必背的計算題FIFO深度怎么算筆試里最常出現(xiàn)的題型是給定寫時鐘頻率、讀時鐘頻率和突發(fā)長度算FIFO最小深度。我給你一個我實際考到過的變體。寫時鐘100MHz讀時鐘80MHz寫側每200個寫時鐘周期連續(xù)寫入160個數據讀側以每200個讀時鐘周期讀出80個數據的恒定速率讀取問FIFO最小深度是多少。先把時間單位統(tǒng)一到寫時鐘周期。讀時鐘80MHz即寫時鐘周期10ns讀時鐘周期12.5ns。200個寫時鐘周期是2000ns這個時間段內讀側能讀出的數據量為2000/12.5160個周期但讀側每200個讀周期只讀80個所以實際讀出80個數據這里要注意題目說的是“每200個讀時鐘周期讀出80個”折算到2000ns就是160個讀周期讀出64個數據。我算了一下突發(fā)期間寫入160讀出64積壓96個突發(fā)結束后的200個寫周期內不再寫入讀側繼續(xù)讀可以把積壓逐漸清空。所以最小深度至少是96。出于同步器延遲和裕量考慮實際選擇128比較穩(wěn)妥。這道題的陷阱在于不能簡單比較讀寫平均速率而要算突發(fā)窗口內的最大積壓。平均速率對比只能判斷“長期來看會不會溢出”無法回答“短期內需要多大緩沖”。4.2 面試追問如果FIFO深度不是2的冪怎么辦格雷碼指針法天然要求FIFO深度是2的冪因為只有位寬為N時格雷碼才能覆蓋完整的0到2^N-1循環(huán)。如果深度不是2的冪比如10那就要考慮兩種處理方式一是把深度向上取整到16代價是浪費6個存儲單元二是自定義非2冪次地址編碼但空滿判斷邏輯會變得復雜跨時鐘域安全性需要額外分析。大多數串口和以太網模塊里的異步FIFO深度是2的冪比如16或32這符合設計慣例。面試里遇到非2冪次深度的題目先回答“會優(yōu)先向上取整到2的冪”再補一句“如果必須精確深度需要重新設計指針編碼和空滿判斷”基本就能過關。4.3 真機調試問題記錄最后分享一個我實際踩過的坑。有一次跑異步FIFO的UVM環(huán)境用例跑到一半就報“FATALobjection count is zero”但波形上看數據明明還在傳輸。排查后發(fā)現(xiàn)問題出在我的寫sequence里用了#delay來模擬時序間隔而讀sequence已經提前跑完了所有item并drop了objection。因為UVM的run_phase結束條件是所有objection都歸零所以即使寫側還有掛起的延時任務環(huán)境也會被強制關閉。解決辦法有兩個一是在test的run_phase里維持一個總objection直到整個測試計劃完成再drop二是確保所有sequence在時間軸上同步退出。我現(xiàn)在更傾向于第一種簡單可靠而且方便控制整個test的生命周期。這類問題不會出現(xiàn)在教科書上但實際工程里幾乎一定會遇到提前知道能省下大量調試時間。異步FIFO看著小但把它的設計、驗證、筆試計算全部吃透幾乎就能覆蓋數字IC驗證崗一半以上的面試知識點。如果你還在準備階段我建議你先自己動手搭一個最小UVM環(huán)境跑通異步FIFO的讀寫用例再逐步加上scoreboard和覆蓋率這個過程比背任何八股都有用。本文還有配套的精品資源點擊獲取