通常情况下,时钟树由大量的缓冲器和反相器组成。而时钟信号为设计中翻转率最高的信号,时钟树的功耗可高达整个设计功耗 30%。加入门控时钟(clock gating)电路,可减少时钟树的开关行为,能节省开关功耗。同时,时钟引脚开关行为的减少,寄存器的内部功耗也会减少。所以,采用门控时钟,可以有效地降低功耗。
实现原理
通俗来讲,当模块或触发器不工作时,将时钟关闭而不影响正常功能的逻辑,可以称之为门控时钟逻辑。此时时钟并不是一直存在的,所以可以形象的称之为门控时钟。

实现门控时钟的方法主要有以下 3 种。
1、使用与逻辑
最简单的方法,是直接将时钟使能控制(门控)信号与时钟做"与"逻辑。
例如对一块 ram 的时钟进行该操作,代码如下:
// use and-logic
module clkgate_basic
(
input clk ,
input clken ,
input rstn ,
input wr_en ,
input [3:0] addr ,
input [7:0] data ,
output [7:0] q
);
//clk gate
wire clk_gate = clk & clken ;
ram #(4, 8)
u1_ram16x8
(
.CLK (clk_gate),
.A (addr),
.D (data),
.EN (clken),
.WR (wr_en),
.Q (q));
endmodule
ram 模型如下:
module ram
#( parameter AW = 2 ,
parameter DW = 3 )
(
input CLK ,
input [AW-1:0] A ,
input [DW-1:0] D ,
input EN ,
input WR , //1 for write and 0 for read
output reg [DW-1:0] Q
);
parameter MASK = 3 ;
reg [DW-1:0] mem [0:(1<<AW)-1] ;
always @(posedge CLK) begin
if (EN && WR) begin
mem[A] <= D ;
end
else if (EN && !WR) begin
Q <= mem[A] ;
end
end
endmodule
testbench 代码如下:
`timescale 1ns/1ns
module test ;
//signals declaration
reg rstn ;
reg clk ;
reg clken ;
reg wr_en ;
reg [3:0] addr ;
reg [7:0] data ;
wire [7:0] q ;
initial begin
rstn = 0 ;
#7 rstn = 0 ;
end
always begin
#50 clk = 0 ;
#50 clk = 1 ;
end
//data logic
initial begin
clken = 0 ;
wr_en = 0 ;
addr = 4'h3 ;
data = 8'h31 ;
# 53 ;
//(1) normal write and read
clken = 1 ;
wr_en = 1 ;
repeat(9) begin
@(negedge clk) ;
data = data + 1 ;
addr = addr + 1 ;
end
@(negedge clk) ;
clken = 0 ;
wr_en = 0 ;
//read
#211;
addr = 4'h3 ;
clken = 1 ;
repeat(9) begin
@(negedge clk) ;
addr = addr + 1 ;
end
@(negedge clk) ;
//end
clken = 0 ;
end // initial begin
clkgate_basic u_ram_clkgate
(
.clk (clk),
.clken (clken),
.rstn (rstn),
.wr_en (wr_en),
.addr (addr),
.data (data),
.q (q)
);
//simulation finish
always begin
#100;
if ($time >= 10000) begin
#1 ;
$finish ;
end
end
endmodule
抓取 ram 端口信号,测试结果如下。
如图可知在读、写操作中间,ram 时钟有一段一直为 0 的时刻。时钟在 ram 没有工作的时候不会翻转,实际中也会减少很多的功耗。

该方法缺点也非常明显。由于时序或抖动的原因,时钟使能信号与时钟进行"与"逻辑后,容易产生毛刺,会对数字电路产生严重影响。
在 testbench 中对时钟使能信号进行非理想的模拟,加入如下仿真代码:
//(2) jitter at the end of read
#985;
addr = 4'h3 ;
clken = 1 ;
repeat(9) begin
@(negedge clk) ;
addr = addr + 1 ;
end
@(negedge clk) ;
clken = 0 ;
#20 clken = 1 ;
#21 clken = 0 ;
#31 clken = 1 ;
#13 clken = 0 ;
读 ram 的仿真结果如下。

由图可知,因为信号 clken 的异步或抖动问题,导致输入到 ram 的时钟已经出现了毛刺。地址为 0x3 的数据被遗漏(和使能信号时序有关),地址为 0xC 的数据读了 2 次。显然该门控时钟的逻辑设计非常的危险。
为解决此类问题,需要使用 latch 结构来消除毛刺。
2、使用 latch
在 《Verilog 教程》章节《6.5 Verilog 避免 Latch》中讲到,数字设计中应当避免 Latch 的产生,但 clock gating 是个例外。所以在进行时序分析时,不用关心 clock gating 部分产生的 Latch。
使用 latch 消除门控时钟毛刺的电路图如下所示。
在时钟下降沿对时钟使能信号进行锁存,并保持一个时钟周期内不变。锁存后的信号再与时钟进行"与"逻辑操作,可将门控时钟中的毛刺消除掉。

将仿真例程钟直接"与"操作的门控时钟逻辑部分,改写为使用 latch 逻辑,修改如下:
//(2) using latch
reg en_latch ;
always @(*) begin
if (!clk) begin
en_latch = clken ;
end
end
wire clk_gate = clk & en_latch ;
仿真结果如下。
虽然地址为 0x3 的数据仍然被遗漏(和使能信号时序有关),但 ram 的时钟已经是正常时钟,不再出现毛刺(标黄的 CLK 信号)。

3、使用标准单元库
虽然使用 latch 可以解决门控时钟毛刺的出现,但是时序也需要严格的约束。
FPGA 或 IC 设计时,综合库中往往会有集成门控逻辑单元。此类门控逻辑单元经过了大量的更新迭代和验证,使用起来更加的方便、安全。
因此一般情况下,门控时钟的设计也都会直接调用专用的集成门控逻辑单元。调用方式和基本的与门、缓冲器等基本单元类似,直接例化即可。
合理的使用门控时钟逻辑,对电路时钟进行控制,也会有效的减少功耗。
1、手动 gating
增加时钟使能信号,人为的控制模块工作时钟的有无。
模块工作时,将使能信号有效,时钟打开;模块空闲时,将使能信号无效,时钟关闭,节省功耗。
上一节的仿真设计,就可以看做是手动 gating 的例子。ram 读写时,使能信号为高,ram 时钟打开,ram 开始工作;使能信号为低时,ram 不工作,此时无输入时钟。
2、自动 gating
模块在工作时,可以自动检测自己的工作状态,并输出一个 busy(忙碌) 信号。外部可以通过该指示信号,对模块内部的部分逻辑进行时钟门控,来减少时钟的翻转,达到自动 gating 的控制。
与手动 gating 不同的是,这些模块在工作时,会有短暂的空闲状态。自动 gating 就是要在这短暂的空闲状态时间内关闭掉无用的时钟,而不是像手动 gating 直接关闭掉整个模块的时钟,否则该模块就不能再正常工作。
例如 uart 在完成一次传输数据时会有一段空闲的状态,此时可将一些 fifo 逻辑、波特率产生逻辑等模块的时钟自动关闭。
例如在包含 cpu 的设计中,可加入检测 bus 总线空闲状态的逻辑,自动控制开关 bus 总线的时钟,以此降低功耗。
限于篇幅,这里先不再举例仿真。
3、自动插入 gating
当 RTL 设计完成之后进行逻辑综合时,编译器也会对代码的逻辑进行自动优化,这就包括将一些触发器的时钟端进行 gating。例如一个带使能端的同步 D 触发器的 RTL 描述如下:
//(2) Flip-Flop with enable port
always @(posedge CLK) begin
if (EN) begin
Q = D ;
end
end
其 RTL 前级仿真如下图所示:

综合后的仿真波形往往会如下图所示:

对比可知,综合后已经没有了 EN 信号,时钟(CP 端)经过 clock gating 后也不是一直存在。既保证了逻辑的正确性,又减少了时钟翻转,降低了功耗。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
我在我的项目中有一个用户和一个管理员角色。我使用Devise创建了身份验证。在我的管理员角色中,我没有任何确认。在我的用户模型中,我有以下内容:devise:database_authenticatable,:confirmable,:recoverable,:rememberable,:trackable,:validatable,:timeoutable,:registerable#Setupaccessible(orprotected)attributesforyourmodelattr_accessible:email,:username,:prename,:surname,:
我正在尝试创建密码规则来设计可恢复的密码更改。我通过passwords_controller.rb做了一个父类(superclass),但我需要在应用规则之前检查用户角色,但我所拥有的只是reset_password_token。 最佳答案 假设您的模型是用户:User.with_reset_password_token(your_token_here)Source 关于ruby-on-rails-设计通过reset_password_token获取用户,我们在StackOverflow
我已经使用Apartment设置了一个Rails5应用程序(1.2.0)和Devise(4.2.0)。由于某些DDNS问题,应用只能在app.myapp.com下访问(请注意子域app)。myapp.com重定向到app.myapp.com。我的用例是每个注册该应用的用户(租户)都应该通过他们的子域(例如tenant.myapp.com)访问他们的特定数据。用户不应限定在其子域内。基本上应该可以从任何子域登录。重定向到租户的正确子域由ApplicationController处理。根据Devise标准,登录页面位于app.myapp.com/users/sign_in。这就是问题开始的
我在关注RyanbatesRailsCast的devise和omniauth(第235集-devise-and-omniauth-revised)。当我尝试使用Twitter登录时,标题中不断出现错误。defself.new_with_session(params,session)ifsession["devise.user_attributes"]new(session["devise.user_attributes"],without_protection:true)do|user|user.attributes=paramsuser.valid?end完整跟踪:C:/Ruby20
我为Devise用户和管理员提供了不同的模型。我也在使用Basecamp风格的子域。除了我需要能够以用户或管理员身份进行身份验证的一些Controller和操作外,一切都运行良好。目前我有authenticate_user!在我的application_controller.rb中设置,对于那些只有管理员才能访问的Controller和操作,我使用skip_before_filter跳过它。不幸的是,我不能简单地指定每个Controller的身份验证要求,因为我仍然需要一些Controller和操作才能被用户或管理员访问。我尝试了一些方法都无济于事。看来,如果我移动authentica
我在我的Rails应用程序中使用设计。我在租户庄园中配置了它,其中帐户/session的范围限定为子域。例如:http://subdomain1.example.com/http://subdomain2.example.com/...这很好用,但我想为“super管理员”添加一个子域,允许这些用户导航到所有其他子域而无需重新验证。这将是这样的:http://admin.example.com/是否可以自定义仅在管理子域上生成的cookie,以便它在所有其他子域上都有效? 最佳答案 Cookie域的定义越不具体,它们的包容性就越大,