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

article/2025/9/19 23:07:00

上篇博文讲了: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.

 


http://chatgpt.dhexx.cn/article/cs7dIhiP.shtml

相关文章

FPGA状态机(一段式、二段式、三段式)、摩尔型(Moore)和米勒型(Mealy)

1、状态机 1.1、理论 FPGA不同于CPU的一点特点就是CPU是顺序执行的&#xff0c;而FPGA是同步执行&#xff08;并行&#xff09;的。那么FPGA如何处理明显具有时间上先后顺序的事件呢&#xff1f;这个时候我们就需要使用到状态机了。 状态机简写为 FSM&#xff08;Finite Sta…

三段式状态机_verilog

这是一篇转载的文章&#xff0c;但是个人理解笔者将前两个always块结构搞错了&#xff0c;自行纠正了一下。 原文链接 https://www.jianshu.com/p/5eee434ab24d 1. 三段式要求 有限状态机采用三段式风格&#xff0c;即三个always块描述状态机. 第一个时序逻辑always块用来描…

2021-08-21Verilog三段式状态机的写法,标准示例和仿真。

Verilog三段式状态机的写法&#xff0c;标准示例和仿真。 第一段&#xff1a;同步状态转移。第一个always块格式化描述次态寄存器迁移到现态寄存器。 第二段&#xff1a;当前状态判断接下来的状态。组合逻辑always模块&#xff0c;描述状态转移条件判断用current_state 第三段&…

verilog 3段式状态机

3段式状态机&#xff1a; 3段式状态机写法&#xff0c;写出下图状态转换图。 1 确定输入输出信号&#xff0c;及其类型&#xff08;是wire还是reg&#xff09;&#xff1b; 2 声明内部信号&#xff0c;一般需要定义current_state和next_state&#xff1b; 3 用3个always语句描…

三段式状态机设计

状态机设计需满足的几个要求&#xff1a; 1. 三段式要求 有限状态机采用三段式风格&#xff0c;即三个always块描述状态机. 第一个组合逻辑always块用来描述下一状态的转移&#xff08;next state logic&#xff09; 第二个时序逻辑always块用来描述当前状态.&#xff08;cur…

三段式状态机浅析

三段式状态机 文章目录 三段式状态机三段式状态机优点书写格式formater整形器状态机书写举例 关注作者 三段式状态机优点 将组合逻辑与时序逻辑分开&#xff0c;所写代码层次清晰&#xff0c;方便理解和后续的维护相较两段式状态机&#xff0c;解决了输出毛刺的影响。 书写格…

(三段式)有限状态机【原理+实例】

状态机的基本要素&#xff1a;输入、输出、状态。 状态机根据状态变化是否与输入条件有关分为两类&#xff1a;即Moore型状态机和Mealy型状态机。 Moore型状态机的状态变化仅和当前状态有关&#xff0c;而与输入条件无关&#xff1b; Mealy型状态机的状态变化不仅和当前状态…

状态机设计(一段式、两段式和三段式)

三段式状态机 第一段&#xff0c;时序always块&#xff0c;状态跳转 第二段&#xff0c;组合always块&#xff0c;状态更新 第三段&#xff0c;时序always块&#xff0c;输出控制 两段式状态机 两段式状态机是把三段式状态机的第二段和第三段合为一段&#xff0c;那么两段式…

FPGA——三段式状态机(1)

状态机全称是有限状态机&#xff08;Finite State Machine、FSM&#xff09;&#xff0c;是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。状态机可根据控制信号完成预定的状态转换&#xff0c;由组合逻辑电路和寄存器组成&#xff0c;可由状态转换表或状态转…

状态机详解(一段式、二段式、三段式)

一、有限状态机FSM&#xff08;Finite State Machine&#xff09; 组成元素&#xff1a; 输入、状态、状态转移条件、输出。 可以分为两类&#xff1a; Mealy状态机&#xff1a;时序逻辑的输出不仅取决于当前状态&#xff0c;还与输入有关&#xff1b; Moore状态机&#xff1a…

