Random constraint, random distribution, random array, etc. - systemverilog

1, Introduction

why

  • With the increase of chip size and complexity, directional testing can not meet the needs of verification, and the proportion of randomized verification increases gradually;
  • Directional testing can find defects you think may exist, while random testing can find defects you can't think of;
  • The environmental requirements of random testing are more complex than directional testing. It requires excitation, reference model and online comparison.
  • Compared with directional testing, random testing can reduce a considerable amount of code, and generate more incentives than directional testing;
  • CRT (constraint random test) can improve efficiency and provide test incentives and test scenarios;

what

  • Device configuration: through registers and system signals
  • Environment configuration: randomize the verification environment and instantiate reasonable clocks and external feedback signals;
  • Original input data: for example, the length and width of data packets, and the order of data
  • Delay: the timing relationship between handshake signals, such as the timing relationship between valid and ready, req and ack
  • Protocol exception: if the feedback signal gives an exception, can the design maintain the stability of data processing

2, Randomization type

class packet;
//Define random variables
rand bit[31:0] src,dst,data[8];
randc bit[7:0] kind;
//Constraint variable
constraint c//Constraint requires instance name
{
  src > 10;
  src < 15;
}//Note that there is no sign
endclass

program test;
packet p;
initial begin
  p = new();
  assert(p.randomize)
  else $fatal(0,"Packet :: randomize failed");
  transmit(p);
end
endprogram
  • rand is a random definition that can be repeated. randc can be likened to drawing one card from a deck, but it will not be put back after drawing it. It will not be drawn again until all cards are drawn. In addition, randc variables will be analyzed first during random constraint analysis. Different analysis sequences may lead to different random distribution results;
  • randc loop is random in nature, but its resource occupation ratio is large, because it needs to save the previous random values;
  • randomize randomizes all attributes in the class;
  • General randomization method:
  • Define the class, and declare the concerned attribute in the class as rand/randc;
  • new object
  • handle calls the random function randomize;
  • Note the use of assertions: assert(p.randomize) $info(...);else $fatal(...); note that if there is info after assert, you can add a semicolon. If there is no message to print, you don't need to add a semicolon
assert(condition) expression;
else              expression;
assert(condition) 
else              expression;

2.1 Boolean expression

Generally, all expressions in constraints are judged logically

class order;
rand bit [7:0] lo,med,hi;
constraint bad
{
  lo<med<hi;
  }
endclass
  • Constraint bad divides two expressions from left to right: ((LO < MED) < HI). First calculate Lo < Med, and their values are 0 or 1. Then, according to the constraint, the value of hi should be greater than 0 or 1. Therefore, although the variables lo and med are randomized, they are not constrained;
class order;
rand bit [15:0] lo,med,hi;
constraint good
{
  lo < med;
  med <hi;
}
endclass

2.2 weighted distributions

Symbolmeaning
:=Indicates that the weight of each value in the value range is the same;
: /The weight is equally distributed to each value within the value range
rand int src,dst;
constraint c_dist
{
  src dist{0:=40,[1:3]:=60};
  //src = 0,weight = 40/220
  //src = 1,weight = 60/220
  //src = 2,weight = 60/220
  //src = 3,weight = 60/220
  dst dist{0:/40,[1:3]:/60};
  //dst = 0,weight = 40/100
  //dst = 1,weight = 20/100
  //dst = 2,weight = 20/100
  //dst = 3,weight = 20/100
}

Weight assignment with variables

typedef enum {READ8,READ16,READ32} read_e;
class ReadCommands;
rand read_e read_cmd;
int read8_wt = 1,read16_wt = 1,read32_wt = 1;
constraint c_read
{
  read_cmd dist
  {
    READ8  := read8_wt;
    READ16 := read16_wt;
    READ32 := read32_wt;
  };
}
endclass
  • The weight read8/16/32_wt can be changed later. Here, 8 / 16 / 32 refers to bus access, corresponding to byte access, half word access and word access respectively, so the data access is different;
  • Byte access bit 0 is reserved, half word access bit 0 is not concerned, and word access bit 0 and the first bit are not concerned;

