Verilog状态机详谈

2024-05-25 22:58
文章标签 状态机 verilog 详谈

本文主要是介绍Verilog状态机详谈,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

时序电路的状态是一个状态变量集合,这些状态变量在任意时刻的值都包含了为确定电路的未来行为而必需考虑的所有历史信息。
状态机采用VerilogHDL语言编码,建议分为三个always段完成。这是为什么呢?
    设计FSM的方法和技巧多种多样,但是总结起来有两大类:第一种,将状态转移和状态的操作和判断等写到一个模块(process、block)中。另一种是将状态转移单独写成一个模块,将状态的操作和判断等写到另一个模块中(在Verilog代码中,相当于使用两个“always” block)。其中较好的方式是后者。其原因如下。
首先FSM和其他设计一样,最好使用同步时序方式设计,好处不再累述。而状态机实现后,状态转移是用寄存器实现的,是同步时序部分。状态的转移条件的判断是通过组合逻辑判断实现的,之所以第二种比第一种编码方式合理,就在于第二种编码将同步时序和组合逻辑分别放到不同的程序块(process,block)中实现。这样做的好处不仅仅是便于阅读、理解、维护,更重要的是利于综合器优化代码,利于用户添加合适的时序约束条件,利于布局布线器实现设计。
三段式建模描述FSM的状态机输出时,只需指定case敏感表为次态寄存器,然后直接在每个次态的case分支中描述该状态的输出即可,不用考虑状态转移条件。
三段式描述方法虽然代码结构复杂了一些,但是换来的优势是使FSM做到了同步寄存器输出,消除了组合逻辑输出的不稳定与毛刺的隐患,而且更利于时序路径分组,一般来说在FPGA/CPLD等可编程逻辑器件上的综合与布局布线效果更佳。
示例如下:
//第一个进程,同步时序always模块,格式化描述次态寄存器迁移到现态寄存器
always @ (posedge clk or negedge rst_n) //异步复位
if(!rst_n)
current_state <= IDLE;
else
current_state <= next_state;//注意,使用的是非阻塞赋值
//第二个进程,组合逻辑always模块,描述状态转移条件判断
always @ (current_state) //电平触发
begin
next_state = x; //要初始化,使得系统复位后能进入正确的状态
case(current_state)
S1: if(...)
next_state = S2; //阻塞赋值
...
endcase
end
//第三个进程,同步时序always模块,格式化描述次态寄存器输出
always @ (posedge clk or negedge rst_n)
...//初始化
case(next_state)
S1:
out1 <= 1'b1; //注意是非阻塞逻辑
S2:
out2 <= 1'b1;
default:... //default的作用是免除综合工具综合出锁存器。
endcase
end
三段式并不是一定要写为3个always块,如果状态机更复杂,就不止3段了。
//注:================================================================
1. 三段always模块中,第一个和第三个always模块是同步时序always模块,用非阻塞赋值(“ <= ”);第二个always模块是组合逻辑always模块,用阻塞赋值(“ = ”)。
2. 第二部分为组合逻辑always模块,为了抑制warning信息,对于always的敏感列表建议采用always@(*)的方式。
3. 第二部分,组合逻辑always模块,里面判断条件一定要包含所有情况!可以用else保证包含完全。
4. 第二部分,组合逻辑电平要维持超过一个clock,仿真时注意。
5. 需要注意:第二部分case中的条件应该为当前态(current_state),第三部分case中的条件应该为次态(next_state)。
6. 编码原则,binary和gray-code适用于触发器资源较少,组合电路资源丰富的情况(CPLD),对于FPGA,适用one-hot code。这样不但充分利用FPGA丰富的触发器资源,还因为只需比较一个bit,速度快,组合电路简单。
7. 初始化状态和默认状态。
一个完备的状态机(健壮性强)应该具备初始化状态和默认状态。当芯片加电或者复位后,状态机应该能够自动将所有判断条件复位,并进入初始化状态。需要注明的一点是,大多数FPGA有GSR(Global Set/Reset)信号,当FPGA加电后,GSR信号拉高,对所有的寄存器,RAM等单元复位/置位,这时配置于FPGA的逻辑并未生效,所以不能保证正确的进入初始化状态。所以使用GSR企图进入FPGA的初始化状态,常常会产生种种不必一定的麻烦。一般的方法是采用异步复位信号,当然也可以使用同步复位,但是要注意同步复位的逻辑设计。解决这个问题的另一种方法是将默认的初始状态的编码设为全零,这样GSR复位后,状态机自动进入初始状态。
令一方面状态机也应该有一个默认(default)状态,当转移条件不满足,或者状态发生了突变时,要能保证逻辑不会陷入“死循环”。这是对状态机健壮性的一个重要要求,也就是常说的要具备“自恢复”功能。对应于编码就是对case,if-else语句要特别注意,要写完备的条件判断语句。VHDL中,当使用CASE语句的时候,要使用“When Others”建立默认状态。使用“IF...THEN...ELSE”语句的时候,要用在“ELSE”指定默认状态。Verilog中,使用“case”语句的时候要用“default”建立默认状态,使用“if...else”语句的注意事项相似。
8. 另外提一个技巧:大多数综合器都支持Verilog编码状态机的完备状态属性--“full case”。这个属性用于指定将状态机综合成完备的状态,如Synplicity的综合工具(Synplify/Synplify Pro,Amplify,etc)支持的命令格式如下:
case (current_state) // synthesis full_case
2’b00 : next_state <= 2’b01;
2’b01 : next_state <= 2’b11;
2’b11 : next_state <= 2’b00;
//这两段代码等效a
case (current_state)
2’b00 : next_state <= 2’b01;
2’b01 : next_state <= 2’b11;
2’b11 : next_state <= 2’b00;
default : next_state <= 2bx;
9. Synplicity还有一个关于状态机的综合属性,叫“synthesis parallel_case”,其功能是检查所有的状态是“并行的”(parallel),也就是说在同一时间只有一个状态能够成立。
10. 状态机的定义可以用parameter定义,但是不推荐使用`define宏定义的方式,因为`define宏定义在编译时自动替换整个设计中所定义的宏,而parameter仅仅定义模块内部的参数,定义的参数不会与模块外的其他状态机混淆。
11. 对于状态比较多的状态机,可以将所有状态分为几个大状态,然后再使用小状态,可以减少状态译码的时间。

