ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

门级仿真中SDA毛刺引发的I2C START误报:定位与三层根治方案

门级仿真中SDA毛刺引发的I2C START误报:定位与三层根治方案 上个月做I2C控制器的门级仿真Gate Simulation时跑到第三万条随机用例从机模型突然报了一个吓人的错START条件在非法时刻出现。第一反应是检查testbench怀疑是monitor抽风。但打开波形一看SDA上确实有一根下探的窄毛刺宽度小到几乎看不见肉眼一不留意就会滑过去。更麻烦的是这根毛刺只在Gate仿真里存在RTL仿真跑同样的激励一百次也复现不出来。当时我就意识到又来了门级仿真里典型的SDA delta毛刺问题。这类问题看似刁钻但背后往往是综合网表里一条真实的竞争路径不只是仿真环境的“灵异事件”。这篇就完整复盘一下我是怎么从“START误报”入手定位到SDA驱动路径上的OE竞争最终从验证环境、仿真配置、设计加固三个层面选定根治方案的。如果你也在做I2C、SPI这类协议IP的门级验证或者被仿真中的超窄毛刺折磨过这篇应该能帮你省不少时间。1. 为什么RTL仿真一片太平Gate仿真里SDA却冒出Delta毛刺1.1 SDF反标后组合逻辑的竞争路径才真正暴露要理解这个问题先要搞清楚Gate仿真和RTL仿真在时间模型上的本质差别。RTL仿真里寄存器、组合逻辑都是零延时或者默认单位延时的行为模型信号传播路径短同一个仿真时刻内大家几乎“同时”完成变化。综合网表则完全不同每个标准单元都有具体的库延时反标SDF之后每个组合单元、每段布线路径的delay都是实数。两个输入信号从一个状态翻到另一个状态时如果它们各自到达组合逻辑的延时不一样输出就会在一个短暂的时间窗口内出现既不是旧值、也不是新值的状态——这就是竞争冒险也就是毛刺的来源。这个道理做数字的人多少都懂但真正的问题是这类路径在RTL仿真里被零延时掩盖了。举个例子某个使能信号由状态位ack_slot和byte_active相或产生这两个信号来自不同的逻辑锥。RTL仿真里同一纳秒内同时翻转输出看起来完全正常到了门级仿真一条路径比另一条晚0.2ns到达输出就可能先跳一下再稳定。你盯着RTL代码怎么也想不明白这里怎么会有毛刺但网表里这个问题天然存在。1.2 delta cycle毛刺可以比一个仿真时间精度还窄“Delta毛刺”这个词很多新人第一次见到会困惑波形上明明能看到毛刺宽度到底怎么算在Verilog/SystemVerilog仿真中仿真器处理同一仿真时刻的多个事件依靠的是delta cycle也就是同一时刻内一轮一轮迭代。当某个信号的翻转在delta n-1被调度而它下一跳在delta n1才被调度这段时间里其他观察者看到的是一个中间值宏观时间并没有推进但逻辑上却形成了一个极窄的脉冲。Gate仿真里的毛刺通常带有实际物理延时宽度可以到几百ps甚至几ns但有些毛刺因为延时极小在波形上看起来就是一条竖线必须放大到最小分辨率才看得清。这里有一个很实在的排查经验别急着把毛刺归因于“仿真器抽风”。delta毛刺在门级仿真里往往是真实电路风险在时间域上的投影。RTL仿真看不到它不代表它不存在。同时timescale的影响也非常大。如果仿真精度是1ns几百ps的毛刺会被量化掉根本显示不出来如果精度是1ps毛刺就现形了。Gate仿真强烈建议把仿真精度统一到1ps级别同时确认SDF里的延时单位与仿真精度匹配否则毛刺宽度不可信对问题严重程度的判断也可能被带偏。2. 定位过程复盘怎么一步步咬住这根不到1ns的毛刺2.1 第一步确认是协议模型误报还是SDA上真的存在毛刺拿到复现用例后第一件事不是改代码而是排除“testbench误报”的可能性。我把波形放大到毛刺附近看到SDA有一个下降沿在SCL高电平期间出现随后立刻恢复高电平。为了确认这不是波形显示精度造成的错觉我在测试bench里对SDA的negedge事件加了打印always (negedge sda_io) begin $display(%t ps: SDA falling, SCL%b, $realtime, scl); end结果打出来时间点精确到ps而且SCL确实为高铁证如山。如果是协议模型自身的问题打印出的沿时间点往往在delta上抖动或者与SCL边沿对不上真正的毛刺则会有一个相对稳定的物理延时位置。这里有个容易踩的坑有的同事看到毛刺后第一反应是给monitor加一个“毛刺过滤”让测试继续跑下去。这样做测试确实能过但只是在掩盖现象。如果毛刺源于真实路径竞争芯片流片回来照样会在真实硬件上出现系统里其他I2C从设备也会收到一个错误的START。所以排查必须追到根因不能为了回归通过率而自欺欺人。2.2 第二步事件打印和二分隔离锁定OE信号路径I2C的SDA是双向IO空闲时靠外部上拉电阻维持高电平只有OE输出使能有效时内部驱动才会接管。所以SDA上出现向下毛刺要么是OE信号在错误瞬间有效要么是输出数据在错误瞬间变成了低电平。要快速二分可以在SDA下降沿前后把OE、输出数据、状态机状态全部打印出来always (negedge sda_io) begin #1; $display(%t ps: SDA falling, oe%b out%b state%h, $realtime, sda_oe_q, sda_out, state_q); end我当时的打印结果非常典型在毛刺出现的那一瞬间sda_oe先有一个极短的回落随后又恢复也就是说OE在瞬间撤销了驱动。但SDA本应靠上拉维持高电平为什么会出现低电平再往深处追原来OE撤销的同时输出数据信号tx_bit上也出现了一个反向毛刺。两个毛刺碰在一起SDA被内部驱动拉成了一个非常窄的低脉冲。要确认OE路径是必要条件可以用仿真器的force命令做单变量实验把OE强制为1毛刺消失把OE强制为0毛刺也消失。只有让OE按原路径自然跳变时毛刺才复现。这基本就印证了OE路径上的竞争冒险是毛刺的根源。另一个容易被忽略的检查点是SDF反标日志。VCS里可以打开sdfverboseQuesta里加-sdfreport检查有没有反标失败、超范围截断、单位换算异常。我之前遇到过SDF延时因为仿真精度不匹配被放大导致一个本来很窄的毛刺被拉成几个纳秒直接干扰了问题定位白折腾了三天。2.3 第三步回到RTL环境用注入延时反向验证定位到OE路径之后我并没有立刻去改设计而是在RTL环境里做了最后一步“实锤”验证人为在OE路径上注入等效延时复现毛刺。做法不复杂写一个简单的wrapper把OE信号截出来经过一个delay模型再送回驱动sda_io。在同样的激励下只要毛刺能复现就证明这个现象与“该路径存在额外延时”有直接因果关系。这一步看似多此一举但非常有用。因为在真正的门级仿真里影响时序的因素太多很难做到单变量归因。回到RTL做点注入可以迅速排除随机性、仿真器调度差异等干扰。验证通过后再去翻综合网表和STA报告发现这条路径的时序余量确实很差毛刺出现的原因就彻底闭环了。3. 根因还原双向IO的OE竞争如何被协议检成START3.1 OE组合信号“先撤后给”叠加输出数据的反向毛刺把定位结果还原一下就能完整解释这一根毛刺的产生过程。假设I2C控制器处于“发送ACK后释放总线”的阶段状态机在时钟上升沿从ACK状态迁出ack_slot信号在组合逻辑上随之变化同时下一个状态的byte_active开始建立。由于逻辑锥深度不同ack_slot的回落比byte_active的建立早了一些。这在门级仿真里非常常见本质就是两条并行路径的延时差。于是sda_oe ack_slot || byte_active在中间窗口变成0OE先撤销。而输出数据tx_bit恰好是0并且它的释放路径比OE晚一点点于是SDA在这段时间内被驱动为低。等byte_active稳定为1后OE恢复SDA重新被外部上拉拉高。整个过程不到1ns在SCL高电平区间形成了一根向下的毛刺。这里必须强调这不是测试环境造出来的假象而是设计在特定时序条件下真实可能发生的竞争冒险。门级仿真最大的价值恰恰在于把这些理论上的风险用波形呈现出来让你有机会在流片前看到它。3.2 START检测逻辑为什么一口咬定就是STARTI2C的START条件定义是SCL为高电平期间SDA从高到低跳变。多数monitor和从机模型直接通过SDA沿事件配合SCL电平来判断START。SDA毛刺的下降沿发生在SCL高电平期间自然满足条件。更糟糕的是毛刺之后还有一个上升沿恢复。如果监控逻辑继续用上升沿做STOP判定它会在极短时间后报一个STOP。于是波形上就会出现“START后马上STOP”的离奇序列。如果你只看到报错信息“START timing violation”会觉得很莫名其妙但把波形展开看一眼就能明白整条链路。有人可能会问协议checker为什么不做毛刺过滤这其实是一个设计边界问题。协议checker的职责是检查协议行为不是替代设计做信号完整性处理。如果一个信号在物理层的行为已经违反了协议假设checker应该把它报出来而不是自行滤掉。否则它到了真实系统里照样会被下游设备误认为START那才是真正的灾难。3.3 这个毛刺在真实芯片上到底会不会出现排查到这一步必须冷静下来判断毛刺在门级仿真里出现不代表芯片实测必然复现。真实芯片里的路径延时由工艺、电压、温度决定而门级仿真用的是某个工艺角下的库延时。同一根毛刺在不同PVT下宽度会变化极端情况下甚至消失。我的判断依据有三条第一毛刺对应的组合竞争路径是否真实存在于网表中第二STA报告里这条路径的时序余量是否处于临界状态第三毛刺是否会影响对外协议接口。I2C的SDA/SCL是对外接口哪怕毛刺概率不高一旦发生就会导致总线错误影响面是系统级的风险和收益完全不成比例。所以只要毛刺源于真实路径竞争且作用于外部接口就应当修复不能指望“实测碰不上”这样的侥幸心理。4. 别只想着过滤毛刺三层根治方案怎么落地4.1 验证环境侧把采样窗口移到安全区间而不是野蛮滤波先说验证环境侧。I2C总线协议里SDA的值只允许在SCL低电平期间变化START/STOP除外接收方应该采样SCL高电平中段的SDA电平。所以monitor里的正确做法不是对所有SDA变化一律忽略而是把采样点放在SCL高电平中点附近避开边沿附近的高风险区间。具体实现上可以在SV monitor里对SDA连续采样N次比如在一个SCL周期的一半内采样3到5次全部一致才更新内部状态。这样既滤除极窄毛刺又不会误伤正常数据。需要提醒的是滤波器的时间窗口不能大于半个SCL周期否则在高速I2C模式下可能把合法的快速变化当成毛刺滤掉。对于顶层协议checker里的START检测我后来统一做了一个开关当“毛刺滤波”使能时SDA沿事件被迟滞到稳定窗口后再上报不使能时维持最严格的协议检查。两个模式同时保留回归时跑严格模式让毛刺暴露长时间回归用过滤模式避免大量无意义中断比一刀切更灵活。4.2 仿真配置侧timescale、SDF反标质量与精度必须可控仿真侧有一个经常被忽略的坑timescale不统一。整个验证环境里有的模块是1ns/100ps有的是1ns/1ps仿真器在处理跨模块事件时会产生额外量化误差。对于SDA这种双向IO、带外部上拉的信号我建议仿真精度统一到1ps至少不能比SDF里的最小延时单位粗。否则毛刺宽度会被高估或低估直接影响风险等级的判断。每次跑GLS之前检查SDF反标报告也应该成为一种条件反射。VCS加sdfverboseQuesta加-sdfreport重点看反标失败、超范围截断、单位换算异常。如果SDF里延时是0.1ns而仿真精度是1ns毛刺会被直接吞掉你看到的“没有毛刺”其实是假象反过来如果精度远高于延时精度仿真器可能把事件拆成很多轮delta毛刺被无限放大看起来比实际情况严重得多。4.3 设计侧给OE信号寄存器化这是最省心的根治手段最后说设计侧的根治。既然毛刺来源于OE和输出数据的组合逻辑竞争最直接的办法就是把OE寄存器化输出。寄存器只在时钟沿后跳变触发它组合逻辑早在时钟沿之前已经稳定这样组合逻辑毛刺就被时钟沿“洗”掉了// 修复前 wire sda_oe_comb; assign sda_oe_comb ack_slot || byte_active; // 修复后 reg sda_oe_q; always (posedge clk or negedge rst_n) begin if (!rst_n) sda_oe_q 1b0; else sda_oe_q sda_oe_comb; end assign sda_io sda_oe_q ? sda_out : 1bz;为什么这个有效关键在于让OE的变化与系统时钟对齐而不是跟随组合逻辑的不稳定变化。代价是OE在时序上比原来晚了一拍但对于I2C这种慢速协议标准模式100kbps到快速模式1Mbps一拍系统时钟完全不影响协议窗口。如果系统时钟频率非常高、与SCL的分频比很小就需要额外确认这一拍延迟不会把OE变化的特征时刻推到SCL高电平区间里。如果业务上不能接受这一拍也可以采用“数据与OE同拍切换”方案把输出数据也寄存器化并约束OE翻转发生在SCL低电平区间。这个方案更精细但验证工作量更大。我的实际经验是对于通用I2C IPOE寄存器化是性价比最高的方案。综合约束方面针对SDA输出路径可以在SDC里对OE和输出数据之间的组合路径做分组加set_max_delay约束促使工具保持路径平衡。但这只能改善网表质量不能替代设计层面的寄存器化。还有一点要提醒不要在RTL里为了过仿真而加入毛刺过滤逻辑除非那是可综合、有明确设计意图的滤波电路否则就是给设计埋雷。5. 把这类问题沉淀成可复用的毛刺排查动作5.1 快速判定毛刺属于哪一类该由谁修门级仿真里的毛刺五花八门但可以粗分成三类设计真实风险、测试环境伪影、仿真配置问题。怎么快速区分我习惯用下面这个判断矩阵现象可能原因修复归属毛刺只出现在Gate仿真RTL无组合逻辑竞争路径设计/约束毛刺宽度小于仿真精度且位置漂移timescale/SDF配置问题仿真环境同一毛刺在多个随机种子上反复出现设计路径结构性问题设计毛刺出现在testbench虚拟模块内部环境建模问题验证环境毛刺只在某个外部接口双向IO上出现OE与输出数据竞争设计这张表不能覆盖所有情况但能帮团队第一时间把矛头指向正确方向减少无效讨论。5.2 我在GLS调试中常用的几板斧定位毛刺时我的固定动作基本是这几步先把波形毛刺放大到最小分辨率记录毛刺宽度、相对SCL边沿的位置对目标信号加事件打印用$realtime确认毛刺所在时刻$timeformat要设好否则打印精度看不出来检查SDF反标报告和全环境的timescale排除配置因素干扰用force命令对可疑组合逻辑节点做固定电平实验快速二分隔离在RTL环境里注入等效延时单变量复现坐实根因确认根因后再动手改设计或调整环境最后用原Gate仿真激励做全量回归验证。以前我习惯一上来就改代码后来吃过亏改完之后毛刺确实没了但那是被后续逻辑“吞掉”的真正的竞争路径还在换一个工艺角又冒出来了。所以现在强制自己按这个顺序走先定性再动手。5.3 一点个人体会做验证这些年我发现毛刺类问题最难的往往不是修而是“敢不敢认定它就是根因”。门级仿真里信息量巨大波形密密麻麻一根不到1ns的毛刺很容易被当作噪声忽略。但只要确认它是一条真实路径上的一小段竞争产物那么它对协议接口的威胁就值得百分百认真对待。I2C的START误触发只是一个表象背后的“输出使能竞争”才是真正值得留在团队checklist里的东西。希望这篇复盘能帮你在下次遇到同类问题时更快找到那根看不见的毛刺。
返回列表