Verilog:设计饮料自动投币售卖机的核心控制电路

要求:简化考虑,假设饮料只有一种价格为2.5元。硬币有0.5元和1.0元两种,考虑找零。

Design Spec:

  • 输入信号:clk、rst
  • 输入信号:操作开始:op_start; //定义为1时开始执行操作,只影响初始状态,对后续状态没有影响。
  • 输入信号:投币币值:coin_val; //2‘b01时为0.5元,2‘b10时为1元。
  • 输入信号:取消操作:cancel_flag; //定义为1时取消操作。
  • 输出信号:机器是否占用:hold_in; //定义0为不占用,1为占用。
  • 输出信号:取饮料信号:drinktk_ind; //定义1为取走
  • 输出信号:找零退币信号:charge_val; //定义3‘b001为0.5元,3‘b010为1元,3’b011为1.5元,3‘b100为2元,3’b101为2.5元,3‘b110为3元。

状态转移图:

Verilog 代码:

RTL:

module AutoDrinkFSM(
	input	clk,
	input	rst,
	input	op_start,
	input	[1:0]	coin_val,
	input	cancel_flag,
	output	hold_in,
	output	reg drinktk_ind,
	output	reg [2:0] charge_val
);

	reg	[2:0]	state, next_state;
	
	parameter S0 = 3'b000, S1 = 3'b001;
	parameter S2 = 3'b010, S3 = 3'b011;
	parameter S4 = 3'b100, S5 = 3'b101;
	parameter S6 = 3'b110;
	
	always@(posedge clk) begin
		if(rst) begin
			state <= S0;
		end
		else begin
			state <= next_state;
		end
	end 
	
	always@(*) begin
		case(state)
			S0:	begin
				if(op_start) begin
					if(coin_val == 2'b01) begin
						next_state = S1;
					end
					else if(coin_val == 2'b10) begin
						next_state = S2;
					end
					else next_state = S0;
				end
				else begin
					next_state = S0;
				end
			end
			S1:	begin
				if(cancel_flag) begin
					next_state = S0;
				end
				else begin
					if(coin_val == 2'b01) begin
						next_state = S2;
					end
					else if(coin_val == 2'b10) begin
						next_state = S3;
					end
					else next_state = S1;
				end
			end
			S2:	begin
				if(cancel_flag) begin
					next_state = S0;
				end
				else begin
					if(coin_val == 2'b01) begin
						next_state = S3;
					end
					else if(coin_val == 2'b10) begin
						next_state = S4;
					end
					else next_state = S2;
				end
			end
			S3:	begin
				if(cancel_flag) begin
					next_state = S0;
				end
				else begin
					if(coin_val == 2'b01) begin
						next_state = S4;
					end
					else if(coin_val == 2'b10) begin
						next_state = S5;
					end
					else next_state = S3;
				end
			end
			S4:	begin
				if(cancel_flag) begin
					next_state = S0;
				end
				else begin
					if(coin_val == 2'b01) begin
						next_state = S5;
					end
					else if(coin_val == 2'b10) begin
						next_state = S6;
					end
					else next_state = S4;
				end
			end
			
			S5:	next_state = S0;
			S6: next_state = S0;
		endcase
	end
	
	assign hold_in = (state == S0)?1'b0:1'b1;
	
	always@(*) begin
		if(state == S5 || state == S6) begin
			if(cancel_flag) begin
				drinktk_ind = 1'b0;
			end
			else begin
				drinktk_ind = 1'b1;
			end
		end
		else begin
			drinktk_ind = 1'b0;
		end
	end
	
	always@(*) begin
		if(cancel_flag) begin
			case(state)
				S1:	charge_val = S1;
				S2:	charge_val = S2;
				S3:	charge_val = S3;
				S4:	charge_val = S4;
				S5:	charge_val = S5;
				S6:	charge_val = S6;
				default: charge_val = S0;
			endcase
		end
		else begin
			charge_val = S0;
		end
	end

endmodule

TB:

module AutoDrinkFSM_tb;

	reg		clk;
	reg 	rst;
	reg 	op_start;
	reg 	[1:0] coin_val;
	reg 	cancel_flag;
	wire	hold_in;
	wire	drinktk_ind;
	wire	reg [2:0]	charge_val;
	
	AutoDrinkFSM u_AutoDrinkFSM(
		.clk(clk),
		.rst(rst),
		.op_start(op_start),
		.coin_val(coin_val),
		.cancel_flag(cancel_flag),
		.hold_in(hold_in),
		.drinktk_ind(drinktk_ind),
		.charge_val(charge_val)
	);
	
	initial begin
		clk = 0;
		rst = 1;
		op_start = 0;
		coin_val = 2'b01;
		cancel_flag = 0;
		#30 rst = 0;
	end
	
	always #10 clk = ~clk;
	
	always@(posedge clk) begin
		if(({$random()}%3)<1) begin
			op_start = 1'b1;
		end
		else begin
			op_start = 1'b0;
		end
		
		if(({$random()}%4)<1) begin
			coin_val = 2'b01;
		end
		else if(({$random()}%4)<1) begin
			coin_val = 2'b10;
		end
		else begin
			coin_val = 2'b00;
		end
		
		if(({$random()}%10)<1) begin
			cancel_flag = 1;
		end
		else begin
			cancel_flag = 0;
		end
	end
	
	initial begin
		#20000 $finish;
	end
	
endmodule

波形:

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王bf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值