前言:状态机大法好,状态机几乎可以实现一切时序逻辑电路。

有限状态机(Finite State Machine, FSM),根据状态机的输出是否与输入有关,可分为Moore型状态机和Mealy型状态机。Moore型状态机输出仅仅与现态有关和Mealy型状态机不仅与现态有关,也与输入有关,所以会受到输入的干扰,可能会产生毛刺(Glith)的现象,所以我们通常使用的是Moore型状态机。

状态机的编码,二进制编码(Binary),格雷码编码(Gray-code),独热码(One-hot)。不同的编码方式是防止在状态转移中发生突变,使得状态转移更为稳定,系统更加可靠,但是通常情况下我们直接采用的是二进制进行编码,除非系统对稳定性和状态编码有特殊要求。

状态机的描述,一段式、二段式、三段式。

一段式状态机,将组合逻辑和时序逻辑混合在一起,这样的写法对于逻辑简单的状态机来说还是可以使用的,但是对于复杂的逻辑就不推荐了,如果状态复杂也会容易出错,而且一个always块中信号太多也不利于维护和修改。

 //状态参数声明
parameter S0 = 'b0000,
S1 = 'b0001,
s2 = 'b0010;
//FSM one segment
reg [:] state;
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
state <= S0;
else begin
case(state)
S0:
S1:
S2:
.
.
.
default:
endcase
end
end

两段式状态机也是一种常用的写法,它把组合逻辑和时序逻辑区分出来,第一段负责状态的转移,第二段是组合逻辑赋值,但是这种写法的缺点是,组合逻辑较容易产生毛刺等常见问题,关于组合逻辑较容易产生毛刺原因,下文会提到。

 //状态参数声明
parameter S0 = 'b0000,
S1 = 'b0001,
s2 = 'b0010;
//FSM two segment
reg [:] pre_state;
reg [:] next_state;
//--------------------------------------
//FSM one
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
pre_state <= S0;
else
pre_state <= next_state;
end //FSM two
always @(*)begin
case(pre_state)
S0:
S1:
S2:
.
.
.
default:;
endcase end

三段式状态机就可以较好的解决一段二段的不足,我也是比较推荐的写法,第一段采用时序逻辑负责状态转移,第二段组合逻辑负责数据赋值,第三段时序逻辑负责输出,代码层次清晰,容易维护,时序逻辑的输出解决了两段式写法中组合逻辑的毛刺问题。但是资源消耗会多一些,此外,三段式从输入到输出会比一段式和二段式延迟一个时钟周期。在书写状态机的时候,一定要事先设计好状态转移图,将所有的状态都考虑到,避免状态进入死循环,或者跳到偏离态。

 //状态参数声明
parameter S0 = 'b0000,
S1 = 'b0001,
s2 = 'b0010;
//FSM three segment
//--------------------------------------
//FSM one
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
pre_state <= S0;
else
pre_state <= next_state;
end //FSM two
always @(*)begin
case(pre_state)
S0:
S1:
S2:
.
.
.
default:;
endcase
end //FSM three
always @(posedge clk or negedge rst_n)begin
if(!rst_n)
dout <= 'b0;
else begin
case(pre_state)
S0:
S1:
S2:
.
.
.
default:;
endcase
end
end

如下图,我通过一个实例来说明一下状态机的使用。下面是一个序列检测状态转移图,检测是的使1101这个序列,我们给这个序列的检测序列是11101 1101这一串数据。在这个序列检测器中,我们允许使用重复位。也就是说,前一个“1101”最后一位的1可以作为后一个“1101”序列的起始位。如果不允许重复为位,只需要将S4到S2的转移替换成S4到S1即可。

首先,从输出状态S0开始检测,当S0检测到1时跳到S1,否则跳回S0,S1检测到1状态跳到S2,否则跳回S0,S2检测到0状态跳到S3,否则还停留在S2状态,因为这里我们的检测序列允许重复位,所以S1检测到的1与S2检测到的1保留,不舍弃作为一下组1101的前两位,所以只需要继续检测下一位数据即可。S3、S4的状态一次类推。这里举着个例子是为了说明状态机的状态跳转,在我们实际的设计中这种情况也是会遇到的。

在使用状态机来描述时序电路的时候,首先应该做的是画出状态转移图,然后根据状态跳转来描述代码,最后便会事半功倍。这段序列检测的代码我也贴出来。当然这只是序列检测的一个应用了,我前面也说了状态机机会可以实现一切的时序电路。如果你遇到实在不好解决的设计,那么这个时候,你就可以考虑一下使用状态机了。

 module state(
input mclk,
input rst_n,
input din,
output reg dout;
); parameter s0 = 'b000,
s1 = 'b001,
s2 = 'b010,
s3 = 'b011,
s4 = 'b100;//状态
//此为三段式状态机,还有一段式状态机,二段式状态机
reg [:] present_state, next_state;
//用摩尔状态机设计1101序列检测器
//状态寄存器
always @(posedge mclk or negedge rst_n)
begin
if(!rst_n)
present_state <= s0;
else
present_state <= next_state;
end //状态转换模块
always @(*)
begin
case(present_state)
s0: if(din==)
next_state = s1;
else
next_state = s0;
s1: if(din==1)
next_state = s2;
else
next_state = s0;
s2: if(din==0)
next_state = s3;
else
next_state = s2;
s3: if(din==)
next_state = s4;
else
next_state = s0;
s4: if(din==)
next_state = s0;
else
next_state = s2;
default: next_state = s0;
endcase
end always @(posedge clk or negedge rst_n)begin
if(!rst_n)
dout <= 'b0;
else if(present_state ==s4)
dout <= 'b1;
else
dout <= 'b0;
end endmodule

