找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1972|回复: 0
收起左侧

FPGA实现贪吃蛇游戏源程序 VGA显示模块 QuartusⅡ9.1代码

[复制链接]
ID:1007214 发表于 2022-3-5 20:12 | 显示全部楼层 |阅读模式
VGA原理简介
2.1.1 VGA定义
VGA即视频图像阵列的意思,时IBM公司在1987年随ps/2一起推出的一种视频传输标准,具有分辨率高、显示速度快、颜色丰富等优点,在彩色显示领域得到了广泛的应用。VGA显示器时阴极射线管显示器,通过VGA显示器接口和计算机内部的显卡相连。
2.1.2 VGA规格参数
实验用到的显示器规格为640*480,具体参数如下:
行同步:
  
前沿
  
16
后沿
48
行同步头
96
行图像
640
行周期
800
场同步:
  
前沿
  
10
后沿
33
场同步头
2
场图像
480
场周期
525
2.1.3 彩色原理
人眼是根据所看见光的波长来识别颜色的,这些颜色是根据三种基色按照不同的比例相互混合得到的,三种基本光色为红、绿、蓝三原色光,当这三种光以不同的颜色比例混合,得到了不同的颜色(比如相同比例得到白色)。
在VGA显示器上,R、G、B三种基色分别接到电子枪的阳极,通过阴极发射电子,然后在电场的作用下,电子轰击荧光粉层,荧光粉层发出不同强度的三种颜色光,根据空间混色法将三个基色光同时照射同一表面相邻很近的三个点上进行混色,可以产生不同的颜色,利用人眼在超过一定距离后分辨率下降的原理,可以得到较为清晰的颜色。
对于本实验,只能显示八种颜色,就是RGB分别用一位二进制数表示,从而显示8中颜色。
2.1.4 消隐脉冲和同步脉冲
同步脉冲:场同步和行同步
消隐脉冲:场消隐和行消隐
计算机显示器采用逐行扫描显示,从屏幕的左上方开始,按照从左到右、从上到下的顺序进行扫描。每扫描完一行,行同步信号进行行同步,会到下一行的起点进行扫描。扫描完所有行后,即显示了整个屏幕,用场同步信号进行场同步,并且扫描回到屏幕左上方,进行下一帧的刷新。
当电子枪从某一行的末尾转到下一行的开头时,或者从屏幕最下面一行最后一个像素转到左上角第一个像素位置时,都需要一定的时间,这期间不需要发射电子,否则会干扰画面。所以行同步场和同步信号要在需要显示区域驱动显示器显示,通过对行同步和场同步的设置,实现行消隐和场消隐。
2.1.5 VGA显示原理
对于640*480*60hz的显示器,工业标准的时钟频率为25.175hz,行周期为800个周期,场周期为525个周期,这些周期数也就对应着时间。
计算机显示器采用逐行扫描显示,从屏幕的左上方开始,按照从左到右、从上到下的顺序进行扫描。每扫描完一行,行同步信号进行行同步,会到下一行的起点进行扫描。扫描完所有行后,即显示了整个屏幕,用场同步信号进行场同步,并且扫描回到屏幕左上方,进行下一帧的刷新。
每行800个时钟脉冲,前640个时钟频率对应前640个点,在不同的时间输出不同的颜色,在640到800时钟频率RGB输出低电平,行计数器为648时,场计数器加一或清零,行计数器为656到752时,行同步信号为低电平,其他时刻为高电平;场计数器为490到492时,场同步信号为低电平,其他时刻为高电平。因为整个过程是循环进行的,从而显示正常。

3 信号发生器设计
3.1软件环境介绍
   本实验使用的软件是QuartusⅡ9.1。QuartusⅡ 是Altera公司为FPGA/CPLD芯片设计的集成化专用开发工具,在QuartusⅡ上可以设计输入、HDL综合、布线布局、仿真、下载和硬件测试等整个设计流程,功能强大,被广泛使用。
在早期, Max+plusⅡ 是Altera公司的开发工具,现在已经被QuartusⅡ代替。并且Max+plusⅡ已经不再支持Altera公司的新器件,同时,QuartusⅡ也放弃了对老器件的支持。QuartusⅡ具有Max+plusⅡ界面,上手简单,界面友好、使用便捷。
Altera Quartus Ⅱ提供了完整的设计环境,设计工具完全支持VHDL、Verilog和AHDL设计流程。QuartusⅡ也可以使用第三方的综合工具,并且可以直接调用这些综合工具;同时QuartusⅡ也支持第三方的仿真工具,如Modelism;QuartusⅡ与Matlab和DSP Builder结合,也可以进行DSP系统开发。
除此之外,Quartus还包含许多LPM模块,在SOPC设计中被大量使用,也可以在普通设计文件一起使用。例如DSP模块、PLL、各类片上存储器等。
QuartusⅡ还支持第三方EDIF文件输入,并且提供了很多EDA软件接口,支持层次化设计,解决了原理图和HDL混合输入问题。
3.4 VGA
贪吃蛇游戏显示设计
3.4.1模块功能
VGA显示模块:主要实现VGA的显示,hcnt,vcnt,hs,vs的设置。
静态图片模块:这里显示在贪吃蛇撞身显示the end静态图案。
游戏背景模块:贪吃蛇边界设计,设计了四堵墙,在显示器显示,在墙外有自己的名字英文缩写DLH显示。
游戏控制模块:贪吃蛇蛇身移动及运动方向处理,蛇身撞身处理,蛇身吃到后自增处理和蛇身上限处理,随机出现的食物方块处理。这一模块最为重要,将会重点进行说明。
连线模块:将这些模块连到一起,使最终下载到显示器上的是可以显示正确的图案。
3.4.2贪吃蛇设计
VGA显示模块:
1)分频模块
这里通过二分频,clk为输入50mhz的频率,在clk上升沿对clk25取反,就得到二分频的clk25,频率为25mhz:

always@(posedgeclk or negedge rst)
              if(!rst) clk_25M=0;
              else clk_25M=~clk_25M;
2)显示模块
设置了行计数器和场计数器hcnt、vcnt,行信号和场信号hs、vs。
按照先通过行同步头/场同步头,再通过后沿,再通过显示区域,再到前沿完成一整个周期来计算:
hs行信号hcnt>=639+16并且hcnt<639+16+96输出为0,其他输出1;
vs场信号在vcnt>=479+10并且vcnt<479+10+2输出为0,其他输出1。
  设置了坐标位置,xpos和ypos,分别为hcnt-96-48和vcnt-2-33用于后面位置的表示。
  当hcnt和vcnt在显示区域输出rgb_sig, rgb_sig与后面的相对应。
always@(posedgeclk_25M or negedge rst) begin
              if(!rst) begin
                     h_cnt<=0;
                     v_cnt<=0;
              end
              else begin
                     if(h_cnt==(H_CNT_MAX-1))begin
                            h_cnt<=0;
                            if(v_cnt==(V_CNT_MAX-1))v_cnt<=0;
                            elsev_cnt<=v_cnt+10'd1;
                     end
                     else h_cnt<=h_cnt+10'd1;
              end
       end

静态图片和游戏背景模块
        设置了the end和DLH静态图案,设置了四堵墙,这些设置方法基本相同,都是通过对hcnt和vcnt的范围进行设置,这里可以直接使用xpos和ypos,在规定的范围内填充RGB色彩即可。
例如对我的名字缩写而言,d的设置包括两横两竖,对xpos和ypos进行设置即可:
左右为10上下为20:
assign d1 = ((vga_xpos > 40 ) &&(vga_xpos < 50 ) && (vga_ypos > 20 ) && (vga_ypos < 40) );
左右为10上下为40:
      assignd2 = ((vga_xpos > 70 ) && (vga_xpos < 80 ) && (vga_ypos> 0 ) && (vga_ypos < 40 ) );
左右为40上下为5:
      assignd3 = ((vga_xpos > 40 ) && (vga_xpos <80 ) && (vga_ypos> 20 ) && (vga_ypos < 25 ) );
左右为40上下为5:
      assignd4 = ((vga_xpos > 40 ) && (vga_xpos < 80 ) && (vga_ypos> 35 ) && (vga_ypos < 40 ) );
这样就得到了小写d,通过这样一直将背景和四堵墙的显示设置好。对于四堵墙,这里只设置了在显示器中显示,而对四堵墙的边界格挡作用,在游戏控制模块进行说明。
游戏控制模块:
1时钟控制:在时钟上升沿(25mhz频率的时钟),i自增,当i到达摸个数值的时候,i清零,同时temp取反,这样在后面的贪吃蛇移动模块,通过在temp上升沿移动,从而可以通过i的最大值来实现对速度的控制,这里设置i为4999999,如果想要更快,只需要慢速度即可。
2)运动模块:
首先设置了四种状态,来标识运动方向,这四个状态和ps/2键盘相连接,来完成对运动的控制。
             if(P_left)
                    state<= left;
             elseif(P_right)
                    state<= right;
             elseif(P_down)
                    state<= down;
             elseif(P_up)
                    state<= up;
我这里设置每个小贪吃蛇由10*10的像素方块组成。设置了两个数组mn,代表左上角坐标,m数组代表左边坐标,n代表上边坐标。
蛇头运动:对于贪吃蛇蛇头运动,通过rst信号对贪吃蛇初始位置进行设定。当贪吃蛇出边界时(我们上面设置的四堵墙就是这里的边界),四堵墙上下左右边界值分别为:60,420,40,600。例如当出左边界时即m[0]<40的时候m【0】=600,实现当出边界时可以从对应边界回来。当未出边界时,与上面的上下左右四种运动标识对应,实现运动(加减10):
if(!rst)
             beginm[0]<=200; n[0]<=200;end
             elseif(m[0] > 600)
                    m[0]<= 40;
             elseif(m[0] < 40)
                    m[0]<= 600;
             elseif( n[0] > 420)
                    n[0]<= 60;
             elseif( n[0] < 60)
                    n[0]<= 420;
             elseif(hit)   
                    beginm[0]<=0; n[0]<=0;the_end=1;end
             else
                    begin
                           case(state)
                                  left: m[0] <= m[0] - 12'd10;
                                  right: m[0] <= m[0] + 12'd10;
                                  down: n[0] <= n[0] + 12'd10;
                                  up:n[0] <= n[0] - 12'd10;
                                  default: m[0] <= m[0]+12'd10 ;
end case;
蛇身运动:每当设运动一次,m[a+1]就会代替m[a]的位置:
for(long_cnt=0; long_cnt<(2**N-1);long_cnt=long_cnt+1) begin   
                                  m[long_cnt+1]<= m[long_cnt];
                                  n[long_cnt+1]<= n[long_cnt];
                           end        
3)撞身模块:当蛇头和蛇身相撞时,即为m[0]=m[a],n[0]=n[a]时,结束游戏显示屏显示the end 界面。
4)食物随机出现:设置一个初始的食物出现位置(300,300),通过吃到食物所用用的时钟时间,来判断下一个食物的位置。
设置了四个信号o,p,o_temp ,p_temp。在时钟上升沿o_temp ,p_temp加10,当吃到才会将o_temp 和p_temp赋值给o,p,实现了根据吃到食物所用的时间变位置(其实是一个伪随机),其中change是用来判断是否吃到的信号,吃到为1,未吃到为0。
if(!rst)begin   
                            p <= 300;//lie
                            o <= 300;//hang
              end
              else if(change)
                     begin
                            p <= p_temp;
                            o <= o_temp;
                     end
              else if(o_temp > 400)
                     o_temp <= 100;
              else if(o_temp <100)
                     o_temp <= 400;
              else if(p_temp > 400)
                     p_temp <= 80;
              else if(p_temp < 80)
                     p_temp <= 400;
              else
                     begin
                            o_temp <= o_temp+ 10;
                            p_temp <= p_temp+ 10;
5)吃食物:当o和p和蛇头坐标,m[0],n[0]对应时吃到食物。吃到食物后相应的蛇身也要增长:

6)贪吃蛇显示:贪吃蛇左上坐标为m[a],n[a],坐标在xpos和ypos的范围内,例如蛇头为m[0] <xpos < m[0] + 10并且n[0] < ypos < n[0] + 10这样就可以在VGA上显示。

连线模块:这里就是将这些模块,设置的信号,连在一起,例如将每个模块设置的颜色和VGA显示模块颜色先对应、贪吃蛇坐标对应行计数器和场计数器等等。

此程序用Cyclone Ⅲ EP3C40Q240C8对应引脚分配图:
51hei.png 51hei.png

上图压缩包代码下载,仅供参考: 基于FPGA的贪吃蛇小游戏(1).7z (6.38 MB, 下载次数: 30)

评分

参与人数 2黑币 +56 收起 理由
外星人11111 + 6
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表