北邮数电实验报告 简易迷宫游戏.docx

上传人:b****6 文档编号:7197849 上传时间:2023-01-21 格式:DOCX 页数:33 大小:479.16KB
下载 相关 举报
北邮数电实验报告 简易迷宫游戏.docx_第1页
第1页 / 共33页
北邮数电实验报告 简易迷宫游戏.docx_第2页
第2页 / 共33页
北邮数电实验报告 简易迷宫游戏.docx_第3页
第3页 / 共33页
北邮数电实验报告 简易迷宫游戏.docx_第4页
第4页 / 共33页
北邮数电实验报告 简易迷宫游戏.docx_第5页
第5页 / 共33页
点击查看更多>>
下载资源
资源描述

北邮数电实验报告 简易迷宫游戏.docx

《北邮数电实验报告 简易迷宫游戏.docx》由会员分享,可在线阅读,更多相关《北邮数电实验报告 简易迷宫游戏.docx(33页珍藏版)》请在冰豆网上搜索。

北邮数电实验报告 简易迷宫游戏.docx

北邮数电实验报告简易迷宫游戏

数字电路与逻辑设计实验

简易迷宫游戏

专业:

电子信息工程

姓名:

班级:

2012211102

学号:

班内序号:

设计课题的任务要求

(一)实验目的

1.熟练掌握VHDL语言和QuartusII软件的使用;

2.理解状态机的工作原理和设计方法;

3.掌握利用EDA工具进行自顶向下的电子系统设计方法;

(二)相关知识

本实验主要利用状态机来设计实现一个简易迷宫系统,本系统分为控制器与受控电路两部分。

控制器主要控制整个系统按设定的工作方式实现点阵、计时器、数码管工作的通与断,并使用逻辑判断判决小人是否移动与否和移动的方向。

同时本实验也运用到了包括分频器、计数器、数码管、点阵等相关知识。

主要利用六位数码管显示30s计时和小人移动步数,用点阵显示开机画面、迷宫地图、小人移动过程和游戏失败、胜利的相应画面。

(三)实验任务

基本要求:

1、用8×8点阵进行游戏显示。

2、迷宫游戏如图1所示,采用双色点阵显示,其中红色LED为迷宫墙壁,绿色LED

表示人物。

通过BTN0~BTN3四个按键控制迷宫中的人物进行上下左右移动,使人

物从起始点出发,走到迷宫的出口,游戏结束

3、普通计时模式:

通过按键BTN7启动游戏,必须在30秒内找到出口,否则游戏失败,

用两个数码管进行倒计时显示。

游戏胜利或者失败均要在8×8点阵上有相应的画面

出现。

4、迷宫中的人物在行走过程中,如果碰到墙壁,保持原地不动

提高要求:

1.多种迷宫地图可以选择。

2.在计时的基础上增加计步的功能,每按一次控制按键步数加1,碰壁不计算步数,

计步结果用数码管显示。

3.增加了计时显示的精确度,让倒计时精确到0.01s

4.增加了开机画面,当按下START开始键后,点阵上开始显示“GO-6-5-4-3-2-1”的开始画面。

系统设计

(四)设计思路

此程序利用自顶向下的设计思想。

首先要考虑实现基本功能所需要哪些模块,倒计时的功能要用数码管来实现,地图的显示和迷宫游戏中动画的交互要用8×8点阵来实现,方向的选择和开始游戏需要独立按键来显示,这些都是最顶层的模块。

然后,要实现这些模块,第一需要适当的时钟频率来驱动,这就要完成一个分频器,根据点阵、数码管以及独立按键各自的特征完成相应频率的分配。

实现倒计时功能的时候,需要一个计时器在每秒改变一次数码管的显示状态,于是还需要一个计时器模块。

而数码管动态扫描需要相应的LED灯亮灭,这就需要先定义好了显示相应数字的时候对应八段LED的高低电平状态。

点阵的显示控制原理和数码管类似,都是一个较高频率的动态扫描过程,只是代码量更大。

其次,也是该程序最关键的地方就是绿色小人移动的控制。

题干中说明小人撞墙后原地不动,不撞墙的时候进行移动。

这就需要我们判断是否撞墙。

经过和同学的商讨,我绝对将点阵坐标化,而小人所处的位置用(x,y)表示并实时的更新,然后将墙壁坐标封装好,当下一步的坐标在墙壁坐标的集合中则判定为撞墙,否则根据方向进行移动。

