Verilog实战:手把手教你用Moore和Mealy状态机实现101序列检测(附完整代码)

张开发
2026/4/13 14:50:38 15 分钟阅读

分享文章

Verilog实战:手把手教你用Moore和Mealy状态机实现101序列检测(附完整代码)
Verilog实战从零构建101序列检测器的状态机艺术第一次接触状态机设计时我被它的优雅所震撼——用几个简单的状态就能描述复杂的行为逻辑。今天我们就来探索如何用Verilog实现经典的101序列检测器这不仅是FPGA初学者的必修课更是理解数字系统设计的绝佳案例。我们将从基础概念出发逐步构建可重叠/不可重叠的Moore和Mealy状态机最后通过仿真验证它们的差异。1. 状态机设计基础概念与选择在数字电路设计中状态机就像一个有记忆的智能开关它能根据历史输入决定当前行为。想象一个自动售货机投币金额不同它给出的响应也不同——这就是状态机的典型应用。Moore与Mealy的本质区别在于输出信号的产生方式Moore型输出仅取决于当前状态像一位深思熟虑的决策者Mealy型输出由当前状态和输入共同决定像一位随机应变的谈判专家选择哪种模型这取决于你的设计需求// Moore输出示例 always (*) begin if (current_state S3) dout 1; else dout 0; end // Mealy输出示例 always (*) begin if (current_state S2 din 1) dout 1; else dout 0; end对于101序列检测两种模型各有优势Moore机更稳定输出与时钟同步Mealy机响应更快输入变化立即影响输出提示初学者常犯的错误是混淆两种模型的状态转移图。记住Mealy的输出标注在转移箭头旁Moore的输出写在状态圆圈内。2. 可重叠检测器的实现可重叠检测意味着已匹配的序列可以部分用于新序列的识别。比如输入10101会触发两次检测位置0-2和位置2-4。2.1 Mealy型可重叠设计Mealy机的灵魂在于组合逻辑输出。下面这段代码展示了如何用三个状态实现检测module mealy_overlap( output reg dout, input clk, rst, din ); reg [1:0] state; parameter IDLE 0, S1 1, S2 2; always (posedge clk or negedge rst) begin if (!rst) state IDLE; else case(state) IDLE: state (din) ? S1 : IDLE; S1: state (din) ? S1 : S2; S2: state (din) ? S1 : IDLE; endcase end always (*) dout (state S2 din); endmodule关键点解析状态编码使用二进制编码节省触发器资源异步复位确保电路初始状态确定输出逻辑当处于S2状态且输入为1时立即输出2.2 Moore型可重叠设计Moore机需要额外状态来表示完整的序列匹配module moore_overlap( output reg dout, input clk, rst, din ); reg [1:0] state; parameter IDLE0, S11, S22, S33; always (posedge clk or negedge rst) begin if (!rst) state IDLE; else case(state) IDLE: state (din) ? S1 : IDLE; S1: state (din) ? S1 : S2; S2: state (din) ? S3 : IDLE; S3: state (din) ? S1 : S2; endcase end always (*) dout (state S3); endmodule状态转移对比表当前状态输入Mealy下一状态Moore下一状态IDLE1S1S1S10S2S2S21S1 (输出1)S33. 不可重叠检测器的实现不可重叠检测要求每次匹配后必须回到初始状态相当于重置检测过程。3.1 Mealy型不可重叠设计module mealy_non_overlap( output reg dout, input clk, rst, din ); reg [1:0] state; parameter IDLE0, S11, S22; always (posedge clk or negedge rst) begin if (!rst) state IDLE; else case(state) IDLE: state (din) ? S1 : IDLE; S1: state (din) ? S1 : S2; S2: if (din) begin state IDLE; dout 1; end else begin state IDLE; dout 0; end endcase end endmodule3.2 Moore型不可重叠设计module moore_non_overlap( output reg dout, input clk, rst, din ); reg [1:0] state; parameter IDLE0, S11, S22, S33; always (posedge clk or negedge rst) begin if (!rst) begin state IDLE; dout 0; end else begin case(state) IDLE: begin state (din) ? S1 : IDLE; dout 0; end S1: begin state (din) ? S1 : S2; dout 0; end S2: begin state (din) ? S3 : IDLE; dout 0; end S3: begin state IDLE; dout 1; end endcase end end endmodule4. 仿真验证与调试技巧没有验证的HDL代码就像没有试飞的飞机。我们使用$display和波形分析来验证设计module tb; reg clk0, rst1, din; wire mealy_out, moore_out; mealy_overlap u1(mealy_out, clk, rst, din); moore_overlap u2(moore_out, clk, rst, din); always #5 clk ~clk; initial begin $dumpfile(wave.vcd); $dumpvars; #10 rst 0; #10 rst 1; // 测试序列010110101011 din0; #10 din1; #10 din0; #10 din1; #10 din1; #10 din0; #10 din1; #10 din0; #10 din1; #10 din0; #10 din1; #10 din1; #10 $finish; end endmodule常见问题排查指南锁存器警告确保组合逻辑块中的所有路径都有赋值使用default分支覆盖所有可能性状态机卡死检查每个状态的转移条件是否完备添加超时恢复机制时序违例在高速时钟下可能需要流水线设计对输出寄存器化以提高稳定性注意仿真时建议同时观察状态寄存器和输出信号这能帮助你直观理解状态转移过程。状态机设计就像搭积木每个状态都是精心放置的模块。当我第一次看到自己设计的101检测器在波形图上正确响应时那种成就感至今难忘。建议你在理解本文代码后尝试修改检测模式比如11011序列这会让你对状态机的理解更加深刻。

更多文章