digiwleeaLearn
Open the lab →

always @(posedge clk)

Describing logic that remembers

9 min read

A clocked always @(posedge clk) block in Verilog describes edge-triggered sequential logic, and assigning a reg with the nonblocking operator <= inside it captures a value on the rising clock edge, synthesising to a D flip-flop or register.

Build it in the lab →
A continuous assignment describes combinational logic: output follows input, no memory. But a computer must remember, and from the D flip-flop you know memory comes from capturing a value on the clock edge. Verilog describes that with an always block triggered on the clock edge. This is how you write anything sequential: registers, counters, the accumulator of your CPU. It is Verilog's answer to the VHDL process.

The always block and posedge

An always block (always @(...) begin ... end) is a chunk of behavior that re-runs whenever an event in its sensitivity list (the @(...) part) happens. The magic phrase for clocked storage is always @(posedge clk): posedge means the positive (rising) edge, the instant clk goes from 0 to 1, exactly the one moment a D flip-flop samples. Anything assigned inside is captured at that edge and held until the next one. This single pattern is the universal template for edge-triggered storage; synthesis turns it into real flip-flops.
module dff(
  input      clk,
  input      D,
  output reg Q
);
  always @(posedge clk) begin
    Q <= D;
  end
endmodule
A D flip-flop as a clocked always block. On each rising edge of clk, the output register Q captures D. This is the exact Verilog counterpart of the VHDL rising_edge process, and it is a touch simpler because Q can be an output reg directly.
Read the module as hardware. Q is declared output reg: a port that also holds state (a reg is a variable that keeps its value between updates, here the flip-flop's stored bit). The always block says: on every rising clock edge, load Q with whatever D is at that instant. Notice Verilog needs no separate internal signal, unlike VHDL where an out port could not be read back; a Verilog output reg can be both driven and remembered directly, so the D flip-flop is one block.

Nonblocking <= for flip-flops

Inside a clocked always block, assign registers with the nonblocking operator <=, not the blocking =. Nonblocking means: on the edge, every right-hand side is read first, then all the left-hand sides update together, exactly like real flip-flops all sampling their inputs on the same edge. That is what lets a chain of registers shift, or a counter read its own current value while computing the next. Use <= for every clocked register and the simulation matches the hardware.
The classic Verilog trap: using the blocking = instead of nonblocking <= in a clocked block. Blocking assignments take effect immediately and in order, like software, so in a shift register b = a; c = b; would copy a straight through to c in one edge instead of shifting one stage. It also causes simulation-versus-synthesis mismatches. The rule: **<= for sequential (clocked) logic, = for combinational always @(*)**. When in doubt in a posedge block, use <=.

Why there is no else

There is no else for the non-edge case. When clk is not rising, the always block simply does not fire, so Q keeps its old value, it remembers. A register that is not reassigned on an edge holds its previous value, and that held value is exactly what makes it storage. Testing a level instead (always @(clk) or a latch-style if (clk)) describes a transparent latch, not an edge-triggered flip-flop.

Latch or flip-flop: level versus edge

That same "no else means hold" idea builds a different part depending on what the block is sensitive to. Trigger on a level and you get a transparent D latch; trigger on an edge and you get a flip-flop. A level-sensitive always block (an enable in the sensitivity list, no posedge) is transparent: while the enable is 1, Q follows D continuously; the instant the enable drops to 0, Q freezes at its last value. An edge-triggered block (always @(posedge clk)) instead looks at D only at the rising instant. Level for a latch, edge for a flip-flop, from the same skeleton.
module dlatch(
  input      en,
  input      D,
  output reg Q
);
  always @(en, D) begin
    if (en)
      Q <= D;   // transparent while en is 1
    // no else: en = 0 leaves Q holding its last value
  end
endmodule
A transparent D latch. The sensitivity list @(en, D) has no posedge, so the block is level-sensitive (both en and D are listed so Q can track D while enabled). It is a storage element, so it takes the nonblocking <=, but unlike the flip-flop it responds to the level of en, not an edge: while en is 1, Q tracks D; when en is 0 the if is false and Q holds.
Read the two side by side. In the latch, while en is 1 any change on D flows straight through to Q (it is "transparent"), and only when en falls to 0 does Q lock its last value. In the flip-flop, Q ignores D at every instant except the rising edge, so between edges D can glitch freely and Q never notices (exactly the exercise below). The essential difference is what the block reacts to: a level (en) makes a transparent latch, an edge (posedge clk) makes a flip-flop.
The accidental latch: in a block you meant to be *combinational* (always @(*)), if any path leaves an output unassigned, synthesis must remember the old value to honor your code, so it quietly infers a latch, a real bug that brings glitches and timing surprises. The usual causes are an if with no else, or a case missing branches (or a default). For example always @(*) if (sel) y = a; never assigns y when sel is 0, so y latches. Fix it by giving every output a default at the top (y = 0; first, then the if) or by covering every branch (add the else, add the default). Rule: in a combinational always @(*), assign every output on every path.

A JK flip-flop with a case

A JK flip-flop is an edge-triggered part with two control inputs, J (set) and K (reset), that on each rising edge picks one of four behaviors from J and K: hold, reset, set, or toggle. It is still the always @(posedge clk) plus <= template, but instead of a plain load it chooses what to store. The standout mode is J=K=1, toggle: Q flips on every edge, which is exactly a counter bit (a T flip-flop).
JKModeQ next
00holdQ
01reset0
10set1
11toggle~Q
JK flip-flop characteristic table (evaluated on each rising clk edge). Q is the current stored bit and ~Q its complement. J sets, K resets, and J=K=1 toggles.
module jkff(
  input      clk,
  input      J,
  input      K,
  output reg Q
);
  always @(posedge clk) begin
    case ({J, K})
      2'b00: Q <= Q;      // hold
      2'b01: Q <= 1'b0;   // reset
      2'b10: Q <= 1'b1;   // set
      2'b11: Q <= ~Q;     // toggle
    endcase
  end
endmodule
A JK flip-flop. The two control bits are bundled with the concatenation {J, K} into a 2-bit selector, and a case picks the next value, all captured with <= on the rising edge. {J, K} puts J in the high bit, so 2'b01 means J=0, K=1 (reset).
Read it row by row: case ({J, K}) bundles the two controls into a 2-bit value and matches it. 2'b00 writes Q back to itself (hold), 2'b01 writes 1'b0 (reset), 2'b10 writes 1'b1 (set), and 2'b11 writes ~Q (toggle). Every clocked assignment uses <=, and all four patterns are listed, so the intent is explicit. Because this is a clocked block, an uncovered pattern would simply hold Q (harmless for a register, unlike the combinational accidental latch above); even so, a default: Q <= Q; is a tidy habit that documents "hold" outright.
Why this matters: always @(posedge clk) with <= is the single most-used pattern in real Verilog, because every register, counter, and state machine in a synchronous design is built on it. The register, the program counter (counter), and the instruction register of your CPU are all this template, widened to many bits. Master it and you can describe any sequential circuit you built by hand, in either HDL.
The flip-flop the always block describes. Open it in the lab and pulse the clock: Q captures D only on the rising edge, the hardware behind always @(posedge clk).
Try it
Inside always @(posedge clk) Q <= D;, suppose clk is currently high and steady (no new edge) while D flips from 0 to 1. Does Q change? Why?

Frequently asked

What is an always block in Verilog?

An always block, always @(...) begin ... end, is a chunk of behavior that re-runs whenever an event in its sensitivity list occurs. With @(posedge clk) it describes edge-triggered sequential logic; with @(*) it describes combinational logic. It is Verilog's counterpart to a VHDL process.

What does posedge mean in Verilog?

posedge is the positive (rising) edge of a signal, the instant it goes from 0 to 1. always @(posedge clk) runs its body only at that instant, capturing the assigned registers, which is exactly how a D flip-flop samples its input. There is also negedge for the falling edge.

What is the difference between blocking (=) and nonblocking (<=) assignment in Verilog?

Nonblocking <= reads all right-hand sides first, then updates all left-hand sides together, matching how real flip-flops sample on the same edge; use it for clocked (sequential) logic. Blocking = takes effect immediately and in order, like software; use it for combinational always @(*) blocks. Mixing them up causes shift registers to collapse and simulation-versus-synthesis mismatches.

How do you describe a D flip-flop in Verilog?

Declare the output as reg and write always @(posedge clk) Q <= D; inside the module. On each rising edge Q captures D and holds it until the next edge, with no else needed. That is the standard, synthesisable D flip-flop, the same circuit as the VHDL rising_edge process.

What is the difference between a latch and a flip-flop in Verilog?

A latch comes from a level-sensitive always block (no posedge): while its enable is high the output follows the input continuously, then freezes when the enable drops. A flip-flop comes from an edge-triggered always @(posedge clk) block: the output samples its input only at the rising clock edge. Level-sensitive infers a transparent D latch; edge-triggered infers a D flip-flop.

Why did my Verilog code infer an unwanted latch?

In a combinational always @(*) block, if any path leaves an output unassigned (an if with no else, or a case missing branches or a default), synthesis must remember the old value to match your code, so it silently infers a latch. Fix it by assigning every output a default value at the top of the block, or by covering every branch (add the else, add the default).

How do you code a JK flip-flop in Verilog?

Use an edge-triggered always @(posedge clk) block with a case on the two control bits: case ({J, K}) with 2'b00 hold (Q <= Q), 2'b01 reset (Q <= 1'b0), 2'b10 set (Q <= 1'b1), and 2'b11 toggle (Q <= ~Q). All four patterns are covered so no latch is inferred, and the toggle mode lets a JK flip-flop double as a counter bit.

You've got the theory. Now build it from scratch and watch it work.

Build it in the lab →
Builds towardTestbenches
Found this useful? Share itShare on X