一、VGA原理
基本原理参见前一篇VGA(一)文章
二、彩条显示原理
彩条显示原理,可以将场同步信号的中间480行依次分成三段,每一段显示一种颜色,根据cnt_vs的计数到哪一行产生使能脉冲,根据使能脉冲输出颜色。
三、代码
1、顶层模块
module vga_stripes (
input wire clk,
input wire rst_n,
output wire [7:0] vga_rgb,
output wire vga_hs,
output wire vga_vs
);
wire clk_25m;
wire pll_locked;
pll pll_inst (
.areset ( ~rst_n ),
.inclk0 ( clk ),
.c0 ( clk_25m ),
.locked ( pll_locked)
);
vga_ctrl vga_ctrl_inst (
.clk (clk_25m ),
.rst_n (pll_locked ),
.vga_rgb (vga_rgb ),
.vga_hs (vga_hs ),
.vga_vs (vga_vs )
);
endmodule
2、vga_ctrl模块
`define VGA_640x480x60 // choose different video standard,revise PLL clk ,alter cnt WIDTH
//`define VGA_640X480X75
//`define VGA_800X600X60
//`define VGA_800X600X75
//`define VGA_1024X768X60
//`define VGA_1024X768X75
//`define VGA_1280X1024X60
//`define VGA_1280X800X60
//`define VGA_1440X900X60
module vga_ctrl (
input wire clk,
input wire rst_n,
output reg [7:0] vga_rgb,
output reg vga_hs,
output reg vga_vs
);
//================ VGA_640X480X60 =========================================================
`ifdef VGA_640x480x60 // PLL clk = 25M = 640x480x60
localparam HS_A = 96; // synchronous pulse, horizontal
localparam HS_B = 48; // back porch pulse
localparam HS_C = 640; // display interval
localparam HS_D = 16; // Front porch
localparam HS_E = 800; // horizontal cycles
localparam VS_A = 2; // synchronous pulse, vertical
localparam VS_B = 33;
localparam VS_C = 480;
localparam VS_D = 10;
localparam VS_E = 525;
localparam HS_WIDTH = 10;
localparam VS_WIDTH = 10;
`endif
//================ VGA_800X600X60 =========================================================
//
//`ifdef VGA_800X600X60 // PLL clk = 40.0M
//
// localparam HS_A = 128;
// localparam HS_B = 88;
// localparam HS_C = 800;
// localparam HS_D = 40;
// localparam HS_E = 1056;
//
// localparam VS_A = 4;
// localparam VS_B = 23;
// localparam VS_C = 600;
// localparam VS_D = 1;
// localparam VS_E = 628;
//
// localparam HS_WIDTH = 11; // different resolution correspond to different couter width
// localparam VS_WIDTH = 10;
//
//`endif
//=====================================================================================================
parameter CNT_VS_R = 195; // 195 = 2+33+160, 35~195 is red
parameter CNT_VS_G = 355; // 195~355 is green
reg [HS_WIDTH - 1:0] cnt_hs; // counter for vertical synchronous signal
reg [VS_WIDTH - 1:0] cnt_vs; // counter for horizontal synchrous signal
wire en_hs; // dsiplay horizontal enable
wire en_vs; // display vertical enable
wire en; // effective display zone
wire en_vs_r; // red stripe enable
wire en_vs_g; // green stripe enable
always @ (posedge clk, negedge rst_n)
if (!rst_n)
cnt_hs <= 0;
else
if (cnt_hs < HS_E - 1)
cnt_hs <= cnt_hs + 1'b1;
else
cnt_hs <= 0;
always @ (posedge clk, negedge rst_n)
if (!rst_n)
cnt_vs <= 0;
else
if (cnt_hs == HS_E - 1)
if (cnt_vs < VS_E - 1)
cnt_vs <= cnt_vs + 1'b1;
else
cnt_vs <= 0;
else
cnt_vs <= cnt_vs;
always @ (posedge clk, negedge rst_n)
if (!rst_n)
vga_hs <= 1'b1;
else
if (cnt_hs < HS_A - 1)
vga_hs <= 1'b0;
else
vga_hs <= 1'b1;
always @ (posedge clk, negedge rst_n)
if (!rst_n)
vga_vs <= 1'b1;
else
if (cnt_vs < VS_A - 1)
vga_vs <= 1'b0;
else
vga_vs <= 1'b1;
assign en_hs = (cnt_hs > HS_A + HS_B - 1) && (cnt_hs < HS_E - HS_D);
assign en_vs = (cnt_vs > VS_A + VS_B - 1) && (cnt_vs < VS_E - VS_D);
assign en_vs_r = (cnt_vs > VS_A + VS_B - 1) && (cnt_vs < CNT_VS_R);
assign en_vs_g = (cnt_vs > CNT_VS_R - 1) && (cnt_vs < CNT_VS_G);
assign en = en_hs && en_vs;
always @ (posedge clk, negedge rst_n)
if (!rst_n)
vga_rgb <= 8'b000_000_00;
else
if (en)
if (en_vs_r)
vga_rgb <= 8'b111_000_00; // red
else
if (en_vs_g)
vga_rgb <= 8'b000_111_00; // green
else
vga_rgb <= 8'b000_000_11; // blue
else
vga_rgb <= 8'b000_000_00;
endmodule
三、下板验证
实物显示效果如下图