自定义、枚举、结构体类型

时间:2022-07-22
本文章向大家介绍自定义、枚举、结构体类型,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

01

自定义类型

通过用户自定义类型,简化了verilog代码量并实现更多功能;用户自定义类型使得代码的可读性更强;

  • 通过typedef来创建用户自定义类型;
  • 通过enmu来创建枚举类型;
  • 通过struct来创建结构体类型;

SV提供自定义类型可以帮助用户构建更高抽象层的数据类型;

同C语言一样,用户可以利用已有的数据类型定义新的数据类型,一旦定义了新的数据类型,就可以利用该类型声明变量。

typedef int unsigned unit;//定义新类型unit
unit a,b;//unit自定义类型unit声明的2个变量

注意:为了代码可读性,通常添加“_t”后缀表示它是一个自定义类型(type),而不是变量。

在某些时候,自定义一个新的数据类型也是必须的,因为在SystemVerilog中要通过数据类型的标识符才可以做类型转换,如代码所示。

用户自定义类型实例

module test_ typedef( );
typedef enum (red, green, blue, yellow, white, black)  colors ;
 colors  my_colors;
 initial begin
    $display("my_ color's default vaule is %s",my_colors );
    my_colors = green;
   //my_ colors=1;   //错误使用方法,需要做数据类型转换
    my_ co1ors=colors'(2);   //通过colors数据类型标识符做类型转换
    $disp1ay( "my_co1or is % s" ,my_colors.name);
 end
endmodule

02

枚举类型

枚举类型(enum)可以描述变量的合法值范围,其每一个值都需要提供一个用户自定义的名字;

如枚举类型 IC可以拥有ICer1,ICer2,ICer3.....ICerN数值,即enum{ICer1,ICer2,ICer3.....ICerN} IC;

Verilog语言不支持枚举类型,因此为了提供类似于枚举类型设计方式,我们不得不采用参数来表示可取值的范围,或者使用来定义各个合法值的宏名称。

定义枚举值

默认的枚举类型是int,即32位的二值逻辑数据类型;

为了更准确的描述变量,SV允许指明其数据类型,例如:

enum bit {TRUE,FALSE} Boolean;
enum logic [1:0] {WAITE,LOAD,READY} state;

自定义枚举类型

如果枚举类型变量被赋值,那么所赋的值应在其数值范围。

enum logic {2:0] {WAITE=3’b001,LOAD=3’b010,READY=3’b100} state;

如果枚举变量是四值逻辑,那么将其值赋为X或者Z也是合法;

enum logic {ON=1’b1,OFF=1’b z}  out;

如果枚举类型并没有伴随着typedef,那么该枚举类型指的是匿名枚举类型;此时变量名应伴随其后;

将typedef与enum合并,可以将匿名枚举类型声明为自定义类型,这就使得可以用同一个枚举类型来声明多个变量或者线网;

typedef enum {WAITE,LOAD,READY} states_t;
States_t state,next_state;

verilog或者SV可以在不同的数据类型之间通过隐性转换,进行直接赋值,因此verilog/SV的数据类型转换是宽松的;

枚举类型赋值

枚举类型赋值时则相对严格,例如下面的例子中,赋值操作符“=”的左右两侧应该尽量为相同的枚举类型。

typedef enum {WAITE, LOAD, READY} states_t;
states_t  state, next_State ;
int foo;
state = next_state; //合法操作
foo=state+1;//合法操作
state=foo+1;//非法赋值
state = states_t' (foo + 1) ;//合法赋值
state = state + 1; //非法赋值
state= states_t' (state + 1) //合法赋值
state++;     // 非法赋值
next_state += state;   //非法赋值

SystemVerilog为枚举类型提供了如下内置方法来方便操作:

  • function enum first ():返回枚举类型中第一个成员的值。
  • function enum last ():返回枚举类型中最后一个成员的值。
  • function enum next ( int unsigned N=1):以当前成员为起点,返回后续第N个成员的值,默认是下一个成员的值;若起点为最后一个成员,则默认返回第一个成员的值。
  • function enum prev ( int unsigned N=1):以当前成员为起点,返回前面第N个成员的值,默认是前面一个成员;若起点为第一个成员,则默认返回最后一个成员的值。
  • function int num ():返回该枚举类型的成员数目。
  • function string name ():以字符串的形式返回该成员名字。

03

结构体类型

SV添加了和C一样的结构体struct,而结构体成员可以是任何变量类型,包括自定义类型或者其他常量类型;

struct{
int a,b;//32位变量
opcode_t  opcode;//用户自定义类型
logic [23:0] address;//24位变量
bit error;//1位变量
}Instruction_Word;//变量名

结构体类型的变量可以用来索引到其内部的变量,索引方式同C一样。

<structure_name>.<variable_name>
Instruction_Word.address=32’hF000001E;

结构体类型默认也是变量类型,用户可以显式声明为var或者wire类型;

类似与枚举类型,结构体类型也可以伴随着typedef来实现自定义结构体类型;

typedef struct {  //自定义结构体
  logic [31:0] a,b;
  logic [7:0] opcode;
  logic [23:0] address;
}instruction_word_t  IW;// 结构体变量声明

结构体变量可以通过索引其各个成员做依次的成员赋值:

always @(posedge clk or negedge rst_n)begin
     if(!rst_n)begin
            IW.a=100;//结构体成员
            IW.b=5;
            IW.address=0;
      end
      else begin
  ......
      end
end

也可以通过分号’ 和花括号{}来实现整体赋初值;

IW=’ {100,3,8’hFF,0};
IW=’ {addres:0,opcode:8’hFF,a:100,n:5};   //成员和数值通过冒号:一一对应。

END