FPGA实战:VGA成像原理、时序详解与Verilog控制器设计与验证

文章目录

概要

VGA(Video Graphics Array)作为经典的视频显示接口标准,至今仍在FPGA图像处理、嵌入式显示系统等领域广泛应用。它不仅支持CRT显示器,也兼容LCD液晶屏,具有时序清晰、驱动简单、分辨率灵活等特点。本文将系统介绍VGA的成像原理、时序参数,并结合一个完整的Verilog控制器设计与仿真调试实例,帮助读者深入理解VGA驱动实现的全流程。

一、VGA成像原理与基本时序

1.1 VGA接口与显示原理

VGA是一种模拟视频接口,采用RGB三原色分量传输图像信号。在CRT显示器中,电子束从左到右、从上到下逐行扫描荧光屏,通过控制RGB电子枪的强度合成彩色像素。液晶显示器虽无电子枪,但为兼容VGA标准,其内部电路会模拟相同的时序行为。

1.2 同步与消隐信号

行同步(HSync):指示一行扫描结束,电子束返回左侧。

场同步(VSync):指示一场(一帧)扫描结束,电子束返回左上角。

消隐期(Blank):在行/场回扫期间关闭电子束,避免显示干扰信号。

1.3 时序参数详解

VGA一行的时序包含以下阶段(以像素时钟为单位)

同步脉冲(Sync Pulse)

后消隐(Back Porch)

左边界(Left Border)

有效数据显示区(Visible Area)

右边界(Right Border)

前消隐(Front Porch)

一场的时序则以行为单位,结构类似。

1.4 常见分辨率标准

二、VGA控制器Verilog设计(以800×480为例)

2.1 设计目标

设计一个VGA控制器,能输出符合VGA时序的同步信号(HSync、VSync)、消隐信号(BLK)和RGB数据。

2.2 核心信号

h_sync, v_sync:行、场同步信号

vga_blk:数据有效标志(高电平表示在有效显示区)

