芯航线——普利斯队长精心奉献

 

实验目的:1.学习状态机的相关概念

2.理解一段式、两段式以及三段式状态机的区别以及优缺点

实验平台:芯航线FPGA核心板

实验原理:

状态机全称是有限状态机(finite-state machine,缩写:FSM)是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。

状态机分为摩尔(Moore)型有限状态机与米利(Mealy)型有限状态机。摩尔状态机输出是只由输入确定的有限状态机(不直接依赖于当前状态)。米利有限状态机的输出不止与其输入有关还于它的当前状态相关,这也是与摩尔有限状态机的不同之处。其分别的原理图如图8-1,8-2所示

图8-1 摩尔型状态机

图8-2 米利型状态机

状态机顾名思义会有各种状态,这也就分支出一种情况如何对状态进行有效的编码。编码格式,最简单的就是直接使用二进制进行表示,除此之外还有使用格雷码、独热码。假设有八个状态从A到R,利用不同的编码格式分别如表8-1所示。

编码格式

状态

二进制

独热码

格雷码

A

3'b000

8'b0000_0000

4'b0000

B

3'b001

8'b0000_0010

4'b0001

C

3'b010

8'b0000_0100

4'b0011

D

3'b011

8'b0000_1000

4'b0010

E

3'b100

8'b0001_0000

4'b0110

F

3'b101

8'b0010_0000

4'b0111

G

3'b110

8'b0100_0000

4'b0101

H

3'b111

8'b1000_0000

4'b0100

表8-1 状态不同的编码格式

独热码,每一个状态均使用一个寄存器,相比其他译码简单;格雷码,所需寄存器数与二进制码一样,译码复杂,但相邻位只跳动一位,一般用于异步多时钟域多bit位的转换,如异步FIFO; 二进制码,最为常见的编码方式,所用寄存器少,译码较复杂。

    按照Altera给的建议,选择哪一种编码格式是要根据状态机的复杂度、器件类型以及从非法状态中恢复出来的要求均有关。在使用不同的编码格式生成出来的RTL视图中可以看出二进制比独热码使用更少的寄存器。
二进制用7个寄存器就可以实现100个状态的状态机,但是独热码就需要100个寄存器。但是另一方面,虽然独热码使用更多的寄存器但是其组合逻辑相对简单。一般推荐在CPLD中由于提供较多的组合逻辑资源多使用前者,FPGA中提供较多的时序逻辑而多用后者。

    状态机描述方式,可分为一段式、两段式以及三段式。

一段式,整个状态机写到一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出;

两段式,用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出;

三段式,在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以时序电路输出)。

可以看出两段式有限状态机与一段式有限状态机的区别是FSM将时序部分(状态转移部分)和组合部分(判断状态转移条件和产生输出)分开,写为两个always语句,即为两段式有限状态机。将组合部分中的判断状态转移条件和产生输入再分开写,则为三段式有限状态机。这样就使得二段式在组合逻辑特别复杂时,注意需在后面加一个触发器以消除组合逻辑对输出产生的毛刺。三段式则没有这个问题,这是由于第三个always会生成触发器。其实现在的器件根本不在乎这一点资源消耗,推荐使用二段式或者三段式以及输出寄存的状态机输出来进行描述。

编写状态机还需主要注意的事项是状态穷举或者default 避免生成锁存器;在编写状态定义时推荐使用本地化参数定义localparam,这样可以在编写时状态更清晰且不容易出错,也方便修改;在复位或者跑飞能回到初始态或者预定态;要有异步或者同步复位来确保状态机上电有个初始态。

实验步骤:

为了实现让FPGA输出一个HELLO字符串,首先画出其状态转移图,如图8-3所示。

图8-3 "HELLO"状态转移图

由上图可以看出如果在任意态不符合转换条件,那么状态就会重新回到初始态H。且每一个状态都有特定的方向,这是一个摩尔型状态机。

建立工程子文件夹后,新建一个以名为Hello的工程保存在prj下,并在本工程目录的rtl文件夹下新建verilog file文件在此文件下输入以下内容并以Hello.v保存。这里对状态机用独热码编码且如果完成一次"HELLO"输出, led灯翻转一次。

module Hello(Clk,Rst_n,data,led);

 

input Clk;//50M

input Rst_n;//低电平复位

 

input
[7:0]data;

 

output
reg led;

 

localparam

CHECK_H =
5'b0_0001,

CHECK_e =
5'b0_0010,

CHECK_la =
5'b0_0100,

CHECK_lb =
5'b0_1000,

CHECK_o =
5'b1_0000;

 

reg[4:0]state;

 

always@(posedge Clk or
negedge Rst_n)

