通常情況下,時(shí)鐘樹(shù)由大量的緩沖器和反相器組成。而時(shí)鐘信號(hào)為設(shè)計(jì)中翻轉(zhuǎn)率最高的信號(hào),時(shí)鐘樹(shù)的功耗可高達(dá)整個(gè)設(shè)計(jì)功耗 30%。加入門(mén)控時(shí)鐘(clock gating)電路,可減少時(shí)鐘樹(shù)的開(kāi)關(guān)行為,能節(jié)省開(kāi)關(guān)功耗。同時(shí),時(shí)鐘引腳開(kāi)關(guān)行為的減少,寄存器的內(nèi)部功耗也會(huì)減少。所以,采用門(mén)控時(shí)鐘,可以有效地降低功耗。
通俗來(lái)講,當(dāng)模塊或觸發(fā)器不工作時(shí),將時(shí)鐘關(guān)閉而不影響正常功能的邏輯,可以稱(chēng)之為門(mén)控時(shí)鐘邏輯。此時(shí)時(shí)鐘并不是一直存在的,所以可以形象的稱(chēng)之為門(mén)控時(shí)鐘。
實(shí)現(xiàn)門(mén)控時(shí)鐘的方法主要有以下 3 種。
最簡(jiǎn)單的方法,是直接將時(shí)鐘使能控制(門(mén)控)信號(hào)與時(shí)鐘做"與"邏輯。
例如對(duì)一塊 ram 的時(shí)鐘進(jìn)行該操作,代碼如下:
// 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 端口信號(hào),測(cè)試結(jié)果如下。
如圖可知在讀、寫(xiě)操作中間,ram 時(shí)鐘有一段一直為 0 的時(shí)刻。時(shí)鐘在 ram 沒(méi)有工作的時(shí)候不會(huì)翻轉(zhuǎn),實(shí)際中也會(huì)減少很多的功耗。
該方法缺點(diǎn)也非常明顯。由于時(shí)序或抖動(dòng)的原因,時(shí)鐘使能信號(hào)與時(shí)鐘進(jìn)行"與"邏輯后,容易產(chǎn)生毛刺,會(huì)對(duì)數(shù)字電路產(chǎn)生嚴(yán)重影響。
在 testbench 中對(duì)時(shí)鐘使能信號(hào)進(jìn)行非理想的模擬,加入如下仿真代碼:
//(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 的仿真結(jié)果如下。
由圖可知,因?yàn)樾盘?hào) clken 的異步或抖動(dòng)問(wèn)題,導(dǎo)致輸入到 ram 的時(shí)鐘已經(jīng)出現(xiàn)了毛刺。地址為 0x3 的數(shù)據(jù)被遺漏(和使能信號(hào)時(shí)序有關(guān)),地址為 0xC 的數(shù)據(jù)讀了 2 次。顯然該門(mén)控時(shí)鐘的邏輯設(shè)計(jì)非常的危險(xiǎn)。
為解決此類(lèi)問(wèn)題,需要使用 latch 結(jié)構(gòu)來(lái)消除毛刺。
在 《Verilog 教程》章節(jié)《Verilog 避免Latch》中講到,數(shù)字設(shè)計(jì)中應(yīng)當(dāng)避免 Latch 的產(chǎn)生,但 clock gating 是個(gè)例外。所以在進(jìn)行時(shí)序分析時(shí),不用關(guān)心 clock gating 部分產(chǎn)生的 Latch。
使用 latch 消除門(mén)控時(shí)鐘毛刺的電路圖如下所示。
在時(shí)鐘下降沿對(duì)時(shí)鐘使能信號(hào)進(jìn)行鎖存,并保持一個(gè)時(shí)鐘周期內(nèi)不變。鎖存后的信號(hào)再與時(shí)鐘進(jìn)行"與"邏輯操作,可將門(mén)控時(shí)鐘中的毛刺消除掉。
將仿真例程鐘直接"與"操作的門(mén)控時(shí)鐘邏輯部分,改寫(xiě)為使用 latch 邏輯,修改如下:
//(2) using latch
reg en_latch ;
always @(*) begin
if (!clk) begin
en_latch = clken ;
end
end
wire clk_gate = clk & en_latch ;
仿真結(jié)果如下。
雖然地址為 0x3 的數(shù)據(jù)仍然被遺漏(和使能信號(hào)時(shí)序有關(guān)),但 ram 的時(shí)鐘已經(jīng)是正常時(shí)鐘,不再出現(xiàn)毛刺(標(biāo)黃的 CLK 信號(hào))。
雖然使用 latch 可以解決門(mén)控時(shí)鐘毛刺的出現(xiàn),但是時(shí)序也需要嚴(yán)格的約束。
FPGA 或 IC 設(shè)計(jì)時(shí),綜合庫(kù)中往往會(huì)有集成門(mén)控邏輯單元。此類(lèi)門(mén)控邏輯單元經(jīng)過(guò)了大量的更新迭代和驗(yàn)證,使用起來(lái)更加的方便、安全。
因此一般情況下,門(mén)控時(shí)鐘的設(shè)計(jì)也都會(huì)直接調(diào)用專(zhuān)用的集成門(mén)控邏輯單元。調(diào)用方式和基本的與門(mén)、緩沖器等基本單元類(lèi)似,直接例化即可。
合理的使用門(mén)控時(shí)鐘邏輯,對(duì)電路時(shí)鐘進(jìn)行控制,也會(huì)有效的減少功耗。
增加時(shí)鐘使能信號(hào),人為的控制模塊工作時(shí)鐘的有無(wú)。
模塊工作時(shí),將使能信號(hào)有效,時(shí)鐘打開(kāi);模塊空閑時(shí),將使能信號(hào)無(wú)效,時(shí)鐘關(guān)閉,節(jié)省功耗。
上一節(jié)的仿真設(shè)計(jì),就可以看做是手動(dòng) gating 的例子。ram 讀寫(xiě)時(shí),使能信號(hào)為高,ram 時(shí)鐘打開(kāi),ram 開(kāi)始工作;使能信號(hào)為低時(shí),ram 不工作,此時(shí)無(wú)輸入時(shí)鐘。
模塊在工作時(shí),可以自動(dòng)檢測(cè)自己的工作狀態(tài),并輸出一個(gè) busy(忙碌) 信號(hào)。外部可以通過(guò)該指示信號(hào),對(duì)模塊內(nèi)部的部分邏輯進(jìn)行時(shí)鐘門(mén)控,來(lái)減少時(shí)鐘的翻轉(zhuǎn),達(dá)到自動(dòng) gating 的控制。
與手動(dòng) gating 不同的是,這些模塊在工作時(shí),會(huì)有短暫的空閑狀態(tài)。自動(dòng) gating 就是要在這短暫的空閑狀態(tài)時(shí)間內(nèi)關(guān)閉掉無(wú)用的時(shí)鐘,而不是像手動(dòng) gating 直接關(guān)閉掉整個(gè)模塊的時(shí)鐘,否則該模塊就不能再正常工作。
例如 uart 在完成一次傳輸數(shù)據(jù)時(shí)會(huì)有一段空閑的狀態(tài),此時(shí)可將一些 fifo 邏輯、波特率產(chǎn)生邏輯等模塊的時(shí)鐘自動(dòng)關(guān)閉。
例如在包含 cpu 的設(shè)計(jì)中,可加入檢測(cè) bus 總線空閑狀態(tài)的邏輯,自動(dòng)控制開(kāi)關(guān) bus 總線的時(shí)鐘,以此降低功耗。
限于篇幅,這里先不再舉例仿真。
當(dāng) RTL 設(shè)計(jì)完成之后進(jìn)行邏輯綜合時(shí),編譯器也會(huì)對(duì)代碼的邏輯進(jìn)行自動(dòng)優(yōu)化,這就包括將一些觸發(fā)器的時(shí)鐘端進(jìn)行 gating。例如一個(gè)帶使能端的同步 D 觸發(fā)器的 RTL 描述如下:
//(2) Flip-Flop with enable port
always @(posedge CLK) begin
if (EN) begin
Q = D ;
end
end
其 RTL 前級(jí)仿真如下圖所示:
綜合后的仿真波形往往會(huì)如下圖所示:
對(duì)比可知,綜合后已經(jīng)沒(méi)有了 EN 信號(hào),時(shí)鐘(CP 端)經(jīng)過(guò) clock gating 后也不是一直存在。既保證了邏輯的正確性,又減少了時(shí)鐘翻轉(zhuǎn),降低了功耗。
點(diǎn)擊這里下載源碼
更多建議: