【附源码】基于fpga的自动售货机(三段式状态机)

目录

1、VL38 自动贩售机1

题目介绍

思路分析

代码实现

仿真文件

2、VL39 自动贩售机2

题目介绍:

题目分析

代码实现

仿真文件

3、状态机基本知识


1、VL38 自动贩售机1

题目介绍

        设计一个自动贩售机,输入货币有三种,为0.5/1/2元,饮料价格是1.5元,要求进行找零,找零只会支付0.5元。

ps:

        1、投入的货币会自动经过边沿检测并输出一个在时钟上升沿到1,在下降沿到0的脉冲信号

        2、注意rst为低电平复位

信号示意图:

波形示意图:

思路分析

代码实现

module seller1(
	input wire clk  ,
	input wire rst  ,
	input wire d1 ,			//0.5元
	input wire d2 ,			//1.0元
	input wire d3 ,			//2.0元
	
	output reg 		out1,	//饮料
	output reg [1:0]out2	//零钱
);
//*************code***********//


parameter [2:0]	s0 = 3'b000,
				s1 = 3'b001,		
				s2 = 3'b010,
				s3 = 3'b011,
				s4 = 3'b100,	
				s5 = 3'b101,
				s6 = 3'b110;
						
reg [2:0] curr_state;
reg [2:0] next_state;

//第一段 状态转移
always @(posedge clk or negedge rst)begin
	if(!rst)
		curr_state <= s0;
	else
		curr_state <= next_state;
	end

//第二段 转移状况
always @(*)begin
	case(curr_state)
		s0:begin	
			if(d1) 		next_state = s1;
			else if(d2) next_state = s2;
			else if(d3) next_state = s3;
			else 		next_state = next_state;	//为什么保持原值next_state,而不是s0?
		   end
		s1:begin	
			if(d1) 		next_state = s2;
			else if(d2) next_state = s4;
			else if(d3) next_state = s5;
			else 		next_state = next_state;
		   end
		s2:begin	
			if(d1) 		next_state = s4;
			else if(d2) next_state = s3;
			else if(d3) next_state = s6;
			else 		next_state = next_state;
		   end
		s3,s4,s5,s6:begin next_state = s0;end	
		default: begin next_state = s0;end
	endcase	   
end
	
//第三段 状态输出 moore FSM

always @(posedge clk or negedge rst)begin	//为什么用时序电路,而不是组合电路?
	if(!rst)
		out1 <= 0;
	else if(	
		next_state == s3 || 
		next_state == s4 || 
		next_state == s5 || 
		next_state == s6
	)
		out1 <= 1;	//出货标志
	else
		out1 <= 0;	
	end

always @(posedge clk or negedge rst)begin  //为什么用时序电路,而不是组合电路?
	if(!rst)
		out2 <= 0;
	else if(next_state == s3)
		out2 <= 2'd1;	//找零5毛的数量	
	else if(next_state == s5)
		out2 <= 2'd2;	
	else if(next_state == s6)
		out2 <= 2'd3;				
	else
		out2 <= 2'b0;	
	end

//*************code***********//
endmodule

针对代码中的问题“为什么保持原值next_state,而不是s0?”

答:如下图所示,如果保持s0,因为是组合逻辑,且输入信号d1为半个时钟周期,那么就会导致next_state在s1和s0之间翻转,而不是保持正确的状态s1。

 参考这个回答:

仿真文件

仿真图:

仿真代码:

module tb_seller1;
	
	reg clk;
	reg rst;
	reg d1,d2,d3;	
	
	wire 		out1;
	wire [1:0] 	out2; 
	
//1、初始化
initial begin
	clk = 0;
	rst = 0;
	d1 = 0;
	d2 = 0;
	d3 = 0;
end	
		
//2、产生激励
always #5 clk = ~clk;
	
initial begin
	#10;
	rst = 1'b1;
	
	#20;
	@(posedge clk); {d1,d2,d3}=3'b100;	//0.5
	@(posedge clk); {d1,d2,d3}=3'b000;	
	#50;                    
	@(posedge clk); {d1,d2,d3}=3'b010;	//1.5
	@(posedge clk); {d1,d2,d3}=3'b000;		
	#30;                    
	@(posedge clk); {d1,d2,d3}=3'b100;	//0.5
	@(posedge clk); {d1,d2,d3}=3'b000;		
	#60;                    
	@(posedge clk); {d1,d2,d3}=3'b100;	//1
	@(posedge clk); {d1,d2,d3}=3'b000;		
	#50;                    
	@(posedge clk); {d1,d2,d3}=3'b001;	//3
	@(posedge clk); {d1,d2,d3}=3'b000;		
	#50;                    
	@(posedge clk); {d1,d2,d3}=3'b001;	//2
	@(posedge clk); {d1,d2,d3}=3'b000;		
	#30;                    
	@(posedge clk); {d1,d2,d3}=3'b100;	//0.5
	@(posedge clk); {d1,d2,d3}=3'b000;		
	#60;                    
	@(posedge clk); {d1,d2,d3}=3'b001;	//2.5
	@(posedge clk); {d1,d2,d3}=3'b000;		
	#50;                    
	@(posedge clk); {d1,d2,d3}=3'b010;	//1
	@(posedge clk); {d1,d2,d3}=3'b000;		
	#60;                    
	@(posedge clk); {d1,d2,d3}=3'b010;	//2
	@(posedge clk); {d1,d2,d3}=3'b000;		
