Constraint for 5 bits set and consecutively set for 80% of the time

Hi,
I have tried to code for the scenario and found below is not working (always first 5 bits are set to 1) when set_consctv is 1. Please let me know the issue.

class a;
  rand bit[99:0] var1;
  rand bit set_consctv;
  constraint c_var1{
    $countones(var1) == 5;
    foreach(var1[i]){
      if(var1[i] && set_consctv && i<=95){
        {var1[i],var1[i+1],var1[i+2],var1[i+3],var1[i+4]} == 5'b11111;
      }else if(var1[i] && !set_consctv && i<=95){
        {var1[i],var1[i+1],var1[i+2],var1[i+3],var1[i+4]} != 5'b11111;
      }
    }
  }
          constraint c_set_consctv{
            set_consctv dist {1:=80, 0:=20};
          }
endclass
module test;
            a a_h;
            initial
              begin
                a_h = new;
                repeat(20) begin
                  void'(a_h.randomize());
                  $display("a_h.set_consctv:%0b a_h.var1:%25h",a_h.set_consctv,a_h.var1);
                end
              end
          endmodule

simulation results:

# run -all
# a_h.set_consctv:0 a_h.var1:0c00000000000080010000800
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:0 a_h.var1:0000480002000050000000000
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:0 a_h.var1:0004000000000020080003000
# a_h.set_consctv:0 a_h.var1:0000000400002000800800200
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:0 a_h.var1:0000040080008040010000000
# a_h.set_consctv:1 a_h.var1:f800000000000000000000000
# a_h.set_consctv:0 a_h.var1:0400000400000280000800000
# a_h.set_consctv:0 a_h.var1:2000020000002800000000020

In reply to verif_eng_20:

Please use code tags making your code easier to read. I have added them for you.

I do not understand what you mean by “not working”. Every case you show where a_h.set_consctv is 1, the first 5 bits are set “F8”

And a much simpler constraint would be

 constraint c_var1{
    $countones(var1) == 5;
    if (set_consctv)
      var1[99:95] == '1;
    else
      var1[99:95] != '1;    
  }

In reply to dave_59:

I was expecting code would place 5’b11111 randomly in the 100-bit var1. However, always bits [99:95] bits are set to 1.

PS:Thank you Dave for adding code tags, I didn’t know there is such a feature. I would do it from my next question

In reply to verif_eng_20:



class cards;
  rand bit[99:0] ab;
  rand int N;
  bit [4:0] cd = 5'b11111;
  
  constraint ab_c {N inside {[0:90]};
                   ab == cd << N;
                  
                  
                  }
  
  
  function void post_randomize();
    ab[99:95] = 5'b11111;
  endfunction
  
  
  
endclass

module tb;
  cards c1;
  
  initial begin
    c1 = new();
    repeat (5) begin
    assert (c1.randomize());
      $display ("%b ***** N value is %d",c1.ab,c1.N);
    end
    
  end
  
  
endmodule


In reply to rag123:

You forgot the question asked for five consecutive 1’s only 80% of the time

class a;
  rand bit[99:0] var1;
  rand bit set_consctv;
  rand int N;
  constraint c_var1{
    $countones(var1) == 5;
    N inside {[0:95]};
    if (set_consctv)
      var1 == 5'b11111 << N;
    else
      foreach(var1[i])
        i <=95 -> var1 != 5'b11111 << N;
  }
          constraint c_set_consctv{
            set_consctv dist {1:=80, 0:=20};
          }
endclass

In reply to dave_59:

I think this would work. However, I am actually more interested in why the code I posted was not working.

In reply to verif_eng_20:

It might help to shrink your code into something more manageable, like 3 consecutive bits in a 6-bit vector. Then unroll the foreach constraints manually.

class a;
  rand bit[5:0] var1;
  constraint c_var1{
    $countones(var1) == 3;
    foreach(var1[i]){
      if(var1[i] && i<=3)
        {var1[i],var1[i+1],var1[i+2]} == 3'b111;
    }
  }
endclass
module test;
            a a_h;
            initial
              begin
                a_h = new;
                repeat(20) begin
                  void'(a_h.randomize());
                  $display("a_h.var1:%6b",a_h.var1);
                end
              end
endmodule

