VGA(Video Graphics Array)是一种显示接口标准,它最初由IBM于1987年推出。VGA协议定义了计算机视频输出信号的格式和特性。它主要用于连接计算机和显示器之间的传输,实现图像和视频的显示。
VGA协议支持最高分辨率为640x480像素,色彩深度为16位色(即65,536种颜色)。它使用模拟信号传输,通过15个针脚的连接器将图像信号传送到显示器。VGA协议还定义了一些控制信号,用于在显示设备上调整图像的参数,例如水平和垂直同步信号、显示器ID等。
尽管VGA协议的分辨率和色彩深度相对较低,但它是计算机和显示器之间的广泛接口,被广泛应用于台式机、笔记本电脑和显示器等设备上。
VGA15针接口 标准VGA母接口
主要针介绍:
VGA 15针端口,也称为VGA D-sub 15针接口,是常见的VGA连接器,用于连接计算机和显示器之间的视频信号传输。下面是VGA 15针端口的功能介绍:
1. 红色信号(Red):通过这个引脚传输红色信号,用于显示图像中的红色分量。
2. 绿色信号(Green):通过这个引脚传输绿色信号,用于显示图像中的绿色分量。
3. 蓝色信号(Blue):通过这个引脚传输蓝色信号,用于显示图像中的蓝色分量。
4. 水平同步信号(HSync):通过这个引脚传输水平同步信号,用于同步显示器上图像的扫描行。
5. 垂直同步信号(VSync):通过这个引脚传输垂直同步信号,用于同步显示器上图像的扫描帧。
6. 地线(Ground):这些引脚用于电路的接地连接,确保信号的稳定和可靠传输。
7. DDC(Display Data Channel):这个引脚允许计算机和显示器之间进行双向通信,以交换显示器的信息和设置。
VGA 15针接口是模拟信号接口,支持最高分辨率为640x480像素。
由下图不难看出Red管脚有5个输入端,Green有6个输入端口,Blue有5个端口,且都只有一个输出端口,也就是说在输出时他们分别输送5位、6位、5位表示的颜色数据,而这些端口共有16位用来表示不同颜色,2的16次方是65536种不同的颜色数据
由于人的肉眼有感知 红 绿 蓝 三种不同颜色的锥体细胞,因此色彩空间通常可以由三种基本色来表达。三种基色是相互独立的,任何一种基色都不能有其它两种颜色合成。红 绿 蓝 是三基色,这三种颜色合成的颜色范围最为广泛。我们的RGB信号就是三基色的运用,对这三个信号赋予不同的数值,混合起来便是不同的色彩
VGA成像扫描原理是指VGA显示器是如何通过扫描线和逐行显示的方式来显示图像的。
下面是VGA成像扫描原理的简要介绍:
1. 水平扫描线:VGA显示器从左到右,一行一行地扫描整个屏幕。每一行开始时,水平同步信号(HSync)会告诉显示器开始新行的扫描。显示器通过红色、绿色和蓝色的信号输入,根据每个像素的颜色值来显示相应的颜色。
行时序:
2. 垂直扫描帧:当一行扫描完成后,垂直同步信号(VSync)会告诉显示器开始新的帧扫描。显示器从上到下,一帧一帧地扫描整个屏幕。垂直同步信号会告诉显示器开始扫描新帧的第一行。
列时序:
3. 刷新率:VGA显示器的刷新率指的是每秒钟显示的帧数。一般情况下,VGA显示器的刷新率为72Hz,意味着显示器可以每秒刷新72帧图像。每个帧由多个扫描行组成,每一行由多个像素点组成。
每帧的时序:
(声明:该图片转自图片右下角博主)找了好多图都没找到比这更好的
4. 分辨率:VGA显示器的分辨率指的是水平和垂直方向上的像素数。常见的VGA分辨率是800x600像素,意味着每行显示800个像素,每帧显示600行。
通过不断扫描每个像素点,并根据其颜色值来显示相应的颜色,VGA显示器可以逐行逐行地构建整个图像。由于VGA采用模拟信号传输,图像的质量可能受到干扰或信号衰减的影响,导致图像出现模糊、噪点或失真等问题。
以800*600/72Hz为例,800*600/72Hz是指刷新频率为72Hz,分辨率为800X600。这个是标准 VGA 显示驱动。
刷新频率为72Hz,是指1秒显示72幅图像。
从表中可以看出,该分辨率行同步信号,同步脉冲是120个基准时钟,显示后沿是84个基准时钟,显示区域是800个基准时钟,显示前沿是16个基准时钟,那么一行一共有1040个基准时钟。
该分辨率场同步信号,同步脉冲是6行(6*1040个基准时钟),显示后沿是23行(23*1040个基准时钟),显示区域为600行(600*1040个基准时钟),显示前沿为37行(37*1040个基准时钟),一共有666行(666*1040个基准时钟)。
基准时钟是多少呢?由于1秒显示72幅图像,所以一幅图像显示的时间是1/72秒。一幅图像占用了1040*666个基准时钟,所以基准时钟周期=(1/72)/(1040*666)秒,约为20.0521ns。那么基准时钟周期就约为50 MHz ,实验中我们取50M(正好是开发板EP4CE22F17C6的系统时钟,不需要再另外分频)。
1:实现八种颜色全屏显示,且要求每秒变换一种颜色,并将颜色的序号通过数码管显示
2:竖条纹显示
3:横条纹显示
4:棋盘间隔显示
模块名要与工程名相同,文件名可以不一样
module VGA4( //顶层模块:将各个模块组合
//外部接口
input clk, //系统时钟50MHz
input rst_n,//低电平复位
input[1:0] button,
output clkout_1s,
output[3:0] G,
output[3:0] count,//模式一全屏显示计数
output [7:0] seg,//7位数码管显示
output vga_vs,//VGA行同步信号
output vga_hs,//VGA列同步信号
output [4:0] vga_r,//红色输出信号
output [5:0] vga_g,//绿色输出信号
output [4:0] vga_b //蓝色输出信号
);
//内部信号:模块内部的接口信号
//wire [4:0] en_rgb_r;
//wire [5:0] en_rgb_g;
//wire [4:0] en_rgb_b;
//模块例化
vga vga( //接入分频时钟,限定显示的有效区域 ,将区域三等分
.clk (clk),
.button (button),
.rst_n (rst_n),
.vga_vs (vga_vs),
.clkout_1s (clkout_1s),
.vga_hs (vga_hs),
.count (count),
.vga_r (vga_r),
.vga_g (vga_g),
.vga_b (vga_b)
);
Nixie_Tube Nixie_Tube(//数码管显示部分
.clk (clk),
.button (button),
.rst_n (rst_n),
.count (count),
.seg (seg),
.G (G)
);
endmodule
module vga( //显示分辨率为800 * 600 *72 MHZ
//端口信号:模块的输入输出接口
input clk, //连接至系统时钟,为50MHz
input rst_n, //低电平复位
input [1:0] button,//拨档开关选择显示模式
output[4:0] vga_r,//颜色使能信号输出以及赋值
output [5:0] vga_g,
output [4:0] vga_b,
output reg vga_hs,//VGA列同步信号
output reg [3:0] count,//颜色序号计数
output reg vga_vs,//VGA行同步信号
output [2:0] en_rgb,//rRGB使能
output reg clkout_1s //1s时钟,用于计数和数码管显示
);
//----------------VGA时序-----------------------------------
// 显示模式 时钟
// 800*600@72 50Mhz
// 同步 后沿 有效 前沿 周期
//hs 120 64 800 56 1040
//vs 6 23 600 37 666
//VGA显示相应参数
parameter hy_all = 11'd1040, //列时序
hy_a = 11'd120,
hy_b = 11'd64,
hy_c = 11'd800,
hy_d = 11'd56,
vy_all = 11'd666, //行时序
vy_a = 11'd6,
vy_b = 11'd23,
vy_c = 11'd600,
vy_d = 11'd37;
//用计数器限定VGA显示相应区域,通过“行扫描,列填充”的方式
reg [10:0] cnt_h,cnt_v;
always@(posedge clk or posedge rst_n) //列计数
if(rst_n)
cnt_h <= 11'd0;
else if(cnt_h == (hy_all-1))
cnt_h <= 11'd0;
else
cnt_h <= cnt_h + 1'b1;
always@(posedge clk or posedge rst_n)//在一列计数完之后将行加1
if(rst_n)
cnt_v <= 11'd0;
else if(cnt_v == (vy_all-1))
cnt_v <= 11'd0;
else if(cnt_h ==(hy_all-1))
cnt_v <= cnt_v + 1'b1;
//限定列同步信号
always @(posedge clk or posedge rst_n)
if(rst_n)
vga_hs <= 1'b1;
else if(cnt_h ==(hy_all-1))
vga_hs <= 1'b0;//同步信号低有效
else if(cnt_h == hy_a)
vga_hs <= 1'b1;
//限定行同步信号
always @(posedge clk or posedge rst_n)
if(rst_n)
vga_vs <= 1'b0;
else if(cnt_v ==(vy_all-1))
vga_vs <= 1'b0;
else if(cnt_v == vy_a)
vga_vs <= 1'b1;
reg [31:0] cnt_1s;
always @(posedge clk or posedge rst_n)//1s分频
if (rst_n)
cnt_1s <= 0;
else
begin
if (cnt_1s == 32'd2500_0000-1)
begin
cnt_1s <= 0;
clkout_1s <= ~clkout_1s; // 每过 0.5s 就反转时钟信号,1s信号
end
else
begin
cnt_1s <= cnt_1s + 1; // 计数器增加
end
end
//计数模块
always @(posedge clkout_1s or posedge rst_n)
begin
if(rst_n)
begin
count<=0;
end
else
begin
if(button==2'b00)
begin
if(count<=7)
count<=count+1;
else
count<=0;
end
else
begin count<=0;end
end
end
reg [4:0]reg_enr;
reg [5:0]reg_eng;
reg [4:0]reg_enb;
always @(posedge clk or posedge rst_n)
begin
if(rst_n)
begin reg_enr=5'b11111;reg_eng=6'b111111;reg_enb=5'b11111;end
else
begin
if(button==2'b00)
begin//全屏显示
case(count)
0:begin reg_enr <=5'b00000;reg_eng <=6'b000000;reg_enb <=5'b11111;end
1:begin reg_enr <=5'b00000;reg_eng <=6'b111111;reg_enb <=5'b00000;end
2:begin reg_enr <=5'b00000;reg_eng <=6'b111111;reg_enb <=5'b11111;end
3:begin reg_enr <=5'b11111;reg_eng <=6'b000000;reg_enb <=5'b00000;end
4:begin reg_enr <=5'b11111;reg_eng <=6'b000000;reg_enb <=5'b11111;end
5:begin reg_enr <=5'b11111;reg_eng <=6'b111111;reg_enb <=5'b00000;end
6:begin reg_enr <=5'b11111;reg_eng <=6'b111111;reg_enb <=5'b11111;end
7:begin reg_enr <=5'b11100;reg_eng <=6'b111000;reg_enb <=5'b00000;end
default:begin reg_enr <=5'b10111;reg_eng <=6'b100111;reg_enb <=5'b10111;end
endcase
end
else if(button==2'b01)//横屏显示
begin
if(cnt_v > 28 && cnt_v <= 28 + 10'd150) begin reg_enr <=5'b00000;reg_eng <=6'b000000;reg_enb <=5'b11111;end
else if(cnt_v > 28 + 10'd150 && cnt_v <= 28 + 10'd300) begin reg_enr <=5'b00000;reg_eng <=6'b111111;reg_enb <=5'b00000;end
else if(cnt_v > 28 + 10'd300 && cnt_v <= 28 + 10'd450) begin reg_enr <=5'b11111;reg_eng <=6'b000000;reg_enb <=5'b00000;end
else if(cnt_v > 28 + 10'd450 && cnt_v <= 28 + 10'd600) begin reg_enr <=5'b11111;reg_eng <=6'b111111;reg_enb <=5'b11000;end
end
else if(button==2'b10)//竖屏显示
begin
if(cnt_h > 183 && cnt_h <= 183 + 10'd200) begin reg_enr <=5'b11111;reg_eng <=6'b000000;reg_enb <=5'b11111;end
else if(cnt_h > 183 + 10'd200 && cnt_h <= 183 + 10'd400) begin reg_enr <=5'b11111;reg_eng <=6'b111111;reg_enb <=5'b00000;end
else if(cnt_h > 183 + 10'd400 && cnt_h <= 183 + 10'd600) begin reg_enr <=5'b11111;reg_eng <=6'b111111;reg_enb <=5'b11111;end
else if(cnt_h > 183 + 10'd600 && cnt_h <= 183 + 10'd800) begin reg_enr <=5'b10100;reg_eng <=6'b111000;reg_enb <=5'b00110;end
end
else if(button==2'b11)
begin
if((cnt_v > 28 && cnt_v <= 28 + 10'd150)&&(cnt_h > 183 && cnt_h <= 183 + 10'd200)
||(cnt_v > 28+10'd150 && cnt_v <= 28 + 10'd300)&&(cnt_h > 183+ 10'd200&& cnt_h <= 183 + 10'd400)
||(cnt_v > 28+10'd300 && cnt_v <= 28 + 10'd450)&&(cnt_h > 183+ 10'd400&& cnt_h <= 183 + 10'd600)
||(cnt_v > 28+10'd450 && cnt_v <= 28 + 10'd600)&&(cnt_h > 183+ 10'd600&& cnt_h <= 183 + 10'd800))
//(cnt_v >= vy_a+ vy_b && cnt_v <= vy_a + vy_b + 10'd200列范围)&&(cnt_h >= hy_a + hy_b+ 10'd600行范围&& cnt_h <= hy_a + hy_b + 10'd800)
begin
reg_enr <=5'b00000;
reg_eng <=6'b000000;
reg_enb <=5'b11111;
end
else if((cnt_v > 28 && cnt_v <= 28 + 10'd150)&&(cnt_h > 183+10'd600 && cnt_h <= 183 + 10'd800)
||(cnt_v > 28+10'd150 && cnt_v <= 28 + 10'd300)&&(cnt_h > 183+ 10'd400&& cnt_h <= 183 + 10'd600)
||(cnt_v > 28+10'd300 && cnt_v <= 28 + 10'd450)&&(cnt_h > 183+ 10'd200&& cnt_h <= 183 + 10'd400)
||(cnt_v > 28+10'd450 && cnt_v <= 28 + 10'd600)&&(cnt_h > 183&& cnt_h <= 183 + 10'd200))
begin
reg_enr <=5'b11100;
reg_eng <=6'b011100;
reg_enb <=5'b10101;
end
else if((cnt_v > 28 && cnt_v <= 28 + 10'd150)&&(cnt_h > 183+10'd200 && cnt_h <= 183 + 10'd400)
||(cnt_v > 28+10'd150 && cnt_v <= 28 + 10'd300)&&(cnt_h > 183&& cnt_h <= 183 + 10'd200)
||(cnt_v > 28+10'd300 && cnt_v <= 28 + 10'd450)&&(cnt_h > 183+ 10'd600&& cnt_h <= 183 + 10'd800)
||(cnt_v > 28+10'd450 && cnt_v <= 28 + 10'd600)&&(cnt_h > 183+10'd400&& cnt_h <= 183 + 10'd600))
begin
reg_enr <=5'b00100;
reg_eng <=6'b011010;
reg_enb <=5'b00101;
end
else if((cnt_v > 28 && cnt_v <= 28 + 10'd150)&&(cnt_h > 183+10'd400 && cnt_h <= 183 + 10'd600)
||(cnt_v > 28+10'd150 && cnt_v <= 28 + 10'd300)&&(cnt_h > 183+ 10'd600&& cnt_h <= 183 + 10'd800)
||(cnt_v > 28+10'd300 && cnt_v <= 28 + 10'd450)&&(cnt_h > 183&& cnt_h <= 183 + 10'd200)
||(cnt_v > 28+10'd450 && cnt_v <= 28 + 10'd600)&&(cnt_h > 183+10'd200&& cnt_h <= 183 + 10'd400))
begin
reg_enr <=5'b10101;
reg_eng <=6'b111110;
reg_enb <=5'b10101;
end
end
end
end
//rgb使能
assign vga_r=reg_enr;//将寄存器值赋给颜色数据传输线
assign vga_g=reg_eng;
assign vga_b=reg_enb;
endmodule
module Nixie_Tube(
input clk,
input[1:0]button,
input rst_n,
input[3:0]count,
output reg [7:0]seg,//7位数码管显示
output reg[3:0] G//数码管使能
);
reg[31:0]cnt_1ms,clkout_1ms;
//1ms时钟信号
always @ (posedge clk)
if(cnt_1ms==49999)
cnt_1ms<=0;
else
cnt_1ms<=cnt_1ms+1;
always @ (posedge clk)
if(cnt_1ms<=24999)
clkout_1ms<=0;
else
clkout_1ms<=1;
reg [2:0]cnt_clkout_1ms;
always @ (posedge clkout_1ms)
begin
if (cnt_clkout_1ms==3)
cnt_clkout_1ms <=0;
else
cnt_clkout_1ms <= cnt_clkout_1ms + 1;
end
reg [3:0]qout;
always @ (posedge clkout_1ms)
begin
if(button==2'b00)
case(cnt_clkout_1ms)
0:begin
qout <= count;
G <= 4'b1110;
end
1:begin
qout <= 1'b0;
G <= 4'b1101;
end
2:begin
qout <= button/2;
G <= 4'b1011;
end
3:begin
qout <= button%2;
G <= 4'b0111;
end
endcase
else
begin
case(cnt_clkout_1ms)
0:begin
qout <= 4'd9;
G <= 4'b1110;
end
1:begin
qout <= 4'd9;
G <= 4'b1101;
end
2:begin
qout <= button/2;
G <= 4'b1011;
end
3:begin
qout <= button%2;
G <= 4'b0111;
end
endcase
end
end
always @(*)
begin
case(qout)
1:begin seg = 8'b01100000;end//1
2:begin seg = 8'b11011010;end//2
3:begin seg = 8'b11110010;end//3
4:begin seg = 8'b01100110;end//4
5:begin seg = 8'b10110110;end//5
6:begin seg = 8'b10111110;end//6
7:begin seg = 8'b11100000;end//7
8:begin seg = 8'b11111110;end//8
9:begin seg = 8'b00000010;end//-
default:begin seg = 8'b11111100;end//0
endcase
end
endmodule
`timescale 1 ns/ 1 ns
module VGA4_vlg_tst();
reg [1:0] button;
reg clk;
reg rst_n;
wire [3:0] G;
wire clkout_1s;
wire [3:0] count;
wire [7:0] seg;
wire [4:0] vga_b;
wire [5:0] vga_g;
wire vga_hs;
wire [4:0] vga_r;
wire vga_vs;
VGA4 i1 (
.G(G),
.button(button),
.clk(clk),
.clkout_1s(clkout_1s),
.count(count),
.rst_n(rst_n),
.seg(seg),
.vga_b(vga_b),
.vga_g(vga_g),
.vga_hs(vga_hs),
.vga_r(vga_r),
.vga_vs(vga_vs)
);
initial
begin
rst_n=0
clk=0;
$display("Running testbench");
end
always
begin
#30
clk=~clk;
end
endmodule
行时序和场时序仿真波形(深红色是因为没有给值,有需要的都者可以自行添加)
观察可以发现vga_vs低电平持续的时间为vga_hs的6个周期,这个的原理和不同VGA屏显示的时序有关
前两位数码管只有在拨档开关为00时才会正常计数计数内容为单色屏的序号否则为--
后两位数码管显示未拨档开关的状态值:button<=2'b00 单色屏 button<=2'b01 横屏显示 button<=2'b10 竖屏显示 button<=2'b11 棋盘格显示
问题一:count正常计数,数码管正常显示,但是单色屏不能正常显示它只会在极短的时间内闪八种不同的颜色
问题二:可以看到除了竖屏正常显示外,其他的颜色都为渐变色
这两个问题的原因我找了好久但是没有找出来,太痛苦了,希望有知道原因的读者可以不吝赐教,不胜感激