基于FPGA的实时图像处理系统(2)——VGA显示彩条和图片
VGA显示彩条和图片
文章目录
- VGA显示彩条和图片
-
- 一、VGA简介
- 二、功能设计
-
- 1、彩条设计
- 2、图片设计
- 三、结果展示
- 四、代码
一、VGA简介
VGA(Video Graphics Array)是IBM在1987年随PS/2机⼀起推出的⼀种视频,具有分辨率⾼、显⽰速率快、颜⾊丰富等优点,在彩 ⾊显⽰器领域得到了⼴泛的应⽤。不⽀持热插拔,不⽀持⾳频传输。对于⼀些嵌⼊式VGA显⽰系统,可以在不使⽤VGA显⽰卡和计算机的 情况下,实现VGA图像的显⽰和控制。VGA显⽰器具有成本低、结构简单、应⽤灵活的优点。
VGA的显示原理是:CRT (阴极射线管)以“Z”型扫描的方式将阴极射线枪发出的电子束打在涂有荧光粉的灾光屏上,广土RUD 4日方换行的过程中,电下L一行,电子枪都要回到屏幕的下一行左边的起始位置,并且在换行的过程中,电子枪需要消隐,避免破坏已经成像的像素。
标准的VGA接口是15针的D型接口,分成3排,每排5个孔,是显卡上应用最为广泛的接口类型,绝大多数显卡都带有此种接口。它传输红、绿、蓝模拟信号以及同步信号(水平同步信号和垂直同步信号)。
VGA的时序包括同步信号、消隐区,还有颜色数据的输出。行场时序均可分为4部分:同步脉冲、显示后沿、显示时序、显示前沿。
行扫描时序:
同步脉冲a:代表新一行像素扫描的开始,同时也是上一行扫描的结束。
显示时序c:是真正图像的显示区域,在此阶段,像素逐个显示出来,即在这一阶段控制红、绿、蓝三基色信号输出对应像素的 RGB值。
显示后沿b和显示前沿d:这两个阶段是消隐时刻,消隐区红、绿、蓝三基色信号都为0(黑色)或根据实际情况处理。
**场扫描时序:**时序与行扫描相同。
有效区域
常见VGA分辨率参数表
本次运用的开发板通过权电阻网络进行数模转换
可知采用的为RGB565格式。
二、功能设计
在了解了VGA时序之后,即可设计出完整的流程。
通过sw开关控制显示彩条还是显示图片,VGA通过转接线连至PC进行显示。
1、彩条设计
//colorbar(8个横条纹)always @(posedge clk or negedge rst_n)begin if(!rst_n) colorbar <= 16\'h0000; else begin if((cnt_vsync >= `V_SP + `V_BP) && (cnt_vsync < `V_SP + `V_BP + (`V_AV>>3))) colorbar <= 16\'hf8_00; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>3)) && (cnt_vsync < `V_SP + `V_BP + (`V_AV>>2))) colorbar <= 16\'hff_e0; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>2)) && (cnt_vsync < `V_SP + `V_BP + ((`V_AV>>2) + (`V_AV>>3)))) colorbar <= 16\'h04_00; else if((cnt_vsync >= `V_SP + `V_BP + ((`V_AV>>2) + (`V_AV>>3))) && (cnt_vsync < `V_SP + `V_BP + (`V_AV>>1))) colorbar <= 16\'h80_10; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>1)) && (cnt_vsync < `V_SP + `V_BP + (`V_AV>>1) + (`V_AV>>3))) colorbar <= 16\'h00_1f; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>1) + (`V_AV>>3)) && (cnt_vsync < `V_SP + `V_BP + (`V_AV>>1) + (`V_AV>>2))) colorbar <= 16\'hfd_20; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>1) + (`V_AV>>2)) && (cnt_vsync < `V_SP + `V_BP + ((`V_AV>>1) + (`V_AV>>2) + (`V_AV>>3)))) colorbar <= 16\'hf7_be; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>1) + (`V_AV>>2) + (`V_AV>>3)) && (cnt_vsync < `V_SP + `V_BP + `V_AV)) colorbar <= 16\'h80_10; else colorbar <= 16\'h00_00; endend
按照vga显示时序,在有效区分成8个等分的区域,显示八个彩条。
2、图片设计
采用一个ROM,将图片数据存入ROM,由于开发板资源有限,图片只能采用一个极小的格式进行存储。
ken_romken_rom_inst (.address ( address ),.clock ( clk ),.q ( data ));always @( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin address <= 0;// 复位时清零ROM地址 end else if ( flag_clear_rom_address ) begin //计数满清零 address <= 0; end else if (( (cnt_hsync >= 144) && (cnt_hsync < 233) ) && ((cnt_vsync >= 35) && (cnt_vsync < 161)))begin //在有效区域内+1 address <= address + 1; end else begin //无效区域保持 address <= address; endendassign flag_clear_rom_address = ((address == 11214 - 1) );
(ps:本次主要为验证VGA功能,ROM的地址选择和图片的位图有些缺点)
三、结果展示
开关为01,显示图片(地址有误导致图片错位)
开关拨到其他位置显示彩条
四、代码
1、top
module top ( input clk , input rst_n , input [1:0] sw , output hsync , output vsync , output [15:0] vga_data);wire [15:0] colorbar;wire [10:0] cnt_hsync;wire [10:0] cnt_vsync;wire [15:0] ken_data;color_bar inst_color_bar( .clk (clk ), .rst_n (rst_n ), .cnt_hsync (cnt_hsync), .cnt_vsync (cnt_vsync), .colorbar (colorbar ));vga_driver inst_vga_driver( .clk (clk ), .rst_n (rst_n ), .sw (sw ), .ken_data (ken_data ), .colorbar (colorbar ), .hsync (hsync ), .vsync (vsync ), .cnt_hsync (cnt_hsync), .cnt_vsync (cnt_vsync), .h_vld (h_vld ), .v_vld (v_vld ), .vga_data (vga_data ));picture inst_picture( .clk (clk), .rst_n (rst_n), .sw (sw), .cnt_hsync (cnt_hsync), .cnt_vsync (cnt_vsync), .data (ken_data));endmodule
2、color_bar
`include \"param.v\" module color_bar( input clk , input rst_n , input [10:0]cnt_hsync, input [10:0]cnt_vsync, output reg [15:0] colorbar );//colorbar(8个横条纹)always @(posedge clk or negedge rst_n)begin if(!rst_n) colorbar <= 16\'h0000; else begin if((cnt_vsync >= `V_SP + `V_BP) && (cnt_vsync < `V_SP + `V_BP + (`V_AV>>3))) colorbar <= 16\'hf8_00; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>3)) && (cnt_vsync < `V_SP + `V_BP + (`V_AV>>2))) colorbar <= 16\'hff_e0; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>2)) && (cnt_vsync < `V_SP + `V_BP + ((`V_AV>>2) + (`V_AV>>3)))) colorbar <= 16\'h04_00; else if((cnt_vsync >= `V_SP + `V_BP + ((`V_AV>>2) + (`V_AV>>3))) && (cnt_vsync < `V_SP + `V_BP + (`V_AV>>1))) colorbar <= 16\'h80_10; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>1)) && (cnt_vsync < `V_SP + `V_BP + (`V_AV>>1) + (`V_AV>>3))) colorbar <= 16\'h00_1f; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>1) + (`V_AV>>3)) && (cnt_vsync < `V_SP + `V_BP + (`V_AV>>1) + (`V_AV>>2))) colorbar <= 16\'hfd_20; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>1) + (`V_AV>>2)) && (cnt_vsync < `V_SP + `V_BP + ((`V_AV>>1) + (`V_AV>>2) + (`V_AV>>3)))) colorbar <= 16\'hf7_be; else if((cnt_vsync >= `V_SP + `V_BP + (`V_AV>>1) + (`V_AV>>2) + (`V_AV>>3)) && (cnt_vsync < `V_SP + `V_BP + `V_AV)) colorbar <= 16\'h80_10; else colorbar <= 16\'h00_00; endend endmodule
3、picture
`include \"param.v\"module picture( input clk, input rst_n, input [1:0] sw, input [10:0] cnt_hsync, input [10:0] cnt_vsync, output [15:0] data);wire flag_clear_rom_address;reg [14:0] address;ken_romken_rom_inst (.address ( address ),.clock ( clk ),.q ( data ));always @( posedge clk or negedge rst_n ) begin if ( !rst_n ) begin address <= 0;// 复位时清零ROM地址 end else if ( flag_clear_rom_address ) begin //计数满清零 address <= 0; end else if (( (cnt_hsync >= 144) && (cnt_hsync < 233) ) && ((cnt_vsync >= 35) && (cnt_vsync < 161)))begin //在有效区域内+1 address <= address + 1; end else begin //无效区域保持 address <= address; endendassign flag_clear_rom_address = ((address == 11214 - 1) );endmodule
4、vga_driver
`include \"param.v\" module vga_driver( input clk , input rst_n , input [1:0] sw , input [15:0] colorbar , //RGB565 input [15:0] ken_data , output hsync , output vsync , output reg [10:0]cnt_hsync, output reg[10:0]cnt_vsync, output h_vld , output v_vld , output reg [15:0] vga_data);wireadd_cnt_vsync;wireend_cnt_vsync;wireadd_cnt_hsync;wireend_cnt_hsync;//行同步always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_hsync <= \'d0; end else if(add_cnt_hsync)begin if(end_cnt_hsync)begin cnt_hsync <= \'d0; end else begin cnt_hsync <= cnt_hsync + 1\'b1; end endend assign add_cnt_hsync = 1;assign end_cnt_hsync = add_cnt_hsync && cnt_hsync == `H_TOTAL -1;//场同步always @(posedge clk or negedge rst_n)begin if(!rst_n)begin cnt_vsync <= \'d0; end else if(add_cnt_vsync)begin if(end_cnt_vsync)begin cnt_vsync <= \'d0; end else begin cnt_vsync <= cnt_vsync + 1\'b1; end endend assign add_cnt_vsync = end_cnt_hsync;assign end_cnt_vsync = add_cnt_vsync && cnt_vsync == `V_TOTAL - 1;//hsyncassign hsync = (cnt_hsync < `H_SP )? 1\'b0 : 1\'b1;//vsyncassign vsync = (cnt_vsync < `V_SP )? 1\'b0 : 1\'b1;//h_vldassign h_vld = (cnt_hsync >= `H_SP + `H_BP) && (cnt_hsync < `H_TOTAL - `H_FP);//v_vldassign v_vld = (cnt_vsync >= `V_SP + `V_BP) && (cnt_vsync < `V_TOTAL - `V_FP);//vga_dataalways @(*)begin case(sw) 2\'b01 : vga_data = (( (cnt_hsync >= 144) && (cnt_hsync < 233) ) && ((cnt_vsync >= 35) && (cnt_vsync < 161))) ? ken_data : 16\'h0000; default:vga_data = (h_vld && v_vld) ? colorbar : 16\'d0; endcaseendendmodule
5、param
`define PIXEL_640_480// `define PIXEL_800_600// `define PIXEL_1920_1080`ifdef PIXEL_640_480//行同步信号 `define H_SP 96 `define H_BP 48 //显示后沿 `define H_AV 640 //有效区域 `define H_FP 16 //显示前沿 `define H_TOTAL 800 //总像素//场同步信号 `define V_SP 2 `define V_BP 33 //显示后沿 `define V_AV 480 //有效区域 `define V_FP 10 //显示前沿 `define V_TOTAL 525 //总像素`elsif PIXEL_800_600//行同步信号 `define H_SP 128 `define H_BP 88 //显示后沿 `define H_AV 800 //有效区域 `define H_FP 40 //显示前沿 `define H_TOTAL 1056 //总像素//场同步信号 `define V_SP 4 `define V_BP 23 //显示后沿 `define V_AV 600 //有效区域 `define V_FP 1 //显示前沿 `define V_TOTAL 628 //总像素`elsif PIXEL_1920_1080//行同步信号 `define H_SP 44 `define H_BP 148 //显示后沿 `define H_AV 1920 //有效区域 `define H_FP 88 //显示前沿 `define H_TOTAL 2200 //总像素//场同步信号 `define V_SP 5 `define V_BP 36 //显示后沿 `define V_AV 1080 //有效区域 `define V_FP 4 //显示前沿 `define V_TOTAL 1125 //总像素`endif