Verilog -- 狀態機
參考:
https://blog.csdn.net/woshiyuzhoushizhe/article/details/95866063
https://blog.csdn.net/qq_34070723/article/details/100737225
https://www.cnblogs.com/flyuea/p/8421939.html
MOORE 與 MEALEY 狀態機的特征?
Moore 狀態機的輸出僅與當前狀態值有關, 且只在時鍾邊沿到來時才會有狀態變化。次態=f(現狀,輸入),輸出=f(現狀)
Mealy 狀態機的輸出不僅與當前狀態值有關, 而且與當前輸入值有關。次態=f(現狀,輸入),輸出=f(現狀,輸入)
描述同一個事務,mealy的狀態更少。
一段式狀態機
一段式狀態機:一段式狀態機只選擇一個狀態標志位,這個狀態標志位會在輸入的決定下選擇跳轉到下一個狀態還是維持原有狀態,在每一個狀態下檢測狀態標志位及輸入來決定其狀態的跳轉及輸出。其輸出和狀態的切換在一個always循環塊中執行。
示例:
always @ (posedge clk) begin
case(FSM)
S0: begin
out<= ...;//輸出
if(in...) FSM<=S1;//狀態轉移
else FSM <= S0;
end
S1: begin
out<= ...;//輸出
if(in...) FSM<=S2;//狀態轉移
else FSM <= S1;
end
...
default:
endcase
end
優點:
- 單always塊把組合邏輯和時序邏輯放在一個時序always塊描述。輸出時為寄存器輸出,所以無毛刺
- 對於簡單的狀態機,把輸入,轉移,輸出一起體現,比較直觀
缺點: - 產生多余的觸發器(因為把組合邏輯也放在時序邏輯中實現)
- 對於復雜狀態機而言這種寫法難以調試
不建議使用。
二段式狀態機
第一個always塊決定系統狀態標志的自動跳轉,第二個always塊決定系統根據不同狀態下的輸入進行狀態的跳轉及輸出。
//時序邏輯,描述從現態轉移到次態
always @ (posedge clk) begin
current_state<=next_state;
end
//組合邏輯,包括轉移條件以及狀態內容(即輸出)
always @ (*) begin
case(current_state)
S0:begin
out = ...;
if(in...) next_state = S1; //組合邏輯使用阻塞語句
else next_state = S0;
end
S1:begin
out = ...;
if(in...) next_state = S2; //組合邏輯使用阻塞語句
else next_state = S1;
end
...
endcase
end
優點:
- 二段式便於閱讀,理解和維護,有利於綜合器優化代碼。
缺點: - 但是由於采用的是組合邏輯輸出,容易產生毛刺
- 不利於約束,也不利於綜合器和布局布線器實現高性能設計。
三段式狀態機
通用mealy三段式狀態機(建議實際工程中采用的結構)
//------采用獨熱碼或格雷碼或其他方式編碼狀態
parameter IDLE = ...
parameter S0 = ...
...
reg [x:0] curr_state;
reg [x:0] next_state;
//------每個時鍾只產生一次狀態變化
always @(posedge clk or posedge asy_rst)
begin
if(asy_rst) curr_state <= IDLE ;
else curr_state <= next_state;
end
//------產生的下一狀態的組合邏輯
always @(*)
begin
next_state = 'bx;
case(curr_state)
IDLE: if(輸入) next_state = S0 ;else...;
S0: if(輸入) next_state = ...;
...
default: next_state = ...;
endcase
end
/************************時序或組合二選一***********************/
//------時序邏輯輸出(比組合邏輯延時一個時鍾)
always@(posedge clk or posedge asy_rst)
begin
if(asy_rst)out<= ...;
else
case(curr_state)
sO: if(...) out <= ...;
sO: if(...) out <= ...;
default: out <= ...;
endcase
end
// 如果是moore型則上面的判斷條件通常不需要,out只與當前狀態有關。
//------組合邏輯輸出 采用 assign 或always
always @(*)
begin
if(asy_rst)out = ...;
else
case(curr_state)
sO: if(...) out = ...;
sO: if(...) out = ...;
default: out = ...;
endcase
end
三段式結構中,2個時序always塊分別用來描述現態邏輯轉移,及輸出賦值。組合always塊用於描述狀態轉移的條件。
優點:
- 這種結構是寄存器輸出,輸出無毛刺
- 而且代碼更清晰易讀,特別是對於復雜的狀態機來說。
缺點:
- 消耗的面積更多點。
推薦使用三段式。