Enumerations

An enumerated type declares a set of integral named constants. Enumerated data types provide the capability to abstractly declare strongly typed variables without either a data type or data value(s) and later add the required data type and value(s) for designs that require more definition. Enumerated data types also can be easily referenced or displayed using the enumerated names as opposed to the enumerated values.

In the absence of a data type declaration, the default data type shall be int. Any other data type used with enumerated types shall require an explicit data type declaration.

An enumerated type defines a set of named values. In the following example, color1 and color2 are defined to be variables of the anonymous (unnamed) enumerated int type that includes the three members: red, yellow and green.

enum {red, yellow, green} color1, color2; // anonymous int type

An enumerated name with x or z assignments assigned to an enum with no explicit data type or an explicit 2-state declaration shall be a syntax error.

// Syntax error: XX=2’bx in below example

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

An enum declaration of a 4-state type, such as integer, that includes one or more names with x or z assignments shall be permitted.

// Correct: IDLE=0, XX=’x, S1=1, S2=2

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

An unassigned enumerated name that follows an enum name with x or z assignments shall be a syntax error.

// Syntax error: IDLE=2’b00, XX=2’bx, S1=??, S2=??

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

The values can be cast to integer types, and increment from an initial value of 0. This can be overridden.

enum {bronze=3, silver, gold} medal; // silver=4, gold=5

The values can be set for some of the names and not set for other names. The optional value of an enum named constant is an elaboration time constant expression and can include references to parameters, local parameters, genvars, other enum named constants, 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.

enum {a=3, b=7, c} alphabet; // c is automatically assigned the increment-value of 8

If an automatically incremented value is assigned elsewhere in the same enumeration, this shall be a syntax error.

enum {a=0, b=7, c, d=8} alphabet; // Syntax error: c and d are both assigned 8

If the first name is not assigned a value, it is given the initial value of 0.

enum {a, b=7, c} alphabet; // a=0, b=7, c=8

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.

enum bit [3:0] {bronze='h3, silver, gold='h5} medal; // Correct declaration – bronze and gold are unsized

enum bit [3:0] {bronze=4'h3, silver, gold=4'h5} medal; // Correct declaration – bronze and gold sizes are redundant

enum bit [3:0] {bronze=5'h13, silver, gold=3'h5} medal; // Error in the bronze and gold member declarations

Defining new data types as enumerated types

A type name can be given so that the same type can be used in many places.

typedef enum {NO, YES} boolean;

boolean myvar; // named type

Enumerated types in numerical expressions

Elements of enumerated type variables can be used in numerical expressions. The value used in the expression is the numerical value associated with the enumerated value. For example:

typedef enum { red, green, blue, yellow, white, black } Colors;

Colors col;

integer a, b;

a = blue * 3;

col = yellow;

b = col + green;

From the previous declaration, blue has the numerical value 2. This example assigns a value of 6 (2*3), and it assigns b a value of 4 (3+1). An enum variable or identifier used as part of an expression is automatically cast to the base type of the enum declaration (either explicitly or using int as the default). An assignment to an enum variable from an expression other than the same type shall require a cast. Casting to an enum type shall cause a conversion of the expression to its base type without checking the validity of the value.

typedef enum {Red, Green, Blue} Colors;

typedef enum {Mo,Tu,We,Th,Fr,Sa,Su} Week;

Colors C;

Week W;

int I;

C = Colors’(C+1);               // C is converted to an integer, then added to one, then converted back to a Colors type

C = C + 1; C++; C+=2; C = I; // Illegal because they would all be assignments of expressions without a cast

C = Colors’(Su);                // Legal; puts an out of range value into C

I = C + W;                       // Legal; C and W are automatically cast to int

SystemVerilog includes a set of specialized methods to enable iterating over the values of enumerated types.

first() :

The prototype for the first() method is:

function enum first();

The first() method returns the value of the first member of the enumeration.

last() :

The prototype for the last() method is:

function enum last();

The last() method returns the value of the last member of the enumeration.

next() :

The prototype for the next() method is:

function enum next( int unsigned N = 1 );

The next() method returns the Nth next enumeration value (default is the next one) starting from the current value of the given variable. A wrap to the start of the enumeration occurs when the end of the enumeration is reached. If the given value is not a member of the enumeration, the next() method returns the first member.

prev() :

The prototype for the prev() method is:

function enum prev( int unsigned N = 1 );

The prev() method returns the Nth previous enumeration value (default is the previous one) starting from the current value of the given variable. A wrap to the end of the enumeration occurs when the start of the enumeration is reached. If the given value is not a member of the enumeration, the prev() method returns the last member.

num() :

The prototype for the num() method is:

function int num();

The num() method returns the number of elements in the given enumeration.

name() :

The prototype for the name() method is:

function string name();

The name() method returns the string representation of the given enumeration value. If the given value is not a member of the enumeration, the name() method returns the empty string.

<< Previous | Next >>

User-defined types

type_declaration ::=

typedef data_type type_identifier variable_dimension ;

| typedef interface_instance_identifier . type_identifier type_identifer ;

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

The user can define a new type using typedef.

typedef int Myint;

This can then be instantiated as:

Myint a, b;

A type can be used before it is defined, provided it is first identified as a type by an empty typedef:

typedef Mytype;
Mytype M = 1;
typedef int Mytype;

Note that this does not apply to enumeration values, which must be defined before they are used.

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 interface 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 p)
typedef p.data_t my_data_t;
my_data_t data;  // type of ’data’ will be int when connected to interface above
endmodule

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 type parameter values when unpacked array types are used. Sometimes a user-defined type needs to be declared before the contents of the type has been defined. This is of use with user-defined types derived from enum, struct, union, and class.

For examples :

typedef enum type_declaration_identifier;
typedef struct type_declaration_identifier;
typedef union type_declaration_identifier;
typedef class type_declaration_identifier;
typedef type_declaration_identifier;

Note that, while this is useful for coupled definitions of classes, it cannot be used for coupled definitions of structures, since structures are statically declared and there is no support for pointers to structures.

The last form shows that the type of the user-defined type does not have to be defined in the forward declaration.

A typedef inside a generate shall not define the actual type of a forward definition that exists outside the
scope of the forward definition.

<< Previous | Next >>