一、状态机的分类
1、根据输入是否跟当前状态有关分为
Moore状态机 | 状态机的输出只和当前的状态有关 |
---|
Mealy状态机 | 状态机的输出不仅与当前的状态有关,还和当前的输入信号有关 |
2、根据写法分为一段、两段、三段式状态机
一段式 | 二段式 | 三段式 |
---|
状态转换、状态转移、状态输出用一个always块描述 | 状态转换用一个always块,状态转移和输出用一个always块 | 状态转换、状态转移、状态输出分别用一个always块描述 |
可以无组合逻辑输出 | 多数情况有组合逻辑输出 | 无组合逻辑输出 |
不利于综合和布局布线 | 利于综合和布局布线 | 利于综合和布局布线 |
代码可维护性低 | 代码可维护性高 | 代码可维护性最高 |
采用寄存器(时序逻辑)输出的优点:稳定性好、延迟更好计算、时序好计算。所以一般采用三段式的状态机。
二、三段式状态机手撕代码
1、售货机,要求:①每瓶饮料1.5元 ②一次只能输入一个硬币(1元和5角) ③能够找零
module vending(
input clk ,
input rst_n ,
input [1:0] money ,
output drink ,
output cion ,
);
parameter IDLE = 5'b00001;
parameter S1 = 5'b00010;
parameter S2 = 5'b00100;
parameter S3 = 5'b01000;
parameter S4 = 5'b10000;
reg [4:0] cstate;
reg [4:0] nstate;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cstate <= IDLE;
else
cstate <= nstate;
end
always @(*) begin
case(cstate)
IDLE:nstate = money[1] ? S2 : (money[0] ? S1 : IDLE);
S1 :nstate = money[1] ? S3 : (money[0] ? S2 : S1 );
S2 :nstate = money[1] ? S4 : (money[0] ? S3 : S2 );
S3 :nstate = money[1] ? S2 : (money[0] ? S1 : IDLE);
S4 :nstate = money[1] ? S2 : (money[0] ? S1 : IDLE);
endcase
end
reg r_drink;
reg r_cion;
assign drink = r_drink;
assign coin = r_coin;
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
r_drink <= 1'b0;
r_cion <= 1'b0;
end
else if(nstate == S3) begin
r_drink <= 1'b1;
r_cion <= 1'b0;
end
else if(nstate == S4) begin
r_drink <= 1'b1;
r_coin <= 1'b1;
end
end
endmodule
2、模三检测器,要求:①判断输入的数据是否可以被三整除,可以输出1(不可以输出0)②必须串行输入,不支持并行输入
3、序列检测器,要求:检测0111001序列,能重复检测
module seq_detect(
input clk ,
input rst_n ,
input a ,
output match
);
reg cstate;
reg nstate;
parameter IDLE = 4'd0;
parameter S1 = 4'd1;
parameter S2 = 4'd2;
parameter S3 = 4'd3;
parameter S4 = 4'd4;
parameter S5 = 4'd5;
parameter S6 = 4'd6;
parameter S7 = 4'd7;
parameter S8 = 4'd8;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
cstate <= IDLE;
else
cstate <= nstate;
end
always @(*) begin
case(cstate)
IDLE : nstate = (a == 0) ? S1 ; IDLE ;
S1 : nstate = (a == 1) ? S2 ; S1 ;
S2 : nstate = (a == 1) ? S3 ; S1 ;
S3 : nstate = (a == 1) ? S4 ; S1 ;
S4 : nstate = (a == 1) ? S2 ; IDLE ;
S5 : nstate = (a == 0) ? S5 ; S2 ;
S6 : nstate = (a == 0) ? S7 ; S2 ;
S7 : nstate = (a == 1) ? S8 ; S1 ;
S8 : nstate = (a == 0) ? S1 ; S3 ;
default : nstate = IDLE ;
endcase
end
reg r_match;
assign match = r_match;
always @(posedge clk or negedge rst_n) begin
if(rst_n)
r_match <= 0;
else if(cstate == S8)
r_match <= 1;
else
r_match <= 0;
end
endmodule