Section 3.2

LRM-45 LRM-59 LRM-65 LRM-72 LRM-82 LRM-89

Change in Syntax 3-1 (change in red):

data_type data_type_common_item ::=

  integer_vector_type [ signing ] { packed_dimension } [ range ]

| integer_atom_type [ signing ]

| type_declaration_identifier type_identifier { packed_dimension }

| non_integer_type

| struct struct_union [ packed [ signing ]] { struct_union_member { struct_union_member } } { packed_dimension }16

| union packed [ signing ] { { struct_union_member } } { packed_dimension }

| struct [ signing ] { { struct_union_member } }

| union [ signing ] { { struct_union_member } }

| enum [ integer_type [ signing ] { packed_dimension } ]

{ enum_identifier [ = constant_expression ] { , enum_identifier [ = constant_expression ] } }

| enum [ enum_base_type ] { enum_name_declaration { , enum_name_declaration } }

| string

| event

| chandle

| class_scope_type_identifier

| virtual [interface] interface_identifier

 

data_type ::=

                  data_type_common_item

| event

| class_scope_type_identifier

| covergroup_identifier

LRM-59 LRM-69

Change in Syntax 3-1 (change in red):

class_scope_type_identifier::=

                class_scope [ :: type_identifier ]

class_identifier :: { class_identifier :: } type_declaration_identifier

| class_identifier :: { class_identifier :: } class_identifier

 

            class_scope ::=

                                class_identifier [ parameter_value_assignment ]

                                { :: class_identifier [ parameter_value_assignment ] }

LRM-59 LRM-61 LRM-65 LRM-97 LRM-100

Change in Syntax 3-1 (change in red):

struct_union_member ::= { attribute_instance } variable_declaration ;

            struct_union_member ::=

{ attribute_instance } data_type { packed_dimension }

variable_identifier  variable_dimension { , variable_identifier variable_dimension } ;

 

struct_union ::= struct | union

 

variable_decl_assignment ::=

  variable_identifier variable_dimension [ = constant_expression expression ]

| variable_identifier [ ] = new [ constant_expression expression ] [ ( variable_identifier ) ]

| class_variable_identifier [ parameter_value_assignment ] = new [ ( list_of_arguments ) ]

| [ covergroup_variable_identifier ] = new [ ( list_of_arguments ) ]19

Section 3.9

LRM-89

Change Syntax 3-2 (change in red):

type_declaration ::=

  typedef [ data_type ] type_declaration_identifier ;

| typedef hierarchical_identifier . type_identifier type_declaration_identifier ;

| typedef [ class ] class_identifier ;

| typedef class_identifier [ parameter_value_assignment ] type_declaration_identifier ;

  typedef data_type type_identifier variable_dimension ;

| typedef interface_instance_identifier . type_identifier type_identifer ;

| typedef [ enum | struct | union | class ] type_identifier ;

LRM-75

Change (change in red):

If the type is defined within an interface, it must be re-defined locally before being used.

 

interface it;

typedef int intP;

endinterface

 

it it1 ();

typedef it1.intP intP;

 

User defined type identifiers have the same scoping rules as data identifiers, except that hierarchical reference to type identifiers shall not be allowed. References to type identifiers defined within an interfaces through ports are allowed provided they are locally re-defined before being used.

 

interface intf_i;

typedef int data_t;

endinterface

 

module sub(intf_i_i p)

typedef p.data_t my_data_t;

my_data_t data;      //type of 'data'' will be int when connected to interface above

endmodule

LRM-94

Change (change in red):

User-defined type names must be used for complex data types in casting (see Section 3.14, below), which only allows simple type names, and as parameters type parameter values when unpacked array types are used.

Section 3.10

LRM-45 LRM-72

Change in Syntax 3-3 (change in red):

data_type data_type_common_item ::=

...

| enum [ integer_type [ signing ] { packed_dimension } ]

   { enum_identifier [ = constant_expression ] { , enum_identifier [ = constant_expression ] } }

| enum [ enum_base_type ] { enum_name_declaration { , enum_name_declaration } }

