5.4 状态机:Moore 与 Mealy 双实现


5.4 状态机:Moore 与 Mealy 双实现

本节摘要:状态机是时序设计的"大脑",由状态寄存器、次态逻辑、输出逻辑三件套组成。本节用同一需求(检测串行序列)分别实现 Moore 与 Mealy 两种状态机,对照状态数、输出时序与抗扰能力的差异,建立两种结构的选型手感。

先画图,再写码

状态机的需求表达就是一张状态图。以检测串行流中的序列 1-0-1-1 为例,先画 Moore 版:状态记录"当前已匹配到目标序列的第几位"。上电在空闲态 S0;收到 1 进 S1(匹配了一位);S1 收 0 进 S2;S2 收 1 进 S3;S3 再收 1 进 S4(匹配完成,输出检测脉冲);任何状态收到不符位都退回合适的状态。输出只在 S4 拉高——Moore 的输出只由状态决定

注意 S3 收 0 回 S1 而不是 S0——因为尾部的 1 可以当新序列的开头,这种"重叠匹配"的细节只有在画图时才会暴露,这正是"先画图"的价值。

Moore 实现:三件套的标准写法

VHDL 写状态机的标准姿势是枚举类型 + 双进程:

library ieee; use ieee.std_logic_1164.all; entity seq_det_moore is port ( clk, rst : in std_logic; ser_in : in std_logic; hit : out std_logic ); end entity seq_det_moore; architecture rtl of seq_det_moore is type state_t is (S0, S1, S2, S3, S4); -- 状态用枚举,可读且免编码烦恼 signal state : state_t := S0; begin -- 进程一:次态逻辑 + 状态寄存器(单进程写法,紧凑) process (clk) begin if rising_edge(clk) then if rst = '1' then state <= S0; else case state is when S0 => if ser_in = '1' then state <= S1; end if; when S1 => if ser_in = '0' then state <= S2; end if; when S2 => if ser_in = '1' then state <= S3; else state <= S0; end if; when S3 => if ser_in = '1' then state <= S4; else state <= S1; end if; when S4 => if ser_in = '1' then state <= S1; else state <= S0; end if; when others => state <= S0; end case; end if; end if; end process; -- 输出逻辑:纯组合,只看状态 hit <= '1' when state = S4 else '0'; end architecture rtl;

状态用 type state_t is (...) 枚举声明,综合器自动分配编码(通常顺序二进制)。要显式控制编码(比如格雷码防毛刺、独热码省译码逻辑),可以加 encoding 属性或改用常量向量定义状态——初学阶段交给工具即可。

Mealy 实现:少一个状态,快一拍

Mealy 机把输入也纳入输出条件:检测到 S3 状态且当前输入为 1,即可立刻宣布命中,不必专门设 S4。状态图少一个节点,输出提前一拍:

architecture rtl of seq_det_mealy is type state_t is (S0, S1, S2, S3); -- 少了 S4 signal state : state_t := S0; begin process (clk) begin if rising_edge(clk) then if rst = '1' then state <= S0; else case state is when S0 => if ser_in = '1' then state <= S1; end if; when S1 => if ser_in = '0' then state <= S2; end if; when S2 => if ser_in = '1' then state <= S3; else state <= S0; end if; when S3 => if ser_in = '1' then state <= S3; -- 命中且尾部可重叠 else state <= S1; end if; when others => state <= S0; end case; end if; end if; end process; -- 输出逻辑:状态与输入共同决定 hit <= '1' when state = S3 and ser_in = '1' else '0'; end architecture rtl;

Mealy 版 S3 收 1 停留在 S3——序列 1-0-1-1-1-1 连续命中,状态不必绕行,输出在输入有效的同一拍拉高。

图:两种结构的信号路径对比

图:两种结构的信号路径对比

双实现同台验证:差异看得见

给两版状态机喂同一串激励:1、0、1、1、0、1、0、1、1、1。对照波形找三处差异。差异一:状态数,Mealy 比 Moore 少一个状态,触发器占用更省。差异二:命中时刻,在序列第二次出现处,Mealy 的 hit 与最后一位输入同拍拉高,Moore 的 hit 晚一拍(要先跳进 S4)。差异三:毛刺敏感,Mealy 的 hit 是组合输出,输入在时钟间抖动会直接在 hit 上抖出毛刺;Moore 的 hit 从寄存器出发,天生干净。把 hit 定义成寄存器输出(在时钟进程里赋值)可以给 Mealy 补上这一拍延迟,代价是又变回"慢一拍"——工程上常见的折中是 Mealy 逻辑 + 输出打一拍

对比项 Moore Mealy
输出依赖 仅当前状态 状态与当前输入
状态数量 通常多一个"完成态" 更省
输出时延 对齐时钟沿、慢一拍 与输入同拍
抗输入毛刺 弱,必要时输出寄存
典型场景 显示驱动、总线仲裁 协议解析、快速响应

⚠️ 常见坑:状态机的 when others 漏写,或复位只复位了状态寄存器、忘了输出寄存器——前者在状态编码出现非法值时(例如上电亚稳态)整机卡死,后者复位后输出乱跳一拍。case 永远兜底,复位永远成套。

💡 关键直觉:状态机三件套——"记住现在(寄存器)、算出下一步(次态逻辑)、决定说什么(输出逻辑)"。画图时先写清每个状态"收到什么、去哪里、说什么",代码只是把这张表抄进去。

本节要点回顾

  • 先画状态图再写代码,重叠匹配这类细节只有图会提醒你;
  • 枚举类型定义状态,编码交给工具,可读性优先;
  • 单进程写法紧凑,双进程写法结构清晰,工程两种都常见;
  • Moore 输出慢一拍但干净,Mealy 省状态快一拍但怕毛刺;
  • 毛刺敏感场景给 Mealy 输出打一拍,用一拍延迟换信号质量;
  • when others 兜底 + 成套复位,是状态机的两条安全带。

作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U