上篇博文讲了:FPGA中有限状态机的状态编码采用格雷码还是独热码?

那篇博文讲了状态机的状态编码是用格雷码还是独热码的问题,以及两者之间的优劣。状态机的描述方式采用的是一段式描述方式,也就是将整个状态机全部写到一个always模块中去。

这篇博文仍用上篇博文的案例,说说状态机的描述方法。一段式的描述方法、二段式以及三段式,并比较三者之间的功能仿真情况,最后真心吐露这个案例的状态转移图的疑问?不能把有问题的地方回避,我想我不要做这样的人。


首先看看状态机的描述方法,和编码方式,这两段描述借鉴:基于Verilog HDL的有限状态机,人家说的不错,我也懒着码字了。

状态机的描述方法

状态机的描述方法多种多样,将整个状态机写到1个always 模块里,在该模块中既描述状态转移,又描述状态的输入和输出,这种写法一般被称为一段式FSM 描述方法;

还有一种写法是使用两个always模块,其中一个always 模块采用同步时序的方式描述状态转移,而另一个模块采用组合逻辑的方式判断状态转移条件,描述状态转移规律,这种写法被称为两段式FSM 描述方法;

还有一种写法是在两段式描述方法的基础上发展而来的,这种写法使用3 个always模块,一个always 模块采用同步时序的方式描述状态转移,一个采用组合逻辑的方式判断状态转移条件,描述状态转移规律,第三个always 模块使用同步时序电路描述每个状态的输出,这种写法称为三段式写法。

状态机的状态编码

二进制码(Binary)和格雷码(Gray)属于压缩状态编码,这种编码的优点是使用的状态向量最少,但是需要较多的逻辑资源用来状态译码。二进制码从一个状态转换到相邻状态时,可能有多个比特位发生变化,易产生中间状态转移问题,状态机的速度也要比采用其它编码方式慢。格雷码两个相邻的码值仅有一位就可区分,这将会减少电路中相邻物理信号线同时变化的情况,因而可以减少电路中的电噪声。Johnson码也有同样的特点,但是要用较多的位数。

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


给出实际案例:

下面是一个状态转移图,我们接下来就这个状态转移图来用不同的描述方式来描述。

1)一段式描述方法:

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date:    21:27:04 09/02/2018
// Design Name:
// Module Name:    fsm
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module fsm(input Clock,input rst_n,input A,output F,output G);
reg F, G;
reg [3:0] state;parameter Idle = 4'b1000, Start = 4'b0100, Stop = 4'b0010, Clear = 4'b0001;always @(posedge Clock) beginif(!rst_n) beginstate <= Idle;F <= 1'b0;G <= 1'b0;
end
elsecase(state)Idle: beginif(A) beginstate <= Start;G <= 1'b0;endelsestate <= Idle;endStart: beginif(!A)state <= Stop;elsestate <= Start;endStop: beginif(A) beginstate <= Clear;F <= 1'b1;endelsestate <= Stop;endClear: beginif(!A)beginstate <= Idle;F <= 1'b0;G <= 1'b1;endelsestate <= Clear;enddefault: state <= Idle;endcase end endmodule

给出测试文件,测试文件在这个案例中通用:

