狀態機FSM

狀 態機簡寫爲FSM(Finite State Machine),主要分爲2大類:第一類,若輸出只和狀態有關而與輸入無關,則稱爲Moore狀態機;第二類,輸出不只和狀態有關並且和輸入有關係,則 稱爲Mealy狀態機。要特別注意的是,由於Mealy狀態機和輸入有關,輸出會受到輸入的干擾,因此可能會產生毛刺(Glitch)現象,使用時應當注 意。事實上如今市面上有不少EDA工具能夠很方便的將 狀態圖的描述轉換成能夠綜合的VHDL程序代碼
中文名
狀態機
外文名
Finite State Machine)
縮    寫
FSM
又    名
狀態轉移圖

1基本信息編輯

就 是狀態轉移圖。舉個最簡單的例子。人有三個狀態健康,感冒,康復中。觸發的條件有淋雨(t1),吃藥(t2),打針(t3),休息(t4)。因此狀態機就 是健康-(t3)->健康;健康-(t1)->感冒;感冒-(t3)->健康;感冒-(t2)->康復中;康復中 -(t4)->健康,等等。就是這樣狀態在不一樣的條件下跳轉到本身或不一樣狀態的圖。

2狀態機綜述編輯

關 於狀態機的一個極度確切的描述是它是一個有向圖形,由一組節點和一組相應的轉移函數組成。狀態機經過響應一系列事件而「運行」。每一個事件都在屬於「當前」 節點的轉移函數的控制範圍內,其中函數的範圍是節點的一個子集。函數返回「下一個」(也許是同一個)節點。這些節點中至少有一個必須是終態。當到達終態, 狀態機中止。
包含一組狀態集(states)、一個起始狀態(start state)、一組輸入符號集(alphabet)、一個 映射輸入符號和當前狀態到下一狀態的轉換函數(transition function)的計算模型。當輸入符號串,模型隨即進入起始狀態。它要改變到新的狀態,依賴於轉換函數。在有限狀態機中,會有有許多 變量,例如,狀態 機有不少與動做(actions)轉換( Mealy機)或狀態( 摩爾機)關聯的動做,多重起始狀態,基於沒有輸入符號的轉換,或者指定符號和狀態(非定有 限狀態機)的多個轉換,指派給接收狀態(識別者)的一個或多個狀態,等等。
傳統 應用程序的控制流程基本是順序的:遵循事先設定的邏輯,從頭至尾地執行。不多有事件能改變標準執行流程;並且這些事件主要涉及異常狀況。「命令行實用程序」是這種傳統 應用程序的典型例子。
另外一類 應用程序由外部發生的事件來驅動——換言之,事件在應用程序以外生成,沒法由應用程序或程序員來控制。具體須要執行的代碼取決於接收到的事件,或者它 相對於其餘事件的抵達時間。因此,控制流程既不能是順序的,也不能是事先設定好的,由於它要依賴於外部事件。 事件驅動的GUI 應用程序是這種應用程序的典 型例子,它們由命令和選擇(也就是用戶形成的事件)來驅動。
Web 應用程序由提交的 表單和用戶請求的網頁來驅動,它們也可劃歸到上述類別。可是,GUI 應用程序對於接收到的事件仍有必定程度的控制,由於這些事件要依賴於向用戶顯示的窗口和控件,而窗口和控件是由 程序員控制的。Web應用 程序則否則,由於一旦用戶採起不在預料之中的操做(好比使用 瀏覽器的歷史記錄、手工輸入連接以及模擬一次 表單提交等等),就很容易打亂設計好的 應用程序邏輯。
顯然,必須採起不一樣的技術來處理這些狀況。它能處理任何順序的事件,並能提供有意義的響應——即便這些事件發生的順序和預計的不一樣。有限狀態機正是爲了知足這方面的要求而設計的。
有限狀態機是一種概念性機器,它能採起某種操做來響應一個外部事件。具體採起的操做不只能取決於接收到的事件,還能 取決於各個事件的相對發生順序。之因此能 作到這一點,是由於機器能跟蹤一個內部狀態,它會在收到事件後進行更新。爲一個事件而響應的行動不只取決於事件自己,還取決於機器的內部狀態。另外,採起 的行動還會決定並更新機器的狀態。這樣一來,任何邏輯均可 建模成一系列事件/狀態組合。
[1] 狀態機可概括爲4個要素,即現態、條件、動做、次態。這樣的概括,主要是出於對狀態機的內在因果關係的考慮。「現態」和「條件」是因,「動做」和「次態」是果。詳解以下:
①現態:是指當前所處的狀態。
②條件:又稱爲「事件」,當一個條件被知足,將會觸發一個動做,或者執行一次狀態的遷移。
③動做:條件知足後執行的動做。動做執行完畢後,能夠遷移到新的狀態,也能夠仍舊保持原狀態。動做不是必需的,當條件知足後,也能夠不執行任何動做,直接遷移到新狀態。
④次態:條件知足後要遷往的新狀態。「次態」是相對於「現態」而言的,「次態」一旦被激活,就轉變成新的「現態」了。

