您的位置:首页 > 其它

FPGA综合系统设计(三):贪吃蛇游戏(键盘+VGA)

2017-07-14 12:10 555 查看
  “FPGA综合系统设计”是博主新开的一个系列,主要讲述在设计一个完整的系统时采用的方法。博主计划在后面有时间的时候再开一个“FPGA基础设计”的系列,专门讲述FPGA设计一些单独模块的方法,如IIC协议、SPI协议、DDR读写等。

本文是综合系统设计的第一篇,选择的题材是“贪吃蛇游戏”,使用键盘上的WASD键控制小蛇运动,VGA显示屏显示游戏状况和游戏分数。

环境与设备

  Vivado 2017.1

  Xilinx Artix-7系列FPGA芯片(EGO1开发板)

  MATLAB(或其他可以生成coe文件的工具)

  USB键盘和VGA显示屏(或其它接口显示屏+转接线)

系统设计

  仔细分析一下整个系统我们需要哪些模块。为了完成人机交互我们需要键盘检测模块和VGA显示模块。而VGA通常需要一个特定的扫描时钟,因此添加一个时钟管理模块来生成VGA所需的时钟。显示分数最好的方法是把每个数字存储到ROM中供程序调用,这里使用一个单口ROM模块。

  除了上述基本的模块外,再拆解一下游戏本身。一个游戏包括开始、正在游戏、死亡、重新开始四种状态,因此建立一个游戏控制模块来管理游戏状态之间的转换。需要设置开始游戏时小蛇的长度是多少以及在屏幕的哪个位置、判断小蛇的运动方向、运动时是否会撞到墙或撞到自己的身体等,因此建立一个运动控制模块。另外在蛇吃到苹果时随机生成一个新的苹果,建立一个苹果生成模块。

  以上几个游戏模块用来管理游戏方式,最后再添加一个VGA显示控制模块,负责VGA的显示驱动,根据游戏状况和分数进行相应的显示。

  下图就是整体的模块划分以及各自模块设计的主要功能,还有各个模块之间的主要联系,我们在写程序时只要按照下图的设计思路来编写即可。我分别介绍一下每个模块的关键设计方法。



游戏控制模块

  这个模块涉及到游戏的四种状态,显然用状态机的方式进行控制更为方便。在设计状态机时要考虑好每个状态之间的转换条件,以及每个状态时的输出。游戏在一开始会停留在“开始状态”,转移到下一个状态的条件就是检测到有按键按下。此时进入“正在游戏”状态,当检测到“撞墙”和“撞身体”事件发生时,便跳入到“死亡”状态。在“死亡”状态下,设定一个计数器来让死亡标志反转几次,这个输出主要是提供给VGA显示模块,它可以根据死亡标志的反转来让小蛇闪烁,从而提示玩家游戏已结束。当闪烁结束后,便可以跳转到“重新开始”状态。

运动控制模块

  我们可以考虑将整个屏幕划分为很多个小方格,一个小方格就是一种游戏元素–墙、头、身、背景、苹果。这样控制小蛇的运动其实就是控制小蛇在方格间移动的情况。

  该模块应该完成按键的检测,按键检测要注意的问题是小蛇在向右运动时,它下一个运动状态只能是向上或向下;当小蛇在向下运动时,它下一个运动状态只能是向右或向左,其余情况类似。按键检测应该做好对小蛇运动情况的判断。

  蛇初始状态的设定其实就是在复位期间和“重新开始”游戏状态时选择几个固定的小方格作为蛇身的初始身体。

  撞墙检测,如果把显示屏的最外面一圈小方格作为墙,则当小蛇在墙的附近仍然向墙的方向运动时,即可认为撞墙;装身体检测,这部分其实就是检测小蛇的头部所处的小方格是否与它身体所处的小方格重合,如果重合则表示撞到了自身。我们在玩游戏时发现,小蛇的下一节身体所运动的方向总是上一节身体刚才所处的位置,按照这个思路设计小蛇的运动轨迹即可。

时钟管理模块和ROM存储模块

  这两个模块使用的是Vivado中的IP核。

  Clocking Wizard这个IP核可以将输入时钟设置为指定的频率输出。

  Block Memory Generator这个IP核可以选择单口ROM形式,并指定存储的宽度和深度。ROM中导入的文件应该是coe格式的。我们可以用Windows自带的画图制作出各个数字的图片,用MATLAB读取图片按coe格式写入一个文件即可。使用MATLAB方式较为灵活,网上也有一些生成coe文件的工具,只是使用起来对输入的图片有特殊要求。

苹果生成模块

  这个模块主要是检测小蛇是否已经吃到了苹果,如果吃了就应该产生一个新的苹果。为了让新产生的苹果可以随机产生在显示屏的任意一个位置上,我们可以产生一个随机数列,用这个序列作为苹果的坐标,如果追求完美可以使用M序列、Gold序列等近乎完全随机的序列。我在这里使用的是一个加法器作为随机数,实际效果也很不错了。

VGA显示模块

  VGA的驱动方式其实已经很固定了,需要改变的只是当计数器扫描到屏幕的显示区域时,决定显示什么元素即可。

  我们这里需要显示的有墙壁、蛇头、蛇身、苹果、背景等游戏元素还有分数。在显示区我们对这几个元素进行判断,然后输出不同的颜色从而构成游戏画面。分数需要调用事先存储好的数字ROM,所有的ROM接一个地址信号,不同的只是数据信号。根据分数情况决定从存储哪一个数据的ROM中提取数据即可。







  博主可提供Vivado 2017.1下的完整工程,代码都有详细注释,需要的请联系godwar_liuqi@outlook.com索取。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  fpga 游戏