`timescale 1ns / 1ps// Company:
// Engineer:
//
// Create Date:   23:39:28 09/02/2018
// Design Name:   fsm
// Module Name:   G:/modelsim_file/fsm01/fsm_tb.v
// Project Name:  fsm01
// Target Device:
// Tool versions:
// Description:
//
// Verilog Test Fixture created by ISE for module: fsm
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// module fsm_tb;// Inputsreg Clock;reg rst_n;reg A;// Outputswire F;wire G;// Instantiate the Unit Under Test (UUT)fsm uut (.Clock(Clock), .rst_n(rst_n), .A(A), .F(F), .G(G));initial begin// Initialize Inputs   rst_n = 0;A = 0;#30 A = 1;rst_n = 1;#30 A = 0;#20 A = 1;#20 A = 0;// Wait 100 ns for global reset to finish#100;endinitial beginClock = 0;      forever #10 Clock = ~Clock;endendmodule

功能仿真:

两段式描述方法:

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date:    21:27:04 09/02/2018
// Design Name:
// Module Name:    fsm
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module fsm(input Clock,input rst_n,input A,output F,output G);
reg F, G;
reg [3:0] pre_state;
reg [3:0] next_state;parameter Idle = 4'b1000, Start = 4'b0100, Stop = 4'b0010, Clear = 4'b0001;//第一个过程,同步时序always块,描述状态转移方程
always @(posedge Clock) beginif(!rst_n)pre_state <= Idle;
elsepre_state  <= next_state;end
//第二个过程,组合逻辑always块,描述激励方程以及输出方程
always @(pre_state or A or rst_n) begincase(pre_state)Idle:beginif(!rst_n) beginnext_state = Idle;F = 1'b0;G = 1'b0;endelse if(A) beginnext_state = Start;G = 1'b0;endelse beginnext_state = Idle;end
endStart: beginif(!rst_n) beginnext_state = Idle;F = 1'b0;G = 1'b0;endelse if(!A) beginnext_state = Stop;endelse beginnext_state = Start;end
endStop: beginif(!rst_n) beginnext_state = Idle;F = 1'b0;G = 1'b0;endelse if(A) beginnext_state = Clear;F = 1'b1;endelse beginnext_state = Stop;end
endClear: beginif(!rst_n) beginnext_state = Idle;F = 1'b0;G = 1'b0;endelse if(!A) beginnext_state = Idle;F = 0;G = 1;endelse beginnext_state = Clear;end
enddefault: beginnext_state = Idle;
endendcaseendendmodule

三段式描述:

`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date:    21:27:04 09/02/2018
// Design Name:
// Module Name:    fsm
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module fsm(input Clock,input rst_n,input A,output F,output G);
reg F, G;
reg [3:0] pre_state;
reg [3:0] next_state;parameter Idle = 4'b1000, Start = 4'b0100, Stop = 4'b0010, Clear = 4'b0001;//第一个过程,同步时序always块,描述状态转移方程
always @(posedge Clock) beginif(!rst_n)pre_state <= Idle;
elsepre_state  <= next_state;end
//第二个过程,组合逻辑always块,描述激励方程
always @(pre_state or A or rst_n) begin
case(pre_state)Idle: beginif(!rst_n) next_state = Idle;else if(A) next_state = Start;else next_state = Idle;
endStart: beginif(!rst_n) next_state = Idle;else if(!A) next_state = Stop;else next_state = Start;
endStop: beginif(!rst_n) next_state = Idle;else if(A) next_state = Clear;else next_state = Stop;
endClear: beginif(!rst_n) next_state = Idle;else if(!A) next_state = Idle;else next_state = Clear;
enddefault: next_state = Idle;endcaseend
//第三个always块,描述输出方程
always @(pre_state or A or rst_n) begincase(pre_state)Idle:beginif(!rst_n) beginF = 1'b0;G = 1'b0;endelse if(A) beginG = 1'b0;endelse begin;end
endStart: beginif(!rst_n) beginF = 1'b0;G = 1'b0;endelse if(!A) begin;endelse begin;end
endStop: beginif(!rst_n) beginF = 1'b0;G = 1'b0;endelse if(A) beginF = 1'b1;endelse begin;end
endClear: beginif(!rst_n) beginF = 1'b0;G = 1'b0;endelse if(!A) beginF = 0;G = 1;endelse begin;end
enddefault: begin;
endendcaseendendmodule

功能仿真:


可见,三种描述方式的仿真图都是一样的,说明了完成同样的功能。

但是从代码的简洁度来看,就这个小状态转移图来说,无疑,一段式的描述方式是最为简单的。但是随着项目的复杂度增高,这种描述方式不便于维护和阅读。

所以呢?要综合来看,不能说哪一种一定好,哪一种一定坏,要根据实际情况而定。

最后我要提出的问题,就是Clear这个状态向Idle这个状态转移的条件:从状态图上看,注意图中的状态图的复位我用rst_n代替,这样更人性化!继续:从状态图上看,是!rst_n或!A有效时,向Idle状态转移,并且输出是F = 0 ,且 G =1;

但是从原作者的一段式代码中,我们可以看出,复位信号rst_n的优先级别要高,如果复位了,那么状态肯定转向Idle,且此时,输出F=0且G=0.这明显和状态转移图中的意思不一样啊,我们推测状态转移图写法有误,所以这里我个人默认复位信号有限,其次是输入A和当前状态决定输出。也就是说,如果复位信号无效时,当前状态为Clear且 !A有效,那么输出就是F = 0 ,且 G =1,并且状态转向Idle.

