ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

异步复位同步释放与复位树构建:数字IC复位设计完全指南

异步复位同步释放与复位树构建:数字IC复位设计完全指南 做数字IC设计这些年如果要我排一个最容易被低估的信号复位信号肯定排前三。刚入行时觉得复位就是复位端口拉低清零后来做到SoC级、低功耗多电源域、以及后端物理实现时才发现一个看似简单的异步复位背后藏着亚稳态、恢复时间、移除时间、复位树平衡、跨域隔离一整套问题。这篇文章从异步复位同步释放的经典电路讲起再聊到复位树如何构建最后分享一些实际项目里的翻车与排查经验。适合做数字前端、DFT、后端物理设计以及刚接触复位设计的同学参考。1. 复位设计到底在解决什么问题1.1 复位不只是“上电清零”很多人对复位的理解停留在“让寄存器恢复默认值”这个说法没错但不完整。芯片里的复位信号承担的任务远不止上电初始化它还要覆盖错误恢复、低功耗唤醒、DFT测试准备等场景不同场景对复位的要求完全不同。上电复位要求复位信号在电源稳定之后仍然保持足够长的时间等时钟和电源管理状态机准备好后再释放。错误恢复场景则要求复位信号能快速打断当前执行路径把芯片拉回一个确定的安全状态这类复位通常由看门狗、软件复位、外部按键触发。低功耗场景下某个电源域可能已经断电复位信号在下电和上电过程中必须被正确隔离和钳位否则会在电源域边界产生漏电甚至闩锁。DFT场景更特殊扫描链在装载测试向量之前所有触发器必须处于已知状态这时复位通常由测试通道单独控制而不是功能复位路径。这些场景对复位设计提出了不同要求既要能异步响应又要在释放时避免亚稳态既要覆盖所有时序逻辑又不能成为后端收敛的噩梦。所以真正做好复位不是写一个带异步复位的always语句就算完事而是要当成一个系统性的设计维度来对待。1.2 同步复位、异步复位、异步复位同步释放业界常用的复位策略主要有三种同步复位、异步复位、异步复位同步释放。先看差异才能理解为什么主流方案会选择异步复位同步释放。特性同步复位异步复位异步复位同步释放复位响应是否依赖时钟是复位信号必须满足建立时间才能在时钟沿生效否复位有效沿立即生效否复位有效沿立即生效释放沿由时钟同步无时钟时能否复位不能能复位拉低能生效但释放必须等时钟稳定对毛刺的敏感度毛刺会被时钟沿采样只要不落在建立保持窗口内风险可控非常敏感毛刺可能直接触发复位毛刺仍可能触发复位输入侧需要滤波时序分析复杂度类似普通数据路径需要恢复/移除时间检查释放时刻与时钟对齐主要检查恢复/移除时间寄存器面积最小不需要复位端特殊处理需要带异步复位端的寄存器需要带异步复位端寄存器另加同步器同步复位的优点是综合简单、适合纯同步设计但缺点也很明显复位响应必须等时钟沿若时钟还没稳定复位无法生效如果复位信号在数据路径上经过组合逻辑还可能在时钟沿附近出现亚稳态窗口。异步复位的优势是响应快、不依赖时钟缺点恰恰在释放阶段异步释放沿和时钟沿没有固定相位关系一旦释放点落在触发器恢复时间窗口内输出可能进入亚稳态。异步复位同步释放方案就是冲着这个矛盾去的复位信号在有效阶段像异步复位一样立刻生效但释放阶段通过两级同步器把释放沿“搬”到目标时钟域的一个时钟沿上从而同时拿到异步复位和同步复位的好处。这也是为什么几乎所有高性能SoC都会在复位管理单元里用这种结构。1.3 复位设计中的经典失效模式先列几个我在项目里真实遇到过的失效场景后面再展开讲原理和解决方式。第一种是异步复位释放沿离时钟沿太近导致同一时刻一部分触发器完成复位释放、另一部分没有释放芯片从复位状态出来后内部状态不一致功能立刻错乱。这类问题本质是恢复时间违例。第二种是复位毛刺导致的意外复位。比如外部按键复位信号没有做滤波或者芯片内部某个组合逻辑产生的复位控制信号存在毛刺一个很窄的负脉冲就可能让所有寄存器瞬间清零。异步复位端对这类毛刺几乎没有免疫力这也是外部复位信号必须经过专门复位芯片或去抖滤波的原因。第三种是复位树偏斜过大。全局复位信号从根节点到远端模块可能要走很长的线模块A离复位驱动端近已经释放出来开始跑软件了模块B离得远复位还没释放完两个模块之间如果有握手交互很容易出现协议错乱。这种问题在仿真里很难提前发现因为仿真环境默认复位是理想的全局信号。第四种是低功耗电源域隔离问题。某个电源域已经下电但复位信号仍然穿过该域或者复位信号在域边界没有做隔离处理导致漏电、信号冲突极端情况下还会触发闩锁。处理这类问题需要把复位树和UPF电源设计放到一起考虑。这些失效模式说明复位设计不是一个普通的信号连接问题它涉及时序收敛、跨域交互、低功耗策略和物理实现四个层面。2. 异步复位同步释放被反复提及的方案到底好在哪里2.1 为什么不能只用同步复位或异步复位先明确一个原则复位的本质是把电路置入确定状态所以最怕的是“不确定”。同步复位把复位信号当作数据信号处理在时钟沿采样后才生效好处是时序模型统一坏处是如果没有时钟复位永远不生效。这在芯片还没有稳定时钟的上电阶段是致命的所以纯同步复位方案很难用于上电复位。异步复位则把复位信号当作一个专门的异步控制端不依赖时钟只要复位有效寄存器立刻清零。这个特性让它在电源域刚上电、时钟还没稳定时也能强制复位。但异步复位释放时释放沿和时钟上升沿之间会产生竞争。如果释放沿落在触发器的恢复时间窗口附近触发器输出可能在整个时钟周期内处于亚稳态采样到哪个值完全不确定。更麻烦的是每个触发器的释放路径长度不同有些已经稳定有些还在亚稳态整个状态机的初始状态就乱了。所以单一方案都不完美。异步复位同步释放的本质是在保留异步复位优点的基础上把释放过程变成“有序事件”。释放沿不再是自由异步事件而是由目标时钟域里的同步器产生和时钟沿有明确相位关系从而可以被STA分析和验证。2.2 经典复位同步器电路结构复位同步器的结构并不复杂核心是两个串联触发器再配合一个固定为高电平的输入源。以低有效复位为例外部异步复位信号rst_n连接到两级的异步复位端。第一级触发器D端接逻辑1。第一级输出接到第二级D端。第二级输出就是同步后的内部复位信号低有效。复位拉低时两级触发器的Q都会被异步清零所以输出立即变低。复位释放时第一级触发器的D端虽然是高电平但输出不会立刻变高而是等到下一个时钟上升沿第二级也要再等一拍最终第二级输出在时钟上升沿之后才变高。这意味着内部复位的释放沿被同步到了时钟的上升沿附近距离竞争窗口足够远触发器能稳定采样到高电平。二级结构为什么必要如果只用一级复位释放时第一级触发器的D端和复位端之间仍然存在竞争输出有可能在一个时钟周期内处于亚稳态。两级串接后即使第一级出现亚稳态也有整整一个时钟周期去稳定第二级采样到确定值的概率极高把亚稳态传播到后续逻辑的风险降到了很低水平。示例代码如下这个模块我一般在项目里会放在复位管理单元称为rst_clk_domain_syncmodule reset_synchronizer ( input wire clk, input wire rst_n, output wire rstn_sync ); reg rst_n_r1; reg rst_n_r2; always (posedge clk or negedge rst_n) begin if (!rst_n) begin rst_n_r1 1b0; rst_n_r2 1b0; end else begin rst_n_r1 1b1; rst_n_r2 rst_n_r1; end end assign rstn_sync rst_n_r2; endmodule需要特别注意两级同步器的复位端接的是原始异步复位信号而不是同步后的内部复位。如果接内部复位等于自己复位自己同步就失效了。另外两个触发器必须放在同一个时钟域参考时钟就是目标时钟域时钟这样同步出来的复位释放沿才能与该时钟域内的寄存器时钟沿对齐。2.3 恢复时间与移除时间和setup/hold的类比异步复位同步释放虽然解决了大部分问题但时序约束仍然绕不开两个检查恢复时间recovery和移除时间removal。这两个概念和建立时间、保持时间非常像但针对的是异步复位端的时序。可以这么类比建立时间要求数据在时钟沿之前提前稳定恢复时间要求复位信号在时钟沿之前提前释放保持时间要求数据在时钟沿之后保持稳定移除时间要求复位有效沿在时钟沿之后至少保持一段时间。换句话说恢复时间是“释放沿不能离时钟沿太近”移除时间是“复位有效沿不能离时钟沿太近”。在STA里恢复时间检查类似建立时间检查需要看复位释放沿相对目标时钟上升沿的slack。如果释放沿比时钟沿晚得太多说明恢复时间不足触发器输出可能仍处于复位状态或亚稳态。移除时间检查则类似保持时间看复位有效沿相对时钟沿有没有保持足够的裕量避免复位刚刚生效的瞬间被时钟沿采到未定义状态。用异步复位同步释放的电路后释放沿是从时钟沿产生的所以本身的恢复时间检查比较容易满足。真正容易出问题的是同步器之前的原始异步复位信号这个信号可能从片外引脚进来也可能来自另一颗芯片相位完全未知。因此还是要对原始复位信号插入的路径做恢复/移除时间检查并且尽可能让原始复位信号经过专门复位管理单元做毛刺滤波后再进同步器。2.4 RTL实现和综合约束要点实际项目里复位同步器不能写完RTL就不管后续约束不做等于白做。第一两个触发器的D端有常量1综合工具很可能认为是无用逻辑做优化所以通常需要加dont_touch或keep属性确保两级结构被保留。第二要在SDC里把原始异步复位信号设置为异步路径同时对恢复、移除时间做检查。对于低有效复位约束上要特别留意复位拉低期间整个目标时钟域处于复位状态数据路径没有意义可以把复位有效期间的路径设成false path但复位释放沿必须在时钟沿之前满足恢复时间这个不能设false path。不要图省事把整个复位路径都设成false path那等于把问题掩盖到流片后才暴露。代码层面还有一个常见坑有人习惯在同步器输出后加很多反相器来驱动大扇出结果这些反相器的延迟不一样导致内部复位信号在不同路径上出现几千皮秒的偏斜。这种做法不是不可以但需要和后端一起做复位树平衡不是RTL阶段随便插几个buffer就能交差。3. 复位树构建从RTL到物理实现的完整链路3.1 什么是复位树和时钟树比有什么不同说到时钟树大多数芯片工程师都能理解CTS什么意思但提到复位树很多项目连专门的检查项都没有。复位树指的是从复位源比如复位同步器输出到所有受控触发器复位端之间的缓冲器网络。它和时钟树一样有延迟、偏斜和负载问题但在设计方法论上差别很大。时钟树是周期性信号CTS工具会自动做延迟匹配和时钟树综合它是后端标准流程的一部分。复位树是电平信号没有周期性工具不会为它做自动综合很多时候要靠手动规划、约束和检查。时钟树对偏斜要求极其严格几百ps的偏差都会导致建立保持违例而复位树的偏斜容忍度要高一些因为它只要保证所有触发器在一个安全窗口内完成释放即可这个窗口通常是几十ns甚至一个时钟周期。但容忍度高不代表不用管。复位树如果绕过一个大模块或者通过了一长串单元偏斜可能达到几个ns在某些高速接口和跨模块握手场景下依然会造成功能性错误。尤其复位释放本身已经经过同步器对齐到时钟沿如果后续复位树偏斜太大等于把这个对齐又破坏了。3.2 复位树的构建策略我见过比较健康的复位树都是分层设计。顶层复位管理单元接收外部复位芯片信号、看门狗、软复位请求、调试复位请求统一处理后输出多路复位域每个复位域对应一个或多个时钟域。每个时钟域的入口再放一个复位同步器同步器输出才真正驱动该时钟域内所有寄存器的复位端。具体到单域复位树会按几个原则来做。第一按功能模块划分不要把整个芯片所有寄存器接到一根直线上而是按CPU域、总线域、外设域、模拟控制域分开处理。每个子域可以有一个本地复位缓冲器既隔离负载又让每个区域的复位路径可控。第二功能复位和DFT复位要分开。扫描测试模式下复位信号来自测试通道参考时钟是测试时钟如果让功能复位树在DFT模式驱动扫描链测试模式极容易出问题。所以寄存器的复位端前通常有个MUX功能模式下选功能复位测试模式下选scan复位。第三高扇出时要复制同步器而不是复制buffer。当一个复位同步器要驱动上千个触发器单根信号的fanout太大后端会插很多级缓冲器偏斜难控制。更稳妥的做法是复制多份复位同步器每份驱动一个区域。但复制后多份同步器的输入仍然都是同一个原始异步复位信号这样它们的释放都会对齐到同一个时钟沿只是各自在域内的布线延迟不同整体偏斜仍然可控。第四复位树和电源域边界必须结合UPF设计来做。跨越电源域的复位信号要加level shifter下电域边界要加isolation cell把复位信号在下电期间钳位到有效电平避免下游寄存器看到浮空信号。3.3 复位树的验证与检查RTL阶段最常见的验证方式是在仿真环境里对复位释放沿做参数扫描比如人的复位释放时间相对时钟沿偏移0ps、100ps、1ns观察状态机是否能从复位状态正确恢复。很多问题就藏在这些边界case里如果只用理想复位源很难暴露。CDC验证工具需要显式识别复位同步器。工具会检查每个时钟域里是否存在带异步复位端的寄存器但复位信号没有经过同步器或者同步器结构不符合标准两级模式就会被报告为CDC违例。这类报告不能一关了之要逐个确认复位源是不是来自复位管理单元以及是否真的在每个时钟域内独立同步。后端阶段恢复/移除时间检查要覆盖整个复位树。复位同步器输出到所有寄存器复位端之间的路径要检查有没有出现恢复时间违例。有的EDA工具支持专门检查异步引脚时序可以跑出每一步的slack和分层的偏斜报告。拿到报告后重点看偏斜最大的路径是否存在跨模块长线。形式验证方面复位树插入后的RTL网表对比也是必做项。综合工具可能会把复位端的连接方式做优化反相器级别也会变动但功能性等价必须保证。如果在综合后的网表上复位信号被重新综合成组合逻辑很容易在后面的流程里埋雷。3.4 复位树与低功耗、时钟门控的配合低功耗和复位是一对容易互相打架的设计需求。很多模块在休眠时会把时钟关掉节省动态功耗。这时如果复位释放沿刚好到了而时钟还关着同步器不会采样到高电平复位释放实际上被无限期推迟。等时钟恢复时复位才突然释放这就不叫“同步释放”了更像一个不确定的异步事件。所以设计上要在电源管理和复位管理之间建立顺序约束。典型流程是电源域上电 → POR复位产生并保持 → 时钟恢复且稳定 → 复位释放 → 模块开始运行。这个顺序最好由专门的复位状态机控制而不是靠几个寄存器随手写。跨电源域时复位信号本身也要经过隔离方案。如果一个模块电源已经断开那么复位信号的有效电平必须由边界isolation单元钳位否则断开域内部的复位线是悬空状态漏电路径会非常明显。等目标域重新上电后isolation单元先让复位线恢复有效再由复位管理状态机控制释放。这个过程在UPF里要写清楚和电源开关的控制顺序保持一致。4. 实战中的问题与排查技巧4.1 复位释放时序违例的表现与定位曾经遇到一个SOC在低温低压测试时发现偶发性死机问题非常难复现。后来抓内部波形发现复位释放沿和某个时钟域的时钟上升沿距离只有几十皮秒相当于落入恢复时间窗口。查出原因后发现某个复位同步器输出经过的复位树分支没有做平衡导致释放沿经过一个长路径后延迟飘移最终出现在了一个不该出现的位置。这个案例给我们的教训是复位树虽然不要求像时钟树一样精确平衡但在高速接口、跨模块握手的区域必须对偏斜做定量约束。排查时不能只看负责时序报告要看全部复位路径上每段buffer的延迟贡献。如果报告里有恢复时间违例优先在版图高亮该路径检查是否存在绕线绕了大半圈、跨过模拟模块、或者穿过了高密度区域这些情况。调整floorplan往往比单纯加大buffer更有效。4.2 多时钟域复位同步的常见错误多时钟域项目里最典型的错误就是拿一个时钟域同步后的复位输出直接去复位另一个时钟域的寄存器。从RTL功能看两个域复位后的初始值可能一样仿真也看不出问题但实际上第二个时钟域的复位释放沿是由第一个时钟域产生的第二个时钟域自己的时钟和这个释放沿没有任何固定相位关系本质上又退化成异步复位释放亚稳态问题重新冒出来。正确做法是一个时钟域一套复位同步器独立同步复位释放。即使多个时钟域都来自同一个外部复位源也必须分别在各自域内打两拍。同步器的输出不能跨域共享只能域内使用。这一点我会在代码评审里专门检查凡是发现rst信号从模块A直接连到模块B的复位端就打回去。另一个常见错误是同步器的复位端接错了信号。有人为了图省事把同步器输出的内部复位信号接到同步器自身的复位端结果是复位拉低时同步器清零但复位释放后同步器的两个触发器需要重建高电平这个重建过程完全没有同步关系等于把异步释放问题原样保留。标准结构必须坚持两级触发器的复位端接原始异步复位源。4.3 复位释放的毛刺与半途问题异步复位端对毛刺的敏感程度是很多工程师低估的。复位信号虽然是电平信号但几乎所有数字单元库的异步复位端在电平翻转的前后都会有一个很小的时间窗口如果在这个窗口内出现毛刺输出的状态可能直接被打翻。外部复位信号必须通过专门的复位芯片输出内部复位控制信号尽量由状态机生成不要在数据通路里随便与组合逻辑做与或运算后当复位用。半途复位是另一个隐蔽问题。复位释放不是瞬间完成的从驱动端到远处寄存器有一个传播过程离驱动端近的寄存器先释放远的后释放如果两个模块之间没有等待机制先释放的模块可能立即访问后释放的模块导致读到全零、非零或中间态。解决这种问题一是靠复位树平衡把同域内的释放偏斜压到安全范围二是靠软件或硬件握手在复位释放后等待固定周期再启用跨模块访问。如果芯片里有一个“复位完成”状态寄存器软件读到置位后才开始初始化外设这种设计就稳健得多。4.4 从仿真失败到定板的排查步骤如果怀疑复位相关故障我一般按下面的顺序排查。第一打开仿真波形单独拉出复位信号和各个时钟域时钟信号看复位释放沿和时钟上升沿的相对位置。如果释放沿落在时钟沿附近基本可以定位为恢复时间窗口问题。第二把所有寄存器的复位端连接情况梳理一遍找出哪些寄存器没有经过复位同步器。仿真中如果复位信号断开但时钟仍在跑那些寄存器的初始值完全随机行为表现为状态机跳转到非法分支。第三用CDC工具跑一遍看看有没有跨时钟域复位同步违例。尤其是同时存在多个时钟域、多个电源域的设计这一步最节省时间。第四看后端报告里的恢复/移除时间slack。哪怕只有一条路径违例也要顺着路径追下去看是复位树偏斜、电源域边界延迟不匹配还是下方标准单元摆放过密。第五在板级测试时用可编程复位芯片调整复位释放时间点看问题是否随着释放点偏移而消失。如果可复现再回头看芯片内部复位树的延迟。这个方法在系统级验证里效果很明显能用最小代价快速判断是芯片内部问题还是板级时序问题。4.5 芯片复位与板级、软件复位的边界和复位相关的岗位不只做芯片设计的工程师。嵌入式工程师经常关注Linux设备树里的复位控制属性比如外设复位信号时间怎么调整本质是在芯片外部管理和控制一个复位时序。这块和芯片内部复位树是上下游关系芯片复位树保证芯片内部状态可控软件再通过复位控制器去管理外部外设的复位脉冲宽度、释放顺序。像STC单片机复位电路、按键复位、看门狗复位这些话题属于板级和系统级复位设计关注点是复位芯片选型、RC延时、手动复位去抖。芯片内部设计做完后外部复位电路通常只需要提供稳定、干净、足够宽的上电复位脉冲剩下的事情交给芯片内部的复位管理单元。现在很多带内部POR、BOR功能的SoC外部复位电路已经简化到一两个阻容或专用复位芯片这恰恰说明芯片内部复位树承担了大部分工作。5. 一些个人经验做过的项目越多越觉得复位设计要在RTL阶段就当成一个完整方案来规划而不是后端发现问题再补。每个复位信号在写代码之前都要先想清楚四件事来源是谁、同步到哪个时钟域、覆盖哪些寄存器、和电源域时序是什么关系。这四点想清楚了后续的综合、约束、后端会轻松很多。如果项目时间紧优先级最高的就是确保每个时钟域都有独立的复位同步器并且同步器输出只在该时钟域内使用。这一条做好了能避免我前面讲的大部分问题。其次是复位释放与其他模块的握手等待哪怕只是软件上多等一段时间也能显著提高系统稳定性。最后有一个建议刚接触芯片设计的人可以自己搭一个小模块故意把复位释放沿放在时钟沿附近跑仿真看结果再对比加了复位同步器之后的行为差异。这种最直观的实验比看一百篇文档都管用。复位这个东西看着基础但正因为基础才值得花时间去琢磨。真到了芯片回来后出问题的那一步再想改代价就不是几行代码那么简单了。
返回列表