在状态机的设计中,一段式状态机用时序逻辑,二段式状态机第一段用时序逻辑,第二段用组合逻辑,三段式状态机第一段用时序逻辑,第二段用组合逻辑,第三段用时序逻辑。我在设计的时候,尝试把第二段写成时序逻辑,最终结果并没有影响,时序逻辑随时钟变化,组合逻辑是直接赋值,所以在第三段状态机进行输出时,输出结果肯定是稳定的,但是这样会限制fmax。如果用时序逻辑的主频率过高的话,可能不如第二段组合逻辑赋值来的稳定,这里就还需要考虑到时序分析了,暂且不谈。这里还需要提的是使用三段式状态机相较于一段二段式,会延迟一个时钟周期输出,就是因为第三段使用了时序逻辑的缘故。

既然谈状态机的时候,说到了组合逻辑会产生毛刺的现象,那么这里就顺便整理一下,为什么组合逻辑会产生毛刺,组合逻辑的冒险与竞争分析。

竞争(Competition)在组合逻辑电路中,某个输入变量通过两条或两条以上的途径传到输出端,由于每条途径延迟时间不同,到达输出门的时间就有先有后,这种现象称为竞争。把不会产生错误输出的竞争的现象称为非临界竞争。把产生暂时性的或永久性错误输出的竞争现象称为临界竞争。

冒险(risk)信号在器件内部通过连线和逻辑单元时,都有一定的延时。延时的大小与连线的长短和逻辑单元的数目有关,同时还受器件的制造工艺、工作电压、温度等条件的影响。信号的高低电平转换也需要一定的过渡时间。由于存在这两方面因素,多路信号的电平值发生变化时,在信号变化的瞬间,组合逻辑的输出有先后顺序,并不是同时变化,往往会出现一些不正确的尖峰信号,这些尖峰信号称为"毛刺"。如果一个组合逻辑电路中有"毛刺"出现,就说明该电路存在冒险

竞争冒险(Competition risk)产生原因:由于延迟时间的存在,当一个输入信号经过多条路径传送后又重新会合到某个门上,由于不同路径上门的级数不同,或者门电路延迟时间的差异,导致到达会合点的时间有先有后,从而产生瞬间的错误输出。

首先看下面这个电路,使用了两个逻辑门,一个非门和一个与门,本来在理想情况下F的输出应该是一直稳定的0输出,但是实际上每个门电路从输入到输出是一定会有时间延迟的,这个时间通常叫做电路的开关延迟。而且制作工艺、门的种类甚至制造时微小的工艺偏差,都会引起这个开关延迟时间的变化。

实际上如果算上非门的延迟的话,那么F最后就会产生毛刺。信号由于经由不同路径传输达到某一汇合点的时间有先有后的现象,就称之为竞争,由于竞争现象所引起的电路输出发生瞬间错误的现象,就称之为冒险,所以在设计中我们要注意避免这个现象,最简单的避免方法是尽量使用时序逻辑同步输出。

这篇状态机和组合逻辑的冒险竞争就聊到这里,下次我们接着说时序逻辑的冒险竞争。

参考资料:百度百科,冒险竞争、《FPGA设计技巧与案例开发详解》、《FPGA数字逻辑设计教程——Verilog》、《深入浅出玩转FPGA》等网络文章。

转载请注明出处:NingHeChuan(宁河川)

个人微信订阅号:开源FPGA

如果你想及时收到个人撰写的博文推送,可以扫描左边二维码(或者长按识别二维码)关注个人微信订阅号

知乎ID:NingHeChuan

微博ID:NingHeChuan

原文地址:http://www.cnblogs.com/ninghechuan/p/7898297.html

