Case-statement-problems
The official behavior of case, casez and casex is
problematic with respect to X and Z values.
Generally speaking, Verilog's behavioral modeling constructs are
rife with problems when it comes to the handling of unknown and high-impedence
values. Even the basic if statement treats X values as false, which is
deeply troubling—if we don't know what some value is, we certainly should
not simply assume it is false.
Verilog's case, casex, and casez statements have especially
bad behavior with regards to X and Z values.
For basic case statements, each match is compared against the test
expression using case-equality === instead of ordinary equality ==.
This allows you to match precisely against X and Z, which can easily lead to an
improper, non-conservative treatment of X.
The fancier casez and casex statements are especially badly
behaved. At first glance these statements seem pretty convenient. For
instance, in casez you are told that you can use Z or (equivalently)
? as a pattern-matching character. You might look at a code fragment like
this:
casez (inst)
5'b00001: out = a + b;
5'b0001?: out = a - b;
5'b001??: out = a & b;
5'b01???; out = a | b;
default: out = 16'hXXXX;
endcase
And think—wow, that looks nice. You might expect that the
second pattern here, 5'b0001?, will match:
And you're right. Unfortunately, what you probably did not expect, is that
this pattern will also match many other values, like:
And so on. This is because Z values are treated as wildcards not only in
your pattern, but also in the data itself, which is terrible and makes
no sense at all.
The casex statement is even worse. Here, any X or Z values in the data
will match anything you've written in your pattern. So, for instance,
casex (inst)
5'b00001: out = GOOD;
default: out = BAD;
endcase
Will, quite unexpectedly, produce GOOD for instructions such as XXXXX,
ZZZZZ, and so on.