赞
踩
VGA显示&游戏状态控制模块 game_show
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 同时有效区域(低有效)
单帧时序图
选用 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
//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;
//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
//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));
//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
//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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。