Sutherland Logo Graphic Motto Graphic
Home Workshop Descriptions eTutored™ Online Schedule Register for a Workshop Request Private Training Workshop Pricing & Terms Books by Stuart Sutherland Papers by Stuart Sutherland Online Reference Guides

"Mr. Sutherland's expert knowledge of SystemVerilog provides insight not possible from other courses."

Verilog and SystemVerilog Quiz and Tips

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?

Answer

The reason an invalid select value of 3'bzzz goes undetected is because the "wildcard" bits for casex (and casez) apply to both sides of comparison.  When all bits of select are X or Z, it is the same as saying every possible value of select is a match.  Therefore the 4 possible values of the first branch will all match, and the first branch will be executed.

The intent of the code is for problems with select values to fall into the default branch, but it is how the code works. THIS IS A GOTCHA!

SystemVerilog has a construct that fixes the subtle GOTCHA, a "case...inside" statement. 

case (select) inside   // select is 3 bits wide
  3'b1??: y = a;       // matches 3'b100, 3'b101, 3'b110, 3'b111
  3'b00?: y = b;       // matches 3'b000, 3'b001
  3'b01?: y = c;       // matches 3'b010, 3'b011
  default: $display("ERROR: select had an unexpected value of %b", select);
endcase

The case...inside construct allows the use of wildcard bits in the values listed within the case statement, but unlike casex and casez, the wildcards do NOT apply to the expression being evaluated (select, in this example).  Using case...inside, a select value of X or Z would not match any of the decoded values, and an error message would be displayed, as intended.

A good coding practise to follow is to never use casex or casez.  Instead, only use case...inside when wildcard bits are required in a case statement.  Stuart Sutherland and Don Mills presented a paper at the 2013 Synopsys Users Group conference on Synthesizable SystemVerilog.  The paper discusses the advantages of case...inside and many other SystemVerilog constructs thate are useful for modeling hardware logic that simulates and synthesizes accurately and efficiently.  The paper received the "Best Presentation" award at the conference, and can be downloaded here.

Coding Tips Sign-Up