計(jì)WDT看門狗:從需求拆解到RTL驗(yàn)證的完整實(shí)踐)
在可編程邏輯和芯片設(shè)計(jì)的圈子里IPIntellectual Property這個(gè)詞聽起來(lái)多少有點(diǎn)距離感。說(shuō)白了它就是一段經(jīng)過(guò)驗(yàn)證、可以反復(fù)復(fù)用的電路功能模塊從串口、I2C到復(fù)雜的總線橋都算。這幾年AI輔助開發(fā)在軟件界已經(jīng)卷成常態(tài)但在硬件設(shè)計(jì)領(lǐng)域很多人還是將信將疑總覺得RTL這種東西“AI寫不了”。我自己的態(tài)度是有保留的于是挑了看門狗WDTWatchdog Timer這個(gè)經(jīng)典模塊做了一次從零開始的AI輔助設(shè)計(jì)。結(jié)果不算驚艷卻非常務(wù)實(shí)活兒能干但前提是你得把設(shè)計(jì)意圖徹底想清楚不然AI會(huì)把定時(shí)器做成FPGA Demo而不是一顆能上芯的IP。這篇不是理論課我會(huì)把整個(gè)流程拆開需求規(guī)格、提示詞設(shè)計(jì)、RTL生成、驗(yàn)證平臺(tái)、集成復(fù)盤每個(gè)環(huán)節(jié)都放我實(shí)際用過(guò)的代碼和踩過(guò)的坑。就算你沒(méi)有接觸過(guò)數(shù)字IC設(shè)計(jì)看完也能明白AI輔助硬件設(shè)計(jì)到底省在哪、難在哪。1. 需求拆解AI設(shè)計(jì)的第一步不是寫代碼而是把“邊界”寫清楚1.1 看門狗WDT到底要干哪些活看門狗定時(shí)器Watchdog TimerWDT是絕大多數(shù)SoC和單片機(jī)里都有的基礎(chǔ)外設(shè)它的職責(zé)非常粗暴用硬件去監(jiān)測(cè)系統(tǒng)軟件是否還活著。如果軟件運(yùn)行正常就會(huì)周期性喂狗也就是往WDT某個(gè)寄存器寫一個(gè)特定值讓計(jì)數(shù)器重置如果軟件死循環(huán)、跑飛或者干脆宕機(jī)了計(jì)數(shù)器就會(huì)一路減到零WDT隨即發(fā)出復(fù)位信號(hào)或者中斷通知讓系統(tǒng)拉回可控狀態(tài)。聽起來(lái)就是一個(gè)倒計(jì)時(shí)器對(duì)不對(duì)直接按著這個(gè)理解去讓AI生成會(huì)發(fā)現(xiàn)提示詞根本沒(méi)法提取出設(shè)計(jì)特征。這個(gè)模塊看著邏輯簡(jiǎn)單但它有三個(gè)容易出問(wèn)題的邊界。一是窗口喂狗。只做“最長(zhǎng)時(shí)間到了就復(fù)位”是最低級(jí)的看門狗現(xiàn)在主流設(shè)計(jì)都會(huì)做窗口模式。喂狗太早也不行因?yàn)檫^(guò)早喂狗說(shuō)明程序可能在重復(fù)某段短暫執(zhí)行的邏輯并沒(méi)有真正運(yùn)行到主循環(huán)甚至可能是在死循環(huán)里碰巧經(jīng)過(guò)喂狗代碼。窗口模式要求喂狗必須在計(jì)數(shù)器值落到某一段區(qū)間內(nèi)才能成功早喂、晚喂都觸發(fā)復(fù)位。二是防誤關(guān)機(jī)制。看門狗開關(guān)如果只是一位使能寄存器系統(tǒng)軟件一旦跑飛先給你寫個(gè)零把WDT關(guān)了那看門狗就徹底失去了意義。所以常見做法是想要修改控制寄存器必須先在鎖寄存器里寫入一串固定數(shù)值行業(yè)里叫unlock sequence或者寫保護(hù)。三是復(fù)位信號(hào)的處理。WDT發(fā)的不是普通脈沖它要區(qū)分是上電復(fù)位還是看門狗復(fù)位也要保證復(fù)位電平寬度足夠讓系統(tǒng)里其他模塊完成復(fù)位流程同時(shí)又要避免把復(fù)位原因寄存器沖掉。這些細(xì)節(jié)直接決定芯片中的復(fù)位管理模塊怎么協(xié)同工作。我最初給的提示詞只寫了“16位遞減計(jì)數(shù)器、定時(shí)到了輸出復(fù)位信號(hào)”AI立刻給我返了個(gè)勉強(qiáng)能跑的模塊但計(jì)數(shù)器到0只保持了一個(gè)周期就自己恢復(fù)成復(fù)位值這在真實(shí)系統(tǒng)里完全不夠——很多外設(shè)的復(fù)位邏輯需要幾十甚至上百個(gè)時(shí)鐘周期才能完成狀態(tài)收斂。所以這次實(shí)踐給我的第一個(gè)啟發(fā)是給AI寫提示詞本質(zhì)上是在幫它做“可綜合功能的邊界定義”。1.2 分頻、計(jì)數(shù)和喂狗序列先把參數(shù)表釘死先確定一下這次設(shè)計(jì)的目標(biāo)參數(shù)。為了讓驗(yàn)證不過(guò)于簡(jiǎn)單我把核心計(jì)數(shù)器定位32位驅(qū)動(dòng)時(shí)鐘假設(shè)50MHz。這里需要先用一個(gè)預(yù)分頻器產(chǎn)生低頻的計(jì)數(shù)時(shí)鐘否則32位計(jì)數(shù)器在50MHz下要跑到85秒才溢滿仿真和功能驗(yàn)證都要跟著遭殃。我選的分頻系數(shù)是256這樣計(jì)數(shù)時(shí)鐘約為195312.5Hz計(jì)數(shù)步進(jìn)是5.12微秒。老老實(shí)實(shí)把全范圍跑完大概需要將近86秒日常調(diào)試如果嫌長(zhǎng)可以留一個(gè)仿真專用的快速配置寄存器直接改計(jì)數(shù)初始值。這里注意一點(diǎn)分頻系數(shù)、計(jì)數(shù)寬度、超時(shí)閾值都做參數(shù)化不給參數(shù)化會(huì)讓后面做SoC集成的人很頭疼因?yàn)椴煌酒黝l不同WDT的固定時(shí)間反而沒(méi)通用性。喂狗序列我選了經(jīng)典的雙鍵方式總線先寫0x5A再寫0xA5只有連續(xù)兩次寫入成功才真正把計(jì)數(shù)器重裝回初始值。如果第一次寫錯(cuò)或第二次寫錯(cuò)都要讓“喂狗狀態(tài)機(jī)”清零避免軟件只靠反復(fù)窮舉喂狗序列來(lái)碰運(yùn)氣。再加一層鎖寄存器解鎖碼0xE1E5必須要先寫對(duì)解鎖碼控制寄存器里使能位才可以被修改。我把寄存器表做成了一張會(huì)說(shuō)人話的表格寄存器名偏移位寬讀/寫功能說(shuō)明WDT_CTRL0x002R/Wbit0:使能 bit1:窗口模式使能WDT_LOAD0x0432R/W重裝載值WDT啟動(dòng)時(shí)讀取WDT_FEED0x088W依次寫0x5A、0xA5完成喂狗WDT_LOCK0x0C32W寫0xE1E5解鎖控制寄存器WDT_INT_ST0x101R/W1C中斷標(biāo)志位寫1清除我建議讀者在做類似設(shè)計(jì)時(shí)把這張表格當(dāng)作提示詞的一部分直接發(fā)給AI。別小看這個(gè)動(dòng)作我實(shí)際對(duì)比過(guò)不給寄存器表讓AI自由發(fā)揮的版本AI會(huì)自己發(fā)明接口生成之后你再跟總線側(cè)對(duì)齊改動(dòng)成本非常高。接口一旦定死AI返工的痛苦就沒(méi)有了。1.3 時(shí)序和復(fù)位策略不能丟給AI自由發(fā)揮再聊聊時(shí)序約束。我說(shuō)過(guò)這個(gè)模塊的復(fù)位策略在真實(shí)SoC里很微妙。我自己定的復(fù)位策略如下整個(gè)模塊使用一個(gè)異步復(fù)位信號(hào)sys_reset_n上電時(shí)有效由芯片復(fù)位管理模塊統(tǒng)一拉低。WDT模塊內(nèi)部所有同步邏輯都統(tǒng)一用這個(gè)異步復(fù)位置0在這個(gè)復(fù)位樹上消除毛刺的辦法是由復(fù)位管理模塊統(tǒng)一做時(shí)鐘域同步WDT本身只管接收。這里很多人會(huì)糾結(jié)既然已經(jīng)有了異步復(fù)位做整體復(fù)位為什么中斷、使能寄存器還要額外做同步清除為了穩(wěn)妥。實(shí)際項(xiàng)目中跑飛現(xiàn)場(chǎng)經(jīng)常是無(wú)規(guī)律的你在頂層硬件上留一個(gè)“看門狗復(fù)位清使能”的電平信號(hào)比依賴軟件自己重新配置更靠譜。計(jì)數(shù)器遞減邏輯反而用同步復(fù)位就夠了。因?yàn)楫惒綇?fù)位用于模塊整體復(fù)位計(jì)數(shù)器遞減屬于正常運(yùn)行路徑每一拍都用時(shí)鐘沿對(duì)齊如果計(jì)數(shù)路徑也搞全異步復(fù)位綜合工具在STA階段反而會(huì)多出不確定路徑。這個(gè)決定是我在生成RTL前端就寫進(jìn)提示詞的要求AI在這個(gè)點(diǎn)上做了但它額外給我加了一句“posedge clk or negedge rst_n”的異步復(fù)位寫法后來(lái)審查時(shí)被我一處處揪出來(lái)改掉了因?yàn)槲乙木褪怯?jì)數(shù)器內(nèi)部的復(fù)位始終同步。把判斷都在需求階段定好最后會(huì)發(fā)現(xiàn)提示詞已經(jīng)不像是在聊天更像一份簡(jiǎn)化的RTL spec。這其實(shí)就對(duì)了AI再怎么聰明也不會(huì)替你背“系統(tǒng)的功能性需求”它只是把自然語(yǔ)言翻譯成描述語(yǔ)言和寄存器邏輯的工具。2. 讓AI動(dòng)手寫RTL提示詞、工具與首輪代碼審查2.1 工具選擇和關(guān)于大模型的幾條心得工具上我嘗試了GitHub Copilot、ChatGPT和Claude。結(jié)論先說(shuō)寫這種工業(yè)風(fēng)格RTLClaude的完成度高ChatGPT勝在上下文交互Copilot適合在已有框架里補(bǔ)填空。但我最后還是用最笨的辦法把大段提示詞發(fā)給對(duì)話工具然后COPY代碼回編輯器。原因很現(xiàn)實(shí)IDE里邊的AI補(bǔ)全對(duì)我想保持的“從需求出發(fā)”沒(méi)有幫助——它太迎合我手頭的半成品代碼而不是從設(shè)計(jì)規(guī)范出發(fā)。關(guān)于大模型硬傷我總結(jié)三條其一它對(duì)“可綜合性”是盲的會(huì)一廂情愿地寫initial塊、fork join、甚至原語(yǔ)其二它會(huì)自作聰明添加一些多余的狀態(tài)——看著結(jié)構(gòu)漂亮但綜合出來(lái)面積和時(shí)序就講故事了其三它對(duì)接口的想象非常脆弱如果寄存器表里沒(méi)寫明位寬它按時(shí)就按32位全量處理而實(shí)際設(shè)計(jì)中往往是需要位寬匹配的。這些觀點(diǎn)不是紙上談兵是這次設(shè)計(jì)里實(shí)際撞過(guò)的坑。AI生成代碼的過(guò)程其實(shí)很流暢但你一旦放松審查它會(huì)把整個(gè)模塊變成“仿真器里正常、綜合器里崩潰”的定時(shí)炸彈。2.2 我實(shí)際使用的提示詞高成功率模板為了方便快速執(zhí)行我通常會(huì)把設(shè)計(jì)需求組合成下面這種格式盡量一次給出所有約束。提示詞本身的套路比大家想象得樸素就是把“接口、行為、約束邊界”分開放像填單子一樣一項(xiàng)項(xiàng)寫清楚。這里我給一個(gè)我自己實(shí)際用過(guò)的精簡(jiǎn)版提示詞讀者可以直接套請(qǐng)你用Verilog設(shè)計(jì)一個(gè)32位遞減計(jì)數(shù)的看門狗定時(shí)器模塊。 接口要求 - 輸入clkrst_nbus_wrbus_addrbus_wdata - 輸出wdt_rstwdt_int以及一個(gè)仿真調(diào)試用計(jì)數(shù)器值輸出cnt_dbg 行為要求 - 復(fù)位方式模塊入口使用異步復(fù)位計(jì)數(shù)器內(nèi)部使用同步復(fù)位 - 分頻對(duì)clk做256分頻后產(chǎn)生計(jì)數(shù)脈沖但只能作為時(shí)鐘使能不能作為獨(dú)立時(shí)鐘 - 喂狗程序依次向FEED寄存器寫0x5A和0xA5兩個(gè)值連續(xù)正確才重載計(jì)數(shù)器 - 窗口模式開啟窗口時(shí)計(jì)數(shù)器大于0x0FF0或小于0x0800時(shí)喂狗都觸發(fā)復(fù)位 - 計(jì)數(shù)器到0時(shí)輸出wdt_rst一個(gè)時(shí)鐘周期高電平 禁止項(xiàng) - 不允許使用initial - 不允許在always塊外產(chǎn)生變量 - 所有時(shí)序邏輯統(tǒng)一使用posedge clk有意思的是我試過(guò)讓AI自己梳理這類需求效果一般它會(huì)過(guò)度發(fā)揮。反而是把需求和幾個(gè)邊界條件直接丟給它干活速度快又準(zhǔn)。這個(gè)對(duì)比很重要AI在硬件設(shè)計(jì)里是“承重翻譯”不是“架構(gòu)師”。2.3 對(duì)AI生成代碼做的三處手術(shù)AI在第一次就給出了能編譯的主體代碼大約120行。但這120行里我在“使用”之前強(qiáng)制要求自己做了一次完整的review找出三個(gè)必須要改的地方。第一個(gè)問(wèn)題是計(jì)數(shù)器的遞減條件。AI默認(rèn)寫成了“只要使能就遞減”完全沒(méi)考慮預(yù)分頻和快重裝之間的競(jìng)爭(zhēng)。我要求遞減信號(hào)必須是在分頻計(jì)數(shù)滿之后產(chǎn)生的單周期脈沖AI卻把分頻計(jì)數(shù)器放在always塊里直接拿分頻輸出作為獨(dú)立時(shí)鐘節(jié)點(diǎn)。這在仿真中看不出來(lái)但綜合工具會(huì)報(bào)多時(shí)鐘警告上板甚至?xí)霈F(xiàn)隨機(jī)丟計(jì)數(shù)。我把它改為統(tǒng)一時(shí)鐘沿驅(qū)動(dòng)用一個(gè)分頻計(jì)滿脈沖作為時(shí)鐘使能而不是把分頻輸出當(dāng)獨(dú)立時(shí)鐘。第二個(gè)問(wèn)題是喂狗序列的狀態(tài)寄存器。AI用了一個(gè)單字節(jié)變量去記住當(dāng)前寫到第幾位可我要求的是通過(guò)一個(gè)只有三態(tài)的狀態(tài)機(jī)去區(qū)分“空閑、已寫0x5A、成功”這樣既節(jié)省資源也避免了狀態(tài)跳轉(zhuǎn)不完整導(dǎo)致的非法輸入問(wèn)題。第三個(gè)問(wèn)題也是最隱蔽的AI沒(méi)有統(tǒng)計(jì)“早到喂狗”。早期版本里只要寫入合法序列就會(huì)無(wú)條件重載計(jì)數(shù)器于是窗口模式形同虛設(shè)。我后來(lái)在狀態(tài)機(jī)里加了一段比較邏輯用上限和下限控制喂狗有效區(qū)段只要計(jì)數(shù)器的當(dāng)前值不在窗口區(qū)間內(nèi)喂狗序列完成也算非法。做完這三處修改整個(gè)模塊的代碼仍然保留著AI的骨架我自己只改了20%左右。這個(gè)過(guò)程讓我明顯感受到AI輔助RTL創(chuàng)作的真實(shí)定位它適合生成大框架和模板化代碼不適合承擔(dān)帶有系統(tǒng)策略性的時(shí)刻判斷。3. 用驗(yàn)證平臺(tái)來(lái)證明AI寫的IP到底能不能信3.1 測(cè)試平臺(tái)結(jié)構(gòu)從零搭的SystemVerilog仿真環(huán)境代碼寫完只是開始真正驗(yàn)證AI生成設(shè)計(jì)是否可靠的是仿真環(huán)境。用得最多的是SystemVerilog UVMUVM對(duì)于這種小外設(shè)反而顯得笨重。我用的是非常輕量的定向testbench加斷言核心思路是搭一個(gè)簡(jiǎn)單CPU模型模擬軟件通過(guò)總線讀寫WDT寄存器觀測(cè)WDT的復(fù)位和中斷行為。testbench里最重要的部分是總線模型。因?yàn)閃DT是外圍設(shè)備我要模擬軟件周期寫0x5A再到寫0xA5的過(guò)程??偩€模型里用task封裝一次寫操作task automatic bus_write(input bit [1:0] addr, input bit [31:0] wdata); (posedge clk); bus_wr 1b1; bus_addr addr; bus_wdata wdata; (posedge clk); bus_wr 1b0; endtask我在主測(cè)試序列里依次調(diào)用bus_write模擬CPU正常喂狗先寫0x5A到FEED寄存器再寫0xA5兩步做完后WDT內(nèi)部會(huì)重裝計(jì)數(shù)器。這里如果第二個(gè)周期被調(diào)成別的值就要能看到計(jì)數(shù)器不重裝繼續(xù)往下運(yùn)行這是最基本的功能驗(yàn)證項(xiàng)。配合斷言我用一個(gè)只讀的debug信號(hào)把計(jì)數(shù)器當(dāng)前值引出來(lái)在testbench里直接檢查喂狗之后的計(jì)數(shù)值約等于重裝載值property p_feed_reload; (posedge clk) disable iff(!rst_n) (wdt_reload_flag) | (cnt_dbg cnt_load_value); endproperty assert property(p_feed_reload);有了這種斷言仿真跑完直接看通過(guò)和失敗情況。這種斷言的意義在于讓AI生成邏輯里的隱性bug在仿真階段現(xiàn)形而不是等板子燒出來(lái)之后變玄學(xué)。3.2 測(cè)試用例清單一種“窗口喂狗”的獨(dú)特驗(yàn)證功能測(cè)試用例怎么定其實(shí)是整份驗(yàn)證計(jì)劃里最見功力的地方。對(duì)于WDT我梳理出下面幾條硬性用例。首先是“正常運(yùn)行不喂狗計(jì)數(shù)器到零時(shí)產(chǎn)生復(fù)位”。這是最核心的用例大部分WDT都必須過(guò)。仿真把超時(shí)配置為很短的初值比如計(jì)數(shù)100個(gè)主時(shí)鐘周期就溢出然后等待wdt_rst信號(hào)拉高。然后是“窗口內(nèi)喂狗正常重裝”和“窗口外喂狗觸發(fā)復(fù)位”。窗口模式開啟后我把窗口定義為重裝載值0x1000允許喂狗區(qū)間是0x0800到0x0FFF之間。軟件必須等計(jì)數(shù)器落到中段再喂喂太早比如計(jì)數(shù)還在0x1000附近和喂太晚比如計(jì)數(shù)值已經(jīng)小于0x0800都會(huì)被判斷為異常。實(shí)現(xiàn)這種驗(yàn)證最重要的地方是你要給testbench一個(gè)“讀取當(dāng)前計(jì)數(shù)值”的仿真調(diào)試接口這個(gè)接口在真實(shí)IP里可能不會(huì)暴露給軟件但在仿真階段是查狀態(tài)的關(guān)鍵窗口。還有一個(gè)很容易被忽略的用例是“連續(xù)兩步寫正確但中間間隔過(guò)長(zhǎng)”。為什么單獨(dú)提這一條因?yàn)槲构愤^(guò)程中第一步寫0x5A后如果長(zhǎng)時(shí)間不寫0xA5狀態(tài)機(jī)會(huì)一直停在中間態(tài)這種中間態(tài)如果被后續(xù)復(fù)位意外觸發(fā)清掉就會(huì)導(dǎo)致喂狗邏輯狀態(tài)錯(cuò)亂。我的處理是在狀態(tài)機(jī)加了一段超時(shí)自清邏輯如果0x5A寫后256個(gè)周期沒(méi)等到0xA5就自動(dòng)回空閑態(tài)。這個(gè)特性在第一版提示詞里沒(méi)有體現(xiàn)是驗(yàn)證時(shí)發(fā)現(xiàn)仿真狀態(tài)會(huì)卡在中間態(tài)回頭補(bǔ)進(jìn)去的。3.3 覆蓋率統(tǒng)計(jì)看看AI生成的RTL有沒(méi)有留死角功能仿真通過(guò)以后我跑了一遍覆蓋率分析。覆蓋率分兩塊行覆蓋率和狀態(tài)機(jī)遷移覆蓋率。行覆蓋率是說(shuō)RTL里每一行代碼都被執(zhí)行過(guò)沒(méi)有狀態(tài)機(jī)遷移覆蓋率則是狀態(tài)機(jī)的每個(gè)遷移邊都至少走過(guò)一次。行覆蓋率很快跑到了95%左右剩下5%基本都是錯(cuò)誤分支像“解鎖碼錯(cuò)誤”路徑如果只在異常注入用例里才走會(huì)被算進(jìn)死角。我為此單獨(dú)寫了一個(gè)異常注入用例專門往LOCK寄存器寫錯(cuò)誤值確保錯(cuò)誤路徑也能覆蓋到。狀態(tài)機(jī)遷移覆蓋率就更要重視喂狗狀態(tài)機(jī)一共有四個(gè)狀態(tài)IDLE、FEED_FIRST、FEED_SECOND、RELOAD。我的用例覆蓋了全部遷移邊的90%剩下一條邊是“兩個(gè)階段之間非法跳轉(zhuǎn)”得故意在FEED_FIRST狀態(tài)下連寫兩個(gè)0xA5才能踩到加上這個(gè)非法序列用例之后狀態(tài)機(jī)遷移覆蓋率就到了100%。這些覆蓋率在AI自己寫testbench的時(shí)候基本是陪跑需要人工補(bǔ)寫用例因?yàn)锳I對(duì)“覆蓋率優(yōu)化”這種驗(yàn)證域的認(rèn)知非常淺——它知道概念卻不知道邊界在哪。這正是驗(yàn)證工程師的經(jīng)驗(yàn)所在。4. 綜合前后AI生成代碼最容易翻車的三個(gè)環(huán)節(jié)4.1 復(fù)位風(fēng)格不一致仿真里的復(fù)位和綜合里的復(fù)位是兩回事前面在需求階段就說(shuō)了復(fù)位策略要提前定這里單獨(dú)把它作為綜合問(wèn)題再?gòu)?qiáng)調(diào)一次是因?yàn)锳I默認(rèn)生成的復(fù)位寫法往往是“全模塊統(tǒng)一異步復(fù)位”。這在做原型驗(yàn)證的FPGA上問(wèn)題不大但是在ASIC綜合時(shí)如果整個(gè)芯片復(fù)位樹已經(jīng)確定你又來(lái)了一堆用異步清0的寄存器很容易破壞復(fù)位樹和時(shí)鐘樹的平衡。我們這版代碼里計(jì)數(shù)器內(nèi)部用同步復(fù)位外部控制寄存器和中斷狀態(tài)寄存器用異步復(fù)位兩種風(fēng)格并存。這在RTL仿真階段很難發(fā)現(xiàn)但綜合工具會(huì)幫你插滿某種形式的復(fù)位邏輯時(shí)序上平白多出很多需要修的路徑。這種問(wèn)題本質(zhì)上是設(shè)計(jì)風(fēng)格的規(guī)范性。AI不會(huì)知道這顆芯片復(fù)位樹的時(shí)鐘域分區(qū)它只會(huì)機(jī)械地根據(jù)自然語(yǔ)言里出現(xiàn)“復(fù)位”的表述選用最常用的寫法。所以提示詞里必須寫明哪個(gè)小模塊用異步哪個(gè)部分用同步。這話說(shuō)著簡(jiǎn)單實(shí)際執(zhí)行起來(lái)還是得你自己心里有數(shù)。4.2 預(yù)分頻電路被AI寫成了獨(dú)立時(shí)鐘綜合立刻教你做人第二個(gè)翻車點(diǎn)是預(yù)分頻電路的處理。很多RTL新手和AI都會(huì)犯同一個(gè)毛病用計(jì)數(shù)器產(chǎn)生一個(gè)周期信號(hào)然后把這個(gè)信號(hào)當(dāng)成時(shí)鐘沿去驅(qū)動(dòng)下游邏輯。這在模塊仿真里邏輯功能確實(shí)對(duì)但在綜合工具眼中它就是一個(gè)新的時(shí)鐘節(jié)點(diǎn)會(huì)觸發(fā)CTCClock Tree Cell相關(guān)的違規(guī)整個(gè)工程里多個(gè)不確定路徑會(huì)把你折騰到崩潰。我要求AI生成代碼時(shí)明確所有邏輯都在同一個(gè)clk域預(yù)分頻輸出只是時(shí)鐘使能不是時(shí)鐘本身。經(jīng)過(guò)這一改綜合工具就不會(huì)多報(bào)出一個(gè)時(shí)鐘網(wǎng)了時(shí)序只收斂在單一主時(shí)鐘上工程簡(jiǎn)單一大截。很多讀者可能在軟件領(lǐng)域見過(guò)“把定時(shí)器回調(diào)當(dāng)成時(shí)鐘”的壞味道這句話在RTL里一樣準(zhǔn)確。解決思路就是“同源時(shí)鐘加使能”而不是“剪出細(xì)分時(shí)鐘”這個(gè)概念建議大家在審查AI代碼時(shí)單獨(dú)盯一下。4.3 集成角度WDT使能位不能輕易對(duì)系統(tǒng)軟件關(guān)閉最后說(shuō)一個(gè)真正會(huì)在芯片集成階段救命的點(diǎn)看門狗的使能位必須和系統(tǒng)復(fù)位原因、安全監(jiān)控邏輯綁定在一起。AI給了我一個(gè)很直接的使能寄存器en模塊內(nèi)部if(en)才開始計(jì)數(shù)理論上沒(méi)問(wèn)題可一旦系統(tǒng)軟件有能力直接關(guān)閉它前面所有的看門狗功能都是擺設(shè)。我在集成階段增加了兩個(gè)設(shè)計(jì)約束第一WDT_CTRL的寫操作必須受LOCK寄存器保護(hù)解鎖成功才能修改第二WDT一旦使能即使發(fā)生復(fù)位也要回到“使能”狀態(tài)除非外部有可靠的上電復(fù)位。這個(gè)做法在消費(fèi)電子芯片里非常常見叫“軟鎖定不可逆使能”策略。在代碼里它不是復(fù)雜邏輯但對(duì)安全性的提升非常關(guān)鍵。AI在這一步幫不上忙是我在做集成評(píng)審時(shí)被安全專家提醒回頭改了一版才鎖住的。5. 常見問(wèn)題速查與經(jīng)驗(yàn)總結(jié)5.1 驗(yàn)證階段遇到的高頻問(wèn)題清單我把這次開發(fā)過(guò)程中遇到的高頻問(wèn)題整理成一張表方便大家以后直接對(duì)照問(wèn)題現(xiàn)象大概率原因處理方式計(jì)數(shù)器遞減永遠(yuǎn)停不住預(yù)分頻使能被當(dāng)成持續(xù)高電平信號(hào)檢查分頻模塊的“滿僅一個(gè)周期”邏輯喂狗成功但計(jì)數(shù)器不重裝數(shù)據(jù)比較未在正確邊沿采樣把FEED數(shù)據(jù)的采樣放到wren有效沿窗口模式喂早不觸發(fā)復(fù)位窗口比較寫反或漏了早期判定在斷言里先觀察窗口判定信號(hào)復(fù)位輸出電平過(guò)窄用組合邏輯直接輸出復(fù)位改為寄存器打拍輸出中斷置位后無(wú)法清除沒(méi)做W1C寫1清除處理檢查總線讀回邏輯增加寫1清除通路綜合報(bào)多時(shí)鐘域警告預(yù)分頻輸出驅(qū)動(dòng)了邏輯改為“同源時(shí)鐘時(shí)鐘使能”寫法這張表上的前三條我在AI生成的第一版RTL里全中。說(shuō)實(shí)話不意外這幾個(gè)問(wèn)題在行業(yè)里也比較典型很多手工寫RTL的人也會(huì)踩但區(qū)別在于手工寫的人會(huì)憑著慣性規(guī)避AI不會(huì)你敲下來(lái)的每個(gè)細(xì)節(jié)它都會(huì)忠實(shí)執(zhí)行包括錯(cuò)誤。5.2 關(guān)于提示詞迭代的一些經(jīng)驗(yàn)有沒(méi)有什么能讓prompt效果更好的技巧我用下來(lái)比較靠譜的有幾條把寄存器的地址和位寬全部表格化把復(fù)位策略明確到模塊級(jí)別把“只允許一個(gè)時(shí)鐘域”“不允許initial”“不允許fork”這類禁列直接寫成約束條目最后要求AI在生成代碼的同時(shí)說(shuō)明關(guān)鍵路徑。一旦它解釋不通那地方基本上就是有問(wèn)題的。這個(gè)“反問(wèn)”法雖然在面向過(guò)程的代碼里也一樣管用但放到RTL上特別有效因?yàn)榭删C合代碼里不允許有“賭一把”的地方。另外我習(xí)慣把提示詞存版本每個(gè)版本的提示詞和對(duì)應(yīng)的RTL、仿真結(jié)果放同一工程目錄改動(dòng)一行需求就重新生成一次。時(shí)間長(zhǎng)了你會(huì)發(fā)現(xiàn)提示詞版本歷史就是比代碼注釋更全面的需求變更文檔比很多集成手冊(cè)都好用。5.3 一點(diǎn)心頭話回到開頭那句話AI能不能設(shè)計(jì)WDT能但它設(shè)計(jì)出來(lái)的東西跟你“會(huì)不會(huì)提出正確約束”是強(qiáng)綁定關(guān)系。從頭到尾把提示詞、寄存器表、驗(yàn)證、綜合跑完我的真實(shí)體感是AI至少把我預(yù)研時(shí)間壓掉了40%讓我能把精力放到窗口策略、復(fù)位樹和集成安全這些真正的設(shè)計(jì)難點(diǎn)上。以后做其他IP這套流程大概率也能復(fù)用先固化接口和時(shí)序再讓AI生成代碼然后人工重點(diǎn)審查狀態(tài)機(jī)和跨時(shí)鐘路徑最后用斷言和覆蓋率把高風(fēng)險(xiǎn)功能卡死。最后再分享一個(gè)小技巧如果項(xiàng)目時(shí)間充??梢园淹瑯拥脑O(shè)計(jì)需求發(fā)給兩個(gè)不同的大模型讓它們各生成一版然后互相當(dāng)reviewer。我在這個(gè)項(xiàng)目里就試過(guò)把其中一版的問(wèn)題丟給另一版去檢查它能指出很多人類容易忽略的邊界情況。AI互相挑刺你坐在中間當(dāng)裁判這種感覺挺奇妙的也算是2024年之后硬件設(shè)計(jì)工作流里最讓我興奮的變化之一。