状态机分为摩尔(Moore)型有限状态机和米利(Mealy)型有限状态机。摩尔型电路:输出与输入变量无直接关系的时序逻辑电路。米利型电路:输出与输入变量直接相关的时序逻辑电路。
状态机描述方式可分为一段式、两段式和三段式的。但目前我只用到一段式,后面再更新两段式和三段式。
编写状态机的注意事项:
(1)为了避免不必要的锁存器生成,需要穷举所有状态对应的输出动作,或使用default来定义状态动作;
(2)在定义状态时,推荐使用本地化参数定义localparam
下面一段代码,状态的跳转还是不能很好地写出
module Hello(Clk,Rst_n,data,led);
input Clk;
input Rst_n;
input [7:0]data;
output reg led;
localparam
CHECK_H = 5'b0_0001,
CHECK_e = 5'b0_0010,
CHECK_la = 5'b0_0100,
CHECK_lb = 5'b0_1000,
CHECK_o = 5'b1_0000;
reg [4:0]state;
/* 实现字符串的检测,每检测成功一次,LED状态便翻转一次 */
always@(posedge Clk or negedge Rst_n)
if(!Rst_n)begin
led <= 1;
state <= CHECK_H;
end
else begin
case(state)
CHECK_H:
if(data=="H") state <= CHECK_e;
else state <= CHECK_H;
CHECK_e:
if(data=="e") state <= CHECK_la;
else state <= CHECK_H;
CHECK_la:
if(data=="l") state <= CHECK_lb;
else state <= CHECK_H;
CHECK_lb:
if(data=="l") state <= CHECK_o;
else state <= CHECK_H;
CHECK_o:
begin
state <= CHECK_H;
if(data=="o") led <= ~led;
else led <= led;
end
default:state <= CHECK_H;
endcase
end
endmodule
`timescale 1ns/1ns
`define clock_period 20
module Hello_tb;
reg Clk;
reg Rst_n;
reg [7:0]ASCII;
wire led;
Hello Hello1(
.Clk(Clk),
.Rst_n(Rst_n),
.data(ASCII),
.led(led)
);
initial Clk = 1;
always#(`clock_period/2) Clk = ~Clk;
initial begin
Rst_n = 0;
ASCII = 0;
#(`clock_period*20);
Rst_n = 1;
#(`clock_period*20 + 1);
forever begin
ASCII="I";
#(`clock_period);
ASCII="A";
#(`clock_period);
ASCII="M";
#(`clock_period);
ASCII="X";
#(`clock_period);
ASCII="i";
#(`clock_period);
ASCII="a";
#(`clock_period);
ASCII="o";
#(`clock_period);
ASCII="M";
#(`clock_period);
ASCII="e";
#(`clock_period);
ASCII="i";
#(`clock_period);
ASCII="G";
#(`clock_period);
ASCII="e";
#(`clock_period);
#(`clock_period);
ASCII="H";
#(`clock_period);
ASCII="e";
#(`clock_period);
ASCII="M";
#(`clock_period);
ASCII="I";
#(`clock_period);
ASCII="H";
#(`clock_period);
ASCII="E";
#(`clock_period);
ASCII="L";
#(`clock_period);
ASCII="L";
#(`clock_period);
ASCII="O";
#(`clock_period);
ASCII="H";
#(`clock_period);
ASCII="e";
#(`clock_period);
ASCII="l";
#(`clock_period);
ASCII="l";
#(`clock_period);
ASCII="o";
#(`clock_period);
end
end
endmodule