본문으로 건너뛰기Skip to content 1:1 문의 — [email protected]로 이메일 작성 Contact us — email [email protected]

用 AI 代理製作 RTL 的實戰配置:AGENTS.md、spec、tasks、testbench、驗證迴圈如何分工

公開用 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 的封閉迴圈,才能用在實務上。
man in black jacket and white pants wearing yellow knit cap sitting on black metal fence
Photo by Carl Barcelo on Unsplash

為什麼一句提示詞不夠

生成式 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 中逐行留下理由

延伸閱讀

相關文章

📩 今天錯過的分析,明天早上寄到您的信箱

每天10:30(KST)Daily Silicon與財報·機構報告核心解讀搶先送達。訂閱後可選擇韓語/英語/日語新聞通訊,中文深度分析每日在網站更新。

免費訂閱 →

免費 · 無垃圾郵件 · 隨時退訂

Discussion

VLSI KOREA BRIEFING

반도체를 읽는 안목, 메일함으로.

엔지니어의 시각과 산업의 흐름을 함께. 무료로 구독하세요.

이미 구독 중인가요? 로그인