Module 5: Behavioral Verilog for Synthesis ยท 5.3 Conditional and Case Statements

full_case and parallel_case

Plain Verilog has no way to say “this case covers every value” or “these arms never overlap”. Synthesis vendors added comment pragmas to say it anyway, and you will meet them in existing code, so it is worth knowing what they promise and what happens when the promise is a lie.

The pragmas

(* full_case *)       // every value that can occur is listed; no default needed
(* parallel_case *)   // the arms are mutually exclusive; build a flat decode

Older code writes them as // synopsys full_case parallel_case after the case keyword. They are not part of the IEEE standard. Only the synthesiser reads them, and the simulator ignores them, which is the whole problem.

full_case

It says: the listed values are the only ones this expression ever takes, so treat everything else as don’t-care. When true, the tool drops the logic for the unlisted values and the result is smaller. When false, an unlisted value, or an x, arrives, the simulator does what the language says and shows an unassigned output, while the synthesised netlist, which threw that logic away, does something else. Both did what you told them; they were told different things.

The alternative is to write the default:

default: result = 'x;

which gives the tool the same freedom, in a form the simulator also sees.

parallel_case

It says: no two arms can match at once, so do not build a priority chain. When true, a flat decode. When false, because the items overlap in a way you did not notice, the simulator takes the first match as case semantics require, while the hardware built on the assumption of exclusivity merges the outputs of both matching arms into something neither intended.

The alternative is to make the arms exclusive in fact, distinct constants, and then no pragma is needed.

unique and priority

SystemVerilog replaced both with keywords that have defined meaning and that the simulator checks:

  • unique case: exactly one arm matches, and the simulator warns if that is violated;
  • priority case: the first match wins, and the simulator warns if no arm matches and there is no default.

They make the same promises as the pragmas, and they are checked in simulation, which closes the gap the pragmas opened. Module 9 covers them. Until then, write the default, keep the arms distinct, and when you find full_case parallel_case in old code, treat it as a note to go and check whether the claim is true.

The last article of this section puts priority and parallel decode side by side and asks how to choose between them for a given specification.

โ† casez, and Why Not casex Priority or Parallel โ†’