Section 8.2

LRM-39 LRM-41LRM-66 LRM-73

Changes to Syntax 8-1 (change in red):

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

Section 8.3

LRM-59

Changes to Syntax 8-2 (change in red):

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

LRM-100

Changes (change in red):

SystemVerilog also allows a time unit to be specified in the assignment statement, as follows:

Section 8.4

LRM-81

Changes to Syntax 8-3 (change in red):

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 ]

LRM-81

Changes (change in red):

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.

Section 8.5

LRM-44 LRM-100

Changes to Syntax 8-4 (change in red):

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

LRM-44

Changes to Syntax 8-4 (change in red):

 

Verilog provides for, while, repeat and forever loops. SystemVerilog enhances the Verilog for loop, and adds a do...while loop and a foreach loop.

Section 8.5.3 (New)

LRM-44

Changes (change in red):

 

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. Loop variables are automatic, read-only, and their scope is local to the loop. The type of each loop variable is implicitly declared to be consistent with the type of array index. It shall be an error for any loop variable to have the same identifier as the array.

 

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.

Section 8.10

LRM-73

Changes in Syntax 8-8 (change in red):

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

Section 8.10.1 (New)

LRM-73

Add (change in red):

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.

Section 8.11 (New)

LRM-73

Add following new section and renumber succeeding (change in red):

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.