verilogpriority-queue

localparam for case values with don't cares. Is 1'b? legal?


Can you replicate, concatenate a '?' literal somehow? It seems my tools accept it.

Most direct answer: Section 3.5 Numbers of 1364-2005 has a stanza for 'z_digits'. z_digit ::= z | Z | ?, so it is fine to use either '?' or 'z' as they are equivalent.


I have a list of bits. The text 'EV#' is some appropriately named event. Like ON_HOOK, OFF_HOOK or whatever. Several events are arriving and the intent is to prioritize the translation and insertion to a fifo. My initial coding transposition to stackoverflow has some errors which have been corrected. The code here is intended to be minimal example. Apologies for any confusing in the editing/transposition here.


localparam BIT_EV0 = 0;
localparam BIT_EV1 = 1;
localparam BIT_EV2 = 2;
localparam BIT_EV3 = 3;
localparam BIT_MAX = 4; // Register size.

reg [BIT_MAX-1:0] event_queue;

I would like to define a case constants such as,

`define CASE_VALUE(bit) {{BIT_MAX-bit-1{1'b0}}, 1'b1, {bit{1'b?}}}
localparam [BIT_MAX-1:0] PRI_EV0 = `CASE_VALUE(BIT_EV0);
localparam [BIT_MAX-1:0] PRI_EV1 = `CASE_VALUE(BIT_EV1);
localparam [BIT_MAX-1:0] PRI_EV2 = `CASE_VALUE(BIT_EV2);
localparam [BIT_MAX-1:0] PRI_EV3 = `CASE_VALUE(BIT_EV3);
`undef CASE_VALUE

So that I can construct,

 casez(event_queue)
   PRI_EV0: ;
   PRI_EV1: ;
   PRI_EV2: ;
   PRI_EV3: ;
   /* etc. */
   default: ;
 endcase

Events are set/cleared with event_queue[BIT_EVx] = 1'b0; Now, I have to explicitly type the case constants and update all of them when adding and removing a new event bit. Prior was written without the understanding that 1'b? may exist. The case labels have actions which are not numerically constructed. They aggregate data for a destination message queue/fifo.

Interestingly, I can use a local parameter like,

localparam [BIT_MAX-1:0] PRI_EV2 = 4'b01??;

So the only issue is specifying a '?' constant, which seems to work with 1'b?, but I was not aware that this was a language construct and had never seen it mentioned in replication and concatenation. It tried to trace the 2001 standard and got stuck with 'constant_expression'.

I am trying to restrict to Verilog-2001.


Solution

  • You should use casez to support wildcards. You can use z to represent the don't care bits.

    IEEE1364-2001 § 9.5.1 Case statement with don’t-cares

    Don’t-care values (z values for casez, z and x values for casex) in any bit of either the case expression or the case items shall be treated as don’t-care conditions during the comparison, and that bit position shall not be considered.

    Equivalent statement in latest SystemVerilog IEEE1800-2023 § 12.5.1 Case statement with do-not-cares

    Tested with iverilog on EDAplayground https://www.edaplayground.com/x/DxKz

    module tb;
      localparam BIT_EV0 = 0;
      localparam BIT_EV1 = 1;
      localparam BIT_EV2 = 2;
      localparam BIT_EV3 = 3;
      localparam BIT_MAX = 4; // Register size.
    
      reg [BIT_MAX-1:0] event_queue;
    
    
      localparam [BIT_MAX-1:0] PRI_EV2 = {{BIT_MAX-BIT_EV2-1{1'b0}}, 1'b1, {BIT_EV2{1'bz}}}; // z for wildcard
    
    
      always @* begin
        casez(event_queue)
          PRI_EV2: $display("in PRI_EV2 with event_queue=%b", event_queue);
          /* etc. */
          default:  $display("in default with event_queue=%b", event_queue);
        endcase
      end
    
      integer i;
      initial begin
        for(i=0; i<2**BIT_MAX; i=i+1)
          #1 event_queue = i;
        #2 $finish;
      end
    
    endmodule
    

    Alternate solution if one priority bit is expected is to use case(1'b1)

    case(1'b1) // Note: inline synthesis priority/parallel flag may be needed
      event_queue[BIT_EV3]: ; // highest priority
      event_queue[BIT_EV2]: ;
      event_queue[BIT_EV1]: ;
      event_queue[BIT_EV0]: ; // lower priority
      default:  // catch-all , lowest priority
    endcase
    

    I see in the LRMs case(1) should work the same as case(1'b1). My experience over the years with a several Verilog simulators is case(1) always hit the default condition. The case(1'b1) works as expected on all simulators.