这是2011下半年我在这边第一年的一个期末课程项目。课程是嵌入式系统。我利用一个FPGA开发板做了一个VGA视频输出的弹球游戏。自认为做得不错,课程拿了A+,也因为这个作业通过了暑期实习面试。现在拿出来分享。

平台:

该课程使用的是Sparten 3e starter board开发板。开发板信息及购买地址:http://www.digilentinc.com/Products/Detail.cfm?NavTop=2&NavSub=423&Prod=S3EBOARD&CFID=11126446&CFTOKEN=5eb3071295cc867b-F8FA2FD5-5056-0201-02D18B76539FBE9D

实现效果:

在这个开发板上我做了个弹球游戏。该弹球游戏有上下两个挡板互相弹球,一个挡板由板上按键控制,另一个挡板由一个PS/2键盘控制,视频通过开发板的VGA口输出到普通显示器上,同时板上液晶显示器显示比分。

实现思路:

PS/2接口,按键,液晶显示接口都是使用的现成的IP。

VGA显示接口是自己通过VHDL写的。

主程序是Xilinx Sparten 3e FPGA的Microblaze内核作为处理器上C语言编程实现的。软件编程使用了qp-nano状态机。(qp-nano:http://www.state-machine.com/qp/qpn/)

主要难点是VGA接口和软件实现。

VGA接口主要要弄清楚信号的时序。这个在开发板手册上有说明。我使用的是640x480 @60hz的分辨率,相应的信号模式间下图:

其次要显示图片就得有显存。显存我用的是FPGA内部的BRAM,速度快但容量小。由于Microblaze微处理器需要32KB的内存,我只剩下8KB的显存可用。由于BRAM一个字节还预留了个校验位,所以实际上可用空间是8K×9bit。一个像素只要3个bit,显示8种颜色足以。最后有效的显示区域为128×192。这个分辨率对于这个小游戏来说足够了,要知道gameboy只有160x144的分辨率,但照样有很多伟大的游戏。

还有个难点就是和软件的接口问题。Microblaze使用的是PLB接口。大部分接口部分的VHDL Xilinx已经帮你写好了。我只弄了两个寄存器,一个赋予要写的地址像素信息,一个控制写入。

软件相比VHDL来说就简单了许多,只要对上面设置好的寄存器写像素信息即可。我当时使用了个状态机控制游戏,具体怎么做忘了,实现起来应该不难。

实际效果:

实际运行效果我弄了个视频,如下:

(视频中那个人是我的partner,他主要负责了PS2键盘的控制部分,工作量跟我比小了很多)

frameborder="0" width="640" height="498" src="http://v.qq.com/iframe/player.html?vid=i0150qodz1d&tiny=0&auto=0" allowfullscreen="">

源代码:

源代码可以在我的GitHub里找到:

https://github.com/shallen320/Ping_pong_Sparten3e

报告:

最后附上我的课程报告。全英文的不翻译了,大家凑合看吧

VGA PingPong Game


Objective:

The goal of the project is to build a video game device on the Xilinx Spartan 3E Starter Board. In order to achieve this,we implement a VGA and PS/2 keyboard interface as the output and input of the game. Xilinx doesn’t provide any VGA interface in EDK, we make our own using VHDL. The PS/2 interface is ready made by Xilinx in EDK so we can directly use it.

The game is a 2 players game that one play versus another. Each player controls a paddle to bounce the ball to its rival.If the ball is missed by either of the player, he or she loses one point. The player who loses 3 points loses the game.

We have a VGA monitor as the output to display the game graphic with a resolution of 128*192. The on board LCD screen displays the scores and shows who wins.

We use the on board buttons and keyboard separately to control the two paddles because we find that the PS/2 interface cannot recognize two key at the same time. On board buttons West and East control the blue paddle. The keyboard A and S key control the green paddle. If the space key on the key board is pressed, the blue paddle emits the ball and starts the game.

VGAmodule

The block diagram of the VGA design is as follows:

Vga_sync:

This module is to generate the synchronizing signals VGA_HSYNC & VGA_VSYNC and outputs RGB color signalsVGA_RED, VGA_GREEN, VGA_BLUE.

The output resolution of the VGA signal is 640*480 @ 60Hz. The timing of VGA_HSYNC and VGA_VSYNC is specified in the following form:

We use a 25Mhz clock to drive the module,each period corresponds to each pixel. During the 480 lines and 640 cycles each line, the RGB signals have valid output, thus giving colors to pixels on the monitor.

The essence of the module is two counters,one counts the number of pixels per line, and one counts lines per frame. During the RGB valid time, the address of display memory is generated according to the count number thus RGB signals can be read from the memory.

The variable ‘h_count’ is the number of pixels in a line, and ‘v_count’ is number of lines in a frame. ‘Addr’ is the current reading address of frame buffer. Since one address stores the RGB signal of three pixels (explained below), we have another variable ‘remain’ indicates the number of current pixel, can only be 0, 1 or 2. Variable ‘pix’ is the current number of pixel in a frame.

Following is a screen shot of our simulation result.

Clock:

The clock module is a clock divider todived the input 50Mhz clock signal to 25Mhz to drive the vga_sync.

Vga_ram:

This is the display memory. We use the remaining on chip Bram as the memory. Sparten3E has 20 blocks of Bram while Microblaze uses the 16 of them as a 32KB internal memory, so we can only use the 4 blocks left. Each block has a 2K * 9bit storage, so in total that serves 8K * 9bit storage. Each pixel need 3 bit space to store RGB value, so we can store 24K pixels, so we make the display area to 128*192.

The vga_ram is a dual port ram, with one input, one clock, and two outputs. One output is connected to vga_sync module to provide the in storage RGB signal, the other output is sent to DMA module and is used to calculated new data to write with. For example if the content of 0x24 is 001110101, and we need to change the second pixel from color yellow to color red, so DMA will need to read 0x24’s content 001110101 and change the second pixel to 100 and write 001100101 back to 0x24 in the vga_ram.

DMA:

This module connects the microblaze PLB bus to VGA for microblaze to write pixel signal to vga_ram. We implement tworegisters to achieve the functionality, their relative address is 0x0 and 0x4 and both 32 bits wide but only few bits are writable.

Pixel Register: VGA_base_address+0x0:

Bit[29 30 31]: RGB signal. Bit 29 is valueof red, bit 30 is green, bit 31 is blue. Each value is either 1 or 0, togetherone pixel can have 8 different colors.

Bit[27 28]: This two bits specifies whichpixel the RGB value give to. Each address corresponds to a 9 bit value, whichstores 3 pixel, if bit[27 28] is “00”, it points to the first pixel; “01” thesecond; “10”the third. If it is “11” that will clear the 9bit to all zero,which can be utilized when clear the screen.

Bit[14:26]: This area specify the addressof vga_ram. It can reach 8K address, together with NUM area, the register can reach every 24K pixel. The ADDR bits are always connected to the one of address port of vga_ram.

Other bits in the register are reserved.

Write Control Register:VGA_base_address+0x4:

Bit[31]: If this bit is written with 1, thecontent of Pixel Register will be written into vga_ram. For example if the content of Pixel Register is 1010001001001 01 101, when bit[31] of Write Control Register is written 1, the DMA will make the 2nd pixel in addr1010001001001 to be magenta. If the writing operation is complete, the bit[31]will be cleared to 0 automatically.

Bit[30] is read only, which reflex whetherthe writing operation is complete. If it is busy, the bit will be 0, otherwisethe bit is 1 indicating ready for another writing operation.

Other bits in the register are reserved.

We use a finite state machine to implemen tthe design. The writing process consists of 4 state, st1_read, st2_gen,st3_write, st0_null. The default sate is st0_null, with a low ‘wea’ and highbit[30]. When the bit[31] of write control register becomes 1, the statemachine starts and goes into the first state st1_read. At st1_read, the content of vga_ram at the writing address is read, bit[30] is asserted low and clearthe bit[31], then it goes to st2_gen, in which state the data to written withis generated. After st2_gen, st3_write is the state to write vga_ram with ahigh ‘wea’ signal, which is the write enable, to vga_ram. After st3_write, thestate machine change to st0_null state and bit[30] is asserted high again.

In the previous example, the data 001110101 at addr 0x24 is read at st1_read, and in st2_gen, we generate the new data 001100101 as we want to change the second pixel to red. In st3_wirte, we assert the write enable signal ‘wea’ to high to write new data to 0x24 and de-assertit in st0_null with a bit[30] to be 1 again.

The following screen shot is from our simulation result. In this simulation, the content of pixel register is 0x00aa0aa0 which is to change the first pixel from white to black at addr 0x1055.

PS/2 interface

In our project we just use PS/2 interface in the XPS, and build the code based on that. The PS2 protocol consists of host-to-device and device-to-host communication. Since we just need to read the keyboard button, we just need device-to-host communication. In the project we use polling to implement this. When you press one button, keyboard writes the data into receive data register .RXx_Full_Status flag in the status register is set when the data packet is received by the Portx SIE and is waiting for the host to read this data packet. XPs2_Recv function can only receive one byte and store it in the buffer to wait for the host to read it.

Graphic:

By writing the two registers at addrXPAR_VGA_0_BASEADDR+0x0 and XPAR_VGA_0_BASEADDR+0x4 we can draw our gamegraphic interface pixel by pixel. Below is an example of the function to draw pixels

void VGA_write_coord(int x, int y, int color){      //VGA write coordinatesint pixel, remain, addr, data;pixel = x + y*128;remain = pixel%3;addr = pixel/3;data = (addr<<5) + (remain<<3) + color;      //calculate the data to writeVGA_mWriteReg(XPAR_VGA_0_BASEADDR, 0x0, data);     // VGA_mWriteReg(XPAR_VGA_0_BASEADDR, 0x4, 0x1);        //write
}

Ball coordinates calculation

Since we still cannot get the floatpoint calculation to work on microblaze, the coordinates of the ball are all calculated in integers. The basic idea is to determine the path of ball using two point, original point and destination point

Below is the structure of the ball:

typedef struct ball_tag{int x;      //current x coordinateint y;        //current y coordinateint x_d;  // x coordinate of destine pointint y_d;    // y coordinate of destin pointint x_o; // x coordinate of original pointint y_o;   // y coordinate of original pointint q;     // q=m>n?m/n:n/mint r;       // q=m>n?m%n:m%nint a;       // a=(q-r)/rint b;      // b=(q-r)%rint m;      //m=abs(x_d-x_o)int n;      //n=abs(y_d-y_o)
}ball;

The q,r,a,b,m,n are parameters to helpcalculate the path

Below is the code sample for ball to move at the direction with increasing y and increasing z;

if(bal->n>bal->m){
bal->y++;dif=bal->y-bal->y_o;if(bal->r==0)bal->x=bal->x_o+dif/bal->q;else {del=(dif-((dif+1)/(bal->a+1)))/bal->q;bal->x=bal->x_o+del;}}
else if(bal->n<bal->m){bal->x++;dif=bal->x-bal->x_o;if(bal->r==0)bal->y=bal->y_o+dif/bal->q;else {del=(dif-((dif+1)/(bal->a+1)))/bal->q;bal->y=bal->y_o+del;}}else {          // the angle here is 45 degreebal->x++;bal->y++;
}

FSM in QP-nano

We only usetwo state in the QP-nano(code size limitation), and one is game_preset stateand another is game_ongoing state. In game_preset state we need to draw theball and draw paddle and enable to player to move the paddle with ball without firingthe ball. Once the space is pressed the game begins and transit to the game_on going state,which involves many events just as shown below in the FSM

Then we use LCD to present the mark andshow who is the winner.

Difficulties

When I imported the HDL design into the Xilinx Plat form Studio Project, I found that it did notwork as I expected, the pixels I write in software went all black, and the three pixels under the same address became black together. I realized that itis a problem of writing vga_ram, that data could not be written properly,instead, they are all written zero. Since it is really difficult to simulateperipheral design with the PLB bus, I had a really hard time tried to find out what went wrong. Then I realized that I can convert the peripheral into a FPGA project with the similar PLB peripheral functionality and to simulate it as aFPGA project. It still took me three days to find the problem becauseeverything behaved correctly in the waveform simulation. Finally I found outthe problem is that the data signal becomes invalid simultaneously with ‘wea’signal became 0 from 1. Then I prolonged the data signal hold time and the problem finally resolved.

For the PS/2 interface, at first we want to use interrupt mode to read the scan code from the keyboard, because in interrupt mode XPs2_Recv can receive data and interrupt handler will continue receive data and store it in buffer. You can define the buffer size as your will. But we can only write into buffer withnumber of bytes equals to the buffer size and cannot clear the buffer after thehost reads that. In this case, the host cannot response even we press morebuttons.

Anotherdifficulty is to calculate the ball’s path without using float point, but afterfew hours thinking, I found a good way to approximate the path to a smooth skewline with integers.

To be improved

Limited by theBram, the VGA can only display a small area at the left up corner at thescreen. Given more time, actually we can move the display area to the center ofthe screen and zoom in to a double size.

It takes us three weeks to finish the VGA peripheral and thus we do not have enough time to polish the software game. There are still many bugs and the features are limited,for example the ball’s speed is too slow and it is too easy not to miss theball. Besides my original intention is to add a title screen to the game and add a single player mode, thus players can select 1 player or 2 players at the title screen. Another reason we cannot add this feature is that we are runningout of the 32KB ram memory. I think this can be solved if we make our codeshorter or to store the code in SDRam

Another problem is that the PS/2 keyboard performs not so well in the polling mode. It is really slow to correspond to a key pressed down. If we have time, we will change it to interrupt mode which may achieve better performance.

基于FPGA的VGA视频弹球游戏相关推荐

  1. imut FPGA课设 基于FPGA的VGA弹球游戏设计 *秋昊

    写在前面的话: 本文主要呈现了一篇IMUT的FPGA课设报告. 课设报告内容(word版),视频演示,程序源码,专业创新实践简介,专业创新实践指导书均已放入下面的百度云链接中,也不大,总共不到20MB ...

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

    基于FPGA的VGA显示对贪吃蛇游戏的设计 摘要 目前,电子数码产品已经进入了人生活的方方面面,而大多数电子产品都依靠显示屏来传递信息,由此可见用电路对显示屏进行控制的研究有很大的实用价值和市场需求. ...

  3. 基于FPGA的VGA/LCD显示控制器设计(中)

    今天给大侠带来基于FPGA的VGA/LCD显示控制器设计,由于篇幅较长,分三篇.今天带来第二篇,中篇,VGA 显示原理以及VGA/LCD 显示控制器的基本框架,话不多说,上货. 之前也有图像处理以及V ...

  4. 基于FPGA的VGA接口设计(三)

    关于VGA系列文章的所有链接: 基于FPGA的VGA接口设计(一) 基于FPGA的VGA接口设计(二) 基于FPGA的VGA接口设计(三) 结篇   在之前的文章中介绍了有关VGA的扫描方式.行场同步 ...

  5. 基于FPGA的VGA协议实现

    基于FPGA的VGA协议实现 一.VGA简述 1.VCG接口 2.原理 3.显示器扫描 4.VGA时序分析 5.VGA时钟计算 6.不同分辨率的VGA参数 二.显示彩条 1.色彩原理 2.彩条输出 三 ...

  6. 基于FPGA的高性能视频硬件编码器

    基于高性能视频编解码技术的解决方案,可以实现高清画质更快的压缩速度.更少的带宽消耗,在满足用户高清画质要求的前提下有效降低运营成本.阿里巴巴达摩院XG实验室,高级算法专家杨名远在LiveVideoSt ...

  7. 基于FPGA的VGA控制输出显示(使用GM7123高清视频编码芯片)

    目录 一.VGA原理 1.VGA接口简介 2.VGA显示原理 二.VGA模块 三.VGA接口设计 1.设计要求 2.设计实现 3.实现结果 四.总结 一.VGA原理 1.VGA接口简介 VGA的全称是 ...

  8. 基于FPGA的VGA显示设计(一)

    前言 FPGA主要运用于芯片验证.通信.图像处理.显示VGA接口的显示器是最基本的要求了. 原理 首先需要了解 : (1)VGA接口协议:VGA端子_维基百科 .VGA视频传输标准_百度 引脚1 RE ...

  9. 基于FPGA的VGA时序分析

    前言 FPGA主要运用于芯片验证.通信.图像处理.显示VGA接口的显示器是最基本的要求了. 原理 首先需要了解 : (1)VGA接口协议:VGA端子_维基百科 .VGA视频传输标准_百度 引脚1 RE ...

最新文章

  1. 2020年Java程序员不得不学习的10大技术
  2. 想让进程后台运行,试试Linux的nohup命令,3分钟学会。
  3. python操作gif
  4. js截取超链接后参数
  5. wms地图绘制工具_GeoServer地图开发解决方案(四):发布Web地图服务(WMS)篇
  6. java初学编程题及答案_Java 入门编程题答案记录(记录)
  7. 【CF813F】Bipartite Checking(线段树分治+可删除并查集)
  8. apm固定翼调试方法
  9. html浏览器的区别是什么意思,不同浏览器对css的识别有区别吗?
  10. 排行榜上用C++写局域网聊天程序
  11. Docker安装ActiveMQ(docker-compose.yml)
  12. nginx redis mysql_Nginx + Lua + Kafka + Redis + Mysql
  13. 查看数值类型python_Python数据科学实践 | 数据类型
  14. iOS开发之错误码国际化
  15. linux强制获得锁,Linux中的两种文件锁——协同锁与强制锁
  16. ajax提交图片流,img显示
  17. bugku 啊哒 有趣的表情包
  18. jerryscript有关“error: inlining failed in call to always_inline”问题的解决
  19. 论文阅读:Graph Contrastive Learning with Augmentations
  20. 国产Google地球如何下载2021版谷歌高清卫星地图?

热门文章

  1. 一款尝试“去区块链”化的UGC+爬塔类链游
  2. 互联网/移动互联网小团队创业 第二集 汪华
  3. python基础篇——for语句
  4. 【Python数据分析与处理 实训03】 --- 酒类消费信息分析(数据分组聚合 group().agg()应用)
  5. 计算机开机过程 南桥,详解电脑开机过程
  6. 计算机室档案建设方案,档案室建设方案.doc
  7. java中qq好友怎么加,手机qq怎么加好友?
  8. step by step 3000 3_实验3:Zigbee事件处理机制 - 新兵训练营(5)
  9. 关于sched_yield()主动出让CPU的占有权
  10. 物联网商机巨大 联发科再不切入未来将受制于人