Verilog-语法篇4-状态机(正点原子笔记)

为什么使用状态机?
因为vreilog并行执行的,当需要顺序执行时(类似c语言),可以使用状态机

状态机概念

状态机(State Machine)

有限状态机(Finite State Machine,简称FSM)
		在有限个状态之间按一定规律转换的时序电路
	由两个组合逻辑电路和一个时序逻辑电路组成

状态机模型(抽象的状态机结构)

在这里插入图片描述

状态寄存器
		由一组触发器组成,用来记忆当前状态机所处的状态,
		状态寄存器状态的改变只发生在时钟的跳变沿
		
Mealy状态机如上(Moore状态机较为不同)
		
状态是否改变、如何改变取决于组合逻辑F的输出,	F又取决于输入信号和当前状态

状态机的输出是由组合逻辑G提供的,			G也取决于输入信号和当前状态

状态机设计

方法——四段论

1.状态空间定义
2.状态跳转
3.下个状态判断
4.各个状态下的动作
1.状态空间定义
//denfine 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;//bits match top parameter
reg	[1:0]	next_state;

/
独热码写法(每个状态对应一个寄存器),状态机推荐
//denfine state space
parameter SLEEP		=		2'b1000		;
parameter STUDY		=		2'b0100		;
parameter EAT		=		2'b0010		;
parameter AMUSE		=		2'b0001		;

//internal variable
reg [3:0]	current_state;//bits match top parameter
reg	[3:0]	next_state;
2.状态跳转(时序逻辑–状态寄存器)
//transition
always @ (posedge clk or negedge rst_n) begin
	if (!rst_n)
		current_state		<=		SLEEP		;	//give starter
	else
		current_state		<=		next_state	; 
end
3.下个状态判断(产哼下一状态的组合逻辑)
always @ (current_state or input_singnals) begin	//senstive list are high and low voltage
	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:	...			;
//if与else配对,case要有default ,是为了避免产生锁存器(latch)	——电平触发,只在组合逻辑中产生
//											触发器        	——边沿触发		
	endcase
end
	
4.各个状态下的动作(产生输出的组合逻辑)
//action

第一种写法,状态较为简单时
wire read_book;
assign	read_book	=	(current_state == STUDY ? 1'b1 : 1'b0)

第二种写法,状态较为复杂时
always @ (current_state) begin
	if(curent_book == STUDY)
		read_book = 1;
	else
		read_book = 0;
end
由上述步骤所组合称为三段式状态机

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

moudle 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			;

//wire define

//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 negedge sys_rst_n) begin
	if(sys_rst_n == 1'b0)
		curr_st <= 7'b0;
	else
		curr_st <= next_st;
end

//FSM state logic
always @ (*) begin
	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 @ (posedeg 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)) begin
		clk_divide_7 <= 1'b0;
	end else if ((curr_st == S4) | curr_st == S5) | curr_st == S6)) begin
		clk_divide_7 <= 1'b1;
	end else ;
end
三段式可以在组合逻辑后再增加一级寄存器来实现时序逻辑输出;
	1.可以有效地过滤去组合逻辑输出的毛刺(锁存器等);
	2.可以有效地进行时序计算与约束;
	3.另外对于总线形式的输出信号(8_bits)来说,容易使总线数据对齐,从而减少总线数据间的偏移,
															 所以就减少了接收端数据采样出错的频率。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值