一、状态机基础:从概念到实战

大家好,我是你们的硬件设计讲师。今天咱们聊聊状态机——这个在数字电路里无处不在的东西。

说实话,我刚开始学硬件那会儿,觉得状态机就是个高大上的概念。后来做了几个项目才发现,它其实就是个「有限状态的机器」。你想想看,任何需要按步骤执行的操作,背后都藏着一个状态机。

1.1 什么是状态机?

状态机,全称有限状态机(FSM)。说白了,就是一个系统在有限个状态之间跳来跳去。每个时刻它只能处于其中一个状态,遇到特定事件就切换到另一个状态。

举个最简单的例子——你家的自动门。它只有两个状态:打开和关闭。当有人靠近(事件),门从关闭变成打开(动作)。人走远了,门再关回去。这就是一个活生生的状态机。

我在做FPGA项目时,经常用状态机来控制DDR内存的读写时序。那玩意儿状态多得很,但核心逻辑没变——状态、事件、动作,三样东西搞定一切。

核心要点:状态机不是玄学,它就是「当前状态 + 输入事件 → 下一状态 + 输出动作」的循环。

1.2 状态机的三要素

状态机有三个核心要素,我习惯叫它们「铁三角」:

  • 状态(State):系统在某个时刻的稳定情况。比如门的「打开」和「关闭」。
  • 事件(Event):触发状态变化的条件。比如「有人靠近」这个信号。
  • 动作(Action):状态变化时执行的操作。比如「电机转动把门打开」。

这三个东西缺一不可。没有状态,系统就是乱的;没有事件,状态永远不变;没有动作,状态变了也没意义。

我曾经接手过一个同事的代码,状态机里只定义了状态和事件,动作全写在外部逻辑里。结果调试的时候,根本搞不清哪个动作对应哪个状态转换。嗯,那叫一个痛苦。

我的习惯:写状态机时,先把三要素列成表格。状态列出来,事件列出来,每个转换对应的动作也列出来。这样写代码时思路清晰,不容易漏掉边界情况。

1.3 状态机的分类:Moore型与Mealy型

状态机分两种:Moore型和Mealy型。这俩名字听着唬人,其实区别就一句话——输出什么时候产生。

特性 Moore型 Mealy型
输出依赖 只依赖当前状态 依赖当前状态 + 输入
输出时机 状态变化后立即输出 输入变化时立即输出
响应速度 慢一拍(一个时钟周期后) 快(组合逻辑直接输出)
抗干扰能力 强(输出稳定) 弱(输入毛刺会传出去)
典型应用 控制类、安全类电路 高速数据通路

Moore型:输出只跟当前状态有关。比如自动门,只要状态是「打开」,门就一直开着,不管有没有人。这种设计稳定,但响应慢一拍。

Mealy型:输出跟当前状态和输入都有关。比如自动门,有人靠近时立刻开门,人一走立刻关门。响应快,但输入信号有毛刺时,输出也会跟着抖。

我个人偏好Moore型,因为调试起来省心。但做高速接口时,Mealy型确实能省一个时钟周期。怎么选?看你的项目对延迟敏感还是对稳定性敏感。

避坑指南:我曾经在一个UART接收模块里用了Mealy型状态机,结果输入信号有毛刺,导致接收数据错位。后来改成Moore型,加了一级寄存器缓冲,问题就解决了。所以,如果你的输入信号质量不好,优先考虑Moore型。

1.4 状态机的图形化表示

光说理论太干,咱们画个图看看。下面是一个简单的交通灯状态机,用SVG画的。

红灯 绿灯 黄灯 计时到 计时到 计时到 交通灯状态机(Moore型) 三个状态,每个状态输出固定颜色

这个交通灯状态机是典型的Moore型。每个状态对应一个固定的输出颜色:红灯亮红灯,绿灯亮绿灯,黄灯亮黄灯。事件就是「计时到」,触发状态切换。

你可能会问:那Mealy型怎么画?其实结构一样,只是把输出写在箭头上。比如「红灯→绿灯」的箭头上写「计时到 / 输出绿灯」。这样输出就依赖输入事件了。

1.5 实战中的选择建议

说了这么多,到底怎么选?我给大家一个简单的判断方法:

  • 控制类电路(比如按键检测、协议解析):用Moore型。稳定第一,慢一拍无所谓。
  • 数据通路类(比如高速串行接口):用Mealy型。能省一个时钟周期就省一个。
  • 混合场景:把核心控制用Moore型,输出部分用Mealy型组合逻辑。这样既有稳定性又有响应速度。

一个小技巧:写Verilog时,我习惯把状态编码成独热码(one-hot)。虽然多用了几个触发器,但译码逻辑简单,时序容易收敛。尤其是状态数少于8个时,独热码比二进制编码好使。

好了,状态机的基础就聊到这儿。记住三要素、两种类型,再结合项目需求选型,基本不会出大问题。下一节咱们会深入状态机的编码方式和实际代码写法,到时候我会拿几个真实项目案例来讲。


可可精品资料库