3兩種寫法編輯

有限狀態機FSM

思 想普遍應用於硬件控制電路設計,也是軟件上經常使用的一種處理方法(軟 件上稱爲FMM--有限消息機)。它把複雜的控制邏輯分解成有限個穩定狀態,在每一個狀態上判斷事件,變連續處理爲離散數字處理,符合計算機的工做特色。同 時,由於有限狀態機具備有限個狀態,因此能夠在實際的工程上實現。但這並不意味着其只能進行有限次的處理,相反,有限狀態機是閉環系統,有限無窮,能夠用 有限的狀態,處理無窮的事務。
有限狀態機的工做原理如圖1所示,發生事件(event)後,根據當前狀態(cur_state) ,決定執行的動做(action),並設置下一個狀態號(nxt_state)。
-------------
| |-------->執行動做action
發生事件event ----->| cur_state |
| |-------->設置下一狀態號nxt_state
-------------
當前狀態
圖1 有限狀態機工做原理
e0/a0
--->--
| |
-------->----------
e0/a0 | | S0 |-----
| -<------------ | e1/a1
| | e2/a2 V
---------- ----------
| S2 |-----<-----| S1 |
---------- e2/a2 ----------
圖2 一個有限狀態機實例
--------------------------------------------
當前狀態 s0 s1 s2 | 事件
--------------------------------------------
a0/s0 -- a0/s0 | e0
--------------------------------------------
a1/s1 -- -- | e1
--------------------------------------------
a2/s2 a2/s2 -- | e2
--------------------------------------------
表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可知,狀態機能夠用兩種方法實現:豎着寫(在狀態中判斷事件)和橫着寫( 在事件中判斷狀態)。這兩種實如今本質上是徹底等效的,但在實際操做中,效果卻截然 不一樣。

豎着寫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;
}
}
橫着寫(在事件中判斷狀態)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;
}
}

4其它編輯

Moore狀態機

其Moore 狀態圖如圖1所示。
S0/0S1/1S3/0S2/100110011
其中S0/0所表明的意思爲如今是狀態S0且輸出爲0, 狀態圖最主要是將每一個狀態都給予一個編號,詳細描述以下:
1) 在某狀態時,列出全部的輸出條件。
2) 在某狀態時,當輸入信號是什麼則會跳至哪個狀態。
3) 在某狀態時,當輸入信號是什麼則會維持原狀態不變。
能夠將圖1的Moore狀態機寫成狀態表如表1.
表1 Moore狀態表
現態
次態
輸出
輸入
X=0
X=1 X=0 X=1
S0
S0
S1
0
0
S1
S1
S2
1
1
S2
S3
S0
0
0
S3
S0
S3
0
0
狀態表主要描述它與 狀態圖的關係,再設計狀態機電路是,須要先定義狀態機的 變量,定義狀態機的變量時使用枚舉類型來定義,以下範例所示:
Type State is (S0,S1,S2,S3)
接下來,狀態會被加以編碼。其狀態編碼方式以下:
(1) 時序編碼(Sequential)
將每一個狀態以二進制來作編碼。
(2) 格雷碼(Gray)
也是將四個State以二進制來編碼,不過不一樣的是每次編碼只會差一個位,其主要缺點是狀態改變是要依序改變才能夠,若狀態不是依序是,則Gray編碼不適用。
(3) 獨熱碼(One hot)
獨熱碼狀態編碼的特點爲每個狀態均有本身的觸發器,因此如有N個狀態就也存在有N個觸發器,在任一時刻只會有一組狀態編碼,缺點是會產生較大的電路,可是相對的使用獨熱碼狀態編碼對幀錯至關有幫助。
三種格式之狀態編碼如表2所示。
狀態
時序編碼
Gray編碼
One hot編碼
S0
00
00
0001
S1
01
01
0010
S2
10
11
0100
S3
11
10
1000
從狀態編碼表能夠看出時序編碼和Gray編碼均是用二個位來作編碼,而以獨熱碼做爲編碼方式則編碼位增長至四個位,因此電路比其餘兩種編碼方式都大一些。
因此可使用屬性來定義編碼方式,若要編碼成獨熱碼編碼,則可加上:
Type State is (S0,S1,S2,S3);
Attribute encoding of state;
Type is 「0001 0010 0100 1000」;
在設計狀態機時,一般使用進程語句來描述狀態機,其中進程語句又能夠分爲三種方式:
n 一個進程
利用一個進程來描述狀態的轉換及輸出信號的定義。
n 兩個進程
一個爲時序電路主要負責狀態變量的更新,此進程爲同步電路,而另外一個進程語句主要是描述下次態變量和輸出的更新。
n 三個進程
第一個進程主要負責狀態變量的更新,第二個進程語句負責描述次態變量,而最後一個則是負責輸出信號的更新。
有了以上的初步觀念,能夠設計圖1四個狀態的Moore狀態機。

