时钟切换电路的意义

为什么要做clock switching,在现代的SoC设计中,很多时候我们设计的模块并不是要跑在一个固定的频率下,而是根据性能和功耗的要求要跑在不同的时钟频率下当需要降低功耗以及不需要很高性能的时候,我们可以降低时钟频率,将驱动这个模块的时钟换成一个慢速时钟。通常时钟控制模块会产生不同频率的时钟,可能来自不同的PLL,也可能是来自不同的时钟分频器然后有选择逻辑来选择让哪一个时钟驱动电路。

几种时钟切换电路

mux时钟切换


当SEL为0的时候,CLK1被上面的AND门给block住,当SEL为1的时候,CLK0被下面的AND门给block住。但是问题会出在SEL变化的时候,AND的门变化是立刻的,当SEL恰好在CLK1为高的时候从1变为0,或者恰好在CLK0为高的时候从0变为1,那么输出的CLK_OUT就会产生一个毛刺glitch

毛刺的危害:如果下级电路对毛刺敏感,比如异步复位,时钟,清零和置位端口对等,就会是负载电路产生错误操作,影响电路工作的稳定性、可靠性,严重时会导致整个数字系统的误动作和逻辑紊乱。”

负沿触发的触发器

那么接下来我们就要思考如何避免毛刺的产生。一个思路就是,我们要先把当前正选中的时钟完全停下来,然后再切换成我们想要的目标时钟。

然后问题就变成了,我们在什么时候可以把当前时钟停下来且无毛刺,以及我们在什么时候可以让目标时钟通过且无毛刺。

关于什么时候让时钟停下来且无毛刺,我们回想一下我们在设计clock gating里也遇到过类似的问题,在Clock Gating 技术解析 (一)里,解决的办法是利用一个负沿触发的latch,使得真正的gating发生在clock为低的时候。这里我们也要利用这个想法,即在clock为低的时候停住clock。相应的,对于目标clock,我们也在它为低的时候打开,这样下一个正沿就可以完整的输出。

利用clock gating的设计,这样我们就可以得到下面一个电路:


上面的两个flop注意都是负沿触发的,也就是说它们的Q会在CLK1和CLK2的下降沿到来之后才发生变化,这样就可以保证CLK1/2为高的半个周期完整的输出,同时,切换为另外一路的时候由于Flop之前的AND门,也保证了即使SELECT立刻变化,AND门的输出也是在另外一路停下来之后才能发生变化,这样就保证了先停一路,再切另外一路。

当SELECT为0时,明显CLK1的那部分通路到输出无效,仅仅看下半部分电路即可,在CLK0的下降沿采样SELECT(取反后)信号,与CLK0相与之后输出;

当SELECT为1时,同理上半部分电路有效;

以后都不是问题,需要重点分析的是当SELECT在任意时刻切换的时候,输出会不会出现毛刺?
当SELECT由0转换为1时,在CLK0的下降沿来临之前,DFF0的输出依然为1保持不变,此时输出仍为CLK0,当CLK0的下降沿到来时,DFF0的输出为0,此时下半部分电路无效,上半部分电路的输入为1,但在CLK1的下降沿来临前,DFF1的输出依旧为0,保持不变,此时outclock输出为0,当CLK1的下降沿来临时,此时outclock的输出为clk1。

看起来问题解决了,但是上面的电路有什么问题呢?这里面有个CDC的问题。请问,SELECT信号到底是同步于CLK1还是CLK2呢?甚至有没有可能SELECT信号是异步于CLK1和CLK2呢?我们说,如果CLK1和CLK2为两个异步的CLK,那么SELECT至多和其中之一同步,和另外一路必然异步。既然是一个异步信号,那么直接去寄存器的D端就会产生CDC的问题,flop可能会产生亚稳态!当flop出现亚稳态的时候,输出CLK_OUT当然也不是干净稳定的,造成的恶果不亚于毛刺!

好,那么要怎么解决问题亚稳态的问题?很简单加synchronizer,也就是要在flop前面再加一级flop,来达到利用2flop synchronizer来synchronize SELECT的目的。电路变成下面


rtl代码

reg     out_r1;reg     out1;reg     out_r0;reg     out0;always @(posedge clk1 or negedge rst_n)beginif(rst_n == 1'b0)beginout_r1 <= 0;endelse beginout_r1 <= ~out0 & select;endendalways @(negedge clk1 or negedge rst_n)beginif(rst_n == 1'b0)beginout1 <= 0;endelse beginout1 <= out_r1;endendalways @(posedge clk0 or negedge rst_n)beginif(rst_n == 1'b0)beginout_r0 <= 0;endelse beginout_r0 <= ~select & ~out1;endendalways @(negedge clk0 or negedge rst_n)beginif(rst_n == 1'b0)beginout0 <= 0;endelse beginout0 <= out_r0;endendassign outclk = (out1 & clk1) | (out0 & clk0);

