1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 自动售货机控制模块-Verilog HDL

自动售货机控制模块-Verilog HDL

时间:2020-08-12 04:28:39

相关推荐

自动售货机控制模块-Verilog HDL

一、问题描述

设计一个自动售货机控制模块,信息如下:

1. 售货机可提供8种可售商品,其中01号商品(代表第一种商品),价格为2元,02商品为4元,依次类推,08号商品售价为16元。

2. 售货机可接受1元,5元和10元的纸币收入。

3. 交易开始,用户需要先投入一定量的货币;在外部货币投入后,售货机累计输入货币总值;完成投币后,用户选择所有需要的商品;选择结束后,按下交易键;交易成功,售货机出货、找零,更新系统的存量货币信息和货物信息;交易不成功,退回用户投入货币。

4. 交易不成功可能可能因为投币不足;货物不足;零钱不足等原因造成;

5. 管理员可以通过外部设备访问和修改可售商品信息和存量货币信息。

二、功能概括

自动售货机刚初始化时,需要管理员对其剩余钱数和商品数进行管理,之后用户可以进行商品购买。用户首先选择商品,无误后对商品进行确认,否则取消,在用户选择了某种商品后,售货机会对其存货进行确认,如果该商品已经售罄,则交易失败,回到空闲状态。该商品有存货时,售货机延时一段时间(30S)留给用户进行投币,用户只能投入1,5,10元的钱币,否则售货机会将其退出。用户在延时内投币后,售货机进行找零计算,如果售货机内现金不足找零,则退出所有钱币,售货机进入管理员管理状态,此时需要管理员管理现金。正确情况下,零钱足够多,则正常找零,如果找零数额为0直接出货,找零数不为0则是先找零再出货。出于实际情况的考虑,我认为自动售货机更适合使用先选择产品,再投入钱币的方式更为合理,因此在设计时使用的是先选择确认,再延时投币的流程。自动售货机的整个管理和售货流程如下图所示:

图1 自动售货机工作流程图

三、接口定义

表1 系统接口与描述表

四、电路设计

系统设计:

根据题目要求,本项目关注点在于自动售货机控制的模块,因此对于一些软件、机械、电气方面的错误无法进行处理,如退钱时卡纸,突然停电等。出于集成化的考虑,采用了3个always块,always39为初始化状态模块,即将state的状态初始化为S_idle(可综合的Verilog不能使用initial进行初始化),always39为计时模块,在选定商品后,必须在规定的时间内投币。always63为自动售货机控制管理模块,是本设计主要电路。自动售货机控制模块的整体功能概括如下:

图2 自动售货机控制模块功能概括

数据通路:

考虑测试输入输出模块,数据流图和控制流图如下图所示,其中蓝线为数据线,红线为控制线。

图3 自动售货机控制模块数据通路

状态机:

自动售货机定义了10种状态,分别是选择(S_select),确认(S_confirm),是否售罄(S_allselled),延时(S_60s),投币是否足够(S_enough),是否需要找零(S_requirechange),找零(S_change),出货(S_out),空闲(S_idle),管理(S_management)。状态机如下图所示。

图4自动售货机控制模块状态机

时序设计:

首先要将售货机初始化,然后管理员进行第一次管理,在管理员管理阶段,需要设定各个商品的剩余数量,以及售货机里用于找零的现金。管理结束后进入用户使用阶段,用户首先选择商品号,在规定的延迟之内完成投币,之后在不缺货和现金的情况下,会进行找零和出货,售货机会更新商品数量和现金信息。如果出现缺货,现金不足,投币超时等情况会进行特殊处理,返回空闲或管理状态。

图5自动售货机控制模块时序图

内部信号定义:

自动售货机控制模块的内部信号主要用于保存信息和中间过程处理,管理员在初始化管理时会输入商品数量以及内部现金余量,这些都需要寄存器进行寄存,在进行正常售货时,因为有找零和出货,内部的信息也在不断的更新。

表2 内部信号描述表

