有限状态机(FSM)设计实例
有限状态机(Finite State Machine, FSM)是数字系统设计中处理时序逻辑的重要模型,广泛应用于序列检测、控制逻辑、协议处理等场景。以下通过三个典型案例,详细展示 Moore 型和 Mealy 型状态机的设计方法。
一、Moore 型状态机:序列检测(检测 “101” 序列)
功能描述
输入一个串行比特流,当检测到连续输入 “101” 时,输出 detect 信号为高电平(持续 1 个周期)。输出仅依赖于当前状态(Moore 型)。
状态定义(二进制编码)
状态 | 编码 | 含义 |
---|---|---|
S0 | 2’b00 | 初始状态(无有效输入) |
S1 | 2’b01 | 检测到第一个 ‘1’ |
S2 | 2’b10 | 检测到 ‘10’ 序列 |
S3 | 2’b11 | 检测到 ‘101’ 序列(终止状态) |
状态转移图
Verilog 代码实现
状态的存储和状态转换的逻辑进行分离,实现代码块之间的解耦
存储很简单,而状态的转换其实就是多个组合逻辑电路(多个子神经元)
module sequence_detector (
input clk, // 时钟
input rst_n, // 复位(低有效)
input din, // 输入比特流
output reg detect // 检测信号(高有效)
);
// 状态定义
parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
reg [1:0] current_state, next_state;
// 状态寄存器(时序逻辑)
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
current_state <= S0;
else
current_state <= next_state;
end
// 状态转移逻辑(组合逻辑)
always @(*) begin
case (current_state)
S0: begin
if (din == 1'b1)
next_state = S1;
else
next_state = S0;
end
S1: begin
if (din == 1'b0)
next_state = S2;
else if (din == 1'b1) // 连续'1',保持S1
next_state = S1;
else
next_state = S0; // 非法输入,默认回到S0
end
S2: begin
if (din == 1'b1)
next_state = S3;
else if (din == 1'b0) // '10'后接'0',回到S0(无法形成有效序列)
next_state = S0;
else
next_state = S0;
end
S3: begin
if (din == 1'b1) // '101'后接'1',进入S1(新序列开始)
next_state = S1;
else if (din == 1'b0) // '101'后接'0',回到S0
next_state = S0;
else
next_state = S0;
end
default: next_state = S0;
endcase
end
// 输出逻辑(仅依赖当前状态,Moore型)
always @(*) begin
detect = (current_state == S3) ? 1'b1 : 1'b0;
end
endmodule
二、Mealy 型状态机:带使能的模 3 计数器
功能描述
当使能信号 en 为高电平时,计数器在时钟上升沿递增,计数到 2 后回到 0;en 为低电平时保持当前值。输出 cout 在计数值为 2 且 en 为高时产生进位信号(提前一个周期响应输入,Mealy 型)。
状态定义(独热码编码,适合 FPGA)
Verilog
parameter S0 = 3'b001, S1 = 3'b010, S2 = 3'b100; // 3个状态,独热码
状态转移与输出逻辑
当前状态 | 输入 en | 下一状态 | 输出 cout |
---|---|---|---|
S0 | 0 | S0 | 0 |
S0 | 1 | S1 | 0 |
S1 | 0 | S1 | 0 |
S1 | 1 | S2 | 0 |
S2 | 0 | S2 | 0 |
S2 | 1 | S0 | 1 |
状态转移图
Verilog 代码实现
module mod3_counter (
input clk, // 时钟
input rst_n, // 复位(低有效)
input en, // 使能信号(高有效)
output reg [1:0] q, // 计数值(0-2)
output reg cout // 进位信号(高有效)
);
// 状态定义(独热码)
parameter S0 = 3'b001, S1 = 3'b010, S2 = 3'b100;
reg [2:0] current_state, next_state;
// 状态寄存器
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
current_state <= S0;
else
current_state <= next_state;
end
// 状态转移与输出逻辑(Mealy型,输出依赖输入en)
always @(*) begin
case (current_state)
S0: begin
q = 2'b00;