## Why do we need enumeration ?

Many digital designs have finite state machines or signals to represent a particular state the design has reached. For example, a traffic light controller can change states from GREEN -> YELLOW -> RED.

A 2-bit state variable of type `reg` is typically used where 00, 01, 10 represents green, yellow and red respectively. Although this is quite sufficient to be implemented as hardware, it's not so convenient from a verification perspective.

If there is a need to debug the design, this state variable will only provide integral values and we have to match this value with the actual representation of the value for it to make sense.

## What is SystemVerilog enumeration ?

SystemVerilog solves this problem with the introduction of enumeration. An enumerated type defines a set of named values. In the following example, light is an enumerated variable that can store one of the three possible values. Internally these names are tied with integer values where the first name by default gets 0.

```
enum  {RED, YELLOW, GREEN} light1;                 // int type; RED = 0, YELLOW = 1, GREEN = 2
enum bit[1:0] {RED, YELLOW, GREEN} light2;         // bit type; RED = 0, YELLOW = 1, GREEN = 2
enum  {RED=3, YELLOW, GREEN} light3;               // RED = 3, YELLOW = 4, GREEN = 5
enum  {RED = 4, YELLOW = 9, GREEN} light4;         // RED = 4, YELLOW = 9, GREEN = 10 (automatically assigned)
enum  {RED = 2, YELLOW, GREEN = 3} light5;         // Error : YELLOW and GREEN are both assigned 3

enum bit[0:0] {RED, YELLOW, GREEN} light6;         // Error: minimum 2 bits are required
```

```
enum {1WAY, 2TIMES, SIXPACK=6} e_formula;     // Compilation error

enum {ONEWAY, TIMES2, SIXPACK=6} e_formula;   // Correct
```

## How to define a new enumerated data type ?

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

```
module tb;
// boolean is a new data-type with two valid values: NO and YES
typedef enum {NO, YES} boolean;

initial begin
// Declare a variable of type boolean that can store NO or YES

// Assign NO/YES to the enumerated variable

// Display string value of the variable
end
endmodule
```
Simulation Log
```ncsim> run
ncsim: *W,RNQUIE: Simulation is complete.
```

Click to try this example in a simulator!

## Enumerated type ranges

 name The next number will be associated with name name = C Associates the constant C to name name[N] Generates N named constants : name0, name1, ..., nameN-1 name[N] = C First named constant gets value C and subsequent ones are associated to consecutive values name[N:M] First named constant will be nameN and last named constant nameM, where N and M are integers name[N:M] = C First named constant, nameN will get C and subsequent ones are associated to consecutive values until nameM

### Example

In the following example, we'll try out each of the different styles shown in the table above.

```
module tb;
// name : The next number will be associated with name starting from 0
// GREEN = 0, YELLOW = 1, RED = 2, BLUE = 3
typedef enum {GREEN, YELLOW, RED, BLUE} color_set_1;

// name = C : Associates the constant C to name
// MAGENTA = 2, VIOLET = 7, PURPLE = 8, PINK = 9
typedef enum {MAGENTA=2, VIOLET=7, PURPLE, PINK} color_set_2;

// name[N] : Generates N named constants : name0, name1, ..., nameN-1
// BLACK0 = 0, BLACK1 = 1, BLACK2 = 2, BLACK3 = 3
typedef enum {BLACK[4]} color_set_3;

// name[N] = C : First named constant gets value C and subsequent ones
// are associated to consecutive values
// RED0 = 5, RED1 = 6, RED2 = 7
typedef enum {RED[3] = 5} color_set_4;

// name[N:M] : First named constant will be nameN and last named
// constant nameM, where N and M are integers
// YELLOW3 = 0, YELLOW4 = 1, YELLOW5 = 2
typedef enum {YELLOW[3:5]} color_set_5;

// name[N:M] = C : First named constant, nameN will get C and
// subsequent ones are associated to consecutive values until nameM
// WHITE3 = 4, WHITE4 = 5, WHITE5 = 6
typedef enum {WHITE[3:5] = 4} color_set_6;

initial begin
// Create new variables for each enumeration style
color_set_1 color1;
color_set_2 color2;
color_set_3 color3;
color_set_4 color4;
color_set_5 color5;
color_set_6 color6;

color1 = YELLOW; \$display ("color1 = %0d, name = %s", color1, color1.name());
color2 = PURPLE; \$display ("color2 = %0d, name = %s", color2, color2.name());
color3 = BLACK3; \$display ("color3 = %0d, name = %s", color3, color3.name());
color4 = RED1;   \$display ("color4 = %0d, name = %s", color4, color4.name());
color5 = YELLOW3;\$display ("color5 = %0d, name = %s", color5, color5.name());
color6 = WHITE4; \$display ("color6 = %0d, name = %s", color6, color6.name());

end
endmodule
```
Simulation Log
```ncsim> run
color1 = 1, name = YELLOW
color2 = 8, name = PURPLE
color3 = 3, name = BLACK3
color4 = 6, name = RED1
color5 = 0, name = YELLOW3
color6 = 5, name = WHITE4
ncsim: *W,RNQUIE: Simulation is complete.
```

