1、介绍
状态机(FSM,Finite State Machine),也称为同步有限状态机,其“同步”指的是所有状态跳转在时钟信号的作用下进行,而“有限”则表示状态的数量是有限的。每个状态代表一个事件,状态的跳转或转移发生在当前事件执行后,从而使系统能够正常运转。通过控制状态间的跳转,状态机使得流程更加清晰易懂,特别适合于管理复杂的控制流程,展现出明显的优势。
2、写法
根据状态机的输出是否与输入条件相关,可将状态机分为两大类,即摩尔(Moore)型状态机和米利(Mealy)型状态机。
米利状态机模型是一种有限状态机,其输出依赖于当前状态和输入信号。它由三个主要部分组成:组合逻辑用于根据当前状态和输入生成下一状态,状态寄存器存储当前状态并在时钟边沿更新,而组合逻辑则根据当前状态和输入实时计算输出。
摩尔状态机的模型如下图所示,摩尔状态机的输出只取决于当前状态。
区别:
米利状态机:输出依赖于当前状态和输入信号。这意味着输出可以根据输入的变化即时更新,适合需要快速反应的场合。例如,当输入变化时,输出可能立即改变,即使当前状态没有改变。
摩尔状态机:输出仅依赖于当前状态,输出在状态改变时更新。这意味着输出在进入新状态时才会改变,而不受输入的即时影响。这种结构通常使得系统行为更为稳定,适合对输出变化的延迟要求较高的场景。
3、类型
根据状态机的实际写法,可以将其分为一段式、二段式和三段式状态机:
1.一段式状态机:
- 整个状态机逻辑集中在一个 always 模块中,既负责状态转移,又描述状态的输入和输出。
- 缺点:不推荐使用,因为组合逻辑和时序逻辑混合在一起,导致代码风格不佳,增加了维护和修改的难度。
2、 二段式状态机:
- 使用两个 always 模块来描述状态机。一个模块负责同步时序描述状态转移,另一个模块采用组合逻辑判断状态转移条件,并描述状态转移规律及输出。
- 特点:需要定义现态和次态,通过这两者的转换实现时序逻辑。相比一段式,二段式更清晰,便于维护。
3、 三段式状态机:
- 在二段式的基础上,使用三个 always 模块。一个模块用于同步时序描述状态转移,第二个模块用于组合逻辑判断状态转移条件并描述转移规律,第三个模块专门描述状态输出,可以采用组合电路或时序电路进行输出。
- 优势:这种设计进一步提高了代码的可读性、可维护性和可扩展性,适合于处理复杂的控制任务。
4、案例
设计一个简单的交通灯控制系统时,可以利用状态机来管理红灯、黄灯和绿灯的状态转移,其红绿灯状态跳转图,如下图所示:
例程:
verilog
module traffic_light(
input clk, // 时钟信号
input rst, // 复位信号
output reg [2:0] light // 交通灯输出,3位,0: 红灯, 1: 绿灯, 2: 黄灯
);
// 状态定义
localparam RED = 2'b00; // 红灯状态
localparam GREEN = 2'b01; // 绿灯状态
localparam YELLOW = 2'b10; // 黄灯状态
reg [1:0] current_state;
reg [1:0] next_state; // 当前状态和下一个状态
reg [3:0] counter; // 计时器
// 状态转移逻辑
always @(posedge clk or posedge rst) begin
if (rst) begin
current_state <= RED; // 初始状态为红灯
counter <= 0; // 计数器重置
end
else if (counter == 4'b1111) begin
current_state <= next_state; // 状态转移
counter <= 0; // 计数器重置
end
else begin
counter <= counter + 1; // 增加计数
end
end
// 下一个状态逻辑
always @(*) begin
case (current_state)
RED: next_state = GREEN; // 从红灯转到绿灯
GREEN: next_state = YELLOW; // 从绿灯转到黄灯
YELLOW: next_state = RED; // 从黄灯转到红灯
default: next_state = RED; // 默认状态
endcase
end
// 输出逻辑
always @(posedge clk or negedge rst) begin
case (current_state)
RED: light = 3'b100; // 红灯
GREEN: light = 3'b001; // 绿灯
YELLOW: light = 3'b010; // 黄灯
default: light = 3'b100; // 默认红灯
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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
注释:
- 第 17 - 29 行:这里实现一个计数器,当计数器达到预设值时,进行状态转移和继续计时。
- 第 32 - 39 行:这里是切换到下一个状态,而不是基于输入条件。在实际应用中,一般根据输入的条件来判断是否跳转到其它状态或者停留在当前转态,
- 第 42 - 49 行:这里是将状态利用时序输出。可以更具体地描述输出信号的内容。