Verilog · Chapter 14.5.3 · Behavioural Modeling
Multiway Advanced Techniques in Verilog — full_case, parallel_case & Priority vs Parallel
This lesson closes the branching section with the advanced patterns and the synthesis pragmas, along with the discipline of mostly avoiding them. The full-case pragma tells synthesis that a case statement covers every possible value, so it need not infer a latch for unlisted ones, and the parallel-case pragma tells it the branches are mutually exclusive, so it can build a parallel mux rather than a priority cascade. Both are dangerous, because they make promises to the synthesizer that the simulator does not honour, creating a mismatch when the promise is false and an unlisted value is actually hit or cases actually overlap. The modern discipline is to avoid the pragmas and instead write a real default and genuinely non-overlapping cases, so simulation and synthesis agree by construction. This page also covers the choice between priority and parallel structures and how to handle don't-care values.
Foundation13 min readVerilogfull_caseparallel_casePriorityParallelSynthesis Pragma
Chapter 14 · Section 14.5.3 · Behavioural Modeling
1. The Engineering Problem
Synthesis pragmas like full_case and parallel_case promise the synthesizer things about a case — but the simulator ignores them, so a false promise makes RTL simulation and hardware disagree:
full_case/parallel_casemake promises to synthesis that the simulator does not honour — if the promise is false, sim and synth diverge. The discipline is to avoid the pragmas and instead write a realdefaultand non-overlapping cases.
This page drills the pragmas, their dangers, the priority-vs-parallel choice, and the avoidance discipline.
2. Mental Model — Pragmas Promise Synthesis What the Simulator Ignores
3. The full_case Pragma
full_case tells synthesis all values are covered:
// RISKY — full_case promises completeness:
always @(*)
case (sel) // synopsys full_case
2'd0: y = a;
2'd1: y = b;
2'd2: y = c;
// 2'd3 NOT listed; full_case says "treat as don't-care"
endcase
// BETTER — a real default:
always @(*)
case (sel)
2'd0: y = a;
2'd1: y = b;
2'd2: y = c;
default: y = 8'h00; // explicit, sim and synth agree
endcaseWith full_case, synthesis treats 2'd3 as a don't-care (no latch), but simulation (which ignores the pragma) leaves y unassigned for 2'd3, holding the old value — a latch-like behaviour that differs from the synthesized hardware. A real default makes both agree.
4. The parallel_case Pragma
parallel_case tells synthesis cases are mutually exclusive:
// RISKY — parallel_case promises mutual exclusion:
casez (req) // synopsys parallel_case
4'b1???: grant = 3; // these patterns OVERLAP (1100 matches both)
4'b?1??: grant = 2;
endcaseIf the patterns actually overlap (e.g. 4'b1100 matches both), simulation uses priority (first match wins) while parallel_case makes synthesis build a parallel structure that may pick differently — a mismatch. If you want priority, write overlapping casez patterns without the pragma (simulation and synthesis both treat it as priority). If you want parallel, write genuinely non-overlapping cases. The pragma is unnecessary and dangerous either way.
5. Priority vs Parallel — The Real Choice
The deliberate structural choice, without pragmas:
- Priority (first match wins): use
if/else if/else, or acase/casezwith overlapping patterns. Synthesizes to a priority cascade. For prioritized decisions (interrupts, error handling). - Parallel (mutually exclusive): use a plain
casewith non-overlapping values. Synthesizes to a parallel mux/decoder. For value selection (opcodes, states).
// PARALLEL — non-overlapping case → parallel mux:
case (op) 2'd0: y=a; 2'd1: y=b; 2'd2: y=c; default: y=d; endcase
// PRIORITY — overlapping casez patterns → priority encoder:
casez (req)
4'b1???: g=3; 4'b01??: g=2; 4'b001?: g=1; default: g=0;
endcaseThe structure follows from how you write the cases — non-overlapping for parallel, overlapping (or if/else) for priority — so the code expresses the intent, and simulation and synthesis agree. No pragma needed.
Visual A — pragmas vs real code
Pragma promises vs honest code
data flow6. Common Mistakes
- Using
full_case/parallel_case— risk of sim/synth mismatch; use a realdefaultand non-overlapping cases (§2-§4, DebugLab 1). - Relying on a pragma instead of a
default— the simulator still infers latch-like behaviour (§3). parallel_caseon overlapping patterns — sim priority vs synth parallel disagree (§4).- Not choosing priority vs parallel deliberately — let the case structure express intent (§5).
7. Debugging Lab
One advanced-branching debug post-mortem
Pitfall — full_case hides a sim/synth mismatch
module sel (input [1:0] s, [7:0] a, b, c, output reg [7:0] y);
// full_case promises all values covered — but s=2'd3 is not listed.
always @(*)
case (s) // synopsys full_case
2'd0: y = a;
2'd1: y = b;
2'd2: y = c;
endcase
endmodule
// Synthesis treats s=2'd3 as a don't-care (no latch, optimized). Simulation
// IGNORES the pragma, so for s=2'd3 y is unassigned and holds its old value
// (latch-like). RTL sim and synthesized hardware behave differently for
// s=2'd3 — a hidden sim/synth mismatch.A design behaves correctly in synthesis but a gate-level / RTL comparison shows divergence for the unlisted select value (s=2'd3): RTL simulation holds a stale value while the synthesized logic produces an optimized (don't-care-based) result. The mismatch only appears for the uncovered input.
The full_case pragma tells SYNTHESIS that all case values are covered, so it treats the unlisted s=2'd3 as a don't-care and does not infer a latch. But the SIMULATOR ignores the pragma and follows standard semantics: for s=2'd3 no branch assigns y, so y holds its previous value (latch-like). The two disagree — a sim/synth mismatch caused by a pragma promise the simulator does not honour.
The fix is to remove the pragma and write a real default, which makes simulation and synthesis agree (both assign y for the uncovered value).
module sel (input [1:0] s, [7:0] a, b, c, output reg [7:0] y);
always @(*)
case (s)
2'd0: y = a;
2'd1: y = b;
2'd2: y = c;
default: y = 8'h00; // real default — sim and synth agree
endcase
endmodule
// A real default achieves completeness without a pragma, and there is no
// sim/synth mismatch. Avoid full_case/parallel_case.8. Interview Q&A
9. Exercises
Exercise 1 — Replace the pragma
Rewrite a case that uses // synopsys full_case to be complete without the pragma.
Exercise 2 — Priority or parallel?
For (a) a 4:1 mux on a 2-bit select and (b) a priority interrupt decoder, state whether you want a priority or parallel structure and how to write it without a pragma.
Exercise 3 — Spot the mismatch
Explain how // synopsys parallel_case on a casez with overlapping patterns causes a sim/synth mismatch.
10. Summary
Advanced branching is mostly about avoiding the synthesis pragmas:
full_case/parallel_casepromise completeness/mutual-exclusion to synthesis, but the simulator ignores them — a false promise causes a sim/synth mismatch.- The discipline — avoid the pragmas; write a real
default(completeness) and non-overlapping cases (parallelism), so sim and synth agree. - Priority vs parallel is a deliberate choice expressed by the code:
if/elseor overlappingcase/casezfor priority; non-overlappingcasefor parallel.
Multiway branching complete
This closes Chapter 14.5 Multiway Branching — if/else (priority, 14.5.1), case/casez/casex (parallel, 14.5.2), and the advanced pragmas and priority/parallel choice (14.5.3) — unified by the latch-avoidance discipline: assign every output on every path in combinational blocks.
The chapter now turns to iteration: Chapter 14.6 Loops drills for, while, repeat, and forever — the looping constructs of behavioural code.
Related Tutorials
- Case Statements — Chapter 14.5.2; the
casethese pragmas modify. - if/else Statements — Chapter 14.5.1; the priority structure.
- Multiway Branching — Chapter 14.5; the branching overview.
- Dataflow Advanced Techniques — Chapter 13.3; the synthesis-discipline mindset.
Standards & specifications
- Governing standard
- IEEE Std 1364 (Verilog)(opens IEEE in a new tab)
Defines the Verilog language and its simulation semantics, including the event scheduling model. Synthesis support is defined by tools, not by this standard.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the Verilog HDL curriculum.
