The Multi-Way Branch
case is Verilog's flat dispatch construct. You give it an expression; it picks the matching branch:
case (expression)
pattern_1: statement_1;
pattern_2: statement_2;
pattern_3: begin
statement_3a;
statement_3b;
end
default: default_statement;
endcase
It's structurally similar to C's switch, but:
- There's no
break- each branch is implicitly terminated by the next one. - Patterns can be vectors, not just integers.
- The synthesizer turns the whole thing into a flat mux (or a one-hot decoder when the patterns make it possible).
A Worked Example: 4-to-1 Mux
The case body has four explicit patterns plus a default. The synthesizer sees a 2-bit input mapped to one of four values and emits a 4-to-1 multiplexer. Clean, flat, fast.
Why You Need default
For combinational case, omitting default is the same trap as if without else: any unmatched input value leaves out unassigned, and the synthesizer infers a latch.
For a 2-bit sel, the patterns above cover all four possible values - so in theory default is redundant. In practice:
- The synthesizer doesn't always prove that the cases are exhaustive.
- The selector might be
xorzin simulation, which doesn't match any explicit case. - Adding a new case later might leave the default behavior unspecified.
Always write default. For state machines and mux logic where you know the default is unreachable, assigning 'x:
default: out = 8'bx;
…tells the synthesizer "this is a don't-care, optimize freely" and surfaces a bright red x in simulation if the unreachable case does somehow get reached. That's the best of both worlds.
A State Machine in case
The classic use of case is the state-transition logic of a finite state machine:
The case (state) block is the state-transition logic. Each branch decides what the next state is and how long to stay in it. default is unreachable here (we cover RED/GREEN/YELLOW exhaustively in the 2-bit space), but it's there as a safety net - if state somehow becomes 2'd3, the FSM resets cleanly to RED instead of latching.
Finite State Machines goes deeper on this pattern.
Multiple Patterns Per Branch
You can list several patterns sharing a single statement, separated by commas:
case (opcode)
4'h0, 4'h1, 4'h2: result = a + b;
4'h3, 4'h4: result = a - b;
4'h8: result = a & b;
default: result = 8'd0;
endcase
That's two opcodes both meaning "subtract", three meaning "add". The synthesizer ORs the patterns together for the comparator.
casez and casex: Don't-Care Matching
Sometimes you want to match a pattern with some bits unspecified - "any opcode that starts with 010":
casez (opcode)
8'b010?_????: instruction = ALU_OP;
8'b110?_????: instruction = LOAD_OP;
8'b1110_????: instruction = JUMP_OP;
default: instruction = UNKNOWN;
endcasez
casez treats ? (and z) in the pattern as don't-cares. Each ? matches 0 or 1. Useful for decoding instruction formats where some bit positions are unused for certain opcode classes.
casex extends this to treat x as a don't-care too. casex is dangerous because uninitialized signals (which are x in simulation) match every case, producing surprising behavior. Most modern style guides recommend casez and forbid casex.
In SystemVerilog you also get case inside, which is the cleanest version of all - it accepts ranges and lists - but plain Verilog stops at casez.
case vs if/else if Chain
The two constructs can both express multi-way decisions, but they synthesize to different hardware:
caseis a flat dispatch. The synthesizer can produce a one-hot decoder, a balanced mux tree, or other flat structures. Constant time to evaluate.if/else ifis a priority chain. The synthesizer produces a cascade where each level adds delay. Logarithmically slower.
Functionally they overlap. Stylistically: use case whenever the conditions are about the value of a single expression. Use if/else if when there's a true priority or when conditions involve different signals.
// Better as case:
if (sel == 2'd0) out = a;
else if (sel == 2'd1) out = b;
else if (sel == 2'd2) out = c;
else out = d;
// Better as if/else if:
if (urgent_event) next_state = HANDLE_URGENT;
else if (timer_expired) next_state = TIMEOUT;
else if (data_ready) next_state = PROCESS;
else next_state = state;
The first three conditions are all "what is sel?" - a case reads more naturally and synthesizes flatter. The second three are independent events with an obvious priority - if/else if is the better fit.
What Comes Next
The last doc in this chapter - For Loops - covers Verilog's for and the surprising thing that happens when you use it in synthesizable code. Then we move into sequential logic and FSMs in earnest.
Frequently Asked Questions
What is the case statement in Verilog?
case (expr) ... endcase is Verilog's multi-way branch construct. It evaluates the expression once and dispatches to whichever branch matches. It's the idiomatic choice for state machines, opcode decoders, mux selectors, and anything else that picks among several mutually-exclusive options.
What is the difference between case, casex, and casez in Verilog?
case matches bit-exactly, including x and z values. casez treats z (and ?) in case items as don't-cares. casex treats both x and z as don't-cares. Don't-care matching is useful for opcode patterns where some bit positions are irrelevant, but casex is dangerous in simulation because uninitialized signals (x) can accidentally match every case.
Why do I need default in a Verilog case statement?
Without default, the synthesis tool sees the possibility that no case matched, decides the output signal has to keep its previous value, and infers an unwanted latch. The default branch handles every unmatched value - typically by setting the output to a safe value or by marking the case unreachable with an x assignment. Always include it.
When should I use case vs if-else in Verilog?
Use case when the conditions are mutually exclusive and dispatch on a single expression's value - state machines, opcode decoders, mux selectors. Use if/else when there's a true priority order or the conditions involve different signals. case synthesizes to flatter, faster hardware than a long else if chain.