而终点坐标也都是提前用代码设定好的,这样通过坐标显示出点阵应该进行的下一画面。

到此为止,该实验的基本功能都已经规划得较为清晰。

对于提高要求,我通过一个拔码开关控制初始迷宫地图的选择,在程序中加入一个输入信号来选择相应地图;在程序中添加两个计数变量,分别表示步数的个位和十位,两者添加到判断撞墙与否的逻辑语句中,在数码管显示模块中增加两个数码管的显示便可实现。

此外,为了丰富点阵界面,我还添加了开机画面,通过一个1s加1的变量扫描显示“GO-6-5-4-3-2-1”;想到很多倒计时显示中个都精确到了0.01s甚至更精确,我又增加两个数码管来显示倒计时的小数点后两位。

(五)总体框图

1.系统结构框图

2.逻辑划分方框图

3.控制模块流程图

4.状态转移图

(六)分块设计

点阵模块:

点阵模块主要分为点阵扫描显示模块、小人移动逻辑判断模块。

扫描显示模块,主要是对迷宫地图、开机动画以及小人移动变化后的图案进行动态扫描,完成游戏交互。

开机画面通过一个一秒更新一次的变量,然后通过case语句来完成扫描;地图图案的显示也是同样的方案,只不过要胜利或者失败的逻辑判断。

小人移动的逻辑判断模块,主要通过坐标定位。

首先将地图中墙壁的坐标位置封装好,然后将小人时刻的位置定义为(x,y),再根据按键对x,y进行变化,最后通过判断新的坐标是否在封装好的墙壁集合中来进行移动与否的判决。

如果移动则更新(x,y);如果不移动,则保持(x,y)不变。

数码管显示模块:

数码管显示模块主要分为30s倒计时模块和小人移动步数计数模块

倒计时模块中将一个1KHZ的时钟信号进行四次的十分频,可以得到一个精确到0.01s的倒计时。

每个变量都是十进制的数,再将它们传送到数码管动态扫描模块,便可以顺利地显示30s倒计时。

小人移动步数计数模块,定义两个计数变量count、count10分别表示计数的个位和十位,将其放在小人移动逻辑判断模块中,当逻辑判定为移动,则将count加一,当加到10的时候进位。

再将两者传送到数码管动态扫描模块,就可以实时显示小人移动的步数。

按键防抖模块:

该程序再一开始开发的时候并没有加防抖模块,而是尽可能地找到一个最佳的按键扫描控制频率,使得既可以得到灵敏可靠的按键控制,又可以再长按一次后进行多步移动,这样可以方便用户的操作,一开始测试得到的按键扫描频率为5Hz。

但是好像要求按键必须加防抖,并且为了提高按键输入可靠性,由于机械触点的弹性振动,因而在按键闭合和断开的瞬间均会出现一连串的抖动,按键的抖动会造成按一次键产生的开关状态被CPU误读几次。

为了使CPU能正确地读取按键状态,必须在按键闭合或断开时,消除产生的前沿或后沿抖动。

一、仿真波形及波形分析

(七)复位、开始()

注:

以下关于点阵显示的仿真都是最开始测试用的模块,并不包含点阵动态显示的所有状态,只是挑选其中一些典型状态展示,而且点阵扫描红色和绿色是分开的。

.复位:

当按下复位键的时候,停止对点阵的扫描,点阵上无任务图形显示。

开始:

当按下开始键的时候,点阵开始进行行扫描,开始倒计时显示“GO-6-5-4-3-2-1”,上图为点阵用红色LED显示“GO”。

(二)点阵显示胜利、失败

胜利:

当玩家在30s之内到达了迷宫的终点,游戏结束并点阵显示“V”的标志。

上图为当信号victory置高电平的时候,点阵开始行扫描,并将红色、绿色LED均点亮显示“V”,上图可明显地看出。

失败:

当玩家在30s之内没有到达迷宫的终点,游戏结束并且点阵显示“X”的标志。

上图为信号fail置高电平的时候,点阵开始行扫描,并将红色、绿色LED均点亮显示“X”,由上图可以明显地看出。

(三)数码管倒计时

数码管倒计时:

实际上应该是四位数码管从30.00s倒计时,为了方便展示将倒计时的计数变量改成二进制,上图中输出信号ledshow代表数码管段选的信号,而ledstate代表数码管位选的信号,变量ledsao表示分五次对四位数字加上一个小数点进行扫描。

