数字设计--门控时钟与时钟切换

门控时钟(ICG)

使用门控时钟的原因

芯片功耗组成中,大部分是由时钟树消耗掉的。因为这些时钟树在系统中具有最高的切换频率,而且有很多时钟buffer,并且为了最小化时钟延时,它们通常具有很高的驱动强度。此外,即使输入和输出保持不变,接收时钟的触发器也会消耗一定的功耗。而且这些功耗主要是动态功耗

那么减少时钟网络的功耗消耗,最直接的办法就是如果不需要时钟的时候,就把时钟关掉。这种方法就是大家熟悉的门控时钟:clock gating。

门控时钟的结构

与门门控

实现门控时钟最直接的方法,即不需要时钟的时候关掉时钟,就是操作,我们只需要把enable使能信号和CLK时钟进行操作就可以了,电路图如下:

image

这种直接将控制EN信号和时钟CLK进行与操作完成门控的方式,可以完成EN为0时,时钟被关掉。但是同时带来另外一个很大的问题:毛刺

image

如上图所示,EN是不受控制的,随时可能跳变,这样纯组合输出GCLK就完全可能会有毛刺产生。时钟信号上产生毛刺是很危险的。虽然采用这种门控方式最直接,但在实际中很少采用。

所以我们需要改进电路,为了使门控时钟不产生毛刺,我们必须对EN信号进行处理,使其在CLK的高低电平期间保持不变,或者说EN的变化就是以CLK为基准的

1 很自然的我们会想到触发器,只要把EN用CLK寄存一下,那么输出就是以CLK为基准的;

2 其实还有一种办法是锁存器,把EN用锁存器锁存的输出,也是以CLK为基准的。

锁存器门控

image

时序

image

可以看到,当CLK为低电平时,锁存器输出EN,当CLK升为高电平时,锁存器锁存输入的EN。因为后面与门只有在CLK为高电平时才可能输出高,所以只有在CLK为高的时候,GCLK才可能会输出高,并且在CLK高电平时,锁存器输出不变,这样就能消除EN带来的毛刺。

这是因为D锁存器是电平触发,在clk=1时,数据通过D锁存器流到了Q;在Clk=0时,Q保持原来的值不变。

虽然达到了我们消除毛刺的目的,但是这个电路还有两个缺点:

  1. 如果在电路中,锁存器与门相隔很远,到达锁存器的时钟与到达与门的时钟有较大的延迟差别(也有可能锁存器输出先到,也有可能时钟先到),则仍会出现毛刺。

  2. 如果在电路中,时钟使能信号距离锁存器很近,可能会不满足锁存器的建立时间,会造成锁存器输出出现亚稳态。

如下图分析所示:

image

上述的右上图中,B点的时钟比A时钟迟到,并且Skew>delay,这种情况下,产生了毛刺。为了消除毛刺,要控制Clock Skew,使它满足Skew<Latch delay(也就是锁存器的clk-q的延时)。

上述的右下图中,B点的时钟比A时钟早到,并且\(|Skew| > EN_{setup_{(D->Q)}}\),这种情况下,也产生了毛刺。为了消除毛刺,要控制Clock Skew,使它满足\(|Skew|<EN_{setup_{(D->Q)}}\)

寄存器门控

用寄存器来寄存 EN 信号再与上 CLK 得到GCLK

image

由于DFF输出会delay一个周期,所以除非CLKB上升沿提前CLKA很多,快半个周期,才会出现毛刺,而这种情况一般很难发生。CLKB也可能比CLKA晚到,这种情况是不会出现毛刺的。

当然,如果第一个D触发器不能满足setup时间,还是有可能产生亚稳态。

门控寄存器存在时钟翻转,可能产生功耗,但是他控制着后面的时钟通断,当用不到时钟时,后面的寄存器(或寄存器组)将没有时钟,降低了功耗。

门控时钟的选择

那么到底采用哪一种门控时钟的结构呢?是锁存结构还是寄存结构呢?通过分析,我们大概会选择寄存器结构的门控时钟,这种结构比锁存器结构的问题要少,只需要满足寄存器的建立时间就不会出现问题。

那么实际中是这样么?答案恰恰相反,SOC芯片设计中使用最多的却是锁存结构的门控时钟

