Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constraints for arrays in system verilog

Is it valid to use initially generated random elements to constraint consecutive elements of a randomized array. Eg: I want to generate a set of 10 addr, size pairs to mimic a typical memory allocation routine and have a class as follows:

class abc;
  rand bit[5:0] size[8];
  rand bit[5:0] addr[8];

  constraint mem_unique{
  foreach(size[i]) begin
    solve size[i] before addr[i];
    size[i] inside {[6'h2:6'h10]};
    if(i>0)
      addr[i] > addr[i-1]+size[i-1];
  end
  }
endclass:abc
like image 870
venkstart Avatar asked Mar 20 '23 11:03

venkstart


2 Answers

A few extra lines of code in your example would have shown if it worked or not. Here is what I got to work:

module top;
class abc;
   rand bit[5:0] size[8];
   rand bit[6:0] addr[8];

   constraint mem_unique
     {
      foreach(size[i]) {
                       size[i] inside {[6'h2:6'h10]};
                       if(i>0) // concatenate 1'b0 to catch overflow
                          {1'b0,addr[i]} > addr[i-1]+size[i-1];
                       }
     }
endclass : abc
   abc c=new();
   initial repeat(5) begin
      $display();
      assert(c.randomize());
      foreach(c.addr[i]) $displayh(c.addr[i],, c.size[i]);
   end
endmodule  top

The foreach constraint gets unrolled, like it would by a synthesis tool. So you are left with something that looks like:

 size[0] inside {[6'h2:6'h10]};
 size[1] inside {[6'h2:6'h10]};
 {1'b0,addr[1]} > addr[0]+size[0];
 size[2] inside {[6'h2:6'h10]};
 {1'b0,addr[2]} > addr[1]+size[1];
 ...

 size[7] inside {[6'h2:6'h10]};
 {1'b0,addr[7]} > addr[6]+size[6];
like image 84
dave_59 Avatar answered Apr 27 '23 07:04

dave_59


I am not sure if what you want to do is legal, so I hope someone else will come in with a direct answer to your question. However, I can offer a solution that generates what you want in a slightly different way. You can use the post_randomize function:

class abc;
  rand bit[5:0] size[10];
  rand bit[5:0] offset[10];
  bit[5:0] addr[10];

  constraint mem_unique{
    foreach(size[i]) size[i] inside {[6'h10:6'h20]};
    (size.sum + offset.sum) <= 6'h3F;
  }

  function void post_randomize();
    foreach(addr[i]) begin
      if(i == 0) addr[i] = offset[i];
      else addr[i] = addr[i-1] + size[i-1] + offset[i];
    end
  endfunction

endclass

You will notice that this constraint will fail since you have said that the minimum value of size is 6'h10 ('d16) and you want 10 addresses. So even if the offsets are all 0, the maximum address will be 'd160 ('hA0). You do not have enough bits in addr to hold that value.

like image 27
nguthrie Avatar answered Apr 27 '23 09:04

nguthrie