2.3 range expressions

Use the inside operator to generate a set of values. Unless there are other constraints on variables, sv when taking random values from the set of values, the selection opportunities of each value are equal, and variables can also be used in the set

rand int c;
int lo,hi;
constraint c_range
{
  c inside{[lo:hi]};//!(c inside{[lo:hi]};c<lo or c >hi
}

You can use $to represent the minimum and maximum values of the value range

rand bit [6:0]b;//0<=b<=127
rand bit [5:0]e;
constraint c_range
{
  b inside {[$:4],[20:$]};
  c inside {[$:4],[20:$]};
}

Using data in a collection

rand int f;
int fib[5] = '{1,2,3,5,8};
constraint c_fibonacci
{
 f inside fib;
}

2.4 conditional expression

Generally, all constraints in the constraint block are valid, but sometimes we only want the constraint to be valid at some time, for example, when the bus supports byte, half word and word reading operations, but we want to only support word operations.

  • Use if...else
class stim;
bit flag;
rand bit [31:0] dst;
constraint c_stim
{
  if(flag)
  {
    dst inside {[40:80]};
  }
  else
    dst inside {[2:10],[50:67]};
}
endclass
  • Use - >
class stim;
bit flag;
rand bit [31:0] dst;
constraint c_stim
{
  flag -> dst inside {[40:80]};
  !flag -> dst inside {[2:10],[50:67]};
}
endclass

2.5 external constraints

External constraints can be added when necessary or not;

class packet;
rand bit [7:0] length;
rand bit [7:0] payload[];
constraint c_valid 
{
  length > 0;
  payload.size() == length;
}
constraint c_external;
endclass

program test;
  constraint packet::c_external{length ==  1;}
endprogram

Format for displaying external constraints: an error will be reported if there is no previous extern before use;

extern constraint c_ext

2.6 bidirectional restraint

Constraint blocks do not want to execute procedural code from top to bottom. They are declarative code and executed in parallel. All constraint expressions are valid at the same time. Ancient SV will calculate all random scalar constraints at the same time and take their intersection

rand logic[15:0] r,s,t;
constraint c_bitir
{
  r < t;
  s == r;
  t <30;
  s >25;
}

There is an exercise:

parameter MAX_SIZE = 10;
class packet;
rand bit [31:0] src,dst,data[8];
randc bit [2:0] kind;
constraint c
{
  src > 10;
  src < 15;
}
endclass:packet
//Randomization handle array
class randarray;
rand packet array[];
constraint c
{
  array.size() inside{[1:MAX_SIZE]};
}
function new();
  array = new[MAX_SIZE];
  foreach(array[i])
    array[i] = new();
endfunction
endclass:randarry

module top_tb;
packet p;
initial begin
  p = new();
  assert (p.randomize)
  else $fatal(0,"packet::randomize failied");
  foreach(p.array[i])begin
    $display("src =%d",p.array[i].src);
    $display("dst =%d",p.array[i].dst);
    $display("data = ",p.array[i].data);
    $display("kind = %d",p.array[i].kind);
  end
end
endmodule

3, Random Constrained distribution probability

3.1 classes without constraints

class unconstrained;
rand bit x;//0,1
rand bit[1:0]y;//0,1,2,3
endclass
module top_tb;
unconstrained u;
int cnt000,cnt001,cnt010,cnt011,cnt100,cnt101,cnt110,cnt111;
initial begin
  u = new();
  for(int i = 1;i<20000;i++)begin
  assert(u.randomize());
  case({u.x,u.y})
  3'b000:cnt000 = cnt000+1'b1;
  3'b001:cnt001 = cnt001+1'b1;
  3'b010:cnt010 = cnt010+1'b1;
  3'b011:cnt011 = cnt011+1'b1;
  3'b100:cnt100 = cnt100+1'b1;
  3'b101:cnt101 = cnt101+1'b1;
  3'b110:cnt110 = cnt110+1'b1;
  3'b111:cnt111 = cnt111+1'b1;
  endcase
  end
  $display("{u.x,u.y} is 000 time %0d",cnt000);
  $display("{u.x,u.y} is 001 time %0d",cnt001);
  $display("{u.x,u.y} is 010 time %0d",cnt010);
  $display("{u.x,u.y} is 011 time %0d",cnt011);
  $display("{u.x,u.y} is 100 time %0d",cnt100);
  $display("{u.x,u.y} is 101 time %0d",cnt101);
  $display("{u.x,u.y} is 110 time %0d",cnt110);
  $display("{u.x,u.y} is 111 time %0d",cnt111);
  end
endmodule
solutionxyprobability
A001/8
B011/8
C021/8
D031/8
E101/8
F111/8
G121/8
H131/8

  • For classes without constraints, the probability can be calculated according to different solutions corresponding to x and Y respectively. For example, the probability of x is 1 / 2, and the probability of y 0 is 1 / 4, so the probability bit is 1 / 8

3.2 relationship operation

class impact1;
rand bit x;//0,1
rand bit[1:0]y;//0,1,2,3

constraint c_xy
{
  (x == 0)->y == 0;
}
endclass
module top_tb;
impact1 u;
int cnt000,cnt001,cnt010,cnt011,cnt100,cnt101,cnt110,cnt111;
initial begin
  u = new();
  for(int i = 1;i<20000;i++)begin
  assert(u.randomize());
  case({u.x,u.y})
  3'b000:cnt000 = cnt000+1'b1;
  3'b001:cnt001 = cnt001+1'b1;
  3'b010:cnt010 = cnt010+1'b1;
  3'b011:cnt011 = cnt011+1'b1;
  3'b100:cnt100 = cnt100+1'b1;
  3'b101:cnt101 = cnt101+1'b1;
  3'b110:cnt110 = cnt110+1'b1;
  3'b111:cnt111 = cnt111+1'b1;
  endcase
  end
  $display("{u.x,u.y} is 000 time %0d",cnt000);
  $display("{u.x,u.y} is 001 time %0d",cnt001);
  $display("{u.x,u.y} is 010 time %0d",cnt010);
  $display("{u.x,u.y} is 011 time %0d",cnt011);
  $display("{u.x,u.y} is 100 time %0d",cnt100);
  $display("{u.x,u.y} is 101 time %0d",cnt101);
  $display("{u.x,u.y} is 110 time %0d",cnt110);
  $display("{u.x,u.y} is 111 time %0d",cnt111);
  end
endmodule
solutionxyprobability
A001/5
B010
C020
D030
E101/5
F111/5
G121/5
H131/5

  • A relational constraint is added here. When x is equal to 0, y is equal to 0;
  • The value of y depends on the value of x, so there are only five possibilities, so they are all 1 / 5;
class impact2;
randc bit x;//0,1
rand bit[1:0]y;//0,1,2,3

constraint c_xy
{
  (x == 0)->y == 0;
}
endclass
module top_tb;
impact2 u;
int cnt000,cnt001,cnt010,cnt011,cnt100,cnt101,cnt110,cnt111;
initial begin
  u = new();
  for(int i = 1;i<20000;i++)begin
  assert(u.randomize());
  case({u.x,u.y})
  3'b000:cnt000 = cnt000+1'b1;
  3'b001:cnt001 = cnt001+1'b1;
  3'b010:cnt010 = cnt010+1'b1;
  3'b011:cnt011 = cnt011+1'b1;
  3'b100:cnt100 = cnt100+1'b1;
  3'b101:cnt101 = cnt101+1'b1;
  3'b110:cnt110 = cnt110+1'b1;
  3'b111:cnt111 = cnt111+1'b1;
  endcase
  end
  $display("{u.x,u.y} is 000 time %0d",cnt000);
  $display("{u.x,u.y} is 001 time %0d",cnt001);
  $display("{u.x,u.y} is 010 time %0d",cnt010);
  $display("{u.x,u.y} is 011 time %0d",cnt011);
  $display("{u.x,u.y} is 100 time %0d",cnt100);
  $display("{u.x,u.y} is 101 time %0d",cnt101);
  $display("{u.x,u.y} is 110 time %0d",cnt110);
  $display("{u.x,u.y} is 111 time %0d",cnt111);
  end
