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

本文详细解析了VGA显示模块的时序分析,包括关键信号HSync和VSync的参数设定,以及如何通过行列计数、信号产生和有效区域设定实现640*480@60Hz分辨率的VGA显示。同时,介绍了像素点坐标扫描和子模块play_vga的数据输出显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 


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;
(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
(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));

在这里插入图片描述

(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
(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

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值