基于FPGA的VGA显示对贪吃蛇游戏的设计

基于FPGA的VGA显示对贪吃蛇游戏的设计

摘要

目前,电子数码产品已经进入了人生活的方方面面,而大多数电子产品都依靠显示屏来传递信息,由此可见用电路对显示屏进行控制的研究有很大的实用价值和市场需求。且FPGA作为专用集成电路又综合许多其他可编程器件的优点,本文则以FPGA的VGA显示对贪吃蛇游戏的设计,对FPGA的VGA显示进行了较深层次的研究。
本文在对贪吃蛇游戏进行设计时,将整个项目细分为菜单选择状态机、复位键模块、按键消抖、难度设置状态机、运动方向状态机、蛇的移动、食物的产生、蛇的生长与死亡、VGA图片的显示和最终RGB显示11个小模块进行分项设计,最终实现了传统贪吃蛇游戏的基本功能,并对界面进行了适合用户使用的美化。

关键字:FPGA,VGA显示,贪吃蛇游戏

注:原工程文件下载链接 https://download.csdn.net/download/qq_42025108/11711503

一、FPGA技术

1.1 FPGA技术简介
FPGA,即现场可编程门阵列,它是在PAL、GAL、CPLD等可编程器件的基础上进一步发展的产物。它是作为专用集成电路领域中的一种半制定电路而出现的,即解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。
采用FPGA设计ASIC电路时,用户不再需要去投片生产,就可以得到合用的芯片,同时其内部有十分丰富的触发器和I/O引脚,是ASIC电路中设计周期最短、开发成本最低、风险由最小的器件之一,还具有功耗低、与多平台兼容的特点。可以说FPGA芯片是小批量系统提高系统集成度、可靠性的最佳选择之一。

1.2 FPGA选用
Spartan系列开发板是针对FPGA的初、中级学习者设计,帮助用户降低学习成本和加快用户快速进入可编程逻辑器件设计开发领域,该核心板可配合与之配套的实验主板进行相应的实验,也可做为CPLD、FPGA研发的原形。核心板简单实用、扩展性好,适合前期用户开发验证用。
核心板上拥有下面资源:
FPGA主芯片:XC6SLX9
有源晶振:50MHz
引脚数目:144

二、VGA显示控制的理论

2.1 VGA显示概述
VGA的英文全称是Video Graphics Array,即视频图像阵列,其彩色显示标准是IBM在1987年随PS/2机一起推出的一种视频的传输标准,它运用到模拟的信号代替数字信号的显示,具有分辨率高、颜色多样、显示速率高的特点,具有十分广泛的应用。如今VGA彩色显示系统基础指标已经被整个工业界采纳并标准化。可在640×480的较高分辨率下显示出16种彩色和256种灰度。
目前从工控产品到消费产品,基于VGA接口的显示器常见于许多需要大屏幕的场合。由于上述的那些优点,VGA接口的显示器广泛应用于各自终端设备、医疗仪器、汽车电子、消费电子等领域。

2.2 VGA显示控制方式
通用的VGA显示卡系统主要由控制电路、显示缓存区和视频BIOS程序三部分组成。控制电路则主要完成时序发生、显示缓冲区数据的操作和将数字信号转换为模拟信号等功能;显示缓冲区提高显示数据缓存空间;视频BIOS作为控制程序的固化在显示卡的ROM中。
在解决数据来源、数据储存的问题之后,最关键的便是实现VGA的时序问题。VGA的时序不是直接由模拟信号产生的,而是由数字信号控制的,为了将数字信号变成模拟信号,中间要经过D/A转换处理。同时,与其他显示器不同的是,VGA接口是没有数据使能信号的,主要通过行、场扫描来实现显示控制的。
当用户确定好所需要显示的分辨率即刷新一屏的频率后,就得参照VGA时序标准,相应解决VGA的时序问题。本文在制作贪吃蛇游戏时采用的便是常见的640×480的分辨率和60Hz的场频率,则下面只对该时序进行介绍:
由像素点和场频率可计算出时序中点时钟频率,此处则为25MHz,则在整个VGA的设计中,均应用该时钟作为基础时钟。其次在VGA的显示过程中还涉及电子枪的消隐、换行和换屏等操作,而该问题可结合VGA时序标准,通过对电子枪打点所在位置的行列的计数来解决:
在VGA时序中,完成一行扫描的时间称为水平扫描时间,其时序下面记作行时序为HSync;列时序则记作VSync。查询标准可知其对应的时序标准如图1所示:
在这里插入图片描述
图1:640×480@60Hz的驱动时序
其中Sync、Back proch、Top/Left Border、”Addressable” Video、Bottom/Right Border、Front Porch分别表示行时序和列时序都需要产生的同步脉冲、同步后肩、顶/左边框、显示时序段、底/边框和同步前肩,且通过对VGA标准时序的查询可以得到上述各个参数值:
表一:640×480@60Hz的同步信号参数
在这里插入图片描述