if(!Rst_n)begin

led <=
1'b1;

state <= CHECK_H;

end

else
begin

case(state)

CHECK_H:

if(data ==
"H")

state <= CHECK_e;

else

state <= CHECK_H;

 

CHECK_e:

if(data ==
"e")

state <= CHECK_la;

else

state <= CHECK_H;

 

CHECK_la:

if(data ==
"l")

state <= CHECK_lb;

else

state <= CHECK_H;

 

CHECK_lb:

if(data ==
"l")

state <= CHECK_o;

else

state <= CHECK_H;

 

CHECK_o:

begin

state <= CHECK_H;

if(data ==
"o")

led <=
~led;

else

led <= led;

end

 

default:state <= CHECK_H;

endcase

end

 

endmodule

进行分析和综合直至没有错误以及警告。可以在RTL Viewer中看到实现的状态机如图8-4所示,与预期设计相同。

图8-4 生成的状态转移图

为了测试仿真编写测试激励文件,新建Hello_tb.v文件保存到testbench文件夹下,输入以下内容再次进行分析和综合直至没有错误以及警告。本激励文件除产生正常的时钟以及复位信号外,还生成了状态转移信号。

 

`timescale
1ns/1ns

`define clock_period 20

 

module Hello_tb;

 

reg Clk;

reg Rst_n;

reg
[7:0]ASCII;

 

wire led;

 

Hello Hello0(

.Clk(Clk),

.Rst_n(Rst_n),

.data(ASCII),

.led(led)

);

 

initial Clk =
1;

always#(`clock_period/2)Clk =
~Clk;

 

initial
begin

Rst_n =
0;

ASCII =
0;

#(`clock_period*200);

Rst_n =
1;

#(`clock_period*200
+
1);

forever
begin

ASCII =
"I";

#(`clock_period);

ASCII =
"A";

#(`clock_period);

ASCII =
"M";

#(`clock_period);

ASCII =
"X";

#(`clock_period);

ASCII =
"i";

#(`clock_period);

ASCII =
"a";

#(`clock_period);

ASCII =
"o";

#(`clock_period);

ASCII =
"M";

#(`clock_period);

ASCII =
"e";

#(`clock_period);

ASCII =
"i";

#(`clock_period);

ASCII =
"g";

#(`clock_period);

ASCII =
"e";

 

#(`clock_period);

ASCII =
"H";

#(`clock_period);

ASCII =
"E";

 

#(`clock_period);

ASCII =
"M";

#(`clock_period);

ASCII =
"l";

 

#(`clock_period);

ASCII =
"H";

#(`clock_period);

ASCII =
"E";

#(`clock_period);

ASCII =
"L";

#(`clock_period);

ASCII =
"L";

#(`clock_period);

ASCII =
"O";

#(`clock_period);

 

ASCII =
"H";

#(`clock_period);

ASCII =
"e";

#(`clock_period);

ASCII =
"l";

#(`clock_period);

ASCII =
"l";

#(`clock_period);

ASCII =
"o";

 

#(`clock_period);

ASCII =
"l";

end

end

 

endmodule

 

设置好仿真脚本后进行功能仿真,可以看到如图8-5所示的波形文件,可以看出在复位信号置高之前状态均不发生转移。在复位有效后,只有当输入发生变化时状态才会根据设计进行转换,且没有出现转移错误,led的状态也能根据状态来进行翻转。

图8-5 仿真波形文件

    至此就完成了一个简单的状态机的设计,在后面的例程中会经常用到状态机设计思想,这里也就不再对二段式、三段式状态机展开。

