Sequential Logic: Storing State with Flip-Flops
A flip-flop is a circuit that stores one bit of state. Unlike combinational logic gates whose outputs depend only on current inputs, flip-flops have memory — their output depends on both current inputs and previous state. This makes them the fundamental building block of all sequential logic: registers, counters, state machines, and memory.
SR Latch: The Simplest Memory
The SR (Set-Reset) latch is built from two cross-coupled NOR gates (or NAND gates). It has two inputs and two complementary outputs:
- S (Set): when S=1, R=0, the output Q is forced to 1.
- R (Reset): when R=0, Q is forced to 0.
- S=0, R=0: the latch holds its current state (memory!).
- S=1, R=1: this is the forbidden/invalid state — both outputs go to 0 (for NOR-based), which is contradictory since Q and Q' should be complements.
| S | R | Q (next) | Q' (next) | State |
|---|---|---|---|---|
| 0 | 0 | Q (hold) | Q' (hold) | Memory |
| 0 | 1 | 0 | 1 | Reset |
| 1 | 0 | 1 | 0 | Set |
| 1 | 1 | ? | ? | Invalid |
D Flip-Flop: Data Capture on Clock Edge
The D (Data) flip-flop solves the SR latch's forbidden-state problem by providing a single data input D and a clock input. On the rising edge of the clock (transition from 0 to 1), the flip-flop captures the value of D and holds it at output Q until the next clock edge.
- D=1 at clock edge: Q becomes 1
- D=0 at clock edge: Q becomes 0
- Between clock edges: Q holds its value regardless of changes to D
The D flip-flop is the most widely used flip-flop in digital design. Every register in a CPU, every pipeline stage, and every synchronous counter uses D flip-flops.
JK Flip-Flop: The Toggle Flip-Flop
The JK flip-flop extends the SR latch by resolving the forbidden state. It has two inputs J and K:
- J=0, K=0: hold current state (no change)
- J=0, K=1: reset Q to 0
- J=1, K=0: set Q to 1
- J=1, K=1: toggle — Q flips to its complement
| J | K | Q (next) | Action |
|---|---|---|---|
| 0 | 0 | Q | Hold |
| 0 | 1 | 0 | Reset |
| 1 | 0 | 1 | Set |
| 1 | 1 | Q' | Toggle |
The toggle behavior (J=K=1) makes JK flip-flops useful for building binary counters — each flip-flop divides the clock frequency by 2.
Edge-Triggered vs Level-Triggered
- Level-triggered (latch): output can change whenever the enable signal is HIGH. Data "flows through" while the enable is active.
- Edge-triggered (flip-flop): output changes only at the clock edge (rising or falling). This is critical for synchronous design because it prevents race conditions — data is sampled at one precise instant.
Setup and Hold Time
For a flip-flop to correctly capture data, two timing constraints must be met:
- Setup time (tsu): D must be stable for at least tsu before the clock edge. This gives the internal gates time to propagate.
- Hold time (th): D must remain stable for at least th after the clock edge. This ensures the latch has fully captured the value.
Violating setup or hold time causes metastability — the flip-flop output oscillates unpredictably between 0 and 1 before eventually settling, which can cause system failures.
Real-Life: Sticky Light Switch
Think of an SR latch like a sticky light switch with two buttons — a "Set" button (turns on and stays on) and a "Reset" button (turns off and stays off). Pressing neither button leaves the light in its current state. Pressing both buttons at once is like giving contradictory orders — undefined behavior!
The D flip-flop is like a camera shutter: no matter how the scene changes between shots, the camera only captures what it sees at the precise instant the shutter clicks (the clock edge). The photo (Q) remains the same until the next click.
In real hardware:
- CPU Registers: a 64-bit register is 64 D flip-flops sharing the same clock, capturing a data word on each clock cycle
- Pipeline registers: between each pipeline stage (fetch, decode, execute, ...), flip-flops hold intermediate results so each stage can work independently
- Counters: a chain of JK flip-flops in toggle mode creates a binary counter — the foundation of timers and frequency dividers
- State machines: the current state of a finite state machine (FSM) is stored in flip-flops — traffic light controllers, protocol parsers, and CPU control units all use this pattern
- Clock domain crossing: when data moves between different clock domains, flip-flops are used as synchronizers to reduce metastability risk