Verilog twins: case, casez, casex. Which Should I Use?

The Verilog case statement is a convenient structure to code various logic like decoders, encoders, onehot state machines. Verilog defines three versions of the case statement: case, casez, casex. Not only is it easy to confuse them, but there are subtleties between them that can trip up even experienced coders. In this article I will highlight the identifying features of each of the twins, and discuss when each should be used.

Basic Verilog Case Statement

Let’s start by reviewing the basic case statement:

case (case_expression) // case statement header
  case_item_1 : begin
    case_statement_1a;
    case_statement_1b;
  end
  case_item_2 : case_statement_2;
  default     : case_statement_default;
endcase

A case statement has the following parts:

  • Case statement header—consists of the case, casez, or casex keyword followed by case expression
  • Case expression—the expression in parentheses immediately following the case keyword. Valid expressions include constants (e.g. 1’b1), an expression that evaluates to a constant, or a vector
  • Case item—the expression that is compared against the case expression. Note that C-style break is implied following each case item statement
  • Case item statement—one or more statements that is executed if the case item matches the current case expression. If more than one statement is required, they must be enclosed with begin…end
  • Case default—optional, but can include statements to be executed if none of the defined case items match the current case expression

Wildcard Case Statement: casez

The plain case statement is simple but rigid—everything must be explicitly coded. In some situations, you may want to specify a case item that can match multiple case expressions. This is where “wildcard” case expressions casez and casex come in. casez allows “Z” and “?” to be treated as don’t care values in either the case expression and/or the case item when doing case comparison. For example, a case item 2’b1? (or 2’b1Z) in a casez statement can match case expression of 2’b10, 2’b11, 2’b1X, 2’b1Z. It is generally recommended to use “?” characters instead of “Z” characters in the case item to indicate don’t care bits.

Verilog “wildcard” case statements can have overlapping case items. If more than one case item can match a case expression, the first matching case item has priority. Thus, priority logic can be inferred from a case statement. The following code snippet illustrates how casez can be used to code priority logic. It simulates and synthesizes correctly as a priority decoder.

always @(irq) begin
  {int2, int1, int0} = 3'b000;
  casez (irq)
    3'b1?? : int2 = 1'b1;
    3'b?1? : int1 = 1'b1;
    3'b??1 : int0 = 1'b1;
    default: {int2, int1, int0} = 3'b000;
  endcase
end
Verilog casez priority decoder

The logic will look something like this:

Even though this may seem an elegant way to code a priority decoder, the priority intention may only be apparent to the most experienced coders. Therefore, it is generally recommended to code priority logic using the more explicit if…else statement to clearly convey the intention.

While wildcard case comparison can be useful, it also has its dangers. Imagine a potentially dangerous casez statement where the case expression is a vector and one bit resolves to a “Z”, perhaps due to a mistakenly unconnected input. That expression will match a case item with any value for the “Z” bit! To put in more concrete terms, if the LSB of irq in the above code snippet is unconnected such that the case expression evaluates to 3’b00Z, the third case item will still match and int0 will be set to 1, potentially masking a bug!

Even wilder: casex

Now that we understand the usage and dangers of casez, it is straight-forward to extend the discussion to casex. casex allows “Z”, “?”, and “X” to be treated as don’t care values in either the case expression and/or the case item when doing case comparison. That means, everything we discussed for casez also applies for casex, plus “X” is now also a wildcard. In my previous article on Verilog X Optimism I discussed how X’s can propagate around a design and mask design issues. These propagated X’s can easily cause problems when combined with casex statements. To avoid these problems, the recommendation from RTL Coding Styles That Yield Simulation and Synthesis Mismatches is not to use casex at all for synthesizable code.

Verilog case, casez, casex each has its place and use cases. Understanding the differences between them is key to using them correctly and avoiding bugs. It may also help you in your next job interview 🙂

Have you come across any improper usage of these constructs? What are your recommendations for using them, especially casex? Leave a comment below!

SystemVerilog Unique Case

SystemVerilog adds a possible unique modifier to case statements. How does that change the behaviour? Head over to my post SystemVerilog Unique And Priority – How Do I Use Them?

References

  1. RTL Coding Styles That Yield Simulation and Synthesis Mismatches
  2. “full_case parallel_case”, the Evil Twins of Verilog Synthesis

Quiz and Sample Source Code

Now it’s time for a quiz! How will each of the following variations of case statement behave when the case expression

  1. matches one of the non-default case items
  2. does not match any non-default case item
  3. contains all X’s (e.g. if the signal comes from an uninitialized memory)
  4. contains all Z’s (e.g. if the signal is unconnected)
  5. contains a single bit X
  6. contains a single bit Z

Case statement variations:

  1. Plain case statement
  2. Plain case with default case
  3. Casez
  4. Casez with default case
  5. Casex
  6. Casex with default case
  7. Unique case
  8. Unique case with default case
  9. Unique casez
  10. Unique casex

Stumped? Download the executable source code to find out the answer!

[lab_subscriber_download_form download_id=7]

