沈陽網(wǎng)站seo排名優(yōu)化愛網(wǎng)站關(guān)鍵詞查詢工具
FPGA_狀態(tài)機介紹和工作原理
- 狀態(tài)機工作原理
- Mealy 狀態(tài)機模型
- Moore 狀態(tài)機模型
- 狀態(tài)機描述方式
- 代碼格式
- 總結(jié)
狀態(tài)機工作原理
狀態(tài)機全稱是有限狀態(tài)機(Finite State Machine、FSM),是表示有限個狀態(tài)以及在這些狀態(tài)之間的轉(zhuǎn)移和動作等行為的數(shù)學(xué)模型。
狀態(tài)機分為摩爾(Moore)型有限狀態(tài)機與米利(Mealy)型有限狀態(tài)機。摩爾狀態(tài)機輸出是只由輸入確定的有限狀態(tài)機(不直接依賴于當(dāng)前狀態(tài))。米利有限狀態(tài)機的輸出不止與其輸入有關(guān)還于它的當(dāng)前狀態(tài)相關(guān),這也是與摩爾有限狀態(tài)機的不同之處。
? Mealy 狀態(tài)機:組合邏輯的輸出不僅取決于當(dāng)前狀態(tài),還取決于輸入狀態(tài)。
? Moore 狀態(tài)機:組合邏輯的輸出只取決于當(dāng)前狀態(tài)。
Mealy 狀態(tài)機模型
Moore 狀態(tài)機模型
狀態(tài)機描述方式
可分為一段式、兩段式以及三段式。
一段式,整個狀態(tài)機寫到一個 always 模塊里面。在該模塊中既描述狀態(tài)轉(zhuǎn)移,又描述狀態(tài)的輸入和輸出。
兩段式,用兩個 always 模塊來描述狀態(tài)機。其中一個 always 模塊采用同步時序描述狀態(tài)轉(zhuǎn)移,另一個模塊采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件,描述狀態(tài)轉(zhuǎn)移規(guī)律及其輸出。
三段式,在兩個 always 模塊描述方法基礎(chǔ)上,使用三個 always 模塊,一個 always 模塊采用同步時序描述狀態(tài)轉(zhuǎn)移,一個 always 采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件,描述狀態(tài)轉(zhuǎn)移規(guī)律,另一個 always 模塊描述狀態(tài)輸出(可以用組合電路輸出,也可以時序電路輸出)。實際應(yīng)用中三段式狀態(tài)機使用最多,因為三段式狀態(tài)機將組合邏輯和時序分開,有利于綜合器分析優(yōu)化以及程序的維護;并且三段式狀態(tài)機將狀態(tài)轉(zhuǎn)移與狀態(tài)輸出分開,使代碼看上去更加清晰易懂,提高了代碼的可讀性,推薦大家使用三段式狀態(tài)機,本文也著重講解三段式。
三段式狀態(tài)機的基本格式是:
第一個 always 語句實現(xiàn)同步狀態(tài)跳轉(zhuǎn);
第二個 always 語句采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件;
第三個 always 語句描述狀態(tài)輸出(可以用組合電路輸出,也可以時序電路輸出)。在開始編寫狀態(tài)機代碼之前,一般先畫出狀態(tài)跳轉(zhuǎn)圖,這樣在編寫代碼時思路會比較清晰,下面以一個 7 分頻為例(對于分頻等較簡單的功能,可以不使用狀態(tài)機,這里只是演示狀態(tài)機編寫的方法),狀態(tài)跳轉(zhuǎn)圖如下圖所示:
代碼格式
狀態(tài)跳轉(zhuǎn)圖畫完之后,接下來通過 parameter 來定義各個不同狀態(tài)的參數(shù),如下
parameter S0 = 7'b0000001; //獨熱碼定義方式
parameter S1 = 7'b0000010;
parameter S2 = 7'b0000100;
parameter S3 = 7'b0001000;
parameter S4 = 7'b0010000;
parameter S5 = 7'b0100000;
parameter S6 = 7'b1000000;
這里是使用獨熱碼的方式來定義狀態(tài)機
接下來還需要定義兩個 7 位的寄存器,一個用來表示當(dāng)前狀態(tài),另一個用來表示下一個狀態(tài),如下所示:
reg [6:0] curr_st ; //當(dāng)前狀態(tài)
reg [6:0] next_st ; //下一個狀態(tài)
接下來就可以使用三個 always 語句來開始編寫狀態(tài)機的代碼,第一個 always 采用同步時序描述狀態(tài)
轉(zhuǎn)移,第二個 always 采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件,第三個 always 是描述狀態(tài)輸出,一個完整的三段
式狀態(tài)機的例子如下代碼所示:
module divider7_fsm (
//系統(tǒng)時鐘與復(fù)位
input sys_clk ,
input sys_rst_n ,//輸出時鐘
output reg clk_divide_7
);//parameter define parameter S0 = 7'b0000001; //獨熱碼定義方式parameter S1 = 7'b0000010;parameter S2 = 7'b0000100;parameter S3 = 7'b0001000;parameter S4 = 7'b0010000;parameter S5 = 7'b0100000;parameter S6 = 7'b1000000; //reg define reg [6:0] curr_st ; //當(dāng)前狀態(tài)reg [6:0] next_st ; //下一個狀態(tài)//*****************************************************//** main code//***************************************************** //狀態(tài)機的第一段采用同步時序描述狀態(tài)轉(zhuǎn)移always @(posedge sys_clk or negedge sys_rst_n) beginif (!sys_rst_n)curr_st <= S0;elsecurr_st <= next_st;end//狀態(tài)機的第二段采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件always @(*) begincase (curr_st)S0: next_st = S1;S1: next_st = S2;S2: next_st = S3;S3: next_st = S4;S4: next_st = S5;S5: next_st = S6;S6: next_st = S0;default: next_st = S0;endcaseend//狀態(tài)機的第三段描述狀態(tài)輸出(這里采用時序電路輸出)always @(posedge sys_clk or negedge sys_rst_n) beginif (!sys_rst_n)clk_divide_7 <= 1'b0;else if ((curr_st == S0) | (curr_st == S1) | (curr_st == S2) | (curr_st == S3))clk_divide_7 <= 1'b0;else if ((curr_st == S4) | (curr_st == S5) | (curr_st == S6))clk_divide_7 <= 1'b1; else;endendmodule
總結(jié)
從代碼中可以看出,輸出的分頻時鐘 clk_divide_7 只與當(dāng)前狀態(tài)(curr_st)有關(guān),而與輸入狀態(tài)無關(guān),所以屬于摩爾型狀態(tài)機。狀態(tài)機的第一段對應(yīng)摩爾狀態(tài)機模型的狀態(tài)寄存器,用來記憶狀態(tài)機當(dāng)前所處的狀態(tài);狀態(tài)機的第二段對應(yīng)摩爾狀態(tài)機模型產(chǎn)生下一狀態(tài)的組合邏輯 F;狀態(tài)機的第三段對應(yīng)摩爾狀態(tài)機產(chǎn)生輸出的組合邏輯 G,因為采用時序電路輸出有很大的優(yōu)勢,所以這里第三段狀態(tài)機是由時序電路
輸出的。
狀態(tài)機時序電路輸出模型
采用這種描述方法雖然代碼結(jié)構(gòu)復(fù)雜了一些,但是這樣做的好處是可以有效地濾去組合邏輯輸出的毛刺,同時也可以更好的進行時序計算與約束,另外對于總線形式的輸出信號來說,容易使總線數(shù)據(jù)對齊,減小總線數(shù)據(jù)間的偏移,從而降低接收端數(shù)據(jù)采樣出錯的頻率。