Clock-driven components with synchronous reset and enable signals. State that persists across clock cycles.
Sequential logic is what gives digital circuits memory. While combinational logic computes outputs purely from current inputs, sequential components capture and hold values at specific moments in time, determined by a clock signal. On each rising edge of the clock, the circuit samples its inputs and updates its internal state. Between clock edges, outputs remain stable regardless of input changes.
This distinction is fundamental: combinational logic answers "what should the output be given these inputs right now?" while sequential logic answers "what should the output be given these inputs and everything that happened before?" Counters, shift registers, state machines, and pipeline registers all rely on sequential behavior.
| Property | Combinational | Sequential |
|---|---|---|
| Clock | Not used | Required (rising edge triggered) |
| State | None | Stored in flip-flops/registers |
| Output depends on | Current inputs only | Current inputs + stored state |
| RHDL keyword | behavior | sequential |
| Reset | Not applicable | Synchronous reset to known state |
In RHDL, the sequential keyword declares a clock-driven block. You specify the clock signal, an optional reset signal, and reset values for all stateful outputs. On each rising clock edge, all assignments within the block take effect simultaneously. When reset is asserted, outputs snap to their declared reset values.
class DFlipFlop < RHDL::Sim::Component
input :clk, :rst
input :d, width: 8
output :q, width: 8
# Sequential block: updates on rising edge of clk
# Synchronous reset sets q to 0
sequential clock: :clk,
reset: :rst,
reset_values: { q: 0 } do
q <= d
end
end
An enabled register only updates its value when the enable signal is high. This is essential for building pipeline registers that can be stalled, or data registers that should hold their value until explicitly written.
class EnabledRegister < RHDL::Sim::Component
input :clk, :rst, :en
input :d, width: 16
output :q, width: 16
sequential clock: :clk,
reset: :rst,
reset_values: { q: 0 } do
# Only update when enable is asserted
q <= cond(en, d, q)
end
end
Registers and counters are the most common sequential building blocks. A counter increments (or decrements) on each clock cycle, optionally wrapping around or stopping at a limit. These are used everywhere: address generators, timers, clock dividers, and control sequencers.
A parameterized up-counter with configurable width and maximum value. When the counter reaches its limit, it wraps back to zero.
class Counter < RHDL::Sim::Component
parameter :WIDTH, default: 8
parameter :MAX, default: 255
input :clk, :rst, :en
output :count, width: WIDTH
output :wrap
sequential clock: :clk,
reset: :rst,
reset_values: { count: 0 } do
wrap <= count.eq?(MAX) & en
count <= cond(en,
cond(count.eq?(MAX), 0, count + 1),
count)
end
end
A shift register that shifts data in serially and provides parallel output. Useful for serial-to-parallel conversion, SPI interfaces, and delay lines.
class ShiftRegister < RHDL::Sim::Component
parameter :WIDTH, default: 8
input :clk, :rst
input :serial_in
input :shift_en
input :load_en
input :parallel_in, width: WIDTH
output :parallel_out, width: WIDTH
output :serial_out
sequential clock: :clk,
reset: :rst,
reset_values: {
parallel_out: 0
} do
serial_out <= parallel_out[WIDTH - 1]
parallel_out <= cond(load_en,
parallel_in,
cond(shift_en,
{ parallel_out[WIDTH - 2..0], serial_in },
parallel_out))
end
end
Understanding timing is critical for reliable sequential designs. Every flip-flop has setup and hold time requirements that constrain how fast the clock can run. RHDL's sequential model abstracts away the analog details but the designer must still reason about timing at the architecture level.
| Concept | Description |
|---|---|
| Setup time | Data must be stable before the clock edge. Limits maximum clock frequency based on the longest combinational path between registers. |
| Hold time | Data must remain stable after the clock edge. Ensured by minimum propagation delay through combinational logic. |
| Clock-to-Q delay | Time from clock edge until the register output is valid. Adds to the critical path of downstream logic. |
| Synchronous reset | Reset is sampled on the clock edge, like any other input. RHDL uses synchronous reset by default for cleaner synthesis. |
| Asynchronous reset | Reset takes effect immediately, regardless of the clock. Used when the circuit must reach a known state without waiting for a clock edge (e.g., power-on). |
| Metastability | When signals cross clock domains, they must be synchronized using multi-stage flip-flop chains to avoid metastable states. |
A two-stage synchronizer for safely crossing clock domains. The input signal is sampled twice through flip-flops in the destination clock domain, dramatically reducing the probability of metastable values propagating into the design.
class Synchronizer < RHDL::Sim::Component
input :clk, :rst
input :async_in
output :sync_out
# Internal pipeline stage
signal :meta
sequential clock: :clk,
reset: :rst,
reset_values: {
meta: 0,
sync_out: 0
} do
# Two flip-flop synchronizer chain
meta <= async_in # first stage (may go metastable)
sync_out <= meta # second stage (resolved)
end
end