加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
    • 并行與流水
    • 資源共享與狀態(tài)編碼        
    • 操作數(shù)隔離
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

數(shù)字芯片中的低功耗設(shè)計(jì)(二)

2022/09/14
3996
閱讀需 3 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

書接上文,數(shù)字芯片中典型的低功耗設(shè)計(jì)是添加clk gate。另外還有一種方法是并行與流水技術(shù)。

并行與流水

硬件描述語言的一個(gè)突出優(yōu)點(diǎn)就是指令執(zhí)行的并行性。多條語句能夠在相同時(shí)鐘周期內(nèi)并行處理多個(gè)信號(hào)數(shù)據(jù)。但是當(dāng)數(shù)據(jù)串行輸入時(shí),指令執(zhí)行的并行性并不能體現(xiàn)出其優(yōu)勢(shì)。而且很多時(shí)候有些計(jì)算并不能在一個(gè)或兩個(gè)時(shí)鐘周期內(nèi)執(zhí)行完畢,如果每次輸入的串行數(shù)據(jù)都需要等待上一次計(jì)算執(zhí)行完畢后才能開啟下一次的計(jì)算,那效率是相當(dāng)?shù)偷?。流水線就是解決多周期下串行數(shù)據(jù)計(jì)算效率低的問題。一般來講,對(duì)于一個(gè)功能模塊,可以通過并行的方式實(shí)現(xiàn),也可以通過流水線的方式實(shí)現(xiàn),這兩種方法都是用資源換速度。

對(duì)于并行處理,可以同時(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) begin        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測(cè)試平臺(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é)果是相同的,但是對(duì)于并行處理方法,由于其時(shí)鐘頻率降低了1/2,功耗也會(huì)隨之降低,但是電路面積會(huì)隨之增加。

對(duì)于一個(gè)處于連續(xù)工作模式的 N 級(jí)流水線,效率提升N倍。與并行設(shè)計(jì)類似,流水線設(shè)計(jì)也可以通過降低工作頻率,達(dá)到降低功耗的目的。除此之外,我們可以將流水線設(shè)計(jì)分成 N 級(jí)流水線,假設(shè)新的路徑長(zhǎng)度為L(zhǎng)new,原始路徑長(zhǎng)度為L(zhǎng)old,則Lnew=1/N*Lold。如果時(shí)鐘頻率保持固定,則在一個(gè)周期內(nèi),不需要對(duì)原來的電容 C 進(jìn)行充放電,只需要對(duì)電容 C/N 進(jìn)行充放電。因此可以采用較低的電壓來驅(qū)動(dòng)芯片電路,從而達(dá)到降低功耗的目的。

資源共享與狀態(tài)編碼        

對(duì)于某設(shè)計(jì),一個(gè)相同的邏輯在多處被調(diào)用時(shí),可以對(duì)該邏輯進(jìn)行資源共享,以降低功耗。例如,對(duì)于一個(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ì)減少功耗。

對(duì)于一些變化頻繁的信號(hào),翻轉(zhuǎn)率相對(duì)較高,功耗相對(duì)較大??梢岳脿顟B(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è)簡(jiǎn)單的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ù)信號(hào)然后相應(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;else 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

相關(guān)推薦

電子產(chǎn)業(yè)圖譜