Facebook/LinkedIn login is now deprecated, please disconnect our access to your social profile.
Let us contribute to a cleaner Earth, Go Green Updated: May 31, 2020

Why do we need randomness in the environment ?

Directed tests take a long time to develop because you have to think about all possible scenarios to verify different features. There is a high possibility that you would miss some kind of corner cases. So we want to be able to generate random values that fall within a valid range and apply these random values to the signals we are interested in.

Why cannot we have any random value ?

Simply running randomized tests do not make much sense because there will be many invalid cases. The way we create randomized tests with valid configurations is by the use of constraints. Such a verification style is commonly called Constrained Random Verification (CRV).

How is randomization done in SystemVerilog ?

To enable randomization on a variable, you have to declare variables as either rand or randc. The difference between the two is that randc is cyclic in nature, and hence after randomization, the same value will be picked again only after all other values have been applied. If randomization succeeds, randomize() will return 1, else 0.

We can ensure that randomization has succeeded by using assert() function. This is will avoid running simulations junk values that we may not figure until we look closer.

class myPacket;

	// Declare two variables for randomization
	// mode is of type rand and hence any random value between 0 and 3 can be picked each time
	// key is of type randc and hence random values between 0 and 7 can be picked and 
	// values will be repeated only after all other values have been already taken
	rand   bit [1:0]    mode;
	randc  bit [2:0]    key;
	// These statements are called constraints that help us to limit
	// the randomness within specified ranges
	// mode is constrained to have a value less than 3 (excluding)
	// key is constrained to have a value between 2 and 7 (excluding)
	constraint c_mode1 { mode < 3; } constraint c_key1 { key > 2;
                         key < 7; }
    // This is just a function to display current values of these variables
    function display ();
       $display ("Mode : 0x%0h Key : 0x%0h", mode, key);

module tb_top;

	// Create a class object handle
	myPacket pkt;
	initial begin
		// Instantiate the object, and allocate memory to this variable
		pkt = new ();
		// Let's just randomize the class object 15 times and display all the
		// values randomization yielded each time
		for (int i = 0; i < 15; i++) begin
			// By using assert(), we are ensuring that randomization is successful.
			assert (pkt.randomize ());
			pkt.display ();

Simulation Log
Mode : 0x0 Key : 0x3
Mode : 0x0 Key : 0x5
Mode : 0x0 Key : 0x4
Mode : 0x0 Key : 0x6
Mode : 0x2 Key : 0x4
Mode : 0x1 Key : 0x6
Mode : 0x2 Key : 0x5
Mode : 0x0 Key : 0x3
Mode : 0x1 Key : 0x3
Mode : 0x2 Key : 0x6
Mode : 0x0 Key : 0x4
Mode : 0x0 Key : 0x5
Mode : 0x0 Key : 0x5
Mode : 0x1 Key : 0x6
Mode : 0x0 Key : 0x3

Notice that randomization of Mode has resulted in repetitive values, while for Key, the values are cyclic in nature (3,4,5,6 is a complete set).

What are the different constraint styles ?

You can write constraints in a variety of ways. Constraints should not contradict each other, else randomization will fail at run-time.

class myPacket;
	rand   bit [7:0] mode;
	randc  bit [7:0] key;
	int  low, high;
	constraint c_simple {  mode > 2; 
	                       key == 3; }
// This won't work, because it contradicts c_simple - Run-time error
//	constraint c_key    {  key < 2; }

// This won't work either, because of wrong syntax - you can't specify it this way
//  constraint c_signs  {  0 < key < 4; }

    constraint c_range  { key inside {[low:high]};
    					mode inside {[21:50]}; 
    					mode inside {23, 24, 51}; }

// Choose any value other than 2,3,4,5					 
    constraint c_invert { !(key inside {[2:5]}); }
// Choose 10 or 22 ; with equal probability even if 10 and 20 appeared multiple times
    constraint c_weight { mode inside {10, 10, 10, 22, 22};
// 4 has 50/130 chance, 43 has 10/130 chance, any value between 45:90 has 70/130 chance
    constraint c_key_dist  { key  dist {4:=50, 43:=10, [45:90]:=70 };

// 4 has 10/100 chance, 43 has 30/100 chance, any value between 45:47 has 20/100 chance
    constraint c_mode_dist { mode dist {4:/10, 43:/30, [45:47]:/60 };
    function void pre_randomize ();
       this.low = 1;
       this.high = 2;


In the next section, we'll look into more examples using SystemVerilog constraints.

You consent to our cookies if you continue to use our website. To know more about cookies, see our privacy policy. I accept cookies from this site.