The following example illustrates a long-standing Verilog "gotcha". The code is for a simple decoder that uses a "casex" statement with wildcard bits in order to simplify the lines of code required to decode all possible values of the 3-bit select input. With casex, any bits in the comparison that are either X, Z or ? will match all possible values for that bit (in Verilog literal numbers, a ? represents high-impedance, and is the same as Z).
module decoder (output reg [31:0] y,
input wire [31:0] a, b, c,
input wire [ 2:0] select
);
always @(select, a, b, c) begin
casex (select) // select is 3 bits wide
3'b1??: y = a; // matches if select is 3'b100, 3'b101, 3'b110, 3'b111
3'b00?: y = b; // matches if select is 3'b000, 3'b001
3'b01?: y = c; // matches if select is 3'b010, 3'b011
default: $display("ERROR: select had an unexpected value of %b", select);
endcase
end
endmodule
Note that all valid 2-state values of select are decoded, and therefore the default branch should never be executed. Should an invalid value of select occur, however, such as if select is X or Z, an error message is printed. At least that is the intent...
The gotcha occurs if there is a problem with the select input to the module, and some of the bits are either X or Z. For example, if the select input were inadvertently left unconnected, select would have the value of 3'bzzz. It seems obvious in the code that this value is not decoded by the casex statement, and therefore the default branch will be executed and an error message will be printed. Instead, however, y is assigned the value of the a input, and the invalid select value goes undetected.
Why?