状态机的描述方法案例分析(一段式、二段式、三段式)相关推荐

  1. 大型网站技术架构:核心原理与案例分析阅读笔记二

    大型网站技术架构:核心原理与案例分析阅读笔记二 网站架构设计时可能会存在误区,其实不必一味追随大公司的解决方案,也不必为了技术而技术,要根据本公司的实际情况,制定适合本公司发展的网站架构设计,否则会变 ...

  2. python财务案例分析考试答案_《财务案例分析》作业及答案(三次).

    <财务案例分析>作业一 一.单选题(每题 2 分) 1. 企业投资者进行财务分析的根本目的是关心企业的( A ) A .盈利能力 B .营运能力 C .偿债能力 D .增长能力 2. 公司 ...

  3. python财务案例分析考试答案_《财务案例分析》作业及答案(三次)

    <财务案例分析>作业一 一.单选题(每题 2 分) 1. 企业投资者进行财务分析的根本目的是关心企业的( A ) A .盈利能力 B .营运能力 C .偿债能力 D .增长能力 2. 公司 ...

  4. 抢红包案例分析以及代码实现(三) 侵立删

    转自:https://mp.weixin.qq.com/s/Pp-nCYrzXXXfLcFFS_ttWg 前文回顾 抢红包案例分析以及代码实现(一) 抢红包案例分析以及代码实现(二) 接下来我们使用乐 ...

  5. html三段式布局,运用三段式框架,教你轻松应对10分钟即兴演讲!

    即兴演讲不宜篇幅过长,一般人在很短的时间也不可能构思出内容复杂的宏篇巨论.因此,即兴演讲宜简短精炼,结构简单,一般为单线条式的结构,或横向的以事物的几个方面为纲,或纵向的以事物的发展过程为目,按逻辑思 ...

  6. MBA案例分析(人员培训二)

    [案例三]美国斯图·伦纳德奶制品商店:访问竞争对手美国斯图·伦纳德奶制品商店的经理斯图·伦纳德培训教育中层干部,使他们成为零售业务和竞争分析方面的专家,成为主人翁.成为胜者的方法很独特,其做法就是访问 ...

  7. 机器视觉——OpenCV案例分析基础(二)(给图片打马赛克与图像的运算处理)

    给图片打马赛克与图像的运算处理 一.理论分析 二.代码分析 2.1 对图像全局采用马赛克处理 2.2 局部马赛克 2.3 对图片进行运算处理 2.3.1 图像的或运算 2.3.2 图像的与运算 2.3 ...

  8. 软考系统架构师笔记-案例分析重点(二)

    系统架构设计非功能需求主要有4类:操作性需求.性能需求.安全性需求.文化需求: 性能需求:响应时间.吞吐量.准确性.有效性.资源利用率.系统完成任务效率等.可靠性.可用性等指标也能归此类. 安全性需求 ...

  9. S7-200SMART案例分析——运动控制编程(二)

    类似于LDOFF,LDOFF是创建新的参考点(零点),而LDPOS是可以将位置更改为任意坐标,例如将50的位置设置为60或者其他值 AXISx_LDPOS 子例程(加载位置)将运动轴中的当前位置值更改 ...

最新文章

  1. linux 空格函数,linux c语言的split函数和空格处理函数
  2. 36.Silverlight中播放视频和打印文档【附带源码实例】
  3. ES6中解构赋值深入解读
  4. colab把数据放在content下面以及放在drive下面的训练速度比较
  5. 计算机二级和英语四六级是同一个账号吗,英语四六级考试和计算机考试的登录账号和密码一样吗?我好像混了,但是密码一直输不对,...
  6. [html] 写一个类似刮刮卡效果的交互,即鼠标划过时显示号码
  7. ZigBee MAC层(上)
  8. neo4j unwind
  9. 网御神州和北京邮电大学成立信息安全联合实验室(2007-07-04)
  10. linux 自学笔记
  11. Steinberg Cubase Elements 11 for Mac(音频处理软件)
  12. CUID卡写入错误数据被锁死——入坑NFC的一段经历
  13. Html的基本操作简介
  14. 假设检验实验和拟合优度检验练习题
  15. pdf添加水印的方法,pdf加水印步骤
  16. 利用 Eclipse Visual Editor 项目构建 GUI 应用程序
  17. 面试官喜欢问的 设计模式之观察者模式
  18. Pygame 官方文档 - Tutorials - 逐行的黑猩猩教程(Line By Line Chimp)
  19. 【C语言】实现双人控制的战斗小游戏
  20. 概念结构设计、逻辑结构设计、物理设计的区分

热门文章

  1. excel满足其中任何一个条件的筛选
  2. HCIE--mac地址 详解
  3. AD自动布地孔和不需要阻焊层
  4. Flink DataStream API 中的多面手——Process Function详解
  5. 杀毒软件引起共享打印机不能打印
  6. Windows 11 安装的那些事
  7. 如何制作GHOST系统安装盘?
  8. 迁出X86架构,你准备好了吗?
  9. vpython 贞测碰撞_VPython - example - 模拟球在两板之间的碰撞
  10. 计算机信息加工是指什么作用,什么是信息加工信息加工的方式