时钟切换电路(无毛刺)——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.所有 ...
随机推荐
- flutter系列之:如丝般顺滑的SliverAppBar
目录 简介 SliverAppBar详解 SliverAppBar的使用 总结 简介 对于一个APP来说,肯定会有一个AppBar,这个AppBar一般包含了APP的导航信息等.虽然我们可以用一个固定 ...
- 《HTTP权威指南》– 1.HTTP概述
HTTP的概念 HTTP : Hypertext Transfer Protocol 超文本传输协议 因特网上有数千种不同的数据类型,HTTP仔细地给每种要通过Web传输的对象都打上了名为MIME类型 ...
- Linux 下使用Docker 安装 LNMP环境 超详细
首先在阿里云购买了一台服务器 选择了华南-深圳地区 操作系统选用了 CentOS8.0 64位 1. 初始化账号密码 登陆xshell,开始装Docker 一.安装docker 1.Docker 要求 ...
- Burp Suite进阶
1.Scanner Burp Scanner主要用于自动检测Web系统的各种漏洞. 首先,确认Burp Suite正常启动并完成浏览器代理的配置.然后进入Burp Proxy,关闭拦截代理功能,快速浏 ...
- AcWing341. 洛谷P1073, NOIP2009 最优贸易
AcWing题目传送门 洛谷题目传送门 题目大意 \(~~~~~~\)一个投机倒把的奸商想要通过城市不太健全的贸易系统坑点钱,任意城市都可以买入或者卖出水晶球,他想尽量在便宜的城市买入,在贵的城市卖出 ...
- [C++]C++11:Function与Bind
std::function 它是函数.函数对象.函数指针.和成员函数的包装器,可以容纳任何类型的函数对象,函数指针,引用函数,成员函数的指针. 以统一的方式处理函数.函数对象.函数指针.和成员函数. ...
- P1278 单词游戏【题解】(状压dp)
单词游戏 题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍 ...
- django框架之drf:2、restful规范,序列、反序列化,drf安装及使用(django原生接口及drf接口编写)
Django之drf 一.restful规范 1.概念 REST全称是Representational State Transfer,中文意思是表述:表征性状态转移,它首次出现在2000年Roy ...
- Random概述和基本使用-Random生成指定范围的随机数
Random概述和基本使用 什么是Random类 此类的实例用于生成伪随机数. 例如,以下代码使用户能够得到一个随机数: Random r = new Random(); int i = r.next ...
- Vue3源码阅读梳理
简单代码例子 const { createApp, defineComponent, computed, watch, ref, reactive, effect } = Vue const app ...