Restrict Data to powers-of-Two

I am trying alternatives to using $countones / $onehot() to achieve Powers-of-Two .

Here is a Snippet from LRM Section 18.3 ::


  class Bus;
     rand bit[31:0] data;
  endclass

  Bus bus ;
 
  initial begin
 
    if ( bus.randomize() with { ( data & ( data - 1 ) ) == 0 ; } // Issue here !!
      $display("Success")

  end

I believe there is an issue with the Code in LRM above that data can also be Constrained to be 0 which is Not a Power-of-Two !!

I believe we need one more additional in-line Constraint ::


    if ( bus.randomize() with { ( data & ( data - 1 ) ) == 0 ; data != 0 ; }  // Equivalent to constraint :: $countones(data) == 1 ;
   

[Q1] Also need some suggestion to achieve the same using Shift Operator ::


            class Bus;
             rand bit[4:0] data;
  
             constraint ONEHOT_LEFT_SHIFT { 1 << data ; } // [B] Need behavior similar to $countones(data) == 1'b1 ; 
            
            endclass
          
      [B] Any suggestions what I could add in constraint ONEHOT_LEFT_SHIFT ?

In reply to ABD_91:

Hi,

Refer to the code below using left shift operator.


``` verilog

module test;
  
  class powerOf2s;
    rand bit [4:0] data;
    rand int pos;
    constraint c_pos {
      pos inside {[0:4]};
    };
    constraint c_powerof2s {
      data == 1 << pos;
    };
    constraint c_pos_data_order {
      solve pos before data;
    };
    
    function void print();
      $display("pos = %0d", pos);
      $display("data = %d", data);
    endfunction : print
    
  endclass : powerOf2s
  
  powerOf2s p;
  
  initial begin
    p = new();
    repeat(10) begin
    if(!p.randomize()) $error("Rand failed!");
    p.print();
    end
  end
  
endmodule : test