12. 在代码中添加综合器的综合约束属性或者在图形界面下设置综合约束属性可以比较方便的改变状态的编码。

13. 小技巧:仔细检查综合器的综合报告,目前大多数的综合器对所综合出的latch都会报“warning”,通过综合报告可以较为方便地找出无意中生成的latch。(关于latch的综合生成问题请看Verilog中条件语句的综合问题)


这篇关于Verilog状态机详谈的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1002865

相关文章

使用 TinyFSM 和 BehaviorTree.CPP 构建状态机与行为树示例

文章目录 0. 概述1. 有限状态机(FSM)原理状态机示例(FSM) 2. 行为树(BT)原理行为树示例(BT) 3. 结合FSM和BT项目结构4. 代码实现5. 总结6. 参考 0. 概述 在现代软件开发中,有限状态机(FSM)和行为树(BT)是两种常用的工具,用于实现复杂的逻辑控制和决策。本文将展示如何结合使用 TinyFSM 和 BehaviorTree.CPP 创建

【FPGA】`include 和 verilog header的区别

作用域区别 include 是把文件 粘贴到当前位置,作用域也仅限当前文件header 作用域是整个工程 .f添加方式的区别 include “xxx.v” 写在当前文件中,.f文件无需另外添加header文件用+incdir+./…/pathname/ fpga添加方式的区别 include “xxx.v” 写在当前文件中,.f文件无需另外添加header文件需要设置filetype

Verilog中端口应该设置为wire形还是reg形

初学Verilog时,一直搞不清Verilog描述模块时端口应该取什么类型;是reg形?还是wire形?模块对应测试文件的端口类型为什么又与模块的端口类型不一样?因此有必要进行学习与整理: 先写结论: verilog中的端口具有三种传输方向:input、output、和inout,所有的端口均默认为wire类型; 模块描述时,input端口只能为线网形,output端口可以为线网/reg,in

根据状态转移写状态机-二段式

目录 描述 输入描述: 输出描述: 描述 题目描述:    如图所示为两种状态机中的一种,请根据状态转移图写出代码,状态转移线上的0/0等表示的意思是过程中data/flag的值。 要求: 1、 必须使用对应类型的状态机 2、 使用二段式描述方法 注意rst为低电平复位 信号示意图: 波形示意图: 激励描述如下:

PostgreSQL的学习心得和知识总结(一百四十五)|深入理解PostgreSQL数据库之ShowTransactionState的使用及父子事务有限状态机

目录结构 注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下: 1、参考书籍:《PostgreSQL数据库内核分析》 2、参考书籍:《数据库事务处理的艺术:事务管理与并发控制》 3、PostgreSQL数据库仓库链接,点击前往 4、日本著名PostgreSQL数据库专家 铃木启修 网站主页,点击前往 5、参考书籍:《PostgreSQL中文手册》 6、参考书籍:《P

状态机和行为树的搭配使用

下面是一个完整的TypeScript代码示例,展示了如何将状态机和行为树结合起来使用。状态机控制智能体的状态,行为树负责智能体的智能决策。在执行决策前,行为树会检查状态机的当前状态。 // 定义状态枚举enum BodyState {IDLE,MOVING,ATTACKING}// 状态机类,控制智能体的状态class StateMachine {private state: BodySt

深入理解Qt状态机的应用(二)

前文《深入理解Qt状态机的应用(一)》介绍了状态机的理论知识以及简单的状态机示例。在实际应用场景中,状态机往往会比较复杂;本文将详细介绍分组状态、历史状态、并行状态以及其他技术。 通过分组状态共享转换 还是以交通信号灯系统为例,上一篇文章中已经实现了简单的信号灯状态机系统,但只是正常情况下的状态转换。在实际应用场景中,信号灯除了红黄绿相互跳转外,还会存在一种情况是一直跳闪烁黄灯。我们要如何实

EtherCAT笔记(二) —— EtherCAT状态机

EtherCAT 状态机 EtherCAT的状态是由一个称为EtherCAT状态机(ESM: EtherCAT State Machine)来控制的。根据EtherCAT的状态,EtherCAT从站可以访问和执行不同的功能。EtherCAT 主站必须向每个状态下的设备发送特定命令,特别是在从站启动期间。 1 EtherCAT状态机: InitPre-Operational: PreOpSaf

深入理解Qt状态机的应用(一)

Qt的状态机框架提供了一种管理复杂系统状态的方法,它基于经典的有限状态机(FSM)理论。这种框架在开发涉及多种状态和状态之间需要明确转换的应用程序时特别有用,如用户界面交互、网络协议、游戏开发等场景。 什么是有限状态机? 有限状态机(finite-state machine)又称有限状态自动机(finite-state automaton),简称状态机,是表示有限个状态以及在这些状态之间的转

Simulink代码生成: 状态机的其他建模方法

本文研究状态机建模的一些方法和技巧。 文章目录 1 引入2 状态机建模方法2.1 状态机中的计时2.2 状态机中的计数2.3 转移顺序 3 总结 1 引入 博主一直很喜欢用Simulink中的状态机建模,在这里想记录一下自己平时使用Stateflow建模的心得。因为自身行业所限,不可能把状态机讲得面面俱到,但是可以保证具有一定的实用性。 2 状态机建模方法 2.1 状态机中