欢迎光临
我们一直在努力

VGA时序控制原理与实战详解

一 VGA基础

        在写代码之前,我们必须先搞清楚VGA到底是什么,以及它是如何让屏幕亮起来的。

1.1 什么是VGA?

        VGA最早是IBM在1987年推出的一种视频传输标准。虽然它传输的是模拟信号,但其扫描时序被后来的DVI、HDMI等数字接口完美继承。在FPGA开发中,我们通过控制IO口输出高低电平来模拟这些时序,从而实现图像显示。

1.2 VGA物理接口与引脚

        最常见的VGA接口是15针的D-Sub接口。虽然引脚很多,但真正用于传输图像和控制的核心引脚只有5根:

  • R、G、B(红绿蓝):3根模拟信号线。注意,FPGA输出的是数字信号(0或1),要连接到VGA的模拟引脚,通常需要搭建一个电阻分压网络(DAC)。比如用3个电阻将FPGA的3个IO口组合成8种电压等级,实现8位色(RGB 3-3-2)。
  • HSYNC(行同步):告诉显示器“一行开始了”。
  • VSYNC(场同步):告诉显示器“一帧画面开始了”。
  • GND(地):信号参考地。

1.3 VGA显示原理:光栅扫描

VGA显示器(无论是早期的CRT还是现在的LCD)都采用光栅扫描的方式显示图像。你可以想象一支“电子笔”在屏幕上画画:

  • 从左到右画一行(行扫描)。
  • 画到最右边后,电子笔快速回到左边,准备画下一行(行消隐期)。
  • 从上到下画完所有行(场扫描)。
  • 画到右下角后,电子笔快速回到左上角,准备画下一帧(场消隐期)。在这个过程中,电子笔在“回扫”的时候是关闭的(不发光),这段时间被称为消隐期(Blanking)。消隐期就是为了给电子笔留出足够的物理返回时间,同时显示器也需要依靠这段时间来同步信号。

1.4 核心参数:分辨率与像素时钟(Pclk)

  我们常说的“640×480@60Hz”是什么意思?

640×480:表示显示区域的有效区域有640列,480行

60hz:表示一秒扫描的帧数。

       那么,驱动VGA需要一个多快的时钟(像素时钟 Pclk)呢?由于消隐期的存在,扫描一行的时间绝对不是640个时钟,扫描一帧的时间也绝对不是480行。根据行业标准(V640x480@60Hz 的完整时序参数为:

一行总耗时(H_totaltime)= 800 个像素时钟

一帧总耗时(V_totaltime)= 525 行

计算像素时钟:Pclk = 800 * 525 * 60 ≈ 25,200,000 Hz (25.2 MHz)。这也是为什么在FPGA中,我们需要用PLL锁相环将板载的50MHz时钟分频/倍频到 25MHz(或精准的25.175MHz)作为VGA的驱动时钟。

二 VGA时序图基础

请看下面的时序图,它清晰地展示了VGA显示一帧图像时的信号变化规律(以行时序为例,场时序原理完全相同,只是单位从像素变成了行)。

2.

2.1 行时序

行时序描述的是电子枪在屏幕上扫过“一行”像素的过程。它包含以下几个关键阶段:

  • Hor Sync(行同步):告诉显示器一行开始或结束。通常是一个低电平脉冲。
  • H Back Porch(行后沿/后肩):同步脉冲结束到有效图像开始的时间,是电子枪回扫后稳定下来的缓冲期。
  • H Left Border(行左边沿) & H Right Border(行右边沿):图像周围的黑色边框。
  • Hor "Active" Video(行有效视频):实际用于显示的像素区域。图中同时标注了“Addressable Video(可寻址视频区)”,包含在Active Video中。
  • H Front Porch(行前沿/前肩):有效图像结束到下一个同步脉冲开始的缓冲期。

2.2 场时序

场时序描述的是显示器从上到下扫描完一帧画面的过程。原理与行时序一致,但单位是“行”(Line):

  • Ver Sync(场同步):告诉显示器一帧图像结束,准备开始下一帧。
  • V Back Porch(场后沿):场同步后的缓冲期。
  • V Top Border(场上边沿) & V Bottom Border(场下边沿):图像的上下黑边。
  • Ver "Active" Video / Addressable Video(场有效视频):实际的显示图像区域。
  • V Front Porch(场前沿):有效图像结束到下一场同步开始的缓冲期。

一句话总结:一帧画面的扫描,本质上是先进行行扫描(横向),每扫完一行,计数器加1,再进行下一行的扫描;扫完480行后,进入场消隐期,然后从头开始。

三 实战代码(基本时序生成)

结合上面的时序图与基础计算,我们来实现分辨率是 640×480@60Hz的实战项目。

3.1参数定义映射

行时序参数 (H_)

  • H_totaltime = 800:扫描一行总耗时 800 个像素时钟。
  • H_time = 96:行同步脉冲(H Sync)宽度。
  • H_back = 40:行后沿(H Back Porch)。
  • H_left = 8:行左边沿(H Left Border)。
  • H_addrtime = 640:行有效像素(Horizontal Addressable Video)。
  • H_right = 8:行右边沿(H Right Border)。
  • H_front = 8:行前沿(H Front Porch)。

场时序参数 (V_)

  • V_totaltime = 525:扫描一帧总耗时 525 行。
  • V_time = 2:场同步脉冲(V Sync)宽度。
  • V_back = 25:场后沿(V Back Porch)。
  • V_top = 8:场上边沿(V Top Border)。
  • V_addrtime = 480:场有效像素(Vertical Addressable Video)。
  • V_bottom = 8:场下边沿(V Bottom Border)。
  • V_front = 2:场前沿(V Front Porch)。

3.2 计数器逻辑 (cnt_h, cnt_v)

行计数器 cnt_h:在像素时钟 Pclk 驱动下循环计数 0~799。

场计数器 cnt_v:每当行计数器绕回0时(即扫完一行),cnt_v 加1,循环计数 0~524。这是一个典型的嵌套计数结构。

reg [9:0] cnt_h, cnt_v;

always @(posedge Pclk or negedge Prst_n) begin
if(!Prst_n)
cnt_h<=0;
else if(cnt_h==H_totaltime-1)
cnt_h<=0;
else
cnt_h<=cnt_h+1;
end

always @(posedge Pclk or negedge Prst_n) begin
if(!Prst_n)
cnt_v<=0;
else if(cnt_h==H_totaltime-1)begin // 行计数器满,场计数器加1
if(cnt_v==V_totaltime-1)
cnt_v<=0;
else
cnt_v<=cnt_v+1;
end
end

3.3数据有效信号 (data_valid)

assign data_valid = (cnt_h>=(H_time+H_back+H_left))&&(cnt_h<(H_time+H_back+H_left+H_addrtime))
&&(cnt_v>=(V_top+V_back+V_time))&&(cnt_v<(V_top+V_back+V_time+V_addrtime));

这是代码中最核心的部分。 data_valid 决定了何时向屏幕输出真实的图像数据。

水平有效起点:96+40+8 = 144,终点:144+640 = 784。

垂直有效起点:2+25+8 = 35,终点:35+480 = 515。

只有 cnt_h 和 cnt_v 同时处于这两个区间时,data_valid 才为高电平,此时输出的RGB数据才会被显示器识别为有效像素。

3.4. 同步信号生成

assign Hsync = (cnt_h>=H_time)?0:1;
assign Vsync = (cnt_v>=V_time)?0:1;

当计数器在 0 ~ H_time-1(0~95)时,Hsync 输出低电平(同步脉冲);同理,V_time 决定了 Vsync 的低电平脉宽。这与时序图中的负极性同步脉冲相对应。

3.5全部代码

module VGA (
input wire Pclk ,
input wire Prst_n ,
output wire Hsync ,//行同步
output wire Vsync ,//场同步
output wire data_valid //数据有效

);
//行信号基本时序
parameter H_totaltime = 800 ;
parameter H_right = 8 ;//右边沿
parameter H_front = 8 ;//前沿
parameter H_left = 8 ;//左边沿
parameter H_back = 40 ;//后沿
parameter H_time = 96 ;//行同步时间
parameter H_addrtime = 640 ;
//场信号基本时序
parameter V_totaltime = 525 ;
parameter V_top = 8 ;//上边沿
parameter V_front = 2 ;//前沿(前肩时间)
parameter V_bottom = 8 ;//下边沿
parameter V_back = 25 ;//后沿/削隐时间
parameter V_time = 2 ;//场同步时间
parameter V_addrtime = 480 ;

reg [9:0] cnt_h, cnt_v ;

always @(posedge Pclk or negedge Prst_n) begin
if(!Prst_n)
cnt_h<=0;
else if(cnt_h==H_totaltime-1)
cnt_h<=0;
else
cnt_h<=cnt_h+1;
end

always @(posedge Pclk or negedge Prst_n) begin
if(!Prst_n)
cnt_v<=0;
else if(cnt_h==H_totaltime-1)begin
if(cnt_v==V_totaltime-1)
cnt_v<=0;
else
cnt_v<=cnt_v+1;
end
end

assign data_valid = (cnt_h>=(H_time+H_back+H_left))&&(cnt_h<(H_time+H_back+H_left+H_addrtime))
&&(cnt_v>=(V_top+V_back+V_time))&&(cnt_v<(V_top+V_back+V_time+V_addrtime));

assign Hsync = (cnt_h>=H_time)?0:1 ;
assign Vsync = (cnt_v>=V_time)?0:1 ;

endmodule

赞(0)
未经允许不得转载:171主机测评 » VGA时序控制原理与实战详解
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址