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.
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.
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.
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.
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.
Weekly intelligence on VLSI, AI for EDA, and chip careers. 20,000+ engineers already inside.