状态机的定义
状态机(finite state machine):根据控制信号按照预先设定的状态进行状态转移。
状态机(FSM,有限状态机)分为摩尔状态机与米利状态机,其中摩尔状态机的输出(次态)仅与现态有关,米利状态机的输出(次态)与输入和现态有关。
两种状态机的区别:
1.摩尔型状态机所需要的状态比米利型多一个;
2.摩尔型状态机的输出要在下一个有效沿到来时才被赋值,米利型状态机的输出直接以组合逻辑电路的形式输出,不需要等待下一个有效沿。也就是米利状态机比摩尔状态机输出早一个时钟周期。
3.摩尔状态机更安全,米利状态机可能会发生异步反馈。
4.米利状态机更快,但并非所有的时序电路都能用米利状态机实现,一些只能用摩尔状态机实现。
三段式状态机
共三个always段,第一段用同步时序逻辑(always @(posedge clk or negedge rst_n)描述状态转移,第二段用组合逻辑always @(*)描述状态转移条件,第三段用同步时序逻辑(always @(posedge clk or negedge rst_n)描述状态输出。
状态机常用于状态检测,使用三段式摩尔状态机描述状态检测与使用米利状态机实现状态检测的第二段以及第三段是不一样的,主要是由于在第二段中摩尔状态机比米利状态机的状态多一位,第三段中米利状态机的输出要由输入与现态共同决定。
例题:使用状态机实现序列1101的检测
用摩尔状态机实现:
module moore_FSM_1101(
input clk,
input rst_n,
input d_in,
output reg d_out);
//固定模式,先用parameter定义状态,常采用格雷码或者独热码,然后定义现态和次态
parameter S0=5'b00001;
parameter S1=5'b00010;
parameter S2=5'b00100;
parameter S3=5'b01000;
parameter S4=5'b10000;
reg [4:0] cur_state,nxt_state;
//第一段:状态转移
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cur_state<=S0;
else
cur_state<=nxt_state;
end
//状态转移条件
always@(*)begin
case(cur_state)
S0:nxt_state=d_in?S1:S0;
S1:nxt_state=d_in?S2:S0;
S2:nxt_state=d_in?S3:S2;
S3:nxt_state=d_in?S0:S4;
S4:nxt_state=d_in?S0:S2;
default:nxt_state=S0;
endcase
end
//状态机输出
always@(posedge clk or negedge rst_n)begin
if(rst_n)
d_out<=0;
else if(cur_state==S4)
d_out<=1;
else
d_out<=0;
end
endmodule
用米利状态机实现
module moore_FSM_1101(
input clk,
input rst_n,
input d_in,
output reg d_out);
//固定模式,先用parameter定义状态,常采用格雷码或者独热码,然后定义现态和次态
//米利状态机比摩尔状态机少一个状态
parameter S0=4'b0001;
parameter S1=4'b0010;
parameter S2=4'b0100;
parameter S3=4'b1000;
reg [3:0] cur_state,nxt_state;
//第一段:状态转移
always@(posedge clk or negedge rst_n)begin
if(!rst_n)
cur_state<=S0;
else
cur_state<=nxt_state;
end
//状态转移条件
always@(*)begin
case(cur_state)
S0:nxt_state=d_in?S1:S0;
S1:nxt_state=d_in?S2:S0;
S2:nxt_state=d_in?S3:S2;
S3:nxt_state=d_in?S0:S1;
default:nxt_state=S0;
endcase
end
//状态机输出,米利状态机的输出与输入有关
always@(posedge clk or negedge rst_n)begin
if(rst_n)
d_out<=0;
else if(cur_state==S3&&d_in==1)
d_out<=1;
else
d_out<=0;
end
endmodule