三、贪吃蛇游戏设计构思

3.1总体设计思路
贪吃蛇的总体设计思路采用Top-down设计思想,首先是系统模块,再往下按照功能的不同分为蛇的生长与死亡模块、蛇的移动模块、难度设置状态机模块、VGA的图片显示模块、随机坐标模块、按键消抖、复位键模块、菜单选择状态机、运动方向状态机和Rgb显示模块。下面分别介绍各模块的设计构思和功能。
在这里插入图片描述
图2:总体设计框图
贪吃蛇的总体设计思路采用Top-down设计思想,首先是系统模块,再往下按照功能的不同分为蛇的生长与死亡模块、蛇的移动模块、难度设置状态机模块、VGA的图片显示模块、随机坐标模块、按键消抖、复位键模块、菜单选择状态机、运动方向状态机和Rgb显示模块。下面分别介绍各模块的设计构思和功能。

3.2 菜单选择状态机
再次运用状态机的思想便可以很好的实现对菜单选择的控制,在这个状态机中有face_start、face_options、options、game_start、game_back和game六个状态,其依次对应的屏幕显示如下:
在这里插入图片描述
图3:各个菜单状态的实物显示
由于开发板按键只有四个的限制,即按键sw1、sw2、sw3、sw4,此处在face_start和face_options状态时,sw1和sw2分别表示上下,sw3和sw4分别确认和返回;在options时,sw1和sw2分别表示增减难度,sw4表示返回;在game_start和game_back状态时,sw1和sw2分别表示上下,sw3表示确认;在game状态时,sw1、sw2、sw3、sw4分别控制蛇的上下左右,其次sw3和sw4同时按表示返回game_start状态。其次,sw1和sw2按表示复位键。

3.3复位键模块
3.3.1模块分析
在贪吃蛇游戏中需要有一个复位键模块,保证在按下复位键时游戏重新开始,回到初始界面。由于在进入游戏中时,开发板上的四个键分别用于运动方向:上、下、左和右,因此复位键为2个按键同时按下为有效。

3.4按键消抖
3.4.1模块分析
按键消抖通常的按键所用的机械弹性开关,当机器触电断开、闭合时,由于机器触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开,因而在闭合及断开的瞬间均伴随有一连串的抖动,故需要按键消抖。

3.5难度设置状态机
由于用户的需求不同,难易程度的选择往往是游戏的一个必备功能,从而保证新玩家不会无奈游戏太难,老玩家嫌弃游戏太简单。本文在难度的设置上则采用状态机的思想对设置了三个可供选择的难度状态,即蛇的运动速度越快,难度越高。而蛇的速度状态在蛇的运动模块中也有细致讲解,通过改变蛇停留时间的长短即可改变蛇的运动速率。
此处需要注意的是,难度状态界面的状态机与菜单选择状态机紧密联系,即只有当菜单选择状态机进入options状态时才可对难度状态进行调节。其细致调节和状态转移过程如下图所示:
在这里插入图片描述
图4:难度选择状态机
由上图的状态机功能图,运用case语句,便可很轻松的写出难度控制模块的代码。

3.6 运动方向状态机

3.6.1运动方向状态图
在这里插入图片描述
图5:运动状态机

3.6.2运动方向状态分析
蛇的运动方向分为上、下、左、右,我们根据状态机来描述蛇的运动和状态,总共有5个状态,分别是stop、up、down、right、left,初始进入游戏界面是,状态为stop,蛇的初始方向是向右且是水平放置蛇身。按下右键或者上下键,蛇开始移动,蛇的运动方向在5个状态机间根据输入按键信号不断改变,若无按键信号传入,则蛇保持原状态不变。但蛇的下一个运动方向不能与上一个运动方向相反,即蛇的状态无法跳到与之相反的状态中去。举个例子:若此时蛇的运动方向为向右,按下左键,则左键无效,因为无法跳到left状态。同理:
(1) 状态为stop:右键、上键、下键信号为有效,左键信号无效;
(2) 状态为up:右键、上键、下键信号为有效,左键信号无效;
(3) 状态为down:右键、上键、下键信号为有效,左键信号无效;
(4) 状态为right: 右键、上键、下键信号为有效,左键信号无效;
(5) 状态为left: 右键、上键、下键信号为有效,左键信号无效;

