Skip to main content

SystemVerilog Conditional Statements – if-else, case, unique, and priority

· loading · loading · ·
Hardware Design Verification SystemVerilog Conditional Logic If-Else Case Unique Priority
Hardware Design Verification
Axolot Logic
Author
Axolot Logic
Digital Design Engineer
Table of Contents
SystemVerilog Design Series - This article is part of a series.
Part 12: This Article

🧠 SystemVerilog Conditional Statements
#

Conditional constructs are essential in hardware and behavioral modeling. SystemVerilog provides powerful decision-making structures with enhanced features beyond traditional Verilog:

  • if-else for general condition checking
  • case, casex, and casez for multi-way selection
  • unique and priority modifiers to guide synthesis and detect errors
  • ternary operator for concise conditional assignments

🔹 if / else Statement
#

The fundamental conditional construct that selects between execution paths.

if (enable) begin
  data_out = data_in;
  valid = 1'b1;
end
else begin
  data_out = 0;
  valid = 1'b0;
end

✅ Good For:
#

  • Simple 2-way or multi-level conditionals
  • Clear, readable combinational logic
  • Sequential logic in always_ff blocks

⚠️ Watch Out:
#

  • Incomplete if-else in combinational logic infers latches
  • Nested if-else can create priority routing in synthesis

🔹 case Statement
#

A powerful multi-branch conditional structure with several variants:

1. Standard case
#

case (opcode)
  4'b0000: result = a + b;
  4'b0001: result = a - b;
  4'b0010: result = a << 1;
  default: result = 0;
endcase

2. casez (treats ‘z’ as don’t-care)
#

casez (instruction)
  8'b1??????? : process_immediate();
  8'b01?????? : process_register();
  default     : illegal_opcode();
endcase

3. casex (treats ‘x’ and ‘z’ as don’t-care)
#

casex (ctrl_bits)
  4'b1xxx : high_priority();
  4'b01xx : medium_priority();
  default : low_priority();
endcase

🛠️ Pro Tips:
#

  • Always include a default branch in combinational logic
  • casez is safer than casex for synthesis
  • Use bit masks instead of ? for better readability

🔹 Ternary Conditional Operator
#

Compact conditional assignment:

assign out = (sel) ? in1 : in0;

Best for:
#

  • Simple mux implementations
  • Parameter assignments
  • Constant expressions

🔹 unique / priority Modifiers
#

SystemVerilog introduces powerful qualifiers to clarify design intent:

🔸 unique case / if
#

Guarantees that only one condition will match. Generates errors if:

  • No branches match (runtime warning)
  • Multiple branches match (runtime error)
unique case (state)
  IDLE  : next_state = READ;
  READ  : next_state = PROCESS;
  WRITE : next_state = IDLE;
endcase

🔸 priority case / if
#

Ensures at least one branch will execute, evaluating in order:

priority if (irq[3]) handle_irq3();
else if (irq[2]) handle_irq2();
else if (irq[1]) handle_irq1();

🚀 Advanced Usage:
#

unique if (mode inside {SINGLE, BURST}) begin
  // Only one mode can be active
end

🧪 Simulation and Synthesis Behavior
#

ModifierSimulation ChecksTypical Synthesis Result
uniqueExactly one match requiredOptimized parallel mux
priorityAt least one match requiredPriority-encoded structure
(none)No checksMay infer latches if incomplete

⚠️ Modern tools use these hints for optimization and safety checking


⚙️ Synthesis Considerations
#

  • Regular if may create priority routing if deeply nested
  • case typically generates balanced multiplexers
  • unique case enables one-hot optimization
  • priority if creates cascading logic (like if-else chains)
  • Ternary operators often synthesize to compact muxes

🔍 Key Insight:
#

// These may synthesize differently:
if (sel) out = a; else out = b;  // Potential priority routing
assign out = sel ? a : b;        // Usually cleaner mux

📌 Comprehensive Comparison Table
#

ConstructBest Use CaseLatch RiskSynthesis ResultVerification Safety
if-elseSimple conditionsHighPriority routingLow
caseMulti-way decisionsMediumBalanced muxMedium
unique caseMutually exclusive optionsNoneParallel muxHigh
priority ifOrdered conditionsNoneCascading logicMedium
ternarySimple muxesNoneCompact muxLow

✅ Professional Best Practices
#

  1. For FSMs: Always use unique case for state decoding
  2. For interrupt handling: Use priority if for clear precedence
  3. For combinational logic:
    • Either cover all cases explicitly
    • Or use default assignments at the top
  4. For readability:
    • Keep conditions simple
    • Use parentheses for complex expressions
    • Add comments for non-obvious conditions

🏆 Pro Tip:
#

// Good practice - defensive coding
always_comb begin
  // Default assignment
  result = 0;
  
  // Override in specific cases
  unique case (op)
    ADD: result = a + b;
    SUB: result = a - b;
  endcase
end

🚀 Performance Considerations
#

  1. Critical Paths:

    • priority if creates longer paths
    • unique case generally has balanced timing
  2. Area Optimization:

    • Ternary operators often yield smallest muxes
    • case statements are typically well-optimized
  3. Power Implications:

    • unique constructs enable clock gating opportunities
    • Nested if may prevent power optimization

🔖 Key Insight
#

Remember: Conditional statements in RTL don’t execute sequentially like in software. All branches are evaluated concurrently in hardware, and the modifiers (unique/priority) help clarify your design intent to both tools and other engineers.

Advanced Technique: Combine unique with inside operator for super-clean conditionals:

unique if (mode inside {IDLE, RUN, WAIT}) 
  // Only one mode can be active
SystemVerilog Design Series - This article is part of a series.
Part 12: This Article

Related

SystemVerilog Arrays
· loading · loading
Hardware Design Verification SystemVerilog Arrays Packed Dynamic Arrays Queues Testbench
Hardware Design Verification
SystemVerilog Clocking Block – Timing Control for Testbenches
· loading · loading
Verification Hardware Design SystemVerilog Clocking Block RTL Design Testbench UVM Timing
Verification Hardware Design
SystemVerilog Data Types
· loading · loading
Hardware Design Verification SystemVerilog Verilog RTL Design Data Types Synthesis Simulation
Hardware Design Verification
SystemVerilog Enum Data Type
· loading · loading
Hardware Design Verification SystemVerilog Enum FSM RTL Design Testbench Debugging
Hardware Design Verification
SystemVerilog Interface – Modular Signal Grouping with modport and Clocking Blocks
· loading · loading
Hardware Design Verification SystemVerilog Interface Modport Testbench RTL Design Connectivity
Hardware Design Verification
SystemVerilog Intoduction
· loading · loading
Hardware Design Verification SystemVerilog Verilog RTL Design UVM Hardware Verification IEEE 1800
Hardware Design Verification