[FPGA]_状态机基础

一、摩尔状态机和米利状态机

        

 1.1 相关例子

        1.1.1检测"H" "E" "L" "L" "O''

 



 

 

        (输入)检测到"H"+下一个状态的组合逻辑,产生激励信号state<=CHECK_e,给到状态寄存器CHECK_e,产生输出组合逻辑led <= led

       输出仅仅由当前状态机(CHECK_e)组合逻辑;

/***************************************************
*	Module Name		:	Hello		   
*	Engineer		:	小梅哥
*	Target Device	:	EP4CE10F17C8
*	Tool versions	:	Quartus II 13.0
*	Create Date		:	2017-3-31
*	Revision		:	v1.0
*	Description		:   实现字符串检测,每检测成功一次 LED状态便翻转一次
**************************************************/

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

	input Clk;//50M
	input Rst_n;//低电平复位
	
	input [7:0]data;
	
	output reg led;
	
	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;
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		led <= 1'b1;
		state <= CHECK_H;
	end
	else begin
		case(state)
			CHECK_H:
				if(data == "H") state <= CHECK_e;
				else state <= CHECK_H;
			
			CHECK_e:
				if(data == "e") state <= CHECK_la;
				else if(data == "H") state <= CHECK_e;
				else state <= CHECK_H;
					
			CHECK_la:
				if(data == "l") state <= CHECK_lb;
				else if(data == "H") state <= CHECK_e;
				else state <= CHECK_H;
					
			CHECK_lb:
				if(data == "l") state <= CHECK_o;
				else if(data == "H") state <= CHECK_e;
				else state <= CHECK_H;
					
			CHECK_o:
				if(data == "H") state <= CHECK_e;
				else begin
					state <= CHECK_H;
					if(data == "o")
						led <= ~led;
					else
						led <= led;
				end
				
			default:state <= CHECK_H;
		endcase		
	end

endmodule

      1.1.2 fsm 按键消抖

 

        米利有限状态机的输出不止与其输入有关还于它的当前状态相关,这也是与摩尔有限状态
机的不同之处。这句话的理解,在检测按下后检测上升沿的状态时,如果当前状态是检测按下时间到达,则输出就是判断已按下再松开,如果当前状态是正在检测按下时间是否足够,未足够,就检测到上升沿,则输出就是判断未正确按下。所以此时输入就是会影响产生输出的组合逻辑。

/***************************************************
*	Module Name		:	key_filter		   
*	Engineer		   :	小梅哥
*	Target Device	:	EP4CE10F17C8
*	Tool versions	:	Quartus II 13.0
*	Create Date		:	2017-3-31
*	Revision		   :	v1.0
*	Description		:  单按键消抖设计
**************************************************/

module key_filter(
			Clk,      //50M时钟输入
			Rst_n,    //模块复位
			key_in,   //按键输入
			key_flag, //按键标志信号
			key_state //按键状态信号
		);

	input Clk;
	input Rst_n;
	input key_in;
	
	output reg key_flag;
	output reg key_state;
	
	localparam
		IDEL		= 4'b0001,
		FILTER0	= 4'b0010,
		DOWN		= 4'b0100,
		FILTER1 	= 4'b1000;
		
	reg [3:0]state;
	reg [19:0]cnt;
	reg en_cnt;	//使能计数寄存器
	
//对外部输入的异步信号进行同步处理
	reg key_in_sa,key_in_sb;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		key_in_sa <= 1'b0;
		key_in_sb <= 1'b0;
	end
	else begin
		key_in_sa <= key_in;
		key_in_sb <= key_in_sa;	
	end
	
	reg key_tmpa,key_tmpb;
	wire pedge,nedge;
	reg cnt_full;//计数满标志信号
	
//使用D触发器存储两个相邻时钟上升沿时外部输入信号(已经同步到系统时钟域中)的电平状态
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		key_tmpa <= 1'b0;
		key_tmpb <= 1'b0;
	end
	else begin
		key_tmpa <= key_in_sb;
		key_tmpb <= key_tmpa;	
	end

//产生跳变沿信号	
	assign nedge = !key_tmpa & key_tmpb;
	assign pedge = key_tmpa & (!key_tmpb);
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		en_cnt <= 1'b0;
		state <= IDEL;
		key_flag <= 1'b0;
		key_state <= 1'b1;
	end
	else begin
		case(state)
			IDEL :
				begin
					key_flag <= 1'b0;
					if(nedge)begin
						state <= FILTER0;
						en_cnt <= 1'b1;
					end
					else
						state <= IDEL;
				end
					
			FILTER0:
				if(cnt_full)begin
					key_flag <= 1'b1;
					key_state <= 1'b0;
					en_cnt <= 1'b0;
					state <= DOWN;
				end
				else if(pedge)begin
					state <= IDEL;
					en_cnt <= 1'b0;
				end
				else
					state <= FILTER0;
					
			DOWN:
				begin
					key_flag <= 1'b0;
					if(pedge)begin
						state <= FILTER1;
						en_cnt <= 1'b1;
					end
					else
						state <= DOWN;
				end
			
			FILTER1:
				if(cnt_full)begin
					key_flag <= 1'b1;
					key_state <= 1'b1;
					state <= IDEL;
					en_cnt <= 1'b0;
				end
				else if(nedge)begin
					en_cnt <= 1'b0;
					state <= DOWN;
				end
				else
					state <= FILTER1;
			
			default:
				begin 
					state <= IDEL; 
					en_cnt <= 1'b0;		
					key_flag <= 1'b0;
					key_state <= 1'b1;
				end
				
		endcase	
	end
	

	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		cnt <= 20'd0;
	else if(en_cnt)
		cnt <= cnt + 1'b1;
	else
		cnt <= 20'd0;
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		cnt_full <= 1'b0;
	else if(cnt == 20'd999_999)
		cnt_full <= 1'b1;
	else
		cnt_full <= 1'b0;	

endmodule

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值