VHDL · Chapter 7.5 · Sequential Logic Design
Clock Enables
A plain register captures every clock edge, but most real registers should update only sometimes: accumulate when data is valid, hold during a stall, or sample at a slow rate. The right mechanism is a clock enable. The clock keeps running on every flip-flop, and an enable signal decides whether the register takes new data or holds its current value. Crucially this gates the data path, not the clock. Internally it is a multiplexer that chooses between the new value and the register's own output, which keeps every flip-flop on the same free-running clock and keeps timing clean while still controlling updates. This lesson shows the enable pattern, how it maps to hardware, and why it is the correct alternative to physically gating the clock.
Foundation13 min readVHDLClock EnableRegisterStallSynchronousRTL
1. Engineering intuition — update on permission, hold otherwise
Think of a clock enable as a "should I update?" gate in front of a register. The clock still ticks on every cycle, but the register only acts on a tick when the enable says so; otherwise it keeps its current value. This is how you build accumulators that add only on valid data, pipelines that stall, counters that pause, and logic that samples once every N cycles. The key mental shift is that you are not stopping the clock — you are deciding, each cycle, whether to load new data or recirculate the old.
2. Formal explanation — enable inside the edge guard
library ieee; use ieee.std_logic_1164.all;
en_reg : process (clk)
begin
if rising_edge(clk) then -- clock always runs
if en = '1' then q <= d; end if; -- update only when enabled; else q HOLDS
end if;
end process;The enable is an ordinary if inside the rising_edge(clk) guard. When en = '1', the register
captures d; when en = '0', there is no assignment, so the register simply holds (a flip-flop's
natural behaviour with no else). Note en is not in the sensitivity list — only clk is; the
enable is sampled at the edge like any other data input.
3. Production RTL — accumulator with enable and stallable pipeline
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all;
-- Accumulator that adds only when a valid sample arrives.
acc : process (clk)
begin
if rising_edge(clk) then
if rst = '1' then sum <= (others => '0');
elsif valid = '1' then sum <= sum + unsigned(sample); -- update only on valid
end if; -- else sum holds
end if;
end process;
-- A pipeline stage that can stall: advance only when not stalled.
stage : process (clk)
begin
if rising_edge(clk) then
if stall = '0' then data_q <= data_in; end if; -- hold the stage while stalled
end if;
end process;What hardware does this become? Each is a register with an enable: the accumulator's flip-flops
update only when valid (and reset clears them), and the pipeline register loads only when not
stalled. The clock reaches every flip-flop every cycle; the enable controls the data, so the design
stays in one clean timing domain.
4. Hardware interpretation — a feedback mux, not a gated clock
5. Simulation interpretation — updates only on enabled edges
The register loads d only on edges where en=1; otherwise it holds
8 cycles6. Debugging example — enable in the sensitivity list, or a gated clock instead
Expected: a register that updates only when enabled. Observed: a simulation/synthesis mismatch,
or (worse) a design that gated the clock and now has glitches and timing problems. Root cause: for
the mismatch, en (or d) was wrongly added to the sensitivity list of a clocked process, or the
enable was placed outside the edge guard; for the clock issue, the designer ANDed en with clk to
"enable" the register — a gated clock, which creates glitch and skew hazards. Fix: put the enable as
an if inside rising_edge(clk), with only clk in the sensitivity list, and never gate the clock
for an enable. Engineering takeaway: a clock enable is data-path logic inside the edge guard — keep
the clock free-running and let en choose load-versus-hold.
-- WRONG: gating the clock to "enable" → glitches, skew, hard to time.
-- gated_clk <= clk and en; process(gated_clk) ... q <= d; ...
-- RIGHT: free-running clock, enable inside the edge guard.
process (clk) begin
if rising_edge(clk) then
if en = '1' then q <= d; end if;
end if;
end process;7. Common mistakes & what to watch for
- Gating the clock for an enable. Use a clock-enable (data-path) instead; gated clocks cause glitch and skew problems (lesson 7.8).
- Putting
enin the sensitivity list. Onlyclkbelongs there;enis sampled at the edge. - Placing the enable outside the edge guard. The enable
ifmust be insiderising_edge(clk)or it is not a clocked enable. - Forgetting reset interaction. Decide whether reset overrides the enable (usually yes — reset is unconditional within the edge).
- Assuming enable saves clock power by itself. A clock-enable saves data-path activity; true clock power gating is a separate, carefully-managed technique.
8. Engineering insight & continuity
The clock enable is the workhorse of controlled state: it lets a register update on permission while the clock keeps running, implemented as a quiet feedback mux rather than any clock surgery. That distinction — gate the data, not the clock — is one of the most important habits in synchronous design, because it preserves a single clean timing domain. With enables in hand you can build registers that pause, sample, and accumulate on demand. The next lesson applies exactly this to the most common stateful element: the Counter — a register that increments (with enable, load, and clear) — followed by the Shift Register, the other canonical sequential structure.