VGA显示测试模块
VGA(Video Graphics Array)是IBM在1987年随PS/2机一起推出的一种视频传输标准,具有分辨率高、显示速率快、颜色丰富等优点,在彩色显示器领域得到了广泛的应用。不支持热插拔,不支持音频传输。它传输红、绿、蓝模拟信号以及同步信号(水平和垂直信号)。随着显示技术的快速发展,VGA接口显示器逐渐被其他更好的接口所替代,当前使用最广泛的显示接口有HDMI和DP,这两种接口已经成为了主流接口。
VGA接口虽然逐渐退出了舞台,但是做为图像处理的入门是再好不过的。
VGA时序:
一行数据包 括: Hor Sync( 行同步) 、 Hor Back Porch( 行消隐) 、 Hor Active Video( 行视频有效) 和 Hor Front Porch( 行前肩) ; 一场数据包括: Ver Sync( 场同步) 、 Ver Back Porch( 场 消隐) 、 Ver Active Video( 场视频有效) 和 Ver Front Porch( 场前肩) 。而实际显示的画面为Hor Active Video( 行视频有效)与Ver Active Video( 场视频有效)围成的部分即上图中的最小矩形Addressable Video。
VGA 常用分辨率时序参数 :
时钟频率=行最大值 * 列最大值* 扫描频率。例如:800 * 525 * 60 = 25,200,000 ≈ 25.175MHz (误差忽略不计)。
VGA_test_gen.v
1 //************************************************************************** 2 // *** file name : VGA_test_gen.v 3 // *** version : 1.0 4 // *** Description : VGA_test_gen 5 // *** Blogs : https://www.cnblogs.com/WenGalois123/ 6 // *** Author : Galois_V 7 // *** Date : 2022.5.15 8 // *** Changes : Initial 9 //************************************************************************** 10 `timescale 1ns/1ps 11 module VGA_test_gen 12 ( 13 input i_pixel_clk , 14 input i_sys_rstn , 15 16 input i_ctrl_key , 17 output [7:0] o_VGA_red , 18 output [7:0] o_VGA_green , 19 output [7:0] o_VGA_blue , 20 output reg o_VGA_hs , 21 output reg o_VGA_vs , 22 output o_VGA_de , 23 output reg [3:0] o_mode 24 ); 25 26 wire w_cnt_x_end ; 27 wire w_cnt_y_end ; 28 reg [11:0] r_cnt_x ; 29 reg [11:0] r_cnt_y ; 30 reg r_hs_de ; 31 reg r_vs_de ; 32 reg [7:0] r_grid_small ; 33 reg [7:0] r_grid_big ; 34 reg [23:0] r_color_bar ; 35 reg [19:0] r_key_cnt ; 36 reg [7:0] r_VGA_blue ; 37 reg [7:0] r_VGA_green ; 38 reg [7:0] r_VGA_red ; 39 40 /******************************************************************************\ 41 水平扫描参数的设定640*480 60HZ 42 \******************************************************************************/ 43 localparam H_Total = 800 ; 44 localparam H_Sync = 96 ; 45 localparam H_Back = 48 ; 46 localparam H_Active = 640 ; 47 localparam H_Front = 16 ; 48 localparam H_Start = 144 ; //H_Start = H_Sync + H_Back 49 localparam H_End = 784 ; //H_End = H_Total - H_Front 50 /******************************************************************************\ 51 垂直扫描参数的设定640*480 60HZ 52 \******************************************************************************/ 53 localparam V_Total = 525 ; 54 localparam V_Sync = 2 ; 55 localparam V_Back = 33 ; 56 localparam V_Active = 480 ; 57 localparam V_Front = 10 ; 58 localparam V_Start = 35 ; //V_Start = V_Sync + V_Back 59 localparam V_End = 515 ; //V_End = V_Total - V_Front 60 /******************************************************************************\ 61 水平扫描参数的设定1280*720 60HZ 62 \******************************************************************************/ 63 // localparam H_Total = 1650 ; 64 // localparam H_Sync = 40 ; 65 // localparam H_Back = 220 ; 66 // localparam H_Active = 1280 ; 67 // localparam H_Front = 110 ; 68 // localparam H_Start = 260 ; 69 // localparam H_End = 1540 ; 70 /******************************************************************************\ 71 垂直扫描参数的设定1280*720 60HZ 72 \******************************************************************************/ 73 // localparam V_Total = 750 ; 74 // localparam V_Sync = 5 ; 75 // localparam V_Back = 20 ; 76 // localparam V_Active = 720 ; 77 // localparam V_Front = 5 ; 78 // localparam V_Start = 25 ; 79 // localparam V_End = 745 ; 80 81 localparam H_STEP = H_Active >> 3; 82 83 /******************************************************************************\ 84 像素计数 85 \******************************************************************************/ 86 always@(posedge i_pixel_clk) 87 begin 88 if(~i_sys_rstn | w_cnt_x_end) 89 begin 90 r_cnt_x <= 'd0; 91 end 92 else 93 begin 94 r_cnt_x <= r_cnt_x + 1'b1; 95 end 96 end 97 assign w_cnt_x_end = r_cnt_x == (H_Total - 1'b1); 98 99 always@(posedge i_pixel_clk) 100 begin 101 if(~i_sys_rstn | w_cnt_y_end) 102 begin 103 r_cnt_y <= 'd0; 104 end 105 else if(w_cnt_x_end) 106 begin 107 r_cnt_y <= r_cnt_y + 1'b1; 108 end 109 end 110 assign w_cnt_y_end = r_cnt_y == V_Total; 111 /******************************************************************************\ 112 行场同步信号产生 113 \******************************************************************************/ 114 always@(posedge i_pixel_clk) 115 begin 116 if(~i_sys_rstn) 117 begin 118 o_VGA_hs <= 'd0; 119 end 120 else if(r_cnt_x == 0) 121 begin 122 o_VGA_hs <= 1'b1; 123 end 124 else if(r_cnt_x == H_Sync) 125 begin 126 o_VGA_hs <= 'd0; 127 end 128 end 129 always@(posedge i_pixel_clk) 130 begin 131 if(~i_sys_rstn) 132 begin 133 r_hs_de <= 'd0; 134 end 135 else if(r_cnt_x == H_Start) 136 begin 137 r_hs_de <= 1'b1; 138 end 139 else if(r_cnt_x == H_End) 140 begin 141 r_hs_de <= 'd0; 142 end 143 end 144 145 always@(posedge i_pixel_clk) 146 begin 147 if(~i_sys_rstn) 148 begin 149 o_VGA_vs <= 'd0; 150 end 151 else if(r_cnt_y == 0) 152 begin 153 o_VGA_vs <= 1'b1; 154 end 155 else if(r_cnt_y == V_Sync) 156 begin 157 o_VGA_vs <= 'd0; 158 end 159 end 160 always@(posedge i_pixel_clk) 161 begin 162 if(~i_sys_rstn) 163 begin 164 r_vs_de <= 'd0; 165 end 166 else if(r_cnt_y == V_Start) 167 begin 168 r_vs_de <= 1'b1; 169 end 170 else if(r_cnt_y == V_End) 171 begin 172 r_vs_de <= 'd0; 173 end 174 end 175 /******************************************************************************\ 176 图像切换 177 \******************************************************************************/ 178 always@(posedge i_pixel_clk) 179 begin 180 if(i_ctrl_key == 'd0) 181 begin 182 r_key_cnt <= 'd0; 183 end 184 else if((i_ctrl_key == 1) & (r_key_cnt <= 1_000_000)) 185 begin 186 r_key_cnt <= r_key_cnt + 1'b1; 187 end 188 if(r_key_cnt == 1_000_000) 189 begin 190 if(o_mode == 12) 191 begin 192 o_mode <= 'd0; 193 end 194 else 195 begin 196 o_mode <= o_mode + 1'b1; 197 end 198 end 199 end 200 /******************************************************************************\ 201 格子图像 202 \******************************************************************************/ 203 always@(posedge i_pixel_clk) 204 begin 205 if(r_cnt_x[4] ^ r_cnt_y[4]) 206 begin 207 r_grid_small <= 'd0; 208 end 209 else 210 begin 211 r_grid_small <= 8'hff; 212 end 213 end 214 215 always@(posedge i_pixel_clk) 216 begin 217 if(r_cnt_x[6] ^ r_cnt_y[6]) 218 begin 219 r_grid_big <= 'd0; 220 end 221 else 222 begin 223 r_grid_big <= 8'hff; 224 end 225 end 226 /******************************************************************************\ 227 竖彩条图像 228 \******************************************************************************/ 229 always@(posedge i_pixel_clk) 230 begin 231 if(r_cnt_x == H_Start) 232 begin 233 r_color_bar <= 24'hff_00_00; 234 end 235 else if(r_cnt_x == H_Start + H_STEP) 236 begin 237 r_color_bar <= 24'h00_ff_00; 238 end 239 else if(r_cnt_x == H_Start + H_STEP*2) 240 begin 241 r_color_bar <= 24'h00_00_ff; 242 end 243 else if(r_cnt_x == H_Start + H_STEP*3) 244 begin 245 r_color_bar <= 24'hff_00_ff; 246 end 247 else if(r_cnt_x == H_Start + H_STEP*4) 248 begin 249 r_color_bar <= 24'hff_ff_00; 250 end 251 else if(r_cnt_x == H_Start + H_STEP*5) 252 begin 253 r_color_bar <= 24'h00_ff_ff; 254 end 255 else if(r_cnt_x == H_Start + H_STEP*6) 256 begin 257 r_color_bar <= 24'hff_ff_ff; 258 end 259 else if(r_cnt_x == H_Start + H_STEP*7) 260 begin 261 r_color_bar <= 24'h00_00_00; 262 end 263 else 264 begin 265 r_color_bar <= r_color_bar; 266 end 267 end 268 /******************************************************************************\ 269 各模式图像显示 270 \******************************************************************************/ 271 always@(posedge i_pixel_clk) 272 begin 273 if(~i_sys_rstn) 274 begin 275 {r_VGA_red,r_VGA_green,r_VGA_blue} <= 'd0; 276 end 277 else 278 case(o_mode) 279 4'd0:begin //全黑 280 r_VGA_red <= 'd0; 281 r_VGA_green <= 'd0; 282 r_VGA_blue <= 'd0; 283 end 284 4'd1:begin //全白 285 r_VGA_red <= 8'hff; 286 r_VGA_green <= 8'hff; 287 r_VGA_blue <= 8'hff; 288 end 289 4'd2:begin //全红 290 r_VGA_red <= 8'hff; 291 r_VGA_green <= 'd0; 292 r_VGA_blue <= 'd0; 293 end 294 4'd3:begin //全绿 295 r_VGA_red <= 'd0; 296 r_VGA_green <= 'hff; 297 r_VGA_blue <= 'd0; 298 end 299 4'd4:begin //全蓝 300 r_VGA_red <= 'd0; 301 r_VGA_green <= 'd0; 302 r_VGA_blue <= 'hff; 303 end 304 4'd5:begin //小方格 305 r_VGA_red <= r_grid_small; 306 r_VGA_green <= r_grid_small; 307 r_VGA_blue <= r_grid_small; 308 end 309 4'd6:begin //大方格 310 r_VGA_red <= r_grid_big; 311 r_VGA_green <= r_grid_big; 312 r_VGA_blue <= r_grid_big; 313 end 314 4'd7:begin //水平白渐变 315 r_VGA_red <= r_cnt_x[7:0]; 316 r_VGA_green <= r_cnt_x[7:0]; 317 r_VGA_blue <= r_cnt_x[7:0]; 318 end 319 4'd8:begin //垂直白渐变 320 r_VGA_red <= r_cnt_y[8:1]; 321 r_VGA_green <= r_cnt_y[8:1]; 322 r_VGA_blue <= r_cnt_y[8:1]; 323 end 324 4'd9:begin //水平红渐变 325 r_VGA_red <= r_cnt_x[7:0]; 326 r_VGA_green <= 'd0; 327 r_VGA_blue <= 'd0; 328 end 329 4'd10:begin //水平绿渐变 330 r_VGA_red <= 'd0; 331 r_VGA_green <= r_cnt_x[7:0]; 332 r_VGA_blue <= 'd0; 333 end 334 4'd11:begin //水平蓝渐变 335 r_VGA_red <= 'd0; 336 r_VGA_green <= 'd0; 337 r_VGA_blue <= r_cnt_x[7:0]; 338 end 339 4'd12:begin //竖彩条 340 r_VGA_red <= r_color_bar[23:16]; 341 r_VGA_green <= r_color_bar[15:8]; 342 r_VGA_blue <= r_color_bar[7:0]; 343 end 344 default:begin //全黑 345 r_VGA_red <= 'd0; 346 r_VGA_green <= 'd0; 347 r_VGA_blue <= 'd0; 348 end 349 endcase 350 end 351 /******************************************************************************\ 352 输出 353 \******************************************************************************/ 354 assign o_VGA_de = r_hs_de & r_vs_de; 355 assign o_VGA_red = (r_hs_de & r_vs_de) ? r_VGA_red : 'd0; 356 assign o_VGA_green = (r_hs_de & r_vs_de) ? r_VGA_green : 'd0; 357 assign o_VGA_blue = (r_hs_de & r_vs_de) ? r_VGA_blue : 'd0; 358 359 endmodule
如图为彩条模式:
实验成功。