学习有限状态机(FSM)的设计

  • 学习有限状态机FSM的设计
  • 状态机设计
    • 1状态机分类
    • 2有限状态机的状态编码
      • 二进制码
      • 格雷码
      • 独热码
      • 自定义编码
      • 编码总结
    • 3状态机的设计准则
      •  基本准则
      •  一般步骤
    • 4状态机的描述方法
    • 5状态机模板
      • 一段式
      • 两段式
      • 三段式一
      • 三段式格式 二onehot 编码
  • 总结

什么是状态机?简单来说,就是通过不同的状态迁移来完成一些特定的顺序逻辑。
FSM定义:
一个有限状态机是一个设备,或者是一个设备模型,具有有限数量的状态,它可以在任何给定的时间根据输入进行操作,使得一个状态变换到另一个状态,或者是使一个输入或者一种行为的发生。一个有限状态机在任何瞬间只能处在一种状态。
它的优点:
1.编程快速简单,2.易于调试,3.很少的计算开销,4.直觉性,5.灵活性。


图1-1 状态机图例

无论是在C\C++等的高级语言编程,还是用硬件描述语言(verilog HDL)中都会涉及到相关的知识点,学习下来作为自己的知识储备确是一件幸事。


状态机设计

1、状态机分类

如果时序逻辑的输出不但取决于状态还取决于输入,称为 Mealy 状态机。如果输入变化,这类状态机的输出可能在一个时钟周期的中间跟着改变。


图1-2 Mealy 状态机

而有些时序逻辑电路的输出只取决于当前状态,这样的电路就称为 Moore状态机。这类状态机输出和输入成隔离状态:输出将在剩余的时钟周期内保持稳定(为一个常数),即使输入在时钟周期内变化。


图1-3 Moore状态机

2、有限状态机的状态编码

常用的编码有三种:二进制编码、 格雷码 (Gray) 、独热码 (one-hot) 编码。另外,还可以自定义编码,比如在高速设计中以状态编码作为输出。

二进制码

二进制码从一个状态转换到相邻状态时,可能有多个比特位发生变化,易产生中间状态转移问题,状态机的速度也要比采用其它编码方式慢。

格雷码

格雷码两个相邻的码值仅有一位就可区分,这将会减少电路中相邻物理信号线同时变化的情况,因而可以减少电路中的电噪声。Johnson码也有同样的特点,但是要用较多的位数。

独热码

独热码(One-hot)指对任意给定的状态,状态寄存器中只有l位为1,其余位都为0。n状态的有限状态机需要n个触发器,但这种有限状态机只需对寄存器中的一位进行译码,简化了译码逻辑电路,额外触发器占用的面积可用译码电路省下来的面积抵消。当设计中加入更多的状态时,译码逻辑没有变得更加复杂,有限状态机的速度仅取决于到某特定状态的转移数量,而其它类型有限状态机在状态增加时速度会明显下降。独热码还具有设计简单、修改灵活、易于综合和调试等优点。独热码相对于二进制码,速度快但占用面积大。

自定义编码

自定义编码相对灵活。在设计高速电路时,常常有必要使状态机的输出与时钟几乎完全同步。有一个办法是把状态变量(也可能是状态变量中的几位)直接用作输出,称为输出编码的状态指定。属于 Moore 状态机。但这种方法也有缺点,就是开关的维持时间必须与状态维持的时间一致,需要增加状态才能实现。
设计高速状态机时,在输出逻辑 G 后面再加一组与时钟同步的寄存器输出流水线寄存器,让 G 所有的输出信号在下一个时钟跳变沿时同时存入寄存器组,即完全同步地输出,把这种输出称为流水线化的输出。

编码总结

从设计大小的角度来看,在小设计中可以考虑使用 Gray 码或 one-hot。大设计中,由于现在技术进步几乎不用考虑逻辑资源不够的问题,可以考虑使用one-hot 编码以提高速度。至于顺序二进制编码,一般不予考虑。但是要达到最佳性能,需要使用更高级的编码算法,针对给定的状态机进行分析。
从 FPGA/CPLD 的角度来看,由于 CPLD 提供更多的组合逻辑资源,而 FPGA提供更多的触发器资源,所以 CPLD 多使用 Gray 码,而 FPGA 多使用 one-hot编码。

3、状态机的设计准则

1 基本准则

  (1) 一个Verilog模块至多描述一个有限状态机。这样不仅可以简化状态的定义、修改和调试,还可以利用一些EDA工具来协助设计。
  (2) 使用参数给状态赋值,而不是用宏定义(‘define)。因为’define宏定义在编译时自动替换整个设计中所定义的宏,而parameter仅仅定义模块内部的参数,定义的参数不会与模块外的其它状态机混淆。
  (3) 用always模块写组合逻辑时,采用阻塞赋值,而在always块中建立时序电路时,用非阻塞赋值。这样才能保证有限状态机综合前和综合后仿真的一致性。

2 一般步骤

  1. 逻辑抽象得出状态转换图
      就是把给出的一个实际逻辑关系表示为时序逻辑函数,可以用状态转换表来描述,也可以用状态转换图来描述。这就需要:
      1) 分析给定的逻辑问题,确定输入变量、输出变量以及电路的状态数。通常是取原因(或条件)作为输入变量,取结果作为输出变量。
      2) 定义输入、输出逻辑状态的含义,并将电路状态顺序编号。
      3) 按照要求列出电路的状态转换表或画出状态转换图。
    这样,就把给定的逻辑问题抽象到了一个时序逻辑函数了。

  2. 状态化简
      如果在状态转换图中出现这样两个状态,它们在相同的输入转换到同一状态去,并得出一样的输出,则称为等价状态。显然等价状态是重复的,一合并为一个电路的状态数越少,存储电路也就越简单。状态化简的目的就是在于将等价状态尽可能地的合并,以得到最简的状态转换图。

  3. 状态分配

  4. 选定触发器的类型并求出状态方程、驱动方程和输出方程。

  5. 按照方程得出逻辑图
      用Verilog HDL来描述有限状态机,可以充分发挥硬件描述语言的抽象建模能力,使用always块语句和case(if)等条件语句及赋值语句即可方便实现。具体的逻辑化简、逻辑电路到触发器映射均可有计算机自动完成。步骤中的2、4、5不再需要人为干预,使电路设计工作得到简化,效率也有很大的提高。
    ———————————–节选之夏宇闻老师的Verilog HDL数字系统块设计教程(第2版)

4、状态机的描述方法

(1)一段式
使用一个always模块包含整个状态机他不符合将时序和组合逻辑分开描述的Coding Style,而且在描述当前状态时要考虑下个状态的输出,整个代码不清晰,不利于维护修改,并且不利于附加约束,不利于综合器和布局布线器对设计的优化。一般来说,一段式代码长度会比两段式冗长大约80%到150%左右。


图1-4 一段式状态机

(2)两段式
使用两个always模块,其中一个always模块采用同步时序的方式描述状态转移,而另一个模块采用组合逻辑的方式判断状态转移条件、描述状态转移规律,称两段式FSM描述方法;为了使FSM描述清晰简洁、易于维护、易于附加时序约束,使综合器和布局布线器更好的优化设计,推荐使用两段式FSM描述方法。请注意,虽然下一状态寄存器 NS 为寄存器类型,但是在两段式 FSM 的判断状态转移条件的 always 块中,实际对应的真实硬件电路是纯组合逻辑电路。


图1-5 两段式状态机

(3)三段式
使用三个 always 模块,一个 always 模块采用同步时序的方式描述状态转移,一个采用组合逻辑的方式判断状态转移条件、描述状态转换规律,第三个 always模块使用同步时序电路描述每个状态的输出,称三段式写法。


图1-6 三段式状态机

综上,得出三种描述 FSM 方法的比较表

5、状态机模板

一段式

###两段式

两段式

