经常在面试时问到一个问题:对于芯片中的复位信号我们通常会有哪些特殊处理?这个时候我一般希望得到的回答包括:复位消抖、异步复位同步撤离、降频复位、关断时钟复位和复位保护等处理方案。
复位消抖
这篇文章就先聊下复位消抖,在开始之前先说明一下因为我的经验有限且很多是道听途说,所以文中难免有所疏漏和错误,请大家不吝赐教。
复位信号在使用前一般需要进行消抖处理,也称为复位滤毛刺。复位的抖动可能会导致芯片产生多次复位动作,给系统带来不确定性和误差。消抖的目的是为了确保复位信号的稳定性和可靠性,从而保证系统能够正常工作。通过消抖,可以消除复位信号的抖动干扰,保证复位信号的可靠性和稳定性,避免系统故障和数据丢失等问题。
举个例子,如果要消除30ns以下的复位抖动,那么30ns以下的复位信号rst_n拉低操作就会被消抖电路消除,不会对电路产生任何的影响,只有30ns以上的复位拉低操作才能作用于内部电路。
所以复位消抖电路具体长什么样子呢?目前我了解的有三种方式,不过因为没有实际参与过CRG模块的设计与流片,所以以下内容只做参考。我们假定滤毛刺时钟为100M,需要滤除的复位抖动为30ns以下的信号。
第一种方式通过滤毛刺时钟+D触发器来完成,如要滤过30ns的抖动电路图如下:
D触发器的数量关系是如何得到的呢?先假设我只有一个延时D触发器,那么复位信号必须维持L电平在一个clk时钟周期以上或门才能在时钟沿处打出一个L信号出来(即时钟上升沿时rst_n || rst_n_ff1 == 1'b0),如下面的波形图所示:
同样的,如果有两个延时D触发器,那么复位信号必须维持L电平在两个clk时钟周期以上,或门才能在时钟沿处打出一个L信号出来:
如果有三个延时D触发器,那么复位信号必须维持L电平在三个clk时钟周期以上,或门才能在时钟沿处打出一个L信号出来:
因此,在或们前放置了N个延时D触发器,就可以滤除N*T(T为消抖时钟的周期)时长以下的复位毛刺信号。这种方式存在一个巨大隐患,消抖时钟信号是不受复位控制的,一旦消抖时钟信号出了什么问题,复位信号将永远无法从消抖电路传递出去。
第二种方式通过累加器来完成,简单来说就是数一下rst_n连续出现了多少拍,假如需要通过100M消抖时钟来滤除100ns以下的复位抖动,那么rst_n要连续出现10拍低电平才达到100ns的复位标准。将rst_n打两拍rst_n_ff1/rst_n_ff2消除亚稳态,当rst_n_ff2持续达到10拍对外输出复位信号,对应的波形示意如下:
这个消抖方案呢同样存在上面的问题,消抖时钟信号是不受复位控制的,所以在芯片内的模块级别可能会被采用,但是在外部复位消抖时是一般不会使用的。
第三种方式是通过延时器件来实现,要滤去100ns以下毛刺,那么就引入100ns延时器件,组成如下电路:
对应的波形也很简单:
通过波形可以看出,如果复位时长不够100ns,prst_n根本不会被触发。这个电路的隐患在于如何保证延时器件在不同温度等外部环境干扰下的延时准确性。
异步复位,同步撤离
对于使用异步复位的系统,低电平复位系统时复位信号是允许不与工作时钟对齐的即纯纯异步复位;但是在复位撤离时,需要与工作时钟对齐,即满足removal time要求(在时钟有效沿来临之后,异步复位信号需要继续保持有效的最短时间),或者说复位的撤离行为是受到时钟控制的。
既然都已经是异步复位了,为何还要多此一举呢?
1.对于复位这个操作行为而言,纯异步处理是完全可以的,因为所有的元器件都会最终回到初始值。当然了,这里指的是整体复位或者说带保护的局部复位。你别管这些寄存器谁先复位谁后复位谁出现亚稳态了,只要不是着火了最后都会回到复位值。就像电视剧里说的“反正早晚都是没,早没晚没又有什么区别呢”。所以异步复位出电路是没有任何问题的。
2.但是对于复位撤销这个行为就不一样了。一旦复位撤销了各个元器件就会开始工作了,但是复位信号如果是纯异步的打到某个寄存器接口上的时候可能就撞到亚稳态窗口上了(不满足removal time),亚稳态就会在电路里开始蔓延捣乱,出现什么情况可就难说了。所以复位撤离这个事必须得是受到时钟控制的,不能是纯异步电路。
这里有一点要注意哈,同步撤离这个操作解决的是异步复位可能的亚稳态问题,并不是说能够保证所有的寄存器在同一时间收到复位撤离的操作。这个事就类似与信号打3拍同步一样,咱们先解决亚稳态问题,再处理信号传的对不对的问题。通过异步复位同步撤离先确保没有亚稳态,再处理寄存器不能在同一拍接收到复位撤销导致错误的问题。
如何做到异步复位同步撤离呢?请看下面这个电路:
rst_n经过滤波后得到prst_n,因此我们只需要分析prst_n的行为影响即可。
正常工作状态下,prst_n==1;
异步复位时prst_n由1跳转为0,两个D触发器立刻被复位。也就是说rst_work_n会立即下拉至低电平复位系统,这个下拉显然时候不受时钟控制的,因此实现了异步复位;
复位撤离时prst_n由0跳转为1,两个D触发器的复位被撤销了开始正常工作。但是高电平需要两个周期才会到达rst_work_n端,这两个周期足以消除复位带来的亚稳态并且保证系统感知的复位rst_work_n在时钟沿上,因此实现了同步撤销;
借助于这个电路设计,系统的异步复位同步撤离功能就实现了。不过当年我还问了大佬一个问题:这样的话系统就延时了2个周期才复位的啊,会不会有bug?
大佬的回答是这样的:你这啥系统啊真的在乎这一两个周期的事么?早跑几周期晚跑几周期有啥关系,只要别跑错了就行!
解复位的特殊处理
解复位就是复位撤离,系统解复位就是复位结束了系统准备开始工作。
前文咱们提过,复位撤离比复位要复杂一些,因为复位了大家就是一起回到初始状态去,寄存器也不采样了,有什么毛刺啊亚稳态啊只要不影响其他系统(这个之后讲)都没关系的。这就相当于晚上回家上床准备上床睡觉,你爱穿啥衣服睡就穿啥衣服不穿也没人管。但是解复位就不一样了,这就是起床要出门上班了,怎么着也得准备好才能出去工作,不能穿着秋裤就往外跑。
所以的对于解复位(其实也不光是解复位,局部复位本身也很危险)就需要做跟多的额外工作了,上一篇说的同步撤离之后,还有什么问题需要解决呢?
主要是复位信号到达各个寄存器的时间不一致的问题。复位信号在系统内是有很大的扇出的,连接到所有需要复位的寄存器的复位端。这也就导致了复位在系统中的走线特别长,过长的走线又会导致工具在复位信号上增加buffer以提升驱动能力,那么如果时钟频率很高,复位信号最终到达各个寄存器的时间也就无法保证在同一拍。
复位走线到达各个寄存器不在同一拍会有什么后果呢?这个不能一概而论。对于一些复位解除后就开始工作的电路系统比如自动计数取指模块,各个寄存器之间可能存在依赖关系,如果只部分寄存器被复位或解复位,可能会导致不一致的状态,从而影响系统的正确运行。同时呢,如果复位方案做的不好,某系统进行复位时一部分复位了一部分没有复位,也可能会产生毛刺被未复位的寄存器采样,进而输出使能影响到其他系统的正常工作。
总之呢,复位走线到各个寄存器不在同一拍,可能存在系统稳定性的风险。因此在对复位还需要对系统的复位做一些特殊的处理。特殊的处理有哪些呢,不同的团队也有多种多样的选择,这里列举一些我所听闻过的方案吧。
降频后复位。
先把时钟降频,再进行复位和解复位的操作,再提频回正常工作时钟频率。你不是怕复位走线到各个寄存器的时间不一致导致不在同一拍复位吗?那好,我把时钟降频总可以吧,1GHz太快了降到500M,500M还快降到100M,100M还快到10M总可以了吧,一个周期这么长时间足够你复位信号慢慢溜达到各个寄存器的。所以采用这种方案时,会在复位前将工作时钟32分频或者64分频(取决于系统的面积和工作时钟,可以算的),然后进行复位和解复位,之后在将时钟提频至工作状态。
这种方案下,可以在sdc中将复位信号设置为multicycle,检查其在64个时钟周期内能够作用到所有的寄存器复位端。
**关时钟后复位。**
这个方法更彻底,怕各个寄存器看到复位和解复位的时间不一致导致功能错乱?那直接把工作时钟给关断不久好了,反正是异步复位不用担心没有时钟复位信号作用不到寄存器端。时钟一关所有寄存器相当于原地停工,这个时候别说复位信号了,啥信号过来都没事,寄存器都不干了嘛。所以此时复位信号的走线也就不称问题了,先复位再慢慢悠悠的解复位,都搞定了歇一会再把时钟打开。
这种方案下,可以在sdc中将复位信号设置为false_path,毕竟相当于准静态的信号,工作时复位信号不会跳变。
复位保护。
这个方法的思路是,不是担心我这块的复位影响其他系统工作嘛,那么不去处理复位和时钟,而是把系统裹起来。怎么裹起来呢,把所有的对外输出使能啊、握手啊这类信号都先和低电平与在一起,保证不管一会发生啥事,都不会有关键信号发生跳变。保护好之后,再去拉复位信号,过一会再解复位,再等会时间等系统稳定下来了,再把保护电路解除开始正常工作。
这种方案下,也可以在sdc中将复位信号设置为false_path。
复位之后等待一定时间再开始下任务。
这个方案更多的是在任务层面看,也就是说面对解复位后可能存在的系统不稳定性,先不要着急下任务下配置下指令,而是等待一定时间等系统中可能存在的不稳定状态都结束了,再开始进入工作模式去下任务。
当然了不是说所有系统都适用以上的方法,比如某个系统确实是解复位后就立即开始工作,那用复位保护就没效果,因为你内部状态都乱了保护其他系统还有啥用呢。所以说还是具体问题具体分析吧,以上也只是经验之谈难免有所疏漏。
典型的软复位流程
在聊到复位的时候总会区分两个概念:硬复位和软复位。
硬复位就是通常所说的复位,是通过硬件电路或者特殊的硬件信号来触发的复位过程。当拉低外部复位信号时硬复位被触发,复位线会直接影响系统的硬件电路与寄存器,将系统的内部状态恢复到一个已知的初始状态。硬复位通常是由外部的控制电路或者特定的硬件引脚来触发,例如按下一个复位按钮或者通过特定的电路逻辑条件。
软复位是通过软件的程序代码或者寄存器配置等方式触发的复位过程。当软复位被触发时,系统一般需要执行特定的步骤来响应软复位需求,确认进入待复位状态后才会进入复位流程,将系统的内部状态恢复到一个已知的初始状态。软复位通常是在程序执行中的某个特定条件下发生,例如检测到一个错误或者需要重新初始化系统时。
硬复位一般是整芯片甚至芯片组复位,这个过程可以说是比较简单粗暴的。而软复位一般是芯片的部分系统进行复位重启,有时也称为快速复位、动态复位、配置复位,大多是通过一系列的流程来完成的。
本篇中就聊一聊典型的系统软复位流程。
1.触发软复位启动条件。这一般是系统内部或SOC出现了致命的错误比如任务执行超时、总线数据错误或安全机制报错等,上位的MCU或者CPU判断需要对该系统进行软复位操作以恢复功能;
2.停止下发任务。判断需要对系统软复位后,应当从任务层停止下发新的任务,避免系统错误进一步的蔓延影响其他进程;
3.下达软复位请求。请求可能通过配置系统的寄存器或者从控制接口下发使能信号;
4.系统接收到软复位的请求后,需要做出一系列的处理。这时一般有两种方向选择,一种是主动停止工作,比如停止执行接下来的取指、在指令或者卷积层边界停止进一步的计算;另一种是被动停止工作,也就是内部逻辑不停止工作,而通过系统边界的模块响应软复位,进而对内部通路进行阻塞或者假握手假接收等行为使内部被动停止工作。
5.系统边界的模块监听所有通路,等待所有已经发出的请求全部收回应答(典型的比如AW请求收回Bresp,AR请求收回Rdata),这样做的目的是避免本系统的复位对SOC或其他系统产生影响,也避免对解除复位后的本系统产生影响(如未收全,本系统复位解除后总线返回了一笔复位前的Bresp,那本系统直接就乱了);
6.边界的模块收全所有应有的返回信息后,或者未能收全但是到达超时阈值后,系统进入待复位状态;
7.此时如果本系统仍然保留着访问DDR和sram的备份通路,那么上位机可以通过配置寄存器去间接访问内存和寄存器进行保留现场。如果没有规划该功能,则略过这一步骤;
8.上位机配置复位保护寄存器使能复位保护电路,避免系统复位过程中有毛刺或者使能信号扩散到总线或其他系统;
9.上位机配置对系统进行时钟降配或者关断时钟等操作,这个是可选操作,一般来说如果复位保护做的比较严格,这里不对时钟进行处理也没关系;
10.配置复位或拉低系统的复位信号,持续一段时间,这个时间没有太严格的要求,按毫秒计时也没有关系,少的话也得几十拍确保系统内所有寄存器都完成了复位;
11.复位已经完成,之后配置解复位或拉高系统的复位信号,解除系统的复位状态,之后等待一段时间等内部电路稳定下来;
12.配置时钟恢复工作频率或恢复时钟,可选;
13.配置复位保护寄存器解除复位保护,恢复总线连接;
14.可以再等待一段时间后,重新下任务或恢复现场,重启系统完成。
软复位的流程没有特别严格的规定,通常是根据芯片的需求而规划,上面所述也只是经验之谈。不过大抵都遵循停任务 - 收应答 - 断连接 - 复位 - 解复位 - 重连接 - 下任务的思路。
复位保护电路
前面提到了,在一些系统中会通过复位保护的方式来避免复位过程中的“乱象”,所以本章就针对复位保护多聊一下。
复位保护电路,是在系统进行复位的过程中对接口进行硬性逻辑保护,避免毛刺和错误对周围系统产生影响的模块。通常而言,复位保护电路的开启应该在复位之前,关闭应该在复位撤离之后。咱们针对握手接口来分类看下如何进行复位保护(使能接口也类似)。
对外输出valid。
在复位期间由于复位信号到达不同寄存器的时间不同,加之组合逻辑路径,可能会产生错误的valid信号对外输出。显然在本系统单独复位的场景下,是不应该有对外的valid输出的,因此在复位前,需要将对外输出的valid信号&&0操作,确保复位和解复位期间没有valid误触发。
对内输入的ready。
进入复位的阶段,对内输入的ready是可以不做处理的,因为即使复位时出现了对外valid的误触发,系统也马上就会进入复位状态了不会有任何影响。在解复位阶段,如果流程内能够通过时钟关断或时钟降频等手段来保证系统内的寄存器同一拍解复位,在内部不产生valid误触,对内输入的ready可以不经过逻辑处理。
如果没有其他的手段保护,可以考虑对内的in_ready = out_ready || 1来保证在复位撤离阶段将误触发的valid通过假握手丢弃掉。
对外输出的ready。
系统复位期间,从业务需求上其他系统理应不对该系统有事务操作。如果真的出现了极端异常场景,那么比较合理的情况是对外输出的ready保证为1,将事务丢弃,不阻塞其他系统,如果为带rsp的事务那就等待其他系统的超时中断。
对内输入的valid。
在复位和复位期间,一般而言输入的valid是无需理会的。解复位时最好也是通过其他手段保证不出现内部的ready误触,且当本系统单独复位期间其他系统理应不存在请求到来,因此对内输入的valid也是不需要经过特殊处理的。
如果没有其他的手段保护,可以考虑对内的in_valid = out_valid && 0,避免内部误触发的ready同in_valid进行了握手。
复位保护电路。
通常而言,复位保护的使能信号从寄存器输出,作用于RTL,那么同样存在一个异步路径的问题。因为使能复位保护和撤销复位保护时,RTL是没有处于工作状态的,且内部电路处于稳态。没有工作处于稳态时,对外的valid必然为0,ready必然为1(如果不满足这个条件,请单独讨论)。
对外out_valid = 0 && (~prot_en),此时prot_en由1跳变为0(或0跳变位1),输出逻辑不会改变,也不存在亚稳态采样的问题;对外输出的out_ready = 1 || (prot_en),此时prot_en由1跳变为0(或0跳变位1),输出逻辑不会改变,同样不存在亚稳态采样的问题。因此个人认为,由寄存器输出的prot_en作用于内部逻辑时,无需经过跨异步处理。
配置复位
本篇仍旧基于工作经验,难免有疏漏和错误。在前文聊过了软复位和硬复位之后,最后一篇来说说另外一种我遇到的系统复位方案 —— 配置复位,很多情况下我更愿意把配置复位称作快速复位。粗略的一算复位情况还挺多,硬复位、软复位、配置复位、快速复位、动态复位等。
一款芯片的复位会分很多级,很大部分的小系统比如加速器这种的都已经接在三级或者四级复位总线了,看到的硬复位已经和很多软复位&&在了一起,看到的软复位也可以简单理解为更上层的“配置复位”。当然我们不在细节上做太深的探究,画个图简单里表示下好了。
配置复位和其他复位的区别主要在哪里呢?最大的一个区别是,系统的配置复位不会复位寄存器单元。想想看就很清晰,配置复位必然是通过配置寄存器单元来完成的,你要用人家就不能给人家复位了对吧。熟悉的配置复位流程和软复位流程很接近:
1.触发配置复位启动条件。如系统内部出现了致命的错误、任务执行超时、安全机制报错等;
2.停止下发任务。从任务层停止下发新的任务,避免系统错误进一步的蔓延影响其他进程;
3.通过配置总线下发达配置复位请求;
4.系统接收到配置复位的请求后,停下处理的工作;
5.系统边界的模块监听所有通路,等待所有已经发出的请求全部收回应答;
6.边界的模块收全所有应有的返回信息后,或者未能收全但是到达超时阈值后,系统进入待复位状态;
7.此时如果本系统仍然保留着访问DDR和sram的备份通路,那么上位机可以通过配置寄存器去间接访问内存和寄存器进行保留现场。如果没有规划该功能,则略过这一步骤;
8.上位机配置复位保护寄存器使能复位保护电路,避免系统复位过程中有毛刺或者使能信号扩散到总线或其他系统;
9.通过系统总线配置时钟降频寄存器或关断核时钟寄存器;
10.通过系统总线配置复位寄存器,持续一段时间确保系统内所有寄存器都完成了复位;
11.复位完成后配置复位寄存器解除复位,之后等待一段时间;
12.配置时钟恢复工作频率或恢复时钟;
13.配置复位保护寄存器解除复位保护,恢复总线连接;
14.重新下任务或恢复现场,重启系统完成。
流程这么相似的情况下,配置复位和软复位最大的区别在哪里呢?我个人的经验是,配置复位不会将寄存器复位那么所有的配置都得以保留,复位完成后可以不重新下配置的情况下快速的重启任务,所以我更喜欢将配置复位称为快速复位。当然,这个区别并不固定,软复位也可以只复位核部分不复位寄存器部分,连接合理使用得当的情况下都是允许的。
之前面对的最复杂的系统复位场景基本就是下面这样了:
因为历史遗留和甩锅等一些原因吧,我交付的系统中有一部分应该归属于NOC系统的总线模块。这部分总线模块的引入带来了一个尴尬的问题,软复位时候不能将这部分进行复位,否则NOC就挂了!所以最后的系统的复位域分了三个层级:硬复位——复位全系统,软复位——复位core和reg,配置复位——只复位core,保留配置。光复位方案就要分三套,真是不想回首的痛苦经历啊。
审核编辑:刘清
-
寄存器
+关注
关注
31文章
5281浏览量
119746 -
D触发器
+关注
关注
3文章
164浏览量
47809 -
SDC
+关注
关注
0文章
48浏览量
15513 -
CLK
+关注
关注
0文章
127浏览量
17093 -
累加器
+关注
关注
0文章
50浏览量
9436
原文标题:【芯片设计笔记】复位那些小事(建议收藏)
文章出处:【微信号:IC修真院,微信公众号:IC修真院】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论