LRM-88

Changes (change in red):

// Correct: IDLE=2’b00, XX=2’bx, S1=2’b01, S2=2’b10

enum integer {IDLE, XX=’x, S1=2’b01, S2=2’b10} state, next;

LRM-80

Changes (change in red):

The values can be set for some of the names and not set for other names. The optional value of an enum label is an elaboration time constant expression (see Section 5.3) and can include references to parameters, local parameters, genvars, other enum labels, and constant functions of these. Hierarchical names and const variables are not allowed. A name without a value is automatically assigned an increment of the value of the previous name.

LRM-88

Changes (change in red):

A sized constant can be used to set the size of the type. All sizes must be the same.

 

// silver=4’h4, gold=4’h5 (all are 4 bits wide)

enum {bronze=4’h3, silver, gold} medal4;

 

// Syntax error: the width of the enum has been exceeded

// in both of these examples

enum {a=1'b0, b, c} alphabet;

enum [0:0] {a,b,c} alphabet;

 

Any enumeration encoding value that is outside the representable range of the enum shall be an error.

 

Adding a constant range to the enum declaration can be used to set the size of the type. If any of the enum members are defined with a different sized constant, this shall be a syntax error. Any enumeration encoding value that is outside the representable range of the enum shall be an error. If any of the enum members are defined with a different sized constant, this shall be a syntax error.

 

// Error in the bronze and gold member declarations

enum bit [3:0] {bronze=5’h13, silver, gold=3’h5} medal4;

 

// Correct declaration - bronze and gold sizes are redundant

enum bit [3:0] {bronze=4’h13, silver, gold=4’h5} medal4;

 

// Correct declaration - bronze and gold are unsized

enum bit [3:0] {bronze=’h3, silver, gold=’h5} medal4;

 

// Correct declaration - bronze and gold sizes are redundant

enum bit [3:0] {bronze=4’h3, silver, gold=4’h5} medal4;

 

// Error in the bronze and gold member declarations

enum [3:0] {bronze=5’h13, silver, gold=3’h5} medal4;

 

// Error in c declaration, requires at least 2 bits

enum [0:0] {a,b,c} alphabet;

 

Type checking of enumerated types used in assignments, as arguments and with operators is covered in Section 3.10.3. Like C, there is no overloading of literals, so medal and medal4 cannot be defined in the same scope, since they contain the same names.

Section 3.10.2

LRM-82

Changes in Table 3-3 (change in red):

 

name

Associates the next consecutive number with name.

name = N C

Assigns Associates the constant N C to name

name[N]

Generates N labels in the sequence: name0, name1, ..., nameN-1N. must be an integral constant

Each generated label is associated the next consecutive number.

name[N] = C

Optionally, a constant can be assigned to the generated names labels to associate that constant to the first generated label; subsequent generated labels are associated consecutive values.

N must be an integral literal constant.

name[N:M]

Creates a sequence of names labels starting with nameN and incrementing or decrementing until reaching name label nameM.

name[N:M] = C

Optionally, a constant can be assigned to the generated labels to associate that constant to the first generated label; subsequent generated labels are associated consecutive values.

N and M must be integral literal constants.

 

LRM-82

Changes (change in red):

For example:

 

typedef enum { add=10, sub[5], jmp[6:8] } E1;

 

This example defines the enumerated type E1, which assigns the number 10 to the enumerated type label add. It also creates the enumerated types labels sub0,sub1,sub2,sub3,and sub4, and assigns them the values 11..15, respectively. Finally, the example creates the enumerated types labels jmp6,jmp7, and jmp8, and assigns them the values 16-18, respectively.

 

enum { register[1] = 1, register[2:4] = 10 } vr;

 

The example above declares enumerated variable vr, which creates the enumerated labels register0 and register1, which are assigned the values 1 and 2, respectively. Next, it creates the enumerated labels register2, register3, and register4, and assigns them the values 10, 11, and 12.

Section 3.11

LRM-45 LRM-59

Change in Syntax 3-4 (change in red):

data_type data_type_common_item::=

...

| struct struct_union [ packed [ signing ]] { struct_union_member { struct_union_member } } { packed_dimension }16

| union packed [ signing ] { { struct_union_member } } { packed_dimension }

| struct [ signing ] { { struct_union_member } }

| union [ signing ] { { struct_union_member } }

 

struct_union_member ::= { attribute_instance } variable_declaration ;

