Randomization results for signed variables and assignment to RAL variable

rand bit signed [15:0] x[36]; // 36 elements of 16 bit each, with MSB as signed bit

constraints add{
 foreach(x[i]){
  if(i%4==0){
   x[i]+x[i+1]+x[i+2]+x[i+3]=='sh4000;
   x[i] inside {[-32767:32767]};
  }
 }
}

void post_randomize()
{

abc_reg[4]; // Some registers from RAL, here for example, I need to assign first 4 registers value such that their sum is 16384 or 'h40000 (can have negative values, since these are signed 16 bit registers)

foreach(x[i]}{
abc_reg.value = x[i] // value in RAL model is unsigned, uvm_reg_data_t value, so I need to create a separate x[i] array which can take signed values.
}
}

Output for abc_reg →

abc_reg[0] = 22570
abc_reg[1] = 30526
abc_reg[2] = -1
abc_reg[3] = -30626

The sum of above 4 values is not equal to 'h4000 or 16384?

Can anyone tell me what am I missing here?

Can you show us the values in x[0:3]? You have a typo in constraints. Are you sure you copied the code correctly. It would really help to have a minimal, complete reproducible example


constraint add{
 foreach(x[i]){
  if(i%4==0){
   x[i]+x[i+1]+x[i+2]+x[i+3]=='sh4000;
   x[i] inside {[-32767:32767]};
  }
 }
}

void post_randomize()
{

abc_reg[4]; // Some registers from RAL, here for example, I need to assign first 4 registers value such that their sum is 16384 or 'h40000 (can have negative values, since these are signed 16 bit registers)

foreach(x[i]}{
abc_reg.value = x[i] // value in RAL model is unsigned, uvm_reg_data_t value, so I need to create a separate x[i] array which can take signed values.

$display("x[%0d] is =%0d",i,x[i]);
}
}

x[4] is =-30626
x[5] is =-6086
x[6] is =30526
x[7] is =22570

But values of abc_reg are:
abc_reg[4] is =-30626
abc_reg[5] is =-1
abc_reg[6] is =30526
abc_reg[7] is =22570

Hi @dave_59 , can you point out where I might be going wrong?

I’m unable to reproduce your problem with the incomplete code you have shown.

It would really help to have a minimal, complete reproducible example.

If it’s of any help I created this example EDA link and your constraint seems to be working as expected, as Dave mentioned it’s a bit hard to help without showing more code, at least the type of abc_reg and why you loop through all x indices even though it has a bigger size (36) than abc_reg (4) …

module test;
  class c;
    rand bit signed [15:0] x[36];
    constraint add {
     foreach(x[i]){
      if(i%4==0){
       x[i]+x[i+1]+x[i+2]+x[i+3]=='sh4000;
       x[i] inside {[-32767:32767]};
      }
     }
    }
  endclass
  
  initial begin
    bit signed [15:0] slice[4];
    c c0 = new();
    c0.randomize();
    $display("%p", c0.x);
    for(int i = 0 ; i < $size(c0.x); i+=4) begin
      slice = c0.x[i+:4];
      $display("Array slice number %0d is : %p", (i/4), slice);
      $display("The sum of it is %h", slice.sum());
    end
  end
endmodule

Let me explain further, it might help.

I have 18 registers in RAL model. Every register has 2 fields (16 bits signed each).

The constraint requires that sum of every consecutive 4 fields, i.e. field 0 and 1 of reg1 and field 0 and 1 of reg 2 = 16384.

Since in RAL model, value is of type uvm_reg_data_t which is unsigned, I can’t directly apply the addition constraints.

So, I created an array of 36 elements (x), which are signed, applied foreach loop for every 4 elements whose sum equals 'sh16384, and then using these variables value to assign to original RAL registers field (which are abc_reg fields)

I only showed 1 instance of 4 fields or 2 registers here.

Hope this helps
Thank you

Since nothing seems to be wrong with the randomization of x[36], there must be something wrong with the code you have never shown inside post_randomize().\

Just a thought, you can get rid of the extra array by using a signed'() cast.

constraints add{
 foreach(x[i]){
  if(i%4==0){
   signed'(abc_reg[i])+signed'(abc_reg[i+1])+signed'(abc_reg[i+2])+signed'(abc_reg[i+3])=='sh4000;
   signed'(abc_reg[i]) inside {[-32767:32767]};
  }
 }
}