Computer Architecture · Architecture Tradeoffs
Voltage and Frequency Domains: Why DVFS Is Not One Knob
How a frequency change requires a voltage change, why level shifters and synchronisers appear at domain boundaries, and what latency an operating-point transition really costs.
Dynamic voltage and frequency scaling is usually described as a single dial that trades speed for power. The dial is real, but it is not one knob: frequency and voltage are coupled through the circuit’s timing, the coupling is quantised by the clock generation hardware, and the transition between operating points is a sequence with a measurable cost. On a chip with several independently scalable regions the coupling becomes a scheduling problem, because a region cannot change its operating point without coordinating with everything it talks to.
Frequency is set by a divider, voltage by a regulator
The clock that reaches the logic is derived from a fixed reference, usually a crystal oscillator or a PLL output, through a divider and a multiplier. Changing the frequency means reprogramming that ratio. Two properties follow.
First, the achievable frequencies are discrete. A divider gives integer ratios, and a fractional divider gives ratios with a small denominator, so the operating points form a finite set rather than a continuum. Firmware publishes the set as a table, and the operating system selects an index into it rather than a frequency in hertz. The ACPI specification models this with performance states, each listing a core frequency and a core voltage, and requires the entries to be ordered by performance so that one index identifies one operating point.
Second, the change does not take effect instantly. A PLL that is asked to change its output must relock, which takes on the order of microseconds; a divider-based change can be faster but still has to be synchronised so that no flip-flop receives a pulse shorter than its minimum width. The clock generation block therefore has a transition sequence: stop the clock cleanly, change the ratio, wait for stability, restart. During the sequence the domain executes nothing.
The voltage side is slower still. A regulator with a large output capacitance and a feedback loop settles in tens of microseconds, and the settling time depends on the load current, because the loop’s bandwidth and the load interact. If the voltage is raised before the frequency, the logic runs at the new frequency only after the supply has settled; if the frequency is raised before the voltage, the logic runs too fast for its supply and produces timing errors. The rule is therefore fixed: raise voltage before raising frequency, lower frequency before lowering voltage.
/* The ordering rule as a state machine. Each state has exactly one legal
* next state, so a policy cannot accidentally raise frequency first. */
enum op_state { ST_READY, ST_RAISE_V, ST_WAIT_V, ST_RAISE_F,
ST_LOWER_F, ST_LOWER_V };
static enum op_state step(enum op_state s, int target_idx, int current_idx)
{
switch (s) {
case ST_READY:
if (target_idx > current_idx) return ST_RAISE_V;
if (target_idx < current_idx) return ST_LOWER_F;
return ST_READY;
case ST_RAISE_V: return ST_WAIT_V; /* regulator ramping up */
case ST_WAIT_V: return ST_RAISE_F; /* only after the rail settles */
case ST_RAISE_F: return ST_READY;
case ST_LOWER_F: return ST_LOWER_V; /* clock first, rail afterwards */
case ST_LOWER_V: return ST_READY;
}
return ST_READY;
}
The consequence is that a transition in the upward direction is bounded below by the regulator’s settling time, not by the clock generator’s. Firmware that exposes operating points hides this by reporting the transition latency alongside the table, so the scheduler can decide whether a change is worth making.
Why the frequency cannot change without the voltage
A static timing analysis of a design closes at a specific voltage. Each gate’s delay is a function of its supply, and the paths that were marginal at the sign-off voltage become failing paths at a lower one. Lowering the voltage while keeping the clock would therefore not slow the circuit gracefully; it would produce setup violations, which in a synchronous design means a flip-flop captures the previous cycle’s value and the machine computes the wrong answer.
There is a subtlety that matters for robustness: not all paths fail at the same voltage. The critical path at one operating point may not be the critical path at another, because delay does not scale uniformly with voltage across gate types and fanouts. Designs therefore close timing at every operating point in the table, not just at the extremes, and the table’s voltages are chosen with margin rather than derived from a single formula.
The reverse direction has its own failure. Raising the voltage raises the delay through nothing but increases the short-circuit current and the gate oxide stress. Circuits are specified with a maximum supply, and the regulator must never exceed it, which is why voltage changes are bounded by a hardware limit rather than by firmware policy alone.
Domain boundaries cost level shifters and synchronisers
A chip with two voltage domains has signals crossing between them, and those crossings need translation.
A signal driven at 0.7 V into a receiver powered at 1.0 V may not reach the receiver’s threshold, so the receiver can settle at an intermediate level and draw crowbar current through its input stage. A level shifter converts the swing. It costs a few transistors per signal, and it adds delay, which is why crossing a domain boundary is slower than staying inside one.
A signal crossing between two asynchronous clock domains has a worse problem: the receiver’s flip-flop can sample the input while it is changing, and the resulting metastable state resolves after an unpredictable delay. No amount of level shifting fixes this; the crossing needs a synchroniser, a chain of flip-flops in the destination domain, which reduces the probability of failure to an acceptable level rather than eliminating it. The probability of a metastable event surviving $n$ synchroniser stages falls exponentially with $n$ and with the clock period, which is why the depth is chosen against a target failure rate rather than picked by habit.
The architectural consequence is that independently scalable domains are not free. Every signal that crosses a boundary pays delay, area, and a synchronisation constraint, so designers group logic into domains that are mostly self-contained. A core and its private cache belong together; a core and the shared last-level cache usually do not scale independently, because the traffic between them is high and every crossing would need translation.
Operating points as a scheduling resource
Once domains can be scaled independently, the question becomes which domain to slow down. The answer is not uniform, because the workload’s bottleneck moves.
A memory-bound phase gains nothing from a faster core, since the core is waiting on a cache miss that takes a fixed number of memory cycles. Slowing the core during such a phase reduces power with almost no throughput loss, provided the memory side keeps its operating point. The memory controller and the DRAM interface are often in a separate domain for exactly this reason.
A compute-bound phase is the opposite: the core’s frequency is throughput, and lowering it costs performance proportionally. The efficient response is to run at the highest operating point the thermal budget allows and let the memory side idle.
A latency-bound phase, such as pointer chasing through a linked structure, sits between the two. The core is stalled much of the time, but each stall is a dependent load, so the time to complete the chain is the sum of the latencies and lowering the core’s frequency lengthens the non-memory part of each step. This is the pattern that makes prefetching and out-of-order execution valuable, because both convert a serial chain of waits into overlapping work, and it is the reason a latency-bound phase gains less from a higher operating point than a compute-bound one does.
The scheduler’s problem is that it does not know which phase it is in without measurement. Hardware performance counters can report the ratio of stalled cycles to executed cycles, and the operating system can use that ratio to choose a point, which is the basis of the cpufreq governors on Linux and of the equivalent mechanisms elsewhere. A governor that reacts to utilisation alone gets the memory-bound case wrong, because utilisation is high while the core is stalled.
Transition cost versus steady-state gain
The value of a transition is the energy saved at the new point times the time spent there, minus the energy and time lost in the transition. Because the transition costs tens of microseconds and the settling is bounded by the regulator, the break-even is not instantaneous.
For a domain that will be busy for a millisecond, a transition is clearly worth it. For one that will be busy for a few microseconds, the transition costs more than it saves, and the correct policy is to stay at the current point. Real governors therefore apply a rate limit: they will not change the operating point more often than some minimum interval, and they bias toward the point that is likely to be needed next rather than the point that is optimal for the last interval.
The same reasoning extends to entering and leaving low-power states. A domain that is about to be idle can be dropped to the lowest operating point, but if it must wake and serve a request within a microsecond, the wake-up sequence is the dominant cost, and staying at a mid-point is better. The layering of these mechanisms, and their break-evens, is the subject of Clock and Power Gating.
What the abstraction hides
The operating system sees a list of performance states and a transition latency. Behind that abstraction sit a divider, a regulator, a settling time that depends on load, level shifters at domain boundaries, and a timing sign-off at every point in the table. Each of those is a place where a naive assumption fails: a table entry that the hardware cannot actually reach, a regulator that cannot follow a rapid sequence of requests, a domain boundary whose synchroniser latency makes a cross-domain handoff slower than expected.
The practical rule is to treat an operating-point change as a slow operation with a known cost, to request it in advance when the workload’s phase is predictable, and to leave the domain at a stable point when it is not. That is a scheduling decision expressed in microseconds, and it is as much part of the power budget as the transistor-level arithmetic in The Power Wall.
References
- Advanced Configuration and Power Interface (ACPI) Specification — UEFI Forum
- IEEE 1801: Standard for Design and Verification of Low-Power, Energy-Aware Electronic Systems — IEEE
- Low-Power CMOS VLSI Circuit Design — Kaushik Roy and Sharat Prasad, Wiley