3.7蛇的移动

3.7.1蛇移动的速度控制
在蛇移动速度的控制上,首先给一个计数器,s_cnt即为贪吃蛇每次在一点停留的时间,当电子枪在循环打点显示时,每过一帧则计数加1,而最大值在不同的情况有不同的值,即对应着三种难度状态。同时,为保证该计数器在初始状态从零开始计时,只有当界面控制状态等于game时,其才会开始循环累加计数。

3.7.2蛇头运动的实现
蛇头的运动在整个蛇的运动中尤为重要,因为贪吃蛇的运动的实质是身体上的每一个点都是在重复蛇头的运动规律的,因此蛇头运动的完美实现是完成蛇运动最重要也是比较难的一步。
由蛇的运动方向状态机可得到,蛇下步改运动的状态,即按键按下时,蛇的运动并不是马上改变的,而是会等它停留时间结束时,才读取这个动作。在某个时间点,单单知道蛇下一步的运动状态是远远不够的,因为蛇下一步的具体动作是由此时的运动状态和下一步的运动状态同时决定的,此时便引入一个state1。同时储存贪吃蛇此时的运动状态和下一个运动状态,且其位宽为state运动状态的两倍,这样设置方便其通过位拼接的技术实现下一步的运动状态在下一步会变成当前运动状态,同时更出新的下一个运动状态,上述过程图示如下:
在这里插入图片描述
图6:蛇头当前与下一运动状态的记录示意图
当记录完蛇的当前运动状态和下一运动状态后,便可清楚的知道蛇头的运动轨迹了,此处时刻留意蛇头的右下角,记录和理清其最右下点处的运动情况便可实现对蛇头的运动的显示,此处记蛇头右下角的横纵坐标分别为:x,y。则通过分析state1的具体数据可知x,y的变化如下图所示:
在这里插入图片描述
图7:蛇头运动坐标
其中,每次变动在s_cnt==interval-1时发生,而interval就表示难度状态机所控制的蛇每点处的最大停留帧数,且由上图数据可知,蛇身宽为20个像素点,即蛇每次运动的距离也为20个像素点。

3.7.3蛇身运动的实现
由于贪吃蛇的身体部分实质是再次重复头部运动的过程,只是越后面的点延时越长。因此,若蛇身体越长,需要储存头部的运动的数据就越多,由于开发板资源的限制,本文就以最长蛇长为10节为例,若需加长,只需在源代码上作相应的修改即可。
同样的运用移位的思想,定义一个定量xx和yy分别对蛇头部的坐标进行储存,由于蛇头部的坐标的位宽均为10位宽,因此xx和yy的位宽分别为蛇的最大长度的10倍。在运动过程中,分别让蛇身的第k节的坐标赋值为xx或yy第[10(k-1)-1,10(k-2)]位上的数据。而此处需要注意的是的便是初始状态,因为初始时头部不动没有,因此当state==stop状态时,不对xx和yy进行复制位拼接操作,并给xx和yy的各自位宽上赋值上下一步蛇身各节应该位于的坐标点。

3.7.4蛇的移动的时序分析
在蛇的运动过程中也很需要注意时序问题,每一步的赋值时序都十分关键,下面则对运动过程中用到的大量变量进行时序分析,从细节的角度讲解设计过程:
在这里插入图片描述
图8:控制运动变量的赋值时序分析

## 3.8 食物的产生

3.8.1随机坐标模块分析
游戏界面中需要有一个方格作为蛇的吃食,由于蛇的移动范围为520440,故将一个吃食的大小为2020。吃食的出现的随机性实现在于刚进入游戏界面时给了随机坐标模块一个信号。
该模块中定义了两个变量 和 ,分别控制吃食的坐标,因此 , 的范围分别为(0,25),(0,21),在刚开始进入游戏界面时,给随机坐标模块一个信号使 , 不断变化,这个变化是像VGA扫描显示屏一样的一行一行的快速扫描。由于是高速扫描,在按下开始键时,到人按下控制方向的键时,此时记录下 和 的值,这中间的时间是随机不规律的,故第一个吃食的出现是随机的。当蛇头吃下一个食物时,又将信号拉高,重新刷新之前记录下的值,由于人的操作原因来实现食物的出现随机使得代码更简洁。

