statement ::= [ block_identifier : ] { attribute_instance } statement_item
statement_item ::=
{ attribute_instance } blocking_assignment ;
| { attribute_instance } nonblocking_assignment ;
| { attribute_instance } procedural_continuous_assignments ;
| { attribute_instance } case_statement
| { attribute_instance } conditional_statement
| { attribute_instance } inc_or_dec_expression ;
| { attribute_instance } function_call ;
| { attribute_instance } disable_statement
| { attribute_instance } event_trigger
| { attribute_instance } loop_statement
| { attribute_instance } jump_statement
| { attribute_instance } par_block
| { attribute_instance } procedural_timing_control_statement
| { attribute_instance } seq_block
| { attribute_instance } system_task_enable
| { attribute_instance } task_enable
| { attribute_instance } wait_statement
| { attribute_instance } procedural_assertion_item
| { attribute_instance } clocking_drive
| void ’
( function_call )
| randsequence
| scope_randomize
| randcase_statement
| expect
( property_spec ) [ action_block ]
| expect
( property_instance ) [ action_block ]
function_statement ::= [ block_identifier
: ] function_statement_item
function_statement_item ::=
{ attribute_instance } function_blocking_assignment
;
| { attribute_instance } function_case_statement
| { attribute_instance } function_conditional_statement
| { attribute_instance } inc_or_dec_expression ;
| { attribute_instance } function_call ;
| { attribute_instance } function_loop_statement
| { attribute_instance } jump_statement
| { attribute_instance } function_seq_block
| { attribute_instance } disable_statement
| { attribute_instance } system_task_enable
blocking_assignment ::= // from Annex A.6.4 A.6.2
variable_lvalue = delay_or_event_control expression
| hierarchical_variable_identifier = new [ constant_expression
] [ ( variable_identifier ) ]
| class_variable_identifier [ parameter_value_assignment ] = new [ ( list_of_arguments
) ]
| class_variable_identifier .
randomize [ (
) ] with constraint_block ;
| operator_assignment
SystemVerilog also allows a time unit to be
specified in the assignment statement, as follows:
conditional_statement ::= //
from Annex A.6.6
[
unique_priority ]
if ( expression ) statement_or_null [ else
statement_or_null ]
| if_else_if_statement unique_priority_if_statement
if_else_if_statement unique_priority_if_statement ::=
[ unique_priority
] if ( expression ) statement_or_null
{ else [ unique_priority ] if
( expression ) statement_or_null }
[ else statement_or_null ]
A unique
if indicates that there should not be
any overlap in a series of if...else...if conditions, i.e. they should be mutually
exclusive, allowing the expressions to be evaluated in parallel. A
software tool shall issue an error if it determines that there is a potential overlap in the conditions. more than one condition is, or can
be, true. A software tool shall also issue an error if it determines that no
condition is true, or it is possible that no condition is true, and the final
if does not have a corresponding else.
A priority
if indicates that a series of if...else...if conditions
shall be evaluated in the order listed. In the preceding example, if the
variable a had a value of 0, it would satisfy both the first and
second conditions, requiring priority logic. A software
tool shall also issue an error if it determines that no condition is true, or
it is possible that no condition is true, and the final if does not have a
corresponding else.
The unique
and priority keywords apply to the entire series of if...else...if conditions.
In the preceding examples it would have been illegal to insert either keyword
after any of the occurrences of else. To nest another if statement
within such a series of conditions, a begin...end
block should be used.
loop_statement ::=
forever statement_or_null
| repeat ( expression )
statement_or_null
| while ( expression )
statement_or_null
| for ( variable_decl_or_assignment
{ , variable_decl_or_assignment } ; expression
;
variable_assignment { , variable_assignment
} ) statement_or_null
| for
(
for_initialization ; expression ; for_step )
statement_or_null
| do statement_or_null while ( expression ) ;
| foreach ( array_identifier [ loop_variables
] ) statement
for_initialization ::=
list_of_variable_assignments
| data_type list_of_variable_assignments
{ , data_type list_of_variable_assignments
}
for_step ::= for_step_assignment
{ , for_step_assignment
}
for_step_assignment ::=
operator_assignment
| inc_or_dec_expression
variable_decl_or_assignment ::=
variable_declaration
| variable_assignment
Verilog
provides for,
while,
repeat and forever loops. SystemVerilog
enhances the Verilog for loop,
and adds a do...while loop and a foreach loop.
8.5.3
The foreach loop
The foreach
construct specifies iteration over the elements of an array. Its argument is an
identifier that designates any type of array (fixed-size, dynamic, or
associative) followed by a list of loop variables enclosed in square brackets.
Each loop variable corresponds to one of the dimensions of the array. The foreach
construct is similar to a repeat loop
that uses the array bounds to specify the repeat count instead of an
expression.
Examples:
string words [2] = { “hello”, “world” };
int prod [1:8] [1:3];
foreach( words [ j ] )
$display( j , words[j] ); // print each index and value
foreach( prod[ k, m ] )
prod[k][m] = k * m; // initialize
The number of loop variables must match the number of
dimensions of the array variable. Empty
loop variable can be used to indicate no iteration over that dimension of the
array, and contiguous empty loop variables towards the end can be omitted.
The mapping of loop variables to array indexes is determined
by the dimension cardinality, as described
in Section 22.4. The foreach arranges for higher cardinality indexes to change
more rapidly.
//
1 2 3
3
4 1 2
-> Dimension numbers
int A [2][3][4];
bit [3:0][2:1] B [5:1][4];
foreach( A [ i, j, k ] ) …
foreach( B [ q, r, , s ] ) …
The first foreach causes i to iterate from 0 to 1, j from 0 to 2, and k from 0 to 3. The second foreach causes q to iterate from 5 to 1, r from 0 to 3, and s from 2 to 1 (iteration over the 3rd
index is skipped).
Multiple loop variables correspond to nested loops that
iterate over the given indexes. The nesting of the loops is determined by the
dimension cardinality: outer loops correspond to lower cardinality indexes. In
the first example above, the outermost loop iterates over i and the innermost loop iterates over k.
When loop variables are used in expressions other than as
indexes to the designated array, they are auto-cast into a type consistent with
the type of index. For fixed-size and dynamic arrays the auto-cast type is int. For associative arrays indexed by
a specific index type the auto-cast type is the same as the index type. For
associative arrays indexed by a wildcard index (*) the auto-cast type is unsigned longint.
To use different types, an explicit cast can be used.
event_control
::=
@ hierarchical_event_identifier
| @ ( event_expression )
| @*
| @ (*)
| @ sequence_instance
event_expression ::=
[ edge_identifier ]
expression [ iff expression ]
| sequence_instance [ iff expression ]
| event_expression or event_expression
| event_expression , event_expression
8.10.1
Sequence events
A sequence instance can be used in
event expressions to control the execution of procedural statements based on
the successful completion of the sequence. This allows the endpoint of a named
sequence to trigger multiple actions in other processes. Syntax 17-2 describes
the syntax for declaring sequence instances and sequence expressions. A sequence
instance can be used directly in an event expression, as shown below.
When a sequence instance is specified
in an event expression, the process executing the event control shall block
until the given sequence reaches its end-point, that is, the sequence succeeds
non-vacuously. A sequence reaches its end point whenever there is a match for
the entire sequence expression. A process
resumes execution following the Observe region in which the end point is
detected.
An example of using a sequence as an
event control is shown below.
sequence abc;
@(posedge clk) a ##1
b ##1 c;
endsequence
program test;
initial
begin
@ abc $display( “Saw a–b-c” );
L1 : ...
end
endprogram
In the example above, when the named
sequence abc reaches its end point, the initial block in the program
block test is unblocked, which then displays the string “Saw a-b-c” and
continues execution with the statement labeled L1. In this case, the end of the
sequence acts as the trigger to unblock the event.
A sequence used in an event control is instantiated (as if by
an assert property statement); the event control is used to synchronize to the
end of the sequence, regardless of its start-time. Arguments to these sequences
shall be static; automatic variables used as sequence arguments shall result in
an error.
8.11 Level-sensitive sequence controls
The execution of procedural code can be
delayed until a sequence termination status is true. This is accomplished using
the level-sensitive wait statement
in conjunction with the built-in method that returns the current end status of
a named sequence: triggered.
The triggered sequence method evaluates to true if the given sequence
has reached its end point at that particular point in time (in the current
time-step), and false otherwise. The triggered status of a sequence is set
during the Observe region and persists through the remainder of the time-step
(i.e., until simulation time advances).
For example:
sequence abc;
@(posedge clk) a ##1
b ##1 c;
endsequence
sequence de;
@(negedge clk) d
##[2:5] e;
endsequence
program check;
initial
begin
wait( abc.triggered
|| de.triggered );
if( abc.triggered )
$display( “abc succeeded” );
if( de.triggered )
$display( “de succeeded” );
L2 : ...
end
endprogram
In the above example, the initial block
in program check waits for the end point (success) of either sequence abc or sequence de. When either condition evaluates to
true the wait statement unblocks the
process, which displays the sequences that caused the process to unblock and
then continues to execute the statement labeled L2.