狀態機,其實是有限狀態機(finite-state machine(FSM))
的簡稱,字面上來看可以知道它是有有限個狀態,並且可以按照著特定的順序來完成各個狀態內的動作,這使數位電路也能按著想要的順序完成特定的動作,例如某種演算法、某種傳輸協定等等。
常見的編碼有以下三種:
優點:
缺點:
優點:
缺點:
依照順序的
,否則就失去這優勢了,但實際上幾乎不可能狀態都按著順序跳,所以這的編碼方法幾乎與二進制編碼效果差不多。EX:
//One-Hot
localparam IDLE = 4'b0001;
localparam START = 4'b0010;
localparam SHIFT = 4'b0100;
localparam STOP = 4'b1000;
優點:
缺點:
下面來看一個簡單狀態機的範例~
module testFSM(
clkSys,
rst_n,
en,
out
);
/*--------localparam--------*/
localparam one = 2'd0;
localparam two = 2'd1;
localparam three = 2'd2;
localparam four = 2'd3;
/*--------ports declarations--------*/
input clkSys;
input rst_n;
input en;
output [2:0]out;
reg [2:0]out;
/*--------variables--------*/
reg [1:0]fstate;
/*--------state--------*/
always@(posedge clkSys or negedge rst_n)begin
if(!rst_n)fstate <= one;
else begin
case(fstate)
one:begin
if(en)fstate <= two;
else fstate <= one;
end
two:begin
if(en)fstate <= three;
else fstate <= two;
end
three:begin
if(en)fstate <= four;
else fstate <= three;
end
four:begin
if(en)fstate <= one;
else fstate <= four;
end
default:fstate <= one;
endcase
end
end
/*--------output--------*/
always@(posedge clkSys or negedge rst_n)begin
if(!rst_n)out <= 3'd0;
else begin
case(fstate)
one: out <= 3'd1;
two: out <= 3'd2;
three: out <= 3'd3;
four: out <= 3'd4;
default:out <= 3'd0;
endcase
end
end
endmodule
TestBench
`timescale 10ns/1ns
module tb_testFSM();
reg clkSys;
reg rst_n;
reg en;
wire [2:0]out;
testFSM UUT(
.clkSys(clkSys),
.rst_n(rst_n),
.en(en),
.out(out)
);
initial begin
clkSys = 0;
rst_n = 0;
en = 0;
repeat(2)@(posedge clkSys)rst_n = 0;
rst_n = 1;
en = 1;
#20 en = 0;
#40;
en = 1;
#20 en = 0;
#40;
en = 1;
#20 en = 0;
#40;
en = 1;
#20 en = 0;
#100 $stop;
end
always #10 clkSys = ~clkSys;
endmodule
Wave
state machine
上面的例子,狀態是以二進制編碼來表示的,我自己的狀態機是以兩段式為主,並且輸出邏輯為了 timing 更好,在 output logic 會再多敲一級 clk(循序邏輯),可以看到一個 always 處理狀態的轉移,而另一個 always 負責在該狀態輸出對應的信號,在這個例子中,在每一個狀態內都要在 clk 為正緣時並且讀到 en 為 "1" 時才會進入下一個狀態,否則留在原狀態等待 en 的來臨。