前言
今天想探究一个小问题,就是寄存器的时钟如果与主时钟是异步时钟,那么会不会对主功能有影响。当然,这样做肯定不是合理的,我知道的比较多的是寄存器使用降频到同源同相的时钟,或者使用主时钟再对寄存器读取时钟做跨异步。
不过我想了几天总是感觉如果使用异步时钟,是否也可能对功能影响有限?
场景
主要想探究三个场景:RW型配置寄存器、RO型状态记录寄存器和W1C型上报寄存器。
RW型配置寄存器
对于软件配置的RW型寄存器,配置时钟为apb_clk(假定使用apb总线配置,令其为125M),工作时钟为work_clk(令其为800M)。那么在寄存器配置后的几个时钟周期内,内部工作电路看到的值是不定的,最终会在几个周期后获取的正确的配置值,rtl内关联逻辑也会在几个周期后恢复正确:
那么如果rtl对这个值以及这个值的变化非常敏感,或者在电路工作中频繁的配置,则这样会引起电路内部的功能问题。而如果工作的流程是先配置寄存器,稳定后再启动电路工作,并且在工作过程中不会改配,则配置项可以视为准静态信号,此时即使配置寄存器在异步时钟域,也不会影响主电路动作。
举个例子,寄存器配置启动信号,电路中获取配置的沿跳变开始启动,这种场景下即使晚几拍开始工作实际也是没有影响的,而且启动配置一旦稳定为1后也不会随意跳变为0了,因此电路时可以正确工作:
因此我个人认为,如果对于一个系统,配置项在工作之前稳定,在工作过程中可视为准静态信号的话,寄存器处于异步时钟域是可以接受的。
RO型状态记录寄存器
状态寄存器一般用来记录内部的busy、cnt、接口等状态信息,主要用于在出现bug时“甩锅”。比如系统卡死了,我一查自己的模块ostd_cnt都是0,接口和内部的valid都是0,那就可以拍胸脯说:不是卡死在我这的!因此这一类记录寄存器基本为电平上报(即使为脉冲,在高频工作低频寄存器的场景下也会展宽),简单的电路如下图:
对于这种情况,同样的如果软件不需要实时的获取最新最准确的值,且在读取时(比如挂死的场景)这些状态已经稳定在某个值一段时间,那么应该说直接异步采样是不会有问题的,最后总是能够读取到需要的值。如果软件需要实时准确值,那么这样会导致状态读取错误。
W1C型上报寄存器
w1c型寄存器一般用来上报中断、上报完成等软件可以清掉的状态,这类状态一般在电路内部以脉冲的方式上报(总不能中断一直起,清掉了立马又上报吧,致命中断除外)。因此如果电路在高频工作,状态上报时是需要脉冲展宽的,当然如果以电平的方式上报则没有这个问题。那么还是刚刚的思考,脉冲展宽之后虽然有亚稳态的影响会导致寄存器在几拍之后才会采样的正确的值,但是只要正确的值能够被采样到,就可以软件读取到正确的值。
在这里我又多想了一些,w1c型寄存器提供给rtl的接口都是两个(以中断为例):irq_in和irq_wen。如果irq_wen和irq_in做相同的展宽(我印象中需要展宽到慢时钟两个周期),但是apb_clk在信号下降时采样到了亚稳态,irq_wen恢复到了1而irq_in恢复到了0,那是否会使得最终寄存器中保存的值为错误值?换而言之,是否需要将irq_in做更高的展宽确保一定最终上报正确的值呢?
以上就是这两天我的思考内容,并非来自工作经验因此结论很可能是错误的,请大家不吝勘误。