当前位置:   article > 正文

基于FPGA的贪吃蛇游戏设计(2)VGA显示&游戏状态控制模块的子模块a:play_vga_基于正点原子fpga的贪吃蛇游戏设计

基于正点原子fpga的贪吃蛇游戏设计

VGA显示&游戏状态控制模块 game_show
在这里插入图片描述

1. VGA时序分析

VGA 时序的关键信号是行同步信号(HSync)和场同步信号(VSync),共有 6 个参数,分别为

Sync
Back Porch
Left Border(针对行同步信号)/Top Border(针对场同步信号)
Addr Time(数据有效时间,分辨率就是看这个参数)
Right Border(针对行同步信号)/Bottom Border(针对场同步信号)
Front Porch

在这里插入图片描述
VGA 真正显示的区域是 VSync 的 Addr Time 和 HSync 的 Addr Time 同时有效区域(低有效)
在这里插入图片描述
单帧时序图

2.VGA参数设定

在这里插入图片描述
选用 640*480@60Hz 分辨率, 像素时钟频率为 25MHz

`define VGA_640_480_60Hz
//=====================================================================\
// ********** Define Parameter and Internal Signals *************
//=====================================================================/
`ifdef VGA_640_480_60Hz
parameter   Hor_Total_Time  =   800                             ;
parameter   Hor_Addr_Time   =   640                             ;
parameter   Hor_Sync_Time   =   96                              ;
parameter   Hor_Back_Porch  =   40                              ;
parameter   Hor_Left_Border =   8                               ;
parameter   Hor_Start       =   Hor_Sync_Time + Hor_Back_Porch + Hor_Left_Border; 
parameter   Hor_End         =   Hor_Start + Hor_Addr_Time       ;

parameter   Ver_Total_Time  =   525                             ;
parameter   Ver_Addr_Time   =   480                             ;
parameter   Ver_Sync_Time   =   2                               ;
parameter   Ver_Back_Porch  =   25                              ;
parameter   Ver_Top_Border  =   8                               ;
parameter   Ver_Start       =   Ver_Sync_Time + Ver_Back_Porch + Ver_Top_Border; 
parameter   Ver_End         =   Ver_Start + Ver_Addr_Time       ; 
`endif

parameter   Red_Wall        =   16                              ;//边界墙壁厚度
parameter   NONE            =   2'd0                            ;
parameter   HEAD            =   2'd1                            ;
parameter   BODY            =   2'd2 


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

3. Main code

(1)h_cnt&v_cnt行列计数

//h_cnt
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        h_cnt <= 0;
    end
    else if(add_h_cnt)begin
        if(end_h_cnt)
            h_cnt <= 0;
        else
            h_cnt <= h_cnt + 1;
    end
end

assign add_h_cnt     =       1'b1;
assign end_h_cnt     =       add_h_cnt && h_cnt== Hor_Total_Time-1;

//v_cnt
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        v_cnt <= 0;
    end
    else if(add_v_cnt)begin
        if(end_v_cnt)
            v_cnt <= 0;
        else
            v_cnt <= v_cnt + 1;
    end
end

assign add_v_cnt     =       end_h_cnt;
assign end_v_cnt     =       add_v_cnt && v_cnt== Ver_Total_Time-1;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
(2)vga_hs&vga_vs信号产生
//vga_hs
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        vga_hs  <=      1'b0;
    end
    else if(add_h_cnt && h_cnt == Hor_Sync_Time-1)begin
        vga_hs  <=      1'b0;
    end
    else if(end_h_cnt)begin
        vga_hs  <=      1'b1;
    end
end

//vga_vs
always  @(posedge clk or negedge rst_n)begin
    if(rst_n==1'b0)begin
        vga_vs  <=      1'b0;
    end
    else if(add_v_cnt && v_cnt == Ver_Sync_Time-1)begin
        vga_vs  <=      1'b0;
    end
    else if(end_v_cnt)begin
        vga_vs  <=      1'b1;
    end
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
(3)vga显示有效区域设定
//vga显示有效区域,由于vga_r/vga_g/vga_b获取数据需要消耗一拍,所以这里要提前一拍
//v_cnt是多周期的,所以不用提前  
assign  display_area = (h_cnt >= Hor_Start - 1 && h_cnt < Hor_End - 1 && v_cnt >= Ver_Start && v_cnt < Ver_End);
//定义墙壁区域
assign  wall_area = ((h_cnt >= Hor_Start - 1 && h_cnt < Hor_Start - 1 + Red_Wall) || (h_cnt >= Hor_End - 1 - Red_Wall && h_cnt < Hor_End - 1)) || ((v_cnt >= Ver_Start && v_cnt < Ver_Start + Red_Wall) || (v_cnt >= Ver_End - Red_Wall && v_cnt < Ver_End));

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

(4)有效区内像素点的坐标扫描
//pixel_x,pixel_y vga扫描坐标
always  @(posedge clk or negedge rst_n)begin
    if(rst_n == 1'b0)begin
        pixel_x <=  10'd0;
        pixel_y <=  10'd0;
    end
    else if(display_area)begin
        pixel_x <=  h_cnt - Hor_Start + 2;//这里提前了两个时钟,因为前后判断各耽搁一个时钟,具体自己画一下时序图
        pixel_y <=  v_cnt - Ver_Start;//因为v_cnt数据是多个时钟保持的,持续时间长,所以不会耽搁,故不能加2
    end
    else begin
        pixel_x <=  10'd0;
        pixel_y <=  10'd0;
    end
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
(5)子模块play_vga的像素点数据输出显示(RGB565)
//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(wall_area)begin//扫描到墙
        vga_r   <=  5'h1f;
        vga_g   <=  6'h00;
        vga_b   <=  5'h00;
    end
    else if(pixel_x[9:4] == apple_x && pixel_y[9:4] == apple_y)begin//扫描到苹果
        vga_r   <=  5'h1f;
        vga_g   <=  6'h3f;
        vga_b   <=  5'h00;
    end
    else if(object == HEAD)begin//扫描到蛇头
        vga_r   <=  5'h00;
        vga_g   <=  6'h3f;
        vga_b   <=  5'h00;
    end
    else if(object == BODY)begin//扫描到蛇身体
        case({pixel_x[3:0],pixel_y[3:0]})//蛇身四个角做特效处理,
            8'h00,8'h0f,8'hf0,8'hff:begin
                vga_r   <=  5'h00;
                vga_g   <=  6'h00;
                vga_b   <=  5'h00;
            end
            default:begin
                vga_r   <=  5'h00;
                vga_g   <=  6'h3f;
                vga_b   <=  5'h1f;
            end
        endcase
    end//其他显示区域为黑色
    else begin
        vga_r   <=  5'd0;
        vga_g   <=  6'd0;
        vga_b   <=  5'd0;
    end
end
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/775837
推荐阅读
相关标签
  

闽ICP备14008679号