数字电路自动售货机实验报告.docx
《数字电路自动售货机实验报告.docx》由会员分享,可在线阅读,更多相关《数字电路自动售货机实验报告.docx(25页珍藏版)》请在冰豆网上搜索。
数字电路自动售货机实验报告
数字电路综合实验
题目:
简易自动售货机
学院:
信息与通信工程学院
姓名:
班级:
学号:
班内序号:
1.设计课题的任务要求
设计一个简易的自动售货机,能够完成钱数处理、找零、显示、退币等功能。
基本要求:
1.用2个数码管(disp5,disp4)显示钱数,以元为单位。
用3个按键(btn0,btn1,btn2)分别表示一元、五元、十元,每按一次按键,增加一次相应的钱数,上限99元。
2.再用3个按键(btn3,btn4,btn5)分别对应3种商品,其中,商品甲售价3元、商品乙售价8元、商品丙售价12元;
3.买东西时,先输入钱币,再按对应的商品键。
每按一次商品键,钱数要相应地减少,同时有声光(蜂鸣器或发光二极管)提示购买成功。
剩余钱数大于3元可继续按商品键再次购买;当剩余钱数少于3元时,表示钱数的数码管disp5,disp4显示为零,同时用数码管disp0显示退出的钱数。
4.买东西时,按下商品键,若输入的钱数少于商品的价格,表示钱数的数码管disp5,disp4显示为零,同时用数码管(disp1、disp0)显示退出的钱数,并用蜂鸣器或发光二极管闪烁表示购买失败。
5.按下商品键时,用数码管disp2表示当前购买的商品,1代表商品甲,2代表商品乙,3代表商品丙。
6.用btn7做为退出功能键,退出键可以随时按下,按下后,数码管(disp5,disp4)显示为零,同时数码管(disp1、disp0)显示退出的钱数,表示结束购买,钱款全部退出。
提高要求:
允许随时输入钱币,购买时,钱款不足有声光报警并等待追加钱币或选择别的商品。
自拟功能:
用点阵显示投入钱币的面值以及交易成功、失败的提示符。
2.系统设计(包括设计思路、总体框图、分块设计)
2.1设计思路
在设计系统时,我采用了自顶向下(top-down)设计法。
从自动售货机所要完成的功能出发,将整个系统划分成若干子系统:
分频器(clkgen)、防抖单元(keyin)、控制器(automat)、译码显示器(decodingdisplay)(用数码管显示)以及点阵显示单元(dot_matrix)。
分频器(clkgen)将50MHz的时钟频率分成100Hz,提供给防抖单元(keyin)及控制器(automat);由于按键的时刻和按下的时间长短是随机的,并且存在由开关簧片反弹导致的电平抖动,因此必须设计电路消除抖动,此功能由防抖单元(keyin)实现;控制器(automat)负责总额、找零的计算,以及判断交易是否成功;译码显示器(decodingdisplay)和点阵显示单元(dot_matrix)则分别用来控制数码管和点阵的显示。
2.2设计图
⏹
逻辑流程图(ASM图)
图1ASM图
⏹方框图
图2方框图
⏹
MDS图
图3MDS图
2.3分块设计
2.3.1分频器设计
图4clkgensymbol
分频器的原理是对输入的脉冲进行计数,计数的模值对应分频系数。
本实验设置分频系数为50万,占空比为50%,及将50MHz的时钟频率分成100Hz。
2.3.2防抖单元设计
图5keyinsymbol
采用计数器型消抖电路,设置一个模值为(N+1)的控制计数器,当按键持续时间大于N个时钟周期时,计数器输出一个单脉冲。
一般抖动产生的毛刺宽度小于N个时钟周期,则计数器无输出,防抖功能得以实现。
2.3.3控制器设计
图6automatsymbol
控制器内部采用BCD码的加减法,根据输入的投币面值、商品号及退出信号,计算出总额、找零,判断交易是否成功,以输出给下一级的显示模块。
2.3.4译码显示器设计
图7decodingdisplaysymbol
译码显示器将输入的BCD码装换成共阴极数码管0-9时各段对应的编码,对5个数码管进行连续快速扫描,以同时显示输入BCD码对应的数字。
2.3.5点阵显示单元设计
图8dot_matrixsymbol
点阵显示单元采用行扫描循环出0的方式,频率采用1KHz,保证点的亮度一致且足够高。
行为0时表示该行被选中,列为1时表示该列被选中。
图9顶层实体连接图
3.仿真波形及波形分析
3.1分频器(clkgen)
图10分频器仿真波形
分频器波形分析:
此分频器为50万分频,将50MHz分为100Hz,接入控制器(automat)和防抖单元(keyin)。
3.2防抖单元(keyin)
图11防抖单元仿真波形
防抖单元波形分析:
防抖时钟频率设为100Hz,持续时间小于20ms的为不确定按键,每按一次键只产生一个脉冲,脉冲宽度为一个时钟周期。
3.3控制器(automat)
图12控制器仿真波形
控制器波形分析:
图12中总额(amount)与找零(refund)为BCD码显示,商品号(choice)为十进制数显示。
首先投入10元纸币,总额显示“00010000”,之后选择8元商品,总额显示“00000010”,商品号显示“2”,交易成功(success)显示“1”。
又选择了3元商品,商品号显示“1”,由于商品价格大于2元余额,因此交易失败显示“1”。
接着又投入5元纸币,总额显示“00000111”,再选3元商品,总额显示“00000100”,商品号显示“1”,交易成功显示“1”,最后按下退出键(cancel),总额与商品号清零,找零显示“00000100”,整个交易结束。
3.4译码显示器(decodingdisplay)
图13译码显示器仿真波形
译码显示器波形分析:
图13中cat数组代表了数码管disp5-disp0,当cat显示“011111”、“101111”、“110111”、“111011”、“111101”、“111110”时分别表示选择数码管disp5、disp4、disp3、disp2、disp1、disp0,其中disp5、disp4显示总额(amount),disp2显示商品号(choice),disp1、disp0显示找零(refund),disp2不使用。
图13中两个时间轴之间为6个数码管扫描一遍的过程,总额(amount)与找零(refund)用BCD码表示,商品号(choice)用二进制数表示。
此时,输入的总额为“00000101”,商品号为“01”,找零为“00000000”。
则当扫描到数码管disp5、disp4(cat显示“011111”、“101111”)时,led显示“1111110”、“1011011”,对应的数字为“05”;当扫描到数码管disp2(cat显示“111011”)时,led显示“0110000”,对应的数字为“1”;当扫描到数码管disp1、disp0(cat显示“111101”、“111110”)时,led显示“1111110”、“1111110”,对应的数字为“00”。
3.5点阵显示单元(dot_matrix)
图14点阵显示单元器仿真波形
点阵显示单元波形分析:
采用行扫描循环出0的方式,保证点的亮度一致,频率采用1KHz,保证点的亮度足够高。
图14中row[0]-row[7]代表点阵的第1-8行,col[0]-col[7]代表点阵的第1-8列,row为0时表示选中该行,列为1时表示选中该列。
投入10元纸币时,点阵显示“10”(向左旋转
可看出)。
图14中显示的“10”为:
col[0]与col[1]全为1,显示为加粗的“1”。
col[3]与col[7]除第一行与最后一行为0外,其他行都为1,col[4]-col[6]除第一行与最后一行为1外,其他行都为0,即总体显示为数字“0”。
4.源程序(有注释)
4.1分频器源程序:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYclkgenIS--定义分频器实体
PORT(clk:
INSTD_LOGIC;--输入50MHz的时钟信号
newclk:
OUTSTD_LOGIC);--输出100Hz的时钟信号
ENDclkgen;
ARCHITECTUREbehaveOFclkgenIS
SIGNALtmp:
INTEGERRANGE0TO499999;--分频系数为50万
BEGIN
clk100:
PROCESS(clk)
BEGIN
IFclk'eventANDclk='1'THEN
IFtmp=499999THEN
tmp<=0;
ELSE
tmp<=tmp+1;--循环计数,每加到50万便归零
ENDIF;
IFtmp<250000THEN
newclk<='1';
ELSE
newclk<='0';--占空比为50%
ENDIF;
ENDIF;
ENDPROCESSclk100;
ENDbehave;
4.2防抖单元源程序:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYkeyinIS--定义防抖单元实体
PORT(clk:
INSTD_LOGIC;--按键扫描频率为100Hz
key_in:
INSTD_LOGIC;--原始按键信号
key_out:
OUTSTD_LOGIC);--消抖按键信号
ENDkeyin;
ARCHITECTUREbehaveOFkeyinIS
SIGNALcount:
INTEGERRANGE0TO3;
BEGIN
PROCESS(clk)
BEGIN
IF(clk'EVENTANDclk='1')THEN
IF(key_in='1')THEN--计数器型防抖
IFcount=3THENcount<=count;
ELSEcount<=count+1;
ENDIF;
IFcount=2THENkey_out<='1';
ELSEkey_out<='0';--按键持续时间为2个时钟周期才有效
ENDIF;
ELSEcount<=0;key_out<='0';
ENDIF;
ENDIF;
ENDPROCESS;
ENDbehave;
4.3控制器源程序:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYautomatIS
PORT(clk:
INSTD_LOGIC;--100Hz的时钟信号
paper1,paper5,paper10:
INSTD_LOGIC;--投币的面值
select3,select8,select12:
INSTD_LOGIC;--商品的选择
cancel:
INSTD_LOGIC;--退出
success:
OUTSTD_LOGIC;--交易成功
failure:
OUTSTD_LOGIC;--交易失败
amount:
OUTSTD_LOGIC_VECTOR(7DOWNTO0);--总额(BCD码)
choice:
OUTSTD_LOGIC_VECTOR(1DOWNTO0);--商品号(BCD码)
refund:
OUTSTD_LOGIC_VECTOR(7DOWNTO0));--找零(BCD码)
ENDautomat;
ARCHITECTUREbehaveOFautomatIS
SIGNALCOIN:
STD_LOGIC_VECTOR(7DOWNTO0);--保存钱数
SIGNALCOUT:
STD_LOGIC_VECTOR(7DOWNTO0);--保存找零
BEGIN
PROCESS(clk)
BEGIN
IFclk'EVENTANDCLK='1'THEN--全部用BCD加减法
IFpaper1='1'THEN--投入1元
IFCOIN<="10011000"THEN--总额小于等于98元,则加1
IF(COINAND"00001111")="00001001"THENCOIN<=COIN+7;
ELSECOIN<=COIN+1;
ENDIF;
success<='0';failure<='0';
ELSECOIN<=COIN;success<='0';failure<='0';--否则总额不变
ENDIF;
ELSIFpaper5='1'THEN--投入5元
IFCOIN<="10010100"THEN--总额小于等于94元,则加5
IF(COINAND"00001111")>="00000101"THEN
COIN<=COIN+11;
ELSE
COIN<=COIN+5;
ENDIF;
success<='0';failure<='0';
ELSECOIN<=COIN;success<='0';failure<='0';--否则总额不变
ENDIF;
ELSIFpaper10='1'THEN--投入10元,则总额加10
IFCOIN<="10001001"THEN--总额小于等于89元,则加10
COIN<=COIN+16;
success<='0';failure<='0';
ELSECOIN<=COIN;success<='0';failure<='0';--否则总额不变
ENDIF;
ELSIFselect3='1'THEN--选择3元商品
choice<="01";
IFCOIN>="0000011"THEN--总额大于等于3元,则减3
IF(COINAND"00001111")<="00000010"THEN
COIN<=COIN-9;
ELSECOIN<=COIN-3;
ENDIF;
success<='1';failure<='0';--交易成功
ELSEsuccess<='0';failure<='1';--否则交易失败
ENDIF;
ELSIFselect8='1'THEN--选择8元商品
choice<="10";
IFCOIN>="0001000"THEN--总额大于等于8元,则减8
IF(COINAND"00001111")<="00000111"THEN
COIN<=COIN-14;
ELSECOIN<=COIN-8;
ENDIF;
success<='1';failure<='0';--交易成功
ELSEsuccess<='0';failure<='1';--否则交易失败
ENDIF;
ELSIFselect12='1'THEN--选择12元商品
choice<="11";
IFCOIN>="00010010"THEN--总额大于等于12元,则减12
IF(COINAND"00001111")<="00000001"THEN
COIN<=COIN-24;
ELSECOIN<=COIN-18;
ENDIF;
success<='1';failure<='0';--交易成功
ELSEsuccess<='0';failure<='1';--否则交易失败
ENDIF;
ELSIFcancel='1'THEN--退出
success<='0';failure<='0';
COUT<=COIN;COIN<="00000000";
choice<="00";--总额赋给找零,并且进行信号的初始化
ENDIF;
ENDIF;
ENDPROCESS;
amount<=COIN;--总额
refund<=COUT;--找零
ENDbehave;
4.4译码显示器源程序:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
ENTITYdecodingdisplayIS--定义译码显示单元的实体
PORT(clk:
instd_logic;--50MHz的时钟信号
amount:
INSTD_LOGIC_VECTOR(7DOWNTO0);--总额(8位BCD码)
choice:
INSTD_LOGIC_VECTOR(1DOWNTO0);--商品号(8位BCD码)
refund:
INSTD_LOGIC_VECTOR(7DOWNTO0);--找零(8位BCD码)
cat:
OUTSTD_LOGIC_VECTOR(5DOWNTO0);--数码管disp5-disp0
led:
OUTSTD_LOGIC_VECTOR(6DOWNTO0));--数码管a-g七个管脚
ENDdecodingdisplay;
ARCHITECTUREbehaveOFdecodingdisplayIS
SIGNALtmp:
INTEGERRANGE0TO999;--分频系数:
1000
SIGNALnewclk:
STD_LOGIC;--数码管扫描频率:
50000
SIGNALamounth:
STD_LOGIC_VECTOR(7DOWNTO0);--disp5对应总额的十位
SIGNALamountl:
STD_LOGIC_VECTOR(7DOWNTO0);--disp4对应总额的个位
SIGNALrefundh:
STD_LOGIC_VECTOR(7DOWNTO0);--disp1对应找零的十位
SIGNALrefundl:
STD_LOGIC_VECTOR(7DOWNTO0);--disp0对应找零的个位
signalt:
integerrange0to5;
BEGIN
process(clk)--将50MHz的时钟信号分为50000Hz
begin
IFclk'eventANDclk='1'THEN
IFtmp=999THENtmp<=0;
ELSEtmp<=tmp+1;
ENDIF;
IFtmp<500THENnewclk<='1';
ELSEnewclk<='0';
ENDIF;
ENDIF;
endprocess;
process(newclk)
begin
ifnewclk'eventandnewclk='1'then
ift=0then--以50000Hz的频率扫描6个数码管
cat<="111110";
t<=1;--选中disp0
elsift=1then
cat<="111101";
t<=2;--选中disp1
elsift=2then
cat<="111011";
t<=3;--选中disp2
elsift=3then
cat<="110111";
t<=4;--选中disp3
elsift=4then
cat<="101111";
t<=5;--选中disp4
elsift=5then
cat<="011111";
t<=0;--选中disp5
endif;
refundl<=refundAND"00001111";--取找零信号的低4位
refundh<=refundAND"11110000";--取找零信号的高4位
amountl<=amountAND"00001111";--取总额信号的低4位
amounth<=amountAND"11110000";--取总额信号的高4位
ift=0then--数码管disp0用以显示找零的个位
CASE(refundl)IS
WHEN"00000000"=>led<="1111110";
WHEN"00000001"=>led<="0110000";
WHEN"00000010"=>led<="1101101";
WHEN"00000011"=>led<="1111001";
WHEN"00000100"=>led<="0110011";
WHEN"00000101"=>led<="1011011";
WHEN"00000110"=>led<="1011111";
WHEN"00000111"=>led<="1110000";
WHEN"00001000"=>led<="1111111";
WHEN"00001001"=>led<="1111011";
WHENOTHERS=>led<="0000000";
ENDCASE;
elsift=1then--数码管disp1用以显示找零的十位
CASE(refundh)IS
WHEN"00000000"=>led<="1111110";
WHEN"00010000"=>led<="0110000";
WHEN"00100000"=>led<="1101101";
WHEN"00110000"=>led<="1111001";
WHEN"01000000"=>led<="0110011";
WHEN"01010000"=>led<="1011011";
WHEN"01100000"=>led<="1011111";
WHEN"01110000"=>led<="1110000";
WHEN"10000000"=>led<="1111111";
WHEN"10010000"=>led<="1111011";
WHENOTHERS=>led<="0000000";
ENDCASE;
elsift=2then--数码管disp2用以显示商品号
CASEchoiceIS
WHEN"00"=>led<="1111110";
WHEN"01"=>led<="0110000";
WHEN"10"=>led<="1101101";
WHEN"11"=>led<="1111001";
WHENOTHERS=>led<="0000000";
ENDCASE;
elsift=4then--数码管disp4用以显示总额的个位
CASE(amountl)IS
WHEN"00000000"=>led<="1111110";
WHEN"00000001"=>led<="0110000";
WHEN"00000010"=>led<="1101101";
WHEN"0000001