18 thoughts on “Verilog twins: case, casez, casex. Which Should I Use?”

  1. I think you should also mention to avoid the dangers of casez and casex while still getting wildcard matching, it is best to use the “inside” keyword. I think this is the best practice when ‘z’ and ‘x’ values are never expected/allowed and should be considered errors.
    case (irq) inside
    3’b1?? : int2 = 1’b1;
    3’b?1? : int1 = 1’b1;
    3’b??1 : int0 = 1’b1;
    3’b000: {int2,int1,int0} = ‘0;
    default: {int2, int1, int0} = ‘x; // bad, propogate-an-X
    endcase

    Reply
    • Hi Vlad. Thanks for your comment. That’s very interesting! I have never seen that style of coding. Reading the SystemVerilog LRM, I see…

      “The inside operator uses the equality ( == ) operator on nonintegral expressions to perform the comparison. If no match is found, the inside operator returns 1’b0. Integral expressions use the wildcard equality (==?) operator so that an x or z bit in a value in the set is treated as a do-not-care in that bit position (see 11.4.6). As with wildcard equality, an x or z in the expression on the left-hand side of the inside
      operator is not treated as a do-not-care”

      So I think you’re right! Your example code should handle wildcards in the case items only, but not in the case expression. That’s a slight difference from the behaviour of casez and casex, but I think that’s generally what we want. Thanks for the tip, I’ll have to give that a try! Do you know how well various tools handle your code?

      Reply
  2. Hi Jason,

    As per your comment “For example, a case item 2’b1? (or 2’b1Z) in a casez statement can match case expression of 2’b10, 2’b11, 2’b1X, 2’b1Z. ”

    For casez statements 2’b1X should not match. It would match if it would have been a casex statement. Let me know if I am wrong here.

    Nitin

    Reply
    • Hi Nitin, consider the following code.

      reg [1:0] case_exp;
      initial begin
      case_exp = 2'b1x;
      casez (case_exp)
      2'b1?: $display("matched");
      endcase
      end

      This will match, because the case item 2’b1? is equivalent to 2’b1z, which in a casez statement will match a LSB of any value in the case expression, even if it is X.

      Reply
      • Hi Jason,

        How it is then different with casex?

        casez : Matches 1, 0, Z, X
        casex: Matches 1, 0, Z, X again…

        “X” seems to be a wildcard in both casez and casex. How they differ?

        Reply
        • Hi Nick. Think of it this way. Casez allows one to mark certain bits (using Z or ?) in both the case item and case expression as wildcard in the comparison. If a bit is marked as a wildcard, then it becomes a don’t care and will match any value (0, 1, Z, X). Casex allows one to mark wildcard bits using Z or ?, and additionally X.

          However, it gets a bit more complicated because as a person coding the RTL, you can “mark” the bits in the case item in your code, but you cannot manually “mark” the bits in the case expression because it comes from whatever signal is passed into the case expression dynamically. That’s where you have to be careful whether the dynamic signal contains any Z or X that can cause it to match a case item that you didn’t expect. That’s also the reason that casez is generally considered safer than casex for coding because it’s relatively easy to have a dynamic signal unintentionally resolve to X in simulation, and cause the code to select a different case item than you expected.

          Reply
    • Hi Hetal. Like described in the article, you must be very careful when using casex because X’s that you may not expect or know about, from a signal in the case item or case statement, can potentially cause an unwanted case code path to be executed and the logic to not behave as expected. X’s are relatively common in simulations—flip flops without reset, SRAMs that have not been written to, selecting an invalid index of a vector—can all cause X’s to appear on a signal. When these signals go into a casex statement, the casex may select a code path that you did not expect (unless you really know what you’re doing). So it’s safer to avoid the potential problem in the first place.

      Reply
  3. Hi Jason,

    Enjoyed reading your post.

    I have an quick question on how case, casex and casez will be inferred in terms of gates? Will be the synthesized logic look same in all three flavors?

    Can H/W detect if the signal is “X” or “Z” ?

    Thanks

    Reply
    • Hi Yogesh. What casex and casez synthesizes to depends on whether any of the signals in the case expression or case items are x or z (or case item has a wildcard ?). If none of the signals behave that way, then casex and casez behave and synthesize exactly like case. But if a signal does have the value of x or z (or case item has a wildcard ?), then casex and casez will behave and synthesize differently.

      To your question of whether HW can detect X or Z. Keep in mind X is not a real value that exists in synthesized HW. X is a simulation only concept, to mean contention or uninitialized signal in simulation. The danger with using casex is a signal with X will take one deterministic code path in simulation, but in synthesized HW it is going to be unpredictably 1 or 0, and will cause HW to potentially execute a different code path than in simulation, perhaps resulting in unexpected behaviour. Similar idea applies to Z, which means unconnected signal in simulation. But a synthesis tool may tie an unconnected signal to an actual value during synthesis, causing potentially another difference in behaviour between simulation and actual HW.

      Personally I avoid casex, and I only use casez if I specifically need to use the wildcard ? in a case item or case expression to simplify coding. If I don’t need any wildcard behaviour I stick with plain case.

      Reply
  4. If casez and casex use === for comparing case expressions and case items, how are they synthesizable (since === to compare X or Z isn’t synthesizable)?

    Reply
    • Hi Arushi. I’m not sure I wrote exactly that casez and casex use === for comparing. What I meant was casez and casex will both do 4-state matching in simulation (similar to behaviour of ===), as opposed to 2-state matching (similar to behaviour of ==). casez and casex are synthesizable, with the caveats mentioned in this article.

      Reply
  5. Hello
    In VHDL there is an case option as the following:

    signal counter : integer
    case counter
    when 1 to 10 => data_s

    Reply
  6. You are not posting anymore at the moment?

    It helped me a lot with my understanding in Verilog and my projects.

    Thank you I appreciate.

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.