FPGA 13 基础 状态机学习(简单线性状态机)

在这里插入图片描述

FPGA 13 状态机学习(字符串状态机)

模块结构:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-890Pd4FB-1627396597935)(img/blog_img/fpga/image-20210303171411927.png)]

主要功能: 设计了一个判断 “ Hello ” 字符串判断的状态机,当一个数据流中出现了 ”Hello“字符串 ,那么 OUT 的输出电平就会翻转

实现(设计)流程:内部设计一个状态机,当时钟上升沿到来的时候,接收data[7:0]的数据流,连续判断是否接收到 ‘Hello’,只要数据流中出现 ‘Hello ’字符,那么输出的OUT的电平进行翻转,否则电平状态不发生改变。

注:设计状态机时,每一个状态有个单独的判断标志码(编码),我们在实现状态机的使用的是case(state): 语句,所以进入状态判断时,需要根据输入来判断是否进入到下一个状态,或者时回归到空闲状态。

注: 在设计状态机时,可以看到,这个是基于一个 case + if --else 语句来实现状态机功能的,case:语句来判断当前处于某种状态,if–else 来执行state 状态跳转和执行当前状态下所需要执行的语句。

实验目的 : 了解基本的状态机在FPGA的使用。区分一段、二段、三段式状态机的区别。后续有(专题:状态机)

数据判断状态机的设计基本框图 :

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wzjoDZpU-1627396597937)(img/blog_img/fpga/image-20210303171304365.png)]

Hello.v 文件

module Hello(Clk,Rst_n,data,led);

	input Clk;//50M
	input Rst_n;//低电平复位
	
	input [7:0]data;
	
	output reg out;
	
	localparam
		CHECK_H		= 5'b0_0001,
		CHECK_e 	= 5'b0_0010,
		CHECK_la	= 5'b0_0100,
		CHECK_lb	= 5'b0_1000,
		CHECK_o		= 5'b1_0000;

	reg[4:0]state;
//状态机表示状态的 3种编码方式:
  //  1、独热码   6个状态的独热码状态编码为:000001,000010,000100,001000,010000,100000
  //     独热码优势 :大大简化解码方式,效率高,但是占用更多的寄存器资源,可以看的一个状态占用 1个位.
  //  2、二进制编码    6个状态的独热码状态编码为:000,001,010,011,100,101
  //  3、格雷码 格雷码特点: 0000 0001 0011 0010 0110 ,每个状态和相邻的只有一二进制是变化的,其余保持不变
    
// 状态机分类 :
    // 一段式状态机 (本次学习使用)
    // 两段式状态机
    // 三段式状态机 (效率最高、收敛性最好)
    
    
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		out <= 1'b1;		//设置初始值为高电平
		state <= CHECK_H;   //设置 初始状态机的状态 state <= CHECK_H; 
	end
	else begin
        case(state)   //判断 state 的值
			CHECK_H:    //如果现在是 CHECK_H 的状态
                if(data == "H")   //判断此时 data 接收到的数据是否是 ‘H’
					state <= CHECK_e;   //是 ,则进入下一个状态  CHECK_e
				else
					state <= CHECK_H;  //不是,回到最初 CHECK_H 的状态
			
			CHECK_e:
				if(data == "e")
					state <= CHECK_la;
				else
					state <= CHECK_H;
					
			CHECK_la:
				if(data == "l")
					state <= CHECK_lb;
				else
					state <= CHECK_H;
					
			CHECK_lb:
				if(data == "l")
					state <= CHECK_o;
				else	
					state <= CHECK_H;
					
			CHECK_o:
				begin 
					state <= CHECK_H; //到了最后一个 CHECK_o状态,
                    				  //不论怎么样,都需要将状态返回到最初的CHECK_H 状态
                    if(data == "o")    //接收到最后一个 是字符 ‘ o ’,表示已经成功接收到一个完整的字符串
						out <= ~led;  //输出结果翻转
					else
						out <= led;  //保持该信号
				end
				
			default:state <= CHECK_H;
		endcase		
	end

endmodule
	
	/*				
			CHECK_o :				//进入第5个状态条件
				if(data == "o") begin
					led <= ~led ;
					state <= CHECK_H ;

				end	
				else
					state <= CHECK_H ;	
			default :				//其它非正常状态
					state <= CHECK_H ;
	*/


Hello_tb.v 文件

`timescale 1ns/1ns
`define clock_period 20
module Hello_tb ;

	reg Clk ;
	reg Rst_n ;
	reg [7:0]ASCII;
	
	wire led;

	Hello Hello_0(
		.Clk(Clk) ,
		.Rst_n(Rst_n) ,
		.data(ASCII) ,
		
		.out(led) 
	);

	initial Clk = 1 ;
	always#(`clock_period/2) Clk = ~Clk ;
	
	initial begin
	//信号初始化
		Rst_n = 0;
		ASCII = 0;
		#(`clock_period * 200);
		Rst_n = 1;
		#(`clock_period * 200 +1);
		
		
	// forever : 循环调用,在仿真的时候设置仿真时间即可
		forever begin
			ASCII = "I";
			#(`clock_period);
			ASCII = "A";
			#(`clock_period);
			ASCII = "M";
			#(`clock_period);
			ASCII = "X";
			#(`clock_period);
			ASCII = "i";
			#(`clock_period);
			ASCII = "a";
			#(`clock_period);
			ASCII = "o";	
			#(`clock_period);
			ASCII = "M";
			#(`clock_period);
			ASCII = "e";
			#(`clock_period);
			ASCII = "i";
			#(`clock_period);
			ASCII = "g";
			#(`clock_period);
			ASCII = "e";	
			
			#(`clock_period);
			ASCII = "H";
			#(`clock_period);
			ASCII = "E";
			
			#(`clock_period);
			ASCII = "M";
			#(`clock_period);
			ASCII = "l";
			
			#(`clock_period);
			ASCII = "H";
			#(`clock_period);
			ASCII = "E";
			#(`clock_period);
			ASCII = "L";
			#(`clock_period);
			ASCII = "L";
			#(`clock_period);
			ASCII = "O";
			#(`clock_period);
			
			ASCII = "H";
			#(`clock_period);
			ASCII = "e";
			#(`clock_period);
			ASCII = "l";
			#(`clock_period);
			ASCII = "l";
			#(`clock_period);
			ASCII = "o";
			
			#(`clock_period);
			ASCII = "l";
		end
	end
    
endmodule



本次主要学习和了解的是关于状态机器的学习,

主要是如何从当前状态转移到下一个状态,并且知道如何进行判断进入下一状态,状态机错误后该如何去解决这一情况。

另外一个,就是再测试脚本文件中的 forever 语句的功能,我们通过设置仿真文件的的时间让其运行的时间停止,否则就会不断进行循环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值