原因是:在实际的SOC芯片中,要使用大量的门控时钟单元。所以通常会把门控时钟做出一个标准单元,有工艺厂商提供。那么锁存器结构中线延时带来的问题就不存在了,因为是做成一个单元,线延时是可控和不变的。而且也可以通过挑选锁存器和增加延时,总是能满足锁存器的建立时间,这样通过工艺厂预先把门控时钟做出标准单元,这些问题都解决了。

那么用寄存器结构也可以达到这种效果,为什么不用寄存器结构呢?那是因为面积!一个DFF是由两个D锁存器组成的,采用D锁存器组成门控时钟单元,可以节省一个锁存器的面积。当大量的门控时钟插入到SOC芯片中时,这个节省的面积就相当可观了。

所以,我们在工艺库中看到的标准门控时钟单元就是锁存结构了:

image

当然,这里说的是SOC芯片中使用的标准库单元。如果是FPGA或者用RTL实现,个人认为还是用寄存器门控加上setup约束来实现比较稳妥。

RTL中的门控时钟

通常情况下,时钟树由大量的缓冲器和反相器组成,时钟信号为设计中翻转率最高的信号,时钟树的功耗可能高达整个设计功耗40%。

加入门控时钟电路后,由于减少了时钟树的翻转,节省了翻转功耗。同时,由于减少了寄存器时钟引脚的翻转行为,寄存器的内部功耗也减少了。采用门控时钟,可以非常有效地降低设计的功耗,一般情况下能够节省20%~60%的功耗。

那么RTL中怎么才能实现门控时钟呢?答案是不用实现。现在的综合工具比如DC会自动插入门控时钟。如下图所示:

image

这里有两点需要注意:

1. 插入门控时钟单元后,上面电路中的MUX就不需要了,如果数据D是多bit的(一般都是如此),插入CG后的面积可能反而会减少

2. 如果D是单bit信号,节省的功耗就比较少,但是如果D是一个32bit的信号,那么插入CG后节省的功耗就比较多了。

这里的决定因素就是D的位宽了,如果D的位宽很小,那么可能插入的CG面积比原来的MUX大很多,而且节省的功耗又很少,这样得不偿失。只有D位宽超过了一定的bit数后,插入CG的收益就比较大。

那么这个临界值是多少呢?不同的工艺可能不一样,但是DC给的默认值是3.

也就是说,如果D的位宽超过了3bit,那么DC就会默认插入CG,这样综合考虑就会有收益。

门控时钟的RTL描述

虽然现在综合工具可以自动插入门控时钟,但是如果编码风格不好,也不能达到自动插入CG的目的。比较下面两种RTL写法:

image

左边的RTL代码能够成功的综合成自动插入CG的电路;

右边的RTL不能综合成插入CG的电路;

右边电路在d_valid为低时,d_out也会一直变化,其实没有真正的数据有效的指示信号(d_out设置为0,也认为这个输出在变化),所以综合不出来插入CG的电路。

需要注意的是,有的前端设计人员,为了仿真的时候看的比较清楚,很容易会写成右边的代码,这样不仅不能在综合的时候自动插入CG来减少功耗;而且增加了d_out的翻转率,进一步增加了功耗。

在不用的时候把数据设成0并不能减少功耗,保持数据不变化才能减少toggle,降低功耗!

如果在第一种编码风格中再加一句else信号保持不变,DC仍然能自动插入clock gating。

时钟切换

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

直接时钟切换

可以通过选择逻辑直接对时钟进行切换。

image

assign clk_out = sel_clk ? clk1 : clk2;

这种方法的问题在于会产生毛刺,如果在clk1高电平时进行时钟切换就有可能导致毛刺的出现。

image

clk1为高电平,在切换时clk2为低电平,切换时输出时钟就会出现一段低电平,之后是clk2的高电平,输出出现了毛刺。

glitch free时钟切换电路

为了避免毛刺可以通过glitch free时钟切换电路进行时钟的切换。

image

在时钟选择信号和时钟输出之间插入由clk1和clk0下降沿驱动的寄存器。一开始两个寄存器初始化输出为0,如果select为1,Q1在clk1下降沿到来时输出为1,Q1N输出为0,在clk0下降沿到来时,Q0输出为0,Q0N输出为1,这时相当于选择clk1输出。当select由1变为0时,在这一时刻,Q1N输出仍为0,Q0N输出仍为1,DFF1输入D1为0,DFF0输入D0为0,当clk1下降沿到来时,DFF1输出Q1为0,Q1N为1,这时DFF0输入D0为1,当clk0下降沿到来时,DFF0输出Q0为1,Q0N为0,这时完成了对clk0的选择输出。

