01
狀態機設計概述
硬件電路設計通常以并行方式實現,但是在實際工程中經常會存在系統按照順序邏輯執行的需求。如果希望分多個時間步驟完成一個任務,同時減少使用大量使能信號銜接多個模塊造成的麻煩,就需要引出狀態機的概念。
狀態機(State Machine)由輸入、輸出和狀態三要素構成,輸入是指一些引發狀態變化的條件,輸出是指狀態改變后引起的變化,狀態是指順序邏輯執行的步驟,通常利用一些邏輯值進行表示。
以NAND FALSH控制過程的狀態機為例,NAND FALSH操作通常需要按順序依次執行擦除、壞塊檢測和讀寫操作:NAND FLASH在系統復位信號rst = 1后進入空閑狀態IDLE;當指令使能信號i_cmd_en = 1且指令選擇信號i_cmd_sel = h18時,NAND FLASH 進入擦除狀態ERASE;當指令結束信號i_cmd_finish = 1時,NAND FLASH進入擦除狀態讀取狀態......NAND FLASH根據不同的輸入條件和當前狀態實現狀態跳轉,通過在不同狀態實現不同功能,完成NAND FLASH讀寫等操作。
狀態機設計按照不同的標準分類:
1. 輸出與輸入是否相關:
Moore型狀態機:輸出只與狀態相關,與輸入無關;
Mealy型狀態機:輸出與狀態和輸入都相關。
2. 狀態轉移與輸出是否依賴時鐘信號:
同步狀態機:狀態轉移和輸出都發生在時鐘沿;
異步狀態機:狀態轉移和輸出不依賴時鐘信號,而是依賴于輸入信號的變化。
3. 輸出與狀態是否相關:
順序邏輯狀態機:輸出與輸入和狀態都相關,當前時刻的輸出會影響下一個時刻的狀態;
組合邏輯狀態機:輸出只與輸入相關,與狀態無關,當前時刻的輸出不會影響下一個時刻的狀態。
4. 狀態數目是否有限:
有限狀態機:狀態數目是有限的,可以用狀態轉移圖來表示狀態和狀態之間的轉移關系;
無限狀態機:狀態數目是無限的,一般用差分方程或狀態轉移函數來表示狀態轉移關系。
在FPGA設計過程中,通常考慮的狀態機是有限狀態機(FSM, Finite State Machine)。FPGA有限狀態機根據寫法不同可以分為一段式、兩段式和三段式,不同狀態機寫法在代碼可讀性和速度面積平衡性方面有所優劣,本文將以不同寫法下狀態機的Verilog代碼為例,對三種狀態機寫法的效果進行對比分析。
02
一段式狀態機設計分析
一段式狀態機將狀態機的三要素(輸入、輸出和狀態)邏輯實現在同一個always內,示例代碼如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Cascatrix
// Engineer: Carson
//?
// Create Date: 2023/07/16
// Design Name: FSM
// Module Name: FSM
// Tool Versions: v1.0
// Description: Finite State Machine?
//////////////////////////////////////////////////////////////////////////////////
module FSM(
? ? clk,
? ? rst_n,
? ? condition1,
? ? condition2,
? ? result
? ? );
? ? input? ? ? ? ? ?clk;
? ? input? ? ? ? ? ?rst_n;
? ? input? ? ? ? ? ?condition1;
? ? input? ? ? ? ? ?condition2;
? ? output? [3:0]? ?result;
? ? wire? ? ? ? ? ? clk;
? ? wire? ? ? ? ? ? rst_n;
? ? wire? ? ? ? ? ? condition1;
? ? wire? ? ? ? ? ? condition2;
? ? reg? ? ?[3:0]? ?result;
? ? parameter IDLE = 1;
? ? parameter STATE_S11 = 2;
? ? parameter STATE_S12 = 3;
? ? parameter STATE_S21 = 4;
? ? parameter STATE_S22 = 4;
? ? reg [3:0] current_state;? ?
? ? always@(posedge clk or negedge rst_n)
? ? begin
? ? ? ? if(!rst_n)
? ? ? ? begin
? ? ? ? ? ? current_state <= IDLE;
? ? ? ? ? ? result <= 4'b0101;
? ? ? ? end
? ? ? ? else
? ? ? ? begin
? ? ? ? ? ? case(current_state)
? ? ? ? ? ? IDLE:
? ? ? ? ? ? begin
? ? ? ? ? ? ? ? if(condition1)
? ? ? ? ? ? ? ? begin
? ? ? ? ? ? ? ? ? ? current_state <= STATE_S11;
? ? ? ? ? ? ? ? ? ? result <= 4'b1110;
? ? ? ? ? ? ? ? end
? ? ? ? ? ? ? ? else if(condition2)
? ? ? ? ? ? ? ? begin
? ? ? ? ? ? ? ? ? ? current_state <= STATE_S21;
? ? ? ? ? ? ? ? ? ? result <= 4'b1111;
? ? ? ? ? ? ? ? end
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? begin
? ? ? ? ? ? ? ? ? ? current_state <= IDLE;
? ? ? ? ? ? ? ? ? ? result <= 4'b0101;
? ? ? ? ? ? ? ? end
? ? ? ? ? ? end
? ? ? ? ? ? STATE_S11:
? ? ? ? ? ? begin
? ? ? ? ? ? ? ? current_state <= STATE_S12;
? ? ? ? ? ? ? ? result <= 4'b0010;
? ? ? ? ? ? end
? ? ? ? ? ? STATE_S12:
? ? ? ? ? ? begin
? ? ? ? ? ? ? ? current_state <= IDLE;
? ? ? ? ? ? ? ? result <= 4'b0101;
? ? ? ? ? ? end
? ? ? ? ? ? STATE_S21:
? ? ? ? ? ? begin
? ? ? ? ? ? ? ? current_state <= STATE_S22;
? ? ? ? ? ? ? ? result <= 4'b1000;
? ? ? ? ? ? end
? ? ? ? ? ? STATE_S22:
? ? ? ? ? ? begin
? ? ? ? ? ? ? ? current_state <= IDLE;
? ? ? ? ? ? ? ? result <= 4'b0101;
? ? ? ? ? ? end
? ? ? ? ? ? default:current_state <= IDLE;
? ? ? ? ? ? endcase
? ? ? ? end
? ? end
endmodule
上述代碼所實現的一段式狀態機RTL視圖如下:?
通過分析一段式狀態機代碼可以發現,狀態current_state、輸入condition1/2和輸出result在同一個always內,整體而言代碼編寫較為簡單。然而,從代碼可讀性和可維護性的角度而言,一段式狀態機的這種代碼格式并不利于后期的閱讀與維護,當狀態機較為復雜時,一段式狀態機更容易出現錯誤。
03
兩段式狀態機設計分析
兩段式狀態機將狀態機的時序邏輯和組合邏輯劃分為兩個always,時序邏輯內進行當前狀態和下一狀態的切換,組合邏輯里實現各個輸入、輸出和狀態的判斷,示例代碼如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Cascatrix
// Engineer: Carson
//?
// Create Date: 2023/07/16
// Design Name: FSM
// Module Name: FSM
// Tool Versions: v1.0
// Description: Finite State Machine?
//////////////////////////////////////////////////////////////////////////////////
module FSM(
? ? clk,
? ? rst_n,
? ? condition1,
? ? condition2,
? ? result
? ? );
? ? input? ? ? ? ? ?clk;
? ? input? ? ? ? ? ?rst_n;
? ? input? ? ? ? ? ?condition1;
? ? input? ? ? ? ? ?condition2;
? ? output? [3:0]? ?result;
? ? wire? ? ? ? ? ? clk;
? ? wire? ? ? ? ? ? rst_n;
? ? wire? ? ? ? ? ? condition1;
? ? wire? ? ? ? ? ? condition2;
? ? reg? ? ?[3:0]? ?result;
? ? parameter IDLE = 1;
? ? parameter STATE_S11 = 2;
? ? parameter STATE_S12 = 3;
? ? parameter STATE_S21 = 4;
? ? parameter STATE_S22 = 4;
? ? reg [3:0] next_state;? ?
? ? reg [3:0] current_state;? ?
? ? always@(posedge clk or negedge rst_n)
? ? begin
? ? ? ? if(!rst_n)
? ? ? ? ? ? current_state <= IDLE;
? ? ? ? else
? ? ? ? ? ? current_state <= next_state;
? ? end
? ? always@(current_state or condition1 or condition2)
? ? begin
? ? ? ? if(!rst_n)
? ? ? ? begin
? ? ? ? ? ? next_state = IDLE;
? ? ? ? ? ? result = 4'b0101;
? ? ? ? end
? ? ? ? else
? ? ? ? begin
? ? ? ? ? ? case(next_state)
? ? ? ? ? ? IDLE:
? ? ? ? ? ? begin
? ? ? ? ? ? ? ? if(condition1)
? ? ? ? ? ? ? ? begin
? ? ? ? ? ? ? ? ? ? next_state = STATE_S11;
? ? ? ? ? ? ? ? ? ? result = 4'b1110;
? ? ? ? ? ? ? ? end
? ? ? ? ? ? ? ? else if(condition2)
? ? ? ? ? ? ? ? begin
? ? ? ? ? ? ? ? ? ? next_state = STATE_S21;
? ? ? ? ? ? ? ? ? ? result = 4'b1111;
? ? ? ? ? ? ? ? end
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? begin
? ? ? ? ? ? ? ? ? ? next_state = IDLE;
? ? ? ? ? ? ? ? ? ? result = 4'b0101;
? ? ? ? ? ? ? ? end
? ? ? ? ? ? end
? ? ? ? ? ? STATE_S11:
? ? ? ? ? ? begin
? ? ? ? ? ? ? ? next_state = STATE_S12;
? ? ? ? ? ? ? ? result = 4'b0010;
? ? ? ? ? ? end
? ? ? ? ? ? STATE_S12:
? ? ? ? ? ? begin
? ? ? ? ? ? ? ? next_state = IDLE;
? ? ? ? ? ? ? ? result = 4'b0101;
? ? ? ? ? ? end
? ? ? ? ? ? STATE_S21:
? ? ? ? ? ? begin
? ? ? ? ? ? ? ? next_state = STATE_S22;
? ? ? ? ? ? ? ? result = 4'b1000;
? ? ? ? ? ? end
? ? ? ? ? ? STATE_S22:
? ? ? ? ? ? begin
? ? ? ? ? ? ? ? next_state = IDLE;
? ? ? ? ? ? ? ? result = 4'b0101;
? ? ? ? ? ? end
? ? ? ? ? ? default:next_state = IDLE;
? ? ? ? ? ? endcase
? ? ? ? end
? ? end
endmodule
上述代碼所實現的兩段式狀態機RTL視圖如下:?
相比于一段式狀態機,兩段式狀態機通過劃分組合邏輯和時序邏輯提高代碼的可讀性和可維護性,對組合邏輯內容更改即可提高。然而,兩段式狀態機的組合邏輯輸出在同一個模塊中可能會出現競爭冒險,因此較為容易出現毛刺等問題。
04
三段式狀態機設計分析
三段式狀態機將兩段式狀態機組合邏輯的狀態和輸出劃分為兩部分,狀態轉換使用組合邏輯、邏輯輸出使用時序邏輯,示例代碼如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: Cascatrix
// Engineer: Carson
//?
// Create Date: 2023/07/16
// Design Name: FSM
// Module Name: FSM
// Tool Versions: v1.0
// Description: Finite State Machine?
//////////////////////////////////////////////////////////////////////////////////
module FSM(
? ? clk,
? ? rst_n,
? ? condition1,
? ? condition2,
? ? result
? ? );
? ? input? ? ? ? ? ?clk;
? ? input? ? ? ? ? ?rst_n;
? ? input? ? ? ? ? ?condition1;
? ? input? ? ? ? ? ?condition2;
? ? output? [3:0]? ?result;
? ? wire? ? ? ? ? ? clk;
? ? wire? ? ? ? ? ? rst_n;
? ? wire? ? ? ? ? ? condition1;
? ? wire? ? ? ? ? ? condition2;
? ? reg? ? ?[3:0]? ?result;
? ? parameter IDLE = 1;
? ? parameter STATE_S11 = 2;
? ? parameter STATE_S12 = 3;
? ? parameter STATE_S21 = 4;
? ? parameter STATE_S22 = 4;
? ? reg [3:0] next_state;? ?
? ? reg [3:0] current_state;? ?
? ? always@(posedge clk or negedge rst_n)
? ? begin
? ? ? ? if(!rst_n)
? ? ? ? ? ? current_state <= IDLE;
? ? ? ? else
? ? ? ? ? ? current_state <= next_state;
? ? end
? ? always@(current_state or condition1 or condition2)
? ? begin
? ? ? ? case(current_state)
? ? ? ? IDLE:
? ? ? ? begin
? ? ? ? ? ? if(condition1)
? ? ? ? ? ? ? ? next_state = STATE_S11;
? ? ? ? ? ? else if(condition2)
? ? ? ? ? ? ? ? next_state = STATE_S21;
? ? ? ? ? ? else
? ? ? ? ? ? ? ? next_state = IDLE;
? ? ? ? end
? ? ? ? STATE_S11: next_state = STATE_S12;
? ? ? ? STATE_S12: next_state = IDLE;
? ? ? ? STATE_S21: next_state = STATE_S22;
? ? ? ? STATE_S22: next_state = IDLE;
? ? ? ? default:next_state = IDLE;
? ? ? ? endcase
? ? end
? ? always@(posedge clk or negedge rst_n)
? ? begin
? ? ? ? if(!rst_n)
? ? ? ? ? ? result <= 4'b0101;
? ? ? ? else
? ? ? ? case(current_state)
? ? ? ? IDLE:
? ? ? ? begin
? ? ? ? ? ? if(condition1)
? ? ? ? ? ? ? ? result <= 4'b1110;
? ? ? ? ? ? else if(condition2)
? ? ? ? ? ? ? ? result <= 4'b1111;
? ? ? ? ? ? else
? ? ? ? ? ? ? ? result <= 4'b0101;
? ? ? ? end
? ? ? ? STATE_S11: result <= 4'b0010;
? ? ? ? STATE_S12: result <= 4'b0101;
? ? ? ? STATE_S21: result <= 4'b1000;
? ? ? ? STATE_S22: result <= 4'b0101;
? ? ? ? default:result <= 4'b0101;
? ? ? ? endcase
? ? end
endmodule
上述代碼所實現的三段式狀態機RTL視圖如下:?
三段式狀態機通過時序邏輯解決了兩段式寫法中組合邏輯產生毛刺的問題,同時保證代碼的可讀性和可維護性。從資源消耗方面而言,相比于一段式和兩段式狀態機,三段式狀態機會占用更多資源,同時從輸入到輸出會延遲一個時鐘周期。
05
狀態機設計總結
狀態機三種寫法可以總結如下:
一段式狀態機:一個always塊,既描述狀態轉移,又描述狀態的輸入輸出,當前狀態用寄存器輸出;
二段式:兩個always塊,時序邏輯與組合邏輯分開,一個always塊采用同步時序描述狀態轉移;另一個always塊采用組合邏輯判斷狀態轉移條件,描述狀態轉移規律以及輸出,當前狀態用組合邏輯輸出,可能出現競爭冒險,產生毛刺,而且不利于約束,不利于綜合器和布局布線器實現高性能的設計;
三段式:三個always塊,一個always模塊采用同步時序描述狀態轉移;一個always采用組合邏輯判斷狀態轉移條件,描述狀態轉移規律;第三個always塊使用同步時序描述狀態輸出,寄存器輸出。
注:需要注意的是,狀態機三種不同寫法的本質區別是狀態機三要素(狀態、輸入和輸出)的邏輯功能,而非always塊的數量。
審核編輯:劉清
評論