:從RTL到流片全流程避坑指南)
1. 從零到流片開源EDA與Sky130 PDK的實戰(zhàn)避坑指南1.1 為什么我要走這條路三年前如果有人跟我說用一套完全開源的工具鏈加上一個開源工藝設(shè)計套件能把一顆芯片從RTL一路推到流片我大概率會覺得他在開玩笑。那時候商業(yè)EDA的License費(fèi)用動輒幾十萬美金一年一次MPW多項目晶圓的流片機(jī)會更是貴得離譜個人開發(fā)者和小團(tuán)隊根本玩不起。但這兩年情況變了開源EDA工具鏈的成熟度上來了Sky130 PDK也穩(wěn)定了再加上OpenMPW這類項目給了普通人免費(fèi)流片的機(jī)會整個門檻一下子降到了“你只要有臺像樣的電腦、愿意花時間學(xué)”的程度。這篇文章我想聊的就是這條路上的真實體驗。不是那種“Hello World”級別的跑通demo而是從環(huán)境搭建、RTL綜合、布局布線、時序收斂、DRC/LVS驗證一直到提交流片文件的全流程把我在這個過程中踩過的坑、繞過的彎、總結(jié)出來的經(jīng)驗一次性講清楚。適合誰看如果你是電子工程或者計算機(jī)專業(yè)的學(xué)生想親手做一顆真正的芯片但苦于沒有資源如果你是嵌入式工程師想從寫固件往上再走一層理解硬件底層或者你只是對芯片設(shè)計好奇想找個低成本的方式入門——那這篇內(nèi)容應(yīng)該能幫你省下不少時間。核心工具鏈我用的是OpenROAD做布局布線Yosys做綜合Magic和KLayout做版圖驗證PDK就是Sky130。整個流程跑下來從零到提交GDS大約需要兩到三周的業(yè)余時間前提是你得知道哪些地方容易卡住。1.2 整體流程長什么樣先給一個全局視角免得后面講細(xì)節(jié)的時候你迷失在工具參數(shù)里。一顆數(shù)字芯片從代碼到流片大致要經(jīng)過這么幾個階段RTL設(shè)計用Verilog或者SystemVerilog寫功能邏輯這一步跟FPGA開發(fā)很像但約束條件完全不同。功能仿真用Verilator或者Icarus Verilog跑testbench確保邏輯正確。邏輯綜合Yosys把RTL翻譯成門級網(wǎng)表映射到Sky130的標(biāo)準(zhǔn)單元庫上。布局布線OpenROAD接管做floorplan、placement、CTS、routing最后輸出DEF和GDS。物理驗證Magic和KLayout跑DRC設(shè)計規(guī)則檢查和LVS版圖與原理圖一致性檢查。流片提交把最終GDS打包按照OpenMPW或者其它shuttle的要求提交。每一步都有它自己的坑而且很多坑是文檔里不會寫的。下面我按階段拆開講。2. 環(huán)境搭建別在這一步就放棄2.1 工具鏈安裝的三種方式裝開源EDA工具鏈這件事說簡單也簡單說麻煩也麻煩。目前主流有三種路子第一種是直接用OpenLane的Docker鏡像。這是最省心的方式OpenLane把Yosys、OpenROAD、Magic、KLayout、Netgen這些工具全打包好了你只需要裝個Docker拉個鏡像就能跑。缺點是鏡像體積大好幾個GB而且如果你想單獨調(diào)某個工具的版本會比較麻煩。第二種是用conda或者pip逐個安裝。比如Yosys可以通過conda-forge裝OpenROAD有預(yù)編譯的二進(jìn)制包Magic和KLayout也都有各自的安裝渠道。這種方式靈活但版本兼容性需要你自己把控。我試過用conda裝Yosys然后手動編譯OpenROAD結(jié)果因為依賴庫版本對不上折騰了一整天。第三種是從源碼編譯。適合想深度定制或者研究工具內(nèi)部實現(xiàn)的人但對新手極度不友好。我第一次嘗試編譯OpenROAD的時候光是處理依賴就花了大半天最后還因為某個庫的版本問題編譯失敗。我的建議如果你是第一次走這個流程直接用OpenLane的Docker鏡像。等整個流程跑通了再考慮逐個替換工具做定制化。2.2 Sky130 PDK的獲取與配置Sky130 PDK是SkyWater公司開源的一個130nm工藝節(jié)點包含了標(biāo)準(zhǔn)單元庫、IO庫、SRAM編譯器、以及各種工藝文件。獲取方式主要有兩個一個是Google和SkyWater合作的Sky130 PDK倉庫另一個是通過OpenLane自帶的PDK安裝腳本。PDK里面你最需要關(guān)注的是這幾個東西組件用途關(guān)鍵文件標(biāo)準(zhǔn)單元庫綜合和布局布線的基礎(chǔ)sky130_fd_sc_hd 系列工藝文件DRC/LVS規(guī)則sky130A.tech (Magic)時序庫靜態(tài)時序分析.lib 文件物理庫布局布線用.lef 文件配置PDK的時候最容易出問題的是環(huán)境變量。OpenLane需要知道PDK的根目錄在哪通常通過PDK_ROOT和PDK兩個變量來指定。如果你手動安裝PDK一定要確保目錄結(jié)構(gòu)跟OpenLane預(yù)期的一致否則它會找不到庫文件然后報一堆莫名其妙的錯誤。我踩過的一個坑是PDK版本和OpenLane版本不匹配。OpenLane的某些版本對PDK的目錄結(jié)構(gòu)有特定要求如果你用的是舊版PDK配新版OpenLane可能會在讀取LEF文件的時候報錯。解決辦法是看OpenLane的文檔確認(rèn)它推薦的PDK版本然后嚴(yán)格按那個版本來。2.3 硬件資源的最低要求開源EDA工具鏈對機(jī)器性能的要求其實不低。綜合和布局布線都是計算密集型任務(wù)尤其是布局布線階段OpenROAD會吃滿CPU并且占用大量內(nèi)存。我的實測數(shù)據(jù)一個中等復(fù)雜度的設(shè)計大約幾千個標(biāo)準(zhǔn)單元在8核16線程的機(jī)器上跑完整個OpenLane流程大約需要30到60分鐘。內(nèi)存方面16GB是底線32GB會比較從容。如果你只有8GB內(nèi)存大概率會在routing階段因為OOM內(nèi)存不足而失敗。磁盤空間也要留夠PDK加上工具鏈加上中間文件輕松超過20GB。建議至少留50GB的可用空間。3. RTL設(shè)計與綜合從代碼到門級網(wǎng)表3.1 寫RTL時就要考慮的事很多人寫RTL的時候只關(guān)注功能正確等到綜合和布局布線的時候才發(fā)現(xiàn)一堆問題。開源工具鏈對RTL的“容忍度”比商業(yè)工具低有些寫法在商業(yè)綜合器里能過在Yosys里就會出問題。幾個必須注意的點避免使用不可綜合的SystemVerilog特性。Yosys對SystemVerilog的支持在不斷完善但仍然有一些高級特性不支持比如某些類型的interface、復(fù)雜的斷言、動態(tài)數(shù)組等。我建議RTL階段就用Verilog-2001或者SystemVerilog的一個保守子集別一上來就用花哨的語法。時鐘域處理要干凈。開源流程對多時鐘域的支持是有的但配置起來比較麻煩。如果你的設(shè)計有多個時鐘建議先做時鐘域交叉CDC的同步處理然后在約束文件里明確指定每個時鐘的頻率和關(guān)系。復(fù)位策略要統(tǒng)一。同步復(fù)位還是異步復(fù)位在綜合和時序分析時會有不同的處理方式。Sky130的標(biāo)準(zhǔn)單元庫里有帶異步復(fù)位端的觸發(fā)器如果你用異步復(fù)位綜合器會直接映射到這些單元上。但如果你的復(fù)位信號處理不當(dāng)可能會在布局布線后出現(xiàn)復(fù)位樹時序問題。3.2 Yosys綜合腳本的編寫要點Yosys的綜合流程大致是讀入RTL → 層次化處理 → 工藝映射 → 優(yōu)化 → 輸出網(wǎng)表。每一步都有對應(yīng)的命令你可以寫一個.ys腳本來自動化。一個典型的綜合腳本長這樣# 讀取RTL read_verilog top.v read_verilog sub_module.v # 指定頂層模塊 hierarchy -top top # 工藝無關(guān)優(yōu)化 proc; opt; fsm; opt; memory; opt # 映射到Sky130標(biāo)準(zhǔn)單元 techmap abc -liberty $PDK_ROOT/sky130A/libs.ref/sky130_fd_sc_hd/lib/sky130_fd_sc_hd__tt_025C_1v80.lib # 輸出網(wǎng)表 write_verilog -noattr top_synth.v這里有幾個容易出問題的地方abc命令的-liberty參數(shù)必須指向正確的.lib文件。Sky130的標(biāo)準(zhǔn)單元庫有多個版本hd、hdll、hs等對應(yīng)不同的面積和速度權(quán)衡。hd是高密度庫單元面積小但驅(qū)動能力弱hs是高速庫面積大但速度快。選哪個取決于你的設(shè)計目標(biāo)。綜合后的網(wǎng)表要檢查一下有沒有未映射的單元。有時候Yosys會遇到無法映射的邏輯會保留成通用門或者直接報錯。你可以用stat命令查看綜合后的統(tǒng)計信息確認(rèn)所有邏輯都映射到了Sky130的單元上。3.3 時序約束文件的寫法時序約束是綜合和布局布線的“指揮棒”。在開源流程里約束文件通常是SDC格式包含時鐘定義、輸入輸出延遲、虛假路徑等。一個最基本的SDC文件create_clock -name clk -period 10 [get_ports clk] set_input_delay -clock clk 2 [all_inputs] set_output_delay -clock clk 2 [all_outputs] set_load 0.1 [all_outputs]create_clock的-period參數(shù)決定了你的目標(biāo)頻率。10ns對應(yīng)100MHz對于Sky130這個130nm工藝來說100MHz是一個比較保守但容易達(dá)到的目標(biāo)。如果你想跑更高的頻率比如200MHz5ns周期就需要更仔細(xì)地優(yōu)化邏輯深度和布局。實操心得第一次跑的時候把時鐘周期設(shè)得寬松一點比如20ns先確保整個流程能跑通。等流程通了再逐步收緊約束看能跑到多少頻率。這樣比一上來就設(shè)一個激進(jìn)的約束然后卡在時序收斂上要好得多。4. 布局布線OpenROAD實戰(zhàn)4.1 Floorplan階段的關(guān)鍵決策Floorplan是布局布線的第一步?jīng)Q定了芯片的物理形狀和標(biāo)準(zhǔn)單元的擺放區(qū)域。OpenROAD的floorplan主要需要你指定兩個東西die的面積和core的面積。die是整個芯片的邊界包括IO pad和電源環(huán)。core是實際擺放標(biāo)準(zhǔn)單元的區(qū)域在die內(nèi)部。core的面積直接決定了布局的密度——面積太小會導(dǎo)致布線擁塞面積太大則浪費(fèi)硅片面積。怎么估算core面積一個經(jīng)驗公式是core面積 ≈ 標(biāo)準(zhǔn)單元總面積 / 目標(biāo)利用率。目標(biāo)利用率一般在0.5到0.7之間。比如你的標(biāo)準(zhǔn)單元總面積是10000平方微米目標(biāo)利用率0.6那core面積大約需要16700平方微米。OpenROAD的floorplan命令initialize_floorplan -die_area 0 0 200 200 \ -core_area 10 10 190 190 \ -site $::env(PDK_ROOT)/sky130A/libs.ref/sky130_fd_sc_hd/techlef/sky130_fd_sc_hd__nom.tlef這里的-site參數(shù)指定了標(biāo)準(zhǔn)單元的site定義必須跟PDK里的tech LEF文件對應(yīng)。4.2 Placement與CTS的注意事項Placement分兩步全局布局global placement和詳細(xì)布局detailed placement。全局布局決定每個單元的大致位置詳細(xì)布局做精細(xì)調(diào)整。OpenROAD的全局布局命令是global_placement詳細(xì)布局是detailed_placement。跑完placement之后建議用check_placement檢查一下有沒有重疊或者越界的單元。CTS時鐘樹綜合是布局布線里比較關(guān)鍵的一步。時鐘信號需要被均勻地分配到所有觸發(fā)器時鐘偏差skew要盡可能小。OpenROAD的clock_tree_synthesis命令會自動構(gòu)建時鐘樹你可以通過參數(shù)控制緩沖器的類型和數(shù)量。我遇到的一個坑是CTS之后沒有重新跑時序分析直接進(jìn)入routing結(jié)果routing完成后發(fā)現(xiàn)時序違例嚴(yán)重。正確的做法是CTS之后跑一次STA靜態(tài)時序分析確認(rèn)時鐘樹的質(zhì)量如果有問題就調(diào)整CTS參數(shù)重新跑。4.3 Routing階段的常見問題Routing分全局路由global routing和詳細(xì)路由detailed routing。全局路由規(guī)劃大致的走線路徑詳細(xì)路由確定具體的金屬層和通孔位置。Routing階段最常見的問題是擁塞congestion。當(dāng)某個區(qū)域的走線需求超過了可用的布線資源時就會出現(xiàn)擁塞導(dǎo)致routing失敗或者產(chǎn)生大量DRC違例。解決擁塞的幾個思路調(diào)整floorplan增大core面積降低布局密度。調(diào)整placement用-density參數(shù)控制布局密度或者手動添加placement blockage。調(diào)整routing參數(shù)OpenROAD的detailed_route命令有多個參數(shù)可以調(diào)整比如-droute_end_iter控制迭代次數(shù)-verbose輸出詳細(xì)信息。我實測下來Sky130的金屬層資源相對緊張尤其是對于復(fù)雜度較高的設(shè)計。如果你的設(shè)計標(biāo)準(zhǔn)單元數(shù)量超過5000個建議把core面積留得寬裕一些否則routing階段會非常痛苦。5. 物理驗證DRC與LVS5.1 DRC檢查與修復(fù)DRCDesign Rule Check是檢查版圖是否符合工藝制造規(guī)則的過程。Sky130的DRC規(guī)則有幾百條涉及金屬間距、寬度、通孔尺寸、阱間距等等。用Magic跑DRCmagic -d sky130A -rcfile $PDK_ROOT/sky130A/libs.tech/magic/sky130A.magicrc進(jìn)入Magic后加載GDS文件然后執(zhí)行drc check和drc why查看違例詳情。DRC違例的修復(fù)有時候很直接比如手動調(diào)整某條金屬線的寬度有時候很麻煩比如需要重新跑routing。常見的DRC違例類型包括違例類型原因修復(fù)方式金屬間距不足routing太密調(diào)整routing參數(shù)或增大間距通孔尺寸不對使用了錯誤的通孔類型檢查PDK的通孔定義阱間距不足標(biāo)準(zhǔn)單元擺放太近調(diào)整placement密度天線效應(yīng)長金屬線連接到柵極插入天線二極管注意DRC修復(fù)是一個迭代過程。修完一輪之后要重新跑DRC因為你的修改可能會引入新的違例。建議每次修改后都完整跑一遍DRC不要攢著一起修。5.2 LVS驗證的流程LVSLayout Versus Schematic是檢查版圖提取出的網(wǎng)表跟原始原理圖網(wǎng)表是否一致。這一步能發(fā)現(xiàn)短路、斷路、錯誤連接等問題。LVS的流程通常是從GDS提取版圖網(wǎng)表 → 跟綜合后的網(wǎng)表對比 → 報告差異。用Netgen做LVSnetgen -batch lvs layout.spice top schematic.spice top \ $PDK_ROOT/sky130A/libs.tech/netgen/sky130A_setup.tclLVS通過的關(guān)鍵是確保版圖提取的網(wǎng)表跟原理圖網(wǎng)表在拓?fù)渖弦恢?。有時候DRC通過了但LVS不通過通常是因為某些連接在版圖上存在但在原理圖上沒有或者反過來。我遇到過一個典型問題電源和地的連接在版圖上是通過電源環(huán)和電源條實現(xiàn)的但原理圖網(wǎng)表里可能沒有顯式地包含這些連接。這種情況下需要在LVS設(shè)置里正確處理電源網(wǎng)絡(luò)的映射。5.3 天線效應(yīng)檢查天線效應(yīng)是制造過程中的一種失效機(jī)制長的金屬線在等離子刻蝕過程中會積累電荷如果這條金屬線連接到晶體管的柵極積累的電荷可能會擊穿柵氧化層。Sky130的DRC規(guī)則里包含天線效應(yīng)的檢查。修復(fù)方法通常是在長金屬線和柵極之間插入一個天線二極管給積累的電荷提供一條泄放路徑。OpenROAD在routing階段可以自動插入天線二極管你需要確保在配置里啟用了這個功能。如果routing完成后DRC報告天線違例可以手動在違例位置插入二極管然后重新跑DRC。6. 流片提交最后的臨門一腳6.1 OpenMPW的提交要求OpenMPWOpen Multi-Project Wafer是Google和SkyWater合作的一個項目定期組織免費(fèi)流片。提交需要準(zhǔn)備的東西包括最終的GDS文件版圖截圖和設(shè)計說明引腳定義和封裝要求驗證報告DRC clean、LVS clean提交前一定要仔細(xì)檢查GDS文件的內(nèi)容。我見過有人提交的GDS里包含了測試結(jié)構(gòu)或者未連接的單元結(jié)果流片出來的芯片功能不對。建議用KLayout打開GDS逐層檢查確認(rèn)沒有多余的東西。6.2 提交前的最終檢查清單在點擊提交按鈕之前我建議按這個清單過一遍DRC cleanMagic和KLayout都跑一遍確保沒有違例。LVS cleanNetgen確認(rèn)版圖跟網(wǎng)表一致。時序收斂STA報告沒有setup和hold違例。電源網(wǎng)絡(luò)完整確認(rèn)所有單元都連接到了電源和地。IO pad正確如果有IO pad確認(rèn)pad的位置和連接正確。GDS層次結(jié)構(gòu)確認(rèn)頂層單元名稱正確沒有多余的層次。文件格式確認(rèn)GDS版本跟shuttle要求的一致。6.3 流片后的測試準(zhǔn)備芯片流片回來之后你需要準(zhǔn)備測試方案。OpenMPW的芯片通常是QFN或者DIP封裝引腳數(shù)有限。你需要提前設(shè)計好PCB測試板準(zhǔn)備好電源、時鐘源和信號采集設(shè)備。測試的時候先從電源開始確認(rèn)芯片的電源引腳沒有短路然后上電測量靜態(tài)電流。如果電流異常大可能是內(nèi)部有短路。靜態(tài)電流正常后再給時鐘信號觀察輸出引腳的行為。我個人經(jīng)驗是第一次流片最好設(shè)計一個簡單的測試電路比如一個計數(shù)器或者移位寄存器功能簡單、容易驗證。等第一次成功了再嘗試更復(fù)雜的設(shè)計。7. 常見問題速查與避坑總結(jié)7.1 工具報錯速查表報錯信息可能原因解決方法Cannot find liberty filePDK路徑配置錯誤檢查PDK_ROOT環(huán)境變量Routing congestion布局密度過高增大core面積或降低利用率Timing violation邏輯深度太大或約束太緊優(yōu)化RTL或放寬時鐘周期DRC violation: metal spacing金屬間距不足調(diào)整routing參數(shù)重新跑LVS mismatch版圖與網(wǎng)表不一致檢查電源連接和未連接單元Out of memory設(shè)計太大或機(jī)器內(nèi)存不足增加內(nèi)存或分塊處理7.2 那些文檔里不會寫的經(jīng)驗第一版本管理很重要。開源工具鏈的版本更新很快不同版本之間的行為可能有差異。建議用Git管理你的設(shè)計文件和腳本每次跑通一個版本就打個tag。這樣出了問題可以回退到已知可用的狀態(tài)。第二增量跑流程。不要每次都從頭跑整個流程。OpenROAD支持從中間步驟恢復(fù)比如你改了placement參數(shù)可以只重跑placement之后的部分。這樣能節(jié)省大量時間。第三多看日志。OpenROAD和Yosys的日志信息很豐富很多問題在日志里都有提示。比如routing階段的擁塞報告會告訴你哪個區(qū)域擁塞最嚴(yán)重時序報告會告訴你哪條路徑違例最多。學(xué)會看日志能幫你快速定位問題。第四社區(qū)是最好的老師。OpenROAD、OpenLane、Sky130都有活躍的社區(qū)論壇和聊天群。遇到問題先搜一下大概率有人已經(jīng)遇到過了。如果搜不到提問的時候附上完整的日志和配置文件這樣別人才能幫你分析。第五別怕失敗。我第一次跑完整流程的時候DRC違例有上千個時序違例幾十條整個人都懵了。但一個一個修下來最后也搞定了。開源流程的成熟度已經(jīng)足夠支撐實際流片關(guān)鍵是你愿不愿意花時間跟它磨。7.3 性能優(yōu)化的幾個方向如果你想讓設(shè)計跑得更快或者面積更小可以從這幾個方向入手邏輯優(yōu)化在RTL階段減少邏輯深度用流水線換頻率。綜合策略嘗試不同的綜合選項比如abc的-script參數(shù)可以指定優(yōu)化腳本。布局策略調(diào)整placement的密度和擁塞控制參數(shù)。時鐘樹優(yōu)化調(diào)整CTS的緩沖器類型和數(shù)量減小skew。電源網(wǎng)絡(luò)優(yōu)化合理規(guī)劃電源條的數(shù)量和寬度減小IR drop。這些優(yōu)化都需要反復(fù)迭代和對比建議每次只改一個變量觀察效果。8. 寫在最后走完這一整套流程我最大的感受是開源EDA和Sky130 PDK已經(jīng)不再是“玩具”了。它們確實能支撐真實的芯片設(shè)計雖然在某些方面還不如商業(yè)工具成熟但對于學(xué)習(xí)、研究和中小規(guī)模的設(shè)計來說完全夠用。如果你正在考慮走這條路我的建議是先跑通一個最簡單的設(shè)計比如一個8位計數(shù)器把整個流程走一遍理解每個階段在做什么。然后再逐步增加設(shè)計的復(fù)雜度同時深入學(xué)習(xí)每個階段的優(yōu)化技巧。不要一上來就做一個復(fù)雜的SoC那樣很容易在某個環(huán)節(jié)卡住然后失去信心。另外OpenMPW的申請是有時間窗口的提前關(guān)注相關(guān)的公告規(guī)劃好你的設(shè)計周期。從開始設(shè)計到提交留出至少一個月的時間因為調(diào)試和驗證往往會超出預(yù)期。最后說一個實際體會開源工具鏈的社區(qū)非常友好很多問題在社區(qū)里都能找到答案。我在這條路上遇到的絕大多數(shù)困難都是通過查文檔、看日志、問社區(qū)解決的。所以別一個人悶頭搞多跟社區(qū)交流效率會高很多。