数字IC低功耗设计——基础概念和低功耗设计方法


参考文献
[1](数字IC)低功耗设计入门
[2]Verilog低功耗设计
[3]低功耗设计基础:DVS, AVS和DVFS都是如何降低功耗的?

一、低功耗设计的必要性

  • 低功耗设计有利于降低便携式电子产品的体积。
  • 功耗越大,产生的热量越多,会导致热噪声越大,会影响器件的正常工作。随着温度的上升,会降低芯片的工作频率。
  • 低功耗设计有利于降低封装成本。

二、功耗的构成

  功耗一般只关注动态功耗和静态功耗。

1. 动态功耗

  动态功耗包括开关功耗(翻转功耗)、短路功耗(内部功耗)。

1) 翻转功耗(switching power)

  翻转功耗的产生原因是在数字CMOS电路中,对负载电容进行充放电时消耗的功耗
在这里插入图片描述

  以上面的CMOS非门为例, 当Vin=0时, 上面的PMOS管导通,下面的NMOS管截止,VDD对负载电容 C l o a d C_{load} Cload进行充电,充电完毕后,Vout的电平为高电平。当Vin=1时,上面的PMOS管截止,下面的NMOS管导通,负载电容通过NMOS进行放电,放电完毕后,Vout为低电平。
  翻转功耗的计算公式为
P s w i t c h = V D D 2 C L f = 1 2 V D D 2 C L T r P_{switch} = V_{DD}^2C_Lf = \frac{1}{2}V_{DD}^2C_LT_r Pswitch=VDD2CLf=21VDD2CLTr
  其中, V D D V_{DD} VDD为供电电压, C L C_L CL为等效负载电容,f为时钟频率(翻转率Tr=2f)。

2)短路功耗(Internal power)

  短路功耗是因为在输入信号进行翻转时,信号的翻转不可能瞬间完成,也就是说PMOS和NMOS不可能总是一个截止一个导通,总有一段时间是PMOS和NMOS同时导通,因此,在这段时间内从电源VDD到地VSS之间就有了通路,如此便形成了短路电流,如下图所示
在这里插入图片描述

  短路功耗的计算公式为
P s h o r t = V D D T r Q x P_{short} = V_{DD}T_rQ_x Pshort=VDDTrQx
  其中, V D D V_{DD} VDD为供电电压, T r T_r Tr为翻转率, Q x Q_x Qx为一次翻转过程中从电源流向地的电荷量。
  综上所述,动态功耗主要有开关功耗和短路功耗,其中开关功耗占比大。并且动态功耗主要是跟供电电压、翻转率、负载电容有关。

2. 静态功耗

  静态功耗的产生原因是在CMOS电路中,静态功耗主要是漏电流引起的功耗,如下图所示
在这里插入图片描述

漏电流有下面几个部分组成:

  • PN结反向电流I1(PN-junction Reverse Current)
  • 源极和漏极之间的亚阈值漏电流I2(Sub-threshold Current)
  • 栅极漏电流,包括栅极和漏极之间的感应漏电流I3(Gate Induced Drain Leakage)
  • 栅极和衬底之间的隧道漏电流I4(Gate Tunneling)

  一般情况下,漏电流主要是指栅极泄漏电流和亚阈值电流(进入超深亚微米工艺之后,隧道漏电流成为主要电流之一)
  栅极泄漏功耗:在栅极上加信号后(即栅压),从栅到衬底之间存在电容,因此在栅衬之间就会存在有电流,由此就会存在功耗。
  亚阈值电流:使栅极电压低于导通阈值,仍会产生从漏极到源极的泄漏电流。此电流称为亚阈值泄漏电流。在较狭窄的晶体管中,漏极和源极距离较近的情况下会产生亚阈值泄漏电流。晶体管越窄,泄漏电流越大。要降低亚阈值电流,可以使用高阈值的器件(HVT器件,相较于LVT器件,功耗低但是速度慢),还可以通过衬底偏置进行增加阈值电压,这些属于低功耗设计。
  静态功耗的计算公式为
P p e a k = V D D I p e a k P_{peak} = V_{DD}I_{peak} Ppeak=VDDIpeak

  其中, I p e a k I_{peak} Ipeak为泄漏电流,此外静态功耗往往与工艺有关

三、低功耗设计方法

  芯片的低功耗设计通过不同的设计层次可以分为系统级低功耗设计,行为级低功耗设计,RTL级低功耗设计,逻辑级低功耗设计和物理级低功耗设计,其设计层次越高对功耗降低的效果越明显。
在这里插入图片描述

四、如何从设计的角度降低功耗

  根据前面分析,动态功耗主要是跟供电电压、翻转率、负载电容有关,静态功耗往往与工艺有关。从前端设计角度来看,无疑只能通过降低信号的翻转率来降低功耗。下面介绍几种常用的降低翻转率的方案。

1)使用格雷码、独热码进行状态机的编码和解码;

  在状态机的编码和解码过程中,采用格雷码最符合低功耗设计。因为格雷码的相邻码元之间只变化一位,所以在发生状态转换时实际上只有一个触发器发生了翻转。对于状态编码常用的二进制码和独热码来说,在发生一次状态转换时可能存在多个触发器发生了翻转,在状态转换过程中也就消耗了更多的能量。另外使用格雷码的一个好处就是降低了亚稳态发生的概率。
在这里插入图片描述

case(state)
2'b00: out = a;
2'b01: out = b;
2'b11: out = c;
2'b10: out = d;
default:out = 0;
endcase

  此外,除了格雷码外,还可以考虑独热码来实现状态机编码,独热码虽然需要更多的触发器进行编码,但是独热码更能减少组合逻辑资源。假如需要判断状态机是否处于某状态S1,对于格雷码来说,需要assign S1 = (State==2’b01); 而对于独热码来说,只需要assign S1 = (State[1])。无疑对于条件复杂但是状态少的状态机来说,独热码也是一个不错的选择。

2)操作数隔离,数据保持;

  操作数隔离原理为,如果在某一段时间内,数据通路的输出是无用的,将输入置成固定值,数据通路部分没有翻转,功耗就会降低。 
  一个示例乘法器电路如下图所示,当 sel0 = 0 或 sel1 = 1 时,乘法器 Multiplier 的输出结果并不能通过两个 Mux 到达寄存器的输入端。即寄存器并不能保存当前乘法器的结果,此次乘法运算是没有必要的。在此种条件下,采用操作数隔离,使乘法器不工作保持静态,也可以节省功耗。
在这里插入图片描述
在这里插入图片描述

  一般来说,操作数隔离的操作发生在代码综合的时候。这个过程往往是人为可设置、编译器可自动识别的。当然,在编写 RTL 电路时就考虑周全,更加有助于实现操作数隔离,从而降低功耗。以下是操作数隔离的示例写法。

//no isolation
module  oper_isolation1
    (
     input                clk ,           //100MHz
     input [1:0]          sel ,
     input [3:0]          din1 ,          //data in
     input [3:0]          din2 ,          //data in
     output reg [7:0]     dout
     );

    reg [7:0]       res ;
    always @(*) begin
        res       = din1 * din2 ;
    end

    always @(posedge clk) begin
        if (sel == 2'b01) begin
            dout   <= res ;
        end
    end
endmodule

//using isolation
module  oper_isolation2
    (
    input                clk ,           //100MHz
    input [1:0]          sel ,
    input [3:0]          din1 ,          //data in
    input [3:0]          din2 ,          //data in
    output reg [7:0]     dout
    );

    wire [3:0]           mul1 = sel == 2'b01 ? din1 : 0 ;
    wire [3:0]           mul2 = sel == 2'b01 ? din2 : 0 ;
    reg [7:0]            res ;
    always @(*) begin
        res       = mul1 * mul2 ;
    end

    always @(posedge clk) begin
        if (sel == 2'b01) begin
            dout   <= res ;
        end
    end
endmodule

3)添加使能、片选信号,减少不必要的信号翻转

  在实际电路设计中,并不是所有时刻输入都是有效的。比如说一个乘法器,可以添加一个en信号,用来使能输入操作数是否有效,有效时输出,无效时数据保持。

module top(
    input clk,
    input en ,
    input [7:0] opt1,
    input [7:0] opt2,
    output reg [15:0] result
);

    always @(posedge clk)begin
        if(en)
            result <= opt1*opt2;
        else
            result <= result;
    end
endmodule

4)逻辑复用

  当设计中一些相同的运算逻辑在多处使用时,就可以使用逻辑复用的方法避免多个运算逻辑的重复出现,减少资源的消耗。虽然说EDA工具会在一定程度上,对相同逻辑进行复用,但是在实际设计过程中,也需要保证良好的代码风格,提高EDA的工具的可靠性和综合速度。以下是逻辑复用的一个例子。

    //未优化前
    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
    // 对上述代码进行优化,描述如下:
    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