二段式格式(组合逻辑输出)
always @ (posedge clk or negedge nrst)
if (!nrst)CS <= IDLE;
elseCS <=NS;//敏感列表必须完整:当前状态及所有相关组合逻辑输入
always @ (nrst or CS or i1 or i2) begin
//第二段 always 中,组合逻辑电平要维持超过一个 clock,仿真时注意。NS = 3'b0; //此处赋值一般有三种方式:(1) X,(2) IDLE (3)不改变//注:因为仿真时“X”视为“don’t care”,所以赋值“X”适合 debug//而实现时,赋值“IDLE”或者“0”ERROR_out;case (CS)IDLE: beginIDLE_out;if (~i1) NS = IDLE;if (i1 && i2) NS = S1;if (i1 && ~i2) NS = ERROR;// 里面判断条件一定要包含所有情况(即 i1 和i2 的四种情况)!可以用 else 保证包含完全。endS1: beginS1_out;if (~i2) NS = S1;if (i2 && i1) NS = S2;if (i2 && (~i1)) NS = ERROR;endS2: beginS2_out;if (i2) NS = S2;if (~i2 && i1) NS = IDLE;if (~i2 && (~i1)) NS = ERROR;endERROR: beginERROR_out;if (i1) NS = ERROR;if (~i1) NS = IDLE;endendcase
end
task S1_out;//对于输出一般用组合逻辑描述,比较简便的方法是用 task 将输出封装起来。{o1,o2,err} = 3'b100;
Endtask

三段式(一)


图1-7 三段式状态机示例

module fsm_cc8_3r(output reg y1, y2, y3,input jmp, go, sk0, sk1, clk, rst_n);
parameter S0 = 4'b0000,S1 = 4'b0001,S2 = 4'b0010,S3 = 4'b0011,S4 = 4'b0100,S5 = 4'b0101,S6 = 4'b0110,S7 = 4'b0111,S8 = 4'b1000,S9 = 4'b1001;
reg [3:0] state, next;//第一个进程,同步时序 always 块,格式化描述次态寄存器迁移到现态寄存器
always @(posedge clk or negedge rst_n) //异步复位if (!rst_n)state <= S0;elsestate <= next; //注意,使用的是非阻塞赋值
//第二个进程,组合逻辑块,判断状态转移条件,电平触发,敏感列表要完备
always @(state or jmp or go or sk0 or sk1) beginnext = 4'bS0; //要初始化,使得系统复位后能进入正确的状态,和 case 中的 default 作用相当,但//不完全等同于把其放在 default 里赋值。因为根据顺序执行语句,这里对所有未//在case 语句中赋值的变量赋值。case (state) //每一状态的条件判断要完备!S0 : if (!go) next = S0; //阻塞赋值else if (jmp) next = S3;else next = S1;S1 : if (jmp) next = S3;else next = S2;S2 : if (jmp) next = S3;else next = S9;S3 : if (jmp) next = S3;else next = S4;S4 : if (jmp) next = S3;else if (sk0 && !jmp) next = S6;else next = S5;S5 : if (jmp) next = S3;else if (!sk1 && !sk0 && !jmp) next = S6;else if (!sk1 && sk0 && !jmp) next = S7;else if ( sk1 && !sk0 && !jmp) next = S8;else next = S9;S6 : if (jmp) next = S3;else if (go && !jmp) next = S7;else next = S6;S7 : if (jmp) next = S3;else next = S8;S8 : if (jmp) next = S3;else next = S9;S9 : if (jmp) next = S3;else next = S0;endcaseend//第三个进程,同步时序 always 模块,格式化描述次态寄存器输出
always @(posedge clk or negedge rst_n)if (!rst_n) begin //初始化y1 <= 1'b0;y2 <= 1'b0;y3 <= 1'b0;endelse begin //可以防止 latch,如上述。y1 <= 1'b0;y2 <= 1'b0;y3 <= 1'b0;case (next) //注意是下一个状态,即预判S0, S2, S4, S5 : ; // default outputsS7 : y3 <= 1'b1; //注意是非阻塞逻辑S1 : y2 <= 1'b1;S3 : beginy1 <= 1'b1;y2 <= 1'b1;endS8 : beginy2 <= 1'b1;y3 <= 1'b1;endS6, S9 : beginy1 <= 1'b1;y2 <= 1'b1;y3 <= 1'b1;endendcaseend
endmodule

