#systemverilog# 关键字之 enum (枚举数据类型)

试想一下:想给数值一个label时,有没有好的方法呢 ?

一  基本知识

Verilog/SV会采取不同的方法。

用parameter/`define来定义一组常数或者宏名。

`define FETCH 3'h7 //宏定义
module controller (output reg read...);
  parameter LOAD = 0;      //常数定义
  always @(State) begin
    if(State == LOAD && instruction == `FETCH)    //使用label
    ...
  end
endmodule

今天,我们介绍另外一种方法,成为 枚举类型 enum 。

package chip_types;
 
  typedef enum {
                FETCH, 
                WRITE, 
                ADD, 
                SUB,
                MULT, 
                DIV, 
                SHIFT, 
                NOP 
  } instr_t;
 
  //用户自定义枚举类型instr_t
 
endpackage
 
import chip_types::*; //import包定义到$unit编译单元域
 
module controller (input instr_t instruction,...); //input instr_t类型instruction
 
  enum { WAITE, LOAD, STORE} State, NextState;    //枚举类型State, NextState。两者值只能是{}中的label
 
  always_comb begin
    if(State == LOAD && instruction == FETCH)  //使用label
    ...
  end
 
endmodule

 1.3. 枚举类型标签序列

state

创建单个标签state

state[N]

创建标签序列 state0,state1, ... stateN-1

state[N:M]

创建标签序列,由stateN开始,到stateM(正反向不存在)

  1.4. 枚举类型标签作用域

enum列表中的label在其作用域内必须是唯一的(label唯一)

这里的作用域包括:$unit, modules, interfaces, programs,begin...end blocks, fork...join blocks, tasks and functions

 1.5. 枚举类型值

  • 枚举类型值在没有显示指定时,默认int从0自加。且label的值也要唯一(value唯一)

enum {A=1, B, C, X=24, Y, Z} list;             //A=1,B=2,C=3,X=24,Y=25,Z=26

  1.6. 枚举类型的基类

  • 枚举类型的默认基类(base type)是int,也可以对枚举类型的基类进行显示声明

enum logic [1:0] {WAITE, LOAD, READY} state;    //2位宽的枚举类型,四态基类

  • 注意label数涉及到value的值,要与基类类型匹配。

 1.7. 自定义枚举类型

typedef enum {WAITE, LOAD, READY} states_t;     //自定义枚举类型states_t
 
states_t state, next_state;  //声明枚举state,next_state

 (同类型枚举变量可以互相赋值)

1.8. 枚举类型的专用系统任务(system tasks)和方法(method)

二  注意细节

enum是system verilog中使用频率极高的数据类型之一,验证中作内置判断类型,设计时作为状态机类型都很常见,平时一直在用但是对于细节一直把控不准,因此总结一下。

常见的枚举类型定义和使用方式,假如我们要定义一个状态机

initial begin
    typedef enum {idle, st1, st2, st3} state_s;
    state_s state, next_state;
    $display("state -> %0d, %0d, %0d, %0d", idle, st1, st2, st3);
end

打印效果如下:

细节1:枚举定义的idle/st1/st2/st2类似于于parameter idle = 0,在当前命名空间域具有独占性;

 例如以下的定义方式,编译时候就会报error:

typedef enum {idle, st1, st2, st3} state_s;
typedef enum {idle, st1}           state_t;

那么当然了,下面这种写法也是不行的,哪怕你定义的值是一样的:

 parameter idle = 0;
typedef enum {idle, st1, st2, st3} state_s;

细节2:枚举内定义的参数值并不是一个完备的取值空间;

这句话有点绕,简单来说就是,枚举变量可以取枚举以外的值!例如下面这段代码,用state_s做强类型转换就可以了:

initial begin
    typedef enum {idle, st1, st2, st3} state_s;
    state_s state, next_state;
    next_state = st1;
    $display("next_state = %0d", next_state);
    next_state = state_s'(10);
    $display("next_state = %0d", next_state);
end

当然了,我是没有想出来什么场景下会这样用,但是这个还是提醒了我们一下,当把枚举类型用作状态机编码时候,不要认为只枚举了三个内置参量,之后写状态或者case时状态机就只能有这三种case,该写default还是要写。

细节3:枚举参量默认是int型,也可以显性的写其他类型;

比如,我要作一个独热码状态机,就可以这么些:

initial begin
	typedef enum logic[2:0]{idle = 3'b000, st1 = 3'b001, st2 = 3'b010, st3 = 3'b100} state_s;
	state_s state, next_state;
	next_state = st1;
	$display("next_state = %0d, state = %0d", next_state, state);
	next_state = state_s'(10);
	$display("next_state = %0d", next_state);
	$finish;
end

值得注意的是,在这个独热码状态机中,由于使用的是logic四态数据类型同时state没有初始化,因此state是X态;此外还是刚刚那个话题,哪怕你就规定了四种参数值,我还是能给你整出来第五个,因此default很关键。

细节4:枚举参量时,你甚至可以写数组;

代码示意如下:

initial begin
    typedef enum {idle, st[3], rt[2]} state_s;
    state_s state, next_state;
    $display("%0d, %0d, %0d", st0, st1, st1);
    $display("%0d, %0d", rt0, rt1);
end

 根据sv标准,st[3]会自动被编译为st0,st1,st2:

这个写法吧,感觉没啥用,估计能用来唬唬人或者用来节省状态机编码时间吧。

 细节5:枚举还内置了很多方法,妈妈再也不怕我忘记怎么用了;

内置方法包括:first()/last()/next(N)/prev(N)/num()/name(),具体用法敲在下面,大家自行感受:

initial begin
	typedef enum logic[3:0]{idle = 4'b0000, st1 = 4'b0001, st2 = 4'b0010, st3 = 4'b0100, st4 = 4'b1000} state_s;
	state_s state;
	state = state.first();
	$display("state.first() = 'b%4b", state);
	state = state.last();
	$display("state.last() = 'b%4b", state);
	state = state.next(2);
	$display("state.next(2) = 'b%4b", state);
	state = state.prev(2);
	$display("state.prev(2) = 'b%4b", state);
	
	$display("state.num() = %0d", state.num());
	$display("state.name() = %s", state.name());
end

打印结果如下:

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值