时钟切换电路(无毛刺)——clock switching glitch free
0.引言
随着越来越多的多频时钟被应用在今天的芯片中,尤其是在通信领域中,经常需要在芯片运行时切换时钟线的源时钟。这通常是通过在硬件中复用两个不同的频率时钟源,并通过内部逻辑控制多路选择器选择线来实现的。
这两个时钟频率可能彼此完全无关联,或者它们可以是彼此之间存在倍数的关系。在这两种情况下,都有可能在切换时在时钟线上产生毛刺(glitch)。时钟线上的毛刺对整个系统来说是十分危险的,因为它可以被一些寄存器解释为捕获时钟边缘(满足建立时间等),而其他寄存器忽略此毛刺,则整个系统数据出现混乱。
本文将会介绍两种时钟切换方法,分别对应两种情况,第一种时两个时钟源的频率呈倍数关系,第二种是两个时钟源完全没有关系。
1.时钟切换的毛刺问题
切换电路:
图1:实时时钟切换
电路语言描述:
assign outclk = (clk1 & select) | (~select & clk0);
当SELECT变化时,可能会由于从当前时钟源的输出立即切换到下一个时钟源而引起毛刺。当前时钟(Current Clock)是当前SELECT选择的时钟源,而下一个时钟(Next Clock)是对应于新SELECT值的时钟源。
图2:实时时钟切换时序
仿真结果:
图3:实时时钟切换仿真
图2中的时序图和图3的仿真结果显示了当SELECT控制信号发生变化时,输出时钟如何产生毛刺(glitch)。这种切换导致的问题是切换控制信号(SELECT)可以相对于源时钟的任何时间发生改变(本质是SELECT信号完全异步),从而产生了切断输出时钟或在输出处产生毛刺的潜在可能。SELECT控制信号最有可能是由两个源时钟中的任一个驱动的寄存器生成的,这意味着它要么与两个时钟具有已知的时序关系,要么这两个时钟是彼此的倍数,或者如果源时钟不存在任何的关系,则它可能与至少一个时钟异步。
在不知道这些时钟的频率或相位关系的情况下,需要避免在任一时钟的高状态期间进行切换。固定延迟可用于引起两个源时钟的开始和停止时间之间的间隔,但仅当两个时钟源之间存在固定关系时可以使用。它不能在输入频率未知或时钟不相关的情况下使用。
2.相关时钟切换的毛刺避免Glitch protection for related clock sources
在图4中给出了防止时钟切换导致输出毛刺的解决方案,其中两个时钟源频率成倍数关系。在每个时钟源的选择路径中插入下降沿触发的D触发器。在时钟的下降沿上用寄存器寄存一下SELECT控制信号,以及仅在其他时钟被取消选择之后才启用选择(既先屏蔽旧时钟,然后在开启新时钟),从而在输出端防止毛刺的产生。
在时钟的下降沿处寄存SELECT信号,保证在任意一个时钟处于高电平时,时钟输出(CLOCK_OUT)中不发生变化,从而防止对输出时钟进行切割(Chopping)。从一个时钟选择到另一个时钟的反馈使得在开始下一个时钟的传播之前必须等待当前时钟的取消,从而避免任何毛刺的产生。
图5:相关时钟无毛刺切换电路
图6:相关时钟无毛刺切换时序
电路语言描述:
reg out1;
reg out0;
always @(negedge clk1 or negedge rst_n)begin
if(rst_n == 1'b0)begin
out1 <= 0;
end
else begin
out1 <= ~out0 & select;
end
end
always @(negedge clk0 or negedge rst_n)begin
if(rst_n == 1'b0)begin
out0 <= 0;
end
else begin
out0 <= ~select & ~out1;
end
end
assign outclk = (out1 & clk1) | (out0 & clk0);
图6显示了SELECT信号从0到1的转换时,首先在CLK0的下降沿时停止了CLK0的输出,然后在CLK1的下降沿处的开始输出CLK1时钟到OUT CLOCK。
仿真结果:
亚稳态问题:
在该电路中,有三个时序路径需要特别考虑:SELECT控制信号到两个下降沿触发触发器中的任一个、DFF0输出到DFF1的输入以及DFF1的输出到DFF0的输入。如果在这三个路径中的任何一个信号与目标触发器时钟的捕获边缘(这里是下降沿)同时变化,那么该寄存器的输出可能变为亚稳态,这意味着它可能进入理想的“1”和理想的“0”之间的状态。时钟多路复用器和另一触发器的使能反馈可以对亚稳态进行不同的解释。因此在异步接口中,需要把两个触发器的捕获边沿和SELECT信号的变换沿(SELECT信号的上升沿)分开,避免亚稳态的产生。这可以容易地通过使用适当的多周期保持约束或最小延迟约束(时序约束)来实现,因为两个时钟之间的时序关系是已知的。
3.时钟容错
在芯片启动时间,两个触发器DFF0和DFF1都应该重置为“0”状态,使得时钟中的任何一个都不被作为初始传播。通过在“零”状态下启动触发器,将容错建立在时钟切换中。
假设其中一个时钟由于启动时的故障而没有切换。如果与故障时钟相关联的触发器已在“1”状态启动,则它将阻止选择其他时钟作为下一个时钟,并且由于缺少运行时钟,其自身状态不可改变。通过以“零”状态启动两个触发器,即使其中一个源时钟未运行,仍然能够将另一个好的时钟传播到开关的输出,保证输出时钟的稳定。
4.非相关时钟切换的毛刺避免Glitch protection for unrelated clock sources
上述避免时钟切换输出处的毛刺的方法需要两个时钟源彼此的倍数关系,使得用户可以避免信号与任一时钟域异步。 但在该实现中没有处理异步信号的机制(上面的办法只是通过时序约束解决异步的问题,并没有真正解决异步的问题)。这引出了实现具有同步器电路的时钟切换的第二种方法,以避免由异步信号引起的潜在的亚稳态。 当两个时钟源彼此完全无关时,异步发送的源头可以是SELECT信号或从一个时钟域到另一个时钟域的反馈。
第二种方法是针对两个异步时钟源的切换,这个方法是在第一种方法的基础上,在选择路径上再插入一个上升沿触发D触发器,这是为了针对对两个异步时钟源产生的反馈信号以及异步信号SELECT,对选择信号进行同步处理,这样即使是两个异步的时钟源进行切换,也可以避免亚稳态的产生。同步器只是两级触发器,其中第一级通过锁定数据来帮助稳定数据,然后将数据传递到下一级,由电路的其余部分解释。
图7:非相关时钟切换毛刺避免电路
图8:非相关时钟切换毛刺避免时序
电路语言描述:
reg clk0_f , clk0_ff;
reg clk1_f , clk1_ff; always@(posedge clk0 or negedge rst_n)begin
if (rst_n == 1'b0)
clk0_f <= 1'b0;
else
clk0_f <= (~select) & (~clk1_ff);
end
always@(negedge clk0 or negedge rst_n)begin
if (rst_n == 1'b0)
clk0_ff <= 1'b0;
else
clk0_ff <= clk0_f;
end always@(posedge clk1 or negedge rst_n)begin
if (rst_n == 1'b0)
clk1_f <= 1'b0;
else
clk1_f <= (select) & (~clk0_ff);
end
always@(negedge clk1 or negedge rst_n)begin
if (rst_n == 1'b0)
clk1_ff <= 1'b0;
else
clk1_ff <= clk1_f;
end assign clk_out = (clk0_ff & clk0) | (clk1_ff & clk1);
仿真电路:
仿真结果:
图9:非相关时钟切换毛刺避免仿真结果
仿真结果十分明显。
5.结论
通过使用本文中介绍的方法,可以通过非常小的开销来避免在时钟源之间切换时在时钟线上产生毛刺的危险。 这些技术完全可扩展,可以扩展到时钟切换两个以上的时钟。 对于多个时钟源,每个时钟源的选择信号将通过所有其他源的反馈启用。
参考:https://www.eetimes.com/techniques-to-make-clock-switching-glitch-free/Techniques to make clock switching glitch-free
时钟切换电路(无毛刺)——clock switching glitch free的更多相关文章
- 单片机成长之路(51基础篇) - 023 N76e003 系统时钟切换到外部时钟
N76e003切换到外部时钟的资料很少(因为N76e003的片子是不支持无源晶振的,有源晶振的成本又很高,所以网上很少有对N76e003的介绍).有图有真相: 代码如下: main.c #includ ...
- RS485自动收发切换电路 [原创www.cnblogs.com/helesheng]
RS485是最常见的一种远距离可靠传输和组网的UART串口信号接口协议.与同样传输UART串口信号的RS422协议相比,RS485使用半双工通信,即只有一个信道,在同一时刻要么从A到B,要么从B到A传 ...
- 电池和Adapter切换电路改进实验(转)
源:电池和Adapter切换电路改进实验 目的:很多单电池的机器在大负载的情况下,如把背光开到最亮,运行3D游戏,此时拔DC电源很容易出现机器死机,或花屏现象: 原因:Q5的导通时间不够,希望通过G极 ...
- 单片机成长之路(stm8基础篇)- 025 stm8 时钟切换
stm8 时钟切换; /************************************ 时钟设置 ************************************/ // 时钟 0: ...
- 电池和Adapter切换电路改进实验
目的:很多单电池的机器在大负载的情况下,如把背光开到最亮,运行3D游戏,此时拔DC电源很容易出现机器死机,或花屏现象: 原因:Q5的导通时间不够,希望通过G极的快速放电,加快到导通时间: 修改前的电路 ...
- tab标签切换(无炫效果,简单的显示隐藏)
从最简单的效果开始写起,一个简单的JQ写出tab切换效果,很静态,没有任何的轮转特效,单纯的点击标签显示区域块. 附上代码: HTML: <div class="wrapper&quo ...
- JS的checkbox状态切换dom无变化
今天调试checkbox,手动加上checked="checked"和去掉,都对实际页面没有产生影响 搜索一番 1.对radio .checkbox 来说说,checked属性可以 ...
- 你要的fpga&数字前端笔面试题都在这儿了
转自http://ninghechuan.com 你要的FPGA&数字前端笔面试题来了 FPGA&ASIC基本开发流程 题目:简述ASIC设计流程,并列举出各部分用到的工具. 勘误:C ...
- 时钟分组的用法---Clock Groups
时钟分组的用法---Clock Groups 哪些时钟互相之间需要分组 同步时钟: 异步时钟: 不确定的时钟: 即使是从同一个MMCMs出来的时钟,有可能为不确定关系的时钟,如果它们之间的相位没有一个 ...
- MSP430 G2553 基本时钟模块+ (Basic Clock Module+)
一.时钟源 MSP430的Basic Clock Module+支持的时钟源有: DCOCLK:内部数字控制振荡器,Internal digitally contrlled oscillator.所有 ...
随机推荐
- 自定义RBAC(4)
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 前面把RBAC的权限系统设计过程都讲清楚了,现在就来实现它.大致分这么几个步骤: 1.先定义出完整的权限系统表结构: 2.实现Entity.Da ...
- 如何通过Java应用程序将Word转为Excel
平时在工作中,很多小伙伴会习惯性地将文件保存为Word文档格式,但有时会发现某些文件如果保存成Excel表格可能会更好地呈现.例如有的文本在Word文本中不如在Excel工作表编辑计算方便,所以要把W ...
- 已完成 10000 多次提交,Solon Java Framework v1.12.1 发布
一个更现代感的 Java 应用开发框架:更快.更小.更自由.没有 Spring,没有 Servlet,没有 JavaEE:独立的轻量生态.主框架仅 0.1 MB. @Controller public ...
- python进阶之路9文件的处理方法
内容回顾 字典内置方法 1.类型转换 dict() 2.重要操作 get() d[key] = values 常用 pop() update() 键存在则修改键值对 键不存在则新增键值对 fromke ...
- P1005 [NOIP2007 提高组] 矩阵取数游戏
题目传送门 前言 今天依旧是不写高精的一天呢!(是的,这位作者又只拿了开 \(LL\) 的 \(\color{yellow}{60}\) 分) 思路描述 看到数据 \(n,m \le 80(30)\) ...
- 异常概念&异常体系-异常分类
异常概念&异常体系 异常,就是不正常的意思.在生活中:医生说,你的身体某个部分有异常,该部位和正常相比有点不同,该部位的功能将受影响,在程序中的意思就是: 异常:指的是程序在执行过程中,出现的 ...
- 《深入理解Java虚拟机》第三章读书笔记(三)——经典垃圾回收器
系列文章目录和关于我 一丶概述 上图展示了 经典的垃圾回收器,其中Serial,ParNew,Parallel Scavenge(途中的Parallel) 作用在新生代Serial Old CMS,P ...
- OpenStack命令行参考
OpenStack命令行参考 hello,大家好,这里是费冰.在使用OpenStack的过程中,固然我们可以通过 web 页面完成绝大多数的操作,但作为管理人员,不能不知晓 OpenStack 命令行 ...
- KingbaseES数据库备份初始化错误处理
KingbaseES使用sys_backup.sh脚本init初始化配置文件常见错误处理: sys_backup.sh脚本按照如下顺序寻找初始化配置文件: [kingbase@postgres ~]$ ...
- Task记录2.ContinueWith 延续任务,等待上一个任务执行完毕
Task.Run(() => {for (int i = 0; i < 20; i++) { Console.WriteLine(i); } } }).ContinueWith(NewTa ...