状态机学习报告.docx
《状态机学习报告.docx》由会员分享,可在线阅读,更多相关《状态机学习报告.docx(25页珍藏版)》请在冰豆网上搜索。
状态机学习报告
状态机学习报告
1.状态机概念
状态机就是对具有逻辑顺序或时序规律的事件进行描述的一种方法,是由寄存器组和组合逻辑构成的硬件时序电路。
所有具有逻辑顺序和时序规律的事情都适合用状态机来描述。
状态机有三要素:
状态(状态变量),在逻辑设计中,使用状态划分逻辑顺序时序规律。
输出,在某一个状态时特定发生的时间。
输入,状态机进入每个状态的条件。
2.状态机分类
根据输出是否与输入条件有关,可以将状态机分为MOORE(摩尔)型和MEALY(米勒)两大类:
A)摩尔型:
状态机的输出仅依赖当前状态,与输入条件无关。
输入X
组合逻状态寄组合输出Y
辑电路存器电路
当前状态
摩尔型状态机的描述方法:
case
A:
next_state<=B
B:
next_state<=C
...
endcase
B)米勒型:
状态机的输出不仅依赖当前的状态,还与输入有关。
输入X输出Y
组合逻
辑电路状态寄
clk存器
当前状态
米勒型状态机描述方法:
case
A:
//不满足条件则停留在当前状态的跳转
if(conditionA)
next_state<=B
else
next_state<=A
B:
//两种不同次态的跳转
if(conditionB)
next_state<=C
else
next_state<=D
endcase
另外,根据状态机数量是否有限,可将状态机分为FSM(有限状态机)和ISM(无限状态机)。
3.设计方法
状态机的描述方式有:
状态转移图、状态转移列表和HDL语言描述。
状态转移图经常在设计规划阶段定义逻辑功能时使用,也可以在分析已有源代码中的状态机时使用,这种图形化的描述方式有助于理解设计意图。
状态转移列表是用列表的方式描述状态机,是数字逻辑电路常用的设计方法之一,经常被用于状态化简,对于可编程逻辑设计而言,由于可用逻辑资源比较丰富,而且状态编码要考虑设计的稳定性、安全性等因素,所以并不经常使用状态转移列表优化状态。
使用HDL语言描述状态机应具有一定的灵活性,通过使用一些规范的描述方法,可以使HDL语言描述状态机更安全、更稳定、更高效、更易于维护。
所以用HDL语言描述状态机,是我学习写状态机的重点。
状态机的一般设计步骤:
(1)分析状态;
(2)确定状态转移图;(3)状态简化;(4)状态编码。
在电路设计中,状态机的基本描述一般有三种:
状态转移列表,状态转移图,HDL语言描述。
状态转移列表是用列表的方式来描述状态机,经常用于状态化简。
但是由于状态编码要考虑设计的稳定性和安全性等因素,并不推荐用状态转移列表优化状态。
状态转移图是状态机描述中最自然的方式,不仅在规划功能状态的时候经常用到,在分析源代码的时候也都经常用到。
这种方法有助于理解设计意图。
3.1用StateCAD自动转化
在ISE中的StateCAD支持以状态转移图作为逻辑设计输入能够自动将状态转移图生成HDL语言。
设计者只要画出状态转移图就可以了,StateCAD能自动将状态转移图翻译成HDL语言代码,而且翻译出来的代码规范,可读性较好、可综合、易维护,但是由于其自动翻译的代码过于格式化,因此效率不高,对于较大规模的逻辑设计而言,还是推荐使用HDL语言进行描述。
下面将介绍使用状态机进行状态机设计的一般步骤。
A)创建状态机:
使用ISE创建工程后,为工程添加新的设计输入,选择“StateDiagram”选项,如下图所示。
然后点击Next,在弹出的Summary框中点选Finish,就会生成如下图所示的State主界面。
选择
图标,就进入了状态机输入的向导,如下图所示。
在这个界面里可以设置状态机图形的形状。
选择Next之后,出现的界面是设置同步或异步复位模式的,一般我们都选择同步复位。
界面如下图所示。
下一个界面是设置转换模式的,如下图所示。
设置完毕后选择“Finish”就完成了状态机的创建。
此时在主界面上将出现向导生成的图形,具体如下图所示。
B)添加状态任务
双击如上图所示的STATE0状态,为其添加任务,此时将出现如下图所示的状态任务编辑器。
在点选OutputWizard可以根据不同的需要来设置。
选择完毕以后点击OK即可。
依此方法便可以完成对各个状态的任务的编辑。
C)添加状态转移条件
在主界面上双击每两个状态间的连线来设定状态转移条件,其余操作与前面添加状态任务基本相同,这里就不重复介绍。
设置完成后的界面如下图所示。
D)优化设置
选择主界面工具条上的
按钮就可以打开优化设置向导,如下图所示,可以看出该向导里面共有5个步骤,下面分别介绍。
(1)选择目标器件,如下图所示。
(2)选择状态机的优化方向,可以选择速度优先、占用面积优先及手动设置三种。
如下图所示。
(3)对状态机的性能改善方式进行选择,如下图所示。
(4)加载优化参数设置,如下图所示
(5)为状态机选择输出的HDL语言格式及综合的工具,如图后面两图所示。
经过这5个步骤,基本就完成了对状态机的优化设置,点选主界面上的
图标,如果没有错误的话就可以生成HDL语言形式的状态机了。
但是,从生成的程序可以看出,自动翻译的代码过于程序化,效率不是很高,所以只推荐对一些规模较小的状态机使用这种方法。
此方法只作一般了解,ISE10.1里面还保留此功能,但到更高的版本,如ISE12.5就没有这项了,因其效率低,慢慢被淘汰,所以还是推荐同HDL进行状态机描述。
3.2用VerilogHDL语言描述
用HDL语言进行描述状态机,具有一定灵活性,通过一些规范的描述风格,可以使描述更加安全、规范,是最为常用的一种方法。
根据状态机的三要素,我们可以知道描述状态机就是说清楚3点内容:
第一,如何进行状态转移;第二,每个状态的输出是什么;第三,状态转移是否与输入条件相关。
由于受可综合条件的限制,描述方法分成三种:
一段式,二段式及三段式。
下面将分开进行阐述和对比。
3.2.1一段式
将整个状态机写在一个always模块里,该模块既描述状态转移又描述状态的输入和输出。
但这种方法往往缺乏条理,不便阅读,不利于维护和修改,还经常受到不可综合的问题,所以不建议使用这种方法,一般推荐使用二段式或三段式。
3.2.2二段式
这种方法使用两个always模块,一个always模块采用同步时序的方式描述状态转移,而另一个always模块采用组合逻辑的方式来判断状态转移条件,描述状态转移的规律。
其中描述同步时序状态转移的模块代码基本都是如下这种格式。
always@(posedgeclkornegedgenrst)
if(!
nrst)CS<=IDLE;
ElseCS<=NS;
在时钟沿到达时将NS赋给CS。
但要注意赋值时要采用非阻塞赋值“<=”。
例1、位于十字路口的交通灯,在A方向和B方向各有红、黄、绿三盏灯,假设各颜色的灯变换的时间间隔相等。
变换顺序如下表:
A方向
B方向
绿
红
黄
红
红
绿
红
黄
交通灯的全部状态及输出,表1:
状态
A方向
(红绿黄)
B方向
(红绿黄)
S0
010
100
S1
001
100
S2
100
010
S3
100
001
画出状态转移图:
编写描述上述功能状态机的verilog程序:
1一个always模块以同步时序的方式描述状态转移,另一个则用组合逻辑。
次程序描述的是Moore型有限状态机。
状态分配部分,本程序采用的是独热编码(one-hot-coding),但其实通常有很多编码方法,如顺序二进制编码、Gray码等,若编码方案选择得当,设计的电路可以很简单。
值得注意的是,本程序采用了独热码后有了多余的状态,就存在一些不可到达的状态,因此在case语句的最后需要增加defual分支项,以确保多余状态能回到S0状态。
对于用FPGA实现的有限状态机建议采用独热码。
因为虽然采用独热码多用了触发器,但所用组合电路可省下许多,因而使电路的速度和可靠性有显著提高,而总的单位数并无显著增加。
下图是仿真结果,各个状态时按照上面所画的状态转移图的规则转移的,所以仿真结果正确,说明程序编写正确。
上面的程序是典型的二段式描述方式描述状态机,即用同步时序描述状态转移:
always@(posedgeclkornegedgeRES)
if(!
RES)CS<=S0;
elseCS<=NS;
用组合逻辑判断状态转移条件,描述转移规律:
always@(CS)begin
case(CS)
S0:
begin
{o1,o2,o3,o4,o5,o6}=6'b010100;
NS=S1;
end
……
default:
……
endcase
end
组合逻辑输出的好处是:
写法简单和利于复用共同的输出。
但是存在的不足之处是,组合逻辑容易产生毛刺等不稳定因素。
解决的办法是,若时序允许,应尽量对组合逻辑的输出插入一个寄存器节拍(在后级电路对FSM的组合逻辑输出用寄存器存一个节拍),以保证输出信号的稳定性。
2下面的程序在①中的程序的基础上添加了寄存器节拍,以减小毛刺。
具体是在描述状态机时的主要用途是将不同状态所对应的输出用task/endtask封装,增强了代码的可维护性和可读性。
仿真结果如下图,以观察出仿真结果是正确的。
两段式思路建模结构清晰、描述简洁、便于约束,但是两段式采用的组合逻辑易产生毛刺等不稳定因素,虽然可以采用额外插入一个时钟节拍的方法改善,但很多情况下设计并不允许插入额外的节拍(latency)。
所以②是①的基础上加以改良了的方案。
3.2.3三段式
三段式FSM描述方法是在两段式描述方法的基础上发展而来的,这种写法采用3个always模块,一个采用同步时序的方式描述状态转移;一个采用组合逻辑的方式判断状态转移条件,描述状态转移规律;还有一个always模块则使用同步时许电路描述每个状态的输出。
注意:
区分n段式描述方法,不是看其使用了几个always模块,而是根据always模块的固定的描述内容个格式化的结构。
三段式描述方法与两段式描述方法相比较,关键在于使用同步时许逻辑寄存FSM的输出,消除了组合逻辑输出的不稳定性,且利于时序路径分组。
而与一段时相比较,三段式逻辑清晰,更符合思维习惯。
三段式思路建模结构清晰,格式化的结构解决了在不改变时序要求的前提下用寄存器做状态输出的问题。
为提高设计的稳定性和消除毛刺,最好使用同步时序方式设计,所以一般不推荐使用一段式写法,而采用二段式或者三段式。
4实例分析
使用不同的FSM描述方法描述状态机。
状态机关系如下图所示,共四个状态:
IDLE、S1、S2、ERROR,输入信号包括时钟clk,低电平异步复位信号nrst和输入信号i1、i2以及输出信号o1、o2、err。
状态的输出如下:
IDLE:
{o1,o2,err}=3’b000;
S1:
{o1,o2,err}=3’b100;
S2:
{o1,o2,err}=3’b010;
ERROR:
{o1,o2,err}=3’b111;
4.1用StateCAD实现
由ISE程序自动生成对应于所画的状态机的verilogHDL语言程序。
由于在画状态转移图时没有标出各状态转移后的输出情况,所以如下面程序所示,没有交代输出状况,不过可以经过后期人工修改,添加所需部分。
可以看出软件系统生成的程序是二段式FSM描述的。
组合逻辑部分是以if/else语句判断状态转移条件是否符合以及描述转台转移规律的,程序在运行时总是要对比判断各个条件里面的每一项,这导致程序运行效率不高。
4.2一段式FSM描述方式
由于ISE12.5要手动描写并生成*.tbw文件,所以功能仿真时先按照下表设置好输入与状态转换表,表2,之后观察仿真结果判断是否出现错误。
nrst
i1i2
state
o1o2err
0
xx
IDLE
000
1
11
S1
100
x0
S1
100
11
S2
010
X1
S2
010
10
IDLE
000
10
ERROR
111
1x
11
IDLE
S1
000
100
01
ERROR
111
对应的.tbw文件中主要修改部分如下面的截图所示:
观察下面的仿真结果图,里面输入输出均与表1里面的吻合,说明此一段式FSM描述程序正确的描绘出了满足题目要求的功能的verilog程序。
4.3二段式FSM描述方式
如下面的程序,两个always模块分别为同步时序和组合逻辑,负责不同的职责,共同完成对设计功能的实现。
按照下面表3所示,设置好仿真输入,观察对比输出转变,判断FSM描述程序是否正确。
nrst
i1i2
state
o1o2err
0
xx
IDLE
000
1
xx
ERROR
111
0x
IDLE
000
11
S1
100
11
S2
010
10
IDLE
000
11
S1
101
01
ERROR
111
此程序为输入信号的时序描述程序。
观察仿真结果,nrst=0时,state为IDLE;而nrst=1之后,state随着当前状态以及i1和i2的变化而转变,而且转变结果与上面的表3吻合,说明程序正确,仿真结果页正确。
4.4三段式FSM描述方式
与二段式FSM描述方式相比,三段式描述方式多了一个描述输出的同步时序。
这里用和上面4.3里面二段式描述程序的.tbw一样的.tbw程序,得到的仿真结果如些图所示。
在nrst=0时,程序里面没有描述此情况的输出情况,故输出为{o1,o2,err}=3’bx;而在nrst=1之后,不在IDLE、S1、S2、ERROR这四种state之内的情况全都输出error且下一个上升沿时钟到来时state跳转为IDLE。
右下图观察比较得出的结论是:
编写的状态机程序以及仿真结果均正确。
5描述标准
在状态机的描述上,容易出各种各样的问题,所以也就有了相应的标准:
A)状态机不会进入死循环,进了非设计状态也要能够迅速恢复,在综合实现结果中要无毛刺等异常状态;B)状态机的速度要快;C)状态机的面积要小;D)状态机设计要清晰易懂,易修改维护,能综合实现。
5.1毛刺问题
(1)产生原因
在一般组合逻辑电路中都容易出现毛刺现象,究其原因有两方面,一是组合逻辑电路中存在竞争冒险的现象,二是各个信号在线路中传输其距离和物理环境的差异造成的传输延迟各不相同,照成各信号线上的值发生改变的时间存在先后,从而使得状态迁移时在初始状态和目的状态之间出现临时状态。
其现象就有点像高频窄脉冲。
(2)造成影响
一般情况下“毛刺”不会产生重大影响。
因为“毛刺”仅发生在时钟有效边沿之后的一小段时间内,只要在下一个时钟有效边沿到来之前“毛刺”消失即可。
但当状态机的输出信号作为其他功能模块的控制信号,将会使受控模块发生误动作,造成系统工作混乱。
(3)消除方法
消除状态机输出信号的“毛刺”一般可采用四种方案:
1对于一般情况下产生的毛刺,可以尝试用D触发器来消除。
但用D触发器消除时,有时会影响到时序。
2调整状态编码,采用格雷码,使相邻状态间只有1位信号改变,从而消除竞争冒险的发生条件,避免了毛刺的产生。
3在有限状态机的基础上采用时钟同步信号,即把时钟信号引入组合进程。
状态机每一个输出信号都经过附加的输出寄存器,并由时钟信号同步,因而保证了输出信号没有毛刺。
4直接把状态机的状态码作为输出信号,即采用状态码直接输出型状态机,使状态和输出信号一致,使得输出译码电路被优化掉了,因此不会出现竞争冒险。
5.2相关的建议
1为了避免状态机进如死循环,提高安全性,在使用case语句时加上default语句,在使用if语句是加上else语句来描述所设状态的补级状态。
2用task/endtask来将输出封装起来,这样做的好处不仅使写法简单,增强代码可读性,还有利于复用共同的输出。
3将敏感表后描述的默认状态设计为不定状态X,使得在仿真时可以很好地观察所设计的状态机的一致性,如果设计的状态机不完备,则会进入任意状态,仿真的时候就很容易发现。
而且综合器对不定态X的处理是忽略,也就是说任何没有定义的状态寄存器都会被忽略。
4当前状态向下一个状态时序转移和寄存状态机输出的always模块中都要使用非阻塞赋值,在状态转移条件判断和组合逻辑输出等always模块中都要使用阻塞赋值。
5要有初始化状态和补级状态,这样才能称得上是一个完备的状态机。