用 AI 代理製作 RTL 的實戰配置:AGENTS.md、spec、tasks、testbench、驗證迴圈如何分工
公開用 AI 代理製作 RTL 所需的實戰配置。整理了如何分離 AGENTS.md、spec、tasks、testbench 與驗證迴圈,代理才不會迷失方向。
🆓 免費文章 · 任何人都可以免費閱讀
核心結論 對 AI 代理丟一句「幫我做一個 FIFO」,demo 會出來,但可重用的 RTL 不會出來。差異不在模型效能,而在資料夾結構與文件分離。AGENTS.md 只放不變的大前提,spec 放要做什麼,tasks 放這次要做什麼,代理才不會動搖。沒有 testbench 與驗證迴圈的 RTL generation,只會大量生產文法正確的程式碼;要建立起包含 lint、simulation、synthesis 的封閉迴圈,才能用在實務上。
為什麼一句提示詞不夠
生成式 AI 能把 Verilog 與 SystemVerilog 寫得像模像樣,這已經被證實了。問題在於之後:參數名稱在每個檔案都不一樣,reset 極性混雜,ready/valid handshake 的假設每個模組都不同,而且代理不記得上次做的介面。程式碼越長,矛盾就累積得越多。當人審查並修正的成本超過親自撰寫的成本時,那個配置就失敗了。
解法不是把提示詞寫長。解法是分離角色。這和半導體設計中,需求文件、微架構文件、工作指示、驗證計畫分開存在的原因相同。代理也需要相同的分離。必須用檔案結構本身來強制:哪個檔案是真實來源、代理可以修改哪些檔案、不能碰哪些檔案、完成的定義是什麼。
本文的配置不依賴特定工具。無論是基於 CLI 的程式碼代理,還是附在 IDE 上的代理,原理都相同。資料夾與文件的分離在先,模型選擇在後。
實戰資料夾結構:最小單位這樣抓
下面的結構是以一個小型 IP 為基準的最小配置。規模變大時,以模組為單位重複相同模式。
my_ip/
├── AGENTS.md # 大前提:適用於所有工作,不常變更
├── README.md # 給人看的概要,建置/執行方法
├── spec/
│ ├── spec.md # 功能需求:要做什麼
│ ├── interface.md # 連接埠、協定、時序圖說明
│ └── params.md # 參數、預設值、允許範圍
├── tasks/
│ ├── TASK-001-fifo-core.md # 這次的工作單位:範圍、完成條件
│ └── TASK-002-cdc-check.md # 下一個工作單位
├── rtl/
│ ├── my_fifo.sv
│ └── my_ip_top.sv
├── tb/
│ ├── tb_my_fifo.sv # self-checking testbench
│ ├── drivers/ # bus driver, monitor
│ └── tests/ # 各情境的測試
├── constraints/
│ └── my_ip.sdc # synthesis / STA 用限制
├── scripts/
│ ├── run_lint.sh
│ ├── run_sim.sh # 編譯 + 模擬 + pass/fail 判定
│ └── run_synth.sh # Yosys 或商用工具的合成確認
├── build/ # 僅供生成物,禁止代理手動編輯
└── docs/
└── decisions.md # 設計決定與理由的紀錄
核心規則有三個。第一,spec/ 不由代理任意變更。需求變更只能透過人先修改 spec,再重新發布 tasks 的方式進行。第二,不用手修改 build/ 下的生成物。想改就改輸入檔案後重新執行。第三,所有執行只能透過 scripts/ 的入口。如果代理每次都發明不同的指令,可重現性就會消失。
要放進 AGENTS.md 的大前提:不要寫長,只寫違反就會壞掉的東西
AGENTS.md 近似於給代理的憲法。它不是長篇寫專案介紹的地方。只放無論做什麼工作都必須遵守、違反了產出就會出錯的規則。常改的話就不是憲法了。篇幅以一頁以內為適當。
應該放的項目如下。
- 語言與風格: SystemVerilog 的使用範圍、命名規則(時脈用
clk、reset 用rst_n,連極性都要明示)、always_ff與always_comb的使用原則、禁止產生 latch 等 coding 規則 - 介面大前提: handshake 訊號的意義、ready 是否可以在沒有 valid 時 assert、backpressure 條件下的資料保持規則
- 參數原則: 不任意創造
params.md中沒有的參數值、不更改預設值 - 修改範圍: 禁止修改
spec/、禁止刪除既有連接埠、修改工作範圍外的檔案時先報告 - 完成的定義: lint 通過、指定的全部測試通過、沒有合成錯誤,這三項都確認前,不寫「完成」
- 輸出格式: 在工作報告中包含變更檔案清單、執行的指令、測試結果
反過來,也有不該放進 AGENTS.md 的東西。這次模組的詳細功能、特定錯誤的修正方法、一次性時程等內容,應該送到 tasks。如果大前提與一次性指示混在一起,代理就無法判斷哪個更優先,舊的一次性指示會持續殘留,污染之後的工作。
分離 spec 與 tasks 的理由
分離 spec 與 tasks 的理由,是兩者的變更速度不同。spec 變得慢。FIFO 的深度政策、overflow 行為、同時 read/write 時的意義等,是設計的本質,不常改變。tasks 變得快。「今天只做 core,CDC 檢查延到下一個工作」這類範圍調整,是 tasks 的角色。
如果兩份文件合在一起,就會發生兩種事故。一是代理為了快速完成工作,偷偷放寬 spec 的要求;二是反過來,因為微小的任務變更而重寫整個 spec,導致既有決定遺失。分離後審查也變得容易。人只要嚴格審查 spec 變更,輕量審查 tasks 變更即可。
一個 task 檔案中,必須有四樣東西:一行目標、要碰的檔案範圍、明確的完成條件,以及不要做的事清單。特別是「不要做的事」很重要。代理有很強的填補空白的傾向,如果不指明範圍,就會一起帶來看似無關的重構與介面變更。在半導體設計中,未經授權的介面變更,是必須重跑整個驗證的事故。
📩 在持續關注這個主題嗎?
財報·報告·HBM供需的後續分析,每天10:30(KST)寄到您的信箱。 免費訂閱 →
docs/decisions.md 也幫助這種分離。留下為什麼選擇非同步 reset、為什麼用 gray code 指標等決定的理由,下一個代理 session 在試圖推翻那個決定時,就能看到依據並停下來。如果只有程式碼而沒有理由,代理每次都會從頭重演同一場爭論。
沒有 testbench 與驗證迴圈,為什麼會崩潰
RTL generation 中最危險的錯覺,是「能編譯就能運作」的想法。編譯只是文法檢查。即使 handshake 時序差了一個週期,即使 full 旗標在邊界條件下出錯,編譯也會通過。由寫程式碼的代理親自用眼睛讀自己寫的程式碼,並判斷「看起來對」的迴圈,不是驗證。共享相同假設的審查者,會共享相同的 blind spot。
因此 testbench 要與 RTL 分開,可能的話直接從 spec 推導。self-checking 結構是必需的。必須有輸入驅動器、計算預期輸出的 reference model 或 scoreboard,以及機械式判定 pass/fail 的 checker,代理才能不去詮釋結果,而是把它當作事實接受。測試結果不能是「大致能運作」,而要以數字呈現,像「12 個測試中通過 12 個,assertion 違規 0 件」。
驗證迴圈分階段封閉。第一階段用 lint 抓結構性錯誤,第二階段用 simulation 確認功能,第三階段用 synthesis 確認無法合成的語句、非預期的 latch 與時序結構。在開源流程中,可以用 Yosys 合成與 OpenROAD-flow-scripts (ORFS) 等 RTL-GDSII 流程,獲得面積與時序的第一手感覺;在商用環境中,則進入正式的 synthesis 與 STA。無論哪一種,核心都相同。給代理修改程式碼的權限與執行權限,但判斷權限只給測試結果。
| 構成要素 | 沒有時會發生的事 | 最低基準 |
|---|---|---|
| AGENTS.md | 每個 session 的風格、極性、假設都會變 | 大前提 1 頁,變更要少 |
| spec/ | 需求在每個工作中被偷偷放寬 | 功能、介面、參數分離 |
| tasks/ | 範圍外修改、未經授權的重構 | 目標、範圍、完成條件、禁止清單 |
| testbench | 只靠編譯就宣告完成 | self-checking、以數字呈現 pass/fail |
| 驗證迴圈 | 無法合成的程式碼、邊界條件錯誤累積 | lint → sim → synth 自動執行 |
| decisions.md | 每次重演相同的設計爭論 | 逐行記錄決定與理由 |
運作時必須遵守的實戰守則
第一,一次只給代理一個 task。同時交辦多個功能,失敗時無法分離原因。第二,失敗日誌不要摘要,直接給原文。代理擅長從日誌的精確行數中找到原因,在人摘要的說明中則較弱。第三,由人擁有 spec 與 testbench。RTL 正文可以提高代理的比重,但如果把需求與驗證基準也交給代理,整個系統就會流向自我確證。第四,定期確認在沒有代理的情況下,建置是否也能跑。如果腳本依賴特定 session 的暫存檔案,那個配置就不可重現。
最後,代理配置不是一次完成的。用一個小型 IP 封閉迴圈,把失敗模式反映到 AGENTS.md 與檢查清單中並逐步擴大,是最快的方法。從一開始就把龐大的 monorepo 全部交出去,不是驗證迴圈,而是賭博。
FAQ
Q1. AGENTS.md 與 README 有什麼不同? README 是給人類讀者的概要與執行方法,AGENTS.md 是代理在工作中必須遵守的規則。讀者不同,文件也要分開,代理才不會混淆規則與說明。
Q2. 不能用程式碼註解代替 spec 嗎? 不能。註解可能會被代理連同程式碼一起改掉,而且像介面與參數這種跨多個檔案的需求,無法在一處查看。spec 必須作為程式碼之外的獨立檔案存在。
Q3. testbench 也可以讓代理寫嗎? 草稿可以交給它,但驗證基準與邊界條件清單,必須由人從 spec 中決定。如果把 testbench 也交給寫 RTL 的同一個 session,測試很可能抓不到相同假設下的錯誤,風險會變大。
Q4. 只用開源工具也能構成驗證迴圈嗎? 作為第一輪迴圈,已經足夠。把 lint、模擬、Yosys 合成,以及透過 ORFS 在佈局後確認時序連接起來,就能在早期抓到大部分結構性錯誤。signoff 水準的判斷,需要另外的環境。
Q5. 代理一直改範圍外的檔案,該怎麼辦? 在 task 檔案中明示允許檔案清單與禁止清單,並在 AGENTS.md 中加入規則:修改範圍外檔案時要中斷並報告。如果仍然重複,就用腳本與權限在物理上限制。
行動清單
- ☐ 在專案根目錄建立 AGENTS.md,只把大前提整理成一頁
- ☐ 把 spec 分成功能、介面、參數三個檔案
- ☐ 把進行中的工作做成 tasks 檔案,寫下完成條件與禁止清單
- ☐ 分離 rtl、tb、scripts、build 資料夾,並禁止手動編輯生成物
- ☐ 讓 lint、simulation、synthesis 各自能用一個指令執行
- ☐ 把 testbench 改成 self-checking 結構,並以數字輸出結果
- ☐ 每當產生設計決定,就在 decisions.md 中逐行留下理由
延伸閱讀
- RTL,會被 AI 取代嗎 — 數字顯示的真正界線與職涯生存策略
- 用了 AI,為什麼工作沒有減少反而增加 — 生產力悖論的結構與半導體設計現場
- 問 ChatGPT 會答錯的 EDA 實務問題:VCS -mfcu、Vivado hold 診斷、工具版本混用的確認順序
相關文章
- 學士電路設計就業,只會 RTL coding 就夠嗎 — 架構理解決定錄取
- RTL 變免費:AI 如何改變標準 IP 的護城河與 RTL 工程師的未來
- PD 工程師需要懂 RTL 的理由
- RTL 優先,PD 在後:想對半導體求職者說的唯一建議
📩 今天錯過的分析,明天早上寄到您的信箱
每天10:30(KST)Daily Silicon與財報·機構報告核心解讀搶先送達。訂閱後可選擇韓語/英語/日語新聞通訊,中文深度分析每日在網站更新。
免費訂閱 →
免費 · 無垃圾郵件 · 隨時退訂