Tutorials

RANDSEQUENCE

The random sequence generator is useful for randomly generating sequences of stimulus. For example, to verify a temporal scenario, a sequence of packets are needed. By randomizing a packet, it will generate most unlikely scenarios which are not interested. These type of sequence of scenarios can be generated using randsequence. A randsequence grammar is composed of one or more productions. Production items are further classified into terminals and nonterminals. A terminal is an indivisible item that needs no further definition than its associated code block.

EXAMPLE:
module rs();
initial
begin
repeat(5)
begin
randsequence( main )
main : one two three ;
one : {\$write("one");};
two : {\$write(" two");};
three: {\$display(" three");};
endsequence
end
end
endmodule

RESULTS:

one two three
one two three
one two three
one two three
one two three

The production main is defined in terms of three nonterminals: one, two and three. Productions one,two and three are terminals. When the main is chosen, it will select the sequence one, two and three in order.

Random Productions:

A single production can contain multiple production lists separated by the | symbol. Production lists separated by a | imply a set of choices, which the generator will make at random.

EXAMPLE:
module rs();
initial
repeat(8)
randsequence( main )
main : one | two | three ;
one : {\$display("one");};
two : {\$display("two");};
three: {\$display("three");};
endsequence
endmodule

RESULTS:

# three
# three
# three
# three
# one
# three
# two
# two

Results show that one, two and three are selected randomly.

Random Production Weights :

The probability that a production list is generated can be changed by assigning weights to production lists. The probability that a particular production list is generated is proportional to its specified weight. The := operator assigns the weight specified by the weight_specification to its production list. A weight_specification must evaluate to an integral non-negative value. A weight is only meaningful when assigned to alternative productions, that is, production list separated by a |. Weight expressions are evaluated when their enclosing production is selected, thus allowing weights to change dynamically.

EXAMPLE:
module rs();
integer one_1,two_2,three_3;
initial
begin
one_1 = 0;
two_2 = 0;
three_3 = 0;
repeat(6000)
randsequence( main )
main : one := 1| two := 2| three := 3;
one : {one_1++;};
two : {two_2++;};
three: {three_3++;};
endsequence
\$display(" one %0d two %0d three %0d",one_1,two_2,three_3);
end
endmodule

RESULTS:

# one 1011 two 2005 three 2984

If..Else

A production can be made conditional by means of an if..else production statement. The expression can be any expression that evaluates to a boolean value. If the expression evaluates to true, the production following the expression is generated, otherwise the production following the optional else statement is generated.

EXAMPLE:
module rs();
integer one_1,two_2,three_3;
reg on;
initial
begin
on = 0;
one_1 = 0;
two_2 = 0;
three_3 = 0;
repeat(2500)
randsequence( main )
main : one three;
one : {if(on) one_1++; else two_2 ++; };
three: {three_3++;};
endsequence
\$display(" one %0d two %0d three %0d",one_1,two_2,three_3);
end
endmodule

RESULTS:

# one 0 two 2500 three 2500

Case

A production can be selected from a set of alternatives using a case production statement. The case expression is evaluated, and its value is compared against the value of each case-item expression, which are evaluated and compared in the order in which they are given. The production associated with the first case-item expression that matches the case expression is generated. If no matching case-item expression is found then the production associated with the optional default item is generated, or nothing if there no default item. Case-item expressions separated by commas allow multiple expressions to share the production.

EXAMPLE:
module rs();
integer one_1,two_2,three_3;
initial
begin
one_1 = 0;
two_2 = 0;
three_3 = 0;
for(int i = 0 ;i < 6 ;i++)
begin
randsequence( main )
main : case(i%3)
0 : one;
1 : two;
default: def;
endcase;
one : {\$display("one");};
two : {\$display("two");};
def : {\$display("default");};
endsequence
end
end
endmodule

RESULTS:

one
two
default
one
two
default

Repeat Production Statements :

The repeat production statement is used to iterate a production over a specified number of times. The repeat production statement itself cannot be terminated prematurely. A break statement will terminate the entire randsequence block

PUSH_OPER : repeat( \$urandom_range( 2, 6 ) ) PUSH ;

