一段式、两段式以及三段式状态机(FSM)设计实例

一段式、二段式以及三段式状态机(FSM)设计实例

  • 状态机(FSM)分类
  • 状态转移的三种编码方式
  • 一段式、两段式状态机(FSM)区别
  • vivado与modelsim联调显示状态机
  • 设计实例
    • 状态转移图
    • 代码
      • 定义代码段
      • 一段式状态机(FSM)
      • 两段式状态机(FSM)
      • 三段式状态机(FSM)
    • vivado生成的综合视图
  • 后记

状态机(FSM)分类

**分类:**摩尔型(Moore)有限状态机,输出只由当前状态确定。米利型(Mealy)有限状态机,输出不止于当前状态有关还与其输入有关。
一段式、两段式以及三段式状态机(FSM)设计实例_第1张图片

状态转移的三种编码方式

一段式、两段式以及三段式状态机(FSM)设计实例_第2张图片
独热码用的寄存器多,但译码简单;格雷码用于异步多时钟多bit的转换;二进制码用的寄存器少,但译码复杂。一般在CPLD中,由于能提供较多的逻辑资源推荐使用独热码,而在FPGA中提供较多的时序逻辑而推荐使用二进制码。

一段式、两段式状态机(FSM)区别

**一段式:**整个状态机写在一个always模块里面,在该模块中既描述状态转移,又描述状态的输入和输出。
**两段式:**用两个always模块来描述状态机,其中一个always模块采用同步时序描述状态转移,另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律及其输出。
**三段式:**在两个always模块描述方法基础上,使用三个always模块,一个always模块采用同步时序描述状态转移,一个always采用组合逻辑判断状态转移条件,描述状态转移规律,另一个always模块描述状态输出(可以用组合电路输出,也可以用时序电路输出)。
**注意事项:**①二段式状态机要在后面加一个触发器消除组合逻辑对输出产生的毛刺的影响。②编写状态机需要穷举所有状态,或者使用default,避免产生不必要的锁存器。③在设计中要有异步或者同步复位来确保状态机始终有个初始态。

vivado与modelsim联调显示状态机

一段式、两段式以及三段式状态机(FSM)设计实例_第3张图片
需要先设置好vivado与modelsim的联调,具体参考其他博客,这段代码在打开modelsim后,再进行仿真时,需要删掉,否则会出现error。

设计实例

实现字符串“hello”的检测。

状态转移图

一段式、两段式以及三段式状态机(FSM)设计实例_第4张图片

代码

代码在一个.v文件中编写,可分段调试。

定义代码段

