有限狀態機(finite-state machine, FSM)
想想紅綠燈。在任何一刻,它都恰好處於某一種狀況——綠燈、黃燈或紅燈——而且它清楚地知道接下來會怎樣:綠燈讓位給黃燈,黃燈轉為紅燈,紅燈再回到綠燈。它絕不會停在半綠的狀態,也絕不會從綠燈直接跳到紅燈。這就是有限狀態機的全部精髓:一段邏輯,它總是恰好處於一組數量不多、固定的具名狀態之一,並在某件事情發生時——按下一個按鈕、計時器到時、一個時脈跳動——沿著定義明確的轉移在這些狀態之間移動。
有限狀態機是控制邏輯的標準範式——也就是數位電路中決定下一步該做什麼、而非埋頭計算數字的那部分。你用三樣東西來描述它:狀態的集合、在狀態間移動的規則(通常取決於當前狀態加上當前輸入),以及每個狀態產生的輸出。在硬體中,"我現在處於哪個狀態"這份記憶存放在由正反器構成的暫存器裡,每個時脈邊緣更新一次;而一塊組合邏輯則根據當前狀態和輸入計算出下一個狀態和輸出。正是這種劃分——保存狀態的時序元件饋送組合判決邏輯——讓有限狀態機成為建構控制器、協定處理器和序列產生器的一種乾淨、可重複使用的方式。
有限狀態機有兩種經典的形式,區別在於輸出從何而來。在摩爾(Moore)型機器中,輸出只取決於當前狀態——讀出狀態,你就知道輸出——這使它們穩定、易於推理,但它們要晚一個時脈才作出反應。在米利(Mealy)型機器中,輸出取決於當前狀態以及當前輸入,因此它們能在同一週期內回應,往往用更少的狀態,代價是輸出可能產生毛刺,或在週期中途隨輸入抖動而變化。一個好記的方法:摩爾型的輸出標在狀態上;米利型的輸出標在轉移上。
// Three-state controller, binary-encoded.
// next-state logic is combinational; the state register is clocked.
localparam IDLE = 2'd0, RUN = 2'd1, DONE = 2'd2;
reg [1:0] state, next;
always @(posedge clk or negedge rst_n) // sequential: hold the state
if (!rst_n) state <= IDLE; // reset to a known state
else state <= next;
always @(*) begin // combinational: choose next
next = state; // default: stay put
case (state)
IDLE: next = start ? RUN : IDLE;
RUN : next = done ? DONE : RUN;
DONE: next = IDLE;
default: next = IDLE; // recover from illegal states
endcase
end一個最簡的三狀態控制器——一個帶時脈的暫存器保存狀態,一塊組合邏輯挑選下一個狀態。重置和 `default` 分支讓它始終停留在已知且合法的狀態上。
"有限"是承重的關鍵詞:這種機器擁有可數、固定數量的狀態,而正是這一點讓你能把它畫成氣泡加箭頭的狀態圖,並對它做窮舉式檢查——每一個狀態和轉移都能被列舉出來、被推敲清楚。一旦加入無界的儲存(一個能無限往上加的計數器、一個堆疊),你就離開了有限狀態機的範疇,進入了一種更強大的計算模型。