Low-Power VLSI Design

Power limits every modern chip, from phones to data-centre GPUs. Learn the dynamic/short-circuit/leakage power equation, clock gating (with a real ICG cell), operand isolation, multi-V_t and multi-V_DD design, power gating with retention, DVFS, UPF power intent, and how power is estimated from activity (SAIF/VCD).

Total power = dynamic (αCV²f) + short-circuit + leakage (V·I_off). Each term has its own weapon: reduce activity α with clock gating; reduce V and f with DVFS; reduce leakage with high-V_t cells and by switching idle blocks off entirely.

Low-power design starts at the architecture (do less work), continues in RTL (gate clocks, isolate operands) and ends in implementation (multi-V_t swaps, power switches). Techniques are described in a UPF file so every tool understands the power domains.

An analogy

Saving power on a chip is like saving electricity at home: switch off lights in empty rooms (power gating), stop the fans that aren't needed (clock gating), use dimmers (voltage scaling), and fix dripping taps (leakage).

Where the power goes

Dynamic power burns whenever nodes toggle; clock networks alone can be 30–40% of it because they toggle every cycle. Leakage flows even when nothing switches and grows with temperature and at smaller V_t. Battery devices care about energy per task; servers care about power density and cooling.

RTL techniques

Reduce useless switching in the design itself:

Voltage and threshold techniques

DVFS lowers V and f when full performance isn't needed (phone CPUs change operating points thousands of times a second). Multi-V_DD islands run slow blocks at lower voltage with level shifters at boundaries. Multi-V_t libraries use fast low-V_t cells only on critical paths and high-V_t (low-leakage) cells elsewhere.

Power gating and power-aware verification

Header/footer switches disconnect idle domains from the supply, cutting leakage almost to zero. Outputs of switched-off domains must be isolated (clamped) and needed state saved in retention flops. Power-up sequencing avoids rush current. Power-aware simulation with UPF, and power estimation from real activity (SAIF/VCD from simulation or emulation) close the loop.

Formulas

Worked example: DVFS

Given: V 1.0 → 0.8 V, f 1.0 → 0.8 GHz

Find: Dynamic power ratio.

Answer: 0.512 → about half the power

Worked example: Clock gating

Given: Registers idle 60% of cycles, reg+clock = 40% of 0.5 W

Find: Saving.

Answer: ≈ 0.12 W saved (24%)

Worked example: Multi-V_t

Given: Swapping to HVT raises V_t by 100 mV, S = 80 mV/dec

Find: Leakage reduction.

Answer: ≈ 18× less leakage (at some delay cost)

Glitch-free integrated clock-gating (ICG) cell and its use

// Integrated clock-gating cell (latch-based, glitch-free).
// The latch is transparent while clk is LOW, so 'en' can only change the
// gated clock while clk is low - no truncated pulses.
module icg (
    input  wire clk,
    input  wire en,          // functional enable
    input  wire test_en,     // forces the clock on during scan test
    output wire gclk
);
    reg en_latched;
    always @(clk or en or test_en)
        if (!clk) en_latched = en | test_en;
    assign gclk = clk & en_latched;
endmodule

// A register bank that only toggles when it has new data.
module gated_regs (
    input  wire        clk, rst_n, load,
    input  wire [31:0] d,
    output reg  [31:0] q
);
    wire gclk;
    icg u_icg (.clk(clk), .en(load), .test_en(1'b0), .gclk(gclk));
    always @(posedge gclk or negedge rst_n)
        if (!rst_n) q <= 32'd0;
        else        q <= d;
endmodule

The latch is intentional (Yosys reports 'latch inferred' for en_latched). In real flows you instantiate the library's ICG cell; synthesis tools also insert them automatically from 'if (load) q <= d;' patterns.

Estimating the effect of clock gating, DVFS and leakage

def dynamic(alpha, C, V, f):
    return alpha * C * V**2 * f

C_total = 2e-9              # F switched capacitance of the whole block
base = dynamic(0.15, C_total, 1.0, 1e9)
print(f"baseline dynamic power: {base:.3f} W")

gated = dynamic(0.15 * 0.6, C_total, 1.0, 1e9)       # clock gating removes 40% of toggles
print(f"with clock gating:      {gated:.3f} W ({(1-gated/base)*100:.0f}% saved)")

dvfs = dynamic(0.15, C_total, 0.8, 0.8e9)             # 0.8 V, 800 MHz
print(f"DVFS 0.8 V / 800 MHz:   {dvfs:.3f} W ({(1-dvfs/base)*100:.0f}% saved)")

leak = 1e8 * 1e-9 * 1.0                               # 1e8 devices x 1 nA x 1 V
print(f"leakage (1e8 x 1 nA):   {leak:.3f} W")
# baseline dynamic power: 0.300 W
# with clock gating:      0.180 W (40% saved)
# DVFS 0.8 V / 800 MHz:   0.154 W (49% saved)
# leakage (1e8 x 1 nA):   0.100 W

A 20% drop in both voltage and frequency halves dynamic power (0.8² × 0.8 = 0.51). Leakage stays unless the block is power-gated.

UPF power intent for a switchable domain

create_power_domain PD_TOP
create_power_domain PD_GPU -elements {u_gpu}

create_supply_net VDD
create_supply_net VDD_GPU -domain PD_GPU
create_power_switch sw_gpu -domain PD_GPU \
    -input_supply_port  {in  VDD} \
    -output_supply_port {out VDD_GPU} \
    -control_port       {ctrl gpu_pwr_en} \
    -on_state           {on in {ctrl}}

set_isolation iso_gpu -domain PD_GPU -isolation_power_net VDD \
    -clamp_value 0 -applies_to outputs
set_isolation_control iso_gpu -domain PD_GPU -isolation_signal gpu_iso -isolation_sense high
set_retention ret_gpu -domain PD_GPU -retention_power_net VDD

UPF tells synthesis, P&R and simulation which blocks can be switched off, where isolation clamps outputs, and which registers keep state (retention) — so power-aware simulation can catch missing isolation before silicon.

Common mistakes

Applications

Key takeaways

Going further