Verilog笔记(四)状态机

来自正点原子的学习笔记
我在学习的过程中会尽量把它和C语言进行比较,毕竟有较大的相似之处

RTL设计主要有组合电路时序电路两个部分,还有一个非常重要的部分就是状态机,都应该熟练的掌握(刷题网站里都有对应的题目哦!~)

状态机Verilog里非常常用的语法结构

状态机

  • 1 状态机概念
    • 1.1 引子
    • 1.2 概念
  • 2 状态机模型
  • 3 状态机设计
    • 3.1 状态空间定义
    • 3.2 状态跳转(时序逻辑)
    • 3.3 下个状态判断(组合逻辑)
    • 3.4 各个状态下的动作
    • 3.5 例子

1 状态机概念

1.1 引子

Verilog笔记(四)状态机_第1张图片

状态机非常适合在Verilog里实现一些顺序的逻辑(例子里的8023四个数字的输入和检测就是顺序逻辑)
而Verilog语言是并行的,不能像C语言一样顺序执行,因此采用状态机

从这个例子里我们能总结出状态机的概念

1.2 概念

状态机(State Machine):
有限状态机(Finite State Machine,简称FSM
有限状态之间按一定规律转换时序电路

2 状态机模型

下面介绍状态机的两个模型
Verilog笔记(四)状态机_第2张图片

状态寄存器由一组触发器组成,用来记忆状态机当前所处的状态,状态的改变发生在时钟的跳变沿

组合逻辑F 不仅与 输入 有关,还与 当前状态 有关(F是当前状态和输入信号的函数)。

状态机的输出是由 输出组合逻辑G 提供的,G也是当前状态和输入信号的函数。(“解锁”就是状态机的输出结果)
更准确的说,刚才的“电子门锁”的G输出不直接(不)受输入的影响(当然,都与当前状态直接相关)
应该是Moore状态机
Verilog笔记(四)状态机_第3张图片

3 状态机设计

设计状态机的方法:四段论(八股文啊哈哈,严格的写法)
1 状态空间定义
2 状态跳转
3 下个状态判断
4 各个状态下的动作

3.1 状态空间定义

(偏抽象)
编码方式一:

//define  state space                               //定义了一天的四种状态,这个集合统称为“状态空间”
parameter  SLEEP   = 2'b00;                         //对四个状态进行编码,因为Verilog只能处理二进制数
parameter  STUDY 	= 2'b01;                        //用parameter来定义参数类型的数据
parameter  EAT      	= 2'b10;					//具体编码的值其实是无所谓的,顺序也是。
parameter  AMUSE 	= 2'b11;                        //但是还是尽量按照状态跳转的顺序来编码

// internal variable                                //定义储存状态的两个变量
reg 	[1:0] 	current_state;
reg 	[1:0] 	next_state;

编码方式二:独热码
:每个状态只有一个寄存器置位,译码逻辑简单

//define  state space                             
parameter  SLEEP   = 4'b1000;                      
parameter  STUDY 	= 4'b0100;                       
parameter  EAT      	= 4'b0010;   					
parameter  AMUSE 	= 4'b0001;   ;                     

// internal variable                                
reg 	[3:0] 	current_state;                       //状态位宽保持一致
reg 	[3:0] 	next_state;

3.2 状态跳转(时序逻辑)

// transition
always @(posedge  clk or negedge rst_n)begin
	if ( ! rst_n)
			current_state  <=  SLEEP;
	else 
			current_state  <= next _state; 			//时序逻辑里用非阻塞赋值,组合逻辑里用阻塞赋值
end 

3.3 下个状态判断(组合逻辑)

F是当前状态和输入信号的函数” 体现在 敏感列表上:

always @(current_state  or input_signals)begin 
//此处也可以用*,将块语句的中的所有变量添加到敏感列表中去

Verilog笔记(四)状态机_第4张图片
latch是电平触发的一个锁存器,会影响整个电路的时序分析,应避免
产生情况:
1.有if没else
2.case表达式没完全(比如default)

3.4 各个状态下的动作

组合逻辑有两种表达方式
方式一:assign的赋值语句

// action
wire read_book;
assign read_book = (current_state ==STUDY)	?	1'b1  : 1'b0			//条件运算符
//适用于输出信号不复杂

方式二:always 的组合语句

always @(current_stat)begin
	if (current_state == STUDY)
			read_book  =  1;
	else 
			read_book  =  0;			
end 
//适用于输出信号复杂

3.5 例子

除去状态空间定义,剩下 状态跳转下个状态判断各个状态下的动作,三个部分
因此也叫三段式状态机

模块的端口声明
Verilog笔记(四)状态机_第5张图片独热码来编码状态
s0没有位置置1,标明是初始状态
Verilog笔记(四)状态机_第6张图片
此处,状态空间定义完毕
///
下面开始三段式状态机

第一段:状态跳转(时序逻辑)
Verilog笔记(四)状态机_第7张图片
第二段:下个状态判断(组合逻辑)
至于当前状态有关,与输入无关
Verilog笔记(四)状态机_第8张图片
第三段:各个状态下的动作(时序逻辑)
虽然上文讲解的时候是组合逻辑但是在此处使用时序逻辑,还是有好处的
Verilog笔记(四)状态机_第9张图片Verilog笔记(四)状态机_第10张图片此处多了一个输出寄存器,多运用了一次时序逻辑,用于输出。

因此,三段式可以在组合逻辑后再增加一级寄存器来实现时序逻辑输出:
1.可以有效滤去组合逻辑输出的毛刺;
2.可以有效地进行时序计算与约束;
3.另外,对于总线形式的输出信号来说,容易使总线数据对齐,从而减小总线数据间的偏移(到达时间不同),减小接收端数据采样出错的频率。

你可能感兴趣的:(FPGA,fpga)