5)逻辑重拍

  以下图为例, a信号变化得最频繁,为了降低输出信号的翻转,我们可以将a和d信号位置互换,实现逻辑的重新排序,也就是将快速变换的信号移至逻辑锥体的前部。此方法同样适用于“if-else-”表达式,可以重拍判断条件,优先判断变化较慢的条件。
在这里插入图片描述

  又比如,电路中b信号是翻转率比较大的信号,在排序前的电路中,b的每次翻转要驱动4个门,在排序后的电路中,b的每次翻转只需要驱动2个门,显然有效地降低了系统的动态功耗。下图所示为排序前后的两个电路模块。
在这里插入图片描述

6)时钟门控(clock gating)

  通常情况下,时钟树由大量的缓冲器和反相器组成,时钟信号为设计中翻转率最高的信号,时钟树的功耗可能高达整个设计功耗40%。加入门控时钟电路后,由于减少了时钟树的翻转,节省了翻转功耗。同时,由于减少了寄存器时钟引脚的翻转行为,寄存器的内部功耗也减少了。采用门控时钟,可以非常有效地降低设计的功耗,一般情况下能够节省20%~60%的功耗。
  在实际设计中,我们是不需要在rtl中自己实现时钟门控的,现在的综合工具会自动插入时钟门控。如下图所示当插入时钟门控后,电路中的MUX就不需要了,如果数据D是多bit的,那么插入CG后面积会减少。
在这里插入图片描述
  常用的时钟门控单元如下图所示。
在这里插入图片描述

  也就是说只有D位宽超过一定的bit数后,插入CG的收益才会大。而这个位宽的临界值在DC中默认值为3。也就是说,如果D的位宽超过了3bit,那么DC就会默认插入CG。可以使用DC命令来修改默认值。

set_clock_gating_style -minimum_bitwidth 4

  当然,虽然现在综合工具可以自动插入门控时钟,但是如果编码风格不好,也不能达到自动插入CG的目的。


//写法1, 能够自动插入clock gating
always @(posedge clk or negedge rst_n)begin
    if(~rst_n)
        Q <= 'd0;
    else if(EN)
        Q <= D;
end
//写法2, 不能够自动插入clock gating
always @(posedge clk or negedge rst_n)begin
    if(~rst_n)
        Q <= 'd0;
    else if(EN)
        Q <= D;
    else 
        Q <= 'd0;
end

五、如何从后端的角度降低功耗

1)多电压域(Multi-Voltage Domain)—— 降低工作电压

  对于多电压域设计,要在不同的电压域之间使用一些电平转换单元(Level Shifter),将输入电压范围转换成输出需要的不同电压范围。
在这里插入图片描述

  如果不同电压与之间的驱动信号与接受信号之间的距离很长,需要插入特殊的驱动单元(Repenter)来增强信号的驱动能力;如果不同的电压域可以单独断电(MV with Power Gating),还要考虑添加保持寄存器(Retention Register)和电压隔离单元(Isolation Cell)。

2)使用HVT高阈值晶体管 —— 降低泄露电流

  对绝大多数工艺,任何一种标准单元(standardcell)都有不同种速度的 Library,也就是常说的不同 Vt 的 cell,比如 HVT(High V threshold), SVT(Standard V threshold)和LVT(Low V threshold)。HVT 逻辑门的特点是速度慢,功耗低,因为其阈值电压高,所以需要更高的电压才能打开晶体管。SVT 逻辑门速度和功耗相对于 HVT 和 LVT 之间,因为其阈值电压在标准范围内。LVT 逻辑门速度快,功耗高,因为其阈值电压低,只需要较小的电压就可以打开晶体管。
  对于系统设计来说,可以在时序紧张的路径上使用LVT,然后在时序宽松的路径上使用HVT,来达到降低系统功耗的目的。此外,HVT/SVT/LVT 三种cell的面积是一样的。

3) DVS, AVS和DVFS

  • DVS(Dynamic Voltage Scaling)和AVS(Adaptive Voltage Scaling), 核心目的都是通过调节芯片整体或者部分power domain的电源电压来实现降低功耗的目的。
  • DVFS(Dynamic Voltage Frequency Scaling),可以根据芯片的性能和功耗需求调整电压和频率,从而在各个不同的工作需求中都已最小的功耗实现需求。在实现DVFS的过程中,需要一个输出电压控制器,一般来说叫做EMU(Energy Management Unit)。它在芯片中的基本逻辑结构如下:
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值