1、狀態機工作原理
狀態機是一種能夠描述具有邏輯順序和時序順序的事件的方法,特別適合描述那些存在先後順序以及其它規律性事件。狀態機是組合邏輯和寄存器邏輯的特殊組合,一般包括兩個部分:組合邏輯部分和寄存器邏輯部分;寄存器用於存儲狀態,組合電路用於狀態譯碼和產生輸出信號。狀態機的下一個狀態及輸出不僅與輸入信號有關,還與寄存器當前狀態有關,其基本要素有三個:狀態、輸出和輸入。
(1)狀態
狀態也叫狀態變量。在邏輯設計中,使用狀態劃分邏輯順序和時序規律。例如要設計一個交通燈控制器,可以允許通行、慢行和禁止通行作爲狀態;設計一個電梯控制器,每層就是一個狀態等等。
(2)輸入
指狀態機中進入每個狀態的條件,有的狀態機沒有輸入條件,其中的狀態轉移較爲簡單;有的狀態機有輸入條件,當某個輸入條件存在時才能轉移到相應的狀態。例如,交通燈控制器就沒有輸入條件,狀態隨着時間的改變自動跳轉;電梯控制器是存在輸入的,每一層的上下按鍵以及電梯內的層數選擇按鍵都是輸入,會對電梯的下一個狀態產生影響。
(3)輸出
輸出指在某一個狀態時特定發生的事件。例如,交通燈控制器在允許通行狀態輸出綠色,緩行狀態輸出黃色,禁止通行狀態輸出紅色;電梯控制器在運行時一直會輸出當前所在層數以及當前運行方向(上升或下降)。
2、例子
Welcom
64個字符長度的序列
fagpaljkhdwiernggaolWelcom
從序列中檢測出總共有多少個需要檢測的序列Welcom。
//時序邏輯
module FSM(
clk,
rst_n,
dv,//數據開始有效信號,開始檢測信號
data,//數據何時傳進來,何時結束。即數據何時有效
num,//Welcon個數
get_flag//數據結束信號
);
input clk;
input rst_n;
input dv;
input [7:0] data;//一個字符,8位
output [3:0] num;
output get_flag;
reg [3:0] cnt;//計數,Welcom的個數
//狀態機
//定義狀態
reg [2:0] state;
//參數法
localparam CHECK_W = 3'd0;
localparam CHECK_E = 3'd1;
localparam CHECK_L = 3'd2;
localparam CHECK_C = 3'd3;
localparam CHECK_O = 3'd4;
localparam CHECK_M = 3'd5;
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
state <= CHECK_W;
cnt <= 4'd0;
end
else if(dv) begin
case(state)
CHECK_W://檢測W
if(data == "W")
state <= CHECK_E;
else
state <= CHECK_W;//沒有檢測到'W',就保持原有狀態
CHECK_E://檢測e
if(data == "e")
state <= CHECK_L;
else if(data == "W")//不是'e',如果是'W',要重新檢測
state <= CHECK_E;
else
state <= CHECK_W;//沒有檢測到'e',就跳轉到新狀態
CHECK_L://檢測'l'
if(data == "l")
state <= CHECK_C;
else if(data == "W")//不是'e',如果是'W',要重新檢測
state <= CHECK_E;
else
state <= CHECK_W;//沒有檢測到'l',就跳轉到新狀態
CHECK_C://檢測'c'
if(data == "c")
state <= CHECK_O;
else if(data == "W")//不是'e',如果是'W',要重新檢測
state <= CHECK_E;
else
state <= CHECK_W;//沒有檢測到'c',就跳轉到新狀態
CHECK_O://檢測'o'
if(data == "o")
state <= CHECK_O;
else if(data == "W")//不是'e',如果是'W',要重新檢測
state <= CHECK_E;
else
state <= CHECK_W;//沒有檢測到'o',就跳轉到新狀態
CHECK_M://檢測'm'
if(data == "m")begin
state <= CHECK_W;
cnt <= cnt + 1'd1;
end
else if(data == "W")//不是'e',如果是'W',要重新檢測
state <= CHECK_E;
else
state <= CHECK_W;//沒有檢測到'm',就跳轉到新狀態
default:state <= CHECK_W;
endcase
end
else
state <= CHECK_W;
endmodule
3、測試文件
`timescale 1ns/1ns
`define clk_period 20
module FSM_Welcome;
reg clk;
reg rst_n;
wire [7:0]data;
reg start;
wire [2:0]num;
wire flag;
wire [511:0]data_tmp;
reg [511:0]data_reg;
assign data_tmp = "abcdeWelcomehijkWelcomedcba";
always@(posedge clk or negedge rst_n)
if(!rst_n)
data_reg <= 0;
else if(start)
data_reg <= data_reg << 8;
else
data_reg <= data_tmp;
assign data = data_reg[511:504];
FSM_Welcome FSM_Welcome(
.clk(clk),
.rst_n(rst_n),
.data(data),
.start(start),
.num(num),
.flag(flag)
);
initial clk = 1;
always#(`clk_period/2)clk = ~clk;
initial begin
rst_n = 0;
start = 0;
#(`clk_period*20)
rst_n = 1;
#(`clk_period*10)
start = 1;
#(`clk_period*64)
#200;
$stop;
end
endmodule