Click to try this example in a simulator!

## Enumerated Type Methods

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

 first() function enum first(); Returns the value of the first member of the enumeration last() function enum last(); Returns the value of the last member of the enumeration next() function enum next (int unsigned N = 1); Returns the Nth next enumeration value starting from the current value of the given variable prev() function enum prev (int unsigned N = 1); Returns the Nth previous enumeration value starting from the current value of the given variable num() function int num(); Returns the number of elements in the given enumeration name() function string name(); Returns the string representation of the given enumeration value

### Enumeration Methods Example

```
// GREEN = 0, YELLOW = 1, RED = 2, BLUE = 3
typedef enum {GREEN, YELLOW, RED, BLUE} colors;

module tb;
initial begin
colors color;

// Assign current value of color to YELLOW
color = YELLOW;

\$display ("color.first() = %0d", color.first());  // First value is GREEN = 0
\$display ("color.last()  = %0d", color.last());  // Last value is BLUE = 3
\$display ("color.next()  = %0d", color.next());   // Next value is RED = 2
\$display ("color.prev()  = %0d", color.prev());   // Previous value is GREEN = 0
\$display ("color.num()   = %0d", color.num());   // Total number of enum = 4
\$display ("color.name()  = %s" , color.name());   // Name of the current enum
end
endmodule
```
Simulation Log
```ncsim> run
color.first() = 0
color.last()  = 3
color.next()  = 2
color.prev()  = 0
color.num()   = 4
color.name()  = YELLOW
ncsim: *W,RNQUIE: Simulation is complete.
```

Click to try this example in a simulator!

## Type Checking

Enumerated types are strongly typed and hence a variable of type enum cannot be assigned an integer value that lie outside the enumeration set unless an explicit cast is used.

```
typedef enum bit [1:0] {RED, YELLOW, GREEN} e_light;

module tb;
e_light light;

initial begin
light = GREEN;
\$display ("light = %s", light.name());

// Invalid because of strict typing rules
light = 0;
\$display ("light = %s", light.name());

// OK when explicitly cast
light = e_light'(1);
\$display ("light = %s", light.name());

// OK. light is auto-cast to integer
if (light == RED | light == 2)
\$display ("light is now %s", light.name());

end
endmodule
```
Simulation Log

Some simulators provide a compilation error for going against SystemVerilog strict typing rules, like Aldec Riviera Pr which may take a commandline argument to avoid these errors.

```ERROR VCP2694 "Assignment to enum variable from expression of different type." "testbench.sv" 11  1
FAILURE "Compile failure 1 Errors 0 Warnings  Analysis time: 0[s]."
```

Some other simulators simply provide a warning and allow simulation to run, like Cadence ncsim.

```  	light = 0;
|
ncvlog: *W,ENUMERR (testbench.sv,11|11): This assignment is a violation of SystemVerilog strong typing rules for enumeration datatypes.