The Building Block: A D Flip-Flop
Everything in synchronous design comes back to one tiny piece of hardware: the D flip-flop. It has a clock input, a data input, and a data output. On each rising clock edge, it captures the value of D and holds it until the next edge. That's it.
In Verilog:
always @(posedge clk) begin
q <= d;
end
Three lines, one flip-flop. The <= is non-blocking, which is exactly the behavior of real flip-flops (covered in Blocking vs Non-blocking). The posedge clk sensitivity is what makes it sequential.
Stack many of these with combinational logic between them and you have any synchronous circuit you'd want to build.
A Register With Reset
Real designs always need a reset - a way to put the system into a known state at power-on or on demand:
That's a synchronous reset - the reset condition is evaluated on a clock edge like any other input. The synthesizer produces a flip-flop with a 2-to-1 mux on its data input: when reset is high, the mux feeds zero; otherwise it feeds d.
For most designs, synchronous reset is the right choice. It's simpler timing, it plays nicely with FPGAs, and the reset signal can come from anywhere - it doesn't need its own clock-aligned source.
A Register With Enable
Often you want a register that only updates when something tells it to. Use an if inside the clocked block, and rely on the implicit "hold previous value" behavior of the missing else:
This is the canonical "load-enabled register". It shows up everywhere - configuration registers, pipeline stages that only advance when downstream is ready, counters that pause and resume. The omission of the final else is deliberate and safe inside a clocked block: a flip-flop already remembers its previous value, so "do nothing" means "hold".
In a combinational block the same code would infer a latch. Different rules, same syntax.
A Counter
A counter is a register whose next value is its current value plus one:
The counter increments on every clock cycle when enable is high. After 16 cycles it wraps back to 0 (because we declared 4 bits and 15 + 1 overflows to 0). That wrapping is intrinsic to N-bit arithmetic and is exactly how a real hardware counter behaves.
A Shift Register
Stacking flip-flops gives you a shift register. The trick is to do all the shifts in one non-blocking statement:
The body is out <= {out[WIDTH-2:0], in} - concatenate the lower bits of the current out with the new in, and assign the whole thing. Because it's non-blocking, the RHS reads the old out before the LHS updates. The effect is a clean N-bit shift in a single clock cycle.
This is the shift-register pattern in its smallest form. It generalizes to LFSRs, serial transmitters, deserializers - any design where data moves through a chain of flip-flops on each clock.
Pipelines
A pipeline is a chain of registers separated by combinational logic. Each stage processes data from the previous stage and feeds the next:
Three stages, three cycles of latency, but a new result every cycle once the pipeline is full. The latency is 3 clocks because the data passes through three flip-flops; the throughput is 1 operation per clock because all three stages work simultaneously on different inputs.
This is how high-performance designs hit their throughput targets: keep stages short, pipeline more deeply, and let parallelism do the work.
Asynchronous Reset (When You Need It)
Sometimes you can't wait for a clock edge to assert reset - the chip is being powered down, the clock is gated, an external watchdog is yanking the line. In those cases:
always @(posedge clk or negedge reset_n) begin
if (~reset_n) q <= 0;
else q <= d;
end
The sensitivity list now has both a clock edge and a reset edge. The flip-flop responds immediately to either. reset_n is by convention active-low (asserted when low), which is why the test is ~reset_n.
Asynchronous reset has tradeoffs: harder to time-analyze, can cause metastability if not handled carefully on de-assertion, not portable across all FPGA architectures. Use synchronous reset by default, async only when the design requires it.
What Comes Next
You can now build any synchronous datapath. The next doc - Finite State Machines - puts a clocked register together with a case statement to produce the standard FSM idiom: the workhorse of every controller, protocol engine, and decision-making block in digital design.
Frequently Asked Questions
What is clocked logic in Verilog?
Logic whose updates are gated by a clock signal. The standard idiom is always @(posedge clk) target <= next_value; - on each rising edge of clk, target captures next_value. That single line describes a flip-flop in hardware. Stacking many of them with combinational logic between them builds counters, shift registers, pipelines - everything synchronous.
What is the difference between synchronous and asynchronous reset in Verilog?
Synchronous reset uses always @(posedge clk) if (reset) ... - the reset is sampled on a clock edge like any other input. Asynchronous reset uses always @(posedge clk or negedge reset_n) if (~reset_n) ... - the block triggers on either a clock edge or a reset assertion, so reset takes effect immediately. Synchronous is the default choice; asynchronous is used when reset has to be guaranteed to take effect even if the clock is dead.
How do you build a pipeline in Verilog?
Stack multiple stages of always @(posedge clk) stageN_reg <= stageN_combinational; - each stage's combinational logic feeds the next stage's register, and every register captures on the same clock edge. The result is a pipeline where new data enters each cycle and emerges N cycles later, with throughput of one result per clock.
What is a shift register in Verilog?
A chain of flip-flops where each one's output feeds the next one's input. Each clock edge shifts every bit one position. The canonical Verilog version uses non-blocking assignments: out <= {out[N-2:0], in}; - that one line creates an N-bit shift register that takes one bit per cycle from in.