初学FPGA——状态机

@[仅记录FPGA学习过程中的点点滴滴,欢迎交流与指正]

基础知识

状态机全称是有限状态机(Finite State Machine,FSM ),是一种在有限个状态之间按一定规律转换的时序电路,可以认为是组合逻辑和时序逻辑的一种组合。状态机通过控制各个状态的跳转来控制流程,使得整个代码看上去更加清晰易懂,在控制复杂流程的时候,状态机优势明显,因此基本上都会用刀状态机。
状态机功能:

  1. 描述系统逻辑功能。
  2. 定义系统的不同状态。
  3. 描述系统转化的条件及转化过程。
  4. 刻画系统状态和输入输出之间的关系。

状态机的分类——Mealy型和moore型
根据状态机的输出是否与输入条件相关,可将状态机分为两大类,即米勒(Mealy)型状态机和摩尔(Moore)型状态机。
Mealy型:时序逻辑的输出,不仅仅取决于状态,还取决于信号的输入。
Mealy型状态机
Moore型:时许逻辑的输出只取决于上一时刻的状态,与当前信号的输入无关。
Moore型状态机
在实际设计中,Mealy型状态机使用最多,Moore型状态机虽然清晰明了,但状态过多,不适合大型状态机。

状态机的设计步骤

状态机的设计步骤主要分为以下四个步骤:
1.逻辑抽象:得出状态转移图,具体的说就是给出一个实际问题表示为时序逻辑函数。可以用状态转换表来描述,也可以用状态转换图来描述。
2.状态化简:化简状态转移图,具体地说就是合并在相同的输入下转换到同一个状态并得到相同输出的状态。
3.状态分配:状态编码,一般使用二进制编码(binary_code)、格雷码(gray_code)、独热码(one_hot_code)等。
4.描述建模

状态机的描述方式

状态机的描述方式有很多种,主要常用的有三种,分别为一段式,二段式和三段式。
1.一段式:单always块把组合逻辑和时序逻辑用同一时序always块描述,其输出是寄存器输出,无毛刺;但这种方式可能会出发多余的粗发起,代码难于修改和调试,不推荐使用。

2.两段式:双always块大多用于描述Mealy型状态机和组合输出的Moore状态机,时序always块描述当前状态逻辑,组合逻辑always块描述次态逻辑并给出输出赋值。这种方式结构清晰,综合后的面积和时间性能好,但组合逻辑输出往往会有毛刺,当输出向量作为时钟信号时,这些毛刺会对电路产生致命的影响。所以两段式很少有人使用。

3.三段式:三always块大多用于同步Mealy状态机,两个时序always块分别用来描述现态逻辑和对输出赋值,组合always块用于产生下一状态。时序电路的状态是一个状态变量集合,这些状态变量在任意时刻的值都包含了为确定电路的未来行为而必须考虑的所有历史信息。
这种三段式的状态机也是寄存器输出,输出无毛刺,并且代码比单always块更加清晰易读,但是面积大于双always块。随着芯片资源和速度的提高,目前这种方式得到了广泛的应用。

一段式状态机的一般结构

总结实例如下:

//一段式状态机示例
//  功能 flag_en信号到来时,实现状态跳转,并输出5位数字信号
`timescale 1ns / 1ps						
module fsm_one(
	input		wire				clk,
	input		wire				rst,
	input		wire				flag_en,
	output		reg		[4:0]		flag_out
    );	
		
	reg			[2:0]	state;			//只需要定义状态寄存器	
	
	//状态编码
	parameter	IDLE	=	3'b000; 	//Binary Gray Code
	parameter	ONE		=	3'b001;
	parameter	TWO		=	3'b011;
	parameter	THREE	=	3'b111;
	parameter	...................

	//一段式状态机
	always @ (posedge clk) begin
		if (rst) begin
			state 	 <= IDLE;			//状态寄存器位于IDLE状态
			flag_out <= 5'b00000;		//输出复位
		end
		else begin
			case (state)				//**case语句,以state作为敏感信号
				IDLE	:	begin
					if (flag_en) begin
						state <= ONE;
						flag_out <= 5'b11110;
					end
					else begin
						state <= IDLE;
						flag_out <= 5'b00000;
					end
				end
				ONE		:	begin
					if (flag_en) begin
						state <= TWO;
						flag_out <= 5'b11101;
					end
					else begin
						state <= ONE;
						flag_out <= 5'b11110;
					end
				end
				TWO		:	begin
					if (flag_en) begin
						state <= THREE;
						flag_out <= 5'b11011;
					end
					else begin
						state <= TWO;
						flag_out <= 5'b11101;
					end
				end
				THREE	:	begin
					if (flag_en) begin
						state <= ....;
						flag_out <= 5'b10111;
					end
					else begin
						state <= THREE;
						flag_out <= 5'b11011;
					end
				end
				............................
				default	:	begin			//默认设置
					state <= IDLE;
				end
			endcase
		end
	end	
endmodule

三段式状态机的一般结构

三段式状态机的一般结构
示例如下:

//三段式状态机示例
//功能 flag_en信号到来时,实现状态跳转,并输出5位数字信号
`timescale 1ns / 1ps
module fsm_three(
	input		wire				clk,
	input		wire				rst,
	input		wire				flag_en,
	output		reg		[4:0]		flag_out
    );
	
	reg			[2:0]	current_state;	//定义当前时刻状态寄存器
	reg			[2:0]	next_state;		//定义下一状态寄存器
	
	// 状态编码
	localparam	IDLE	=	3'b000;
	localparam	ONE		=	3'b001;
	localparam	TWO		=	3'b011;
	localparam  THREE	=	3'b010;
	localparam	...................
	
	// *FSM1 用*时序逻辑* -通用-
	always @ (posedge clk) begin
		if (rst) begin
			current_state <= IDLE;
		end
		else begin
			current_state <= next_state;
		end
	end	
	
	// *FSM2 采用*组合逻辑*描述状态转移过程
	always @ (*) begin					//(*)
		case (current_state)			//采用current_state作为敏感信号
			IDLE	:	begin
				if (flag_en) begin		//控制next_state进行跳转
					next_state = ONE;	//组合逻辑
				end
				else begin
					next_state = IDLE;
				end	
			end
			ONE		:	begin
				if (flag_en) begin
					next_state = TWO;
				end
				else begin
					next_state = ONE;
				end
			end
			TWO		:	begin
				if (flag_en) begin
					next_state = THREE;
				end
				else begin
					next_state = TWO;
				end
			end
			THREE	:	begin
				if (flag_en) begin
					next_state = ....;
				end
				else begin
					next_state = THREE;
				end
			end
			..........................
			default	:	begin
				next_state = IDLE;
			end
		endcase
	end
	
	
	// *FSM3	采用*时序逻辑*进行行为描述 
	
	always @ (posedge clk) begin
		if (rst) begin
			flag_out <= 5'b00000;	//输出初始化	
		end
		else begin
			case (current_state)	//使用current_state作为敏感信号
				IDLE	:	begin
					if (flag_en) begin 
						flag_out <= 5'b11110;//时序逻辑
					end
					else begin
						flag_out <= 5'b00000;
					end
				end
				ONE		:	begin
					if (flag_en) begin
						flag_out <= 5'b11101;
					end
					else begin
						flag_out <= 5'b11110;
					end
				end
				TWO		:	begin
					if (flag_en) begin
						flag_out <= 5'b11011;
					end
					else begin
						flag_out <= 5'b11101;
					end
				end
				THREE	:	begin
					if (flag_en) begin
						flag_out <= 5'b10111;
					end
					else begin
						flag_out <= 5'b11011;
					end
				end
				.............................
				default	:	begin
					flag_out <= 5'b00000;
				end
			endcase
		end
	end
endmodule
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值