【附源码】基于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)beginif(!rst)curr_state <= s0;elsecurr_state <= next_state;end//第二段 转移状况
always @(*)begincase(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?ends1:begin	if(d1) 		next_state = s2;else if(d2) next_state = s4;else if(d3) next_state = s5;else 		next_state = next_state;ends2:begin	if(d1) 		next_state = s4;else if(d2) next_state = s3;else if(d3) next_state = s6;else 		next_state = next_state;ends3,s4,s5,s6:begin next_state = s0;end	default: begin next_state = s0;endendcase	   
end//第三段 状态输出 moore FSMalways @(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;	//出货标志elseout1 <= 0;	endalways @(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;				elseout2 <= 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 beginclk = 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)beginif(!rst)curr_state <= s0;elsecurr_state <= next_state;end//第二段 转移状况
always @(*)begincase(curr_state)s0:	beginif(d1) 		next_state = s1;else if(d2) next_state = s2;else 		next_state = next_state;	ends1:	begin	if(d1) 		next_state = s2;else if(d2) next_state = s3;else 		next_state = next_state;	ends2:	beginif(d1) 		next_state = s3;else if(d2) next_state = s4;else 		next_state = next_state;	ends3:	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;endends4:	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;endend		   s5:	begin next_state = s0; ends6:	begin next_state = s0; end	default: begin next_state = s0;endendcase	   
end/********* 第三段 状态输出 moore FSM ************///出货标志
always @(posedge clk or negedge rst)begin	if(!rst)beginout1 <= 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 beginout1 <= 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 					elseout3 <= 2'b0;	
end//*************code***********//
endmodule

仿真文件

仿真图如下:

3、状态机基本知识

 


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


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部