三段式格式 (二)–onehot 编码

parameter S0 = 0, S1 =1, S2 =2, S3 =3, S4 =4, S5= 5, S6 = 6, S7 = 7, S8 = 8, S9 =9;
reg [9:0] current_state, next_state;//第一个进程,同步时序 always 模块,格式化描述次态寄存器迁移到现态寄存器
always @ (posedge clk or negedge rst_n) //异步复位if(!rst_n) begincurrent_state <=0;current_state[S0] <=1’b1;endelsecurrent_state <= next_state; //注意,使用的是非阻塞赋值//第二个进程,组合逻辑 always 块,判断状态转移条件, onehot 需要加综合约束
full case
always @ (current_state or input1 or input2 ) //电平触发,包括所有组合逻辑输入beginnext_state = 0; //初始化(0 或 IDLE),使系统复位后能进入正确的状态case(1’b1) // synthesis parallel_case full_casecurrent_state[S0]: if(...)next_state [S1]= 1’b1; //阻塞赋值current_state[S1]: if(...)next_state [S2]= 1’b1; //阻塞赋值...endcaseend//第三个进程,同步时序 always 模块,格式化描述次态寄存器输出
always @ (posedge clk or negedge rst_n)if(!rst_n) beginOut1<= 1’b0;Out2<= 1’b0;Out3<= 1’b0;endelse beginOut1<= 1’b0;Out2<= 1’b0;Out3<= 1’b0;case(1’b1) //注意是下一个状态,即预判next_state [S0]: out1 <= 1'b1; //注意是非阻塞逻辑next_state [S1]: out2 <= 1'b1;…endcase //注意,没有 default 选项了end

总结

有限状态机是实现高效率、高可靠性数字系统的重要全知途径,使用Verilog HDL描述有限状态机时可以有不同的状态编码方式和描述风格,实际应用中应根据具体情况和要求来选择,编码方式的选择跟器件结构和状态数目有关,描述风格则推荐使用两段式和三段式,应该尽量避免使用一段式。

参考:
1、有限状态机(FSM)设计原理 http://blog.csdn.net/Pieces_thinking/article/details/76132201?locationNum=1&fps=1
2、状态机设计 V2.0 by foreveryoung http://www.cnblogs.com/foreveryoung/

