徹底搞懂狀態機(一段式、兩段式、三段式)


實例:FSM實現10010串的檢測

狀態轉移圖:初始狀態S0,a = 0,z = 0.如果檢測到1,跳轉到S1。

            下一狀態S1,a = 1,z = 0.如果檢測到0,跳轉到S2。
            下一狀態S2,a = 0,z = 0.如果檢測到0,跳轉到S3。
            下一狀態S3,a = 0,z = 0.如果檢測到1,跳轉到S4。
            下一狀態S4,a = 1,z = 0.如果檢測到0,跳轉到S5。
            下一狀態S5,a = 0,z = 1.如果檢測到1,跳轉到S1;如果檢測到0,跳轉到S3(因為之前S4已經是1,S5是0,若再檢測到0,就是100,因此跳轉到S4)。

 

程序中將一段式(one_fsm)、兩段式(two_fsm)、三段式(three_fsm)以及對應的仿真文件(XXX_tb)包含在了一個工程中。要單獨運行、仿真每一種方式,只需將他們(one_fsm.v、two_fsm.v、three_fsm.v)分別設為頂層文件(選中右擊,然后選擇Set as Top-Level Entity),然后在仿真設置里面選擇對應的仿真文件即可。見下圖:

 

補充:(轉)PART1

1、好的狀態機標准

好的狀態機的標准很多,最重要的幾個方面如下:

第一,狀態機要安全,是指FSM不會進入死循環,特別是不會進入非預知的狀態,而且由於某些擾動進入非設計狀態,也能很快的恢復到正常的狀態循環中來。這里面有兩層含義:其一要求該FSM的綜合實現結果無毛刺等異常擾動;其二要求FSM要完備,即使受到異常擾動進入非設計狀態,也能很快恢復到正常狀態。

第二,狀態機的設計要滿足設計的面積和速度的要求。

第三,狀態機的設計要清晰易懂、易維護。

 

2、狀態機描述方法

狀態機描述時關鍵是要描述清楚幾個狀態機的要素,即如何進行狀態轉移,每個狀態的輸出是什么,狀態轉移的條件等。具體描述時方法各種各樣,最常見的有三種描述方式:

(1)一段式:整個狀態機寫到一個always模塊里面,在該模塊中既描述狀態轉移,又描述狀態的輸入和輸出;

(2)二段式:用兩個always模塊來描述狀態機,其中一個always模塊采用同步時序描述狀態轉移;另一個模塊采用組合邏輯判斷狀態轉移條件,描述狀態轉移規律以及輸出;

(3)三段式:在兩個always模塊描述方法基礎上,使用三個always模塊,一個always模塊采用同步時序描述狀態轉移,一個always采用組合邏輯判斷狀態轉移條件,描述狀態轉移規律,另一個always模塊描述狀態輸出(可以用組合電路輸出,也可以時序電路輸出)。

 

一般而言,推薦的FSM 描述方法是后兩種。這是因為:FSM和其他設計一樣,最好使用同步時序方式設計,以提高設計的穩定性,消除毛刺。狀態機實現后,一般來說,狀態轉移部分是同步時序電路而狀態的轉移條件的判斷是組合邏輯。

 

第二種描述方法同第一種描述方法相比,將同步時序和組合邏輯分別放到不同的always模塊中實現,這樣做的好處不僅僅是便於閱讀、理解、維護,更重要的是利於綜合器優化代碼,利於用戶添加合適的時序約束條件,利於布局布線器實現設計。

在第二種方式的描述中,描述當前狀態的輸出用組合邏輯實現,組合邏輯很容易產生毛刺,而且不利於約束,不利於綜合器和布局布線器實現高性能的設計。

第三種描述方式與第二種相比,關鍵在於根據狀態轉移規律,在上一狀態根據輸入條件判斷出當前狀態的輸出,從而在不插入額外時鍾節拍的前提下,實現了寄存器輸出。

 

PART2

時序電路的狀態是一個狀態變量集合,這些狀態變量在任意時刻的值都包含了為確定電路的未來行為而必需考慮的所有歷史信息。

狀態機采用VerilogHDL語言編碼,建議分為三個always段完成。

 

三段式建模描述FSM的狀態機輸出時,只需指定case敏感表為次態寄存器,然后直接在每個次態的case分支中描述該狀態的輸出即可,不用考慮狀態轉移條件。

三段式描述方法雖然代碼結構復雜了一些,但是換來的優勢是:使FSM做到了同步寄存器輸出,消除了組合邏輯輸出的不穩定與毛刺的隱患,而且更利於時序路徑分組,一般來說在FPGA/CPLD等可編程邏輯器件上的綜合與布局布線效果更佳。

示列模板如下:

//第一個進程,同步時序always模塊,格式化描述次態寄存器遷移到現態寄存器

always @ (posedge clk or negedge rst_n) //異步復位

if(!rst_n)

current_state <= IDLE;

else

current_state <= next_state; //注意,使用的是非阻塞賦值

//第二個進程,組合邏輯always模塊,描述狀態轉移條件判斷

always @ (current_state) //電平觸發

begin

next_state = x; //要初始化,使得系統復位后能進入正確的狀態

case(current_state)

S1: if(...)

next_state = S2; //阻塞賦值

...

endcase

end

//第三個進程,同步時序always模塊,格式化描述次態寄存器輸出

always @ (posedge clk or negedge rst_n)

...//初始化

case(next_state)

S1:

out1 <= 1'b1; //注意是非阻塞邏輯

S2:

out2 <= 1'b1;

default:... //default的作用是免除綜合工具綜合出鎖存器

endcase

end

兩段式有限狀態機與三段式有限狀態機的區別

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,仿真時注意。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM