基于FPGA的贪吃蛇游戏设计(3)VGA显示&游戏状态控制模块的子模块b:start_end_vga和对应的ROM

1.start_end_vga模块介绍

除了上一篇博客的paly模块,游戏还需要设置start、end、speed模块,状态转移图如下:
在这里插入图片描述
前段的h_cnt、v_cnt、vga_hs、vga_vs信号跟前面play_vga的一样,不再赘述。

因为start和end和speed的逻辑是大致一致的,都是在使能信号到来时读出一张mif图片,区别只在于要在VGA上显示的图片内容,这里我们调用三个ROM,将三者的不同图片存在各自的ROM里,分别设计各自的ROM_top模块,即可重复引用该start_end_vga模块用作start、end和speed了。如下图
在这里插入图片描述

2.ROM图片生成与读取

为了减少读取图片的数据量,这里只用一张100*100分辨率的图片即可,意思意思就行了。
故有10000个像素点的数据,rom 的位宽设置为 8,深度设置为 10000。
在这里插入图片描述
以rom_start_top为例:
在这里插入图片描述
需要注意的是, rom 设置时,勾选了‘q’ output port,所以== rom 的数据输出会延迟2拍==,这个地方要注意,自己可以仿真看看现象!!
在这里插入图片描述
可以看出:
rom_rd_en 比 Hor_Addr_Time 区域提前了 3 个时钟周期,所以rom_rd_data 比Hor_Addr_Time 区域只提前了 1 个时钟周期(rom 输出延时 2 拍)。
然后 vga_r/vga_g/vga_b 获取 rom_rd_data 数据需要消耗一拍,所以最终vga_r/vga_g/vga_b 数据与 Hor_Addr_Time 区域正好对齐。
fpga 代码编写最重要的就是时序对齐,要精确到一个时钟周期!!!

rom_rd_en生成

//在显示屏上正中间显示100*100的图像
//rom读出数据有两拍延时,再加上rom_rd_en对start_area打了一拍,所以需要提前3拍
//v_cnt是多周期的,所以不用提前  
assign  rom_rd_en   =   (h_cnt >= Hor_Start - 3 + 270 && h_cnt < Hor_Start - 3 + 370 && v_cnt >= Ver_Start + 190 && v_cnt < Ver_Start + 290);

//start_area_r
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        rom_rd_en_r <=  2'b0;
    end
    else begin
        rom_rd_en_r <=  {rom_rd_en_r[0],rom_rd_en};
    end
end

图片mif文件数据读出,数据拼接输出方式到后面mif文件生成的部分再细说

//vga_r,vga_g,vga_b
always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        vga_r   <=  5'd0;
        vga_g   <=  6'd0;
        vga_b   <=  5'd0;
    end
    else if(rom_rd_en_r[1])begin
        vga_r   <=  {rom_rd_data[7:5],2'h0};//高3位+两个0
        vga_g   <=  {rom_rd_data[4:2],3'h0};
        vga_b   <=  {rom_rd_data[1:0],3'h0};
    end
    else begin
        vga_r   <=  5'd0;
        vga_g   <=  6'd0;
        vga_b   <=  5'd0;
    end
end

3. ROM_top模块

只要根据 rom_rd_en 信号产生 rom_addr并且例化 rom ip 即可。

//依次读出1byte数据,读出数据量计数cnt
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt <= 0;
    end
    else if(add_cnt)begin
        if(end_cnt)
            cnt <= 0;
        else
            cnt <= cnt + 1;
    end
end

assign  add_cnt     =       rom_rd_en;       
assign  end_cnt     =       add_cnt && cnt == ADDR_END-1;   

assign  rom_addr    =       cnt;



//rom
rom_start	rom_start_inst(
        .address                (rom_addr                       ),
        .clock                  (clk                            ),
        .q                      (rom_rd_data                    )
);

此外
rom_end和相应的rom_end_top、start_end_vga_inst_end,
rom_speed和相应的rom_speed_top、start_end_vga_inst_speed都是一样的方法去设计,只是存入的mif图片不同
在这里插入图片描述
下一篇博客介绍如何设置图片分辨率,以及如何生成图片的mif文件并导入rom中

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
现在小孩玩的最多的玩具就是手机了,不禁感慨,我们小时候都是咋过来的,有个游戏机,可以玩个贪吃、俄罗斯方块就不错了。可以自己设计贪吃游戏玩玩,重温童年的经典,也让现在小孩知道,珍惜当下美好的生活。 功能实现说明: 此游戏较为简单,没有设置多余障碍物,只设置了四周的墙壁,贪食所吃的苹果随机刷新,当装上墙壁或者自己的身体,游戏结束。 此游戏使用五个按键,利用Basys3上的按钮,四个方向键,一个重新开始游戏按钮,一个操作开关。使用7位数码管进行计分,每吃到一个苹果分数+1。使用VGA显示游戏界面。 DIY动手指南: Step1:材料准备 硬件: Basys3开发板 VGA连接线及VGA显示器一台 软件平台:Vivado2016.4 Step2:系统框架 系统主要由6部分组成,分别是按键输入模块控制模块、数据路径模块、随机生成 模块VGA显示模块和数码管显示模块。 Step3:程序设计 上图是本程序的RTL级视图。 下面我们对于各个模块进行分析。 1.键盘扫描 我们一共设置了五个按键,分别执行up,down,left,right,restart这五个功能。 以up_key_press为例,介绍消抖的算法。 在每个时钟高电平时并行执行以下两条语句 up_key_press&lt;=0; up_key_last&lt;=0; 当有按键按下时,每100ms(cnt=5_0000) last=up,last输出比up滞后一个周期,若up_key_last==0&amp;&amp;up==1,则说明按键按下,press输出置1。 2.控制模块 当打开开始开关并按下任意一个方向键时,游戏开始,当游戏结束时闪烁5下,重新开始游戏。 3.数据路径模块 cube_x,cube_y表示一整条身体各节的格坐标。is_exist有16位,即体最长为16*1格,每一位对应一个格,1为该格显示,0则不显示(图中虚框)。每吃下一个苹果长度增加1,相应exist位置变为1。 每次移动,对应的cube[x] = cube[x+1],即后一位的身会移动到前一位的位置,头根据按下的按钮来判断是撞到了墙,还是撞到了身,还是移动到了下一个位置。 当头和苹果重合时,生成一个增加身长的信号,并在计数器上+1。 4.随机生成模块 采用伪随机数的产生方法,比较笨拙。 每个时钟周期random_num都在变,而我们吃下苹果的时刻却因走法、按键的时间等有所不同,所以不同时刻吃下苹果后下一个苹果出现的地方近似随机~ 5.VGA显示模块 使用640*480分辨率,需要分频为25MHz的时钟信号。 6.数码管显示模块 当有增长身长信号产生时,分数也对应增加,数码管动态扫描显示分数。 Step4:演示

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值