ANALYSIS OF CASE STATEMENTS
The common practice is to use casez statement in RTL coding. Use of casex is strongly
discouraged. Now we will discuss whether casex is such a bad construct. Before we start
let me say, all case statements are synthesizable.
If someone is required to tell the differences between case, casez, casex constructs in
verilog, the answer will be the pretty familiar one:
casez treats 'z' as dont care.
casex treats 'z' & 'x' as dont care.
case treats 'z' & 'x' as it is.
Now lets go further and unearth the differences between them.
A common misconception is '?' does mean a don’t care, but it does not. It is just an
another representation of high impedence 'z'.
Ex:
case (sel)
00: mux_out = mux_in[0];
01: mux_out = mux_in[1];
1?: mux_out = mux_in[2];
default: mux_out = mux_in[3];
endcase
In the above case statement if the intention is to match case item 3 to either 10 or 11 then
the code is absolutely wrong, because '?' doesnot mean a dont care. The actual case item
written is 1z.
Case statement:
Case statement treats x & z as it is. So a case expression containing x or z will only match
a case item containing x or z at the corresponding bit positions. If no case item matches
then default item is executed. Its more like pattern matching. Any pattern formed from
the symbol set {0,1,x,z} will match its clone only.
Ex:
case (sel)
00: y = a;
01: y = b;
x0: y = c;
1x: y = d;
z0: y = e;
1?: y = f;
default: y = g;
endcase
sel
00
11
xx
x0
1z
z1
y
a
f
g
c
b
sel
00
11
xx
x0
z1
Result:
y
a
g
g
c
f
g
case item
00
default
default
x0
1?
default
Note that when sel is 11, y is not assigned f, but is assigned the default value g.
Casez statement:
Casez statement treats z as dont care. It mean what it sounds, 'don’t care' (dont care
whether the bit is 0,1 or even x i.e, match z(?) to 0 or 1 or x or z).
Ex:
casez (sel)
00: y = a;
01: y = b;
x0: y = c;
1x: y = d;
z0: y = e;
1?: y = f;
default: y = g;
endcase
Result:
case item
00
1?
default
1z
d
x0 (would have matched with z0(item 5) if item 3
is not present.)
1x (would have matched with z0(item 5) &
1?(item 6) also.)
01 (would have matched with 1?(item 6) also.)
The fact that x matches with z in casez gives the illusion 'x is being treated as a dont care
in casez'. What is exactly happening is z, the dont care, is being matched to x. This will
be more clear if you admire the fact 'x will not be matched to 1 or 0 in casez'(but will
match z).
The point we dicussed at the beginning that ? is not dont care is worth an explanation
here. ? is dont care only when used in casez, elsewhere it is nothing but z.
sel
00
11
xx
x0
1z
z1
y
a
d
a
a
c
b
case item
00
1x (would have matched with 1? also)
00 (would have matched with 1? also)
00 (would have matched with all items except 01)
x0 (would have matched with all items except
00,01)
01 (would have matched with 1x, 1? also)
Casex statement:
Casex statement treats x and z as dont cares. x will be matched to 0 or 1 or z or x and z
will be matched to 0 or 1 or x or z.
Ex:
casex (sel)
00: y = a;
01: y = b;
x0: y = c;
1x: y = d;
z0: y = e;
1?: y = f;
default: y = g;
endcase
Result:
The summary of the discussion so far can be put up as follows:
Statement
Case
Casez
Expression contains
Binary
Binary
Binary
x
x
x
z (?)
z (?)
z (?)
Binary
Binary
Binary
x
x
Item contains
Binary
x
? (z)
Binary
x
? (z)
Binary
x
? (z)
Binary
x
? (z)
Binary
x
Result
Match
Don’t match
Don’t match
Don’t match
Match
Don’t match
Don’t match
Don’t match
Match
Match
Don’t match
Match
Don’t match
Match
Match
Match
Match
Match
Match
Match
Match
Match
Match
Match
Match
Match
Match
? (z)
Binary
x
? (z)
Binary
x
? (z)
Binary
x
? (z)
Binary
x
? (z)
x
z (?)
z (?)
z (?)
Binary
Binary
Binary
x
x
x
z (?)
z (?)
z (?)
Casex
We have been discussing the simulations aspects, now we will discuss synthesis aspects
of these statements.
Ex: case (sel)
00: mux_out = mux_in[0];
01: mux_out = mux_in[1];
1?: mux_out = mux_in[2];
default: mux_out = mux_in[3];
endcase
The outputs after synthesis for different case statements of the same code is shown
below:
mux_in[0]
mux_in[1]
0
1
sel[0]
0
1
mux_in[3]
mux_out
sel[1]
case
mux_in[0]
mux_in[1]
0
1
0
1
mux_in[2]
mux_out
sel[0]
sel[1]
casez
mux_in[0]
mux_in[1]
0
1
0
1
mux_in[2]
mux_out
sel[0]
casex
sel[1]
Now let the case item 3 be changed to 1x.
Ex: case (sel)
00: mux_out = mux_in[0];
01: mux_out = mux_in[1];
1x: mux_out = mux_in[2];
default: mux_out = mux_in[3];
endcase
The outputs of synthesis will look like:
mux_in[0]
mux_in[1]
0
1
sel[0]
mux_in[3]
case
mux_out
0
1
sel[1]
mux_in[0]
mux_in[1]
0
1
sel[0]
mux_in[0]
mux_in[1]
0
1
0
1
mux_in[2]
mux_out
sel[1]
casez
0
1
mux_in[2]
mux_out
sel[0]
casex
sel[1]
We can have the following deductions by comparing the two sets of outputs.
1. Case statement will not consider for synthesis, the items containing x or z.
2. Casez and Casex will give the same output after synthesis, treating both x, z in
case items as dont cares.(seems against the nature of casez ?)
If both casez and casex give the same netlist, then why was I adviced to use casez only in
RTL design? The immediate answer would be because of synthesis-simulation mismatch.
If I use casez then, will there be no mismatches? The painful fact is that there will be
mismatches.
Normally in any RTL designed to be synthesized, no case item will be expected, rather
desired to be x (as no such unknown state will be present on the chip). So we wont have
any case item carrying x (as shown in the below example where only 0,1,?(z) is used).
Ex: casez (sel)
00: mux_out = mux_in[0];
01: mux_out = mux_in[1];
1?: mux_out = mux_in[2];
default: mux_out = mux_in[3];
endcase
Result:
sel
xx
1x
0x
zz
1z
0z
Pre-synthesis
mux_in[3]
mux_in[2]
mux_in[3]
mux_in[0]
mux_in[2]
mux_in[0]
mux_in[2]
mux_in[2]
x
x
x
x
mux_in[0]
mux_in[2]
mux_in[0]
mux_in[0]
mux_in[2]
mux_in[0]
mux_in[2]
mux_in[2]
x
x
x
x
casez
casex
Post-synthesis Pre-synthesis
Post-synthesis
Note: 1.Binary combinations of sel signal are not considered as its obvious that no
mismatch can occur for them.
2.Post-synthesis results of casez and casex match because both have the same
netlist.
If we observe the pre and post synthesis results for casez, certainly there are some
mismatches. For casex also there are some mismatches. In some mismatches(when sel is
xx,0x), the pre-synthesis result of casez is different from pre-synthesis result of casex, but
during the match conditions(when sel is 1x,1z) both casez and casex have the same
pre-synthesis results.
Another interesting, very important observation is that when ever there is a
mismatch, post-synthesis result will become x. This is such a crucial observation that it
will make us reach the conclusion that we can use either casez or casex, which ever we
wish as opposed to the common myth to use casez only. This is explained below in a
detailed manner.
During RTL simulation if sel becomes xx, casez executes default statement(which is the
intended behaviour) but casex executes case item1(which is not the intended behaviour),
clearly a mismatch. In netlist simulation both casez and casex results will become x,
making the RTL simulation mismatch between casez and casex trivial.
In all the cases where the netlist simulation result is not x, the RTL simulation results of
casez and casex will match.From this behaviour we can conclude that casex can be used
as freely as casez is being used in designs.
The reason why we prefer casez(casex) to case stament is that casez(casex) has the ability
to represent dont cares.
Ex: casez (sel)
000: y = a;
001: y = b;
01?: y = c;
1??: y = d;
endcase