Then unroll the foreach loop into 6 set of constraints

      if(var1[0] && 0<=3)
        {var1[0],var1[1],var1[2]} == 3'b111;
      if(var1[1] && 1<=3)
        {var1[1],var1[2],var1[3]} == 3'b111;
      if(var1[2] && 2<=3)
        {var1[2],var1[3],var1[4]} == 3'b111;
      if(var1[3] && 3<=3)
        {var1[3],var1[4],var1[5} == 3'b111;
      if(var1[4] && 4<=3)
       // always false
      if(var1[5] && 5<=3)
       // always false

This can be further reduced to

      if(var1[0])
        {var1[2:0]} == 3'b111;
      if(var1[1])
        {var1[3:1]} == 3'b111;
      if(var1[2])
        {var1[4:2]} == 3'b111;
      if(var1[3])
        {var1[5:3]} == 3'b111;


Now you should be able to see why only var1[3] can be true and still satisfy the other constraint $countones(var1) == 3;

In reply to dave_59:

Now, I can see why code wasn’t working. Thank you very much Dave.

In reply to verif_eng_20:

Hi, Could you explain the question?
I got the first part like it needs to have 5 consecutive bits as set-bits. But what about 80%? What does that mean?

In reply to Shubhabrata:

80% of the solutions, the 5 bits set to 1 need to be connectives. The other 20% of the solutions, the 5 bits set to 1 must not be consecutive.

In reply to dave_59:
Thanks. I got it and I tried to make a few changes in verif_eng_20’s code.


class a;
  rand bit[99:0] var1;
  rand bit set_consctv;
  rand int start_point;
  constraint c_var1{
    $countones(var1) == 5;
    start_point inside {[0:95]};
    foreach(var1[i]){
      if(set_consctv && i==start_point && i<=95){
        {var1[i],var1[i+1],var1[i+2],var1[i+3],var1[i+4]} == 5'b11111;
      }else if(!set_consctv && i<=95){
        {var1[i],var1[i+1],var1[i+2],var1[i+3],var1[i+4]} != 5'b11111;
      }
    }
  }
          constraint c_set_consctv{
            set_consctv dist {1:=80, 0:=20};
          }
endclass
module test;
            a a_h;
            initial
              begin
                a_h = new;
                repeat(20) begin
                  void'(a_h.randomize());
                  $display("a_h.set_consctv:%0d , a_h.start_point:%0d , a_h.var1:%b",a_h.set_consctv,a_h.start_point,a_h.var1);
                end
              end
          endmodule

Here I have used a rand property start_point which will decide from where We’ll be getting 1s. In the constrait section, I made it very clear that the value of start_point lies between 0 and 95. Coming to the foreach loop, in the if-condition, I had to mention i<=95. Or it was giving garbage value.
I am not understanding why it happened.

In reply to Shubhabrata:

Like I said above, try working it out on an example with much smaller width.

In reply to dave_59:

Hello Sir, My doubt is not regarding what you explained. If you analyze the following code you will see that I have used a start property and the value is between 0 to 3. Still, I had to mention i<=3 along with i==start.


class a;
  rand bit[5:0] var1;
  randc int start;
  constraint condition{start inside{[0:3]};}
  constraint c_var1{
    $countones(var1) == 3;
    foreach(var1[i]){
      if(i==start) // Here I will have to use i<=3 to get proper output 
        {var1[i],var1[i+1],var1[i+2]} == 3'b111;
      else if(i<start)var1[i] == 0;
      else if(i>start && i-start > 2)var1[i] == 0;
  }
  }
endclass
module test;
            a a_h;
            initial
              begin
                a_h = new;
                repeat(20) begin
                  void'(a_h.randomize());
                  $display("a_h.var1:%6b",a_h.var1);
                end
              end
endmodule

Here for var1[4+2], it’s getting out of bound error. Now my question is when the start is inside 0-3, for i=4 why will the statement be executed?
I hope I explained where I am having doubts pretty well.

In reply to Shubhabrata:

This is because the foreach loop gets unrolled before a value for start gets chosen. And an if expression in a constraint is not procedural code, it is another way of writing the Boolean expression

!(i == start) || {var1[i],var1[i+1],var1[i+2]} == 3'b111;

Adding i<=3 acts as a guard because when you unroll the for loop, it becomes a constant true or false.

In reply to dave_59:

Thank you … Finally understood the mechanism.

In reply to dave_59:

In order for this to work (in Dave’s solution to generate var1), I think following code change is needed
i <=95 → var1 != 5’b11111 << N;
change to:
i <=95 → var1 != 5’b11111 << i;

In reply to dave_59:

Hi Dave

is it legal to use like this:

rand int N;
N inside {[0:95]};
var1[N+:5] == 5'b11111

Thank you

In reply to peter:

It is not currently legal. The LRM says:

Individual array elements can be constrained, in which case the index expression may include iterative constraint loop variables, constants, and state variables.

In reply to dave_59:

What is the state variables? rand variables is not state variable?
Thank you

In reply to peter:

A state variable is a non random variable. It gets treated like a constant value as far as the constraint is concerned.