verilog 实现自动售卖机

题目如下所示:
请设计状态机电路,实现自动售卖机功能,A饮料5元钱,B饮料10元钱,售卖机可接收投币5元钱和10元钱,每次投币只可买一种饮料,考虑找零的情况。

电路的接口如下图所示。sel信号会先于din信号有效,且在购买一种饮料时值不变。

sel为选择信号,用来选择购买饮料的种类,sel=0,表示购买A饮料,sel=1,表示购买B饮料;
din表示投币输入,din=0表示未投币,din=1表示投币5元,din=2表示投币10元,不会出现din=3的情况;
drinks_out表示饮料输出,drinks_out=0表示没有饮料输出,drinks_out=1表示输出A饮料,drinks_out=2表示输出B饮料,不出现drinks_out =3的情况,输出有效仅保持一个时钟周期;
change_out表示找零输出,change_out=0表示没有找零,change_out=1表示找零5元,输出有效仅保持一个时钟周期。
接口电路图如下
在这里插入图片描述
程序编写:
module sale(
input clk,
input rst_n,
input sel, //sel = 0 A drinks
//sel = 1 B drinks
input [1:0] din, // din = 0 no money
// din = 1 5r
// din = 2 10r
output reg [1:0] drinks_out, //drinks_out = 0 no drinks output
// drinks_out = 1 out A drinks
// drinks_out = 2 out B drinks
output reg change_out // change_out = 0 no change
// change_out =1 chang 5r
);
parameter IDLE = 'd0;
parameter S0 = 'd1; //此状态为饮料B 但第一次只投了五元钱

reg [1:0]cur_state;
reg [1:0]next_state;

always@(posedge clk or negedge rst_n)
begin
if(rst_n == 'd0)
begin
cur_state <= IDLE;
next_state <= 'd0;
end
else
cur_state <= next_state;
end

always@(*)
begin
	case(cur_state)
		IDLE : next_state = sel?(din==1 ? S0 : IDLE):IDLE;  //sel=1 即选择B饮料,判断第一次投入的是五元钱还是10元钱,若投的是五元钱则进入状态S0,等待第二次投钱
		S0 : next_state = (din == 0) ? S0 : IDLE;
		default: next_state = IDLE;
	
	endcase
	
end
always@(posedge clk or negedge rst_n)
begin
	if(rst_n == 'd0)
	drinks_out <= 'd0;
	else if(sel == 'd0)
	begin
		if((cur_state==IDLE&&din==1)||(cur_state ==IDLE&&din==2))
		drinks_out <= 'd1;
		else
		drinks_out <= 'd0;
	end
	else if(sel == 'd1)
	begin
		if((cur_state == IDLE&&din=='d2)||(cur_state ==S0&&din=='d1)||(cur_state ==S0&&din=='d2)) 
		drinks_out <= 'd2;
		else
		drinks_out <= 'd0;
	end
end

always@(posedge clk or negedge rst_n) //这里涉及到第一次投入的是五元钱第二次投入五元钱还是十元钱的情况,第二次投入五元则不找零,投入十元则找零
begin
	if(rst_n =='d0)
	change_out <= 'd0;
	else if(sel =='d0)
	begin
		if(cur_state ==IDLE&&din=='d2)
		change_out <= 'd1;
		else
		change_out <= 'd0;
	end
	else if(sel =='d1)
	begin
		if(cur_state == S0&&din=='d2)
		change_out <= 'd1;
		else
		change_out <= 'd0;
	end
end

endmodule

-------------------------------------------------------——————————————————————————————————
编写testbench测试:

module sale_tb;

reg clk;
reg rst_n;
reg sel;
reg [1:0] din;

wire [1:0]drinks_out;
wire change_out;

initial begin
clk = 0;
forever #5 clk = ~clk;
end

initial begin
rst_n = 0;
sel = 0;
din = 0;
#100
rst_n = 1;
#10
sel = 0;
#10
din = 1;
#10
sel =1;
#10
din =2;
#10
sel =1;
#10
din=1;
#10
din =2;
#10
sel =0;
#10
din =2;
#10
din= 0;
#100

$finish;

end
sale sale_m0(
.clk(clk),
.rst_n(rst_n),
.sel(sel), //sel = 0 A drinks
//sel = 1 B drinks
.din(din), // din = 0 no money
// din = 1 5r
// din = 2 10r
.drinks_out(drinks_out), //drinks_out = 0 no drinks output
// drinks_out = 1 out A drinks
// drinks_out = 2 out B drinks
.change_out(change_out) // change_out = 0 no change
// change_out =1 chang 5r
);

endmodule

仿真结果:
在这里插入图片描述

代码下载(包含testbench):
https://download.csdn.net/download/weixin_44413306/85844663

  • 25
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值