Voltage Scaling and Power Domains

Clock gating attacked \alpha. Now for the heavyweight lever in P = \alpha C V^2 f: the square on V. Voltage is the only knob that enters quadratically — and since lowering frequency permits lowering voltage (gates switch slower at lower V, so a slower clock tolerates it), the two move together for a compounded, roughly cubic win. This was the engine of Dennard scaling while it lasted; now that it no longer comes free with each process node, chips do it actively, minute by minute — and carve themselves into independently powered fiefdoms to do it well.

DVFS: the V² lever, pulled at runtime

Dynamic voltage-frequency scaling lets the operating system slide the chip along a table of legal (f, V) operating points. The honest arithmetic, for halving the clock and dropping the supply from 1.0 V to 0.7 V:

\frac{P_{\text{new}}}{P_{\text{old}}} \;=\; \frac{f/2}{f}\cdot\frac{(0.7V)^2}{V^2} \;=\; 0.5 \times 0.49 \;\approx\; 0.245 \;\approx\; \tfrac{1}{4}.

Half the speed for a quarter of the power — that trade is why your laptop's fan spins down when you stop compiling. Note what it does to energy per task: time doubles while power quarters, so the energy for a fixed job scales as V^2 alone — the frequency cancels. Lower voltage is (dynamically) always more efficient per unit of work… until leakage, which flows the whole time the chip is powered, changes the verdict. Run the sweep:

// DVFS sweep: dynamic power falls as f·V², but leakage taxes every second of runtime. const points = [ { f: 2.0, V: 1.0 }, // GHz, volts { f: 1.5, V: 0.85 }, { f: 1.0, V: 0.7 }, { f: 0.5, V: 0.55 }, ]; const P_LEAK = 0.3; // W, roughly constant while the domain is powered // Calibrated so 2 GHz @ 1.0 V burns 2 W of dynamic power; task = 1e9 cycles. const pDyn = (f: number, V: number) => f * V * V; console.log("f(GHz) V(V) Pdyn(W) time(s) energy(J)"); let bestE = Infinity, bestF = 0; for (const p of points) { const t = 1 / p.f; // 1e9 cycles / (f GHz) const E = (pDyn(p.f, p.V) + P_LEAK) * t; console.log(" " + p.f.toFixed(1) + " " + p.V.toFixed(2) + " " + pDyn(p.f, p.V).toFixed(2) + " " + t.toFixed(2) + " " + E.toFixed(2)); if (E < bestE) { bestE = E; bestF = p.f; } } console.log(""); console.log("best energy per task: " + bestF.toFixed(1) + " GHz (" + bestE.toFixed(2) + " J)"); console.log("Crawling is NOT optimal: below the sweet spot, leakage x long runtime"); console.log("dominates - often better to 'race to idle' and power-gate the domain.");

The sweep exposes the real shape of the problem: dynamic energy per task falls with V^2, but leakage energy grows with runtime, so energy-per-task has a minimum at a middling operating point. Below it, the winning strategy flips to race to idle: sprint at an efficient point, finish early, then kill the power entirely. Which raises the question — how do you kill power to only part of a chip?

Power domains: different voltages, switchable islands

A modern SoC is not one circuit at one voltage — it is a federation of voltage domains: the CPU sprinting at 0.9 V, slow peripherals ambling at 0.6 V, each block given just enough voltage for its timing. Two kinds of special cells stitch the federation together, and a third switches parts of it off:

Powering down is therefore a ceremony, run by a small always-on power-controller FSM, and the order is everything: isolate → save → switch off, and on wake-up the mirror image, switch on → restore → de-isolate. Step through it on the floorplan:

Power intent, and one more voltage trick

Notice that none of this — domains, shifters, isolation, retention — appears in your RTL, which still describes pure logic. The partitioning lives in a separate power-intent specification (UPF, or the older CPF): a file declaring the domains, their supply nets, where isolation and retention are required, and the legal power states. Every tool in the flow reads it — synthesis inserts the special cells, verification simulates domains actually losing state (catching the missing-retention bug before silicon), and the back-end wires the switch networks. One spec, honoured everywhere: the same "say what you mean, let the tools enforce it" pattern as clock gating, scaled up to the whole chip.

A final, finer-grained voltage lever: libraries ship each cell in several threshold-voltage (Vt) flavours. Low-Vt cells switch fast but leak hard; high-Vt cells are slow and thrifty. The tools mix them: low-Vt only on the critical paths that need the speed, high-Vt everywhere else — buying back the vast majority of leakage for zero performance cost.

Hundreds — and enumerating them is itself an engineering discipline. A flagship mobile SoC has dozens of switchable domains (per-core, per-cluster, GPU slices, media blocks, modem pieces), each with several DVFS points, plus retention-versus-full-off variants for the sleeping ones. The legal combinations form a state space the power-controller firmware walks all day: your phone crosses power states thousands of times per second, mostly for milliseconds at a time, and a misordered transition in even one obscure corner (de-isolating before the supply is stable, say) becomes the kind of once-a-week freeze that no software patch can fully hide. This is why UPF-aware verification teams simulate power-state machines, not just logic — and why "low-power methodology engineer" is a job title with excellent job security.

Open a domain's power switch without isolation cells and its output wires do not politely go to 0 — they float, drifting toward mid-rail voltages. Every powered gate listening to them now has an input that is neither 0 nor 1: its pull-up and pull-down networks both half-conduct, burning crowbar current continuously, while its output flickers with noise — garbage values marching into live logic. The failure is beautifully perverse: you switched a block off to save power, and the chip now burns more, while corrupting the blocks that are still alive. Every switchable domain's outputs must be clamped by isolation cells before the switch opens — which is exactly why the sequence isolate → save → gate-off is enforced by an FSM in hardware, not left to polite software convention.