注意几个问题:
1.第一级触发器是为了解决select信号亚稳态问题
2.第二级负沿触发器是为了解决毛刺问题,即利用一个负沿触发的latch,使得真正的gating发生在clock为低的时候。这里我们也要利用这个想法,即在clock为低的时候停住clock。相应的,对于目标clock,我们也在它为低的时候打开,这样下一个正沿就可以完整的输出。

3.因为synchronizer的引入,当SEL变化到en0发生变化需要2个CLK0周期,之后才能把CLK0停下来。也就是说,当前CLK不是立刻停下来的,这一点大家在设计模块的时候要留心一下,不能想当然认为SEL一变化CLK立刻就会停。

4.而由于另外一路的synchronizer的延时,当之前的CLK停下之后,目标clock也不是立刻开始反转,所以两个clock切换中间会有一段时间CLK_OUT没有clock,这个gap对你的系统是否有影响要仔细考虑。

5.我们说是利用1个clock周期去使得metastable来稳定下来。但就上面这个设计而言,我们在负沿触发的flop之前只加了一级正沿触发的flop,这样留给flop输出稳定下来的时间只有半个周期。可能会使得MTBF达不到我们需要的值,所以这其实是一个trade off,你可以在前面再加一级正沿触发的flop,这样变成真正的2flop synchronizer。但是代价就是需要更多一个周期来停下clock,以及中间没有clock的gap时间更长。

6.在综合以及PNR的时候,对于后面的两个AND门和OR门要设为dont touch,避免综合工具给替换成别的cell。

如果不希望你用负沿触发的flop,因为我的工艺库里面没有,那么你要怎么设计?


但是很不幸,上面的电路看起来完美无缺,但是其实并不能达到无毛刺的时钟切换。往下看老李的提示之前,请你自己思考一下为什么?和上面的negedge flop + AND有什么区别呢?

其实原因就是en0变为0的时候CLK_OUT并不是立刻停住的!这是clock gating cell的特征。那么当你把en0b传给下一路,下面CLK1可能会在CLK0没有完全停下的时候就打开了,还是会产生glitch。你可能会说,en0b到en1不还得经过一段时间吗?en1变为1到ICG打开不也得要时间吗?你期望CLK0利用这段时间完全关断。但是这并不一定,因为你并不知道CLK0和CLK1的频率关系,如果CLK1比CLK0快很多,下面的synchronizer delay可能并不够。我们要设计的是一个能够在clk0和clk1在任意频率下都可以工作的电路。

所以改进的设计是要在en0之后再加一级flop,将延一拍之后的en0b_dly反馈给另外一路,这样才能保证在当前路完全关断的情况下切换。

再扩展问一个问题,上面我们设计的都是两路clock之间进行切换,如果要求你设计一个多路时钟切换的电路,甚至要求时钟的路数是参数化的,你要怎么设计呢?

关于多路时钟切换,第一个要考虑的问题是,如何设计SEL?是用binary来编码SEL还是别的方式?这里推荐用独热码onehot来编码SEL,因为任意时刻只会选中其中一路,天然就和onehot的编码性质相同,也就是N路clock,那么SEL就是N位,每一位对应一路。利用onehot encoding的还有一个好处是参数化方便,如果利用binary,那么可能会遇到不合法的输入,比如只有3路clock,但是SEL=2‘b11。关于独热码,还推荐大家读面试题分析–独热码检测

另外一个要考虑的问题是最后的那个OR门的实现,当我们只有2路,3路clock需要切换的时候,库里面有2输入的普通OR门,但是并不推荐大家直接用。原因在于,由于最终我们输出的是一个时钟信号,那么我们通常要求时钟信号的transition是非常干净的,而且上升沿和下降沿是平衡的,即tr(rising delay)和tf(falling delay)是几乎差不多的,而普通的2输入OR门并不保证它们tr和tf相等,而且是与2输入中连哪一个输入pin有关。为了解决这个问题,工艺库厂家一般会提供一些特殊的CELL,进行了专门的设计,可以使得tr和tf几乎相等,并且两个输入pin的延时也是一样的,并不区分,所以我们要例化那些特殊的专门给clock path上用的cell。但是当输入变成了多路clock,比如4路,5路,甚至更多路比如8路,16路的时候,厂家也不会提供balanced 多输入clock OR cell。这个时候我们就要专门利用NAND tree来实现最后的OR逻辑,并且要保证每一路所需要的NAND cell delay是一样的(思考题:为什么要balance每一路?)举个例子一个利用NAND tree来达到2input OR的结构如下


最后再提一个很多人都会忽视的问题,请问大家,在上面设计的无毛刺时钟切换电路,对于其中synchronizer flop,以及clock gating cell,你有没有考虑reset信号的影响? 如果你的reset信号是异步reset,那么当你reset active的时候,clock会立刻被切断,那么是不是也会产生glitch?

这个问题的解决思路有两个,一是假设你在reset状态下选中的是clock0,那么需要你在assert reset之前要先切换到clock0;如果不是,比如reset assert的时候是clock3,那么你需要保证所有被clock3驱动的下游逻辑也都会被这个reset信号给复位。

参考文章面试题分析 – 时钟切换

