Control Statements

If-else, case, casez, casex statements.

Mohith N
Updated: 19 March 2026
4 min read

Control statements in Verilog allow a designer to conditionally select which hardware behavior to activate based on signal values. They are used extensively in behavioral modeling for multiplexers, decoders, FSM next-state logic, and arithmetic blocks. Mastery of control statements is essential for translating a logic specification into synthesizable RTL code.

Verilog Control Statement Typesif-elsePriority-encodedif (cond1) ...else if (cond2) ...else ...Top condition checked firstInfers priority encoderMissing else mayinfer latchcaseParallel, equal prioritycase (expr)2'b00: ...2'b01: ...default: ...All cases same prioritydefault avoids latchcasez / casexWildcard matchingcasez: ? matches Z or Xcasex: ? matches Z, X, 0, 1casez(sel)4'b1???: high bit setUsed for priority encodersand don't care patterns
Figure 1: Overview of Verilog control statement types and their hardware synthesis implications

Core Concept: Conditional Execution in Hardware

Control statements in Verilog describe how a circuit selects among multiple outputs or behaviors depending on input values. When synthesized, these statements translate to actual hardware: multiplexers, priority encoders, or lookup tables. The choice of which control statement to use has a direct impact on what hardware gets generated and how efficient it is.

The if-else statement evaluates conditions from top to bottom. The first condition that evaluates true causes its associated statements to execute, and no further conditions are checked. This priority ordering means that synthesis tools infer a priority encoder structure, where the first input has the highest priority. This can consume more logic area than an equivalent case statement when many conditions are involved.

The case statement evaluates all branches in parallel. Each branch specifies an exact value that the case expression must match. Since no ordering priority exists among branches, synthesis tools often implement this as a more area-efficient parallel multiplexer. The default branch handles any unspecified case values and is critical for avoiding unintended latch inference.

casez and casex: Wildcard Matching

The casez statement is a variant of case that treats the high-impedance value Z and the don't-care symbol ? as wildcards during comparison. This means a case item such as 4'b1??? will match any 4-bit value whose most significant bit is 1, regardless of the remaining three bits. This is useful for implementing priority encoders where only partial bit patterns need to be checked.

The casex statement is even more permissive. It treats X (unknown), Z, and ? all as wildcards. While casex appears useful, it is generally avoided in synthesizable RTL because treating X as don't-care can mask simulation errors. Real hardware does not produce X values, but a simulation using casex may incorrectly match a case branch when the signal is actually unknown. casez is the safer choice when wildcards are needed.

Latch Inference: The Critical Synthesis Trap

In combinational always blocks, if a control statement does not assign a value to an output variable in every possible input combination, the synthesis tool infers a latch to hold the previous value when no branch is taken. Latches are generally undesirable in synchronous digital design because they introduce level-sensitive storage that is difficult to time-analyze.

For if-else, including a final else branch that assigns a default value prevents latch inference. For case statements, including a default branch achieves the same effect. A common practice is to assign all outputs to their default values at the top of the always block before the case or if-else structure. This guarantees complete coverage and eliminates any risk of latches.

Example
Given:
3-to-8 decoder using case statement. Input: sel[2:0], Output: out[7:0]
For each value of sel, exactly one bit of out is high.

Why this formula applies:
All 8 input combinations covered including default => no latch inferred.

Formula:
always @(*) begin
  case (sel)
    3'b000: out = 8'b0000_0001;
    3'b001: out = 8'b0000_0010;
    3'b010: out = 8'b0000_0100;
    3'b011: out = 8'b0000_1000;
    3'b100: out = 8'b0001_0000;
    3'b101: out = 8'b0010_0000;
    3'b110: out = 8'b0100_0000;
    3'b111: out = 8'b1000_0000;
    default: out = 8'b0000_0000;
  endcase
end

Substitution:
For sel = 3'b010:
  Matches third branch
  out = 8'b0000_0100 (bit 2 is high)

Calculation:
All 8 combinations covered. default handles any unknown simulation state.
No signal is ever unassigned. No latch inferred.

Final Answer with units:
out[2] = 1, all other bits = 0 when sel = 3'b010. Correct decoder behavior.
Exam Tip: In GATE, if-else infers priority encoder hardware; case infers parallel mux. A case without default in a combinational block infers a latch for any unspecified input. Always add default in case and else in if-else for latch-free combinational logic.

Mechanism: Hardware Generated by Each Statement

Hardware Inferred by Control Statementsif-else chaincond1 (highest priority)cond2else (lowest priority)Cascaded MUX chainPriority encoder structureMore area for many conditionscase statementbranch 0branch 1branch 2branch 3defaultParallel MUX structureAll branches equal priorityArea-efficient for wide decodeMissing else/defaultcovered casesuncovered case=> holds old valueLatch inferredLevel-sensitive storageTiming analysis difficultAvoid in synchronous design
Figure 2: Hardware structures inferred by if-else, case, and incomplete case without default
  • if-else checks conditions top-down in priority order, synthesizing to a cascaded MUX or priority encoder.
  • case matches all branches in parallel, synthesizing to a more compact MUX structure.
  • casez uses ? or Z as wildcard, useful for partial bit-pattern matching in priority encoders.
  • casex additionally treats X as wildcard; generally avoided in RTL due to simulation masking issues.
  • A combinational always block with incomplete coverage infers latches, which are undesirable in synchronous design.
  • Always include default in case and a final else in if-else when modeling combinational logic.

Quick Revision

  • if-else: priority-encoded, first true branch executes, infers priority encoder in synthesis.
  • case: parallel matching, all branches equal priority, infers MUX, needs default to avoid latch.
  • casez: ? and Z are wildcards; use for partial bit-pattern matching; safer than casex in RTL.
  • casex: treats X, Z, ? as wildcards; avoid in synthesizable RTL; masks simulation unknowns.
  • Missing else or default in combinational block: latch inferred for unassigned signal.
  • Prevention: assign all outputs a default value at the top of always block before any if/case.
  • Exam trap: if-else with 4 conditions synthesizes heavier priority logic than case with 4 branches.

Verilog Control Statements

Test your knowledge on this topic.

Question 1 of 3

Q1.Which hardware structure is inferred by a fully specified case statement without overlaps?