//.1.5 葛兴//全定制电路课程课程设计//Verilog自动售货机控制模块//Vending Machinemodule VendingMac(clk,money_input,select,confirm,init,left01,left02,left03,left04,left05,left06,left07,left08,change,out,manage,manage_money,rst);input clk;//时钟信号input rst;//使能信号input confirm,init;//?idle=initinput [3:0] money_input;//1,5,10,最大为1010,4位input [1:8] select;//8种商品,选择上升沿触发input [9:0] manage_money;//输入的钱数input [5:0] left01,left02,left03,left04,left05,left06,left07,left08;//剩余商品数,认为不超过63input [1:0] manage;//这个是管理员功能 reg [9:0] cash;//自动售货机内部的钱数reg [3:0] state;//状态机的各种状态reg [5:0] left1,left2,left3,left4,left5,left6,left7,left8;output integer change;//找零,整数output reg [1:8] out;//出货,8种商品之一reg [1:8] select_sta;//选择某种商品reg isSelled;//判断是否售罄reg timeCnting;//延时计时S_enough=4'b0100,S_requirechange=4'b0101,S_change=4'b0110,S_out=4'b0111,reg [8:0] time_cnt;//500个时间单位,2^9=512reg [1:0] opt;//检查init是否启用integer money_sum;//剩余总钱数parameter S_select=4'b0000,S_confirm=4'b0001,S_allselled=4'b0010,S_60s=4'b0011,S_idle=4'b1000,S_management=4'b1001;//9种state的编号start==4b'0000/* initialbeginstate=S_idle;//所以应该在输入中输入?还是直接在45行那儿初始化?end */always@(posedge clk or posedge rst)beginif(rst)beginstate <= S_idle;endend/* always @(posedge clk)beginif (start==4b'1000)state=S_idle;end */select_sta=8'b00000000;always @(posedge clk)beginif(clk && timeCnting)//根据clk上跳延计时time_cnt=time_cnt+1;if(timeCnting==0)time_cnt=0;endalways @(posedge init or posedge clk or manage)beginif(clk)begincase(state)S_idle://初始化状态begintimeCnting=0;left2 = left02;money_sum=0;change=0;out=0;opt=0;if(manage==1)state=S_management;else beginstate=S_select;endendS_management://管理员可以通过外部设备访问和修改可售商品信息和存量货币信息beginleft1 = left01;left3 = left03;if(confirm||init)//确认和初始化居其一(到下一步可以取消交易)left4 = left04;left5 = left05;left6 = left06;left7 = left07;left8 = left08;cash = manage_money;////manage=0;state=S_idle;endS_select://选择某种商品beginselect_sta=select|select_sta;//按位或,应对选择和商品;begin S_allselled://判断是否售罄opt={confirm,init};state=S_confirm;endendS_confirm:beginif(opt==2'b10)state=S_allselled;//也就是说当confirm=1时,进入判判断货物状态?那init是做什么用的?else if(opt==2'b00||2'b01||2'b11)beginstate=S_idle;endendbeginif(select_sta[6]==1 && left6<=0)isSelled=0;//判断选择的商品是否售罄if(select_sta[1]==1 && left1<=0)isSelled=1;if(select_sta[2]==1 && left2<=0)isSelled=1;if(select_sta[3]==1 && left3<=0)isSelled=1;if(select_sta[4]==1 && left4<=0)isSelled=1;if(select_sta[5]==1 && left5<=0)isSelled=1;timeCnting=1;//有商品则进入到计时付款阶段isSelled=1;if(select_sta[7]==1 && left7<=0)isSelled=1;if(select_sta[8]==1 && left8<=0)isSelled=1;if(cash < 16)state=S_management;//没有足够零钱则进入管理员状态else if(isSelled)beginstate=S_idle;//没有商品,回到空闲状态endelsebeginstate=S_60s;endstate=S_idle;endS_60s:beginif(time_cnt<25)beginif(money_input!=0)begin//只接收1,5,10元if(money_input==1||money_input==5||money_input==10||money_input==0)//检查是否为1,5,10元,不是则退钱并回到空闲状态//添加0是因为可能有连续的钱无法区分,实际上是投币间隔money_sum = money_sum + money_input;else if(select_sta[3]==1)endendelse if(time_cnt==25)if(money_sum!=0)state=S_enough;//在计时结束后有钱放入elsestate=S_idle;endS_enough:begin//其中01号商品价格为2元,02商品为4元,依次类推,08号商品售价为16元。if(select_sta[1]==1)money_sum=money_sum-2;if(select_sta[2]==1)money_sum=money_sum-4;state=S_requirechange;//余额大于等于零,判断是否需要找钱money_sum=money_sum-6;if(select_sta[4]==1)money_sum=money_sum-8;if(select_sta[5]==1)money_sum=money_sum-10;if(select_sta[6]==1)money_sum=money_sum-12;if(select_sta[7]==1)money_sum=money_sum-14;if(select_sta[8]==1)money_sum=money_sum-16;if(money_sum>=0)S_out:else//找零余额不够,退出所有钱,并进入管理状态state=S_management;endS_requirechange:beginif(money_sum==0)//余额为零,不用找零,直接出货state=S_out;else if(money_sum>0)//余额不为零,进入找零模式state=S_change;endS_change:beginchange = money_sum;//将余额找零cash = cash - money_sum;//减去找零state = S_out;endif(select_sta[8]==1)begin//对应的货物减1if(select_sta[1]==1)left1=left1-1;if(select_sta[2]==1)left2=left2-1;if(select_sta[3]==1)left3=left3-1;if(select_sta[4]==1)left4=left4-1;if(select_sta[5]==1)left5=left5-1;if(select_sta[6]==1)left6=left6-1;if(select_sta[7]==1)left7=left7-1;left8=left8-1;out=select_sta;//出货state=S_idle;//进入空闲状态endendcaseendendendmodule

`timescale 1ns/1ns`include "./vending_machine_gx.v"module VendingMac_top;reg clk;reg rst;//复位reg manage;//管理员管理信号reg [9:0] manage_money;//管理售货机内现金reg [3:0] money_input;//用户输入钱reg [7:0] select;reg confirm,init;//确认取消reg [5:0] left01,left02,left03,left04,left05,left06,left07,left08;//剩余商品数,认为不超过63wire integer change;//找零wire [7:0] out;//出货initialbeginclk=0;select=8'b00000000;//初始并没有选择任何商品confirm=0;init=0;money_input=0;manage=0;endalwaysbegin#5 clk=~clk;//产生时钟#5 clk=~clk;endinitialbegin#10 rst = 1;//进行初始化,使售货机初始状态为S_idle#10 rst = 0;#10manage=1;#10left01=63;//每种商品的数量left02=62;left03=61;left04=60;left05=59;left06=58;left07=57;left08=56;manage_money=1000;//开始售货机里放1000元#10 manage=0;//管理结束#30#10 select=8'b00000010;//posedge1#10 select=8'b00000000;#10 confirm=1;//确认购买#10 confirm=0;#50 money_input=10;//投币10元#10 money_input=0;//投币间隔#10 money_input=5;#10 money_input=0;#10 money_input=1;#10 money_input=0;endinitialbegin$monitor($time,,,"select=%b,money_input=%d,confirm=%d,init=%d,out=%b,change=%d",select,money_input,confirm,init,out,change);#60000 $finish;endVendingMac v1(clk,money_input,select,confirm,init,left01,left02,left03,left04,left05,left06,left07,left08,change,out,manage,manage_money,rst);endmodule

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。