08-FPGA状态机设计实例——小梅哥FPGA设计思想与验证方法视频教程配套文档的更多相关文章

  1. 02-FPGA设计流程介绍——小梅哥FPGA设计思想与验证方法视频教程配套文档

    芯航线——普利斯队长精心奉献 课程目标: 1.了解并学会FPGA开发设计的整体流程 2.设计一个二选一选择器并进行功能仿真.时序仿真以及板级验证 实验平台:芯航线FPGA开发板.杜邦线 实验内容: 良 ...

  2. 06-BCD计数器设计与应用——小梅哥FPGA设计思想与验证方法视频教程配套文档

    芯航线--普利斯队长精心奉献   实验目的:1.掌握BCD码的原理.分类以及优缺点          2.设计一个多位的8421码计数器并进行验证          3.学会基本的错误定位以及修改能力 ...

  3. 09A-独立按键消抖实验01——小梅哥FPGA设计思想与验证方法视频教程配套文档

    芯航线--普利斯队长精心奉献   实验目的: 1.复习状态机的设计思想并以此为基础实现按键消抖 2.单bit异步信号同步化以及边沿检测 3.在激励文件中学会使用随机数发生函数$random 4.仿真模 ...

  4. 10-8位7段数码管驱动实验——小梅哥FPGA设计思想与验证方法视频教程配套文档

    芯航线--普利斯队长精心奉献   实验目的: 1.实现FPGA驱动数码管动态显示: 2.使用In system sources and probes editor工具,输入需要显示在数码管上的的数据, ...

  5. 09B-独立按键消抖实验02——小梅哥FPGA设计思想与验证方法视频教程配套文档

    芯航线--普利斯队长精心奉献   实验目的: 1.复习按键的设计 2.用模块化设计的方式实现每次按下按键0,4个LED显示状态以二进制加法格式加1,每次按下按键1,4个LED显示状态以二进制加法格式减 ...

  6. 05-IP核应用之计数器——小梅哥FPGA设计思想与验证方法视频教程配套文档

    芯航线--普利斯顿队长精心奉献   实验目的:了解FPGA的IP核相关知识并以计数器IP核为例学会基本IP使用的流程 实验平台:无 实验原理:     IP核(Intellectual Propert ...

  7. 04-时序逻辑电路设计之计数器——小梅哥FPGA设计思想与验证方法视频教程配套文档

    芯航线--普利斯队长精心奉献 实验目的:以计数器为例学会简单的时序逻辑电路设计 实验平台:芯航线FPGA核心板 实验原理: 时序逻辑电路是指电路任何时刻的稳态输出不仅取决于当前的输入,还与前一时刻输入 ...

  8. 03-组合逻辑电路设计之译码器——小梅哥FPGA设计思想与验证方法视频教程配套文档

    芯航线——普利斯队长精心奉献 课程目标:    1. 再次熟悉Quartus II工程的建立以及完整的FPGA开发流程 2. 以译码器为例学会简单组合逻辑电路设计 实验平台:无 实验原理: 组合逻辑, ...

  9. 07-阻塞赋值与非阻塞赋值原理分析——小梅哥FPGA设计思想与验证方法视频教程配套文档

    芯航线--普利斯队长精心奉献   实验目的:掌握阻塞赋值与非阻塞赋值的区别 实验平台:无 实验原理:     阻塞赋值,操作符为"=","阻塞"是指在进程语句( ...

随机推荐

  1. HDU 1166 敌兵布阵(分块)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  2. myBatis的一对多查询,主要利用resultMap实现一次查询多个结果集

    日常开发中有这中场景,一个用户有多个角色,一个角色又有多个菜单,想查出一个用户的所有菜单.除了常见的关联查询之外,更使用的应该是利用myBatis的resultMap来实现一次查询出多个结果集,缺点: ...

  3. Alfresco.widget.Resizer可拉动div模块

    <#include "include/alfresco-template.ftl" /> <@templateHeader> <script type ...

  4. mysql导入大文件sql

    备份mysqldump mysqldump -u root -p ao2012 > /mnt/www/zq_ao2012/backup.sql 然后数据库密码 导入 mysql -h local ...

  5. 【php】命名空间 和 自动加载的关系

    目的 本文的目的主要是说明 命名空间的 use 关键词 和 new ClassName 这两个步骤,哪个步骤才会执行自动加载,这是逻辑有点混乱的表现,这种想法也是很正常的,让我们来解密吧 命名空间(n ...

  6. jQuery jQuery对象与dom对象的转换

    jQuery对象本质上是一个构造函数,主要作用是返回jQuery对象的实例. jQuery选择器返回的是一个类似数组的对象,用下标运算取出的对象如$('body')[0],是dom对象,对此jquer ...

  7. Python中的对象类型的初步介绍

    一:介绍 1.为什么使用内置对象 对象类型是语言的一个部分 内置对象构成了每个python程序的核心部分 2.核心数据类型 数字 字符串 列表 字典 元组 文件 集合 其他类型 编程单元类型 与实现相 ...

  8. subString(), subStr(),splice(),split()的区别

    1.slice(): Array和String对象都有 在Array中  slice(i,[j]) i为开始截取的索引值,负数代表从末尾算起的索引值,-1为倒数第一个元素 j为结束的索引值,缺省时则获 ...

  9. iOS程序上传流程 2014年9月最新版

    程序上传步骤: 1.登录账户,点击Manage Your Apps 2.点击Add New App 3.注册Bundle ID,点击蓝色的here 4.进入了注册页面,首先要填写App ID的一个描述 ...

  10. Big Data

    Hadoop安装教程_伪分布式配置_CentOS6.4/Hadoop2.6.0 http://dblab.xmu.edu.cn/blog/install-hadoop-in-centos/ Spark ...