三段式状态机理解浅析

版权声明&#xff1a;本文为博主原创文章&#xff0c;遵循 CC 4.0 BY-SA 版权协议&#xff0c;转载请附上原文出处链接和本声明。 本文链接&#xff1a;https://blog.csdn.net/weixin_43070186/article/details/82085463 关于FSM的写法按照always块的个数来划分可以分为一段式…

彻底搞懂状态机(一段式、两段式、三段式)

转自&#xff1a;https://blog.csdn.net/wordwarwordwar/article/details/78509445 实例&#xff1a;FSM实现10010串的检测 状态转移图&#xff1a;初始状态S0&#xff0c;a 0,z 0.如果检测到1&#xff0c;跳转到S1。 下一状态S1&#xff0c;a 1,z 0.如果检测到0&#xff…

Verilog:三段式状态机(数字钟)

状态机在FPGA的设计中是至关重要的&#xff0c;使用的频率也很高&#xff0c;废话不多说在这里介绍一下三段式状态机如何设计。 设计状态机首先要清楚状态有几种&#xff0c;状态转移图是怎样的&#xff0c;各个状态的输出是怎样的。了解了这三样之后就可以开始设计实验所需要的…

三段式有限状态机

一段式、二段式、三段式状态机是按照书写FSM时使用的always块数目进行划分的&#xff0c;一般而言对于简单的状态机&#xff0c;可以使用一段式&#xff0c;其代码量以及使用资源都最少&#xff0c;但如果状态机较复杂&#xff0c;一段式状态机会对代码维护产生很大的不便&…

状态机,从细节出发(一段式、两段式、三段式,moore型、mealy型)

目录 前言 一、状态机要素 二、状态机描述方法 1、一段式描述方法 2、两段式描述方法 3、三段式描述方法 三、关系 1、一段式与三段式 2、两段式与三段式 3、三种FSM描述方法比较表 四、状态机的种类 1、Moore型状态机 2、Mealy型状态机 3、注意点 五、举例 1、…

时间复杂度与空间复杂度分析(递归与非递归比较)

时间复杂度&#xff1a; 一般情况下&#xff0c;算法中基本操作重复的次数就是问题规模n的某个函数f&#xff08;n&#xff09;&#xff0c;进而分析f&#xff08;n&#xff09;随n的变化情况并确定T&#xff08;n&#xff09;的数量级。这里用‘o’来表示数量级&#xff0c;给…

数据结构:时间复杂度空间复杂度(递归)

转载文章 时间复杂度&#xff1a; 一般情况下&#xff0c;算法中基本操作重复执行的次数是问题规模n的某个函数f(n)&#xff0c;进而分析f(n)随n的变化情况并确定T(n)的数量级。这里用"O"来表示数量级&#xff0c;给出算法的时间复杂度。 T(n)O(f(n)); 它表示随着问…

递归理解以及时间复杂度计算

一.复杂度分析&#xff1a; 可以理解为递归的深度就是空间复杂度&#xff0c;时间复杂度就是O(T*depth),其中&#xff34;是每个递归函数的时间复杂度&#xff0c;depth是递归深度&#xff0e; #空间复杂度O(1) def sum1_(n):res 0for i in range(n1):resireturn res#递归 空…

递归的时间与空间复杂度

一、 递归的时间复杂度 递归算法的时间复杂度 递归次数 \times 每次递归的时间复杂度。 递归次数&#xff1a;可以通过画递归树&#xff0c;数递归树的节点数&#xff0c;得到递归次数。 二、递归的空间复杂度 递归算法的空间复杂度 递归深度 \times 每次入栈的空间…

【转】Tomcat相关面试题,看这一篇就够了!

转自公众号&#xff1a;Java思维导图 Tomcat相关的面试题出场的几率并不高&#xff0c;正是因为如此&#xff0c;很多人忽略了对Tomcat相关技能的掌握。下面这篇文章整理了Tocmat相关的系统架构&#xff0c;介绍了Server、Service、Connector、Container之间的关系&#xff0c…