vga_data23:0:RGB888格式像素数据(R23:16, G15:8, B7:0

2.3 时序参数计算(800×480@60Hz)

像素时钟:33MHz

行总周期:1056 像素时钟

HSync脉冲宽度:128

后消隐:88

有效像素:800

前消隐:40

场总行数:525 行

VSync脉冲宽度:2

后消隐:25

有效行数:480

前消隐:2

2.4 Verilog代码段

c 复制代码
`timescale 1ns / 1ps

module VGA(
    clk_33m,
    reset_n,
    data_in,
    hcount,
    vcount,
    VGA_HS,
    VGA_VS,
    VGA_DATA,
    VGA_CLK,
    VGA_BLK

    );
    input clk_33m;
    input reset_n;
    input [23:0]data_in;
    output [11:0]hcount;//行扫描位置
    output [11:0]vcount;//场扫描位置
    output VGA_HS;//VGA行同步信号
    output VGA_VS;//VGA场同步信号
    output [23:0]VGA_DATA;
    output VGA_CLK;
    output VGA_BLK;
    
    parameter HS_end = 11'd127,
               Hdat_begin = 11'd215,
               Hdat_end = 11'd1015,
               Hsync_end = 11'd1055,
               VS_end = 11'd1,
               Vdat_begin = 11'd34,
               Vdat_end = 11'd514,
               Vsync_end = 11'd524;
    
    reg [11:0] hcount_r;
    reg [11:0] vcount_r;
    
    //行计数器 hcount_r(横向扫描)
    always@(posedge clk_33m or negedge reset_n)
    if(!reset_n)
        hcount_r <= 11'd0;
    else if(hcount_r == Hsync_end)
        hcount_r <= 11'd0;
    else
        hcount_r <= hcount_r +1'd1;
    
    //场计数器 vcount_r(纵向扫描)
    always@(posedge clk_33m or negedge reset_n)
    if(!reset_n)
        vcount_r <= 11'd0;
    else if (hcount_r == Hsync_end)
        begin
            if(vcount_r == Vsync_end)
                vcount_r <= 11'd0;   
            else
                vcount_r <= vcount_r + 1'd1;
        end
    else
        vcount_r <= vcount_r;
    
    assign VGA_CLK = ~clk_33m;//把内部像素时钟 clk_33m 输出到显示端当像素时钟
    assign VGA_BLK = ((hcount_r >= Hdat_begin) && (hcount_r < Hdat_end) && (vcount_r >= Vdat_begin) && (vcount_r < Vdat_end))?1'b1:1'b0;//显示有效区 VGA_BLK,只有在有效显示区内,才让 VGA_BLK = 1
    assign hcount = VGA_BLK ? (hcount_r - Hdat_begin):10'd0;//把"整行计数"转换成"屏幕 X 坐标"
    assign vcount = VGA_BLK ? (vcount_r - Vdat_begin):10'd0;//把"整帧行计数"转换成"屏幕 Y 坐标"
    
    assign VGA_HS = (hcount_r > HS_end)?1'b1:1'b0;//行同步信号 HS(给显示器的"行开始脉冲")
    assign VGA_VS = (vcount_r > VS_end)?1'b1:1'b0;//场同步信号 VS(给显示器的"帧开始脉冲")
    assign VGA_DATA = (VGA_BLK)?data_in : 24'h000000;//在显示区:输出你的 data_in(RGB888),不在显示区:输出黑色(防止消隐区乱闪)

endmodule

三、仿真调试

c 复制代码
`timescale 1ns / 1ps

module VGA_tb;

    reg clk_33m;
    reg reset_n;
    reg [23:0]data_in;
    wire [11:0]hcount;
    wire [11:0]vcount;
    wire VGA_HS;
    wire VGA_VS;
    wire              VGA_BLK;
    wire              VGA_CLK;
    wire      [23:0]  VGA_DATA;
  
  VGA VGA(
        .clk_33m         (clk_33m ),
        .reset_n         (reset_n ),
        .data_in         (data_in ),
        .hcount          (hcount  ),
        .vcount          (vcount  ),
        .VGA_HS          (VGA_HS  ),
        .VGA_VS          (VGA_VS  ),
        .VGA_BLK         (VGA_BLK ),
        .VGA_CLK         (VGA_CLK ),
        .VGA_DATA        (VGA_DATA )       
    );  
   initial clk_33m = 1;
    always #15  clk_33m= ~clk_33m; //周期30ns,所以这里是15,实现15ns翻转
    
    initial begin
        reset_n = 0;
        #201;
        reset_n = 1;
        #200000000;
        $stop;
    end

    always @ (posedge clk_33m or negedge reset_n)
    if (!reset_n)
        data_in <= 0;
    else if (!VGA_BLK)
        data_in <= data_in;
    else
        data_in <= data_in + 1;

endmodule

四、仿真分析

1、HS信号分析

低脉冲时间:实测3.84μs,计算得3840/30=128个时钟周期,与800×480时序参数表中

的HS脉冲宽度128⼀致

2、VS信号分析

低脉冲时间:实测63.36μs,计算得63360/30/1056=2⾏扫描时间,与标准参数⼀致

3、数据的起始位置

⾏数据验证:hcount从0开始计数,输出数据0-799(共800个像素),每个像素对应⼀

个时钟周期

小结

本文从VGA成像原理出发,详细解析了其时序结构,并以800×480分辨率为例,给出了完整的Verilog控制器设计、仿真与验证流程。VGA驱动是FPGA图像处理的基础模块,掌握其时序设计与调试方法,可为后续摄像头显示、视频叠加、GUI界面等应用打下坚实基础。

相关推荐
ARM|X86+FPGA工业主板厂家15 小时前
RK3588+FPGA+EtherCAT异构架构解析|工业场景如何同时保住AI算力与微秒级运动实时性
人工智能·fpga开发·架构
zlinear数据采集卡19 小时前
从“脏信号”到“纳伏级纯净”:硬核拆解DABL7606的多级抗混叠滤波与24位过采样算法
arm开发·科技·嵌入式硬件·fpga开发·开源
尤老师FPGA1 天前
HDMI数据的接收发送实验(二十)
fpga开发
千寻xun2 天前
三、实战篇-NVME SSD控制之FPGA实现(一)
fpga开发·nvme ssd·nvme协议
XMAIPC_Robot2 天前
软硬协同实时控制|RK3588业务调度+FPGA硬件时序,ethercat实现半导体设备微秒级响应(125us)
linux·arm开发·人工智能·fpga开发
upper20202 天前
从零开始设计riscv cpu记录之七
fpga开发·riscv·riscv设计·btb·分支预测
ARM|X86+FPGA工业主板厂家2 天前
AI视觉跟随运动控制实战|RK3588 NPU检测+FPGA EtherCAT多轴联动精准跟随方案,适用于半导体视觉对位等
人工智能·fpga开发·硬件工程·ethercat·实时系统
XMAIPC_Robot2 天前
RK3588+FPGA半导体设备量产踩坑大全|发热、时序漂移、推理抖动、成像干扰、EMC干扰方案
人工智能·嵌入式硬件·fpga开发·arm+fpga
凡亿卓达方案设计3 天前
FPGA硬件开发怎么选靠谱方案商?
fpga开发
Eloudy3 天前
QSFP28、RoCEv2、RFSoC-4x2 数据传输与器件链路
网络·fpga开发·rocev2