FPGA--有限状态机(FSM)的设计相关推荐

  1. [转载][FPGA]有限状态机FSM学习笔记(二)

    1. Mealy和Moore状态机的互换 对于给定的时序逻辑功能,可以用Mealy机实现,也可以用Moore机实现.根据Moore机比Mealy机输出落后一个周期的特性,可以实现两种状态机之间的转换. ...

  2. 【算法】有限状态机FSM

    目录 一.快速理解 1.有限状态机(FSM) 2.有限状态机的设计 二.详细说明 1.有限状态机FSM 1)FSM概念 2)FSM的3特点 3)FSM的4要素 4)FSM状态转换图 2.FSM的设计和 ...

  3. 基于FPGA的电子计算器设计(上)

    今天给大侠带来基于FPGA的电子计算器设计,由于篇幅较长,分三篇.今天带来第一篇,上篇,话不多说,上货. 导读 本篇介绍了一个简单计算器的设计,基于 FPGA 硬件描述语言 Verilog HDL,系 ...

  4. 一段式、两段式以及三段式状态机(FSM)设计实例

    一段式.二段式以及三段式状态机(FSM)设计实例 状态机(FSM)分类 状态转移的三种编码方式 一段式.两段式状态机(FSM)区别 vivado与modelsim联调显示状态机 设计实例 状态转移图 ...

  5. Cocos Creator 超简洁代码实现有限状态机 FSM,打造丝滑角色动作

    引言:本文作者黄聪是一名在校大学生,设计毕设的过程中,他参考<游戏编程模式>一书,摸索出了一套角色动作控制方案. 作为一名在校学生,前段时间在做毕业设计的过程中,我也遇到了很多同学都会遇到 ...

  6. 什么是有限状态机FSM

    什么是有限状态机FSM 简介 有限状态机(以下用FSM指代)是一种算法思想,简单而言,有限状态机由一组状态.一个初始状态.输入和根据输入及现有状态转换为下一个状态的转换函数组成.在Gof的23种设计模 ...

  7. CPLD/FPGA的UART接口设计之系统时钟(晶振)和波特率关系

    UART(UniversalAsynchronous ReceiverTransmitter,通用异步收发器)是一种广泛使用的异步串行数据通信协议.目前大多数MCU.串口通信IC等芯片或模块均支持UA ...

  8. 基于FPGA的IIR滤波器设计

    基于FPGA的IIR滤波器设计,使用VHDL语言. 本设计是毕设,包括论文 下面是论文目录截图: 各模块VHDL程序 时序控制模块程序 library ieee; use ieee.std_logic ...

  9. (101)FPGA面试题-Verilog设计偶校验位

    1.1 FPGA面试题-Verilog设计偶校验位 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)FPGA面试题-Verilog设计偶校验位: 5)结束语. 1.1.2 ...

  10. (96)FPGA面试题-Verilog设计半加器

    1.1 FPGA面试题-Verilog设计半加器 1.1.1 本节目录 1)本节目录: 2)本节引言: 3)FPGA简介: 4)FPGA面试题-Verilog设计半加器: 5)结束语. 1.1.2 本 ...

最新文章

  1. 服务器上文件一直被打开吗,Python: 如何判断远程服务器上Excel文件是否被人打开...
  2. 正态分布的前世今生(1)
  3. Eclipse 常用快捷键,实战经典
  4. Jquery通过ajax加载json,jquery ajax json 异步加载数据
  5. 【游戏】基于 matlab GUI lanchester作战模拟设计【含Matlab源码 426期】
  6. ecshop源码分析:会话类cls_session
  7. paypal php 方式,如何使用PHP向paypal汇款
  8. 机器视觉学习笔记(7)——基于OpenCV的双目摄像机标定
  9. BeanNotOfRequiredTypeException,Bean named ‘xx‘ is excepted to be of type ‘xx‘ but was ‘$Proxy30 ‘
  10. 金蝶旗舰版固定资产计提折旧报错‘费用分配表所引用的*是非明细的核算项目’,如何解决?
  11. 农村姑娘误加了一个博士群,结果...
  12. 信息通信与工程学院c语言试题,2020年湖南大学信息与通信工程考研真题试卷及试题答案,C语言程序设计考研试题下载...
  13. linux下,批量复制文件名带空格的文件
  14. 【转载】路由器的原理与作用
  15. python小白用哪个版本好_完全小白Python极速入坑指南
  16. [hive]return code -101 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask. GC overhead limit exceeded
  17. Mac搭建轻量级BI工具Superset(一)
  18. 如何实现Linux系统和Windows系统双系统
  19. [ITIL]-ITIL4的七大指导原则
  20. 医疗dcm格式图像解析成bmp格式图片

热门文章

  1. youtube字幕下载
  2. endNote教程-5、6-高效阅读文献+高效文献调研
  3. 关于“为什么delete以后指针还能被赋值”一种描述
  4. java自行车(java自行车)
  5. D语言/DLang 2.085.1 发布,修复性迭代
  6. 学历不高的人,去学这5个技术,好找工作,上班也不累
  7. 阿泰,水晶报表--推拉之间
  8. 期货市场十赌九输,钱都去哪里了?
  9. 【笔记本双屏外界显示屏分辨率调高】解决方法
  10. 剽悍一只猫---新年分享(2019.12.29)