Verilog之状态机

状态机(State Machine)
有限状态机(Finite State Machine,简称FSM)。
在有限个状态之间按一定规律转换的时序电路。
状态机例子:密码锁的设计(状态转移图)
在这里插入图片描述
状态机模型
Mealy 状态机(输出与输入有关)
在这里插入图片描述
Moore状态机(输出与输入无关)
在这里插入图片描述
状态寄存器由一组触发器组成,用来记忆状态机当前所处的状态,状态的改变只发生在时钟的跳变沿。
状态是否改变、如何改变,取决于组合逻辑F的输出,F是当前状态和输入信号的函数。
状态机的输出是由输出组合逻辑G提供的,G也是当前状态的输入信号的函数。

状态机设计
1、状态空间定义
2、状态跳转
3、下个状态判断
4、各个状态下的动作

1、状态空间定义
方法一:

//define state space
parameter SLEEP		=		2'b00;
parameter STUDY		=		2'b01;
parameter EAT		=		2'b10;
parameter AMUSE		= 		2'b11;

//internal variable
reg	[1:0] current_state;
reg [1:0] next_state;

方法二:状态的赋值使用独热码(每个状态机只有一个寄存器位置位,译码逻辑简单)

//define state space
parameter SLEEP		=	4'b1000;
parameter STUDY 	=	4'b0100;
parameter EAT		=	4'b0010;
parameter AMUSE		=	4'b0001;

//internal variable
reg	[3:0] current_state;
reg [3:0] next_state;

2、状态跳转(时序逻辑)

//transition
always @(posedge clk or negedge rst_n) begin//敏感列表:时钟信号以及复位信号边沿的组合
	if(!rst_n)
		current_state <= SLEEP; //使用非阻塞赋值
	else
		current_state <= next_state;
end

3、下个状态判断(组合逻辑)

//next state decision
always @(current_state or input_signals) begin
	case (current_state)
		SLEEP: begin
			if(clock_alarm)
				next_state = STUDY;
			else
				next_state = SLEEP;
		end
		STUDY: begin
			if(lunch_time)
				next_state = EAT;
			else
				next_state = STUDY;
		end
		EAT: ...;
		AMUSE::...;
		default:...;
	endcase
end

If/else要配对以避免latch的产生

4、各个状态下的动作
方法一:

//action
wire read_book;
assign read_book = (current_state == STUDY) ? 1'b1 : 1'b0;

方法二:

always @(current_state) begin
	if(current_state == STUDY)
		read_book = 1;
	else
		read_book = 0;
end

三段式可以在组合逻辑后在增加一级寄存器来实现时序逻辑输出:
在这里插入图片描述
其优点:
1)可以有效地虑去组合逻辑输出的毛刺;
2)可以有效地进行时序计算与约束;
3)另外对于总线形式的输出信号来说,容易使总线数据对齐,从而减小总线数据见得偏移,减小接收端数据采样出错的频率。

一个三段式状态机的例子(分频器)

module divider7_fsm(
//input ports
input		sys_clk,
input		sys_rst_n,

//output ports
output	reg	clk_divide_7
);

//reg define
reg [6:0]	curr_st;
reg [6:0]	next_st;

//parameter define
parameter WIDTH = 1;

//one hot code design,各个状态的定义
parameter S0 = 7'b0000000;
parameter S1 = 7'b0000001;
parameter S2 = 7'b0000010;
parameter S3 = 7'b0000100;
parameter S4 = 7'b0001000;
parameter S5 = 7'b0010000;
parameter S6 = 7'b0100000;

always @(posedge sys_clk or megedge sys_rst_n) begin
	if (sys_rst_n == 1'b0)
		curr_st <= 7'b0;
	else
		curr_st <= next_st;
end

//FSM state logic
always @(*) degin
	case (curr_st)
		S0: begin
				next_st = S1;
			end
		S1: begin
				next_st = S2;
			end
		S2: begin
				next_st = S3;
			end	
		S3: begin
				next_st = S4;
			end
		S4: begin
				next_st = S5;
			end
		S5: begin
				next_st = S6;
			end
		S6: begin
				next_st = S0;
			end
		default:next_st = S0;
	endcase
end

//control divide clock offset
always @(posedge sys_clk or negedge sys_rst_n) begin
		if (sys_rst_n == 1'b0) begin
			clk_divide_7 <= 1'b0;
		end
		else if ((curr_st == S0) | (curr_st == S1) | (curr_st == S2)  | (curr_st == S3) )
			clk_divide_7 <= 1'b0;
		else if ((curr_st == S4) | (curr_st == S5) | (curr_st == S6) )
			clk_divide_7 <= 1'b1;
		else;
end
发布了8 篇原创文章 · 获赞 7 · 访问量 2877

猜你喜欢

转载自blog.csdn.net/yijiancmy/article/details/104176384