AI辅助RTL设计实战:用WDT验证芯片设计流程的得与失
发布时间:2026/10/7 1:06:39 锦皓数字建站

1. 为什么我决定拿WDT开刀一个太小的IP反而最适合验证AI设计流程先交代一下背景。我在芯片设计这行干了十多年主要做SoC集成和验证。这两年AI辅助编程的风刮得很大GitHub Copilot、ChatGPT这些工具在软件圈已经卷出花了但硬件描述语言这边真正敢拿AI来写RTL的人其实不多。原因很简单RTL代码的正确性不是靠编译通过就能保证的时序、复位、跨时钟域、低功耗这些玩意儿AI根本看不见。但那阵子我正好接到一个任务——评估AI辅助设计在IP开发中的可行性。与其去拿一个复杂的DDR控制器或者PCIe核做实验我反而挑了一个看起来最不起眼的模块看门狗WDTWatchdog Timer。为什么选它因为WDT麻雀虽小五脏俱全有寄存器接口、有计数器逻辑、有中断和复位生成、有低功耗处理该有的基础结构全都有但代码量又控制在几百行的规模。这个尺度非常适合做AI设计流程的试金石——如果AI连WDT都搞不利索那复杂的IP想都别想如果AI能把WDT做好那这套方法论就可以往更大的IP上延伸。另一个原因是WDT这个模块虽然简单但坑一点都不少。超时时间怎么算、窗口模式下窗口怎么配、计数器的时钟分频怎么处理、复位信号要不要过滤毛刺、停机调试模式下WDT要不要暂停——全是细节。我见过不止一次因为WDT配置错误导致芯片一上电就疯狂复位的低级事故。所以这个小IP恰恰是最能暴露AI设计短板、也最能检验设计方法论的东西。这篇文章我就把整个流程完整复盘一遍从和AI对话拆需求到让它生成RTL和验证环境再到我发现它埋下的那些看起来很对但实际上有问题的坑以及最终的收敛策略。如果你也在考虑用AI辅助做IP开发或者你单纯好奇AI写出来的硬件代码到底能不能用这篇应该能给你提供一个相当真实的参考。2. 设计输入与AI辅助拆解把自然语言需求变成可执行的规格书2.1 我到底给AI喂了什么样的需求文档很多人用AI写代码的第一反应是甩一句给我写个看门狗模块然后坐等代码。这个用法放在软件上可能偶尔能跑通放在RTL上基本是作死。硬件设计的核心是规格SpecificationAI不是神仙你给它的输入质量直接决定输出质量。我这次的做法是先把一份简化版但完整的WDT需求文档整理出来要点如下功能定义系统看门狗防止固件跑飞。固件需周期性喂狗写特定序列超时未喂则产生中断或系统复位。接口定义AMBA APB slave接口因为它是低速外设32-bit数据总线支持字节/半字/字访问实际上一般只支持字访问但我在需求里明确了。寄存器定义WDT_CR控制寄存器、WDT_TORR超时周期寄存器、WDT_CCVR当前计数值、WDT_CRR喂狗寄存器、WDT_STAT中断状态这五个寄存器是经典DesignWare WDT的布局。计数器要求32位递减计数器时钟源为PCLKAPB时钟支持可选的分频1/16/256/4096由控制寄存器里的PSC字段决定。超时模式仅中断模式、仅复位模式、中断复位模式三种可选。窗口模式支持喂狗操作必须在窗口打开期间进行过早或过晚都算超时。复位行为模块支持两种复位——系统上电复位nRST和WDT自身产生的复位输出WDOGRES两者对寄存器复位值的影响不同。低功耗当系统进入低功耗状态且APB时钟停止时WDT应停止计数实际上真正的WDT一般有独立的oscillator时钟但为了简化实验我明确要求不引入独立时钟域。我把这份需求整理成大概一页纸的Markdown文档然后粘贴给AI要求它先不要写代码而是先复述需求、指出潜在的歧义点、提出设计问题。这一步非常关键相当于让AI当了一次需求评审员。2.2 让AI做需求评审它确实问出了几个好问题AI的回馈让我有点意外它问了好几个有水平的问题窗口模式下如果固件在窗口关闭期间写喂狗寄存器是直接触发超时事件还是仅仅记录一次违规然后等待真正的超时控制寄存器的INT_EN和RES_EN位是否可以动态修改如果看门狗已经在运行修改这两个位是否立即生效还是需要先关狗喂狗序列是写入特定的固定值比如0x76还是需要先写特定值到特定寄存器再写另一个特定值DesignWare的风格是后者——先写0x76到CRR再写0x76到CRR实际上是同一个寄存器的固定值但时序上有要求。超时周期寄存器是直接表示计数值还是表示分频系数0表示最短超时还是最长超时这些问题如果让我自己写需求文档十有八九会忽略掉其中一两个但它们在RTL实现阶段全是致命细节。AI能做到这一点说明它在海量开源代码和芯片设计文档上确实学到了东西——至少看过猪跑。我在它的提问基础上修改了需求文档把模糊地带全部用确定性描述替换。这个AI做评审、人来拍板的循环大概持续了三轮最终形成了一份干净、无歧义的设计规格。我的体会是用AI做硬件设计最大的价值其实不在写代码那一环而在需求拆解和评审这一环。AI不会累不会嫌问题弱智而且它能一口气列出几十个你可能没想到的边界情况。人力要做的事情是判断哪些问题真正影响设计然后做决策。这一步走扎实了后面写RTL反而顺风顺水。2.3 为什么我选择APB接口而不是AXI或自定义接口说实话这个选择我在一开始就定死了。AI在设计接口时如果没人引导它大概率会给你写一个看起来很好用的自定义接口——每个信号都起个明白名字读起来很爽但接进SoC的时候就是一场灾难因为总线桥接逻辑、地址译码、寄存器访问全都得重新适配。选择APB的理由非常简单第一WDT是现代SoC里公认的低速外设挂在APB总线上是标准做法ARM系统里叫PPBPrivate Peripheral Bus第二APB协议简单到几乎没有学习成本——只有PSEL、PENABLE、PWRITE、PADDR、PWDATA、PRDATA这几个信号状态机就两个状态第三AI训练数据里APB Slave的代码量巨大它对这个协议的理解深度远高于其他总线。事实证明这个选择是明智的。AI生成的APB slave接口部分一次就过了仿真几乎没有协议违例。如果你让AI去写AXI接口的WDT那大概率会撞出一堆并发传输、outstanding事务、写响应通道的问题——那个复杂度完全超出了WDT本身需要的量级。3. 用AI生成RTL主代码从首个版本到功能收敛的三轮迭代3.1 第一轮生成结构正确但充满优雅的陷阱需求定稿后我让AI生成完整的Verilog RTL代码。这里有个细节我指定了语言风格——同步时序风格、非阻塞赋值、寄存器输出全部打拍、参数化设计。AI第一版代码输出得相当快模块结构一眼看上去很规整APB接口逻辑、时钟分频、递减计数器、窗口比较器、中断/复位生成五个子模块划分得清清楚楚。但等我开始做代码评审时问题就浮出来了。它给超时周期寄存器定义了一个非标准的行为当TORR0时它把超时时间解释为立即超时——也就是计数器一启动就触发中断。这个行为从逻辑上讲没错但和DesignWare WDT的规格不符。DesignWare里TORR0意味着最短超时周期2^16个时钟周期而不是0周期。如果固件工程师按照DesignWare的习惯去配置这颗看门狗在TORR0的时候系统会直接炸掉。AI自作聪明地选择了一种不符合工业标准的实现方式而且没有在交付时主动说明——这是我认为最危险的一点。还有一个问题它的窗口模式实现里窗口上限WINDOW寄存器和超时周期的关系处理错了。它把窗口实现为必须在计数器值大于WINDOW时喂狗这个逻辑方向反了——窗口应该是必须在计数器值小于WINDOW时喂狗。Windows模式的定义是超时周期代表了最晚喂狗时间窗口值代表了最早喂狗时间固件只能在窗口值到超时周期这个区间内喂狗。AI理解反了。这两个问题都暴露了同一个深层缺陷AI能够记住窗口模式这个术语但无法理解这个术语背后的时序意图。如果不是有个懂行的人在review这两处错误会直接带进流片后果是灾难性的。3.2 第二轮生成我改变了提问策略——让它先画时序图再写代码第一轮review下来我发现了一个规律直接给AI一个完整需求让它一口气写代码它写得快但容易在语义理解层面出错。于是第二轮我换了一个策略不再让它直接写RTL而是要求它先用文字ASCII时序图描述每一个操作场景的详细时序包括固件写CR寄存器使能看门狗的时序固件写TORR修改超时周期的时序注意修改后是立即生效还是等待当前周期结束喂狗成功的时序窗口内写入0x76后的计数器重置行为喂狗过早/过晚的时序计数器的表现和中断拉起的时机超时中断产生到复位信号输出的延迟周期数我要求nRST在中断拉起后至少16个PCLK周期后再拉低给固件一个抢救窗口这次AI输出的时序图整体质量比第一轮高了一个档次。有意思的是在画时序图的过程中它自己发现了之前窗口逻辑的错误——因为时序图上喂狗窗口和超时周期的先后关系一旦画出来直觉上就知道反了。它在第二轮生成的代码里自动修正了这个问题。但新问题又出现了这次它在计数器重载逻辑上出了错。它把喂狗成功后计数器从TORR配置的预设值重新开始递减实现成了喂狗后计数器清零然后从0向上计数。这又是一个语义理解的偏差。原因是时序图能表达事件发生的先后次序但表达不了事件发生时内部状态的具体数值。计数方向这种细节时序图是画不出来的。3.3 第三轮收敛用可综合子集约束和代码冻结两轮之后我意识到一个事实AI生成RTL的过程有点像和一个很聪明但偶尔犯糊涂的实习生合作。你不能指望它一次到位但它的迭代速度极快你给出精确的指正后它能在几秒内给出修正版。三轮迭代下来核心RTL已经基本收敛——前提是每一轮我都要做完整的代码评审。第三轮我除了让它修正计数方向的问题还额外给了一个约束禁止使用initial语句初始化寄存器复位必须由nRST信号驱动禁止在组合逻辑块里使用阻塞赋值对时序逻辑信号赋值禁止使用function生成寄存器逻辑所有内部FIFO或状态寄存器必须可复位。这些约束的目的只有一个确保AI生成代码的可综合性避免它在细节上放飞自我。AI很听话第三轮的输出已经达到了可以直接进仿真环境的水平。三轮下来最终的RTL主代码大约450行。说实话单论代码质量它已经超过了不少初入职工程师的水平——缩进统一、命名规范、注释清晰每个always块都标注了用途。但如果你要问AI写的代码和资深工程师写的有什么区别区别在于资深工程师在代码里已经隐含了对后端物理实现的考量比如fanout控制、时钟门控的位置而AI完全没有这个概念。这一块只能靠人来补。4. 验证环节才是真正的照妖镜AI自嗨式测试与UVM仿真的正面碰撞4.1 让AI写testbench它给了我一堆人畜无害的测试用例RTL写完下一步是验证。这个环节我一开始就预料到会有问题但没想到问题这么典型。我让AI为其RTL生成一份SystemVerilog testbench要求至少覆盖寄存器读写、正常喂狗、超时中断、超时复位、窗口模式违规、低功耗暂停六个场景。AI生成的testbench代码结构很标准UVM环境、agent、sequence、scoreboard一应俱全编译直接通过。但等我跑完仿真一看覆盖率报告好家伙——寄存器读写场景覆盖了APB接口的100%协议但功能覆盖率几乎是0。具体问题出在哪里AI的寄存器读写测试就是对着每个寄存器做一遍写0xAAAA、写0x5555、读回比对。这个测试能确认APB接口工作正常但完全不关心这些寄存器位的功能语义——比如控制寄存器的INT_EN位写1之后WDT的interrupt输出信号是否真的被使能了它的测试里根本没有检查。换句话说AI的测试验证了总线能通但没验证IP能干活。还有更典型的它的窗口模式违规测试确实在窗口外写了一发喂狗命令但它在同一时刻也把控制寄存器的RES_EN位清零了——美其名曰隔离复位影响。这个操作直接导致违规事件无法产生任何实际的系统级影响测试虽然报了预期错误但那个错误根本不是窗口违规触发的而是它自己关掉了复位使能。这种为了测试通过而测试的做法在AI生成的验证代码里极其常见它在软件单元测试领域可能勉强成立毕竟mock和隔离是常态但在硬件验证里就是自欺欺人。4.2 手工补验的三类关键场景最终能让我拍板签收RTL的是我手工补的几组测试每一组都专门针对AI第一版实现暴露过的语义性问题。第一组是TORR边界测试分别配置TORR为0、1、最大值验证超时周期是否精确对应2^(16TORR)个PCLK周期。这个测试直接检验了最开始的TORR0含义争议。第二组是窗口竞争测试在窗口开启的最后一拍喂狗、窗口关闭后的第一拍喂狗、以及喂狗操作和超时事件在同一拍发生的竞争场景。前两种是功能验证第三种是对计数器重载和超时比较逻辑的时序验证——喂狗信号和超时信号同时置位时谁优先DesignWare的行为是喂狗优先计数重载不产生超时事件。AI的RTL在这个点上第一版是反的我是靠这组测试抓出来的。第三组是复位时序测试验证WDOGRES输出信号从拉低到释放的时长以及nRST输入复位和内部计数器的同步释放关系。AI把内部复位释放设计成了异步释放这在复位控制器的检查清单里属于硬伤——不亚于软件里的空指针解引用。这三组测试跑完RTL又修了两轮。所以我个人的结论非常明确AI生成的RTL如果你决定用验证投入一点都不能省甚至要比人工写的代码更狠。因为人工写的代码你至少知道作者的思路就是你自己AI写的代码是一个混合体——整体看起来合理但每个局部都有可能隐藏着看似合理实则错误的解释。4.3 覆盖率驱动的收敛策略AI负责铺量人负责定向到这一步我形成了一个方法论之后做更大IP的实验也一直沿用让AI负责生成覆盖面广的基础测试用例人类负责设计针对性的语义级测试用例。前者的价值是铺底——把APB协议访问、寄存器读写通路、基本中断路径这些体力活覆盖掉后者的价值是攻坚——专门打AI最容易犯错的语义理解死角。这两种测试混合跑下来最终行覆盖率91%、分支覆盖率88%、功能覆盖率重点项全部达标。其中AI生成的用例贡献了大约60%的行覆盖率但它一个功能覆盖率点都没拉满——全是我手工补的。这个数据相当能说明问题。5. 形式化验证与低功耗检查AI完全失语的地方5.1 断言检查让AI写SVA它连时钟采样的边沿都没搞对RTL功能仿真通过后我按正常流程上了形式化验证。这一步我本来也试试AI水有多深要求它给WDT的关键路径写SVASystemVerilog Assertion断言。结果非常一致AI写出来的断言语法全对没有编译错误但语义上惨不忍睹。举一个例子它想断言写使能WDT的控制寄存器后WDTEN信号至少保持2个时钟周期不会被自动清0结果它的SVA写成了在PCLK的下降沿采样信号——但整个模块的设计是上升沿采样下降沿采到的值永远是上一个半周期之前的旧值。这种断言没有任何仿真场景下会真正违例因为它的采样时机就是错的。类似的问题还有断言复位释放后寄存器值必须在3个周期内稳定但实际设计里复位释放的信号是异步的跟PCLK没有任何相位关系这个断言在随机仿真里一定报错而且报错的原因是断言本身写错了不是RTL有bug。形式化验证这块AI目前给我的感觉是它知道SVA长什么样但完全不懂SVA和设计的时序关系。它能把语法树搭得漂漂亮亮却没有能力把设计意图量化成时序属性。这个判断可能在未来一两年内会变但至少在我做这个项目的当下形式化验证的断言编写还是100%依赖人来完成。5.2 低功耗检查CPF/UPF文件只能手写AI帮不上忙另一个AI完全帮不上忙的环节是低功耗设计。WDT在SoC里通常会被放在一个always-on电源域或者至少需要明确它和CPU电源域的关系——当CPU域断电时WDT的APB接口寄存器不能被访问但计数器还得继续跑这就需要在UPF文件里定义隔离单元和电平转换器。我试着让AI生成一份CPF文件来描述WDT的power intent它的回复是抱歉我无法为您提供完整的CPF文件因为这需要参考您所用工艺库的power management cell列表。这个回答其实在我预料之中——UPF/CPF的写法极度依赖具体工艺库、功耗管理单元型号和SoC级电源拓扑这些数据根本不存在于AI的训练集里它给生成的任何内容都是胡编。这个环节对AI能力的结论也很清晰它能处理的是逻辑设计空间内的问题一旦进入物理实现空间或系统集成空间它的知识就断档了。这不是prompt工程能弥补的是训练数据和领域知识的根本边界。6. 集成验证中的意外收获AI生成的代码在真实SoC环境里暴露了什么6.1 从IP级验证通过到SoC级仿真翻车只差一个复位顺序IP测试台里跑得干干净净的RTL拿到SoC系统级仿真环境里第一轮就跑挂了。现象非常经典系统启动过程中CPU还没有来得及把WDT的喂狗任务注册进调度器WDT已经因为超时把整个系统复位了——无限重启循环。单看WDT的IP级行为这完全符合规格上电默认使能看门狗且超时周期配置为最短档位——这个寄存器复位值我是参考DesignWare的默认配置写的所以IP测试台里它从一开始就在跑。但IP测试台的CPU是一个假的BFM总线功能模型它一上电就立即以最快速度配置WDT所以IP自己测起来没有任何问题。到了SoC里真实的CPU从复位向量取指、初始化栈指针、搬运代码段到RAM、设置时钟、最后才轮到外设初始化——这个过程消耗的时钟周期数早就超过了WDT最短超时档位。问题本质不是WDT的RTL有bug而是WDT的复位默认值在SoC场景下不合理上电默认使能最短超时这个组合在纯IP测试环境里是合规行为但在系统里是自杀行为。AI在生成RTL时完全意识不到IP外面还有一个世界。它所有的设计决策都是基于我给它的一页纸需求文档而那份文档恰好没有规定上电默认状态的合理性问题。修复方案也不复杂把WDT控制寄存器的复位值改为默认关闭需要固件显式打开并配置超时周期或者在SoC复位控制器里加一条上电后屏蔽WDT复位输出N个时钟周期的逻辑。我选择了前者但改动虽然小却牵引出一个更普遍的问题——AI设计IP的边界感和上下文感知能力非常薄弱它不会主动问我这个模块放在系统里会不会干扰其他模块除非需求文档里明确写了。6.2 时钟分频配置AI不会考虑复用场景另一个集成阶段才暴露的问题是时钟分频器的实现。WDT的分频系数我配置为支持1/16/256/4096倍分频AI在RTL里用了一组组合逻辑MUX从32位计数器的对应比特位直接引出分频后的tick信号——比特位0对应1分频比特位4对应16分频以此类推。这个实现非常优雅代码量也少。问题在于APB总线上WDT的PCLK在SoC里常常不是固定频率而是由时钟控制器动态切换的。频率切换瞬间分频MUX的输出可能会出现毛刺这个毛刺如果刚好打在计数器的使能端就会导致计数器异常跳变。在IP测试环境里PCLK恒定为50MHz毛刺根本没机会出现。在SoC环境里时钟切换脚本一跑起来看门狗的计数值就开始随机散步。这个问题最后是靠给分频输出加两级同步打拍边沿检测解决的属于非常经典的时钟域边界的毛刺防护手段。但AI在整个生成过程中完全没有这方面的意识它默认时钟是干净的这个默认在芯片设计里是最危险的假设之一。我后来总结了一句话AI生成RTL的时候它假设了世界是理想的——时钟干净、复位同步、功耗可控、信号无毛刺。而一个合格的硬件工程师第一课学到的就是世界是不理想的。这个认知差距决定了AI生成的RTL在小规模、理想约束下的IP里可能够用但扔进真实SoC就是另一回事。7. AI设计WDT的最终交付物清单与流程复盘7.1 最终交付了什么整个项目从需求拆解到SoC集成验证通过实际耗时三周当然不是每天全职做穿插在其他任务里。最终交付物包括可综合的Verilog RTL源码含参数化配置支持分频系数和超时周期档位可配SystemVerilog/UVM验证环境AI生成基础框架人工补定向用例覆盖关键路径的SVA断言人工编写集成指南文档含寄存器描述、编程模型、低功耗注意事项综合约束脚本SDC人工编写AI生成的约束脚本没法用——它会把false path和multicycle path设置得乱七八糟UPF功耗意图文件人工编写有意思的是最终交付物里AI直接产出的部分只有RTL和testbench的框架正经交付文档、断言、约束、功耗意图全部是人力完成。AI在这个项目里相当于一个效率放大器而不是替代者。7.2 流程复盘五个关键节点的决策记录我做了个简表记录每个决策节点的选择理由方便以后做更大IP时复用流程节点人做AI做理由需求拆解定稿、拍板歧义列出问题清单、模拟边界场景AI问题清单的价值在于全面人的价值在于正确RTL编码架构决策、代码评审逐模块生成、按review意见修正AI速度极快但语义理解需要人把关Testbench撰写定向约束用例铺底生成基础访问用例AI用例多而浅人补少而深断言/形式化完全人工不可用AI不掌握时序意图的量化表达后端/功耗完全人工不可用依赖工艺库和物理上下文AI训练集缺失这个表格也解答了一个很多人关心的问题AI写RTL到底行不行我的答案是——写行设计不行。这两个词之间的差距就是硬件工程师未来几年真正的护城河。7.3 一点实在的建议如果你看完这篇也想试试用AI设计IP我有几条建议都是踩过坑换来的第一别让AI直接写代码先让它写时序图和场景描述。这个环节能逼着AI和你自己把模糊的语义想清楚比直接写RTL省三轮迭代。第二保留每一轮的对话记录。AI在第三轮修正的问题到第五轮可能会复发——它没有长期记忆你需要在prompt里持续强调已确认的约束条件。第三不要跳过我上面说的那组TORR边界、窗口竞争、复位时序测试这组测试哪怕你完全不用AI也应该作为WDT类IP的回归用例沉淀下来。最后这个项目做完后我最大的体会是AI在硬件设计里真正创造价值的环节不是替代而是加速它加速的是从模糊想法到结构化表达的转化过程。这个过程以前要靠一位工程师花半天时间画时序图、列边界条件现在AI几分钟就能给你一版初稿——虽然不能直接用但比从白纸开始快太多了。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。