FSM有限状态机(三段式)-Verilog实现

一. 状态机理论基础

状态机基本概念:

状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作、完成特定操作的控制中心。
以上是标准解释,其实状态机就是为了解决比如IIC协议这种状态多的模块,状态多意味着直接用使能来一一判断各功能触发与否会很复杂,那么此时用状态机就可以巧妙的将所有可能的状态“串”起来,简单根据实时情况实现功能的跳变;所有逻辑顺序和时序规律的事情都可以适合用状态机来描述。
在这里插入图片描述

有限状态机类型:

第一类:若输出只和状态有关而与输入无关,则称为Moore状态机
第二类:输出不仅和状态有关而且和输入有关系,则称为Mealy状态机
两个状态机类型都常用,但一般Moore型状态机消耗的状态会比Mealy多

有限状态机的verilog三种具体实现方式:

分别有一、二、三段式状态机实现方式,这里推荐使用三段式状态机(大部分情况下,有时2段式会更好)
所谓一、二、三段粗暴理解就是可以分别使用一、二、三个always块去实现一有限个状态机
一段式:“状态变量变化,状态转移,输出” 三者全部放到一个always模块里面去实现,新手往往就会这样做,虽然这样似乎比较符合思 路,但这 样写出来的代码过于冗长,难以维护更新,还不符合时序逻辑和组合逻辑分开写的要点,因此不推荐。
二段式:将状态变量变化独立到一个always模块时序逻辑实现,状态转移和输出放到一个always模块里面组合逻辑实现,这样输出容易产生毛刺等不稳定因素。
三段式:在二的基础上,将输出独立时序逻辑输出,可以理解为独立到一个always块中用时钟沿触发,这样做层次分明,可读性强,维护简单,输出还稳定,时序逻辑可以有效“过滤输出”毛刺的问题,但是有些情况下二段式性能会更好,因为输出不用等拍,直接输出。

如何写一个高质量的状态机:

1、安全性:综合实现无毛刺异常扰动,状态机要完备,既不会进入死循环,哪怕偶然跑偏也能恢复到正常状态(三度段式+状态完备);
2、速度:速度要快,满足设计频率的要求;
3、面积:面积要小,满足设计的面积要求;
4、易懂易维护性:FSM设计要清晰易懂,易维护(采用三段式)。

2、3需要有较强的电路时序分析功底才能比较好的优化,要非常熟悉verilog综合(DC)出来的电路情况,要有一定的静态时序分析(STA)和优化的能力,初学者能做好1、4就很不错了。

二.Verilog实现状态机例子

2.1FSM实现实现11010110序列输出

状态机设计
module FSM_gener(
	input					clk,
	input					rst_n,
	
	output reg				data_current
);
	//变量分配定义
	reg	[3:0] state_current;
	reg	[3:0] state_next;
	reg 	  data_next;


	localparam       			//使用格雷码,减少数据翻转,减小误码率和功耗
		IDEL  = 4'b0000,
		ONE   = 4'b0001,
		TWO   = 4'b0011,
		THREE = 4'b0010,
		FOUR  = 4'b0110,
		FIVE  = 4'b0111,
		SIX   = 4'b0101,
		SEVEN = 4'b0100,
		EIGHT  = 4'b1100;


	//第一段状态机,时序逻辑状态更新
	always@( posedge clk or negedge rst_n ) begin
		if( !rst_n )
			state_current <= IDEL;
		else
			state_current <= state_next;
	end
	
	//第二段状态机,组合逻辑状态判断跳转
	always@( * ) begin
		case( state_current )
			IDEL:begin
					state_next <= ONE;	
					data_next <= 1'b0;
				 end
			ONE:begin
					state_next <= TWO;
					data_next <= 1'b1;
				end
			TWO: begin
					state_next <= THREE;
					data_next <= 1'b1;
				 end
			THREE:begin
					state_next <= FOUR;
					data_next <= 1'b0;
				  end
			FOUR:begin
					state_next <= FIVE;
					data_next <= 1'b1;
				 end
			FIVE:begin
					state_next <= SIX;
					data_next <= 1'b0;
				 end
			SIX: begin
					state_next <= SEVEN;
					data_next <= 1'b1;
				 end
			SEVEN:begin
					state_next <= EIGHT;
					data_next <= 1'b1;
				  end
			EIGHT:begin
					state_next <= IDEL;
					data_next <= 1'b0;
				  end
			default:begin
						state_next <= IDEL;
						data_next <= 1'b0;
				    end
		endcase
	end
	
	//第三段状态机,时序逻辑数据输出
	always@( posedge clk or negedge rst_n ) begin
		if( !rst_n )
			data_current <= 1'b0;
		else
			data_current <= data_next;
	end

endmodule
仿真验证
`timescale 1ns/1ns
`define clock_period 20

module FSM_gener_tb();

	reg					clk;
	reg					rst_n;
	wire				data_current;

	FSM_gener FSM_gener0
	(
		.clk(clk),
		.rst_n(rst_n),
	    
		.data_current(data_current)
	);
	
	initial begin clk = 1'b1; end
	always#( `clock_period )    clk = ~clk;
	
	initial begin
		rst_n = 0;
		#( `clock_period*10  );
		rst_n = 1;		
		#( `clock_period*10 + 1'b1 );
		#( `clock_period*50 );
		$stop;
	end

endmodule

仿真结果如下所示,状态机循环输出11010110满足设计要求
在这里插入图片描述

2.2 连续字符串"1101"检测

点击此处访问链接https://blog.csdn.net/weixin_42455055/article/details/119832332

  • 9
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
Verilog是一种硬件描述语言,用于描述数字电路和系统的行为。在Verilog中,可以使用状态机来设计和实现各种电路功能,包括三段式状态机三段式状态机是指状态机具有三个主要阶段:状态、输入和输出。下面是一个简单的三段式状态机Verilog示例: ```verilog module three_stage_fsm ( input clk, input reset, input start, output reg out ); // 状态声明 reg [1:0] state; localparam IDLE = 2'b00; localparam COUNT = 2'b01; localparam DONE = 2'b10; // 输出寄存器声明 reg out_reg; always @(posedge clk or posedge reset) begin if (reset) begin state <= IDLE; // 复位时状态设置为初始状态 out_reg <= 0; // 复位时输出寄存器清零 end else begin case(state) IDLE: begin if (start) begin state <= COUNT; // 转移到COUNT状态 out_reg <= 0; // 输出寄存器清零 end end COUNT: begin if (count_condition) begin state <= DONE; // 转移到DONE状态 out_reg <= 1; // 输出寄存器设置为1 end end DONE: begin state <= IDLE; // 转移到IDLE状态 out_reg <= 0; // 输出寄存器清零 end endcase end end always @(posedge clk) begin out <= out_reg; // 输出赋值给输出端口 end endmodule ``` 上述Verilog代码实现了一个简单的三段式状态机,包含了三个状态:IDLE、COUNT和DONE。在IDLE状态下,当输入start信号为高时,状态转移到COUNT状态,并将输出寄存器清零。在COUNT状态下,当某个条件满足时,状态转移到DONE状态,并将输出寄存器设置为1。在DONE状态下,状态转移到IDLE状态,并将输出寄存器清零。时钟信号用于驱动状态机的时序行为。 请注意,上述代码仅为示例,实际的实现可能会根据具体需求进行修改和调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值