Title

SystemVerilog -- 2.4 Data Types ~ SystemVerilog Enumeration

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.

posted on 2024-05-02 16:52  松—松  阅读(124)  评论(0编辑  收藏  举报

导航