上图红色圈中表示显示小数点,“00000001”表示小数点,而ledstate在“111110—111101—111011—110111—111011”五个状态之间循环表示对四位数字和一个小数点的显示。

而ledshow显示相应的数字。

(四)按键防抖

按键防抖:

keyin输入一个持续时间约为0.1s的按键信号并用高频时钟模拟抖动,keyout输出一个时钟周期的高电平。

二、源程序(注释)

LIBRARYIEEE;

USEIEEE.STD_LOGIC_1164.ALL;

useieee.std_logic_unsigned.all;

ENTITYmazeIS

PORT(

clk:

INSTD_LOGIC;--总时钟

start,reset:

INSTD_LOGIC;--开始和复位键

l,r,f,b,mapflag:

INSTD_LOGIC;--BTN--b/r/f/b分别代表小人向左、右、前、后移动;mapflag代表两种地图的选择

dotshow:

OUTSTD_LOGIC_VECTOR(23DOWNTO0);--点阵显示

ledstate:

OUTSTD_LOGIC_VECTOR(5DOWNTO0);--数码管状态

ledshow:

OUTSTD_LOGIC_VECTOR(7DOWNTO0));--数码管显示

ENDmaze;

ARCHITECTUREmainofmazeIS

signalcnt:

integerrange0to25000;--分频器的计数

signalcnt1:

integerrange0to25000000;

signalcnt2:

integerrange0to5000000;

signalclk_tmp:

std_logic;--分频器的临时信号

signalclk_tmp1:

std_logic;

signaltclk:

std_logic;

signalclk_tmp2:

std_logic;

signalkey_tmp0,key_tmp1,key_tmp2,key_tmp3:

std_logic;

signalrow:

std_logic_vector(7downto0);--点阵行状态

signalcul:

std_logic_vector(15downto0);--点阵列状态

signalaclk:

std_logic;--点阵倒计时开机画面的时钟信号

signalbinclk:

std_logic;--按键时钟信号

sharedvariabletend:

integerrange0to1;

signaltostart:

std_logic;--开始标志信号

signalpreset:

std_logic;--逻辑判断模块重置

signaldotreset:

std_logic;--点阵模块重置

signalledreset:

std_logic;--数码管重置

signaltreset:

std_logic;--计时器重置

signalpwork:

std_logic;--逻辑判断模块工作

signaldotwork:

std_logic;--点阵工作

signalledwork:

std_logic;--数码管工作

signaltwork:

std_logic;--计时器工作

signalworked:

std_logic;

signalvic:

std_logic;--成功

signalfal:

std_logic;--失败

typenstisarray(0to9)ofstd_logic_vector(7downto0);

signalledshowed:

nst;

sharedvariablerowsao:

integerrange0to9;--点阵的行扫描

sharedvariableledsao:

integerrange0to6;--数码管的扫描

sharedvariabledaojishi:

integerrange0to7;--开机动画倒计时扫描

sharedvariabledotsao:

integerrange0to3;

sharedvariablemapsao:

integerrange0to9;

sharedvariablex:

integerrange-7to0;--小人的坐标

sharedvariabley:

integerrange-6to1;

sharedvariablecount:

integerrange0to9;--count和count10分别代表步数的个位和十位

sharedvariablecount10:

integerrange0to9;

sharedvariabletimems:

integerrange0to9;

sharedvariabletime001s:

integerrange0to9;--以下分别代表30倒计时的位数

sharedvariabletime01s:

integerrange0to9;

sharedvariabletime1s:

integerrange0to9;

sharedvariabletime10s:

integerrange0to9;

begin--数码管显示高低电平初始化

ledshowed

(1)<="01100000";

ledshowed

(2)<="11011010";

ledshowed(3)<="11110010";

ledshowed(4)<="01100110";

ledshowed(5)<="10110110";

ledshowed(6)<="10111110";

ledshowed(7)<="11100000";

ledshowed(8)<="11111110";

ledshowed(9)<="11110110";

ledshowed(0)<="11111100";

tdiv:

process(clk,clk_tmp)--计时器分频-----1K

begin

