一、状态机基础回顾:Moore机与Mealy机,状态编码,状态转移图与状态表

各位同学,咱们今天聊聊状态机的基础。说实话,状态机这东西,你刚学的时候觉得挺简单,不就是几个状态跳来跳去嘛。但我在项目里见过太多因为状态机没设计好导致的bug——要么是毛刺满天飞,要么是功耗高得离谱,要么是时序收敛不了。所以,咱们先把基础打扎实了。

1.1 Moore机与Mealy机:两种基本模型

先说说这两种状态机的区别。Moore机和Mealy机,说白了就是输出跟谁有关的问题。

  • Moore机:输出只取决于当前状态。换句话说,只要状态不变,输出就保持不变。
  • Mealy机:输出取决于当前状态 和 当前输入。输入一变,输出可能立刻跟着变。

我刚开始做设计时,总觉得Mealy机更灵活,所以啥都用Mealy。后来有一次做低功耗项目,发现Mealy机的输出组合逻辑路径太长,导致时序紧张,功耗也上去了。嗯,从那以后我学会了——该用Moore的时候别犹豫。

关键区别速览

特性Moore机Mealy机
输出依赖仅当前状态当前状态 + 当前输入
输出变化时机时钟沿后输入变化时(组合逻辑)
状态数通常较多通常较少
对毛刺敏感度较低较高(输入直接影响输出)
典型应用控制逻辑、安全关键电路高速数据通路、协议解析

你想想看,如果你的输出要驱动一个对毛刺很敏感的模块,比如时钟门控信号,那用Moore机更安全。反过来,如果你需要快速响应输入变化,比如在SPI或I2C的从机端,Mealy机可能更合适。

1.2 状态编码:二进制、格雷码、独热码

状态编码这事儿,我见过太多人随便选一个就上了。其实编码方式直接影响功耗、面积和时序。咱们一个一个说。

二进制编码

最直观的方式。状态用二进制数表示,比如S0=00, S1=01, S2=10, S3=11。优点是状态寄存器数量最少(log2(N)个触发器),面积小。但缺点也很明显——状态跳转时可能有多位同时变化,产生大量毛刺,动态功耗高。

我曾经在一个低功耗项目中,一开始用了二进制编码,结果后仿发现状态跳转时的电流尖峰特别大。后来换成格雷码,尖峰直接降了一半。

格雷码编码

格雷码的特点是相邻状态之间只有一位不同。比如S0=00, S1=01, S2=11, S3=10。这样在顺序跳转时,每次只有一个触发器翻转,动态功耗显著降低。

但要注意,格雷码只适合顺序跳转的场景。如果你的状态机有大量非顺序跳转(比如从S0直接跳到S3),那格雷码的优势就没了,甚至可能更差。

独热码编码

每个状态用一个独立的触发器表示,比如S0=0001, S1=0010, S2=0100, S3=1000。优点是译码逻辑非常简单(直接取触发器的输出),时序好,适合高速设计。但缺点也很明显——状态数多的时候,触发器数量线性增长,面积大,静态功耗高。

我的经验之谈

在低功耗设计中,我一般这样选:

  • 状态数 ≤ 8 且顺序跳转多 → 格雷码
  • 状态数 ≤ 16 且需要高速 → 独热码
  • 状态数 > 16 或面积受限 → 二进制码

当然,这只是经验,具体还得看你的功耗和时序目标。

1.3 状态转移图与状态表

状态转移图和状态表,是状态机设计的两个基本工具。我个人的习惯是:先画图,再填表,最后写代码。这样不容易漏状态。

状态转移图

用圆圈表示状态,箭头表示转移,箭头上的标签表示转移条件。Moore机的输出写在圆圈里,Mealy机的输出写在箭头上。

举个例子,一个简单的3状态Moore机:

S0 out=0 S1 out=1 S2 out=0 a=1 b=1 c=1 a=0 b=0 c=0

状态表

状态表就是把图里的信息用表格形式整理出来。对于上面的Moore机,状态表是这样的:

当前状态输入条件下一状态输出
S0a=0S00
S0a=1S10
S1b=0S11
S1b=1S21
S2c=0S20
S2c=1S00

避坑指南

我曾经在写状态表时漏掉了一个转移条件,结果仿真时状态机卡死在一个状态里出不来。后来我养成了一个习惯:写完状态表后,检查每个状态的所有输入组合是否都有对应的转移。如果某个输入组合没写,默认是自环还是跳转到某个安全状态?一定要明确。

1.4 小结

好了,这一章咱们把状态机的基础过了一遍。Moore机和Mealy机的选择、三种编码方式的权衡、状态图和状态表的画法,这些都是后续低功耗设计的基础。下一章咱们会深入讨论状态机功耗的来源,以及如何从架构层面做优化。

本章要点速记

  • Moore机输出稳定,适合安全关键电路;Mealy机响应快,适合高速数据通路
  • 状态编码选对了,功耗能降一半;选错了,后仿有你哭的
  • 状态图+状态表,双保险,别偷懒

可可精品资料库