3.8.2食物刷新的控制
按照上述方法确实能得到两个随机变化的横纵坐标,但是食物的变得必须遵循开始游戏时,食物便出现,然后在吃到他之前,食物的显示坐标是不该改变的因此,在食物刷新的控制上,再给一个标志变量flag_food来提醒机器食物的坐标该刷新了,即只有当蛇吃到食物时,标志位才拉高一个分频后的时钟延,否则就保持低电平,则在食物真实的横纵坐标中,监测到flag_food==1时,才将一直高速循环变化的两个坐标随机数赋值给真实的食物坐标,从而实现食物的刷新显示。

3.9蛇的生长与死亡
3.9.1蛇的生长
蛇的生长则是游戏提升乐趣的一个模块,其设计原理是:蛇长度是一定的,只是从开始就给蛇一个长度显示的计数器long_cnt,在初始时刻身长显示为5,则赋值为5.当吃到食物时,即再次运用到食物刷新模块中的flag_food这个标志变量,在提醒电路中食物该刷新的同时也提醒蛇的长度该增长了,而增长就是将long_cnt加1,当显示模块中监测到身长的显示应该为6时,则会将尾巴后面隐藏的身体显示出来,从而让用户感受到了蛇的生长。

3.9.2蛇的死亡
蛇的死亡时候,界面控制状态机的state_1实质还是在game状态的,只是给了一个死亡标志变量d_flag,也就是当蛇撞墙或者撞到自己时,就将d_flag持续拉高,以这个为标志在屏幕上显示出死亡信号。直到从state_1从game状态变回game_start状态,d_flag就会重新拉低,以保证再次进入game状态时能重新开始游戏。

3.10 VGA的图片显示
3.10.1 IP核的生成
RAM是一种随机存取存贮器,又称作“随机存储器”,是与CPU直接交换数据的内部存贮器,也叫主存(内存)。它可以随时读写,而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储媒介。
在调用RAM存贮所需要的图片的数据时,首先需要调用IP核,IP核用于FPGA中的预先设计好的电路功能模,在需要用到图片信息时,将地址信号传输给RAM,RAM再传出与地址对应的像素点的Rgb数据,以此来完成一张图片的显示。此次设计中IP核的生成如下:
在这里插入图片描述
图9:ip核调用的rom文件

3.10.2 coe文件的生成
在进行图片显示时,要对RAM模块进行初始化。ISE软件本身具备的初始化功能对于较小的RAM是行之有效的,但面对大容量的RAM时就显得捉襟见肘。故在这里要用到Matlab软件,使用它生成.coe文件,将图片信息转化为数据并存贮在coe文件中。coe文件的格式为 : memory_initialization_radix=10; -->文件存储数据的进制,10即为10进制; memory_initialization_vector = -->数据向量。
coe文件用Matlab生成代码如下:
在这里插入图片描述

3.10.3 显示图片
在这里插入图片描述
图10:ROM的调用过程
VGA在调用RAM过程中,VGA将地址信号传给RAM,RAM接受到信号时开始按照存贮顺序以此输出Rgb数据,因此VGA的显示屏上在规定的范围内同样按照输出顺序输出Rgb值,这样就完成了一张图片的显示。而本文在显示时遇到一个难点就是开发板的资源十分有限,当显示200200的像素图片时,便报错提示开发板资源不足,因此只有保存100100的图片数据来以200200的来显示出来,这就在显示时,提高了对读取数据地址运用的难度。即巧妙的运用数据读取的地址可以解决开发板资源不足的问题。细致解决办法如下:
在这里插入图片描述
图11:图片地址读取计数器
由图可以发现,首先,定义一个rd_cnt1计数信号,该信号随着25mhz的时钟的上升延不断0,1变化,只有当rd_cnt11时,读取rom的地址才会加1,这样就保证了在同一行中,每一个rom中的数值,在电脑vga的两个点中显示,实现了照片显示的行拉长。再定义了一个变量rd_cnt2,当h_cntH_START+418时,变会拉高一个时钟延,否则为0,这个就可以分频出一个由rd_cnt3控制的计数器,奇数行则为零,偶数行则为1,同个这个计数器就可以实现,当h_cntH_START+420且rd_cnt31时,地址减99,从而实现偶数行的显示与奇数行保持一致,解决了列拉长的问题,以实现实质是100
100的图片在vga显示屏上一200*200的区域完美的显示出来。

3.11 Rgb显示模块
Rgb的显示便上总和以上所有模块后的一个显示过程,其整体有一个case语句组成,即首先快速判断出state1处于什么状态,不同的界面所显示的画面都有较大差别。在face_start和face_options状态中,需要注意的便是两个选项线框、选项小块和图片的显示位置的具体确定;在options状态中,即确定三个难度显示小块的位置和颜色;game_start和game_back状态时,则需显示的由:蛇行动范围的黑线框、选项小块、选项线框和一个小图片的显示;当在game状态时,则应显示出蛇的行动范围的黑线框、选项线框、选项小图片、食物、和蛇即其动态过程。

