Verilog实现的找零钱系统

又懒得写了,激励文件补了,写的好乱,唐完了,有大佬有见解的话请斧正,

module vending #(
	parameter REST = 2'b00,						//待机
	parameter GET = 2'b01,						//收钱
	parameter RETURN = 2'b10					//找零
	)(						
	input					CLK,						//外部时钟
	input					RSTN,						//复位,低位为复位请求
	input					GET_END,					//表示位被挂起时,表示没有其他的钱币了
	input [7:0]			MONEY,					//目标金额,在收钱时用于输入主机识别的钱币金额,8'h01是1块,8'h02是5块,8'h04是10块,其他的不识别
	output reg [2:0]	CHANGE,					//找零输出
	output reg 			SHELL);					//结束请求,告诉主机,找零流程完成
	
	reg [1:0]			state;
	reg [7:0]			target;
	reg [7:0]			total;
	
	
	initial begin									//初始化
		state = 2'b00;
		total = 8'h00;
		target = 8'h00;
		CHANGE = 'bz;
		SHELL = 1'b1;
	end
	
	
	always @(posedge CLK or negedge RSTN) begin
		if (!RSTN) begin							//复位,不过可能有丢失投入金钱的可能,懒得修了
        state <= REST;
        total <= 8'h00;
        target <= 8'h00;
        CHANGE <= 'bz;
        SHELL <= 1'b1;
		end
		else begin
		case(state)
			REST : begin							//待机状态
				
				if(MONEY != 0) begin
					target <= MONEY;
					state <= GET;
					SHELL <= 1'b0;
				end else SHELL <= 1'b1;
			end
				GET : begin							//收钱状态
					case(MONEY)
						8'h01 : total = total + 1;
						8'h02 : total = total + 5;
						8'h04 : total = total + 10;
						default: ;
					endcase
					
					if(GET_END) begin
						state <= RETURN;
						total <= total - target;
					end
				end
				RETURN : begin						//吐钱状态,每次吐前检验钱的数量,为零则结算,并重置变量
					if(total >= 8'h0a) begin
						total <= total - 10;
						CHANGE <= 3'b100;
					end
					else if(total >= 8'h05) begin
						total <= total - 5;
						CHANGE <= 3'b010;
					end
					else if(total > 0) begin
						total <= total - 1;
						CHANGE <= 3'b001;
					end
					else if(!total) begin
						CHANGE <= 'bz;
						total <= 0;
						target <= 0;
						SHELL <= 1'b1;
						state <= REST;
					end
					
				end
			endcase
		end
	end
endmodule					

下面是激励和仿真图 

`timescale 1 ns/ 1 ns
module test;
	reg clk;
	reg  rstn;
	reg get_end;
	reg [7:0] money;
	wire [2:0] change;
	wire shell;
	
	
	reg [7:0] money_reg [3:0] ;		//模拟主机向模块发送目标金额
	reg [7:0] coin [3:0] [3:0];		//模拟主机向模块逐个发送硬币面额
	
	integer i,j;							//两个数组下标
	
	
	initial begin
		forever begin						//标准时钟
			clk = 1;
			#10;
			clk = 0;
			#10;
		end
	end
	
	initial begin
		i=0;											//一些数据的初始化
		j=0;
		money <= 8'h00;
		rstn <= 1;
		get_end <= 0;
		money_reg[0] <= 2;
		money_reg[1] <= 4;
		money_reg[2] <= 7;
		money_reg[3] <= 11;
		coin[0][0] <= 8'h01;
		coin[0][1] <= 8'h02;
		coin[0][2] <= 8'h00;
		coin[1][0] <= 8'h01;
		coin[1][1] <= 8'h04;
		coin[1][2] <= 8'h00;
		coin[2][0] <= 8'h01;
		coin[2][1] <= 8'h02;
		coin[2][2] <= 8'h04;
		coin[2][3] <= 8'h00;
		coin[3][0] <= 8'h01;
		coin[3][1] <= 8'h02;
		coin[3][2] <= 8'h02;
		coin[3][3] <= 8'h00;
	end
	
	always @(negedge clk)begin
		if(i<4) begin
			if(shell) begin								//模块是否在空闲,是则发送目标金额,同时开启硬币接收
				money <= money_reg[i];
				
				get_end <=0;
			end 
			else if(!get_end) begin						//模块不空闲,且硬币接收状态,当目前硬币为0面额,则关闭硬币接收
				money <= coin[i][j];
				if(!coin[i][j]) begin
					j <=0;
					get_end <= 1;
					i <=i+1;
				end else begin
					
					j <= j+1;
				end
			end
		end
	end
	
	vending 		My_vending(								
		.CLK(clk),
		.RSTN(rstn),
		.GET_END(get_end),
		.MONEY(money),
		.CHANGE(change),
		.SHELL(shell));
	
	initial begin
		forever begin
			#100;
			if($time >= 1000) $finish;
		end
	end
	
endmodule

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值