Sequential Design
Storage and state: latches against flip-flops, the D/T/JK families and how they convert, counters and clock dividers, shift registers and serial conversion, and the Moore/Mealy state machine encodings, with a live stepper for each.
Latches and Flip-Flops: Where a Circuit Gets a Memory
Combinational logic has no memory: its output is a function of its inputs right now. A latch breaks that by feeding its output back to its input, creating two stable states that persist after the inputs change. A flip-flop refines it further, sampling only at a clock edge rather than whenever the enable is high - and that single difference, level-sensitive versus edge-sensitive, is what makes synchronous design possible and is the distinction most often blurred.
How it is built
- Two cross-coupled inverters have two stable states and will hold either indefinitely. Every static storage element is that structure with a way to force it into the state you want.
- An SR latch adds set and reset inputs. It is the primitive, and its illegal state - both inputs asserted - is why it is rarely used directly.
- A D latch is transparent while its enable is high: the output follows the input. When the enable goes low it holds whatever was there. Transparency is the problem, because a change during the high period passes straight through.
- A D flip-flop is two latches in series with opposite enables - a master and a slave. Only one is transparent at a time, so data captured at the edge cannot ripple onward, and the output changes only at that edge.
- Setup and hold times are the consequence of the internal feedback: the input must be stable before the edge for the master to resolve, and after it for the slave to capture. Violate either and the output is undefined for a time.
- Other types are conveniences built on D: a T flip-flop toggles when its input is high, a JK adds a toggle case to SR. All of them are a D flip-flop with logic on the input, and modern design uses D almost exclusively.
Design procedure
- Use edge-triggered flip-flops throughout unless there is a specific reason not to. A design of D flip-flops on one clock is analysable; a mixture of latches and flip-flops usually is not.
- Treat an inferred latch in synthesis as a bug until proven otherwise. It almost always means an incomplete if or case statement rather than a deliberate choice.
- Check setup and hold against the actual path delays, remembering that hold violations do not improve with a slower clock - they are a race, not a speed problem.
- Reset every flip-flop whose initial state the design depends on, and be deliberate about synchronous versus asynchronous reset.
- Keep a single clock edge convention. Mixing rising and falling edges halves the available path time and makes timing analysis much harder to reason about.
- For any signal crossing between clock domains, use a synchroniser rather than a plain flip-flop - a single flop is not enough to make an asynchronous input safe.
Key terms
- Latch
- Level-sensitive: transparent while enabled, holds when not.
- Flip-flop
- Edge-triggered: samples only at a clock edge.
- Master-slave
- Two latches with opposite enables. How a flip-flop is built.
- Setup time
- How long the input must be stable before the edge.
- Hold time
- How long it must remain stable after. A race, not a speed limit.
- Clock-to-Q
- Delay from the edge to the output changing.
- Inferred latch
- Storage synthesis created from an incomplete assignment. Nearly always a bug.
- Metastability
- The undefined state after a timing violation, which resolves in an unbounded time.
Worked example
An incomplete case statement - three of four select values assigned, the fourth left out - infers a latch. The design simulates correctly because the untested value never occurs in the testbench, and synthesis reports a latch that nobody reads. In silicon that latch is transparent for part of every cycle, so a glitch on its input passes through to logic that assumed a stable value. The failure is intermittent, temperature-dependent and traced back to one missing default line.Common pitfalls
Counters and Clock Dividers: Counting Is Sequencing
A counter is a register that advances through a sequence of states on each clock edge. That makes it the simplest useful state machine and one of the most common structures in any design - it generates addresses, times delays, divides clocks and sequences operations. The design choices are the count encoding and whether the carry chain is rippled or synchronous, and both have consequences that show up as glitches rather than as wrong counts.
How it is built
- A synchronous counter clocks every flip-flop from the same edge, with combinational logic deciding each bit's next value. Every output changes together, so a decode of the count is glitch-free apart from the usual settling.
- A ripple counter clocks each stage from the previous stage's output. It is far smaller and its bits change at different times, so any decode of the count sees transient values that never legitimately occurred.
- That transient is the reason ripple counters are unsuitable wherever the count is decoded - a terminal-count decode on a ripple counter produces a glitch as the bits settle, which can trigger downstream logic.
- A binary counter's worst case changes every bit at once, which is a large simultaneous current draw. A Gray-code counter changes exactly one bit per step, which both removes the decode transient and eases the current spike.
- Gray coding is why FIFO pointers crossing clock domains are Gray-coded: with one bit changing, a pointer sampled mid-transition is either the old value or the new one, never a mixture.
- Clock division by a power of two is free - each stage divides by two. Division by an odd number requires a modulo counter and, for a 50% duty cycle, both clock edges.
Design procedure
- Use a synchronous counter unless the size saving genuinely matters and nothing decodes the count.
- Gray-code any counter whose value crosses a clock domain, so a mid-transition sample is always one of the two adjacent values.
- For a modulo-N counter, decide whether to count up and reset at N-1 or down and reload at zero. Down-counting to zero is often smaller because zero-detect is cheaper than comparison.
- Register any decode of the count rather than using it combinationally, so settling transients are never observed.
- For odd division with a 50% duty cycle, use both clock edges - one path on the rising edge and one on the falling, combined.
- Check the terminal count and rollover explicitly. Off-by-one at the wrap is the most common counter bug and the least visible in normal operation.
Key terms
- Synchronous counter
- All flip-flops on one edge. Outputs change together.
- Ripple counter
- Each stage clocks the next. Small, and its bits change at different times.
- Terminal count
- The value at which the counter wraps or reloads.
- Gray code
- One bit changes per step. Safe to sample across clock domains.
- Modulo-N
- Counting to N and wrapping, rather than to a power of two.
- Duty cycle
- Fraction of the period spent high. Odd division needs both edges for 50%.
- Decode glitch
- A transient value seen while a ripple counter's bits settle.
Worked example
A 4-bit ripple counter going from 7 (0111) to 8 (1000) does not change all four bits at once. Bit 0 falls, which clocks bit 1, which falls and clocks bit 2, and so on - so the output passes through 0110, 0100 and 0000 before settling at 1000. A combinational decode looking for 0000 fires spuriously every time the counter passes 7 to 8. The count is never wrong when read at the right moment; the decode is wrong because it looks at the wrong moment.Common pitfalls
Shift Registers: Serial and Parallel, and the Conversion Between
A shift register is a chain of flip-flops in which each stage takes the previous stage's output on every clock. That single structure does a remarkable number of jobs: it converts between serial and parallel form, delays a signal by a known number of cycles, multiplies and divides by powers of two, and with feedback generates pseudo-random sequences. Almost every serial interface has one at each end.
How it is built
- Serial-in parallel-out accepts one bit per clock and presents the accumulated word on its outputs. It is the receiver in any serial protocol.
- Parallel-in serial-out loads a word and shifts it out one bit at a time. It is the transmitter, and the load is a mux on each stage's input choosing between the parallel value and the previous stage.
- As a delay line, an n-stage shift register delays a signal by exactly n clocks. This is how pipelines keep control signals aligned with the data they belong to.
- Shifting left multiplies by two and shifting right divides by two - for unsigned values. A signed right shift must replicate the sign bit, and using a logical shift on signed data is a classic error.
- With XOR feedback from selected taps, a shift register becomes a linear-feedback shift register, cycling through 2^n - 1 states in a pseudo-random order. That is the basis of CRC calculation, scrambling and built-in self test.
- An LFSR never enters the all-zeros state, which is why its period is 2^n - 1 rather than 2^n, and why it must not be initialised to zero.
Design procedure
- Match the shift direction to the protocol. Most serial links are MSB-first and some are LSB-first, and getting it backwards produces a bit-reversed byte.
- Decide whether the register shifts on every clock or only when enabled, and make the enable explicit rather than gating the clock.
- For delay-line use, count the stages against the pipeline depth being matched - one stage per pipeline register, no more and no fewer.
- For signed arithmetic use an arithmetic right shift that replicates the sign bit, not a logical one that shifts in zeros.
- For an LFSR, pick tap positions from a table of maximal-length polynomials and seed it with any non-zero value.
- Verify the parallel load does not disturb the shift on the same edge - load and shift on one clock is a common source of an off-by-one.
Key terms
- SIPO / PISO
- Serial-in parallel-out and its inverse. The receiver and transmitter.
- Delay line
- n stages delay a signal by exactly n clocks. Keeps control aligned with data.
- Arithmetic shift
- Right shift replicating the sign bit. Required for signed division by two.
- LFSR
- Shift register with XOR feedback. Cycles 2^n - 1 states pseudo-randomly.
- Maximal length
- Tap positions giving the full 2^n - 1 period. Taken from a table.
- Lock-up state
- All zeros in an LFSR, which never exits. Never seed it there.
- Shift enable
- Explicit control, in preference to gating the clock.
Worked example
A CRC-16 calculation is a 16-bit shift register with XOR taps at the polynomial's set bits. Each data bit is XORed into the feedback and the register shifts once, so a whole message is processed one bit per clock with sixteen flip-flops and three XOR gates. The same structure, seeded non-zero and left to run, is a pseudo-random generator with a period of 65,535 - and if it is ever seeded with zero it produces zeros forever, which is why every CRC specification states its initial value.Common pitfalls
State Machines: Turning a Sequence Into Hardware
A finite state machine is a register holding the current state plus combinational logic computing the next state and the outputs. That is all of it - and it is the standard way to implement any behaviour described as a sequence of steps with conditions between them. The one structural choice that matters is whether outputs depend on the state alone (Moore) or on the state and the inputs together (Mealy), because it decides whether the outputs are glitch-free.
How it is built
- A Moore machine's outputs are a function of the state register only. They change only after a clock edge, so they are glitch-free and delayed by one cycle relative to the input that caused them.
- A Mealy machine's outputs depend on the state and the current inputs, so they respond one cycle sooner and inherit any glitch on those inputs. That difference is the whole trade.
- State encoding is a real choice. Binary uses the fewest flip-flops; one-hot uses one per state and makes the next-state logic much simpler, which on an FPGA - where flip-flops are plentiful and logic is the constraint - is usually faster.
- Gray encoding is used where the state value crosses a clock domain, for the same reason as in counters: one bit changes per transition.
- Every state machine needs a defined reset state and a defined behaviour for unreachable states. A one-hot machine with a corrupted register can enter a state that is not in the diagram, and without a default it stays there.
- The output logic should be written separately from the next-state logic. Combining them is how a Moore machine quietly becomes a Mealy one and picks up glitches nobody intended.
Design procedure
- Draw the state diagram before writing code: states as circles, transitions as labelled arrows, and outputs marked in the state for Moore or on the arrow for Mealy.
- Check the transitions out of every state are complete and mutually exclusive - every input combination must lead somewhere, and only one somewhere.
- Choose Moore unless the extra cycle of latency genuinely matters. Glitch-free outputs are worth a cycle in most designs.
- Pick the encoding from the target: one-hot on an FPGA, binary where flip-flops are expensive, Gray where the state crosses domains.
- Write next-state logic, output logic and the state register as three separate blocks. Mixing them is the source of most state-machine bugs.
- Define reset and a default for unreachable states, so a corrupted state register recovers rather than locking up.
Key terms
- Moore
- Outputs from the state alone. Glitch-free, one cycle later.
- Mealy
- Outputs from state and inputs. One cycle sooner, and can glitch.
- One-hot
- One flip-flop per state. More registers, much simpler next-state logic.
- State diagram
- The specification. Circles for states, labelled arrows for transitions.
- Unreachable state
- Not in the diagram but physically possible. Needs a defined exit.
- Next-state logic
- Combinational function of state and inputs. Written separately from outputs.
- Reset state
- Where the machine starts. Must be explicit.
Worked example
A UART receiver is a five-state Moore machine: idle, start, data, parity, stop. In idle it waits for a falling edge; in start it samples at the half-bit point to confirm the start is real; in data it samples every bit time and shifts into a register; in stop it checks for a high level and asserts 'byte ready'. Making it Moore means 'byte ready' is a clean single-cycle pulse from the state register. Making it Mealy would assert it a cycle earlier and inherit any glitch on the sampled input, which for a signal arriving from outside the chip is exactly the wrong property.Common pitfalls
Latches and flip-flops: the difference that matters
A latch is level-sensitive: while its enable is asserted, its output follows its input. A flip-flop is edge-triggered: it samples only at a clock transition and holds the value for the rest of the cycle. That distinction decides whether a design is synchronous, and almost every hard-to-find bug in sequential logic traces back to a latch appearing where a flip-flop was intended - usually because an HDL description was incomplete rather than because anyone chose one.
How it is built
- An SR latch is two cross-coupled NOR or NAND gates, and is the storage element every other one is built from.
- A D latch adds an enable so the stored value follows D while enabled and holds when not.
- A D flip-flop is two D latches in a master-slave arrangement on opposite clock phases, so the value changes only at an edge.
- The transparent window of a latch is what makes timing analysis hard: data can flow through it mid-cycle, so paths do not end where the schematic suggests.
- T and JK flip-flops are D flip-flops with input logic: T toggles on 1, JK toggles when both inputs are high.
Design procedure
- Use edge-triggered flip-flops for essentially all synchronous design; reach for a latch only with a specific reason.
- In HDL, assign every output in every branch of a combinational block, since an incomplete assignment infers a latch silently.
- Check synthesis reports for inferred latches and treat every one as a defect until proven deliberate.
- Convert between flip-flop types with input logic rather than swapping cells: T from D is D = Q xor T.
- Give every flip-flop a defined reset, and decide deliberately whether it is synchronous or asynchronous.
Key terms
- Level-sensitive
- Follows the input the whole time the enable is active. A latch.
- Edge-triggered
- Samples only at a clock transition. A flip-flop.
- Master-slave
- Two latches on opposite clock phases, which is how an edge-triggered flip-flop is built.
- Inferred latch
- A latch created by an incomplete HDL assignment rather than by intent. Almost always a bug.
- Transparency
- The interval during which a latch passes its input straight through to its output.
Worked example
The incomplete assignment that creates a latch:
always @(*) begin
if (sel)
y = a; // no else branch
end
When sel is 0, y must keep its previous value - which requires
storage. The synthesiser infers a latch, the design picks up a
transparent path nobody analysed, and it usually still passes
simulation.
always @(*) begin
if (sel) y = a;
else y = b; // every branch assigns
end // pure combinational, no storage
And the type conversions, which are input logic rather than different cells:
T from D D = Q xor T
JK from D D = J·Q' + K'·Q
D from T T = D xor Q
Modern libraries provide the D flip-flop and synthesise the rest.Common pitfalls
Counters, dividers, and the encoding you choose
A counter is a state machine whose next state is its current state plus one, and its design choices are more consequential than that description suggests. The encoding - binary, Gray, one-hot, ring - decides how many bits change per step, and that in turn decides whether the count can be read reliably by anything that is not synchronised to the same clock. Getting that wrong produces a value that was never counted.
How it is built
- A synchronous counter clocks every flip-flop from the same edge, with combinational logic computing the next value.
- A ripple counter clocks each stage from the previous stage's output; it is smaller and its stages settle at different times, so the intermediate value is briefly wrong.
- A Gray-code counter changes exactly one bit per step, so a reader that samples mid-transition sees either the old or the new value, never a third one.
- A ring counter is one-hot and needs no decode; a Johnson counter is a twisted ring giving 2n states from n flip-flops.
- Clock division by a power of two is a ripple of toggle flip-flops; division by an odd number needs both clock edges to keep the duty cycle even.
Design procedure
- Use a synchronous binary counter by default; the extra logic is worth the defined settling behaviour.
- Use Gray coding for any counter read across a clock domain, which is what makes an asynchronous FIFO's pointers safe.
- Avoid ripple counters where the value is decoded, since the transient wrong values will produce glitches on the decode.
- For odd division, clock one path on the rising edge and one on the falling and combine them, or accept an uneven duty cycle.
- Define the behaviour at terminal count explicitly - wrap, saturate, or stop - rather than letting the encoding decide.
Key terms
- Synchronous counter
- All stages clocked together. Predictable settling, more logic.
- Ripple counter
- Each stage clocks the next. Minimal logic, staggered outputs, transient wrong values.
- Gray code
- An encoding where consecutive values differ in one bit. Safe to sample asynchronously.
- Johnson counter
- A ring with the feedback inverted, giving 2n states from n flip-flops.
- Terminal count
- The output marking the counter's maximum, used to cascade stages or trigger an action.
Worked example
Why a binary counter cannot be read across clock domains:
0111 -> 1000 ALL FOUR BITS change
A reader in another domain samples during the transition and the
bits have not all arrived. It can capture 1111, or 0000, or any
of the sixteen combinations - values the counter never held.
Gray code, same sequence:
0000 0001 0011 0010 0110 0111 0101 0100
1100 1101 1111 1110 1010 1011 1001 1000
0101 -> 0100 ONE bit changes
A mid-transition sample gets either 0101 or 0100. Both are real
values, and both are at most one count stale, which is why every
asynchronous FIFO carries its pointers in Gray code.
And odd division, where the naive approach fails:
divide by 3 with rising edges only -> 33% or 67% duty cycle
divide by 3 using both edges -> 50%, at the cost of a
second flip-flop chainCommon pitfalls
Shift registers and serial conversion
A shift register moves its contents one position per clock, and that single behaviour covers a surprising range of uses: converting between serial and parallel form, delaying a signal by a known number of cycles, building a pattern generator, and synchronising an asynchronous input. Every serial protocol on a board has a shift register at each end, and the direction it shifts is a protocol decision rather than an implementation detail.
How it is built
- Serial-in parallel-out collects a bit per clock and presents the assembled word; parallel-in serial-out does the reverse.
- The shift direction decides bit order on the wire, which is why SPI has a bit-order configuration and why getting it wrong reverses every byte.
- A universal shift register adds mode control for hold, shift left, shift right and parallel load.
- With XOR feedback from selected taps it becomes a linear feedback shift register, generating a pseudorandom sequence of length 2^n - 1.
- Two flip-flops in series form the standard synchroniser, which is a two-stage shift register used for its metastability properties rather than for shifting.
Design procedure
- Match the shift direction to the protocol's bit order, and verify it against a capture rather than against the datasheet alone.
- Load in parallel and shift out for transmission; shift in and read in parallel for reception.
- Use an LFSR where a cheap pseudorandom sequence is needed, and remember the all-zeros state is unreachable and self-locking.
- Size a delay line in clock cycles, not in time, and restate the delay whenever the clock frequency changes.
- Use exactly two stages for a standard synchroniser, adding a third only where the metastability budget demands it.
Key terms
- SIPO / PISO
- Serial-in parallel-out and its reverse. The two halves of a serial link.
- LFSR
- A shift register with XOR feedback, producing a maximal-length pseudorandom sequence.
- Maximal length
- 2^n - 1 states: every value except the one that would lock the register.
- Synchroniser
- Two chained flip-flops that let a metastable first stage settle before the second samples it.
- Delay line
- A shift register used purely to align a signal by a fixed number of cycles.
Worked example
The same eight bits, two directions:
MSB first 0xA5 = 1010_0101
wire sees: 1 0 1 0 0 1 0 1
LSB first wire sees: 1 0 1 0 0 1 0 1 ... reversed
= the receiver assembles 0xA5 only if it
shifts in the same direction
A mismatch does not fail loudly. It delivers bit-reversed bytes
that often still look like plausible data, which is why the first
thing to check on a garbled serial link is bit order.
And the LFSR's unreachable state:
4-bit, taps at 4 and 3: next = Q4 xor Q3, shifted in
0000 -> feedback is 0 xor 0 = 0 -> 0000 forever
All-zeros is a fixed point. The register must be seeded with
anything else, and 'anything else' includes whatever reset leaves
behind - so an LFSR without an explicit non-zero seed can come up
dead and stay dead.Common pitfalls
State machines: Moore, Mealy, and the encoding
A finite state machine is the general form every sequential circuit is a special case of: a state register, next-state logic, and output logic. The two classical shapes differ only in what the outputs depend on - Moore outputs depend on the state alone, Mealy outputs depend on the state and the current inputs - and that difference decides both the latency and whether the outputs can glitch.
How it is built
- Moore: outputs are a function of the current state only, so they are stable for a whole clock period and change one cycle after the input that caused them.
- Mealy: outputs are a function of state and input, so they respond in the same cycle and inherit any glitch on the input.
- A Mealy machine generally needs fewer states than the equivalent Moore machine, because the output carries some of the information the extra states would encode.
- State encoding is a real choice: binary minimises flip-flops, one-hot minimises next-state logic and is usually faster in an FPGA.
- Unreachable states must still be handled; a glitch or an upset can put the register into one, and without a defined recovery the machine is stuck.
Design procedure
- Draw the state diagram before writing any logic, and mark which outputs belong to states and which to transitions.
- Choose Moore where the output drives something timing-sensitive, and Mealy where a cycle of latency matters more than glitch-freedom.
- Use one-hot encoding in FPGAs, where flip-flops are plentiful and logic depth is the constraint; use binary in ASICs where area dominates.
- Register a Mealy output when it must be glitch-free, which converts it to a Moore output one cycle later.
- Add a default branch returning to a known state, so an illegal encoding recovers rather than hanging.
Key terms
- Moore machine
- Outputs depend on state alone. Stable for the whole cycle, one cycle of latency.
- Mealy machine
- Outputs depend on state and input. Immediate response, can glitch.
- One-hot encoding
- One flip-flop per state, exactly one set. More registers, simpler and faster next-state logic.
- Unreachable state
- An encoding the design never enters deliberately. Still reachable by an upset.
- Registered output
- A Mealy output passed through a flip-flop, trading a cycle of latency for a clean edge.
Worked example
The same detector, both shapes:
Detect the sequence 1 0 1 on input x.
MOORE MEALY
S0 --1--> S1 S0 --1/0--> S1
S1 --0--> S2 S1 --0/0--> S2
S2 --1--> S3 (out=1) S2 --1/1--> S1
4 states, output on S3 3 states, output on the transition
Moore asserts one cycle after the final 1 arrives, and the pulse
is exactly one clock wide and glitch-free.
Mealy asserts during the same cycle as the final 1, and if x has
a glitch the output has one too.
And the encoding trade:
4 states, binary 2 flip-flops, next-state logic decodes 2 bits
4 states, one-hot 4 flip-flops, next-state logic is one OR term
per state - shallower, so a faster clockCommon pitfalls
More in Digital Electronics
- Combinational BlocksEvery combinational building block in one place: multiplexers and demultiplexers, encoders and priority encoders, decoders and address decoding, and the arithmetic circuits from half adder through carry-lookahead. Each with a live explorer and the propagation-delay cost that decides which one you use.
- Timing, Hazards & MetastabilityWhat breaks when logic meets a clock: setup and hold windows, propagation delay and clock skew, static and dynamic hazards, metastability and the synchroniser chain, switch debouncing, and arbitration between requesters that can collide.
- Boolean Algebra & GatesBoolean algebra, the gate set it maps onto, and Karnaugh-map minimisation: the identities that let an expression be rewritten, why NAND and NOR are functionally complete, how a truth table becomes a minimal sum of products, and where don't-care terms come from in real designs.
- Logic Levels & InterfacingThe electrical contract under the logic: threshold voltages and noise margins across TTL, CMOS and LVCMOS families, level shifting and open-drain interfacing, fan-out and drive strength, and where dynamic and static power actually goes.
- Digital ElectronicsGates, Boolean algebra, K-maps, muxes, encoders, decoders, flip-flops, arithmetic circuits, counters and debouncing.