An enumeration creates a strong variable type that is limited to a set of specified names such as the instruction opcodes or state machine values. Using these names, such as ADD, MOVE, or STATE, makes your code easier to write and maintain than using literals such as 8’h01.
The simplest enumerated type declaration contains a list of constant names and one or more variables. This creates an anonymous enumerated type.
Example 1:
A simple enumerated type
enum {RED, BLUE, GREEN} color;
You usually want to create a named enumerated type to easily declare multiple variables, especially if these are used as routine arguments or module ports. You first create the enumerated type, and then the variables of this type.
You can get the string representation of an enumerated variable with the function name().
Example 2: Enumerated Type
module enum_method; typedef enum {RED,BLUE,GREEN} colour; colour c; initial begin c = c.first(); $display(" %s ",c.name); c = c.next(); $display(" %s ",c.name); c = c.last(); $display(" %s ",c.name); c = c.prev(); $display(" %s ",c.name); end endmodule
Output :
RED
BLUE
GREEN
BLUE
Defining enumerated values
The actual values default to integers starting at 0 and then increase. You can choose your own enumerated values. The below line uses the default value of 0 for RED, then 2 for BLUE, and 3 for GREEN.
typedef enum {RED, BLUE=2, GREEN} color_e;
Enumerated constants, such as RED above, follow the same scoping rules as variables. Consequently, if you use the same name in several enumerated types (such as RED in different state machines), they have to be declared in different scopes such as modules, program blocks, routines, or classes.
Enumerated types are stored as int unless you specify otherwise. Be careful when assigning values to enumerated constants, as the default value of an int is 0. In Example 3 below, position is initialized to 0, which is not a legal ordinal_e variable. This behavior is not a tool bug – it is
how the language is specified. So always specify an enumerated constant with the value of 0, just to catch this error.
Example 3 Incorrectly specifying enumerated values
typedef enum {FIRST=1, SECOND, THIRD} ordinal_e; ordinal_e position;
Example 4 Correctly specifying enumerated values
typedef enum {ERR_O=0, FIRST=1, SECOND, THIRD} ordinal_e; ordinal_e position;
Enumerated methods : Methods associated with enumerated types
SystemVerilog also includes a set of specialized methods0 associated with enumerated types to enable iterating over the values of enumerated.
The first() method returns the value of the first member of the enumeration.
The last() method returns the value of the last member of the enumeration.
The next() method returns the Nth next enumeration value (default is the next one) starting from the current value of the given variable.
The prev() method returns the Nth previous enumeration value (default is the previous one) starting from the current value of the given variable.
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.
The functions next() and prev() wrap around when they reach the beginning or end of the enumeration.
Note that there is no easy way to write a for loop that steps through all members of an enumerated type if you use an enumerated loop variable. You get the starting member with first() and the next() member with next(). The problem is creating a comparison for the final iteration through the loop. If you use the test current!=current.last, the loop ends before using the last value. If you use current<=current.last, you get an infinite loop, as next never gives you a value that is greater than the final value. You can use a do...while loop to step through all the values.
The default type for an enumerated type is int (2-state). You can take the value of an enumerated variable and put it in an integer or int with a simple assignment. But SystemVerilog does not let you store a 4-state integer in an enum without explicitly changing the type. SystemVerilog requires you to explicitly cast the value to make you realize that you could be writing an out-of-bounds value.
Example 5: Assignments between integers and enumerated types
module enum_method; typedef enum {RED, BLUE, GREEN} COLOR_E; COLOR_E color, c2; integer c; initial begin c = color; // Convert from enum to integer c++; // Increment integer if (!$cast(color, c)) begin // Cast integer back to enum $display("Cast failed for c=%0d", c); end $display("Color is %0d & %0s", color, color.name); c2 = COLOR_E'(c); // No type checking done end endmodule
Output :
Color is 1 & BLUE
Run Simulation
In above Example 5, $cast tried to assign from the right value to the left. If the assignment succeeds, $cast returns 1. If the assignment fails because of an out-of-bounds value, no assignment is made and the function returns 0. If you use $cast as a task and the operation fails, SystemVerilog prints an error.
You can also cast the value using the type’(val) as shown above, but this does not do any type checking, so the result may be out of bounds. You should not use this style.
Previous : SystemVerilog Built-in Data Types
Next : SystemVerilog Constants
No comments:
Post a Comment
Please provide valuable comments and suggestions for our motivation. Feel free to write down any query if you have regarding this post.