VHDL · Chapter 7.2 · Sequential Logic Design
Detecting the Clock Edge
A register exists because something happens on a clock edge, a transition rather than a level. In VHDL you express that with the rising-edge and falling-edge functions, which are true only at the instant the clock changes from 0 to 1 or from 1 to 0. That edge is precisely what makes synthesis infer a flip-flop instead of combinational logic or a latch. This lesson covers the edge-detection functions, why the rising-edge function is the modern form preferred over the older clock-event-and-equals-one style because it is metavalue-safe and states intent clearly, how to choose rising versus falling, and why a clocked process keys on exactly one edge of one clock. Getting this right is the foundation of every synchronous circuit you will design.
Foundation13 min readVHDLClock Edgerising_edgeFlip-FlopSynchronousRTL
1. Engineering intuition — capture on a transition, not a level
A flip-flop samples its input at the moment the clock transitions, then holds that value until the next transition. The key word is moment: it is the edge that matters, not whether the clock is high or low. A level-sensitive element (transparent while high) is a latch; an edge-sensitive element (captures at the transition) is a flip-flop. So detecting the clock edge — the 0-to-1 transition — is exactly what tells VHDL "build a flip-flop here," and it is the single ingredient that turns a process from combinational into sequential.
2. Formal explanation — rising_edge and why it is preferred
-- MODERN, preferred: a function from std_logic_1164, true only on the 0→1 transition.
if rising_edge(clk) then ... end if;
if falling_edge(clk) then ... end if; -- the 1→0 transition
-- OLDER form (still seen): clk changed AND its new value is '1'.
if clk'event and clk = '1' then ... end if; -- equivalent intent, but less saferising_edge(clk) is a function (from std_logic_1164) that returns true only for a genuine 0-to-1
transition of a std_logic clock. It is preferred over clk'event and clk = '1' because it is
metavalue-safe (it correctly ignores transitions involving 'U'/'X'/'Z', which the naive form
can misread) and it states intent plainly. Use rising_edge/falling_edge; reserve the
clk'event form for legacy code you are reading, not writing.
3. Production RTL — the edge makes the register
library ieee; use ieee.std_logic_1164.all;
-- The rising_edge guard is what infers a flip-flop for q.
ff : process (clk)
begin
if rising_edge(clk) then -- edge → register
q <= d;
end if;
end process;
-- Without the edge guard, the same assignment is combinational / a latch — NOT a register.
-- y <= d; -- combinational wire, no storageWhat hardware does this become? With the rising_edge(clk) guard, q is a flip-flop that captures
d on each rising edge. Remove the guard and there is no flip-flop — just a wire (or a latch if the
assignment is conditional and incomplete). The edge detection is the difference between a register and
no register.
4. Hardware interpretation — edge vs level
5. Simulation interpretation — capture only at the edge
rising_edge(clk): d is sampled only at the rising edges
8 cycles6. Debugging example — clk'event misread, or a level used
Expected: an edge-triggered register. Observed: a metavalue glitch at time zero produces a
spurious clock (with the clk'event form), or a latch appears (with a level test). Root cause:
clk'event and clk = '1' can react to transitions out of 'U'/'X' that are not real rising edges; a
plain clk = '1' level test is not an edge at all and infers a latch. Fix: use rising_edge(clk),
which is true only for a clean 0-to-1 transition. Engineering takeaway: for clocked logic always use
rising_edge/falling_edge — they are edge-correct and metavalue-safe, unlike level tests or the naive
event form.
-- RISKY: reacts to spurious transitions from 'U'/'X' at startup; or (level) infers a latch.
-- if clk'event and clk = '1' then ... ; -- prefer rising_edge
-- if clk = '1' then q <= d; end if; -- LEVEL → latch, not a flip-flop
-- CORRECT: clean, metavalue-safe edge detection.
if rising_edge(clk) then q <= d; end if;7. Common mistakes & what to watch for
- Using a level test for a register.
clk = '1'is level-sensitive → a latch. Userising_edge(clk)for an edge-triggered flip-flop. - Preferring
clk'event and clk = '1'. It is older and not metavalue-safe;rising_edgeis the modern, robust choice. - Detecting both edges in one process. A clocked process keys on one edge of one clock; dual-edge logic is special and rarely portable.
- Mixing clock domains. One clock per clocked process; crossing domains needs synchronisers (later).
- Putting combinational logic under the edge guard unnecessarily. Anything inside
rising_edgebecomes registered; keep purely combinational logic outside.
8. Engineering insight & continuity
Edge detection is the hinge of sequential design: rising_edge(clk) is what converts a process into a
flip-flop, because flip-flops are defined by capturing at a transition, not a level. Make
rising_edge/falling_edge your reflex — they are correct, safe, and self-documenting — and reserve a
single edge of a single clock per clocked process so all your registers update together in one timing
domain. With the edge understood, the next lesson builds the element it creates: The D Flip-Flop —
the atom of all stateful hardware — followed by Registers (D flip-flops in parallel) and the
enables, counters, and shift registers that compose them.
Standards & specifications
- Governing standard
- IEEE Std 1076 (VHDL)(opens IEEE in a new tab)
Defines the VHDL language — types, the simulation cycle, and the semantics a conforming analyser and simulator must implement. Synthesis restrictions and vendor coding rules are tool behaviour, not language rules.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of VHDL Sequential Logic — Registers, Counters & State Machines.