end	
	
//3、仿真暂停
initial begin
	#1000 
	$finish();
end		
	
//4、实例化
seller1 u1_seller1(
	.clk(clk),
	.rst(rst),
	.d1 (d1),		//0.5元
	.d2 (d2),		//1.0元
	.d3 (d3),		//2.0元
	.out1(out1),	//饮料
	.out2(out2)		//零钱
);
	
endmodule

2、VL39 自动贩售机2

题目介绍:

        设计一个自动贩售机,输入货币有两种,为0.5/1元,饮料价格是1.5/2.5元,要求进行找零,找零只会支付0.5元。

ps:

        1、投入的货币会自动经过边沿检测并输出一个在时钟上升沿到1,在下降沿到0的脉冲信号

        2、此题忽略出饮料后才能切换饮料的问题

        注意rst为低电平复位

波形示意图:

题目分析

代码实现

module seller2(
	input wire clk  ,
	input wire rst  ,
	input wire d1 ,			//0.5元
	input wire d2 ,			//1.0元
	input wire sel ,		//0选择1.5元、1选择2.5元
		
	
	output reg 		out1,	//饮料1(1.5元)
	output reg 		out2,	//饮料2(2.5元)
	output reg [1:0]out3	//零钱
	
);
//*************code***********//


parameter [2:0]	s0 = 3'b000,
				s1 = 3'b001,		
				s2 = 3'b010,
				s3 = 3'b011,
				s4 = 3'b100,	
				s5 = 3'b101,
				s6 = 3'b110;
						
reg [2:0] curr_state;
reg [2:0] next_state;

//第一段 状态转移
always @(posedge clk or negedge rst)begin
	if(!rst)
		curr_state <= s0;
	else
		curr_state <= next_state;
	end

//第二段 转移状况
always @(*)begin
	case(curr_state)
		s0:	begin
				if(d1) 		next_state = s1;
				else if(d2) next_state = s2;
				else 		next_state = next_state;	
			end
		s1:	begin	
				if(d1) 		next_state = s2;
				else if(d2) next_state = s3;
				else 		next_state = next_state;	
			end
		s2:	begin
				if(d1) 		next_state = s3;
				else if(d2) next_state = s4;
				else 		next_state = next_state;	
			end
		s3:	begin	
			if(!sel)  	//选择饮料是1.5元还是2元
				begin next_state = s0; end		
			else begin 
				if(d1) 		next_state = s4;
				else if(d2) next_state = s5;
				else 		next_state = next_state;
			end
			end
		s4:	begin	
			if(!sel) 
				begin next_state = s0; end		
			else begin 
				if(d1) 		next_state = s5;
				else if(d2) next_state = s6;
				else 		next_state = next_state;
			end
			end		   
		s5:	begin next_state = s0; end
		s6:	begin next_state = s0; end	
		default: begin next_state = s0;end
	endcase	   
end
	
/********* 第三段 状态输出 moore FSM ************/

//出货标志
always @(posedge clk or negedge rst)begin	
	if(!rst)begin
		out1 <= 0;
		out2 <= 0;
	end	
	else if(sel==0 && (next_state == s3 || next_state == s4) )
		out1 <= 1;	//饮料1 
	else if(sel==1 && (next_state == s5 || next_state == s6) )
		out2 <= 1;	//饮料2 	
	else begin
		out1 <= 0;
		out2 <= 0;
	end		
end

//找零数量
always @(posedge clk or negedge rst)begin 
	if(!rst)
		out3 <= 0;	
	else if(sel==0 && (next_state == s4) )
		out3 <= 2'd1;	//饮料1 
	else if(sel==1 && (next_state == s6) )
		out3 <= 2'd1;	//饮料2 					
	else
		out3 <= 2'b0;	
end

//*************code***********//
endmodule

仿真文件

仿真图如下:

3、状态机基本知识

 


以上是mealy和moore型状态机的实现区别,注意在代码里理解!

猜你喜欢

转载自blog.csdn.net/qq_40528849/article/details/128446578
今日推荐