Systemverilog 枚举类型 enum


内容:这篇文章的主要是为了描述枚举类型的定义,为什么需要枚举类型,以一个例子说明枚举类型的基类型,以另外一个例子说明枚举类型的重要性


提示:以下是本篇文章正文内容,下面案例可供参考

一、枚举类型

1.枚举类型值

 缺省情况下,枚举类型列表中的标签代表的实际数值是一个int类型的整数,枚举列表中的第一个标签代表数值0,第二个名称表示1,第三个表示数值2,以此类推。 举例如下:
enum {A=1,B,C,X=24,Y,Z} list1;

  标签A被显式的赋值为1,B自动地表示2,C表示3。X的数值被显式地定义为24,Y和Z分别表示25和26。
 枚举列表中的各个标签必须具有唯一的值,如果有两个标签具有相同的值就会出现错误,下面的例子将会产生一个错误,因为C和D具有同样的数值3.

enum {A=1,B,C,D=3} list2; //错误

2.枚举类型的基类

 枚举类型是具有以系列标签值的变量或线网,因此,枚举类型具有一个Verilog或Systemverilog基类。枚举类型的默认基类是int,它是32位两态类型。

//1位宽的枚举类型,两态基类
enum bit {TRUE,FALSE} Boolean;
//2位宽的枚举类型,四态基类
enum logic[1:0] {WAIT,LOAD,READY} state;

 如果对显式定义枚举类型的枚举标签赋值,那么这个值的宽度必须与基类宽度相符。

enum logic[2:0] {WAIT=3'b001,
                LOAD=3'b010,
                READY=3'b100} state;

 将一个与枚举类型声明的基类宽度不同的值赋给一个枚举标签是错误的,下面的例子就是错误的,enum变量默认为int基类,给标签赋给一个3位值就会发生错误。

enum {WAIT =3'b001,
     LOAD = 3'b010,
     READY =3'b100} state;

 这是错误的,因为int类型是32位,但是其中的枚举元素的变量宽度是3位的,违背值的宽度与基类宽度相符的规定。
 如果枚举列表中的标签超过了基类所能代表的宽度,这是错误的。

enum logic {A=1'b0,B,C} list5  //错误,对于1位宽度来说
//只能为01

 如果枚举值的基类是四态数据类型,将枚举标签赋为X或者Z是合法的。

enum logic{ON=1'b1,OFF=1'bz} out;

 如果X或者Z赋值给枚举列表中的一个标签,下一个必须显式地赋值,试图由赋为X或者Z的标签的值加1来自动获得值是错误的。

  enum logic[1:0]{WAIT,ERR=2'bxx,LOAD,READY}state;
  //错误,不能确定LOAD的值

二、枚举类型使用举例

1.使用传统verilog语言define和parameter编写状态机的代码

代码如下(示例):

`define FETCH 3'h0
`define WRITE 3'h1
`define ADD   3'h2
`define SUB   3'h3
`define MULT  3'h4
`define DIV   3'h5
`define SHIFT 3'h6
`define NOP   3'h7

module controller(output reg read,write,
                  input wire [2:0] instruction
                  input wire clock,resetN);
 parameter WAITE=0,
           LOAD=1,
           STORE=2;
 reg [1:0] state,next_state;
 always @(posedge clk,negedge resetN)
 if(!resetN)
   state <= WAITE;
  else
   state <= next_state;

always @(state) begin
  case(state)
   WAITE : next_state= LOAD;
   LOAD  : next_state= STORE;
   STORE : next_state= WAITE;
   endcase
end

always @(state,instruction)begin
 read=0; write=0;
 if(state==LOAD && instruction == `FETCH)
  read=1;
  else if(state == STORE&&instruction==`WRITE)
  write=1;
  end
endmodule

 这是仿真波形
在这里插入图片描述
 这个是利用verilog撰写的代码,使用常数值的变量,如这个例子中的state和next_state,必须声明为标准的Verilog变量类型,这意味着软件工具无法限定这些信号的有效值仅仅是这些常数数值,在这个例子上,没有采用什么方法来限制state和next_state有一个值3,或者有一位或多位被设置成X或者Z的值,因此,模型本身必须加入对这些值的限定检验,至少,需要一个综合的“full case”编译指令来综合工具,状态变量只使用case列表中的常数值,然而,综合编译指令的使用并不影响仿真,这可能会引起仿真行为和由综合产生的结构级设计并不相同。

2.使用systemverilog 枚举类型 enum撰写代码