无毛刺时钟切换(glitch free clock switching)相关推荐

  1. 无毛刺的时钟切换电路(Glitch-free clock switching circuit)设计(Verilog)

    从秋招的经验来看,Verilog设计类的题目,如:奇偶分频,状态机,序列检测,波形产生,跨时钟域处理,门控时钟,同步FIFO,格雷码与二进制码转换,异步复位同步释放,时钟切换,异步FIFO等,其中最为 ...

  2. IC基础知识:时钟无毛刺切换

    参考这篇文章:数字电路时钟无毛刺切换 因为直接用组合逻辑判断去切换时钟,会产生毛刺,如下图所示. 产生该毛刺的原因: sel没有在时钟跳边沿改变.因为我们一般是用clk上升沿采样数据,所以我们sel选 ...

  3. 【Verilog HDL 训练】第 14 天(glitch-free的两个时钟切换电路)

    2019年5月13日 glitch-free的两个时钟切换电路. 可以看到这是一个星期之前的题目了,现在才抽空做,把这篇颠倒个顺序吧,也是最后一天了,以后的题目都是讨论性质的,不会以第多少天的形式来写 ...

  4. glitch-free的两个时钟切换电路

    有毛刺的时钟切换电路 原理图: 这个时钟切换电路是一个纯组合逻辑,输出时钟(OUT CLOCK)由选择信号(SELECT)控制,当SELECT为1时输出CLK1,反之,输出CLK0. 看似很简单,实现 ...

  5. 时钟切换处理(Verilog)

    随着各种应用场景的限制,芯片在运行时往往需要在不同的应用下切换不同的时钟源,例如低功耗和高性能模式就分别需要低频率和高频率的时钟.两个时钟源有可能是同源且同步的,也有可能是不相关的.直接使用选择逻辑进 ...

  6. 歪解单片机的时钟系统--关于内外时钟切换及时钟超频测试

    群友问过这种问题,外部接8M晶振和16M晶振有啥区别?        以我微薄的经验来看,这两个在用的时候差别不大,如果使用ST的固件库(以STM32F103为例),使用8M的晶振会更方便,不用改任何 ...

  7. 关于单片机的时钟浅谈及STM32F103/F030单片机的内外时钟切换问题

    绪论 本文主要讲解单片机的时钟系统的相关知识,并进行超频测试,同时介绍如何在STM32F0单片机上进行内外时钟的切换,在不使用外部晶振或者外部晶振不启动时自动切换内部时钟的方法. 一.杂谈 问题来源于 ...

  8. ABOV单片机时钟切换讲解及示例代码-[MC96F6332D]

    一.准备工作 1.KEIL C51编译环境 2.CodeGen8 代码生成器 3.MC96F6332D 开发板 4.USB-OCD II仿真器 二.生成系统时钟代码 1.在CodeGen8 代码生成器 ...

  9. android 时钟翻转,3D翻转时钟插件 3D Flip Clock World Weather

    编辑点评 翻转效果天气时钟插件 3D翻转时钟插件 3D Flip Clock & World Weather 介绍 3D翻转时钟插件 3D Flip Clock & World Wea ...

最新文章

  1. sed、cut和awk命令的使用
  2. 4.无监督学习--K-means聚类
  3. 考试必错规则:如果你觉得题目很简单,代表你肯定错了
  4. VMware配置网络,主机互通,可上网
  5. 周一“开小差” 淘宝又崩了
  6. Python+tkinter实现任意多层级关系的组合框
  7. java 守护进程 linux_Java使用appache deamon实现linux守护进程
  8. java 表格树_00030-layui+java 树形表格treeTable
  9. DM9000驱动之接受
  10. matlab电力系统建模仿真实验,电力系统建模及仿真课程设计
  11. P3853 路标设置
  12. 教程向 | 安装 地表最强IDE---Microsoft Visual Studio 2022
  13. JS match() 方法 使用
  14. 2022-2027年中国实验室自动化行业市场调研及未来发展趋势预测报告
  15. Linux系统下微信网页版无法登录问题(deepin-wine-for-ubuntu)
  16. 光纤跳线接口_2分钟让你搞懂跳线架和配线架的区别
  17. aix oracle 10.2.0.1 升级 10.2.0.4,【江枫 】AIX平台升级到Oracle10.2.0.4的几个问题
  18. 排球分组循环交叉编排_巍山县举办气排球赛,看谁技高一筹!
  19. 爬取虎扑nba球员得分榜信息并存储至MongoDB数据库
  20. 1103 缘分数 (20 分)

热门文章

  1. 打开fiddler 电脑无法上网问题
  2. SOEM 源码解析 ecx_LRD
  3. 程序员想拿高薪,你还缺了这些,在寒冬下如何选择?创业or进阶
  4. 常用应用层协议及HTTP协议
  5. Hbuilder快捷键教程
  6. Xshell开多个会话和会话分屏
  7. SpringBoot接口数据加解密实战
  8. LeetCode 149 直线上最多的点数
  9. 2022 年最值得学习的 10 种编程语言 [更新]
  10. 使用 Python 计算 DID 及其对应P值