`timescale 1ns / 1ns
module fsm_hello(
    input sys_clk,
    input reset_n,
    input [7:0]data_in,
    input data_in_valid,
    output reg check_ok
    ); 
    localparam
        CHECK_h  = 5'b00_001,
        CHECK_e  = 5'b00_010,
        CHECK_l1 = 5'b00_100,
        CHECK_l2 = 5'b01_000,    
        CHECK_o  = 5'b10_000;    
    reg [4:0]state;//一段式状态机
    reg [4:0]pre_state;//两段式和三段式状态机
    reg [4:0]next_state;   

一段式状态机(FSM)

always@(posedge sys_clk or negedge reset_n)
if(!reset_n)begin
	check_ok <= 1'b0;
	state <= CHECK_h;
end 
else begin
	case(state)
		CHECK_h:begin
			check_ok <= 1'b0;
			if(data_in_valid && data_in == "h")
				state <= CHECK_e;
			else
				state <= CHECK_h;
		end
		CHECK_e:begin
			check_ok <= 1'b0;
			if(data_in_valid && data_in == "e")
				state <= CHECK_l1;
			else if(data_in_valid && data_in == "h")
				state <= CHECK_e;
			else if(data_in_valid)
				state <= CHECK_h;    
			else
				state <= CHECK_e; 
		end      
		CHECK_l1:begin
			check_ok <= 1'b0;
			if(data_in_valid && data_in == "l1")
				state <= CHECK_l2;
			else if(data_in_valid && data_in == "h")
				state <= CHECK_e;
			else if(data_in_valid)
				state <= CHECK_h;    
			else
				state <= CHECK_l1;  
		end     
		CHECK_l2:begin
			check_ok <= 1'b0;
			if(data_in_valid && data_in == "l2")
				state <= CHECK_o;
			else if(data_in_valid && data_in == "h")
				state <= CHECK_e;
			else if(data_in_valid)
				state <= CHECK_h;    
			else
				state <= CHECK_l2;    
		end   	 
		CHECK_o:        
			if(data_in_valid && data_in == "h")
				state <= CHECK_e;                 
			else if(data_in_valid)begin
				state <= CHECK_h;
				if(data_in == "o")
					check_ok <= 1'b1;
				else
					check_ok <= 1'b0;                        
				end  
			else   
				state <= CHECK_o;    
		default:state <= CHECK_h;
	endcase
end

两段式状态机(FSM)

//第一个过程,同步时序always块,描述状态转移方程
always@(posedge sys_clk)
if(!reset_n)
	pre_state <= CHECK_h;
else 
	pre_state <= next_state;
//第二个过程,组合逻辑always块,描述激励方程以及输出方程        
always@(pre_state or reset_n)begin  //电平触发,现存状态为敏感信号
case(pre_state)
	CHECK_h:
		if(!reset_n)begin
			check_ok <= 1'b0;
			next_state <= CHECK_h;
			end 
		else if(data_in_valid && data_in == "h")   
			next_state <= CHECK_e;                
		else
			next_state <= CHECK_h;  
	CHECK_e:
		if(!reset_n)begin
			check_ok <= 1'b0;
			next_state <= CHECK_h;
			end                 
		else if(data_in_valid && data_in == "e")
			next_state <= CHECK_l1;
		else if(data_in_valid && data_in == "h")
			next_state <= CHECK_e;
		else if(data_in_valid)
			next_state <= CHECK_h;    
		else
			next_state <= CHECK_e;    
	CHECK_l1:
		if(!reset_n)begin
			check_ok <= 1'b0;
			next_state <= CHECK_h;
			end                   
		else if(data_in_valid && data_in == "l1")
			next_state <= CHECK_l2;
		else if(data_in_valid && data_in == "h")
			next_state <= CHECK_e;
		else if(data_in_valid)
			next_state <= CHECK_h;    
		else
			next_state <= CHECK_l1;    
	CHECK_l2:
		if(!reset_n)begin
			check_ok <= 1'b0;
			next_state <= CHECK_h;
			end                 
		else if(data_in_valid && data_in == "l2")
			next_state <= CHECK_o;
		else if(data_in_valid && data_in == "h")
			next_state <= CHECK_e;
		else if(data_in_valid)
			next_state <= CHECK_h;    
		else
			next_state <= CHECK_l2;     
	CHECK_o:        
		if(!reset_n)begin
			check_ok <= 1'b0;
			next_state <= CHECK_h;
			end                   
		else if(data_in_valid && data_in == "h")
			next_state <= CHECK_e;                 
		else if(data_in_valid)begin
			next_state <= CHECK_h;
			if(data_in == "o")
				check_ok <= 1'b1;
			else
				check_ok <= 1'b0;                        
			end  
		else   
			next_state <= CHECK_o;                   
			 
	default:next_state <= CHECK_h;
endcase
end

三段式状态机(FSM)

//第一个过程,同步时序always块,描述状态转移方程
always@(posedge sys_clk)
if(!reset_n)
	pre_state <= CHECK_h;
else 
	pre_state <= next_state; 
//第二个过程,组合逻辑always块,描述激励方程
always@(pre_state or reset_n)begin  //电平触发,现存状态为敏感信号
case(pre_state)
	CHECK_h:
		if(!reset_n)
			next_state <= CHECK_h;
		else if(data_in_valid && data_in == "h")   
			next_state <= CHECK_e;                
		else
			next_state <= CHECK_h;  
	CHECK_e:
		if(!reset_n)
			next_state <= CHECK_h;             
		else if(data_in_valid && data_in == "e")
			next_state <= CHECK_l1;
		else if(data_in_valid && data_in == "h")
			next_state <= CHECK_e;
		else if(data_in_valid)
			next_state <= CHECK_h;    
		else
			next_state <= CHECK_e;    
	CHECK_l1:
		if(!reset_n)
			next_state <= CHECK_h;  
		else if(data_in_valid && data_in == "l1")
			next_state <= CHECK_l2;
		else if(data_in_valid && data_in == "h")
			next_state <= CHECK_e;
		else if(data_in_valid)
			next_state <= CHECK_h;    
		else
			next_state <= CHECK_l1;    
	CHECK_l2:
		if(!reset_n)
			next_state <= CHECK_h;    
		else if(data_in_valid && data_in == "l2")
			next_state <= CHECK_o;
		else if(data_in_valid && data_in == "h")
			next_state <= CHECK_e;
		else if(data_in_valid)
			next_state <= CHECK_h;    
		else
			next_state <= CHECK_l2;     
	CHECK_o:        
		if(!reset_n)
			next_state <= CHECK_h;        
		else if(data_in_valid && data_in == "h")
			next_state <= CHECK_e;                 
		else if(data_in_valid)
			next_state <= CHECK_h;
		else   
			next_state <= CHECK_o;        
	default:next_state <= CHECK_h;
endcase
end    
//第三个always块,描述输出方程     
always@(pre_state or reset_n)begin  //电平触发,现存状态为敏感信号
case(pre_state)
	CHECK_h:
		if(!reset_n)
			check_ok <= 1'b0;
	CHECK_e:
		if(!reset_n)
			check_ok <= 1'b0;  
	CHECK_l1:
		if(!reset_n)
			check_ok <= 1'b0; 
	CHECK_l2:
		if(!reset_n)
			check_ok <= 1'b0; 
	CHECK_o:        
		if(!reset_n)
			check_ok <= 1'b0;       
		else if(data_in_valid && data_in == "h")
			;                 
		else if(data_in_valid)begin
			if(data_in == "o")
				check_ok <= 1'b1;
			else
				check_ok <= 1'b0;                        
			end  
		else          
			;
	default:;
endcase
end  

vivado生成的综合视图

一段式、两段式以及三段式状态机(FSM)设计实例_第5张图片

后记

本篇主要参考小梅哥《小梅哥Xilinx FPGA自学教程V1.3》以及夏老的《Verilog数字系统设计教程(第3版)》,小梅哥的基础教程非常适合FPGA小白入门,夏老的教程更是学习Verilog必读的一本书,本人能力有限,博客主要粘贴自己平时做的笔记,难免有错误,希望大家一起讨论学习,谢谢!

你可能感兴趣的:(数电基础,状态机,Verilog)