四、测试分析与总结

整个项目的完成大致经历了学习、设计、写代码和调试四个过程,历时将近一个月,对于一个fpga初学者,由于对这些可以做成成品的项目是充满兴趣的。回想起来最后关键阶段熬过的夜也感觉十分充实。
在整个过程中,首先便是体验到了完成一个项目的过程,其次是学习并巩固了并熟练掌握对状态机、vga显示和top例化、伪随机数知识的运用,并新学习和深度掌握了vga如何调取ip核通过rom地址的调用来显示出图片,同时通过思考发现了如何巧妙节约开发板资源,将一张100100的图片以200200像素点的大小通过vga显示出来。最后就是强化了编程的思维模式,如何思考将功能用代码的形式写出来最后再通过自己的方式实现。
总而言之,还是很感谢有这么一次亲身体验的机会,希望在日后还能通过实践提升自己。最后,感谢老师和学长们的指导和疑惑解答,这段经历也是终身难忘了。

五、参考文献

[1]韩众,李智中,曹飞.基于FPGA的图像接口的设计[J].现代工业经济和信息化,2018,8(05):37-39+97.
[2]申中杰,王素珍,胡安峰,宗卫华.基于FPGA的VGA多幅图片动态显示系统[J].单片机与嵌入式系统应用,2018,18(01):52-56.
[3]陈权,朱卫华,曹亮,陈志勇.基于FPGA的图像叠加及VGA显示设计[J].南华大学学报(自然科学版),2017,31(03):55-59.

基于FPGA设计的贪吃蛇小游戏实验课程设计报告+quartus9.1工程源码,可以做为你的学习设计参考。 摘 要 本次电子技术基础课程设计贪吃蛇游戏,实现了用FPGA来驱动VGA显示贪吃蛇游戏。贪吃蛇的游戏规则是玩家使用PS2键盘操控一条蛇上下左右移动不断吞下苹果,吃下一个苹果蛇身增长一节,当蛇头撞到蛇身或障壁时游戏结束。本课程设计采用Verilog HDL语言编写,涉及到VGA显示,PS2键盘操控,状态机等相关知识。 关键词:FPGAVGA;PS2;贪吃蛇;Verilog HDL 2.1 游戏设计内容及要求 基本要求: ① 利用FPGA开发板、VGA显示器、PS2键盘实现贪吃蛇游戏。 ② 一条蛇可以看成由许多正方形的“小格子”拼凑成,称作节。节是蛇身上最小的单位。蛇的初始长度确定。 ③ 蛇的初始位置及方向由FPGA开发板随机生成,每次游戏预送100分。 ④ 用户使用开发板键盘及PS2键盘可控制蛇头的方向及速度。蛇在屏幕中运动每安全度过1秒加1分,静止状态每过1秒减1分,当游戏达到200分时自动进入游戏下一关,当游戏分值自动减为0时游戏失败终止。 ⑤ 当贪吃蛇触壁则失败。 ⑥ 实现游戏蛇身变换及游戏积分的自动动态显示。 2.2 系统分析 贪吃蛇是经典小游戏,本设计采用VGA显示的方式将游戏展现出来。游戏中玩家通过四个按键控制蛇的身体上下左右移动来吃屏幕中出现的苹果,苹果是随机出现的。当蛇吃的一个苹果时,蛇身体变长一个单位同时会有另一个苹果出现。如果蛇头撞墙或者撞到自己身体,则游戏失败。 所要设计贪吃蛇游戏基于Cyclone III系列EP3C5E114C8N的FPGA芯片为硬件,采用Verilog HDL语言编写程序。在本设计中,有个8按键,分别是上、下、左、右、复位和游戏开始,暂停与继续按键。它们都是输入信号,输出是VGA,在电脑屏幕实现VGA显示字符,游戏画面 第3章 贪吃蛇游戏设计 3.1 VGA显示模块设计 显示器扫描方式分为逐行扫描和隔行扫描:逐行扫描是扫描从屏幕左上角一点开始,从左像右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,CRT对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有的行,形成一帧,用场同步信号进行场同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。   完成一行扫描的时间称为水平扫描时间,其倒数称为行频率;完成一帧(整屏)扫描的时间称为垂直扫描时间,其倒数称为场频率,即刷新一屏的频率,常见的有60Hz,75Hz等等。标准的VGA显示的场频60Hz,行频31.5KHz。 行场消隐信号:是针对老式显像管的成像扫描电路而
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值