fpga狀態機詳解
阿新 • • 發佈:2018-01-15
循環 產生 attribute state begin 分享 hello view 如何
什麽是狀態機:狀態機通過不同的狀態遷移來完成特定的邏輯操作
狀態機的分類:Moore型狀態機和Mealy型狀態機
- Moore型:狀態機的變化只與當前的狀態有關
- Mealy型:狀態機的變化不僅與當前的狀態有關,還與輸入有關
如何創建狀態機:狀態機的創建可以分為一段式,兩段式和三段式
-
一段式:主要是講所有的狀態變化以及導致的輸出變化都寫在了一個always快中。
-
兩段式:將一些復位信號,clk信號單獨寫在一個always快中,其他的狀態變化,輸出值得變化寫在一個always快中。
-
三段式:將一些復位信號,clk信號單獨寫在一個always快中,其他的狀態遷移變化寫在一個always快中,對應狀態的輸出值得變化寫在一個always快中。
舉個例子:從循環輸入的字母中做連續檢測,當連續檢測到“hello”時,將led燈進行狀態的翻轉,繼續進行下一次的檢測。
- 一段式的編寫方式:
module hello(
input clk,//系統時鐘信號 50mHz
input rst_n,//系統復位信號,低電平有效
input [7:0] data,//連續輸入的字母
output reg led//led燈
);
//設置需要改變的狀態
parameter checkh = 5‘b0000_1,
checke = 5‘b0001_0,
checkla = 5‘b0010_0,
checklb = 5‘b0100_0,
checko = 5‘b1000_0;
reg [4:0]state;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
led <= 1‘b0;
state <= checkh;
end
else
begin
case (state)
checkh:
if(data == "h") state <= checke;
else state <= checkh;
checke:
if(data == "e") state <= checkla;
else state <= checkh;
checkla:
if(data == "l") state <= checklb;
else state <= checkh;
checklb:
if(data == "l") state <= checko;
else state <= checkh;
checko:
if(data == "o")
begin
led <= ~led;
state <= checkh;
end
else state <= checkh;
default:state <= checkh;
endcase
end
endmodule
- 兩段式的編寫方式:
module hello(
input clk,
input rst_n,
input [7:0] data,
output reg led
);
parameter checkh = 5‘b0000_1,
checke = 5‘b0001_0,
checkla = 5‘b0010_0,
checklb = 5‘b0100_0,
checko = 5‘b1000_0;
reg [4:0] cstate;
reg [4:0] nstate;
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
cstate <= checkh;
end
else
cstate <= nstate;
always @(cstate or data)
case (cstate)
checkh:
if(data == "h") nstate <= checke;
else nstate <= checkh;
checke:
if(data == "e") nstate <= checkla;
else nstate <= checkh;
checkla:
if(data == "l") nstate <= checklb;
else nstate <= checkh;
checklb:
if(data == "l") nstate <= checko;
else nstate <= checkh;
checko:
if(data == "o")
begin
led <= ~led;
nstate <= checkh;
end
else nstate <= checkh;
default:nstate <= checkh;
endcase
endmodule
- 三段式的編寫方式:
module hello(
input clk,
input rst_n,
input [7:0] data,
output reg led
);
parameter checkh = 5‘b0000_1,
checke = 5‘b0001_0,
checkla = 5‘b0010_0,
checklb = 5‘b0100_0,
checko = 5‘b1000_0;
reg [4:0] cstate;
reg [4:0] nstate;
//復位信號,clk的處理(主要是對初始狀態進行賦值操作)
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
cstate <= checkh;
end
else
cstate <= nstate;
//狀態遷移的處理
always @(cstate or data)
case (cstate)
checkh:
if(data == "h") nstate <= checke;
else nstate <= checkh;
checke:
if(data == "e") nstate <= checkla;
else nstate <= checkh;
checkla:
if(data == "l") nstate <= checklb;
else nstate <= checkh;
checklb:
if(data == "l") nstate <= checko;
else nstate <= checkh;
checko:
if(data == "o")
begin
nstate <= checkh;
end
else nstate <= checkh;
default:nstate <= checkh;
endcase
//輸出數據的處理
always @(posedge clk or negedge rst_n)
if(!rst_n)
begin
led <= 1‘b1;
end
else
case (cstate)
checko:
if(data == "o")
led <= ~led;
default;
endcase
endmodule
註意
- 一般的狀態機是使用Always語句和case語句組合來實現的
- 不可以根據Always快的個數來判斷他是屬於幾段的狀態機
- 一般情況下不建議使用一段式狀態機,建議使用二和三段式狀態機,二段式狀態機使用時序邏輯處理狀態變化,組合邏輯處理輸入輸出的變化,結構比較清晰,但容易產生毛刺
- 三段式從輸入到輸出會比一、兩段式狀態機延時一個時鐘周期
fpga狀態機詳解