FSM(finite state machine)有限状态机
目录
1.1 FSM是一种数据结构
它由以下几个部分组成:
1,内在的所有状态(必须是有限个)
2,输入条件
3,状态之间起到连接性作用的转换函数
1.2 为什么要用FSM?
因为它编程快速简单,易于调试,性能高,与人类思维相似从而便于梳理,灵活且容易修改
1.3 FSM定义
1.3.1 FSM的描述性定义:
一个有限状态机是一个设备,或是一个模型,具有有限数量的状态。它可以在任何给定时间根据输入进行操作,使得系统从一个状态转换到另一个状态,或者是使一个输出或者一种行为的发生,一个有限状态机在任何瞬间只能处于一种状态。
1.3.2 FSM硬件定义
由寄存器组和组合逻辑构成的硬件时序电路。有限状态机的状态(即由寄存器组的1和0的组合状态所构成的有限个状态)只可能在同一时钟跳变沿的情况下才能从一个状态转向另一个状态。
1.3.3 FSM通俗定义
发生一个event(事件)后,根据当前存在的状态(cur-state),决定执行的“动作”(action),并设置下一个状态号(transition).
状态(State)指的是对象在其生命周期中的一种状况,处于某个特定状态中的对象必然会满足某些条件、执行某些动作或者是等待某些事件。
事件(Event)指的是在时间和空间上占有一定位置,并且对状态机来讲是有意义的那些事情。事件通常会引起状态的变迁,促使状态机从一种状态切换到另一种状态。
转换(Transition)指的是两个状态之间的一种关系,表明对象将在第一个状态中执行一定的动作,并将在某个事件发生同时某个特定条件满足时进入第二个状态。
动作(Action)指的是状态机中可以执行的那些原子操作,所谓原子操作指的是它们在运行的过程中不能被其他消息所中断,必须一直执行下去。
1.4 FSM分类
主要分为2大类:
第一类,若输出只和状态有关而与输入无关,则称为Moore状态机
第二类,输出不仅和状态有关而且和输入有关系,则称为Mealy状态机
1.5 好的状态机标准
好的状态机的标准很多,最重要的几个方面如下:
第一,状态机要安全,是指FSM不会进入死循环,特别是不会进入非预知的状态,而且由于某些扰动进入非设计状态,也能很快的恢复到正常的状态循环中来。这里面有两层含义:其一要求该FSM的综合实现结果无毛刺等异常扰动;其二要求FSM要完备,即使受到异常扰动进入非设计状态,也能很快恢复到正常状态。
第二,状态机的设计要满足设计的面积和速度的要求。
第三,状态机的设计要清晰易懂、易维护。
2.FSM实例
2.1 两种FSM表示方法
表1 图2状态机实例的二维表格表示(动作/下一状态)
图2为一个状态机实例的状态转移图,它的含义是:
在s0状态,如果发生e0事件,那么就执行a0动作,并保持状态不变;
如果发生e1事件,那么就执行a1动作,并将状态转移到s1态;
如果发生e2事件,那么就执行a2动作,并将状态转移到s2态;
在s1状态,如果发生e2事件,那么就执行a2动作,并将状态转移到s2态;
在s2状态,如果发生e0事件,那么就执行a0动作,并将状态转移到s0态;
有限状态机不仅能够用状态转移图表示,还可以用二维的表格代表。一般将当前状 态号写在横行上,将事件写在纵列上,如表1所示。其中“--”表示空(不执行动作,也 不进行状态转移),“an/sn”表示执行动作an,同时将下一状态设置为sn。表1和图2表示 的含义是完全相同的。
观察表1可知,状态机可以用两种方法实现:竖着写(在状态中判断事件)和横着写( 在事件中判断状态)。这两种实现在本质上是完全等效的,但在实际操作中,效果却截然 不同。
2.2 C代码伪代码表示
2.2.1 竖着写C代码片段
cur_state = nxt_state;
switch(cur_state){ //在当前状态中判断事件
case s0: //在s0状态
if(e0_event){ //如果发生e0事件,那么就执行a0动作,
并保持状态不变;
执行a0动作;
//nxt_state = s0; //因为状态号是自身,所以可以删除此句
,以提高运行速度。
}
else if(e1_event){ //如果发生e1事件,那么就执行a1动作,
并将状态转移到s1态;
执行a1动作;
nxt_state = s1;
}
else if(e2_event){ //如果发生e2事件,那么就执行a2动作,
并将状态转移到s2态;
执行a2动作;
nxt_state = s2;
}
break;
case s1: //在s1状态
if(e2_event){ //如果发生e2事件,那么就执行a2动作,
并将状态转移到s2态;
执行a2动作;
nxt_state = s2;
}
break;
case s2: //在s2状态
if(e0_event){ //如果发生e0事件,那么就执行a0动作,
并将状态转移到s0态;
执行a0动作;
nxt_state = s0;
}
}
2.2.2 横着写(在事件中判断状态)C代码片段
//e0事件发生时,执行的函数
void e0_event_function(int * nxt_state)
{
int cur_state;
cur_state = *nxt_state;
switch(cur_state){
case s0: //观察表1,在e0事件发生时,s1处为空
case s2:
执行a0动作;
*nxt_state = s0;
}
}
//e1事件发生时,执行的函数
void e1_event_function(int * nxt_state)
{
int cur_state;
cur_state = *nxt_state;
switch(cur_state){
case s0: //观察表1,在e1事件发生时,s1和s2处为
空
执行a1动作;
*nxt_state = s1;
}
}
//e2事件发生时,执行的函数
void e2_event_function(int * nxt_state)
{
int cur_state;
cur_state = *nxt_state;
switch(cur_state){
case s0: //观察表1,在e2事件发生时,s2处为空
case s1:
执行a2动作;
*nxt_state = s2;
}
}
3.FSM描述方法
状态机描述时关键是要描述清楚几个状态机的要素,即如何进行状态转移,每个状态的输出是什么,状态转移的条件等。具体描述时方法各种各样,最常见的有三种描述方式:
(1)一段式:整个状态机写到一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出;
(2)二段式:用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出;
(3)三段式:在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。
一般而言,推荐的FSM 描述方法是后两种。这是因为:FSM和其他设计一样,最好使用同步时序方式设计,以提高设计的稳定性,消除毛刺。状态机实现后,一般来说,状态转移部分是同步时序电路而状态的转移条件的判断是组合逻辑。
第二种描述方法同第一种描述方法相比,将同步时序和组合逻辑分别放到不同的always模块中实现,这样做的好处不仅仅是便于阅读、理解、维护,更重要的是利于综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线器实现设计。
在第二种方式的描述中,描述当前状态的输出用组合逻辑实现,组合逻辑很容易产生毛刺,而且不利于约束,不利于综合器和布局布线器实现高性能的设计。
第三种描述方式与第二种相比,关键在于根据状态转移规律,在上一状态根据输入条件判断出当前状态的输出,从而在不插入额外时钟节拍的前提下,实现了寄存器输出。
补充:
FSM的Verilog HDL 设计的基本准则及有限状态机设计的一般步骤
1.1 基本准则
(1) 一个Verilog模块至多描述一个有限状态机。这样不仅可以简化状态的定义、修改和调试,还可以利用一些EDA工具来协助设计。
(2) 使用参数给状态赋值,而不是用宏定义(‘define)。因为’define宏定义在编译时自动替换整个设计中所定义的宏,而parameter仅仅定义模块内部的参数,定义的参数不会与模块外的其它状态机混淆。
(3) 用always模块写组合逻辑时,采用阻塞赋值,而在always块中建立时序电路时,用非阻塞赋值。这样才能保证有限状态机综合前和综合后仿真的一致性。
1.2 一般步骤
1. 逻辑抽象得出状态转换图
就是把给出的一个实际逻辑关系表示为时序逻辑函数,可以用状态转换表来描述,也可以用状态转换图来描述。这就需要:
1) 分析给定的逻辑问题,确定输入变量、输出变量以及电路的状态数。通常是取原因(或条件)作为输入变量,取结果作为输出变量。
2) 定义输入、输出逻辑状态的含义,并将电路状态顺序编号。
3) 按照要求列出电路的状态转换表或画出状态转换图。
这样,就把给定的逻辑问题抽象到了一个时序逻辑函数了。
2.状态化简
如果在状态转换图中出现这样两个状态,它们在相同的输入转换到同一状态去,并得出一样的输出,则称为等价状态。显然等价状态是重复的,一合并为一个电路的状态数越少,存储电路也就越简单。状态化简的目的就是在于将等价状态尽可能地的合并,以得到最简的状态转换图。
3.状态分配
状态分配又称状态编码。通常有很多编码方法,编码方案选择得当,设计的电路可以简单,反之,选的不好,则设计的电路就会复杂很多。在实际设计中,须综合考虑电路复杂度与电路性能之间的折中。在触发器资源丰富的FPGA或ASIC设计中,采用独热码即可用使电路性能得到保证又可以充分利用其触发器数量多的优势,也可以采用输出编码的状态指定来简化电路结构,并提高状态机的运行速度。
4.选定触发器的类型并求出状态方程、驱动方程和输出方程。
5.按照方程得出逻辑图
用Verilog HDL来描述有限状态机,可以充分发挥硬件描述语言的抽象建模能力,使用always块语句和case(if)等条件语句及赋值语句即可方便实现。具体的逻辑化简、逻辑电路到触发器映射均可有计算机自动完成。步骤中的2、4、5不再需要人为干预,使电路设计工作得到简化,效率也有很大的提高。
———————————–节选之夏宇闻老师的Verilog HDL数字系统块设计教程(第2版)
1.5 设计举例
现以一个有限状态机设计的一般步骤
1. 逻辑抽象得出状态转换图
2.状态化简
3.状态分配
4.选定触发器的类型并求出状态方程、驱动方程和输出方程。
5.按照方程得出逻辑图
—————-节选之夏宇闻老师的Verilog HDL数字系统块设计教程(第2版)简单的交通灯控制电路为例介绍用Verilog HDL编写Moore型状态机的方法。
功能描述:南北方向为主干道(L3~L1),绿灯时间为29S;东西方向为次干道(L6~L4),绿灯时间为19S;在一个方向(A)从红转绿前3S,另一方向(B)黄灯亮3S,这是为了B方向的人或车在黄灯亮时就停止行走,也使已经走出的人或车走尽,A方向的人和车再通行。
状态S1:南北红灯亮,东西绿灯亮(时间为19秒)
状态S2:南北红灯亮,东西黄灯亮(时间为3秒)
状态S3:南北绿灯亮,东西红灯亮(时间为19秒)
状态S4:南北绿灯亮,东西红灯亮(时间为19秒)
然后如此循环。