状态机的分类

有限状态机(FSM)分为两类:摩尔型(Moore)和米勒型(Mealy)。输出仅与当前状态有关的状态机被定义为摩尔型状态机,输出不仅与当前状态有关还与输入有关的状态机被定义为米勒型状态机。状态机的组成要素有输入(包括复位)、状态(包括当前状态的操作)、状态转移条件、状态的逻辑输出,关于摩尔型与米勒型状态机的基本框架如下图所示:

状态机基本框架

有限状态机包含以下三个状态:
1.次态逻辑:负责状态机逻辑状态转移,是组合电路。其输入包括当前状态和外部输入信号。
2.状态记忆:储存当前的逻辑状态,是寄存器时序逻辑。次态逻辑的输出是它的输入信号。
3.输出逻辑:负责逻辑输出的电路部分。

基于上述的分析可知:摩尔有限状态机最重要的特点就是将输入信号与输出信号相隔离,因此输出稳定,输入信号不能传输到输出能有效滤除冒险。而米勒型状态机输出与当前状态和输入信号均有关,因此当输入信号在一个时钟周期内任意时刻变化时,会导致输入的响应发生在当前时钟周期,比摩尔机输入信号的响应要早一个时钟周期。所以输入信号的噪声可能影响输出信号,因此米勒机输出具有冒险现象且不能滤除。

状态机的仿真分析

为了对上述分析进行仿真,计划采用摩尔型状态机和米勒型状态机分别实现以下状态转移图:

状态转移图

在Vivado平台上编写好相应的.v文件和testbench文件后仿真结果如下图所示:

状态机仿真结果

从仿真结果可以看出:当输入在某一时钟周期内部发生改变时米勒机的输出立马发生相应的变化,而摩尔型状态机则等到下一时钟上升沿到来后才会产生对应的输出,符合预期分析。

仿真用的.v文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
module state_machine(indata,clk,reset,outdata_mealy,outdata_moore);

input indata,clk,reset;
output [1:0] outdata_mealy,outdata_moore;
reg [1:0] outdata_mealy,outdata_moore;
reg [1:0] pre_state_mealy,next_state_mealy,pre_state_moore,next_state_moore;
parameter a=2'b00,b=2'b01,c=2'b10,d=2'b11;

//米勒机
//状态复位
always@(posedge clk or posedge reset)
begin
if(reset)
pre_state_mealy <= a;
else
pre_state_mealy <= next_state_mealy;
end

//状态转移过程
always@(pre_state_mealy or indata)
begin
case (pre_state_mealy)
a: begin
if (indata == 1)
next_state_mealy <= a;
else
next_state_mealy <= b;
end
b: begin
if (indata == 1)
next_state_mealy <= a;
else
next_state_mealy <= c;
end
c: begin
if (indata == 1)
next_state_mealy <= a;
else
next_state_mealy <= d;
end
d: begin
next_state_mealy <= a;
end
default: next_state_mealy <= a;
endcase
end

//状态输入映射输出(此时输入输出不隔离)
always@(pre_state_mealy or indata)
begin
case (pre_state_mealy)
a: begin
if(indata == 1)
outdata_mealy <= 2'b00;
else
outdata_mealy <= 2'b01;
end
b: begin
if(indata == 1)
outdata_mealy <= 2'b00;
else
outdata_mealy <= 2'b10;
end
c: begin
if(indata == 1)
outdata_mealy <= 2'b00;
else
outdata_mealy <= 2'b11;
end
d: begin
outdata_mealy <= 2'b00;
end
default: outdata_mealy <= 2'b00;
endcase
end

//摩尔机
always@(posedge clk or posedge reset)
begin
if(reset == 1)
pre_state_moore <= a;
else
pre_state_moore <= next_state_moore;
end

always@(pre_state_moore or indata)
begin
case (pre_state_moore)
a: begin
if (indata == 1)
next_state_moore <= a;
else
next_state_moore <= b;
end
b: begin
if (indata == 1)
next_state_moore <= a;
else
next_state_moore <= c;
end
c: begin
if (indata == 1)
next_state_moore <= a;
else
next_state_moore <= d;
end
d: begin
next_state_moore <= a;
end
default: next_state_moore <= a;
endcase
end
always@(pre_state_moore)
begin
case (pre_state_moore)
a: begin
if(indata == 1)
outdata_moore <= 2'b00;
else
outdata_moore <= 2'b01;
end
b: begin
if(indata == 1)
outdata_moore <= 2'b00;
else
outdata_moore <= 2'b10;
end
c: begin
if(indata == 1)
outdata_moore <= 2'b00;
else
outdata_moore <= 2'b11;
end
d: begin
outdata_moore <= 2'b00;
end
default: outdata_moore <= 2'b00;
endcase
end

endmodule

测试平台的仿真文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
`timescale 1ns / 1ns
`define CLOCK_PERIOD 100

module state_machine_tb();

reg indata;
reg reset;
reg clk;
wire [1:0] outdata_mealy;
wire [1:0] outdata_moore;

state_machine state_machine_inst1 (
.indata(indata),
.clk(clk),
.reset(reset),
.outdata_mealy(outdata_mealy),
.outdata_moore(outdata_moore)
);

initial clk = 1;
always #(`CLOCK_PERIOD/2) clk=~clk;

initial begin
reset = 1'b1;
indata = 1'b0;
#6;
reset = 1'b0;
#(`CLOCK_PERIOD *6 +60);
indata = 1'b1;
#(`CLOCK_PERIOD *3);
$stop;
end

endmodule