VLSIChaps Academy · Track 01

Always Blocks, Sequential Logic and the Clock

~12 min Hands-on lab 1 exercise Verilator
Page 10 of 50
01

Logic With Memory

The previous page built logic with no memory: outputs that recompute from inputs instantly, remembering nothing. Sequential logic is the other half of hardware, logic that holds state. A register keeps its value until told to change, and the thing that tells it to change is the clock. All the state in a chip, every counter, every pipeline stage, every stored byte, lives in sequential logic that updates in step with a clock.

02

The Clock Edge

Sequential logic does not react to every input wiggle the way combinational logic does. It updates at one precise moment: the clock edge, almost always the rising edge. Between edges, the register holds. At the edge, it samples its input and takes a new value. You express this with a clocked always block, written with the construct meant for it, always_ff, sensitive to the rising edge of the clock. Choose the wrong edge and every update in your design lands half a cycle away from where the rest of the world expects it.

03

Reset, the Known Starting Point

A register that has never been written holds an unknown, and unknowns poison everything they touch, as you saw on the data types page. Reset is how a design gets a known starting point: while reset is asserted, the register is forced to a defined value, typically zero, and real work begins only after reset releases. In this primer resets are synchronous, meaning reset takes effect at the clock edge like every other update, not the instant the reset wire moves. A register without a reset is a register whose first value is a guess.

04

Key Insight: the Nonblocking Rule

Inside a clocked block, assignments use the nonblocking form, <=, the operator that schedules the update rather than performing it immediately. The reason is how real registers behave: at a clock edge, every register in the design samples its input first, then all of them update together. Nonblocking assignment models exactly that. The blocking form, =, updates instantly, one statement at a time, which in designs with more than one register lets a value race through two stages in a single cycle, a bug that simulates differently from how silicon behaves.

In a block this small you could not tell the difference by watching values, which is precisely why the rule must be a habit, not a judgement call. The engine on this page enforces it: a blocking assignment inside your clocked block will be flagged, the same way a professional lint flow flags it on the job, echoing the discipline you saw with the accidental latch on Page 09.

Lab: Build a Counter That Starts Clean

Write the clocked block for a four bit counter. On the rising edge of the clock: if reset is high, the count becomes zero; otherwise the count increases by one. Use always_ff, use nonblocking assignment, and make reset synchronous. Run and submit. The engine simulates your counter cycle by cycle, and if an update lands on the wrong edge, the reset is ignored, or a blocking assignment sneaks in, it will name exactly what went wrong and when.

Three ingredients, in order. The block is sensitive to the rising edge of the clock only. Inside, reset is checked first and forces zero. Otherwise the count takes its old value plus one, written with the nonblocking operator, since in clocked logic you schedule the update rather than perform it on the spot.
Compiling, linting, and simulating...
Correct. Your counter starts clean, updates only on the rising edge, and every increment landed exactly one cycle after the last. You have now written both halves of hardware: logic that computes, from the last page, and logic that remembers, from this one. Everything you build from here is a combination of the two.
Not quite. Your block ran, but the cycle by cycle record diverged from the schedule. Either an update landed on the wrong edge, the reset was ignored or fired early, or a blocking assignment was flagged inside the clocked block. The engine output and the mentor below name the cycle and the cause.
Compile error.
Something went wrong reaching the engine. Try again in a moment.
AI Mentor
Thinking...
📲 Join 20K+ Engineers