            struct_union_member ::=

{ attribute_instance } data_type { packed_dimension }

variable_identifier  variable_dimension { , variable_identifier variable_dimension } ;

 

struct_union ::= struct | union

LRM-78

Change (change in red):

Note that writing one member and reading another is independent of the byte ordering of the machine, unlike a normal union of normal structures, which are C-compatible and have members in ascending address order.

 

The signing of unpacked structures is not allowed.  The following declaration would be considered illegal:

 

typedef struct signed {

int f1 ;

logic f2 ;

} sIllegalSignedUnpackedStructType;             // illegal declaration

Section 3.12

LRM-48

Change (change in red):

 

A class is a collection of data and a set of subroutines that operate on that data. The data in a class is referred to as class properties, and its subroutines are called methods. The class properties and methods, taken together, define the contents and capabilities of a class instance or object.

LRM-46

Change (change in red):

 

The object-oriented class extension allows objects to be created and destroyed dynamically. Class instances, or objects, can be passed around via object handles, which add a safe-pointer capability to the language. An object can be declared as an argument of type with direction input, output, inout, or, or ref. In each case, the argument copied is the object handle, not the contents of the object.

Section 3.13

LRM-103

Change (change in red):

3.13 Singular type and Aggregate types

A singular type includes packed arrays (and structures) and all other data types except unpacked structures, unpacked arrays, and chandles.

 

Data types are categorized as either singular or aggregate. A singular type shall be any data type except an unpacked structure, union, or array (See section 4 Arrays). An aggregate type shall be any unpacked structure, union, or array data type. A singular variable or expression represents a single value, symbols, or handle. Aggregate expressions and variables represent a set or collection of singular values. Integral types are always singular even though they may be sliced into multiple singular values.

 

These categories are defined so that operators and functions may simply refer to these data types as a collective group. For example, some functions recursively descend into an aggregate variable until reaching a singular value, and then perform an operation on each singular value.

 

Note that although a class is a type, there are no variables or expressions of class type directly, only class object handles which are singular. So classes need not be categorized in this manner (See section 11 Classes).

Section 3.14

LRM-76

Change in Syntax 3-6 (change in red):

 

casting_type ::= simple_type | number size | signing                     // from Annex A.2.2.1

LRM-109

Change (change in red):

Structures can be converted to bits preserving the bit pattern, which means they can be converted back to the same value without any loss of information. When unpacked data is converted to the packed representation, the order of the data in the packed representation is such that the first field in the structure occupies the most significant bits. The effect is the same as a concatenation of the data items (struct fields or array elements) in order. The type of the elements in an unpacked structure or array must be valid for a packed representation in order to be cast to any other type, whether packed or unpacked.

 

An explicit cast between packed types is not required since they are treated as integral values, but a cast can be used by tools to perform stronger type checking.

 

The following example demonstrates how this conversion. In the example, the $bits attribute gives is used to obtain the size of a structure in bits (the $bits system function is discussed in Section 22.2), which facilitates conversion of the structure into a packed array:.

Section 3.16

LRM-109

Change (change in red):

3.16 Bit-stream casting

 

Type casting may also be applied to unpacked arrays and structs. It is thus possible to convert freely between bit-stream types using explicit casts. Types that can be packed into a stream of bits are called bit-stream types. A bit-stream type is a type consisting of the following:

 

¾      Any integral, packed, or string type

¾      Unpacked arrays, structures, or classes of the above types

¾      Dynamically-sized arrays (dynamic, associative, or queues) of any of the above types

 

This definition is recursive, so that for example a structure containing a queue of int is a bit-stream type.

 

Assuming A is of bit-stream type source_t and B is of bit-stream type dest_t, it is legal to convert A into B by an explicit cast:

 

B = dest_t'(A); 

 

The conversion from A of type source_t to B of type dest_t  proceeds in two steps:

 

1.            Conversion from source_t to a generic packed value containing the same number of bits as source_t.

¾      If source_t contains any 4-state data, the entire packed value is 4-state; otherwise, it is 2-state.

 

2.        Conversion from the generic packed value to dest_t.

¾      If the generic packed value is a 4-state type and parts of dest_t designate 2-state types then those parts in dest_t are assigned as if cast to a 2-state.

 

When a dynamic array, queue, or string is converted to the packed representation, the item at index 0 occupies the most significant bits. When an associative array is converted to the packed representation, items are packed in index-sorted order with the first indexed element occupying the most significant bits.

 

Both source_t and dest_t can include one or more dynamically sized data in any position (for example, a structure containing a dynamic array followed by a queue of bytes). If the source type, source_t, includes dynamically-sized variables, they are all included in the bit-stream.  If the destination type, dest_t, includes unbounded dynamically-sized types, the conversion process is greedy: compute the size of the source_t, subtract the size of the fixed-size data items in the destination, and then adjust the size of the first dynamically sized item in the destination to the remaining size; any remaining dynamically-sized items are left empty.

 

For the purposes of a bit-stream cast, a string is considered a dynamic array of bytes.

 

Regardless of whether the destination type contains only fixed-size items or dynamically-sized items, data is extracted into the destination in left-to-right order. It is thus legal to fill a dynamically-sized item with data extracted from the middle of the packed representation.

 

If both source_t and dest_t are fixed sized unpacked types of different sizes then a cast generates a compile-time error. If source_t or dest_t contain dynamically-sized types then a difference in their sizes will generate an error either at compile time or run time, as soon as it is possible to determine the size mismatch. For example:

 

// Illegal conversion from 24-bit struct to int (32 bits) - compile time error

struct {bit[7:0] a; shortint b;} a;

int b = int'(a);

 

// Illegal conversion from 20-bit struct to int (32 bits) - run time error

struct {bit a[$]; shortint b;} a = {{1,2,3,4}, 67};

int b = int'(a);

 

// Illegal conversion from int (32 bits) to struct dest_t (25 or 33 bits) - compile time error

typedef struct {byte a[$]; bit b;} dest_t;

int a;

dest_t b = dest_t'(a);

 

Bit-stream casting can be used to convert between different aggregate types, such as two structure types, or a structure and an array or queue type. This conversion can be useful to model packet data transmission over serial communication streams. For example, the code below uses bit-stream casting to model a control packet transfer over a data stream:

 

typedef struct {

shortint address;

reg [3:0] code;

byte command [2];

} Control;

 

typedef bit Bits [36:1];

 

Control p;

Bits stream[$];

 

p = ...                                      // initialize control packet

stream = {stream, Bits(p)}                  // append packet to unpacked queue of bits

 

Control q;

q = Control’(stream[0]);                     // convert stream back to a Control packet

stream = stream[1:$];                        // remove packet from stream

 

The following example uses bit-stream casting to model a data packet transfer over a byte stream:

 

typedef struct {

byte length;

shortint address;

byte payload[];

byte chksum;

} Packet;

 

The above type defines a generic data packet in which the size of the payload field is stored in the length field.  Below is a function that randomly initializes the packet and computes the checksum.

 

function Packet genPkt();

Packet  p;

 

void’( randomize( p.address, p.length, p.payload )

with { p.length > 1 && p.payload.size == p.length } );

p.chksum = p.payload.xor();

return p;

endfunction

 

The byte stream is modeled using a queue, and a bit-stream cast is used to send the packet over the stream.

 

typedef byte channel_type[$];

channel_type channel;

channel = {channel, channel_type'(genPkt())};

 

And the code to receive the packet:

 

Packet p;

int    size;

 

size = channel[0] + 4;

p = Packet’( channel[0 : size - 1] );        // convert stream to Packet

channel = channel[ size, $ ];                // remove packet data from stream