FPGA入门学习——状态机

状态机

理论学习

状态机简写为FSM(Finite State Machine),也称为同步有限状态机,我们一般简称为状态机,之所以说“同步”是因为状态机中所有的状态跳转都是在时钟的作用下进行的,而“有限”则是说状态的个数是有限的。状态机根据影响输出的原因分为两大类,即Moore型状态机和Mealy型状态机,其共同点 是:状态的跳转都只和输入有关。区别主要是在输出的时候:若最后的输出只和当前状态有关而与输入无关则称为Moore型状态机;若最后的输出不仅和当前状态有关还和输入有关则称为Mealy型状态机。状态机是时序逻辑电路中非常重要的一个应用,常在大型复杂的系统中使用较多。

实战演练

设计需求

实现一个可乐机,每次可以投1元或者0.5元,当可乐机中有2.5元时,可以取出一瓶可乐。当可乐机中有3元时,可以取一瓶可乐并找零0.5元。

程序框图

在这里插入图片描述

状态转移图与波形图绘制

1、输入:投入0.5元硬币、投入1元硬币;

2、输出:不出可乐/不找零、出可乐/不找零、出可乐/找零;

3、状态:可乐机中有0元、可乐机中有0.5元、可乐机中有1元、可乐机中有1.5元、可乐机中有2元、可乐机中有2.5元、可乐机中有3元。

状态转移图:
在这里插入图片描述
波形图
在这里插入图片描述

代码编写

module complex_fsm
(
	input clk,reset,pi_money_half,pi_money_one,
	output reg po_cola,
	output reg po_money
);


parameter IDLE = 5'b00001;
parameter HALF = 5'b00010;
parameter ONE = 5'b00100;
parameter ONE_HALF = 5'b01000;
parameter TWO = 5'b10000;


wire[1:0] pi_money;
reg [4:0] state;

assign pi_money = {pi_money_one,pi_money_half};

always @(posedge clk or negedge reset)
	if(reset == 1'b0)
		state <= IDLE;
	else
		case(state)
			IDLE:
				if(pi_money == 2'b01)
					state <= HALF;
				else if(pi_money == 2'b10)
					state <= ONE;
				else if(pi_money == 2'b00)
					state <= IDLE;
				else
					state <= state;
			HALF:
				if(pi_money == 2'b01)
					state <= ONE;
				else if(pi_money == 2'b10)
					state <= ONE_HALF;
				else if(pi_money == 2'b00)
					state <= HALF;
				else
					state <= state;
			ONE:
				if(pi_money == 2'b01)
					state <= ONE_HALF;
				else if(pi_money == 2'b10)
					state <= TWO;
				else if(pi_money == 2'b00)
					state <= ONE;
				else
					state <= state;
			ONE_HALF:
				if(pi_money == 2'b01)
					state <= TWO;
				else if(pi_money == 2'b10)
					state <= IDLE;
				else if(pi_money == 2'b00)
					state <= ONE_HALF;
				else
					state <= state;
			TWO:
				if(pi_money == 2'b01 || pi_money == 2'b10)
					state <= IDLE;
				else if(pi_money == 2'b00)
					state <= TWO;
				else
					state <= state;
			default: state <= IDLE;
		endcase


// 输出可乐信号
always @(posedge clk or negedge reset)
	if(reset == 1'b0)
		po_cola = 1'b0;
	else if((state == ONE_HALF && pi_money == 2'b10)
				|| (state == TWO && pi_money == 2'b01)
				|| (state == TWO && pi_money == 2'b10))
		po_cola = 1'b1;
	else
		po_cola = 1'b0;
	
//输出找零信号
always @(posedge clk or negedge reset)
	if(reset == 1'b0)
		po_money = 1'b0;
	else if(state == TWO && pi_money == 2'b10)
		po_money = 1'b1;
	else
		po_money = 1'b0;
	
endmodule

仿真测试

`timescale 1 ns/ 1 ns
module complex_fsm_vlg_tst();

reg clk;
reg pi_money_half;
reg pi_money_one;
reg reset;

wire[4:0] state = i1.state;
wire[1:0] pi_money = i1.pi_money;                                             
wire po_cola;
wire po_money;

                          
complex_fsm i1 (
// port map - connection between master ports and signals/registers   
	.clk(clk),
	.pi_money_half(pi_money_half),
	.pi_money_one(pi_money_one),
	.po_cola(po_cola),
	.po_money(po_money),
	.reset(reset)
);
initial                                                
begin                                                  
	clk = 1'b1;
	reset <= 1'b0;
	#20
	reset <= 1'b1;
end                                                    
always  #10 clk = ~clk;                                                                     

always @(posedge clk or negedge reset)
	if(reset == 1'b0)
		begin
			pi_money_half = 1'b0;
			pi_money_one = 1'b0;
		end
	else
		begin
			pi_money_half = {$random} % 2;
			if(pi_money_half == 1'b0)
				pi_money_one = {$random} % 2;
			else
				pi_money_one = 1'b0;
		end

initial
	begin
		$timeformat(-9,0,"ns",6);
		$monitor("@time %t:pi_money_half=%b,pi_money_one=%b,pi_money=%b,state=%b,po_cola=%b,po_money=%b",$time,pi_money_half,pi_money_one,pi_money,state,po_cola,po_money);

	end
endmodule


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值