endmodule
solutionxyprobability
A001/2
B010
C020
D030
E101/8
F111/8
G121/8
H131/8

  • randc is parsed first, so the value of X (0, 1) is parsed first. If x is equal to 0, y must be 0. For the probability that x value 0 is 1 / 2;
  • In other cases, when x is equal to 1, it is 1 / 2, and then the probability of y appearing 0, 1, 2 and 3 is 1 / 4, so E-H is 1 / 8;
class impact3;
rand bit x;//0,1
randc bit[1:0]y;//0,1,2,3

constraint c_xy
{
  (x == 0)->y == 0;
}
endclass
module top_tb;
impact3 u;
int cnt000,cnt001,cnt010,cnt011,cnt100,cnt101,cnt110,cnt111;
initial begin
  u = new();
  for(int i = 1;i<20000;i++)begin
  assert(u.randomize());
  case({u.x,u.y})
  3'b000:cnt000 = cnt000+1'b1;
  3'b001:cnt001 = cnt001+1'b1;
  3'b010:cnt010 = cnt010+1'b1;
  3'b011:cnt011 = cnt011+1'b1;
  3'b100:cnt100 = cnt100+1'b1;
  3'b101:cnt101 = cnt101+1'b1;
  3'b110:cnt110 = cnt110+1'b1;
  3'b111:cnt111 = cnt111+1'b1;
  endcase
  end
  $display("{u.x,u.y} is 000 time %0d",cnt000);
  $display("{u.x,u.y} is 001 time %0d",cnt001);
  $display("{u.x,u.y} is 010 time %0d",cnt010);
  $display("{u.x,u.y} is 011 time %0d",cnt011);
  $display("{u.x,u.y} is 100 time %0d",cnt100);
  $display("{u.x,u.y} is 101 time %0d",cnt101);
  $display("{u.x,u.y} is 110 time %0d",cnt110);
  $display("{u.x,u.y} is 111 time %0d",cnt111);
  end
endmodule
solutionxyprobability
A001/8
B010
C020
D030
E101/8
F111/4
G121/4
H131/4

  • The difference from the above is that y is parsed first, and then y (0, 1, 2, 3) is 1 / 4 respectively. There are two possibilities for the value of X. however, due to constraints, when y is equal to 1, 2 and 3, X cannot be 0, so y=0,x=0 and 1 are 1 / 8 respectively;
  • So the probability that x equals 1 and y equals 1, 2 and 3 is 1 / 4
class impact1;
randc bit x;//0,1
randc bit[1:0]y;//0,1,2,3

constraint c_xy
{
  (x == 0)->y == 0;
}
endclass
solutionxyprobability
A001/4
B010
C020
D030
E100
F111/4
G121/4
H131/4
  • First, randc is polling
  • x = 0,y can only be 0;
  • x = 1,y can only be in 1, 2 and 3
  • However, the two randc s here may have different simulation results from different simulation tools. We should avoid making the simulation tools problematic;
class impact5;
rand bit x;//0,1
rand bit[1:0]y;//0,1,2,3