 从图中可以看出仿真结果正常,使用systemverilog撰写上述代码
package chip_type;
typedef enum  {FETCH, WRITE, ADD, SUB, MULT, DIV, SHIFT, NOP} instr_t;
endpackage;

import chip_type::*;
module sv_5(
            output logic read, write,
            input instruction,
              input  clk, resetN);
enum {WAIT,LOAD,STORE} state,next_state;
always @(posedge clk or negedge resetN)
 begin
  if(!resetN)
    state <= WAIT;
  else
    state <= next_state;
 end
 
always @(state)
 begin
  case(state)
   WAIT: next_state=LOAD;
   LOAD: next_state=STORE;
   STORE: next_state=WAIT;
  endcase
 end
 
  always @(state,instruction)
  begin       
   read=0; write=0;           
    if(state == LOAD && instruction == `FETCH)
         read=1;     
     else if(state == STORE && instruction ==`WRITE)       
         write=1;           
   end          
                         
endmodule

  testbench

`timescale 1ns/1ns
import chip_type::*;
module sv_5_tb;
logic clk,resetN;

instr_t instruction;
wire read,write;

sv_5 u1(.instruction(instruction),
           .read(read),
           .write(write),
           .clk(clk),
           .resetN(resetN));
 always #5 clk= ~clk;
initial
begin
 clk=0;
 instruction=FETCH;   //FETCH
 resetN=0;
#20
 resetN=1;
#2000
$finish;
 end
endmodule

 仿真波形
在这里插入图片描述
 在这个例子中,变量State和Next_state只能有WAITE、LOAD、和STORE三种有效值,所有的软件工具,包括仿真、综合和形式验证都用相同的方式解释对于枚举类型变量合法值的约束,所以systemverilog撰写的case语句中不需要加入default,也不会生成锁存器。
 分析利用systemverilog仿真的波形,read与write的数值是不定态,而且state,next_state的数值也没有发生更新,这是为什么呢??
 always块建立的组合逻辑不会在零时刻自动触发,
这是因为state是枚举类型,枚举类型的缺省值是int两态数据类型,所以默认初始值是0,0时刻复位没有任何变化,所有不会触发。

总结

 通过举例可以发现,枚举类型enum的引入带来了以下优点:
 (1)systemverilog引入了枚举类型enum之后,简化了代码的复杂度,使得代码便于维护和调试。
 (2)使用systemverilog enum枚举类型可以避免锁存器的产生,但是使用verilog撰写的代码必须设置default的缺省值选项,否则会生成锁存器。
  • 21
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
可以使用SystemVerilog中的typedef和enum结合来实现一个三段式状态机。下面是一个示例代码: ``` typedef enum logic [1:0] {STATE_IDLE, STATE_READY, STATE_BUSY} state_t; module three_state_machine ( input wire clk, input wire reset, output reg [1:0] state ); state_t next_state; always @(posedge clk or posedge reset) begin if (reset) begin next_state <= STATE_IDLE; end else begin case (state) STATE_IDLE: begin // Transition to STATE_READY when input condition is met if (input_condition) begin next_state <= STATE_READY; end else begin next_state <= STATE_IDLE; end end STATE_READY: begin // Transition to STATE_BUSY when enable signal is high if (enable_signal) begin next_state <= STATE_BUSY; end else begin next_state <= STATE_READY; end end STATE_BUSY: begin // Transition to STATE_IDLE when operation is complete if (operation_complete) begin next_state <= STATE_IDLE; end else begin next_state <= STATE_BUSY; end end endcase end // Update state register state <= next_state; end endmodule ``` 在这个三段式状态机中,我们定义了三个状态:STATE_IDLE,STATE_READY和STATE_BUSY。我们使用typedef将这个状态集合命名为state_t。 在模块中,我们有一个时钟输入,一个复位输入和一个状态输出。我们还有一个next_state变量,用于存储下一个状态。在时钟上升沿时,我们使用case语句根据当前状态更新下一个状态。最后,我们将next_state赋值给state,以便在下一个时钟上升沿时更新状态输出。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值