範例

首先根據以前的狀態表編寫VHDL程序以下所示:
Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;
Entity moore_fsm is
Port(
clk : in std_logic;
rstn : in std_logic;
x : in std_logic;
output : out std_logic
);
End moore_fsm;
Architecture rtl of moore_fsm is
Type state is (s0,s1,s2,s3); ---狀態定義
Signal current_state : state; ---現態
Signal next_state : state; ---次態
Begin
Statefsm: process(rstn, x, current_state)
Begin
If rstn = ‘0’ then --異步reset
next_state <= s0;
output <= ‘0’;
else
case current_state is
when s0 =>
if x =’0’ then
next_state <= s0;
else
next_state <= s1;
end if;
output <= ‘0’;
when s1 =>
if x =’0’ then
next_state <= s1;
else
next_state <= s2;
end if;
output <= ‘1’;
when s2 =>
if x =’0’ then
next_state <= s3;
else
next_state <= s0;
end if;
output <= ‘0’;
when s3 =>
if x =’0’ then
next_state <= s0;
else
next_state <= s3;
end if;
output <= ‘0’;
end case;
end if;
end process statefsm;
stat: process(clk) --current_stateànext_state
begin
if rising_edge (clk) then
current_state <=next_state;
end if;
end process stat;
end rtl;
1) 編碼方式預設爲時序編碼
2) 使用兩個進程語句來設計狀態機
其綜合電路如圖2 所示。
狀態圖如圖3 所示。
Moore FSM 模擬波形如圖4 所示。
模擬結果說明:
(1) 因爲reset 爲異步reset ,因此當reset在150ns~200ns爲0時,則 狀態圖會從s1回到s0.
(2) 在50 ns時輸入x爲0且現態爲1,在70 ns 時clk上升沿觸發且x爲1,則current_state會變成next_state s2;

Mealy狀態機

接下來咱們要介紹Mealy狀態機,它和輸入、輸出、狀態皆有關。它的 狀態圖、狀態表與Moore狀態機都有所不一樣,輸出會隨輸入變化而變化。如圖5 所示。
0/0
圖5:
S0S1S3S20/11/10/10/01/11/0 1/0
若現態爲s0輸入爲0時,則次態爲s0且輸出爲0;若現態爲s0輸入爲1時,則次態爲s1且輸出爲1。
根據這個規則,列出Mealy狀態機的狀態表如表3。
現太
次態
 輸出
輸入
X=0
X=1
X=0
X=1
S0
S0
S1
0
1
S1
S2
S1
1
0
S2
S3
S0
0
1
S3
S0
S3
1
0
其Mealy狀態機的VHDL以下所示:
Library ieee;
Use ieee.std_logic_1164.all;
Use ieee.numeric_std.all;
Entity melay_fsm is
Port(
clk: : in std_logic;
rstn : in std_logic;
x : in std_logic;
output : out std_logic
);
End moore_fsm;
Architecture rtl of moore_fsm is
Type state is (s0,s1,s2,s3); ---狀態定義
Signal current_state : state; ---現態
Signal next_state : state; ---次態
Begin
Statefsm: process(rstn, x, current_state)
Begin
If rstn = ‘0’ then --異步reset
next_state <= s0;
output <= ‘0’;
else
case current_state is
when s0 =>
if x =’0’ then
next_state <= s0;
else
next_state <= s1;
end if;
if x= ‘0’ then
output <= ‘0’;
else
output <= ‘1’;
end if;
when s1 =>
if x =’0’ then
next_state <= s2;
else
next_state <= s1;
end if;
if x= ‘0’ then
output <= ‘1’;
else
output <= ‘0’;
end if;
when s2 =>
if x =’0’ then
next_state <= s3;
else
next_state <= s0;
end if;
if x= ‘0’ then
output <= ‘0’;
else
output <= ‘1’;
end if;
when s3 =>
if x =’0’ then
next_state <= s0;
else
next_state <= s3;
end if;
if x= ‘0’ then
output <= ‘1’;
else
output <= ‘0’;
end if;
end case;
end if;
end process statefsm;
stat: process(clk) --current_stateànext_state
begin
if prsing_edge (clk) then
current_state <=next_state;
end if;
end process stat;
end rtl;
Mealy狀態機綜合電路如圖6 所示。
相關文章
相關標籤/搜索