RTL基本知识:使用枚举类型表示状态机进入死循环

在定义状态机中的状态时,除了可以使用宏(define)或者参数(parameter)声明定义外,还可以使用枚举类型,但是如果对于枚举类型使用不正确的话,极易出现编译仿真均没有报错,但是仿真时状态机跳转异常的情况.本文将针对这种情况进行示例说明并给出解决方法.

1  数据类型

在Verilog中所有的变量和线网都是4值数据类型,但在SystemVerilog中,对信号类型和数据类型进行了详细的区分,其中信号类型保持与Verilog一样,主要分为变量和线网类型,但是数据类型分为了2值类型(0和1)和4值类型(0,1,x和z),对信号的数据类型进行了扩展,但是保持了线网类型原有的数据类型,在默认状态下,4值数据类型的默认值为x,2值类型的默认值为0.同时SystemVerilog结合C语言的特性,引入了其他一些类型,例如枚举类型等,通过多种类型的引入,极大地丰富了SystemVerilog进行程序设计的灵活性.

   

2  枚举类型

用户可以通过枚举类型定义特定的常量值的集合.

格式:

使用方式如下:

枚举常量代表该枚举类型的变量的可能取值的列表,编译系统为每个枚举常量指定一个数值,缺省状态下这个数值从0开始,且数据类型为int,即2值型的整型.

3  问题描述

对下述代码进行仿真时,状态跳转执行异常,核心代码如下:

当上述状态机运行时,状态机将一直处于WAIT状态,状态执行异常.

4  问题分析

这里需要注意到,枚举常量列表中的枚举常量在缺省状态下,枚举常量的数值是从0开始递增.且2值数据类型变量的初始值为0.所以在此例中,state_e和nstate_e的初始状态都为0,即WAIT.当复位撤销后,state_e和nstate_e都为WAIT,那么组合逻辑部分always@(state_e)的敏感信号列表中的state_e将一直保持在WAIT状态,所以该部分组合逻辑将不会被执行,从而导致nstate_e状态不会被更新,因此,状态既不能推进,将一直保持在初始的WAIT状态.

5  解决方法

出现上述问题主要是因为代码中组合逻辑部分的敏感信号列表中的变量没有发生变化,从而没有出发进程的执行导致的,因此,解决方法主要是实现组合逻辑部分的有效执行,实现nstate_e的变化.

5.1  使用always_comb结构

always_comb在仿真开始的0时刻会自动调用一次,从而可以实现nstate_e状态的更新,将组合结构中的always@(state_e)替换为always_comb即可.

5.2  将枚举变量的数据类型指定为4值类型,如下所示:

在仿真开始时,因为枚举类型的数据类型为logic型,所以变量state_e和nstate_e的默认状态都为x态,那么在复位阶段state_e被初始化为WAIT时,组合逻辑部分的always@(state_e

中的敏感信号state_e状态从x态变化到了WAIT,即状态发生变化,触发组合逻辑部分进程的执行,nstate_e会被更新为LOAD,从而可以实现状态机的推进.

5.3  指定枚举常量的初始值

枚举列表中的枚举常量列表中的第一个常量,默认初始值为0-,其后常量数值依次递增,但是这个起始值也可以在枚举类型声明定义时指定为其他值,从而可以使2值型枚举变量的初始状态-与枚举变量列表中的常量起始值不一样,在复位阶段state_e被更新为非零值时,更新后的值与类型的默认值0不一样,从而也可以实现组合逻辑部分敏感信号列表中信号的变化,从而使组合逻辑中的nstate_e状态可以被更新,推进状态机的运行,示例如下:

 

 更多资讯,请关注个人公众号:芯光灿烂

原文地址:https://www.cnblogs.com/xgcl-wei/p/9190329.html