實(shí)戰(zhàn):從規(guī)格書到可綜合RTL的AXI與仲裁器生成)
1. 從一份規(guī)格書到可綜合電路我為什么要折騰這套流程去年年底接手一個中等規(guī)模的IP模塊功能不復(fù)雜但接口協(xié)議是AXI4寄存器組有幾十個還帶一個輕量級的仲裁邏輯。按老路子我得先啃完兩百多頁的規(guī)格書手寫RTL再搭驗(yàn)證環(huán)境最后跑綜合看時序。整個過程下來光是把規(guī)格書里的文字翻譯成可綜合的Verilog就花了我將近三周。更別提中間因?yàn)槔斫馄罘倒さ哪菐状巍拇嫫鞯刂酚成溴e了一位仲裁優(yōu)先級搞反了AXI的BVALID握手時序沒對齊每一個都是低級錯誤但每一個都要花半天到一天去定位。后來我就在想規(guī)格書本身就是結(jié)構(gòu)化的描述寄存器表、狀態(tài)機(jī)、接口時序這些東西本質(zhì)上都是可以被機(jī)器理解的。如果能讓AI先幫我生成一版RTL骨架我再在上面做優(yōu)化和修正是不是能把重復(fù)勞動壓縮掉這就是我開始嘗試AI-Native IP研發(fā)流程的起點(diǎn)。所謂AI-Native不是簡單地在寫代碼時用一下補(bǔ)全工具而是把AI嵌入到從規(guī)格解析、架構(gòu)設(shè)計、RTL生成、驗(yàn)證用例生成到綜合約束的每一個環(huán)節(jié)里讓整個流程圍繞AI的能力重新組織。這篇文章適合誰看如果你正在做FPGA或ASIC的IP開發(fā)手頭有AXI、APB、SPI這類標(biāo)準(zhǔn)接口的模塊要寫或者你是一個SoC集成工程師需要快速評估第三方IP的接口行為那這套思路你可以直接參考。如果你只是好奇AI能不能寫RTL那也可以看看我在哪些環(huán)節(jié)踩了坑、哪些環(huán)節(jié)確實(shí)省了時間。我不會吹噓AI能替代工程師但我會告訴你在哪些具體步驟上它確實(shí)能把你的效率提升一個檔次。2. 整體流程設(shè)計把規(guī)格書拆成AI能吃的“飼料”2.1 為什么選擇以Spec為中心驅(qū)動傳統(tǒng)RTL開發(fā)是“人讀Spec人寫RTL人寫Testbench”整個鏈條里Spec是給人看的不是給機(jī)器看的。AI-Native流程的第一步就是把Spec變成機(jī)器可解析的結(jié)構(gòu)化數(shù)據(jù)。我試過兩種方式一種是直接把PDF丟給大模型讓它生成RTL另一種是先人工把Spec拆成結(jié)構(gòu)化的YAML或JSON再讓AI基于結(jié)構(gòu)化數(shù)據(jù)生成RTL。實(shí)測下來第二種方式靠譜得多。原因很簡單。PDF里的表格、腳注、跨頁引用對AI來說都是噪聲。你讓它從一段“寄存器0x10的bit[3:0]用于配置時鐘分頻系數(shù)默認(rèn)值為4”的文字里提取信息它可能給你生成一個帶復(fù)位值的寄存器也可能忘了復(fù)位值還可能把bit范圍搞錯。但如果我先把這個寄存器寫成結(jié)構(gòu)化的描述AI的出錯率會大幅下降。所以我的做法是人工做一次“Spec結(jié)構(gòu)化”把關(guān)鍵信息提取成機(jī)器可讀的格式后續(xù)所有AI生成環(huán)節(jié)都基于這份結(jié)構(gòu)化數(shù)據(jù)。2.2 結(jié)構(gòu)化Spec的字段設(shè)計我用的是一份YAML文件核心字段包括模塊名、接口列表、寄存器映射、狀態(tài)機(jī)描述、時序約束。接口列表里每個接口要寫清楚協(xié)議類型AXI4、APB、SPI等、數(shù)據(jù)位寬、地址位寬、ID位寬。寄存器映射里每個寄存器要有偏移地址、復(fù)位值、字段列表每個字段要有位范圍、讀寫屬性、功能描述。狀態(tài)機(jī)描述里要有狀態(tài)列表、轉(zhuǎn)移條件、輸出信號。時序約束里要寫清楚時鐘頻率、建立保持時間要求、跨時鐘域處理方式。這份YAML不是給AI看的最終產(chǎn)物而是我用來和AI對話的“底稿”。我會把這份YAML連同模塊的功能描述一起發(fā)給AI讓它生成RTL。這樣做的好處是AI不需要從自然語言里猜意圖它只需要把結(jié)構(gòu)化數(shù)據(jù)翻譯成Verilog語法。我試過同一個模塊直接丟PDF給AI生成的RTL有七處錯誤用結(jié)構(gòu)化YAML錯誤降到兩處而且都是可以快速修正的語法問題。2.3 工具鏈選型與AI模型選擇工具鏈方面我用的是開源的Verilator做仿真Yosys做綜合GTKWave看波形。AI模型方面我試過幾個主流的大語言模型最后固定用兩個一個擅長代碼生成一個擅長代碼審查。代碼生成的模型用來出RTL初稿代碼審查的模型用來找時序問題和協(xié)議違規(guī)。兩個模型交叉驗(yàn)證比單用一個模型靠譜。這里有個細(xì)節(jié)不要用同一個模型既生成又審查。我試過它對自己的錯誤有“盲區(qū)”審查時經(jīng)常放過自己生成的bug。換一個模型來審它能挑出不少問題。另外AI生成的RTL一定要過Lint工具。我用的Verilator自帶Lint能抓出位寬不匹配、未驅(qū)動信號、組合環(huán)路這些問題。Lint過了再進(jìn)仿真能省很多調(diào)試時間。3. 核心細(xì)節(jié)解析AXI接口與仲裁邏輯的AI生成要點(diǎn)3.1 AXI4接口的握手時序怎么讓AI理解AXI4的握手時序是AI生成RTL時最容易出錯的地方。VALID和READY的依賴關(guān)系、BVALID和BREADY的握手、RLAST和RVALID的配合這些如果只靠自然語言描述AI很容易搞混。我的做法是在結(jié)構(gòu)化Spec里專門寫一段“時序規(guī)則”用偽代碼的形式描述握手行為。比如對于寫地址通道我會寫“AWVALID由主機(jī)置高直到AWREADY為高后的下一個時鐘沿拉低。AWREADY由從機(jī)置高表示可以接收地址。AWVALID和AWREADY同時為高的時鐘沿地址被采樣?!边@段偽代碼發(fā)給AI后它生成的RTL里AWVALID和AWREADY的握手邏輯基本正確。但BVALID的生成邏輯它經(jīng)常出錯——BVALID應(yīng)該在寫數(shù)據(jù)接收完成后置高而不是在寫地址接收完成后。這個細(xì)節(jié)我在Spec里專門加了一條注釋“BVALID的置高條件是WLAST和WVALID同時為高且WREADY為高與AW通道無關(guān)?!奔恿诉@條之后AI生成的BVALID邏輯就對了。3.2 仲裁器的優(yōu)先級反轉(zhuǎn)問題仲裁器是另一個容易出問題的地方。我設(shè)計的仲裁器支持四個主設(shè)備優(yōu)先級可配置。AI生成的初版仲裁器用的是固定優(yōu)先級高優(yōu)先級設(shè)備一直占用總線低優(yōu)先級設(shè)備餓死。我在Spec里寫的是“輪詢仲裁”但AI理解成了“固定優(yōu)先級”。后來我在Spec里加了一段狀態(tài)轉(zhuǎn)移描述明確寫了“每次仲裁完成后優(yōu)先級指針移向下一個設(shè)備”AI才生成正確的輪詢邏輯。這里有個經(jīng)驗(yàn)對于仲裁器、狀態(tài)機(jī)這類有明確狀態(tài)轉(zhuǎn)移的邏輯最好在Spec里畫出狀態(tài)轉(zhuǎn)移表用表格形式列出當(dāng)前狀態(tài)、輸入條件、下一狀態(tài)、輸出信號。AI對表格的理解能力比純文字強(qiáng)得多。我試過用文字描述狀態(tài)機(jī)AI生成了五個狀態(tài)但轉(zhuǎn)移條件錯了三個換成表格后一次通過。3.3 寄存器組的自動生成與地址映射寄存器組是IP里最枯燥的部分但也是AI最擅長的部分。只要Spec里的寄存器表足夠清晰AI生成的寄存器讀寫邏輯基本不會出錯。我的做法是在YAML里定義每個寄存器的偏移地址、復(fù)位值、字段位寬和讀寫屬性然后讓AI生成一個寄存器文件模塊包含地址譯碼、讀寫使能、字段拼接。這里要注意的是地址對齊。AXI4的地址是字節(jié)地址但寄存器通常是32位對齊的。AI有時候會把地址譯碼寫成按字地址譯碼導(dǎo)致偏移量錯位。我在Spec里明確寫了“地址位[31:2]用于寄存器選擇位[1:0]忽略”AI生成的譯碼邏輯就正確了。另外對于只讀寄存器AI有時候會生成寫邏輯雖然綜合時會優(yōu)化掉但Lint會報warning。我在Spec里標(biāo)注了每個寄存器的讀寫屬性AI生成的代碼就干凈了。4. 實(shí)操過程從YAML到可綜合RTL的完整步驟4.1 第一步手工提取Spec關(guān)鍵信息到Y(jié)AML這一步不能省。我試過讓AI直接從PDF提取結(jié)果它把兩個寄存器的地址搞混了還把一個保留字段當(dāng)成了有效字段。手工提取雖然花時間但這是整個流程里唯一需要人工深度參與的部分大概占整個項(xiàng)目時間的20%。提取的時候我習(xí)慣用雙屏左邊開PDF右邊開YAML編輯器逐條對照。YAML的結(jié)構(gòu)我固定為幾個頂層字段module、interfaces、registers、fsm、timing。interfaces下面每個接口有name、protocol、data_width、addr_width、id_width。registers下面每個寄存器有name、offset、reset_value、fieldsfields下面每個字段有name、bits、access、description。fsm下面有states和transitions。timing下面有clock_freq、cdc_handling、handshake_rules。4.2 第二步用AI生成RTL骨架把YAML和一段簡短的模塊功能描述拼成一個prompt發(fā)給代碼生成模型。Prompt的模板我固定為“你是一個資深RTL工程師請根據(jù)以下結(jié)構(gòu)化規(guī)格生成可綜合的Verilog RTL。要求使用同步復(fù)位復(fù)位信號低有效所有寄存器輸出AXI接口遵循AXI4協(xié)議仲裁器使用輪詢策略。規(guī)格如下[YAML內(nèi)容]?!鄙傻臅r候我習(xí)慣讓AI分模塊生成而不是一次性生成整個IP。先讓它生成AXI接口模塊再生成寄存器文件再生成仲裁器最后生成頂層連線。分模塊生成的好處是每個模塊可以單獨(dú)Lint和仿真出了問題容易定位。一次性生成整個IP出了問題你得在幾千行代碼里找效率反而低。4.3 第三步Lint與仿真驗(yàn)證AI生成的RTL先過Verilator Lint。我用的命令是verilator --lint-only -Wall -Wno-DECLFILENAME top.v axi_if.v reg_file.v arbiter.vLint過了之后寫一個簡單的Testbench跑仿真。Testbench不用手寫讓AI根據(jù)Spec生成。我通常會讓AI生成一個帶隨機(jī)激勵的Testbench覆蓋寄存器讀寫、AXI突發(fā)傳輸、仲裁切換這幾個場景。仿真跑起來后用GTKWave看波形重點(diǎn)看握手信號和狀態(tài)轉(zhuǎn)移。這里有個技巧讓AI生成Testbench時要求它加入斷言assertion。比如“AWVALID拉高后AWREADY必須在10個周期內(nèi)置高”、“BVALID拉高后BREADY必須在5個周期內(nèi)置高”。這些斷言能在仿真時自動抓出協(xié)議違規(guī)比人工看波形快得多。4.4 第四步綜合與時序檢查仿真通過后用Yosys做綜合看資源占用和時序報告。我用的命令是yosys -p read_verilog top.v axi_if.v reg_file.v arbiter.v; synth; stat綜合報告里重點(diǎn)看兩個東西一是LUT和寄存器的數(shù)量二是關(guān)鍵路徑的延遲。如果關(guān)鍵路徑延遲超過時鐘周期的80%就得考慮優(yōu)化。AI生成的RTL有時候會有冗余邏輯比如重復(fù)的地址譯碼、不必要的多路選擇器。這些可以在綜合后手動優(yōu)化也可以讓AI重新生成一版在Prompt里加上“優(yōu)化關(guān)鍵路徑”的要求。5. 常見問題與排查技巧實(shí)錄5.1 AI生成的RTL仿真不通過怎么辦先看Lint有沒有過。Lint沒過先修Lint。Lint過了仿真不過大概率是握手時序或狀態(tài)轉(zhuǎn)移的問題。我的排查順序是先看復(fù)位是否正常釋放再看時鐘是否正常翻轉(zhuǎn)再看狀態(tài)機(jī)是否進(jìn)入預(yù)期狀態(tài)最后看輸出信號是否符合預(yù)期。AI生成的RTL有時候會忘記復(fù)位狀態(tài)機(jī)的狀態(tài)寄存器導(dǎo)致仿真時狀態(tài)機(jī)停在未知狀態(tài)。這個在Lint里不一定能抓出來但仿真波形一看就知道。5.2 AXI突發(fā)傳輸數(shù)據(jù)錯位怎么定位AXI突發(fā)傳輸?shù)臄?shù)據(jù)錯位通常是地址對齊或數(shù)據(jù)計數(shù)的問題。我遇到過AI生成的RTL里突發(fā)長度計數(shù)器在WLAST時沒有正確清零導(dǎo)致下一筆傳輸?shù)臄?shù)據(jù)錯位。排查方法是在Testbench里發(fā)一筆4拍的寫突發(fā)看波形里WSTRB和WDATA的對應(yīng)關(guān)系。如果第一拍數(shù)據(jù)對了第二拍開始錯那就是計數(shù)器的問題。讓AI重新生成時在Spec里明確寫“突發(fā)長度計數(shù)器在WLAST和WVALID同時為高且WREADY為高時清零”。5.3 仲裁器優(yōu)先級不生效的排查仲裁器優(yōu)先級不生效通常是優(yōu)先級編碼邏輯的問題。我遇到過AI生成的仲裁器里優(yōu)先級掩碼沒有正確更新導(dǎo)致高優(yōu)先級設(shè)備釋放總線后低優(yōu)先級設(shè)備仍然拿不到授權(quán)。排查方法是在Testbench里讓兩個設(shè)備同時請求看授權(quán)信號給誰。如果總是給同一個設(shè)備那就是輪詢邏輯沒生效。讓AI重新生成時在Spec里用表格形式寫出狀態(tài)轉(zhuǎn)移明確每個狀態(tài)下哪個設(shè)備獲得授權(quán)。5.4 常見問題速查表問題現(xiàn)象可能原因排查方法修正方式仿真時狀態(tài)機(jī)停在未知狀態(tài)狀態(tài)寄存器未復(fù)位看波形里狀態(tài)信號在Spec里明確復(fù)位值A(chǔ)XI寫數(shù)據(jù)錯位突發(fā)計數(shù)器未清零看WLAST和WVALID波形在Spec里寫明清零條件仲裁器優(yōu)先級不生效優(yōu)先級掩碼未更新看授權(quán)信號波形用表格描述狀態(tài)轉(zhuǎn)移寄存器讀寫地址錯位地址譯碼位寬錯誤看地址譯碼邏輯明確地址位[31:2]用于譯碼綜合后關(guān)鍵路徑過長冗余邏輯未優(yōu)化看綜合時序報告讓AI重新生成并優(yōu)化6. 我在這套流程里踩過的坑和總結(jié)的經(jīng)驗(yàn)第一個坑是過度依賴AI。我試過讓AI一次性生成整個IP的RTL結(jié)果生成了兩千多行代碼Lint報了三十多個warning仿真跑了三天沒跑通。后來改成模塊化生成每個模塊單獨(dú)驗(yàn)證效率反而高。第二個坑是Spec結(jié)構(gòu)化做得不夠細(xì)。我一開始只寫了寄存器地址和位寬沒寫復(fù)位值和讀寫屬性AI生成的寄存器文件里有一半的寄存器沒有復(fù)位值仿真時全是X。后來把復(fù)位值和讀寫屬性補(bǔ)上問題就解決了。第三個坑是忽略了跨時鐘域處理。我的IP里有一個異步FIFOAI生成的RTL里沒有做同步處理仿真時數(shù)據(jù)丟失。后來在Spec里明確寫了“跨時鐘域信號需要兩級同步器”AI才生成正確的同步邏輯。第四個坑是Testbench的覆蓋率不夠。AI生成的Testbench只覆蓋了正常讀寫場景沒有覆蓋錯誤注入和邊界條件。后來我讓AI生成Testbench時加上“隨機(jī)注入錯誤響應(yīng)”和“邊界地址訪問”的要求覆蓋率才上去。這套流程跑下來我的體會是AI能幫你省掉重復(fù)勞動但不能幫你做架構(gòu)決策。Spec結(jié)構(gòu)化、模塊劃分、時序約束這些關(guān)鍵決策還是得人來定。AI的價值在于你定好框架后它能快速填充細(xì)節(jié)讓你把精力集中在真正需要思考的地方。我現(xiàn)在做一個中等規(guī)模的AXI IP從Spec到可綜合RTL大概兩周左右其中AI生成占三天人工修正和驗(yàn)證占一周剩下四天是綜合優(yōu)化和文檔。比傳統(tǒng)流程快了一倍多但前提是Spec結(jié)構(gòu)化做得足夠好。如果你也想試這套流程我的建議是先從一個小模塊開始比如一個帶AXI-Lite接口的寄存器組跑通整個流程后再擴(kuò)展到復(fù)雜模塊。別一上來就搞大IP容易翻車。