基于FPGA的有限状态机浅析的更多相关文章

  1. FPGA经典:Verilog传奇与基于FPGA的数字图像处理原理及应用

    一 简述 最近恶补基础知识,借了<<Verilog传奇>>,<基于FPGA的嵌入式图像处理系统设计>和<<基千FPGA的数字图像处理原理及应用>& ...

  2. 基于FPGA的飞机的小游戏

    基于FPGA的飞机的小游戏 实验原理 该实验主要分为4个模块,采用至上而下的设计方法进行设计.由50M的晶振电路提供时钟源,VGA显示控制模块.图形显示控制模块.移动模块的时钟为25M,由时钟分频电路 ...

  3. 基于FPGA的音频信号的FIR滤波(Matlab+Modelsim验证)

    1 设计内容 本设计是基于FPGA的音频信号FIR低通滤波,根据要求,采用Matlab对WAV音频文件进行读取和添加噪声信号.FFT分析.FIR滤波处理,并分析滤波的效果.通过Matlab的分析验证滤 ...

  4. 基于FPGA的图像去噪

    目录 结构图 其中FPGA 控制模块为核心,通过它实现视频图像数据的获取.缓存.处理和控制各模块间通讯[1].由CCD 相机对目标成像,高速图像数据由camera link 实时传输[2],经信号转换 ...

  5. 基于FPGA的线阵CCD图像测量系统研究——笔记

    本文是对基于FPGA的线阵CCD图像测量系统研究(作者:高尚)的阅读笔记 第一章绪论 1. 读读看 读了前面的摘要依然没有看懂作者要做什么.接着往下读....终于看到了一个字眼“基于机器视觉的图像测量 ...

  6. 基于FPGA的按键扫描程序

    最近在学习FPGA,就试着写了个按键扫描的程序.虽说有过基于单片机的按键扫描处理经验,对于按键的处理还是有一些概念.但是单片机程序的编写通常都采用C写,也有用汇编,而FPGA却是采用VHDL或者Ver ...

  7. 基于FPGA的DW8051移植(三)

    总结一下问题: 1) http://www.cnblogs.com/sepeng/p/4137405.html  基于FPGA的DW8051移植(一)里面用modelsim观测波形发现程序进入了ida ...

  8. 基于FPGA的红外遥控解码与PC串口通信

    基于FPGA的红外遥控解码与PC串口通信 zouxy09@qq.com http://blog.csdn.net/zouxy09 这是我的<电子设计EDA>的课程设计作业(呵呵,这个月都拿 ...

  9. 基于FPGA的OLED真彩色动态图像显示的实现

    源:基于FPGA的OLED真彩色动态图像显示的实现 作为第3代显示器,有机电致发光器件(Organic Light Emitting Diode,OLED)由于其主动发光.响应快.高亮度.全视角.直流 ...

随机推荐

  1. 微信公众号第三方 推送component_verify_ticket协议

    整了一天,终于弄明白了 component_verify_ticket 怎么获取的了.在此先批一下微信公众号平台,文档又没写清楚,又没有客服,想搞哪样哈! 好,回归正题. 第一,先通过开发者资质认证, ...

  2. Ubuntu 16.04 LTS 下安装MATLAB2015b 以及Matlab system error解决办法

    下载MATLAB2015b破解版 操作系统:Ubuntu 16.o4 LTS 程序文件:Matlab2015b-glnxa64破解版 解压提取文件:在ubuntu系统下可以直接提取压缩文件,得到三个文 ...

  3. TensorFlow问题:The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available on your machine and could speed up CPU computations.

    1. 问题描述 The TensorFlow library wasn't compiled to use SSE4.2 instructions, but these are available o ...

  4. win10 uwp 后台获取资源

    本文告诉大家,从后台代码获取界面定义的资源. 如果一个资源是写在 App 的资源,那么如何使用代码去获得他? 简单的方法是使用下面的代码 Application.Current.Resources[& ...

  5. WPF 绑定密码

    我们发现我们无法绑定密码框的密码,PasswordBox 的 Password 不能绑定. 我们想做 MVVM ,我们需要绑定密码,不能使用前台 xaml.cs 监听 密码改变得到密码的值,传到 Vi ...

  6. Python学习笔记(七)

    Python学习笔记(七): 深浅拷贝 Set-集合 函数 1. 深浅拷贝 1. 浅拷贝-多层嵌套只拷贝第一层 a = [[1,2],3,4] b = a.copy() print(b) # 结果:[ ...

  7. junit搭配hamcrest使用

    开篇 - 快速进行软件编码,与功能测试应该是每个写代码的人,应该掌握的技能,如何进行优雅的写代码,把测试的时间压缩,腾出时间来休息.下面听我一一道来: 依赖:junit 4.4 hamcrest 1. ...

  8. eclispe中安装hibernate插件

    用eclispe玩ee的朋友,写配置文件的时候没有提示非常苦恼,而配置dtd文件还是没有得到解决,最后试了试安装插件解决了问题 地址:http://download.jboss.org/jbossto ...

  9. Prometheus 到底 NB 在哪里?- 每天5分钟玩转 Docker 容器技术(84)

    本节讨论 Prometheus 的核心,多维数据模型.我们先来看一个例子. 比如要监控容器 webapp1 的内存使用情况,最传统和典型的方法是定义一个指标 container_memory_usag ...

  10. 【ASP.NET MVC 学习笔记】- 02 Attribute

    本文参考:http://www.cnblogs.com/willick/p/3208427.html 1.特性(Attribute)对程序中的元素进行标注,比如类.字段.方法.属性等. 2.在.NET ...