書接上文,數(shù)字芯片中典型的低功耗設(shè)計(jì)是添加clk gate。另外還有一種方法是并行與流水技術(shù)。
并行與流水
硬件描述語言的一個(gè)突出優(yōu)點(diǎn)就是指令執(zhí)行的并行性。多條語句能夠在相同時(shí)鐘周期內(nèi)并行處理多個(gè)信號數(shù)據(jù)。但是當(dāng)數(shù)據(jù)串行輸入時(shí),指令執(zhí)行的并行性并不能體現(xiàn)出其優(yōu)勢。而且很多時(shí)候有些計(jì)算并不能在一個(gè)或兩個(gè)時(shí)鐘周期內(nèi)執(zhí)行完畢,如果每次輸入的串行數(shù)據(jù)都需要等待上一次計(jì)算執(zhí)行完畢后才能開啟下一次的計(jì)算,那效率是相當(dāng)?shù)偷?。流水線就是解決多周期下串行數(shù)據(jù)計(jì)算效率低的問題。一般來講,對于一個(gè)功能模塊,可以通過并行的方式實(shí)現(xiàn),也可以通過流水線的方式實(shí)現(xiàn),這兩種方法都是用資源換速度。
對于并行處理,可以同時(shí)處理多條執(zhí)行語句,使執(zhí)行效率變高。在滿足設(shè)計(jì)SPEC的前提下,通過并行處理,可減小時(shí)鐘頻率,從而達(dá)到降低功耗的目的。舉例,若實(shí)現(xiàn)4 個(gè)數(shù)據(jù)乘加運(yùn)算,可以采用 1 個(gè)乘法器來實(shí)現(xiàn),也可以通過 2 個(gè)乘法器(并行)來實(shí)現(xiàn) ,verilog代碼描述分別如下:
//1 multiplier, high speedmodule mul1_hs
(
input
clk ,
//200MHz
input
rstn ,
input
en ,
input [3:0]
mul1 ,
//data in
input [3:0]
mul2 ,
//data in
output
dout_en ,
output [8:0]
dout
);
reg
flag ;
reg
en_r ;
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
flag
《= 1‘b0 ;
en_r
《= 1’b0 ;
end
else if (en) begin
flag
《= ~flag ;
en_r 《= 1‘b1 ;
end
else begin
flag
《= 1’b0 ;
en_r
《= 1‘b0 ;
end
end
wire [7:0]
result = mul1 * mul2 ;
// data output en
reg [7:0]
res1_r, res2_r ;
always @(posedge clk or negedge rstn) be
gin
if (!rstn) begin
res1_r
《= ’b0 ;
res2_r
《= ‘b0 ;
end
else if (en & !flag) begin
res1_r
《= result ;
end
else if (en & flag) begin
res2_r
《= result ;
end
end
assign dout_en = en_r & !flag ;
assign dout = res1_r + res2_r ;
endmodule
//===========================================//
2 multiplier2, low speedmodule mul2_ls (
input
clk ,
//100MHz
input
rstn ,
input
en , input [3:0]
mul1 ,
//data in
input [3:0]
mul2 ,
//data in
input [3:0] mul3 ,
//data in
input [3:0]
mul4 ,
//data in
output
dout_en,
output [8:0]
dout
);
wire [7:0]
result1 = mul1 * mul2 ;
wire [7:0]
result2 = mul3 * mul4 ;
//en delay
reg
en_r ;
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
en_r
《= 1’b0 ;
end
else begin
en_r
《= en ;
end end
// data output en
reg [7:0]
res1_r, res2_r ;
always @(posedge clk or negedge rstn) begin
if (!rstn) begin
res1_r
《= ‘b0 ;
res2_r
《= ’b0 ;
end
else if (en) begin
res1_r
《= result1 ;
res2_r
《= result2 ;
end end
assign dout
= res1_r + res2_r ;
assign dout_en
= en_r ;
endmodule
tb測試平臺(tái)描述如下:
`timescale 1ns/1psmodule test ;
reg
rstn ;
//mul1_hs reg
hs_clk; reg
hs_en ; reg [3:0]
hs_mul1 ; reg [3:0]
hs_mul2 ;
wire
hs_dout_en ;
wire [8:0] hs_dout ;
//mul1_ls reg
ls_clk = 0;
reg
ls_en ;
reg [3:0]
ls_mul1 ;
reg [3:0]
ls_mul2 ;
reg [3:0]
ls_mul3 ;
reg [3:0]
ls_mul4 ;
wire
ls_dout_en ;
wire [8:0]
ls_dout ;
//clock generating
real
CYCLE_200MHz = 5 ; //
always begin
hs_clk = 0 ; #(CYCLE_200MHz/2) ;
hs_clk = 1 ; #(CYCLE_200MHz/2) ;
end
always begin
@(posedge hs_clk) ls_clk = ~ls_clk ;
end
//reset
generating
initial begin
rstn
= 1‘b0 ;
#8 rstn
= 1’b1 ;
end
//motivation
initial begin
hs_mul1 = 0 ;
hs_mul2 = 16 ;
hs_en = 0 ;
#103 ;
repeat(12) begin
@(negedge hs_clk) ;
hs_en
= 1 ;
hs_mul1
= hs_mul1 + 1;
hs_mul2
= hs_mul2 - 1;
end hs_en = 0 ; end
initial begin
ls_mul1 = 1 ;
ls_mul2 = 15 ;
ls_mul3 = 2 ;
ls_mul4 = 14 ;
ls_en = 0 ;
#103 ;
@(negedge ls_clk) ls_en = 1;
repeat(5) begin
@(negedge ls_clk) ;
ls_mul1 = ls_mul1 + 2;
ls_mul2 = ls_mul2 - 2;
ls_mul3 = ls_mul3 + 2;
ls_mul4 = ls_mul4 - 2;
end ls_en = 0 ;
end
//module instantiation
mul1_hs
u_mul1_hs (
.clk
(hs_clk),
.rstn
(rstn), .en
(hs_en),
.mul1
(hs_mul1),
.mul2
(hs_mul2),
.dout
(hs_dout),
.dout_en
(hs_dout_en) );
mul2_ls
u_mul2_ls
( .clk
(ls_clk),
.rstn
(rstn),
.en
(ls_en),
.mul1
(ls_mul1),
.mul2
(ls_mul2), .mul3
(ls_mul3),
.mul4
(ls_mul4),
.dout
(ls_dout),
.dout_en
(ls_dout_en) );
//simulation finish
always begin
#100;
if ($time 》= 1000) begin
#1 ;
$finish ;
end
end
endmodule
下圖為仿真結(jié)果,兩種實(shí)現(xiàn)方法的結(jié)果是相同的,但是對于并行處理方法,由于其時(shí)鐘頻率降低了1/2,功耗也會(huì)隨之降低,但是電路面積會(huì)隨之增加。
對于一個(gè)處于連續(xù)工作模式的 N 級流水線,效率提升N倍。與并行設(shè)計(jì)類似,流水線設(shè)計(jì)也可以通過降低工作頻率,達(dá)到降低功耗的目的。除此之外,我們可以將流水線設(shè)計(jì)分成 N 級流水線,假設(shè)新的路徑長度為Lnew,原始路徑長度為Lold,則Lnew=1/N*Lold。如果時(shí)鐘頻率保持固定,則在一個(gè)周期內(nèi),不需要對原來的電容 C 進(jìn)行充放電,只需要對電容 C/N 進(jìn)行充放電。因此可以采用較低的電壓來驅(qū)動(dòng)芯片電路,從而達(dá)到降低功耗的目的。
資源共享與狀態(tài)編碼
對于某設(shè)計(jì),一個(gè)相同的邏輯在多處被調(diào)用時(shí),可以對該邏輯進(jìn)行資源共享,以降低功耗。例如,對于一個(gè)比較邏輯,沒有使用資源共享的代碼描述如下:
always @(*) begin
case (mode) :
3‘b000:
result = 1’b1 ;
3‘b001:
result = 1’b0 ;
3‘b010:
result = value1 == value2 ;
3’b011:
result = value1 != value2 ;
3‘b100:
result = value1 》 value2 ;
3’b101:
result = value1 《 value2 ;
3‘b110:
result = value1 》= value2 ;
3’b111:
result = value1 《= value2 ;
endcase
end
改進(jìn)后,使用資源共享的代碼描述如下:
wire equal_con
= value1 == value2 ;
wire great_con
= value1 》 value2 ;
always @(*) begin
case (mode) :
3‘b000:
result = 1’b1 ;
3‘b001:
result = 1’b0 ;
3‘b010:
result = equal_con ;
3’b011:
result = equal_con ;
3‘b100:
result = great_con ;
3’b101:
result = !great_con && !equal_con ;
3‘b110:
result = great_con && equal_con ;
3’b111:
result = !great_con ;
endcase end
第一種方法綜合實(shí)現(xiàn)時(shí),如果編譯器優(yōu)化做的不好,可能需要 6 個(gè)比較器。第二種資源共享的方法只需要 2 個(gè)比較器即可完成相同的邏輯功能,因此在一定程度會(huì)減少功耗。
對于一些變化頻繁的信號,翻轉(zhuǎn)率相對較高,功耗相對較大。可以利用狀態(tài)編碼的方式來降低開關(guān)活動(dòng),減少功耗。例如高速計(jì)數(shù)器工作時(shí),使用格雷碼代替二進(jìn)制編碼時(shí),每一時(shí)刻只有 1bit 的數(shù)據(jù)翻轉(zhuǎn),翻轉(zhuǎn)率降低,功耗隨之降低。例如進(jìn)行狀態(tài)機(jī)設(shè)計(jì)時(shí),狀態(tài)機(jī)切換前后的狀態(tài)編碼如果只有 1bit 的差異,也會(huì)減少翻轉(zhuǎn)率。
操作數(shù)隔離
操作數(shù)隔離就是在進(jìn)行一些操作比如選擇器的時(shí)候,我們選擇的那個(gè)選項(xiàng)有A和B,但是如果我們直到選擇的是A,那么B之前一大堆計(jì)算就顯得沒有必要了。所以操作數(shù)隔離也就是增加一些選擇器件,如果這個(gè)操作數(shù)不需要的話就不選擇它以及不進(jìn)行之前計(jì)算這個(gè)操作數(shù)所需要的操作。 沒有使用操作數(shù)隔離時(shí),Verilog 代碼描述如下:
module isolated(A,B,C,D,clk,clr,choose,result);
input wire clk;input wire clr;input wire [1:0]choose;input wire [31:0]A;input wire [31:0]B;input wire [31:0]C;input wire [31:0]D;output reg [31:0]result; wire [31:0]choose_a;wire [31:0]choose_b;wire [31:0]choose_c;wire [31:0]choose_d;
//這是一個(gè)簡單的mux,先計(jì)算出A,B,C,D的值再選擇 assign choose_a = A*B;assign choose_b = A+B+C+D;assign choose_c = B*C;assign choose_d = C*D; always@(posedge clk,posedge clr)begin if(clr) result 《= 0;else begin if(choose == 2‘b00) result 《= choose_a;else if(choose == 2’b01) result 《= choose_b;else if(choose == 2‘b10) result 《= choose_c;else result 《= choose_d;endendendmodule
使用操作數(shù)隔離時(shí),Verilog 代碼描述如下:
module isolated2(A,B,C,D,clk,clr,choose,result);
input wire clk;input wire clr;input wire [1:0]choose;input wire [31:0]A;input wire [31:0]B;input wire [31:0]C;input wire [31:0]D;output reg [31:0]result; reg [31:0]choose_A;reg [31:0]choose_B;reg [31:0]choose_C;reg [31:0]choose_D;reg [1:0]cho;//這是一個(gè)使用了isolated的mux,先根據(jù)信號然后相應(yīng)計(jì)算所需的A,B,C或者D的值always@(posedge clk,posedge clr
)begin if(clr) begin choose_A 《= 0; choose_B 《= 0; choose_C 《= 0; choose_D
《= 0;cho 《= 0;endelse if(choose == 2’b00) begin choose_A 《= A; choose_B 《= B; choose_C 《= choose_C; choose_D 《= choose_D; cho 《= 0; endelse if(choose == 2‘b01)
begin choose_A 《= A; choose_B 《= B; choose_C 《= C; choose_D
《= D; cho 《= 1; endelse if(choose == 2’b10) begin choose_A 《= choose_A; choose_B 《= B; choose_C 《= C; choose_D 《= choose_D; cho 《= 2; endelse begin choose_A 《= choose_A; choose_B
《= choose_B; choose_C 《= C; choose_D 《= D; cho 《= 3; endendalways@(posedge clk,posedge clr)begin if(clr) result 《= 0;else begin if(cho == 2‘b00) result 《= choose_A*choose_B;
lse if(cho == 2’b01) result 《= choose_A+choose_B+choose_C+choose_D;else if(cho == 2‘b10) result 《= choose_B*choose_C; else result 《= choose_C*choose_D;endend
endmodule
參考文獻(xiàn): https://www.runoob.com/w3cnote/verilog2-rtl-low-power-design-1.html
編輯:黃飛
-
Verilog
+關(guān)注
關(guān)注
28文章
1351瀏覽量
110195 -
數(shù)字芯片
+關(guān)注
關(guān)注
1文章
110瀏覽量
18428
原文標(biāo)題:數(shù)字芯片中的低功耗設(shè)計(jì)(二)
文章出處:【微信號:IP與SoC設(shè)計(jì),微信公眾號:IP與SoC設(shè)計(jì)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論