Interleaving productions-rand join :

EXAMPLE:
module rs();
integer one_1,two_2,three_3;

initial
begin
one_1 = 0;
two_2 = 0;
three_3 = 0;
repeat(6000)
randsequence( main )
main : one | repeat(2) two | repeat (3) three ;
one : one_1++;
two : two_2++;
three: three_3++;
endsequence

\$display(" one %d two %d three %d",one_1,two_2,three_3);
end
endmodule

RESULTS:

one 989 two 2101 three 2810

Rand Join

The rand join production control is used to randomly interleave two or more production sequences while maintaining the relative order of each sequence.

EXAMPLE:
module rs();

initial
for(int i = 0;i < 24;i++) begin
randsequence( main )
main : rand join S1 S2 ;
S1 : A B ;
S2 : C D ;
A : \$write("A");
B : \$write("B");
C : \$write("C");
D : \$write("D");
endsequence
if(i%4 == 3 )
\$display("");
end
endmodule

RESULTS:

A B C D
A C B D
A C D B
C D A B
C A B D
C A D B

Note that B always comes after A and D comes after C. The optional expression following the rand join keywords must be a real number in the range 0.0 to 1.0. The value of this expression represents the degree to which the length of the sequences to be interleaved affects the probability of selecting a sequence. A sequences length is the number of productions not yet interleaved at a given time. If the expression is 0.0, the shortest sequences are given higher priority. If the expression is 1.0, the longest sequences are given priority.

EXAMPLE:
module rs();

initial
for(int i = 0;i < 24;i++) begin
randsequence( main )
main : rand join (0.0) S1 S2 ;
S1 : A B ;
S2 : C D ;
A : \$write("A");
B : \$write("B");
C : \$write("C");
D : \$write("D");
endsequence
if(i%4 == 3 )
\$display("");
end
endmodule

RESULTS:

A B C D
C D A B
A C B D
A C D B
C A B D
C A D B

EXAMPLE:
module rs();

initial
for(int i = 0;i < 24;i++) begin
randsequence( main )
main : rand join (1.0) S1 S2 ;
S1 : A B ;
S2 : C D ;
A : \$write("A");
B : \$write("B");
C : \$write("C");
D : \$write("D");
endsequence
if(i%4 == 3 )
\$display("");
end
endmodule

RESULTS:

A C B D
A C D B
C A D B
C A D B
A B C D
C D A B
C A B D

Break

The break statement terminates the sequence generation. When a break statement is executed from within a production code block, it forces a jump out the randsequence block.

EXAMPLE:
randsequence()
WRITE : SETUP DATA ;
SETUP : { if( fifo_length >= max_length ) break; } COMMAND ;
DATA : ...
endsequence

When the example above executes the break statement within the SETUP production, the COMMAND production is not generated, and execution continues on the line labeled next_statement.

Return

The return statement aborts the generation of the current production. When a return statement is executed from within a production code block, the current production is aborted. Sequence generation continues with the next production following the aborted production.

EXAMPLE:
randsequence()
TOP : P1 P2 ;
P1 : A B C ;
P2 : A { if( flag == 1 ) return; } B C ;
A : { \$display( A ); } ;
B : { if( flag == 2 ) return; \$display( B ); } ;
C : { \$display( C ); } ;
endsequence

Depending on the value of variable flag, the example above displays the following:
flag == 0 ==> A B C A B C
flag == 1 ==> A B C A
flag == 2 ==> A C A C
When flag == 1, production P2 is aborted in the middle, after generating A. When flag == 2, production B is aborted twice (once as part of P1 and once as part of P2), but each time, generation continues with the next
production, C.

Value Passing Between Productions

Data can be passed down to a production about to be generated, and generated productions can return data to the non-terminals that triggered their generation. Passing data to a production is similar to a task call, and uses the same syntax. Returning data from a production requires that a type be declared for the production, which uses the same syntax as a variable declaration. Productions that accept data include a formal argument list. The syntax for declaring the arguments to a production is similar to a task prototype; the syntax for passing data to the production is the same as a task call.

EXAMPLE:
randsequence( main )
main : first second gen ;
first : add | dec ;
second : pop | push ;