结构化状态机结构化和面向对象象状态机的区别

3701人阅读
程序设计(12)
我们第一次接触到状态机,是在数字电路课程里。计数器、串行奇偶检校、检验三个1连续出现的报错电路 等,都需要状态机作为模型。实现这些功能的电路,与状态机的状态转换图、状态转换表都是等价的。
后来,我们再接触状态机,是在编译原理课程里。状态机用于描述与正则表达式匹配的字符串。
再后来,我们在GUI界面设计中,需要设置一些控件在某些条件下 禁用,某些条件下使能,某些条件下打个对号。这也可以用状态机模型来控制。
1. 不要写成 消息响应/事件处理
状态机和消息响应都是 双层 switch-case 结构。不同的是,状态机的外层是状态,内层是消息;消息响应外层是消息,内层是状态。
有的同学会说,那又有多大的区别呢?代码只是外在形式而非本质,它所反应的是你对模型的理解,或者说,对于问题,你使用了哪种模型。
消息响应适合于这样的情形:有很多种消息,对于同一种消息,你的程序总是给出同一种反应。打个比方,你女朋友喜欢吃冰淇淋,任何时候你给她买,她都高兴,或者转怒为喜,或者转悲为喜,总之,会置心情为&喜&。这种情形,适合用消息响应解决。
而状态机适合于另一种情形,你的程序是&有状态的&,它在不同的情况 (状态)下,会对同一消息做出不同的反应。状态,是一种数据,但是它影响流程的行为。按面向对象的观点,数据与流程间的这种高内聚关系,非常适合用 类 来实现。这是题外话,我们回到女朋友和冰淇淋间的关系。你女朋友可能并非在任何情况下吃了冰淇淋都高兴,比如刚刚吃完十个八个的时候...这与她当前的状态有关。
状态机中,我们需要掌握的核心的数据是:当前状态,当前消息,将迁移到的状态,在迁移中发生的动作。
在状态机代码之前,请先看一段消息响应机制,VC生成的win32api代码大抵如此。我们随便找来一段片断看看:
1 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
3 int wmId, wmE
4 PAINTSTRUCT
6 switch (message)
8 case WM_COMMAND:
9 wmId & &= LOWORD(wParam);
10 wmEvent = HIWORD(wParam);
11 case ID_MENU_GO: ....
12 case IDM_ABOUT: &....
13 case IDM_EXIT: & ....
14 default:
15 return DefWindowProc(hWnd, message, wParam, lParam);
18 case WM_PAINT: ....
19 case WM_DESTROY: ...
20 case WM_KEYDOWN: ...&
21 default: return DefWindowProc(hWnd, message, wParam, lParam);
23 return 0;
第6行开始到第22行结束,对每个消息给出一个响应。没错,win32api也把这个传进来的东西称为 message。这是很典型的适合消息响应机制的情形,程序对于相同的消息,处理的方法总是相同的。
我们常常错误地把状态机写成了消息响应,消息这部分处理得不错,但是,由于没有很好地记录和迁移状态,写起来容易把自己写糊涂了。无他,用错了工具。拿螺丝刀打孔,不是工具差,而是工程师选错了工具。
2. 状态机实例,录音机
实例得是相对简单的,不然我们很容易淹没在细节之中,没有足够精力去关注状态机本身的机制了。假设我们仿真一台录音机...
我们先假设你见过录音机。录音机是一种曾经先进的设备,有一个或两个&卡&,可以放进磁带。&卡&前面有几个按键,这几个按键上的标识因为图形简单且示意性强,现在还在广泛使用。它们分别是 播放 & 、暂停 || 、快进 && 、快退&& 、录音 O 、停止 []。
这几个按键之间是有一定的&互斥关系&的。比如当播放键按下时,我们不应该能把 快进键按下。当然,淘气的同学可能这样干过,我们会听到&咔咔&的声音,然后是家长骂败家玩艺的声音。可以就&互斥关系&开始写程序,但是我觉得这样有点麻烦。
我们认为,这种&互斥关系&是因为录音机是&有状态的&。所以,我们打算用状态机来实现。状态转换图是这样的。请读图的时候关注这四点:当前状态,当前消息,将迁移到的状态,在迁移中发生的动作 (本例中没有) 。
备注:我实在想不起来 暂停 和 停止 之间的关系了,似乎是这样的,又似乎不是。反正大概是那么个意思,不影响对状态机的理解,就这么地吧。
接下来是C代码实现。
3. 接口 及 测试
看到以下代码,有的同学会说,你这不就是主程序么,为什么要把小标题叫做接口。因为,它规定了我们的状态机函数将是什么样子的。
1 enum message { play, stop, forward, backward, record, pause };
3 int main(int argc, char *argv[])
5 & & char c=0x00;
6 & & while(1)
8 & & & & c = getchar();
9 & & & & switch(c)
10 & & & & {
11 & & & & & & case ' ': state_change(pause);
12 & & & & & & case 'p': &state_change(play);
13 & & & & & & case 'r': state_change(record);
14 & & & & & & case 's': state_change(stop);
15 & & & & & & case 'f': state_change(forward);
16 & & & & & & case 'b': state_change(backward);
17 & & & & & & case 'q': & & return EXIT_SUCCESS;
18 & & & & }
20 & & return EXIT_SUCCESS;
上述代码规定了,状态机迁移函数的原型/签名是 void state_change(enum
message m)。
测试的时候,我们这样做:./state & test.in。test.in的内容是&psfsbspq&,测试时期待看到输出的状态迁移过程。之所以这样做,而不是每次从控制台手动输入,是因为每次测试的内容都应该是相同的--相同的输入,程序有相同的反应--可重现性。或者说,DRY原则。
一个非常值得我们注意的问题。在上述接口中,我们看不到&状态&。事实上,我们将会定义:
enum state { s_stop, s_play, s_forward, s_backward, s_pause, s_record };
但是,接口以外的代码,是 *不应该* (是不应该,不是 不必要,是一定不要) 知道状态的,既不应该知道当前状态,也不应该知道将要迁移到哪个状态,也不应该知道在迁移过程中应该做什么动作。如果接口以外的代码知道了这些,就侵入了状态机的隐私,子系统的边界就模糊了。而契约的首要任务就是规定边界,规定国家与个人、个人与个人、个人与集体的边界。
这一原则,早在195X年,软件工程刚刚开始的时候就确立了,是最初确立的原则,即 信息隐藏。后面的原则,都是它的儿子孙子。有个比喻讲过这个道理。当你在超市出口付款的时候,你会自己把钱从钱夹里拿出来递给售货员,而不会转过身去对她说,&在我屁股兜里,你自己掏吧,别忘了把零钱放回来。&这既增加了假设--你极端信任她,也增加了她的责任。
接口,最主要的任务就是为了明确责任,把责任分布在子系统边界两侧。其次才是规定调用的方法,即边界长什么样。
4. 状态迁移
以下是状态机的代码片断。
1 enum state { s_stop, s_play, s_forward, s_backward, s_pause, s_record};
2 void state_change(enum message m)
4 &static enum state s=s_
5 &switch (s)
7 case s_play:
8 & & if(m==stop)
9 & & & &{
11 printf(&stop.\n&); & & & &
12 & & & &}
13 & & & &else if (m==pause)
14 & & & &{
15 & & & & & & &s = s_
16 printf(&pause&);
17 & & & &}
18 & & & &
我们还是要关注那四个关键点: (1) 当前状态, (2) 当前消息, (3) 将迁移到哪个状态, (4) 迁移中会做哪些动作。
(1) 当前状态必然是第1行的枚举类型中的一个。我们初始化状态为 停止,见第4行。
在第5行到第7行,我们的双重 switch-case 的外层 按当前状态分类,如下。
5 &switch (s)
7 case s_play:
下面还有很多 case,第1行的枚举类型中的每一个状态,都有一个 case。
(2) 当前消息。如果当前状态是第7行了,那么,当前消息由双层 switch-case的内层,即第8行,第13行的 if...else if 来响应。
(3) 将迁移到哪个状态。在 s_play状态 (第7行) 接收到 stop 消息 (第8行)的话,将迁移到 s_stop 状态,即第10行。
(4) 在迁移中会做哪些动作,如果还是这个状态这个消息,会做的动作是 第11行,打印一段文字描述接下来的状态。
在函数 void state_change(enum message m) 中,维护了当前状态,规定了在某种状态下-接收到某个消息,会迁移到哪个状态,在状态迁移中做哪些动作。
主函数在调用state_change时,是通过这一接口,向状态机发送一个消息;由状态机对这个消息做出适合自己当前状态的响应--状态迁移、动作。主函数所看到的,是一个多彩或善变的女人,而她之所以对同一消息做出不同响应的原因,在她的内心深入保留着,那是她不会对你说的状态,以及状态迁移中的波澜壮阔。即使表面上善变的状态机,也是可以理解和预测的,如果她对你倘开心扉,允许你一行一行把附录A中的代码读完,了解所有的 switch-case,了解所有的状态下她将会如何响应每一种消息。
附录A 完整代码
1 #include &stdlib.h&
2 #include &stdio.h&
5 //recorder&
7 enum state { s_stop, s_play, s_forward, s_backward, s_pause, s_record &};
8 enum message { play, stop, forward, backward, record, pause };
11 void state_change(enum message m)
13 &static enum state s=s_
14 &switch (s)
16 case s_play:
17 & & if(m==stop)
18 & & & &{
20 & &printf(&stop.\n&); & & & &
21 & & & &}
22 & & & &else if (m==pause)
23 & & & &{
24 & & & & & & s = s_
25 printf(&pause&);
26 & & & &}
27 & & & &
28 case s_pause:
29 if(m==pause)
32 printf(&play.\n&); & & & &
34 else if(m==stop)
37 printf(&stop.\n&); & & & &
40 & & case s_stop:
41 if(m==play)
44 printf(&play.\n&); & & & &
46 if(m==backward)
49 printf(&backward.\n&); & & & &
51 if(m==forward)
54 printf(&forward.\n&); & & & &
56 if(m==record)
59 printf(&record.\n&); & & & &
62 case s_forward:
63 if(m==stop)
66 printf(&stop.\n&);&
69 case s_backward:
70 if(m==stop)
73 printf(&stop.\n&);&
76 case s_record:
77 if(m==stop)
80 printf(&stop.\n&);&
84 & & & &&
90 int main(int argc, char *argv[])
92 & & char c=0x00;
93 & & while(1)
95 & & & & c = getchar();
96 & & & & switch(c)
97 & & & & {
98 & & & & & & case ' ': state_change(pause);
99 & & & & & & case 'p': &state_change(play);
100 & & & & & & case 'r': state_change(record);
101 & & & & & & case 's': state_change(stop);
102 & & & & & & case 'f': state_change(forward);
103 & & & & & & case 'b': state_change(backward);
104 & & & & & & case 'q': & & return EXIT_SUCCESS;
105 & & & & }
107 & & & &&
110 & & return EXIT_SUCCESS;
附录B 状态图源代码 in graphviz
digraph state
graph [ nodesep=1.2];
rankdir = LR;
播放 -& 暂停 [label=&按下 || &];
暂停 -& 播放 [label=&按下 || &];
暂停 -& 停止 [label=&按下 []&];
停止 -& 播放 [label=&按下 &&];
播放 -& 停止 [label=&按下 []&];
停止 -& 快退 [label=&按下 &&&];
停止 -& 快进 [label=&按下 &&&];
快进 -& 停止 [label=&按下 []&];
快退 -& 停止 [label=&按下 []&];
停止 -& 录音 [label=&按下 O&];
录音 -& 停止 [label=&按下 []&];
--------------------
博客会手工同步到以下地址:
[http://blog.csdn.net/younggift]
=======================
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:459506次
积分:7845
积分:7845
排名:第1371名
原创:294篇
评论:684条moor 状态机和mealy状态机的区别是什么?_百度知道
moor 状态机和mealy状态机的区别是什么?
实现了输入与输出的分离moore状态机的输出只和当前状态有关,在一个时钟周期内,当前状态会根据不同输入而有不同输出,无论输入变化几次,输出之变化一次,还和当前的输入状态有关;mealy状态机的输出不仅和当前状态有关,次态不唯一,不与当前输入有关,也就是说当前状态的次态唯一
其他类似问题
为您推荐:
状态机的相关知识
其他1条回答
不给钱你还问
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁帐号:密码:下次自动登录{url:/nForum/slist.json?uid=guest&root=list-section}{url:/nForum/nlist.json?uid=guest&root=list-section}
贴数:10&分页:&发信人: gotolibing (计算所研究生), 信区: DCST.THU
标&&题: 请问:有限状态机和有限状态自动机的区别
发信站: 水木社区 (Tue Oct 12 15:17:47 2010), 站内 && 请问:有限状态机和有限状态自动机的区别
-- && ※ 来源:·水木社区 ·[FROM: 159.226.43.*]
&祝病魔早日战胜方老师发信人: GoldenBull (一小撮散布真相的群众), 信区: DCST.THU
标&&题: Re: 请问:有限状态机和有限状态自动机的区别
发信站: 水木社区 (Tue Oct 12 15:39:39 2010), 站内 && 名字不一样! && 【 在 gotolibing (计算所研究生) 的大作中提到: 】
: 请问:有限状态机和有限状态自动机的区别
1975:国民党反动派的头子、中国人民的公敌蒋介石,四月五日在台湾病死。蒋自从一九二
七年背叛民主革命以来,坚持反共反人民,独裁卖国。他双手沾满了中国革命人民的鲜血
1988:惊悉中国国民党主席蒋经国先生不幸逝世,深表哀悼,并向蒋经国先生的亲属表示诚
挚的慰问。
2003:宋美龄女士亲属:惊悉中国近现代史上有影响的知名人士宋美龄女士逝世,我谨代表
中国人民政治协商会议全国委员会表示深切哀悼,并向你们表示诚挚慰问。 &&&& ※ 来源:·水木社区 newsmth.net·[FROM: 210.51.183.*]
名不正则言承旭发信人: Tux9 (名不正则言承旭), 信区: DCST.THU
标&&题: Re: 请问:有限状态机和有限状态自动机的区别
发信站: 水木社区 (Tue Oct 12 16:10:33 2010), 站内 && 有限状态机包括有限状态手动机和有限状态自动机 && 【 在 gotolibing (计算所研究生) 的大作中提到: 】
: 标&&题: 请问:有限状态机和有限状态自动机的区别
: 发信站: 水木社区 (Tue Oct 12 15:17:47 2010), 站内
: 请问:有限状态机和有限状态自动机的区别
: ※ 来源:·水木社区 ·[FROM: 159.226.43.*]
&&&& -- &&lim&&f(x)=A&&&&&&&&&&&& lim&&g(x)=A&&&&&&&&&&&&f(x)&=h(x)&=g(x)
x-&∞&&&&&&&&&&&&&&&&&& x-&∞ && 则:&& lim&&h(x)=A &&&&&& x-&∞ &&&& ※ 来源:·水木社区 newsmth.net·[FROM: 166.111.64.*]
Roar发信人: roar9 (Roar), 信区: DCST.THU
标&&题: Re: 请问:有限状态机和有限状态自动机的区别
发信站: 水木社区 (Tue Oct 12 18:54:33 2010), 站内 && 请去看书或者google。
您要是个哲学系的研究生,告诉你也就罢了,因为这辈子您第二次肯定用不到。
但看样子您是有很大决心要好好学的,那么,这般问题还请看书解决比较好,因为基本问题还是记得扎实些好。 && 【 在 gotolibing (计算所研究生) 的大作中提到: 】
: 请问:有限状态机和有限状态自动机的区别
&& -- && ※ 来源:·水木社区 ·[FROM: 166.111.68.*]
朱弦一拂余音在,却是当时寂寞心发信人: meteorode (朱弦一拂余音在,却是当时寂寞心), 信区: DCST.THU
标&&题: Re: 请问:有限状态机和有限状态自动机的区别
发信站: 水木社区 (Tue Oct 12 21:02:25 2010), 站内 &&&&&&&&&& 那我们北大生物系的呢。
【 在 roar9 (Roar) 的大作中提到: 】
: 请去看书或者google。
: 您要是个哲学系的研究生,告诉你也就罢了,因为这辈子您第二次肯定用不到。
: 但看样子您是有很大决心要好好学的,那么,这般问题还请看书解决比较好,因为基本问题还是记得扎实些好。
: ...................
&& -- &&&&&&&& 但他们中的大多数都只是呆在这里,呆在这个拥有梦一样的天空、萤火虫的夜晚
和喧闹的黑人街市的慵懒的乐园里——这里尤其盛产落落大方的、柔声细语的少女,把她
们喂养大的不是金钱,而是回忆。 &&&& ※ 来源:·水木社区 newsmth.net·[FROM: 119.40.29.*]
新的声音发信人: FX9 (新的声音), 信区: DCST.THU
标&&题: Re: 请问:有限状态机和有限状态自动机的区别
发信站: 水木社区 (Tue Oct 12 23:11:37 2010), 站内 && 这个有区别么?我说他问的东西 && 【 在 roar9 (Roar) 的大作中提到: 】
: 请去看书或者google。
: 您要是个哲学系的研究生,告诉你也就罢了,因为这辈子您第二次肯定用不到。
: 但看样子您是有很大决心要好好学的,那么,这般问题还请看书解决比较好,因为基本问题还是记得扎实些好。
: ...................
&& -- && ※ 修改:·FX9 于 Oct 12 23:11:55 2010 修改本文·[FROM: 59.66.132.*]
※ 来源:·水木社区 newsmth.net·[FROM: 59.66.132.*]
omNiFic always pays his debts发信人: omNiFic (扶不上泥的滥强), 信区: DCST.THU
标&&题: Re: 请问:有限状态机和有限状态自动机的区别
发信站: 水木社区 (Wed Oct 13 03:42:06 2010), 站内 && 其实这东西大部分人一辈子都用不到第二次了吧
只要知道有自动机这么个东西就行了…… && 【 在 FX9 (新的声音) 的大作中提到: 】
: 这个有区别么?我说他问的东西
&&&& -- &&&&&&&&&&凍りつく時間の中を 崩れ堕ちるアルヴァレス&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&& &&&&&&&&&&&&&&&&パーシファルの雷槍が閃き 崩れ落ちるゲーフェンバウアー&&&&&&&& && &&&&&& &&&&それは…歴史の流れが変わる瞬間だろうか?&&&&&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&& それとも最初から全て決められていのだろうか… &&&&&& 「嗚呼…朱い…何て朱い夕陽なんだ…シャルロッテ…私は必ず…必ず帰って…」
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ———— 聖戦と死神 第四部 ~英雄の帰郷~&& &&&& ※ 来源:·水木社区 newsmth.net·[FROM: 129.10.110.*]
)(发信人: Apache9 ()(), 信区: DCST.THU
标&&题: Re: 请问:有限状态机和有限状态自动机的区别
发信站: 水木社区 (Wed Oct 13 09:28:11 2010), 站内 && 自动鸡嘛
【 在 omNiFic (扶不上泥的滥强) 的大作中提到: 】
: 其实这东西大部分人一辈子都用不到第二次了吧
: 只要知道有自动机这么个东西就行了……
&&&& -- && ※ 来源:·水木社区 newsmth.net·[FROM: 61.135.255.*]
祝病魔早日战胜方老师发信人: GoldenBull (一小撮散布真相的群众), 信区: DCST.THU
标&&题: Re: 请问:有限状态机和有限状态自动机的区别
发信站: 水木社区 (Wed Oct 13 13:38:09 2010), 站内 && 免费嘛? && 【 在 Apache9 ()() 的大作中提到: 】
: 自动鸡嘛
美方指责中国的互联网管理政策,影射中国限制互联网自由。对于这种违背事实、损
害中美关系的言行,我们坚决反对。中国互联网是开放的,中国也是互联网发展最活
跃的国家,到去年底,中国网民达3.84亿,网站达368万个,博客1.8亿。中国宪法保
护公民的言论自由,推动互联网的发展是我们的一贯政策。中国有自己的国情和文化
传统,中国对互联网坚持依法管理,符合世界通行做法。&& 【该评论已关闭】 &&&& ※ 来源:·水木社区 newsmth.net·[FROM: 210.51.183.*]
朱弦一拂余音在,却是当时寂寞心发信人: meteorode (朱弦一拂余音在,却是当时寂寞心), 信区: DCST.THU
标&&题: Re: 请问:有限状态机和有限状态自动机的区别
发信站: 水木社区 (Wed Oct 13 15:21:41 2010), 站内 &&&&&&&&&& 自动又不是敏感词!
【 在 GoldenBull (一小撮散布真相的群众) 的大作中提到: 】
: 免费嘛?
&&&& -- &&&&&&&& 谁这时没有房屋,就不必建筑, &&&&&&&& 谁这时孤独,就永远孤独, &&&&&&&& 就醒着,读着,写着长信, &&&&&&&& 在林荫道上来回 &&&&&&&& 不安地游荡,当着落叶纷飞。 &&&& ※ 来源:·水木社区 newsmth.net·[FROM: 220.194.19.*]
文章数:10&分页:
抽奖到手软!将狂欢进行到底!有限状态机和一堆counter有什么区别?
UID353886&帖子145&精华0&积分1107&资产1107 信元&发贴收入1055 信元&推广收入0 信元&附件收入0 信元&下载支出38 信元&阅读权限30&在线时间157 小时&注册时间&最后登录&
有限状态机和一堆counter有什么区别?
我用verilog实现了一个两层循环的算法,用伪代码就大概是:
for(i=1;i&11;i++)
& & for(j=1;j&11;j++)
& && && &a[i]=a[i]+b[j];
仿真结果是对的,也能综合,但是同组的人都说我没有“有限状态机”,很不专业,也没法写报告;
但是我自认为设计的还是有条理的:
(a 和 b 都是register 或者就是buffer,连RAM的访问都不用)
rst信号时,所有寄存器复位;
外来enable信号时,第1个a 寄存器开始存储b 寄存器的累加值,我用一个counter_b从0开始计b 的相加次数;
当counter_b==10的时候,counter_b归零开始重新算,下一轮的累加结果赋给下一个a 寄存器,counter_a加一;
当counter_a==10的时候,counter_a归零,ready信号从0到1向系统提示任务完成;
说白了就是由rst, enable, counter_a, counter_b来控制的。请问如何用FSM(有限状态机)来抽象出来描述?
关键就是要把控制信号全都放到一个模块里面,起名为FSM,写文章的时候比较好看。
UID747165&帖子246&精华0&积分42975&资产42975 信元&发贴收入1320 信元&推广收入0 信元&附件收入0 信元&下载支出26255 信元&阅读权限80&在线时间1797 小时&注册时间&最后登录&
在综合之前,能从代码直接看出电路的样子吗?你都给不出电路图,文章能好看吗?
当然你的这个东西两个always块就解决了,真的没必要用FSM(有限状态机,看来你也不知道FSM是什么)
UID859698&帖子302&精华0&积分18537&资产18537 信元&发贴收入1645 信元&推广收入0 信元&附件收入764 信元&下载支出1865 信元&阅读权限70&在线时间616 小时&注册时间&最后登录&
电路综合不提倡使用for语句,何况你这还是嵌套使用,至于原因,你可以自己查查
UID811574&帖子37&精华0&积分3481&资产3481 信元&发贴收入210 信元&推广收入0 信元&附件收入0 信元&下载支出2569 信元&阅读权限50&在线时间320 小时&注册时间&最后登录&
如3楼所说,现在综合工具对for的支持都不好,
UID523381&帖子101&精华0&积分58867&资产58867 信元&发贴收入515 信元&推广收入0 信元&附件收入0 信元&下载支出1283 信元&阅读权限90&在线时间780 小时&注册时间&最后登录&
楼上,lz已经说了那个是伪代码……
如果仅实现你说的循环累加,倒是真的没必要用状态机。没有周期要求的话,加法器&寄存器就够了,寄存器用来存放加法结果并返回至加法器输入端。
很多情况下状态机的描述会更清晰,但并不是说一定要用状态机,找到合适的方法即可。
UID998883&帖子180&精华0&积分1105&资产1105 信元&发贴收入1055 信元&推广收入0 信元&附件收入630 信元&下载支出840 信元&阅读权限30&在线时间246 小时&注册时间&最后登录&
你们组都是高人啊,只是一个加法,用什么状态机啊;
UID781270&帖子188&精华0&积分859&资产859 信元&发贴收入985 信元&推广收入0 信元&附件收入0 信元&下载支出2554 信元&阅读权限30&在线时间350 小时&注册时间&最后登录&
状态机只是节省了状态转换的条件 比如一个always使能拧一个always
所以只要是时序电路 可以用状态机也可以不用状态机,也并不是状态机一定好用 看使用环境的
UID25272&帖子23&精华0&积分4&资产4 信元&发贴收入100 信元&推广收入0 信元&附件收入0 信元&下载支出244 信元&阅读权限10&在线时间1 小时&注册时间&最后登录&
状态机有一段式、两端式、三段式。
UID232806&帖子226&精华0&积分3394&资产3394 信元&发贴收入1175 信元&推广收入0 信元&附件收入0 信元&下载支出1061 信元&阅读权限50&在线时间148 小时&注册时间&最后登录&
如果用到状态控制,当然是状态机比较好。但也不用乱用。
FOR语句用在综合,主要是因为它是组会逻辑,时序比较难收敛(除非你的设计只跑几兆)。
[通过 QQ、MSN 分享给朋友]【转】关于状态机 一段式 二段式 三段式 - 仰望苍穹 - 中国电子顶级开发网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台
- Powered by X-Space
【转】关于状态机 一段式 二段式 三段式
& 13:44:03
/ 个人分类:
关于状态机 一段式 二段式 三段式 (网上资料搜集)对于自认很有软件编程经验的我,初识状态机,觉得没什么大不了的,实现起来没什么难度,
初学FPGA时学的是verilog, 看夏宇闻的书上状态机的例子使用的一段式,当然他没有说明这种写法是一段式,当时觉得挺简单明了.
后来用VHDL, 看的一本E文的书上, 状态机的例子是典型的二段式(作者也没说明这是两段式),当时还觉得这种写法挺麻烦的,没有一段式的看起来舒服, 当时还没有切身的体会两种的区别以及一段式的劣处.
后来在一段式状态机上吃了亏, 才想到去重新思考和认识状态机,才知道了一段式 二段式 三段式的概念.
关于详细地概念,我就不复述了,看两篇网上转载的文章就可以了:
Verilog三段式状态机描述(转载)
时序电路的状态是一个状态变量集合,这些状态变量在任意时刻的值都包含了为确定电路的未来行为而必需考虑的所有历史信息。
状态机采用VerilogHDL语言编码,建议分为三个always段完成。
三段式建模描述FSM的状态机输出时,只需指定case敏感表为次态寄存器,&然后直接在每个次态的case分支中描述该状态的输出即可,不用考虑状态转移条件。
三段式描述方法虽然代码结构复杂了一些,但是换来的优势是:使FSM做到了同步寄存器输出,消除了组合逻辑输出的不稳定与毛刺的隐患,而且更利于时序路径分组,一般来说在FPGA/CPLD等可编程逻辑器件上的综合与布局布线效果更佳。
示列如下:
//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
always @ (posedge clk or negedge
rst_n)&&&&//异步复位
&if(!rst_n)
&& current_state &= IDLE;
&& current_state &=
next_&&&//注意,使用的是非阻塞赋值
//第二个进程,组合逻辑always模块,描述状态转移条件判断
(current_state)&&&&&&&&//电平触发
&&& next_state =
x;&&//要初始化,使得系统复位后能进入正确的状态
&&& case(current_state)
&&& S1: if(...)
next_state =
S2;&&&&&&&&&&&//阻塞赋值
&&& endcase
//第三个进程,同步时序always模块,格式化描述次态寄存器输出
always @ (posedge clk or negedge rst_n)
...//初始化
&case(next_state)
&& out1 &=
1'b1;&&&&&&&&&&&&&&&&//注意是非阻塞逻辑
&& out2 &= 1'b1;
default:...&&&&&&//default的作用是免除综合工具综合出锁存器
两段式有限状态机与三段式有限状态机的区别
FSM将时序部分(状态转移部分)和组合部分(判断状态转移条件和产生输出)分开,写为两个always语句,即为两段式有限状态机。
  将组合部分中的判断状态转移条件和产生输入再分开写,则为三段式有限状态机。
  区别:
  二段式在组合逻辑特别复杂时适用,但要注意需在后面加一个触发器以消除组合逻辑对输出产生的毛刺。三段式没有这个问题,由于第三个always会生成触发器。
  设计时注意方面:
  1.编码原则,binary和gray-code适用于触发器资源较少,组合电路资源丰富的情况(CPLD),对于FPGA,适用one-hot code。这样不但充分利用FPGA丰富的触发器资源,还因为只需比较一个bit,速度快,组合电路简单。
  2.FSM初始化问题:
  GSR(Gobal Set/Reset)只是在加电时清零所有的reg和片内ram,并不保证FSM能进入初始化状态,要利用GSR,方案是适用one-hot code with zero idle,即初始状态编码为全零。已可以适用异步复位rst
  3.FSM输出可以适用task
  4FSM中的case最好加上default,默认态可以设为初始态
  5.尤其注意:
  第二段的always(组合部分,赋值用=)里面判断条件一定要包含所有情况!可以用else保证包含完全。
  6第二段always中,组合逻辑电平要维持超过一个clock,仿真时注意。
以前看了不少关于如何写VDHL状态机的文章,都是提倡使用二段式或三段式的写法,都建议避免使用一段式的写法,但看了之后,都没什么体会。象我们写软件出身的,心理上总喜欢一段式的写法,觉得思路比较连贯,而且可以写在一个process里,“内聚性”比较高。软件工程师是最讨厌多个函数共用全局变量的了。
&&&&&&& 但对于硬件开发,就不一样了。因为VHDL还是无法完全屏蔽掉硬件的物理特性,不好的布局,会使得写的逻辑错误执行。最近写的一个状态机,就遇到了这个麻烦。因为喜好的缘故,加上状态机里面有计数器,用组合逻辑写比较麻烦,于是我用了一段式的写法。结果实际运行的时候,发现状态机经常无故锁死,用逻辑分析仪看,发现陷入了非法的状态,而且when others语句也无法使状态机回到IDLE状态。开始怀疑逻辑上有错误,折腾几天后,把状态切换部分独立出来放在一个同步process里,问题解决了。虽然偶尔还会发现落入非法状态,但状态机会自动恢复到初始状态,不会锁死了,而程序逻辑没有做如何修改。看来以后还是得规规矩矩用二段或三段式的写法了。为了便于记忆,把二段、三段式的特点终结成几句话:
&&&&&&& 二段式:状态切换用时序逻辑,次态输出和信号输出用组合逻辑。
&&&&&&& 三段式:状态切换用时序逻辑,次态输出用组合逻辑,信号输出用时序逻辑。信号输出的process中,case语句用next state做条件,可以解决比组合逻辑输出慢一拍的问题。
有时候判断次态需要用到计数器怎么办呢(计数器是时序电路,用组合逻辑是实现不了的)?方法是独立实现一个计数器,而在组合逻辑里用使能信号(或清除、置位等)来控制它。
这最后一篇文章已经把 一段式 二段式 <span style="font-size:12.0
font-family:宋体;mso-ascii-font-family:Amso-hansi-font-family:A
mso-bidi-font-family:Acolor:#333333;mso-font-kerning:0}

我要回帖

更多关于 结构化分析方法是面向 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信