Verilog实现二段式和三段式有限状态机

有限状态机(Finite State Machine,FSM)又称为状态机,为时序逻辑电路中常采用的一种形式,也是时序电路的通用模型任何时序电路,都可以表示为有限状态机。

1、状态机的概述

状态机一般由寄存器和组合逻辑两部分组成,寄存器主要是存储状态,而组合逻辑主要用于产生输出和激励信号。
状态机,根据输出信号是否当前的输入信号,分为米利型(Mealy)和穆尔型(Moore)。米利型状态机的输出由状态机的当前状态和当前输入一起决定,当输入信号不与时钟同步时输出也不与时钟同步。而穆尔型状态机的输出状态只取决于当前状态,与当前的输入状态无关,输出的改变需要等待一个时钟周期才能体现在输出上。
Verilog实现二段式和三段式有限状态机_第1张图片
Verilog实现二段式和三段式有限状态机_第2张图片

2、状态编码

为了适应不同的应用场景,状态机有着不同的编码方式,常见的编码有:8421BCD码,格雷码,约翰逊码,独热码。编码方式对比如表2-1所示:
表2-1
Verilog实现二段式和三段式有限状态机_第3张图片
BCD码将状态,表示成2进制数,这种编码方式可以减少触发器的使用。
而格雷码和约翰逊码,每一个状态只有一位不同,可以有效减少电路噪声。
独热码每一位需要一个单独的触发器,可以有效地减少编码和译码的组合逻辑电路大小。但对触发器数量要求较大。

3、二段式状态机

Verilog语言中,常常采用二段式和三段式描述状态机。其本质是对应状态机的激励方程,状态转换方程和输出方程。三段式每一段对应一个方程,二段式则是将输出方程和激励方程合并在一起描述。
二段式描述五位计数器

module counter_5 (clk,rst,Q);
	input clk,rst;
	output Q;
	reg Q;
	reg [2:0]pre_state,nex_state;
	parameter s0=3'b000,s1=3'b001,s2=3'b010,s3=3'b011,s4=3'b100;
	always@(posedge clk or posedge rst)
	begin
		if (rst==1'b1) pre_state<=s0;
		else pre_state<=nex_state;
	end
	
	always@(pre_state)
	begin
		nex_state<=3'bxxx;
		Q<=1'b0;
		case (pre_state)
			s0:begin nex_state<=s1;Q<=1'b0;end
			s1:begin nex_state<=s2;Q<=1'b0;end
			s2:begin nex_state<=s3;Q<=1'b0;end
			s3:begin nex_state<=s4;Q<=1'b0;end
			s4:begin nex_state<=s0;Q<=1'b1;end
			default:begin nex_state<=s0;Q<=1'b0;end
		endcase
	end
endmodule 

测试代码:

module counter_5_t;
	reg clk,rst;
	wire Q;
	initial
	begin
		clk=1'b0;
		forever #10 clk=~clk;
	end
	
	initial 
	begin
		rst=1'b0;
		#10 rst=1'b1;
		#10 rst=1'b0;
	end
	
	counter_5 u1(.clk(clk),.rst(rst),.Q(Q));
endmodule 

3、三段式

module counter3_5 (clk,rst,Q);
	input clk,rst;
	output Q;
	reg Q;
	reg [2:0] pre_state,nex_state;
	parameter s0=3'b000,s1=3'b001,s2=3'b010,s3=3'b011,s4=3'b100;
	always@(posedge clk or posedge rst)
	begin
		if (rst==1'b1) pre_state<=s0;
		else pre_state<=nex_state;
	end
	
	always@(pre_state)
	begin
		nex_state<=3'bxxx;
		case (pre_state)
		s0:nex_state<=s1;
		s1:nex_state<=s2;
		s2:nex_state<=s3;
		s3:nex_state<=s4;
		s4:nex_state<=s0;
		default:nex_state<=s0;
		endcase
	end
	
	always@(pre_state)
	begin
		Q<=1'b0;
		case (pre_state)
			s0:Q<=1'b0;
			s1:Q<=1'b0;
			s2:Q<=1'b0;
			s3:Q<=1'b0;
			s4:Q<=1'b1;
			default:Q<=1'b0;
		endcase
	end
endmodule 

测试代码可见二段式测试代码
仿真结果如图:
在这里插入图片描述

你可能感兴趣的:(数字电路设计,Verilog,HDL)