constraint c_xy
{
  y > 0;
  (x == 0)->y == 0;
}
endclass
module top_tb;
impact5 u;
int cnt000,cnt001,cnt010,cnt011,cnt100,cnt101,cnt110,cnt111;
initial begin
  u = new();
  for(int i = 1;i<20000;i++)begin
  assert(u.randomize());
  case({u.x,u.y})
  3'b000:cnt000 = cnt000+1'b1;
  3'b001:cnt001 = cnt001+1'b1;
  3'b010:cnt010 = cnt010+1'b1;
  3'b011:cnt011 = cnt011+1'b1;
  3'b100:cnt100 = cnt100+1'b1;
  3'b101:cnt101 = cnt101+1'b1;
  3'b110:cnt110 = cnt110+1'b1;
  3'b111:cnt111 = cnt111+1'b1;
  endcase
  end
  $display("{u.x,u.y} is 000 time %0d",cnt000);
  $display("{u.x,u.y} is 001 time %0d",cnt001);
  $display("{u.x,u.y} is 010 time %0d",cnt010);
  $display("{u.x,u.y} is 011 time %0d",cnt011);
  $display("{u.x,u.y} is 100 time %0d",cnt100);
  $display("{u.x,u.y} is 101 time %0d",cnt101);
  $display("{u.x,u.y} is 110 time %0d",cnt110);
  $display("{u.x,u.y} is 111 time %0d",cnt111);
  end
endmodule
solutionxyprobability
A000
B010
C020
D030
E100
F111/3
G121/3
H131/3

3.3 solve...before

class slovebefore;
rand bit x;//0,1
rand bit[1:0]y;//0,1,2,3

constraint c_xy
{
  (x == 0)->y == 0;
  solve x before y;
}
endclass
module top_tb;
slovebefore u;
int cnt000,cnt001,cnt010,cnt011,cnt100,cnt101,cnt110,cnt111;
initial begin
  u = new();
  for(int i = 1;i<20000;i++)begin
  assert(u.randomize());
  case({u.x,u.y})
  3'b000:cnt000 = cnt000+1'b1;
  3'b001:cnt001 = cnt001+1'b1;
  3'b010:cnt010 = cnt010+1'b1;
  3'b011:cnt011 = cnt011+1'b1;
  3'b100:cnt100 = cnt100+1'b1;
  3'b101:cnt101 = cnt101+1'b1;
  3'b110:cnt110 = cnt110+1'b1;
  3'b111:cnt111 = cnt111+1'b1;
  endcase
  end
  $display("{u.x,u.y} is 000 time %0d",cnt000);
  $display("{u.x,u.y} is 001 time %0d",cnt001);
  $display("{u.x,u.y} is 010 time %0d",cnt010);
  $display("{u.x,u.y} is 011 time %0d",cnt011);
  $display("{u.x,u.y} is 100 time %0d",cnt100);
  $display("{u.x,u.y} is 101 time %0d",cnt101);
  $display("{u.x,u.y} is 110 time %0d",cnt110);
  $display("{u.x,u.y} is 111 time %0d",cnt111);
  end
endmodule
solutionxyprobability
A001/2
B010
C020
D030
E101/8
F111/8
G121/8
H131/8

  • Similar to the prior analysis of randc, the probability distribution is the same as that of randc;
  • However, do not abuse solve... before, which will reduce the calculation speed;

4, Stochastic constrained control

4.1 control multiple constraint blocks (constraint_mode)

class packet;
rand int length;
constraint c_short {length inside{[1:32]};}
constraint c_long {length inside{[1000:1023]};}
endclass
module top_tb;
packet p;
initial begin
p = new();
p.c_short.constraint_mode(0);//disabling short constraint
assert(p.randomize());
$display("p::length = %d",p.length);
p.constraint_mode(0);
p.c_short.constraint_mode(1);
assert(p.randomize());
$display("p::length = %d",p.length);
end
endmodule
  • A constraint block in the class can be closed separately, and each constraint block can be opened separately. Use 0 / 1;
  • You can turn off all constraint blocks in the class at one go;

4.2 control random variable rand_mode()

class packet;
rand bit [7:0] length,payload[];
constraint c_valid {length > 0;payload.size() ==length;}
endclass
module top_tb;
packet p;
initial begin
p = new();
p.length.rand_mode(0);
p.length = 42;
assert(p.randomize());
$display("p::length = %d",p.length);
p.length.rand_mode(1);
assert(p.randomize());
$display("p::length = %d",p.length);
end
endmodule
  • The random function of a random variable can be switched and controlled through rand_mode;

4.3 control random variable randomize (with {}

class transaction;
rand bit [31:0]addr,data;
constraint c1{addr inside{[0:100],[1000:2000]};}
endclass

module top_tb;
transaction t;
initial begin
  t = new();
  assert(tr.randomize() with {addr >= 50;addr <= 1500;data < 10;});
  $display("t::addr is %d",t.addr);
  $display("t:data is %d",t.data);
  assert(t.randomize() with{addr == 2000;data >10;});//force addr to a specific value,data >10
  $display("t::addr is %d",t.addr);
  $display("t:data is %d",t.data);
end
endmodule
  • Here, randomize() with {} can enforce constraints and even become a specific value;

4.4 randomize individual control variables

class rising;
byte low;
rand byte med,hi;
constraint c_up{low<med;med<hi;}
endclass
module top_tb;
rising r;
initial begin
  r = new();
  r.randomize();
  $display("r::low is %d,r:med is %d,r::hi is %d",r.low,r.med,r.hi);
  r.randomize(med);
  $display("r::low is %d,r:med is %d,r::hi is %d",r.low,r.med,r.hi);
  r.randomize(low);
  $display("r::low is %d,r:med is %d,r::hi is %d",r.low,r.med,r.hi);
end
endmodule

  • Here, variables that are not rand type can also be randomized to realize the control of single variables;
  • However, randomization by variables is not recommended here;

4.5 pre_randomize and post_randomize

Their characteristics:

  • They are all function s and will not consume events;
  • pre_randomize->randomize->post_randomize
  • The pre_randomize() and post_randomize() functions can be rewritten by the user. The user uses the pre_randomize() function to modify the values of non random variables in the code before randomization, such as the lower limit, weight, etc;
  • The post_randomize() function can modify the random value or do some other calculations after randomization.
  • If randomize fails, the post will not be executed,
  • pre and post can be rewritten, but randomize cannot be rewritten;
  • You can rewrite the methods in the form of overloading;
class wr_tran;
  int constraint_en;
  int broadcast;
  rand int wr_addr;
  rand int wr_data;
  rand bit valid;
  constraint generic_c
  { 
    valid == 1;
    wr_addr < 100;
  }
  function void pre_randomize();
      $display("call the pre_randomize !");
      if(!constraint_en)
        generic_c.constraint_mode(0);
   endfunction
  function void post_randomize();
     $display("call post_randomize!");
     if(wr_addr == 1)
       broadcast = 1;
     else broadcast = 0;
   endfunction
 endclass
module top_tb;
  wr_tran tr;
  initial begin
    tr = new();
    tr.constraint_en = 0;
    tr.randomize() with
    {
      wr_addr == 200;
      wr_data == 3;
      valid   == 0;
    };
    $display("wr_addr = %d,
              wr_data = %d,
              valid   = %d,
              broadcast = %d",
              tr.wr_addr,tr.wr_data,tr.valid,tr.broadcast);
              end
              endmodule          

5, Randomization common errors

  • The use of signed variables in random variables leads to randomization errors;
  • Variable overflow may lead to high-order removal and randomization error;
    Tips to avoid randomization errors:
  • Avoid multiplication, division and modulo operations. If you want to use it, move left and right instead of multiplication and division;
  • Use AND mask instead of taking mold;
sig1:12345678
sig 1 &000FF 000
class test;
  rand bit[7:0]sig1;
  rand int unsigned sig1;
constrain c
{
  sig2>1000;
  sig1>sig2;//The maximum value of sig1 is 256, which cannot reach 1000. Pay attention to the bit width and symbol
rand bit[7:0]sig1;
rand bit[7:0]sig2;
constraint c1{sig1>5;}
constraint c2{sig2>10;}
constraint c2{sig1+sig2 ==13;}//This is also wrong. The forms of multiple random variables may be contradictory;

So we need to pay attention when using randomization

  • data type
  • Data bit width (more accurate)
  • Relationships between variables in multiple constraint blocks
  • Constrains the result of an expression in a block
  • The constraints in the constraint block conflict

Tags: systemverilog

Posted on Thu, 18 Nov 2021 11:18:49 -0500 by MoombaDS