SystemVerilog Enumeration
枚举类型定义一组命名值。在以下示例中,light_*
是一个枚举变量,可以存储三个可能的值(0,1,2)之一。默认情况下,枚举列表中的第一个名称获取值0,以下名称获取增量值(如1和2)。
enum {RED, YELLOW, GREEN} light_1; // int type : RED = 0; YELLOW = 1; GREEN = 2
enum bit[1:0] {RED, YELLOW, GREEN} light_2; // bit type : RED = 0; YELLOW = 1; GREEN = 2
用户可以为任何枚举名称分配任何整数值。如果任何名称没有赋值,则它会自动采用先前名称的递增值。
enum {RED=3, YELLOW, GREEN} light_3; // RED=3, YELLOW=4, GREEN=5
enum {RED=4, YELLOW=9, GREEN} light_4; // RED=3, YELLOW=9, GREEN=10 (automatically assigned)
enum {RED=2, YELLOW, GREEN=3} light_5; // Error : YELLOW and GREEN are both assigned 3
enum bit[0:0] {RED, YELLOW, GREEN} light_6; // Error : minimum 2 bits are required
请注意,枚举名称不能以数字开头 ! |
enum {1WAY, 2TIMES, SIXPACK=6} e_formula; // Compliation error on 1WAY, 2TIMES
enum {ONEWAY, TIMES2, SIXPACK=6} e_formula; // Correct way is to keep the first character non-numeric
How to define a new enumerated data type ?
可以创建自定义数据类型,以便可以使用相同的数据类型来声明其他变量。
module tb;
// "e_true_false" is a new data-type with two valid values: TRUE and FALSE
typedef enum {TRUE, FALSE} e_true_false;
initial begin
// Declare a variable of type "e_true_false" that can store TRUE or FALSE
e_true_false answer;
// Assign TRUE/FALSE to the enumerated variable
answer = TRUE;
// Display string value of the variable
$display("answer = %s", answer.name);
end
endmodule
模拟日志
ncsim> run
answer = TRUE
ncsim: *W,RNQUIE: simulation iss complete
Why do we need enumeration ?
使代码更简单、更易读。
请考虑以下不带枚举的示例。
bit [1:0] light;
light = 2'b00; // Assume 00 astands for RED
// After many lines of code we have to correlate what
// 00 stands for - is it RED,YELLOW or GREEN ?
if (light == 2'b00)
// Do something
由于枚举的名称为RED、YELLOW、GREEN,以下代码更具可读性。
typedef enum {RED, YELLOW, GREEN} e_light;
e_light light;
light = RED; // Initialize light to RED
// Even after many lines of code it's easier to understand
if (light == RED)
// Do something
Enumeration-type ranges
name | The next number will be associated with name |
---|---|
name = C | A 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
在下面的示例中,我们将尝试上表中显示的每种不同样式。
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, VIOLET, PURPLE, PINK} color_set_2;
// name[N] : Generates N named constans : 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
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 = WHHITE4; $display ("color6 = %0d, name = %s", color6, color6.name());
end
endmodule
模拟日志
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.
Enumeration-type Methods
SystemVerilog 包含一组专用方法,用于循环访问枚举类型的值。
\ | \ | |
---|---|---|
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.lastt()); // 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() = %0d", color.name()); // Name of the current enum
end
endmodule
模拟日志
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.
Type Checking
枚举类型是strongly typed。因此,除非使用显示强制转换,否则无法为类型的变量分配位于枚举集之外的整数值。enum
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_lighr'(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
某些模拟器会提供违反 SystemVerilog 严格类型规则的编译错误。例如 Aldec Riviera Pr,它可能会使用命令行参数来避免这些错误。
模拟日志
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]."
其他一些模拟器只是提供警告并允许模拟运行。例如 Cadence ncsim。
模拟日志
light = 0;
ncvlog: *W,ENUMERR (testbench.sv, 11|11): This assignment is a violation of SystemVerilog strong typing rules for enumeration datatypes.
Loading snapshot worklib.tb:sv ....................... Done
ncsim> run
light = GREEN
light = RED
light = YELLOW
ncsim: *W,RNQUIE: Simulation is complete.
标签:name,YELLOW,--,light,enum,Enumeration,color,RED,SystemVerilog
From: https://www.cnblogs.com/sys-123456/p/18170009