触发器下降沿触发的原因在于如果是在高电平时做切换,很容易造成高电平被切掉一段变成一个毛刺,下降沿触发可以保证时钟在低电平时进行切换,这时保证了时钟输出没有毛刺。

两个寄存器一开始要初始化为0,如果一开始初始化为1,这时相当于两个时钟都被选通,如果复位的时间比较长,则一直输出两个时钟相或的结果,这肯定不是我们想看到的。一开始初始化为0,保证这时输出时钟为0。

module test_clk_switch(input clk0,input clk1,input rst_n,input select,output clk_out);reg clk1_out;reg clk0_out;always @(negedge clk0 or negedge rst_n) if(!rst_n)clk0_out <= 1'b0;elseclk0_out <= ~select & ~clk1_out;always @(negedge clk1 or negedge rst_n)if(!rst_n)clk1_out <= 1'b0;elseclk1_out <= select & ~clk0_out;assign clk_out = (clk1_out & clk1) | (clk0_out & clk0);endmodule

testbench

module test_clk_switch_sim();reg clk0;reg clk1;reg select;reg rst_n;wire clk_out;initialbegin#0 clk0 = 1'b0;forever #5 clk0 = ~clk0;end   initialbegin#0 clk1 = 1'b0;forever #18 clk1 = ~clk1;end   initialbegin#0 select = 1'b0;#42 select = 1'b1;#200 select = 1'b0;end   initialbegin#0 rst_n = 1'b1;#1 rst_n = 1'b0;#5 rst_n = 1'b1;endtest_clk_switch test_1(.clk0(clk0),.clk1(clk1),.rst_n(rst_n),.select(select),.clk_out(clk_out));   endmodule

仿真结果

image

可以看到

当select变化时,先经过原时钟的下降沿再经过要切换时钟的下降沿之后输出要切换的时钟。因为中间经过了原时钟的下降沿后保证了原时钟的一个脉冲,再经过要切换时钟的下降沿保证了两个时钟的高电平不会有重叠的部分,保证了不会产生毛刺。

这个电路概念上是对的,但有明显的瑕疵,如果 Select 相对于 clk1, clk0是完全异步的,电路中的两个触发器在Select变化时会有亚稳态的可能性。解决这个问题的方法很简单,把图中的单个寄存器换成两级寄存器组成的同步器就可以了。

image

对于每个时钟,两个寄存器,第一个寄存器时钟的上升沿触发,第二个寄存器时钟的下降沿触发。

clk1和clk0的第一个寄存器上升沿有效,用于削弱亚稳态出现的可能性,第二个寄存器下降沿有效用于时钟的切换。

module test_clk_switch_1(input clk0,input clk1,input rst_n,input select,output clk_out);reg clk1_out_1,clk1_out_2;reg clk0_out_1,clk0_out_2;always @(posedge clk1 or negedge rst_n)if(!rst_n)clk1_out_1 <= 1'b0;elseclk1_out_1 <= ~select & ~clk0_out_2;always @(negedge clk1 or negedge rst_n)if(!rst_n)clk1_out_2 <= 1'b0;elseclk1_out_2 <= clk1_out_1;always @(posedge clk0 or negedge rst_n)if(!rst_n)clk0_out_1 <= 1'b0;elseclk0_out_1 <= select & ~clk1_out_2;always @(negedge clk0 or negedge rst_n)if(!rst_n)clk0_out_2 <= 1'b0;elseclk0_out_2 <= clk0_out_1;         assign clk_out = (clk1 & clk1_out_2) | (clk0 & clk0_out_2);               endmodule

testbench

module test_clk_switch_sim();reg clk0;reg clk1;reg select;reg rst_n;wire clk_out;initialbegin#0 clk0 = 1'b0;forever #5 clk0 = ~clk0;end   initialbegin#0 clk1 = 1'b0;forever #18 clk1 = ~clk1;end   initialbegin#0 select = 1'b0;#42 select = 1'b1;#200 select = 1'b0;end   initialbegin#0 rst_n = 1'b1;#1 rst_n = 1'b0;#5 rst_n = 1'b1;endtest_clk_switch_1 test_1(.clk0(clk0),.clk1(clk1),.rst_n(rst_n),.select(select),.clk_out(clk_out));   endmodule

仿真结果

image

可以看到

当select变化时,先经过原时钟的一个上升沿和下降沿再经过要切换时钟的一个上升沿和一个下降沿之后输出要切换的时钟。

如果觉得用一个寄存器来减少亚稳态出现的概率有点不够用,可以在一开始打两拍,即再插入一个上升沿驱动的寄存器。

image

如上图,对于每个时钟,有三个寄存器,前两个寄存器由上升沿驱动,用来处理亚稳态,第三个寄存器用来时钟切换。

我们前面提到了门控时钟(ICG),那能不能将最后时钟输出前的与门替换为ICG呢?当然可以

image

但是换成ICG后如果时钟的初始值时高电平,电路可能会出问题,因为ICG内部存在一个低电平时钟触发的锁存器,当一开始时钟的电平为高电平时,锁存器这时没有初始数据输出,所以输出信号为高阻态x。为了避免上述ICG未初始化引起的问题,使用ICG搭时钟切换电路时,系统设计中要考虑加一个时钟初始为0的要求。

上面几种电路都只能在时钟正常跑起来的情况下完成切换。如果当前选中的时钟停了,选择信号无法通过由当前时钟驱动的两级DFF,也就无法实现切换了。

时钟停止属于系统级错误,需要在系统设计找到解决方案,这里就不赘述了。


参考
(3条消息) 18.门控时钟_薄荷茶哈哈哈的博客-CSDN博客_门控时钟
(3条消息) Verilog设计(一):时钟门控_风中少年01的博客-CSDN博客_门控时钟
芯片设计进阶之路——门控时钟 - 知乎 (zhihu.com)
(3条消息) 数字SOC设计之低功耗设计入门(五)——RTL级低功耗设计(续)_简单同学的博客-CSDN博客
ICG
为什么ICG Cell中使用锁存器(Latch),而不使用触发器(Flip Flop)? - 知乎 (zhihu.com)
(4条消息) Clock Gating cell 与 Integrated Clock Gating cell(ICG)_zhenhuagege的博客-CSDN博客_cell clock gating
ICG的结构是怎么样的,工作原理是什么啊?和使用MUX相比有什么优点?[已解决] - 后端讨论区 - EETOP 创芯网论坛 (原名:电子顶级开发网) -
ICG与low power设计 - 知乎 (zhihu.com)
IMPL20. ICG应用浅析 - 知乎 (zhihu.com)
数字IC设计面试--阿里平头哥--门控时钟(ICG) (aisoutu.com)
(4条消息) Integrated Clock Gating (ICG)_kevindas的博客-CSDN博客_芯片icg
时钟切换
Glitch Free时钟切换技术 - 知乎 (zhihu.com)
(4条消息) 用Verilog实现时钟切换电路_wangn1633的博客-CSDN博客_verilog时钟切换
(4条消息) Verilog学习心得之一-----时钟无缝切换_poirot12的博客-CSDN博客_verilog时钟切换
时钟切换(1) - jake的日志 - EETOP 创芯网论坛 (原名:电子顶级开发网) -
时钟切换 (2) - jake的日志 - EETOP 创芯网论坛 (原名:电子顶级开发网) -
FPGA中多时钟切换(无毛刺):通过代码的方式 - 小翁同学 - 博客园 (cnblogs.com)
(4条消息) 时钟分频与时钟切换_Zokion的博客-CSDN博客_soc设计
5.4 Verilog 时钟切换 | 菜鸟教程 (runoob.com)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/739448.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ComfyUI进阶篇:ComfyUI核心节点(二)

ComfyUI核心节点(二) 前言: 学习ComfyUI是一场持久战。当你掌握了ComfyUI的安装和运行之后,会发现大量五花八门的节点。面对各种各样的工作流和复杂的节点种类,可能会让人感到不知所措。在这篇文章中,我们将用通俗易懂的语言对ComfyUI的核心节点进行系统梳理,并详细解释每…

题目集7~8