if(clk'eventandclk='1')then

ifcnt=24999then

cnt<=0;

clk_tmp<=notclk_tmp;

else

cnt<=cnt+1;

endif;

endif;

tclk<=clk_tmp;

endprocess;

adiv:

process(clk,clk_tmp1)--点阵分频-------1HZ

begin

if(clk'eventandclk='1')then

ifcnt1=24999999then

cnt1<=0;

clk_tmp1<=notclk_tmp1;

else

cnt1<=cnt1+1;

endif;

endif;

aclk<=clk_tmp1;

endprocess;

usediv:

process(clk,clk_tmp2)--按键控制判断分频-----5HZ

begin

if(clk'eventandclk='1')then

ifcnt2=4999999then

cnt2<=0;

clk_tmp2<=notclk_tmp2;

else

cnt2<=cnt2+1;

endif;

endif;

binclk<=clk_tmp2;

endprocess;

process(clk_fd)--防抖模块

begin

if(clk_fd'eventandclk_fd='1')then

key_tmp0<=keyin;

key_tmp1<=key_tmp0;

endif;

endprocess;--利用信号赋值延时将前后信号相与完成防抖

key_tmp2<=key_tmp0andkey_tmp1;

process(clk_fd)

begin

if(clk_fd'eventandclk_fd='1')then

key_tmp3<=key_tmp2;

keyout<=not(key_tmp2)andkey_tmp3;

endif;

endprocess;

end;--时钟上升沿输出一个时钟周期宽度的脉冲

control:

process(clk,reset,start)--控制器

begin

if(clk'eventandclk='1')then

if(start='1')then

tostart<='1';

endif;

if(reset='1'ortend=1)then

preset<='1';

dotreset<='1';

ledreset<='1';

treset<='1';

tostart<='0';

dotwork<='0';

else

preset<='0';

dotreset<='0';

ledreset<='0';

treset<='0';

if(tostart='1')then

dotwork<='1';--启动点阵模块

endif;

endif;

endif;

endprocess;

a:

process(aclk,dotreset)--点阵工作模块

begin

if(dotreset='1')then

dotsao:

=0;

else

if(aclk'eventandaclk='1')then

if(vic='1'orfal='1')then

if(dotsao<=2)then

dotsao:

=dotsao+1;

endif;

endif;

endif;

endif;

endprocess;

process(tclk,dotreset)

begin

if(dotreset='1')then

mapsao:

=0;

else

if(tclk'eventandtclk='1')then

if(mapsao=9)then

mapsao:

=0;

else

mapsao:

=mapsao+1;

endif;

endif;

endif;

endprocess;

process(aclk,dotwork,worked,dotreset)

begin

if(dotreset='1')then

daojishi:

=0;

else

if(aclk'eventandaclk='1'anddotwork='1'andworked='0')then

if(daojishi=7)then

daojishi:

=0;

else

daojishi:

=daojishi+1;

endif;

endif;

endif;

endprocess;

process(tclk,dotreset)

begin

if(dotreset='1')then

rowsao:

=0;

else

if(tclk'eventandtclk='1')then

if(rowsao=9)then

rowsao:

=0;

else

rowsao:

=rowsao+1;

endif;

endif;

endif;

endprocess;

process(clk,dotreset,dotwork,mapflag)--开机动画

begin

if(dotreset='1')then

dotshow<="000000000000000000000000";

tend:

=0;worked<='0';twork<='0';pwork<='0';

else

if(clk'eventandclk='1')then

if(dotwork='1')then

if(worked='0')then

casedaojishiis

when0=>

caserowsaois

when1=>dotshow<="111111111111111100000000";

when0=>dotshow<="101111111111011100000000";

when2=>dotshow<="110111111000010100000000";

when3=>dotshow<="111011111000010100000000";

when4=>dotshow<="111101111011010100000000";

when5=>dotshow<="111110111001010100000000";--go

when6=>dotshow<="111111011111011100000000";

when7=>dotshow<="111111111111111100000000";

when8=>dotshow<="111111111111111100000000";

when9=>dotshow<="111111111111111100000000";

endcase;

when1=>

caserowsaois

when1=>dotshow<="011111110011110000000000";

when0=>dotshow<="101111110010000000000000";

when2=>dotshow<="110111110010000000000000";

when3=>dotshow<="111011110010000000000000";

when4=>dotshow<="111101110011110000000000";--6

when5=>dotshow<="111110110010010000000000";

when6=>dotshow<="111111010010010000000000";

when7=>dotshow<="111111100011110000000000";

when8=>dotshow<="111111111111111100000000";

when9=>dotshow<="111111111111111100000000";

endcase;

when2=>

caserowsaois

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 研究生入学考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1