Verilog 实现状态机自动售卖机

Verilog 实现状态机自动售卖机

教学视频:https://www.bilibili.com/video/BV1Ve411x75W?p=33&spm_id_from=pageDriver&vd_source=19ae31dff4056e52d2729a4ca212602b

功能需求

使用1元、2元、5元面值的纸币进行支付,获取6元的物品,不设找零

  • 输入:1元,2元,5元
  • 判定条件:>=6元
  • 输出:可以交货(输入额满足判断条件)

代码思路:使用状态机进行逻辑设计(详细教学可以看最上面的链接)

verilog 复制代码
module vlg_design(
	input 		clk			,
	input 		rst_n		,
	input 		one_yuan	,
	input		two_yuan	,
	input 		five_yuan	,
	
	output 	reg done
);

//变量声明
localparam 	IDLE	=4'd0 ,
			IN_1 	=4'd1 ,
			IN_2 	=4'd2 ,
			IN_3 	=4'd3 ,
			IN_4 	=4'd4 ,
			IN_5 	=4'd5 ,
			IN_6 	=4'd6 ,
			DONE 	=4'd7 ;
			
localparam	MONEY_PAY = 4'd6;

reg [3:0] cstate,nstate;
reg [3:0] money_sum;

//时序逻辑,锁存状态
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		cstate <= IDLE;
	else
		cstate <= nstate;
end

//组合逻辑实现状态变迁
always @(*) begin
	case(cstate)
		IDLE : begin
			if(one_yuan||two_yuan||five_yuan)
				nstate = IN_1;
			else
				nstate = IDLE;
		end
		IN_1 : begin
			if(one_yuan||two_yuan||five_yuan)
				nstate = IN_2;
			else
				nstate = IN_1;
		end		
		IN_2 : begin
			if(money_sum >= MONEY_PAY)
				nstate = DONE;
			else if(one_yuan||two_yuan||five_yuan)
				nstate = IN_3;
			else
				nstate = IN_2;
		end	
		IN_3 : begin
			if(money_sum >= MONEY_PAY)
				nstate = DONE;
			else if(one_yuan||two_yuan||five_yuan)
				nstate = IN_4;
			else
				nstate = IN_3;
		end	
		IN_4 : begin
			if(money_sum >= MONEY_PAY)
				nstate = DONE;
			else if(one_yuan||two_yuan||five_yuan)
				nstate = IN_5;
			else
				nstate = IN_4;
		end	
		IN_5 : begin
			if(money_sum >= MONEY_PAY)
				nstate = DONE;
			else if(one_yuan||two_yuan||five_yuan)
				nstate = IN_6;
			else
				nstate = IN_5;
		end	
		IN_6 : begin
			if(money_sum >= MONEY_PAY)
				nstate = DONE;
			else if(one_yuan||two_yuan||five_yuan)
				nstate = DONE;
			else
				nstate = IN_6;
		end	
		DONE : nstate = IDLE;
		
		default : ;
	endcase
end

//当前状态输入钱币的累计计算
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		money_sum <= 'b0;
	else begin
		case(cstate)
			DONE : money_sum <= 'b0;
			default : begin
				if(one_yuan)
					money_sum <= money_sum + 4'd1;
				else if(two_yuan)                 
					money_sum <= money_sum + 4'd2;
				else if(five_yuan)                
					money_sum <= money_sum + 4'd5;
				else ;
			end
		endcase
	end
end

//状态机的输出赋值
always @(posedge clk or negedge rst_n) begin
	if(!rst_n)
		done <= 'b0;
	else if(cstate == DONE)
		done <= 1'b1;
	else
		done <= 'b0;
end

endmodule

测试文件:

verilog 复制代码
`timescale 1ns/1ps

module tb_top();


reg clk;
reg rst_n;
reg one_yuan;
reg two_yuan;
reg five_yuan;

wire done;


vlg_design u_vlg_design(
	.clk		(clk),
	.rst_n		(rst_n),
	.one_yuan	(one_yuan),
	.two_yuan	(two_yuan),
	.five_yuan	(five_yuan),

	.done       (done)
);

//产生时钟
initial clk = 1;
always #10 clk = ~clk;

integer i;

//测试激励产生
initial begin
	rst_n = 0;
	one_yuan	=0 ;
	two_yuan	=0 ;
	five_yuan	=0 ;
	#200;
	rst_n = 1;
	
	for(i=0;i<50;i=i+1)begin
		task_random_pay();
	end
	#5000;
	
end

integer random_data;

task task_random_pay;
	begin 
		#1000;
		random_data = {$random}%3;
		@(posedge clk);
		if(random_data == 0)
			one_yuan <= 1'd1;
		else if(random_data == 1)
			two_yuan <= 1'd1;
		else if(random_data == 2)
			five_yuan <= 1'd1;
		@(posedge clk);
			one_yuan	<=0 ;
			two_yuan	<=0 ;
			five_yuan	<=0 ;
	end
endtask

always @(posedge clk) begin
	if(one_yuan)
		$display("Pay 1 yuan.");
	else if(two_yuan)
		$display("Pay 2 yuan.");
	else if(five_yuan)
		$display("Pay 5 yuan.");
	else if(done)
		$display("Got you want.\n*********\n");
	else ;
end

endmodule

仿真结果

波形:

结果:

相关推荐
茯苓gao2 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾2 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
DKPT3 小时前
Java内存区域与内存溢出
java·开发语言·jvm·笔记·学习
aaaweiaaaaaa3 小时前
HTML和CSS学习
前端·css·学习·html
看海天一色听风起雨落4 小时前
Python学习之装饰器
开发语言·python·学习
speop5 小时前
llm的一点学习笔记
笔记·学习
非凡ghost5 小时前
FxSound:提升音频体验,让音乐更动听
前端·学习·音视频·生活·软件需求
ue星空6 小时前
月2期学习笔记
学习·游戏·ue5
萧邀人6 小时前
第二课、熟悉Cocos Creator 编辑器界面
学习
m0_571372827 小时前
嵌入式ARM架构学习2——汇编
arm开发·学习