01
狀態(tài)機設(shè)計概述
硬件電路設(shè)計通常以并行方式實現(xiàn),但是在實際工程中經(jīng)常會存在系統(tǒng)按照順序邏輯執(zhí)行的需求。如果希望分多個時間步驟完成一個任務(wù),同時減少使用大量使能信號銜接多個模塊造成的麻煩,就需要引出狀態(tài)機的概念。
狀態(tài)機(State Machine)由輸入、輸出和狀態(tài)三要素構(gòu)成,輸入是指一些引發(fā)狀態(tài)變化的條件,輸出是指狀態(tài)改變后引起的變化,狀態(tài)是指順序邏輯執(zhí)行的步驟,通常利用一些邏輯值進行表示。
以NAND FALSH控制過程的狀態(tài)機為例,NAND FALSH操作通常需要按順序依次執(zhí)行擦除、壞塊檢測和讀寫操作:NAND FLASH在系統(tǒng)復(fù)位信號rst = 1后進入空閑狀態(tài)IDLE;當(dāng)指令使能信號i_cmd_en = 1且指令選擇信號i_cmd_sel = h18時,NAND FLASH 進入擦除狀態(tài)ERASE;當(dāng)指令結(jié)束信號i_cmd_finish = 1時,NAND FLASH進入擦除狀態(tài)讀取狀態(tài)......NAND FLASH根據(jù)不同的輸入條件和當(dāng)前狀態(tài)實現(xiàn)狀態(tài)跳轉(zhuǎn),通過在不同狀態(tài)實現(xiàn)不同功能,完成NAND FLASH讀寫等操作。
狀態(tài)機設(shè)計按照不同的標(biāo)準(zhǔn)分類:
1. 輸出與輸入是否相關(guān):
Moore型狀態(tài)機:輸出只與狀態(tài)相關(guān),與輸入無關(guān);
Mealy型狀態(tài)機:輸出與狀態(tài)和輸入都相關(guān)。
2. 狀態(tài)轉(zhuǎn)移與輸出是否依賴時鐘信號:
同步狀態(tài)機:狀態(tài)轉(zhuǎn)移和輸出都發(fā)生在時鐘沿;
異步狀態(tài)機:狀態(tài)轉(zhuǎn)移和輸出不依賴時鐘信號,而是依賴于輸入信號的變化。
3. 輸出與狀態(tài)是否相關(guān):
順序邏輯狀態(tài)機:輸出與輸入和狀態(tài)都相關(guān),當(dāng)前時刻的輸出會影響下一個時刻的狀態(tài);
組合邏輯狀態(tài)機:輸出只與輸入相關(guān),與狀態(tài)無關(guān),當(dāng)前時刻的輸出不會影響下一個時刻的狀態(tài)。
4. 狀態(tài)數(shù)目是否有限:
有限狀態(tài)機:狀態(tài)數(shù)目是有限的,可以用狀態(tài)轉(zhuǎn)移圖來表示狀態(tài)和狀態(tài)之間的轉(zhuǎn)移關(guān)系;
無限狀態(tài)機:狀態(tài)數(shù)目是無限的,一般用差分方程或狀態(tài)轉(zhuǎn)移函數(shù)來表示狀態(tài)轉(zhuǎn)移關(guān)系。
在FPGA設(shè)計過程中,通??紤]的狀態(tài)機是有限狀態(tài)機(FSM, Finite State Machine)。FPGA有限狀態(tài)機根據(jù)寫法不同可以分為一段式、兩段式和三段式,不同狀態(tài)機寫法在代碼可讀性和速度面積平衡性方面有所優(yōu)劣,本文將以不同寫法下狀態(tài)機的Verilog代碼為例,對三種狀態(tài)機寫法的效果進行對比分析。
02
一段式狀態(tài)機設(shè)計分析
一段式狀態(tài)機將狀態(tài)機的三要素(輸入、輸出和狀態(tài))邏輯實現(xiàn)在同一個always內(nèi),示例代碼如下:
`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
上述代碼所實現(xiàn)的一段式狀態(tài)機RTL視圖如下:?
通過分析一段式狀態(tài)機代碼可以發(fā)現(xiàn),狀態(tài)current_state、輸入condition1/2和輸出result在同一個always內(nèi),整體而言代碼編寫較為簡單。然而,從代碼可讀性和可維護性的角度而言,一段式狀態(tài)機的這種代碼格式并不利于后期的閱讀與維護,當(dāng)狀態(tài)機較為復(fù)雜時,一段式狀態(tài)機更容易出現(xiàn)錯誤。
03
兩段式狀態(tài)機設(shè)計分析
兩段式狀態(tài)機將狀態(tài)機的時序邏輯和組合邏輯劃分為兩個always,時序邏輯內(nèi)進行當(dāng)前狀態(tài)和下一狀態(tài)的切換,組合邏輯里實現(xiàn)各個輸入、輸出和狀態(tài)的判斷,示例代碼如下:
`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
上述代碼所實現(xiàn)的兩段式狀態(tài)機RTL視圖如下:?
相比于一段式狀態(tài)機,兩段式狀態(tài)機通過劃分組合邏輯和時序邏輯提高代碼的可讀性和可維護性,對組合邏輯內(nèi)容更改即可提高。然而,兩段式狀態(tài)機的組合邏輯輸出在同一個模塊中可能會出現(xiàn)競爭冒險,因此較為容易出現(xiàn)毛刺等問題。
04
三段式狀態(tài)機設(shè)計分析
三段式狀態(tài)機將兩段式狀態(tài)機組合邏輯的狀態(tài)和輸出劃分為兩部分,狀態(tài)轉(zhuǎn)換使用組合邏輯、邏輯輸出使用時序邏輯,示例代碼如下:
`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
上述代碼所實現(xiàn)的三段式狀態(tài)機RTL視圖如下:?
三段式狀態(tài)機通過時序邏輯解決了兩段式寫法中組合邏輯產(chǎn)生毛刺的問題,同時保證代碼的可讀性和可維護性。從資源消耗方面而言,相比于一段式和兩段式狀態(tài)機,三段式狀態(tài)機會占用更多資源,同時從輸入到輸出會延遲一個時鐘周期。
05
狀態(tài)機設(shè)計總結(jié)
狀態(tài)機三種寫法可以總結(jié)如下:
一段式狀態(tài)機:一個always塊,既描述狀態(tài)轉(zhuǎn)移,又描述狀態(tài)的輸入輸出,當(dāng)前狀態(tài)用寄存器輸出;
二段式:兩個always塊,時序邏輯與組合邏輯分開,一個always塊采用同步時序描述狀態(tài)轉(zhuǎn)移;另一個always塊采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件,描述狀態(tài)轉(zhuǎn)移規(guī)律以及輸出,當(dāng)前狀態(tài)用組合邏輯輸出,可能出現(xiàn)競爭冒險,產(chǎn)生毛刺,而且不利于約束,不利于綜合器和布局布線器實現(xiàn)高性能的設(shè)計;
三段式:三個always塊,一個always模塊采用同步時序描述狀態(tài)轉(zhuǎn)移;一個always采用組合邏輯判斷狀態(tài)轉(zhuǎn)移條件,描述狀態(tài)轉(zhuǎn)移規(guī)律;第三個always塊使用同步時序描述狀態(tài)輸出,寄存器輸出。
注:需要注意的是,狀態(tài)機三種不同寫法的本質(zhì)區(qū)別是狀態(tài)機三要素(狀態(tài)、輸入和輸出)的邏輯功能,而非always塊的數(shù)量。
審核編輯:劉清
評論
查看更多