由于个人原因,最后两次题目集未提交,对自己的放纵感到愧疚,后期的补练我也会抽出时间完成这两道题 经过分析,题目集7,是在前面的基础上加上了一个新概念:互斥开关,以及模拟一种受控窗帘, 在我的想法,互斥开关便可当作两个普通开关去完成电路,窗帘则是新增一个用电器。…

EtherCAT转Profinet网关配置说明第一讲:配置软件安装及介绍

网关XD-ECPNS20为EtherCAT转Profinet协议网关,使EtherCAT协议和Profinet协议两种工业实时以太网网络之间双向传输 IO 数据。适用于具有EtherCAT协议网络与Profinet协议网络跨越网络界限进行数据交换的解决方案。 网关XD-ECPNS20为EtherCAT转Profinet协议网关,使EtherCAT协议…

4、flask-项目拆分

项目的拆分其实就是将app.py中的工作拆分开来、类似Django一样、每个项目都把路由模板和试图函数分开写 app.py # 路由 + 视图函数from flask import Blueprint from models import *#蓝图 # 创建蓝图对象 # 第一个参数:蓝图的名字 # 第二个参数:蓝图的包名 blue = Blueprin…

2-SAT 问题

2-SAT 问题 模型有 \(n\) 个布尔类型的变量 \(x_1, x_2, \ldots, x_n\),有 \(m\) 条限制形如 \(x_i \space [\operatorname{or}/\operatorname{and}]\space x_j=[1/0]\). 求一组符合要求的解。核心问题只需要考虑有没有解。 对于每个变量都只有两种取值:\(0/1\),那么把每…

坚果云与floccus实现Chrome书签国内跨设备、跨平台同步

本文介绍基于floccus插件与坚果云协同使用的方法,对浏览器的书签进行实时在线同步的操作~本文介绍基于floccus插件与坚果云协同使用的方法,对浏览器的书签进行实时在线同步的操作。在工作与学习中,我们时常希望在不同浏览器之间实现书签的同步;而一些传统的浏览器书签同步方…

性能监控调优

1.命令行工具 1.1 jps 查看系统JVM进程 jps [options] [hostid]optionhostid:省略则本机,监控远程需要安装jstatd1.2 jstat 查看JVM统计信息 jstat -[-t] [-h] [[]]option-t:加程序运行时间 [-h]:输出设定行数加表头信息 :查询间隔时间 count:查询总次数 结果:当ou上涨趋…

【第7个渗透靶机项目】 DerpNStink

Hack it 信息搜集 发现主机 nmap 192.168.0.17 -sS -sV -A -T5 全面扫描一下,有点有用信息访问一下但是没有用。 访问一下http服务查看源代码,发现有文件泄露下面还有个flag查看info.txt。<-- @stinky,确保使用本地 dns 更新您的主机文件,以便可以在新的 derpnstink 博客…

Linux运维工程师推荐学习的开发语言

前言:会开发的运维和不会开发的运维可以说是两个世界的运维。 个人推荐python和go,前者可以做自动化运维,后者可以深挖k8s;最近就不先演示运维服务技术的部署和架构搭建了,在深挖自动化运维,为了让现在的工作更加高效和便捷。如果有需要了解的运维服务技术,可以评论说出…

2、flask-run启动参数详解

app.py 这里 app.run(True, port=5001, host=0.0.0.0) from flask import Flask#创建flask应用对象 app = Flask(__name__)@app.route(/) # 路由 def hello_world(): # 视图函数return Hello World! # 响应给前端#添加路由和视图函数 @app.route(/index/) def index():…

从零学习的JAVAday1~day7

作为一个刚要迈入大二的预备程序员,已经学习过了c语言和c++的部分知识,在暑假期间满怀期待的开始Java的学习,希望一个暑假可以对Java的了解加深一些。 学习Java首先要学习windows电脑的cmd命令: 同时点击键盘上面的win+r键输入cmd即可进入默认的cmd面版,然后我们就可以输入…

面试官:Java线程可以无限创建吗?

哈喽,大家好🎉,我是世杰。 ⏩本次给大家介绍一下操作系统线程和Java的线程以及二者的关联1. 面试连环callJava线程可以无限创建吗? Java线程和操作系统线程有什么关联? 操作系统为什么要区分内核态和用户态?⏩要想解答这些问题,我们要先从操作系统线程开始说起,让我们…