打地鼠课程设计.docx
《打地鼠课程设计.docx》由会员分享,可在线阅读,更多相关《打地鼠课程设计.docx(25页珍藏版)》请在冰豆网上搜索。
打地鼠课程设计
课程名称:
数字系统与课程设计
实验名称:
打地鼠VHDL的实现
院系:
吴健雄学院
学号:
61006209
姓名:
***
1.课题介绍----------------------------------------------------------------------------3
2.具体实施方案----------------------------------------------------------------------3
3.面板图--------------------------------------------------------------------------------3
4.系统结构图--------------------------------------------------------------------------4
5.状态流程图-------------------------------------------------------------------------6
6.程序清单-----------------------------------------------------------------------------7
7.各主要模块仿真结果波形----------------------------------------------------17
8.课程设计总结---------------------------------------------------------------------18
一、课题介绍
本设计灵感来源于文曲星上风靡一时的打地鼠游戏,旨在一方面作为娱乐游戏,同时可以锻炼人的反应速度。
游戏开始后4*4的点阵中每隔一定秒数(由设计难度决定)会随机点亮一盏,以供选手进行游戏。
当一盏灯点亮时,在下一盏灯亮之前按下对应的键盘即可得分,否则失分。
游戏开始时难度初始值可设定,随后进行一分钟倒计时,一旦为0游戏结束。
在规定时间内得分最高者胜出。
二、具体实施方案
界面用4*4的点阵实现,在点阵中用随机亮起的等表示探出的老鼠,
按键用键盘来实现,由键盘4*4的键对应相应的点阵中的地鼠,控制器通过读取用户的按键及点阵输出代码并进行判断来相应的加减分。
当玩家分数为零或者游戏时间倒计时置0时,游戏停止。
在游戏过程中当玩家按了结束键之后推出进入游戏难度选择,这是用四个开关输入的。
三、面板图:
难度得分时间
输入:
输入名称
功能及操作说明
Startstop
控制游戏开始结束,其中start是游戏总开关,start置1时游戏时钟才会走,游戏才可以开始。
在start置1的前提下,若stop置0游戏开始,stop置1时时间、分数等均清零,恢复初始状态。
K1K2K3K4
输入初始等级的四个开关,为二进制数,如K1K2K3K4为0100时则等级为4级,注意此输入只有在stop为1时才有效,即输入为初始等级,一旦stop置0游戏开始后,置数无效,只有等下一次stop置1时才能再次置入初始等级。
键盘
用作打地鼠的“榔头”,当某一盏灯亮时,在下一盏灯亮之前按下响应键盘按钮即可加分,否则扣分。
输出:
输出名称
输出功能
七段码管6
显示游戏当前难度等级
七段码管4、3
显示玩家得分
七段码管2、1
显示本局游戏剩余时间
4*4点阵
每隔一段时间(随难度等级不同而变化)随机点亮其中一盏(熄灭前面一盏)表示地鼠出现
显示模块
四、系统结构图:
1.总的系统框图
2.顶层结构图
3.各个模块的功能描述
A.分数判断模块
判断选手得分或失分主要是由一个比较器完成的,将系统传给LED灯的信号与选手输入的信号作比较,相同则加分,否则扣分,这两个信号分别传给计分模块,从而完成系统判定得分的工作。
B.系统时钟模块
将内部2MHz的时钟分频为1kHz、及游戏时钟,供以后程序适使用
C.键盘电路
主要通过产生行扫描,来识别用户的按键,电路中已经对按键进行了消抖。
其提供给控制器按键的编码。
D.等级判断模块
判断等级,若游戏未开始时,将等级设为初始值,游戏开始后则判断是否按对五次或按错五次,并响应的加、减等级。
E.随机数产生模块
为使得测试结果的公平性,需要4*4等灯亮灭具有随机性,因而需要随机数产生过程,在本方案中,采用伪随机数产生方法,即在ROM中存入随机表中的数据,游戏开始后采用一个计数器不断从其中读取数据。
F.显示模块
用来将BCD码转化为可以在七段数码管中显示的。
G.计时模块
系统的计时部分需要一个能置初值的计数器即可,其控制信号应为Start,stop
五、状态流程图:
六、程序清单
1.分数判断模块
--该模块实现系统的分数计算
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEIEEE.STD_LOGIC_UNSIGNED.ALL;
ENTITYSCOREIS
PORT(STOP1,clk,start:
INSTD_LOGIC;--stop1为系统中间开始、结束信号,
--若分数或时间为零则置1,clk为游戏时钟,start为游戏清零键
UP,DN:
INSTD_LOGIC;--up为加分信号,dn为减分信号
P:
OUTSTD_LOGIC_VECTOR(7DOWNTO0);--p为分数高位、低位输出
STOP:
OUTSTD_LOGIC);--若游戏分数为零则出高
ENDSCORE;
ARCHITECTUREBEHAVEOFSCOREIS
begin
process(clk,STOP1)
variabletmp:
std_logic_vector(7downto0);
begin
ifclk'eventandclk='1'then
ifSTOP1='1'then--如果stop1=1
tmp:
=tmp;--保持分数不变
else
IFUP='1'THEN--如果加分等于1
TMP:
=TMP+1;--分数加一
IF(TMP(3DOWNTO0)="1010")THEN--如果分数低位为十
TMP(3DOWNTO0):
="0000";--低位变为零
TMP(7DOWNTO4):
=TMP(7DOWNTO4)+1;--高位加一
ENDIF;
ELSIFDN='1'THEN--如果减分信号等于1
IF(TMP(3DOWNTO0)="0000")THEN--如果分数低位等于十
TMP(3DOWNTO0):
="1010";--分数低位变为九
TMP(7DOWNTO4):
=TMP(7DOWNTO4)-1;--高位减一
ENDIF;
TMP:
=TMP-1;--低位减一
ENDIF;
p<=tmp;--输出分数
IFTMP="00000000"THEN--如果分数为零
STOP<='1';--清零信号置一
ELSESTOP<='0';
ENDIF;
endif;
endif;
ifstart='1'then--如果游戏开始键为1
tmp:
="01000000";--分数显示为初始的40分
p<=tmp;
endif;
endprocess;
endBEHAVE;
2.系统时钟分频
--将内部2MHz的时钟分频为1kHz,供以后程序适使用
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entityfenpinkaishiis
port(clk:
instd_logic;--输入的2MHz时钟
clk1:
outstd_logic;--输出的2000Hz时钟
clk2:
outstd_logic);--输出的1000Hz时钟
endfenpinkaishi;
architecturebehaveoffenpinkaishiis
signalx:
std_logic;
begin
process(clk)
variablecnt:
integerrange0to1000;
begin
ifclk'eventandclk='1'then
ifcnt<1000then--变量cnt小于1000时继续加一
cnt:
=cnt+1;
else
cnt:
=0;
x<=notx;--否则清零,翻转x
endif;
endif;
clk1<=x;
endprocess;
process(x)
variabley:
std_logic;
begin
ifx'eventandx='1'then--x变化则翻转y并输出
y:
=noty;
endif;
clk2<=y;
endprocess;
endbehave;
3.等级判断模块
--判断等级,若stop=1,将等级设为初始值,若stop=0则判断是否按对五次或按错五次,并响应的加分、减分。
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitylevelis
port(
level:
outstd_logic_vector(3downto0);--游戏等级输出
clk,up:
instd_logic;--游戏时钟,加分信号
stop:
instd_logic;--游戏清零键
shuru:
instd_logic_vector(3downto0));--初始等级输入
endlevel;
architecturebehaveoflevelis
signalx:
std_logic_vector(3downto0);
begin
process(shuru,clk)
variablecnt1:
integerrange0to9;
variablecnt2:
integerrange0to9;
begin
ifstop='1'thenlevel<=shuru;x<=shuru;cnt1:
=0;cnt2:
=0;--如果stop=1,为等级附初始设定值
else
ifclk'eventandclk='1'then
ifup='1'then--如果按对,
ifcnt1<5thencnt1:
=cnt1+1;--若cnt1小于五,则cnt1加一
elsecnt1:
=0;x<=x+1;level<=x;--若cnt1等于五,则归零且level加一
endif;
else--如果按洞恚?
ifcnt2<5thencnt2:
=cnt2+1;--若cnt2小于五,则cnt2加一
elsecnt2:
=0;x<=x-1;level<=x;--若cnt2等于五,则归零且level减一
endif;
endif;
endif;
endif;
endprocess;
endbehave;
4.游戏时钟分频
--该模块在前面系统时钟模块已分得的1KHz系统时钟基础上,结合游戏等级判断进一步分频,从而得到游戏时钟
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entityfenpinis
port(clk:
instd_logic;--1KHz时钟信号
level:
instd_logic_vector(3downto0);--游戏当前等级
clk1:
outstd_logic;
clk2:
outstd_logic);--输出的游戏信号
endfenpin;
architecturebehaveoffenpinis
signalx:
std_logic;
begin
process(clk)
variablecnt:
integerrange0to10000;
begin
ifrising_edge(clk)then
caselevelis--判断游戏等级,进行响应分频
when"0000"=>ifcnt<3599thencnt:
=cnt+1;
elsecnt:
=0;x<=notx;
endif;
when"0001"=>ifcnt<3399thencnt:
=cnt+1;
elsecnt:
=0;x<=notx;
endif;
when"0010"=>ifcnt<3199thencnt:
=cnt+1;
elsecnt:
=0;x<=notx;
endif;
when"0011"=>ifcnt<2399thencnt:
=cnt+1;
elsecnt:
=0;x<=notx;
endif;
when"0100"=>ifcnt<2199thencnt:
=cnt+1;
elsecnt:
=0;x<=notx;
endif;
when"0101"=>ifcnt<1999thencnt:
=cnt+1;
elsecnt:
=0;x<=notx;
endif;
when"0110"=>ifcnt<1799thencnt:
=cnt+1;
elsecnt:
=0;x<=notx;
endif;
when"0111"=>ifcnt<1599thencnt:
=cnt+1;
elsecnt:
=0;x<=notx;
endif;
whenothers=>ifcnt<1399thencnt:
=cnt+1;
elsecnt:
=0;x<=notx;
endif;
endcase;
endif;
clk1<=x;
endprocess;
process(x)
variabley:
std_logic;
begin
ifx'eventandx='1'then--计数完后翻转y并输出作为游戏时钟
y:
=noty;
endif;
clk2<=y;
endprocess;
endbehave;
5.随机数组产生模块
--产生随机数组,驱动点阵随机亮灭,
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
useieee.std_logic_unsigned.all;
entitysuijiis
port(clk:
instd_logic;--游戏时钟信号
addr:
std_logic_vector(6downto0);--计数模块产生的地址
Q:
outstd_logic_vector(7downto0));--输出的行列点阵信号
endsuiji;
architecturebehaveofsuijiis
signalx:
std_logic_vector(7downto0);
begin
process(clk)
begin
ifrising_edge(clk)then--以下为随机产生的数组
caseaddris--有计数器产生地址,输出响应的随机数组
when"0000000"=>x<="11101110";
when"0000001"=>x<="10111110";
when"0000010"=>x<="11101101";
when"0000011"=>x<="11010111";
when"0000100"=>x<="01111011";
when"0000101"=>x<="10111110";
when"0000110"=>x<="01111011";
when"0000111"=>x<="11011101";
when"0001000"=>x<="10111101";
when"0001001"=>x<="01111110";
when"0001010"=>x<="11101110";
when"0001011"=>x<="11010111";
when"0001100"=>x<="01111011";
when"0001101"=>x<="10110111";
when"0001110"=>x<="11100111";
when"0001111"=>x<="01111110";
when"0010000"=>x<="10110111";
when"0010001"=>x<="11011011";
when"0010010"=>x<="01110111";
when"0010011"=>x<="10111011";
when"0010100"=>x<="01111110";
when"0010101"=>x<="11011101";
when"0010110"=>x<="10111101";
when"0010111"=>x<="11101110";
when"0011000"=>x<="11101110";
when"0011001"=>x<="01111110";
when"0011010"=>x<="11101110";
when"0011011"=>x<="11010111";
when"0011100"=>x<="01111011";
when"0011101"=>x<="10110111";
when"0011110"=>x<="11100111";
when"0011111"=>x<="01111110";
when"0100000"=>x<="11101110";
when"0100001"=>x<="10111110";
when"0100010"=>x<="11101101";
when"0100011"=>x<="11010111";
when"0100100"=>x<="01111011";
when"0100101"=>x<="10111110";
when"0100110"=>x<="01111011";
when"0100111"=>x<="11011101";
when"0101000"=>x<="10111101";
when"0101001"=>x<="01111110";
when"0101010"=>x<="11101110";
when"0101011"=>x<="11010111";
when"0101100"=>x<="01111011";
when"0101101"=>x<="10110111";
when"0101110"=>x<="11100111";
when"0101111"=>x<="01111110";
when"0110000"=>x<="10110111";
when"0110001"=>x<="11011011";
when"0110010"=>x<="01110111";
when"0110011"=>x<="10111011";
when"0110100"=>x<="01111110";
when"0110101"=>x<="11011101";
when"0110110"=>x<="10111101";
when"0110111"=>x<="11101110";
when"0111000"=>x<="11101110";
when"0111001"=>x<="01111110";
when"0111010"=>x<="11101110";
when"0111011"=>x<="11010111";
when"0111100"=>x<="01111011";
when"0111101"=>x<="10110111";
when"0111110"=>x<="11100111";
when"0111111"=>x<="01111110";
whenothers=>x<="01110111";
endcase;
endif;
Q<=x;
endprocess;
endbehave;
6.比较模块
--该模块只是起到简单的比较作用,判断键盘输入和点阵输出是否相等
--分别输出加分和减分信号为后面的模块服务
libraryieee;
useieee.std_logic_1164.all;
entitycompis
port(a,b:
instd_logic_vector(7downto0);--输入的键盘译码和点阵译码
clk:
instd_logic;--游戏时钟
y1,y0:
outstd_logic);--y1为加分信号,y0为减分信号,他们为1时有效
endcomp;
architecturebehaveofcompis
begin
process(clk)
variablex:
std_logic;
begin
ifa=bthen--比较a和b
y1<='1';y0<='0';--相等则y1置1,y0置0
else
y1<='0';y0<='1';--不相等则y1置0,y0置1
endif;
endprocess;
endbehave;
7.游戏时间控制模块
--该模块控制游戏时间
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
USEI