作为一名逻辑工程师,掌握和应用状态机设计是必不可少的。能够灵活的应用状态机是对逻辑工程师最基本的要求,状态机设计的好坏能够直接影响到设计系统的稳定性,所以学会状态机是非常的重要。
1.状态机的概念
状态机通过不同的状态迁移来完成特定的逻辑操作。状态机主要内容包括以下几个方面:
(1)状态机是用来描述系统逻辑功能的一种方式;
(2)定义了系统所处的不同状态;
(3)描述了系统状态转化的条件及转换过程;
(4)刻画了系统状态和输入输出之间的关系。
状态机可以通过文字、状态转移图、状态转移表等方式进行描述,最后以Verilog或者VHDL进行程序编写,最后实现对应的电路逻辑功能。
举个简单的生活实例来对状态机的概念说明一下,例如我每天的生活为例,如表-1所示。
表-1
时间 | 对应的事件 |
7:00到7:30 | 起床洗漱 |
7:30到8:00 | 在家吃早饭 |
8:00到9:00 | 坐地铁去上班 |
9:00到12:00 | 在公司工作 |
12:00点到13:00 | 吃午饭、休息 |
13:00到18:00 | 在公司工作 |
18:00到19:00 | 坐地铁回家 |
19:00到21:00 | 在家看电视、玩游戏 |
21:30到22:00 | 洗漱 |
22:00以后 | 睡觉 |
如表-1所示,每一个时间段就相当于状态机中的一个状态,在每个对应的状态里,就做对应的事情,这就叫做状态机。在逻辑设计,逻辑工程师通过采用状态机的设计方法,能够将一个复杂的逻辑事件变得简单容易。
2.状态机的分类
状态机主要分为两种,一种是Mealy状态机,另一种是Moore状态机。A.Mealy状态机:时序逻辑的输出不但取决于状态还取决于输入,如图所示。
B.Moore状态机:时序逻辑的输出仅仅取决于上一时刻的状态,而与当前时刻的输入无关,如图所示。
在实际设计中,Mealy类型的状态机是用的最多的,Moore类型虽然清晰明了,但是状态太多,不适合大型状态机的设计。
3.状态机的设计步骤
状态机的设计步骤主要分为以下4个步骤:
A.逻辑抽象:得出状态转换图:就是把给出的一个实际问题表示为时序逻辑函数。可以用状态转换表来描述,也可以用状态转换图来描述。
B.状态化简:如果在状态转换图中出现这样两个状态:它们在相同的输入下转换到同一个状态中,并得到相同的输出,或称它们为等价状态。显然等价状态是重复的,可以合并为一个(电路的状态越少,存储电路也就越简单)。
C.状态分配:状态分配又称状态编码。通常有很多编码方法,编码方案选择得当,设计的电路简单,反之,选得不好,则设计的电路就会复杂许多;(binary_code/gray_code/one_hot_code/.ect)。
D.用逻辑描述语言进行行为描述建模(行为级)。
4.状态机的描述方式
状态机的描述方式有很多种,但是最常用的主要有3中,分别是一段式(always)、两段式(2 always)、三段式(3 always)。
A.单always块把组合逻辑和时序逻辑用同一个时序always块描述,其输出是寄存器输出,无毛刺;但是这种方式可能会产生多余的触发器,代码难于修改和调试,应该尽量避免使用。
B.双always块大多用于描述Mealy状态机和组合输出的Moore状态机。
时序always块描述当前状态逻辑,组合逻辑always块描述次态逻辑并给输出赋值。
这种方式结构清晰,综合后的面积和时间性能好。但组合逻辑输出往往会有毛刺,当输出向量作为时钟信号时,这些毛刺会对电路产生致命的影响。
C.三always块大多用于同步Mealy状态机。
两个时序always块分别用来描述现态逻辑和对输出赋值,组合always块用于产生下一状态。
时序电路的状态是一个状态变量集合,这些状态变量在任意时刻的值都包含了为确定电路的未来行为而必需考虑的所有历史信息。
这种方式的状态机也是寄存器输出,输出无毛刺,并且代码比单always块清晰易读,但是面积大于双always块。随着芯片资源和速度的提高,目前这种方式得到了广泛应用。
5.举例
下面分别用三种状态机的描述方式实现流水灯的功能。A.一段式状态机实现流水灯功能
一段式代码内容如下图所示:
在代码中,每当cnt_num计数到7时,led_out的亮灯的位置变化,state跳转,计数器清零,通过循环的方式实现流水灯的功能。
仿真结果:
B.两段式状态机实现流水灯功能
两段式的代码如下图所示:
在两段式状态机的代码中,cnt_num计数器必须单独使用一个always,不能添加到两段式中;两段式的第一段必须是时序逻辑,实现将next_state赋值给current_state;第二段是组合逻辑,实现在当前的current_state下,当cnt_num等于7时,输出对应的led_out以及next_state。
仿真结果
C.三段式状态机实现流水灯功能
三段式状态机的代码如下图所示:
第一段为时序逻辑,实现cuurent_state<=next_state;
第二段为组合逻辑,根据跳转条件(cnt_num==3’d7)实现next_state状态的跳转
第三段为时序逻辑,在对应的状态中输出对应的led_out结果。
仿真结果
6. 三种FSM状态机比较
三种FSM描述方法比较
比较项目 | 一段式描述方法 | 两段式描述方法 | 三段式描述方法 |
推荐等级 | 不推荐 | 推荐 | 最优推荐 |
代码简洁程度 | 冗长 | 最简洁 | 简洁 |
always模块个数 | 1 | 2 | 3 |
是否利于时序约束 | 不利于 | 利于 | 利于 |
是否有组合逻辑输出 | 可以无组合逻辑输出 | 有组合逻辑输出 | 无组合逻辑输出 |
是否利于综合与布局布线 | 不利于 | 利于 | 利于 |
代码的可靠性与可维护性 | 低 | 高 | 最好 |
代码风格的规范性 | 低,任意度较大 | 格式化,规范 | 格式化,规范 |
7. 本章总结
使用状态机的描述方式来编写程序,能够将复杂的逻辑时序关系变得简单易懂,状态机是一种逻辑思想的体现。状态机的描述方式不只是本章节介绍的3中描述方式,只要能够将逻辑关系表述清楚的都可以认为是状态机。