Enumerations

Jan. 6, 2024 || Item:1.5.Enumerations

An enumerated type declares a set of integral named constants. The default data type shall be int. Any other data type shall require an explicit data type declaration.

In the following example, color1 and color2 are enum variables which can get one of three values: red, yellow and greenIn default, the first element in enum list has a value of 0, and subsequent elements increase by 1 unit.

enum {red, yellow, green} color1, color2; // anonymous int type: red=0, yellow=1, green=2

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: IDLE=2’b00, XX=2’bx <ERROR>, S1=2’b01, S2=2’b10

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. A name without a value is automatically assigned an increment of the value of the previous name.

// c is automatically assigned the increment-value of 8

enum {a=3, b=7, c} alphabet;

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

// Syntax error: c and d are both assigned 8

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

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

// a=0, b=7, c=8

enum {a, b=7, c} alphabet;

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.

// 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 bit [3:0] {bronze=5'h13, silver, gold=3'h5} medal4;

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

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

Type checking of enumerated types used in assignments.

 

1. 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

 

2. Enumerated type ranges

A range of enumeration elements can be specified automatically, via the following syntax:

Table 1-2: Enumeration element range

Table 1-2

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 named constant add. It also creates the enumerated named constants sub0,sub1,sub2,sub3,and sub4, and assigns them the values 11...15, respectively. Finally, the example creates the enumerated named constants jmp6,jmp7, and jmp8, and assigns them the values 16-18, respectively.

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

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

 

3. Type checking

A variable of type enum cannot be directly assigned a value that lies outside the enumeration set unless an explicit cast is used, or unless the enum variable is a member of a union. This restriction only applies to an enumeration that is explicitly declared as a type.

The enumeration values can still be used as constants in expressions, and the results can be assigned to any variable of a compatible integral type.

Both the enumeration names and their integer values must be unique. The values can be set to any integral constant value, or auto-incremented from an initial value of 0. It is an error to set two values to the same name, or to set a value to the same auto-incremented value.

Enumerated variables are auto-cast into integral values, but, assignment of arbitrary expressions to an enumerated variable requires an explicit cast.

For example:

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

This operation assigns a unique number to each of the color identifiers, and creates the new data type Colors.

This type can then be used to create variables of that type.

Colors c;

c = green;

c = 1; // Invalid assignment

if ( 1 == c ) // OK. c is auto-cast to integer

In the example above, the value green is assigned to the variable c of type Colors. The second assignment is invalid because of the strict typing rules enforced by enumerated types.

Casting can be used to perform an assignment of a different data type, or an out of range value, to an enumerated type. 

The result of any operation on an enumeration variable after the variable has been assigned an out of range value shall be undefined.

 

4. 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 the 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.

4.1. first()

The prototype for the first() method is:

function enum first();

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

4.2. last()

The prototype for the last() method is:

function enum last();

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

4.3. 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.

4.4. 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.

4.5. num()

The prototype for the num() method is:

function int num();

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

4.6. 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.

4.7. Using enumerated type methods

The following code fragment shows how to display the name and value of all the members of an enumeration.

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

Colors c = c.first;

forever begin

$display( "%s : %d\n", c.name, c );

if( c == c.last ) break;

c = c.next;

end



Comments:

Leave a comment: