VGA成像原理与时序

一,什么是VGA

        VGA(Video Graphics Array)视频图形阵列IBM于1987年提出的一个使用模拟信号的电脑显示标准。VGA接口即电脑采用VGA标准输出数据的专用接口。VGA接口共有15针,分成3排,每排5个孔,显卡上应用最为广泛的接口类型,绝大多数显卡都带有此种接口。它传输红、绿、蓝模拟信号以及同步信号(水平和垂直信号)。

       

DE15母接座(显卡端)
引脚1RED红色视频
引脚2GREEN绿色视频
引脚3BLUE蓝色视频
引脚4ID2/RES过去为屏幕ID比特2;自DDC2起保留
引脚5GND接地(水平同步)
引脚6RED_RTN红色接回
引脚7GREEN_RTN绿色接回
引脚8BLUE_RTN蓝色接回
引脚9KEY/PWR过去为key;现为 +5V DC
引脚10GND接地(垂直同步,DDC)
引脚11ID0/RES过去为屏幕ID比特0;自E-DDC起保留
引脚12ID1/SDA过去为屏幕ID比特1;自DDC2起为I²C数据
引脚13HSync水平同步
引脚14VSync垂直同步
引脚15ID3/SCL过去为屏幕ID比特3;自DDC2起为I²C时钟

图表中详叙了较新的15针VESA DDC2连接头。图标中的针脚编号是显卡常见的母接头;在公接头上的针脚相当于图例的左右镜像

VGA的显示效果取决于RGB三个分量的位数,最高24位(即RGB各8位),16位,12位也都存在。

        具有分辨率高、显示速率快、颜色丰富等优点。
        VGA接口不但是CRT显示设备的标准接口,同样也是LCD液晶显示设备的标准接口,具有广泛的应用范围。在FGPA中,常广泛用于图像处理等领域。

在一般应用中就是使用VGA显示器去显示图像传感器实时采集到的图像

比如用摄像头采集数据通过VGA显示器显示,

我们只需要去控制图像数据流的存储和传输就可以了。无需对图像数据进行加工处理,不需要FPGA主动生成数据。

二,VGA成像原理

        在 VGA 标准兴起的时候,常见的彩色显示器一般由 CRT(阴极射线管)构成,色彩是由 RGB 三基色组成。显示是用逐行扫描的方式解决。阴极射线枪发出的电子束打在涂有荧光粉的荧光屏上,产生 RGB 三基色,合成一个彩色像素。

        显示器扫描方式分为逐行扫描和隔行扫描:逐行扫描是扫描从屏幕左上角一点开始,从左像右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,CRT对电子束进行消隐,每行结束时,用行同步信号进行同步;当扫描完所有的行,形成一帧,用场同步信号进行场同步,并使扫描回到屏幕左上方,同时进行场消隐,开始下一帧。隔行扫描是指电子束扫描时每隔一行扫一线,完成一屏后在返回来扫描剩下的线,隔行扫描的显示器闪烁的厉害,会让使用者的眼睛疲劳。 
        完成一行扫描的时间称为水平扫描时间,其倒数称为行频率;完成一帧(整屏)扫描的时间称为垂直扫描时间,其倒数称为场频率,即刷新一屏的频率,常见的有60Hz,75Hz等等。标准的VGA显示的场频60Hz,行频31.5KHz。
        行场消隐信号:是针对老式显像管的成像扫描电路而言的。电子枪所发出的电子束从屏幕的左上角开始向右扫描,一行扫完需将电子束从右边移回到左边以便扫描第二行。在移动期间就必须有一个信号加到电路上,使得电子束不能发出。不然这个回扫线会破坏屏幕图像的。这个阻止回扫线产生的信号就叫作消隐信号,场信号的消隐也是一个道理。
        显示带宽:带宽指的显示器可以处理的频率范围。如果是60Hz刷新频率的VGA,其带宽达640x480x60=18.4MHz,70Hz的刷新频率1024x768分辨率的SVGA,其带宽达1024x768x70=55.1MHz。
        时钟频率:以640x480@59.94Hz(60Hz)为例,每场对应525个行周期(525=10+2+480+33),其中480为显示行。每场有场同步信号,该脉冲宽度为2个行周期的负脉冲,每显示行包括800点时钟,其中640点为有效显示区,每一行有一个行同步信号,该脉冲宽度为96个点时钟。由此可知:行频为525*59.94=31469Hz,需要点时钟频率:525*800*59.94约25MHz.

三,VGA时序分析 

相关概念

        VGA时序标准是指视频图像在VGA显示系统中的时序规范。它定义了图像信号的各种时序参数,包括水平同步信号、垂直同步信号、行频率、场频率等,以确保正确的图像显示。VGA扫描完一行所需要的时间为水平扫描时间,水平扫描时间的成为行频;完成一帧(全屏)扫描所需要的时间为垂直扫描时间,垂直扫描时间的倒数成为场频,即刷新一次显示屏的频率。在CRT显示中,为避免电子束扫描线的回归线产生的信号称为消隐信号,用于控制电子束的移动以避免破坏屏幕画面,有行消隐信号和场消隐信号两种,其存在的时间称为行消隐期和场消隐期[9]。

        在行扫描完成后,需要信号对下一行的数据进行同步,所以称为行同步信号,同理,每完成一顿画面的扫描需要信号对下一帧的数据进行同步,这就是场同步信号。用来产生基准频率信号叫做时钟信号,在显示系统中用于同步VGA接口的时序操作,其频率取决于显示分辨率和刷新率的需求。

        根据视频电子标准协会(VESA)的标准定义,行时序和场时序都必须包含同步脉冲、显示后沿、显示时序段和显示前沿四个部分。同时VGA工业标准显示模式对其进行了进步的规范:行同步信号、场同步信号都必须为负极性,也就是说同步脉冲要求必须是负脉冲。

时序分析

        从时序图中可以看出,行扫描和场扫描都包括四个主要阶段:同步、消隐(前消隐和后消隐)、以及扫描阶段。同步阶段的目的是防止连续叠加、滞后或超前扫描;消隐阶段主要是为了老式阴极射线管显示而设计,以避免回扫描线干扰正常显示;扫描阶段就是对显示器上的实际像素单元进行显示操作。

        行扫描周期由a、b、c、d四部分组成,其中行同步是最先进行的,然后才开始数据扫描,具体如下:

image

                                                             VGA时序标准(行扫描)

行扫描具体过程:

序号

步骤

名称

描述

1

H_SYNC

行同步时期

进行行扫描地址的复位

2

H_BACK

行消隐后肩

扫描地址转移后稳定等待/准备期

3

H_DISP

行显示时期

行地址扫描/显示期,此时数据有效

4

H_FRONT

行消隐前肩

扫描地址转移的准备

5

H_TQTAL

行扫描总时间

一行扫描的总时间(5个过程)

场扫描时序与行扫描时序相似,但场扫描周期由多个行扫描周期组成,每个场扫描都有自己的时序,包括场消隐前肩、场同步时期、场消隐后肩和场总显示时间。在场消隐期间,H_SYNC时序保持不变,但数据输入被屏蔽。尽管显示器具有不同的分辨率,但扫描时序保持一致。场扫描周期也由a、b、c、d四部分组成,首先进行行同步操作,然后才开始数据扫描,具体如下:

image

                                                        VGA时序标准(场扫描)

场扫描具体过程

序号

步骤

名称

描述

1

V_SYNC

场同步时期

进行场扫描地址的复位

2

V_BACK

场消隐后肩

扫描地址转移后稳定等待/准备期

3

V_DISP

场显示时期

场地址扫描/显示期,此时数据有效

4

V_FRONT

场消隐前肩

扫描地址转移的准备

5

V_TQTAL

场扫描总时间

一场扫描的总时间(5个过程)

时序标准表

        在VGA 接口协议中,不同的显示模式因为有不同的分辨率或不同的刷新频率,所以其时序也不相同。对于每种显示模式的时序,VGA 都有严格的工业标准,下表所示即为Xilinx公司制定的VGA时序标准。

                                                VGA时序工业标准(Xilinx Inc.)

显示模式

时钟信号 /MHz

水平参数(单位:像素)

垂直参数(单位:行)

有效区城

前肩脉冲

同步脉冲

后肩脉冲

有效区城

前肩脉冲

同步脉冲

后肩脉冲

640× 480,60 Hz

25

640

16

96

48

480

10

2

33

640× 480,72 Hz

31

640

24

40

128

480

9

3

28

640×480,75 Hz

31

640

16

96

48

480

11

2

32

640×480,85 Hz

36

640

42

48

112

480

1

3

25

800×600,56 Hz

38

800

42

128

128

600

1

4

14

800×600,60 Hz

40

800

40

128

88

600

1

4

23

800×600,72 Hz

50

800

56

120

64

600

37

6

23

800×600,75 Hz

49

800

16

80

160

600

1

2

21

800×600,85 Hz

56

800

32

64

152

600

1

3

27

1024×768,60 Hz

65

1024

24

136

160

768

3

6

29

1024×768,70 Hz

75

1024

24

136

144

768

3

6

29

1024×768,75 Hz

78

1024

16

96

176

768

1

3

28

1024×768,85 Hz

94

1024

48

96

208

768

1

3

36

这里还有VGA协议标准

链接:百度网盘 请输入提取码 提取码:igee

四,VGA控制器Verilog设计与实现

以640× 480,60 Hz显示模式为例。

序号

步骤

名称

描述

1

H_SYNC

行同步时期

进行行扫描地址的复位

2

H_BACK

行消隐后肩

扫描地址转移后稳定等待/准备期

3

H_DISP

行显示时期

行地址扫描/显示期,此时数据有效

4

H_FRONT

行消隐前肩

扫描地址转移的准备

5

H_TQTAL

行扫描总时间

一行扫描的总时间(5个过程)

显示模式

时钟信号 /MHz

水平参数(单位:像素)

垂直参数(单位:行)

有效区城

前肩脉冲

同步脉冲

后肩脉冲

有效区城

前肩脉冲

同步脉冲

后肩脉冲

640× 480,60 Hz

25

640

16

96

48

480

10

2

33

行同步脉冲的开始位置(序号1的开始)        HS_Begin        =        0

行同步脉冲的结束位置(序号2的开始)        HS_End           =        96     

行数据开始输出的位置(序号3的开始)        Hdat_Begin      =        96  +  48 

行数据停止输出的位置(序号4的开始)        Hdat_End         =        96  + 48  + 640

行同步信号的结束位置(序号5)                   Hsync_End       =        96 +  48 +  640  +  16      

同理:

场同步脉冲的开始位置(序号1的开始)        VS_Begin              =  0

场同步脉冲的结束位置(序号2的开始)        VS_End                 =  2

场数据开始输出的位置(序号3的开始)        Vdat_Begin           =   2  +   33

场数据停止输出的位置(序号4的开始)        Vdat_End              =   2  +  33  +  480

场同步信号的结束位置(序号5)                   Vsync_End           =   2   +  33  + 480  +10

 采用线性序列的方法:首先定义以下参数

parameter   VGA_HS_end  =   11'd95 ,   //HS_End - 1    
            hdat_begin  =   11'd144 ,   //Hdat_Begin   
            hdat_end    =   11'd784,   //Hdat_End      
            hpixel_end  =   11'd799,   //Hsync_End - 1 
            VGA_VS_end  =   11'd1   ,   //VS_End - 1   
            vdat_begin  =   11'd35  ,   //Vdat_Begin   
            vdat_end    =   11'd515 ,   //Vdat_End     
            vline_end   =   11'd524 ;   //Vsync_End - 1

 信号时序条件:

assign VGA_CLK = ~sys_clk_25M ;
assign VGA_BLK = ((hcount_r >= hdat_begin)&&(hcount_r < hdat_end)
                 &&(vcount_r >= vdat_begin)&&(vcount_r < vdat_end))?1'b1:1'b0;
assign hcount  = VGA_BLK ? (hcount_r - hdat_begin) : 10'd0;
assign vcount  = VGA_BLK ? (vcount_r - vdat_begin) : 10'd0;
assign VGA_HS  = (hcount_r > VGA_HS_end) ? 1'b1 : 1'b0 ;
assign VGA_VS  = (vcount_r > VGA_VS_end) ? 1'b1 : 1'b0  ;
assign VGA_DATA= (VGA_BLK)?Data_in : 24'h000000;

verilog代码:

module VGA_CTRL(
    input   sys_clk_25M,      // 系统时钟输入
    input   sys_rst_n,        // 系统复位信号输入
    input   [23:0] Data_in,   // 数据输入
    
    output  [10:0] hcount,    // 水平计数输出
    output  [10:0] vcount,    // 垂直计数输出
    output  VGA_HS,           // 水平同步信号输出
    output  VGA_VS,           // 垂直同步信号输出
    output  VGA_BLK,          // 背景信号输出
    output  VGA_CLK,          // VGA时钟输出
    output  [23:0] VGA_DATA   // 数据输出
);

// 时序参数
parameter VGA_HS_end   = 11'd95,    // 水平同步结束位置 (HS_End - 1)
            hdat_begin  = 11'd144,   // 水平数据开始位置 (Hdat_Begin)
            hdat_end    = 11'd784,   // 水平数据结束位置 (Hdat_End)
            hpixel_end  = 11'd799,   // 水平像素结束位置 (Hsync_End - 1)
            VGA_VS_end  = 11'd1,     // 垂直同步结束位置 (VS_End - 1)
            vdat_begin  = 11'd35,    // 垂直数据开始位置 (Vdat_Begin)
            vdat_end    = 11'd515,   // 垂直数据结束位置 (Vdat_End)
            vline_end   = 11'd524;   // 垂直行结束位置 (Vsync_End - 1)

reg [10:0] hcount_r;    // 水平计数器寄存器
reg [10:0] vcount_r;    // 垂直计数器寄存器

// 水平计数器逻辑
always @(posedge sys_clk_25M or negedge sys_rst_n)
begin
    if (!sys_rst_n)
        hcount_r <= 11'd0;
    else if (hcount_r == hpixel_end)
        hcount_r <= 11'd0;
    else
        hcount_r <= hcount_r + 1'd1;
end

// 垂直计数器逻辑
always @(posedge sys_clk_25M or negedge sys_rst_n)
begin
    if (!sys_rst_n)
        vcount_r <= 11'd0;
    else if (hcount_r == hpixel_end)
    begin
        if (vcount_r == vline_end)
            vcount_r <= 11'd0;
        else
            vcount_r <= vcount_r + 1'd1;
    end
    else
        vcount_r <= vcount_r;
end

// 输出信号赋值
assign VGA_CLK = ~sys_clk_25M;  // VGA时钟为系统时钟的反相
assign VGA_BLK = ((hcount_r >= hdat_begin) && (hcount_r < hdat_end) &&
                  (vcount_r >= vdat_begin) && (vcount_r < vdat_end)) ? 1'b1 : 1'b0;
assign hcount = VGA_BLK ? (hcount_r - hdat_begin) : 10'd0;
assign vcount = VGA_BLK ? (vcount_r - vdat_begin) : 10'd0;
assign VGA_HS = (hcount_r > VGA_HS_end) ? 1'b1 : 1'b0;
assign VGA_VS = (vcount_r > VGA_VS_end) ? 1'b1 : 1'b0;
assign VGA_DATA = VGA_BLK ? Data_in : 24'h000000;

endmodule

textbench:

`timescale 1ns / 1ps  // 定义时间单位和精度

module VGA_CTRL_tb();

reg sys_clk_25M;       // 系统时钟信号
reg sys_rst_n;         // 系统复位信号
reg [23:0] Data_in;    // 数据输入信号
wire [10:0] hcount;    // 水平计数信号
wire [10:0] vcount;    // 垂直计数信号
wire VGA_HS;           // 水平同步信号
wire VGA_VS;           // 垂直同步信号
wire VGA_BLK;          // 背景信号
wire VGA_CLK;          // VGA时钟信号
wire [23:0] VGA_DATA;  // 数据输出信号

VGA_CTRL VGA_CTRL(
    .sys_clk_25M(sys_clk_25M),
    .sys_rst_n(sys_rst_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 sys_clk_25M = 1;  // 初始化系统时钟信号为高电平
always #20 sys_clk_25M = ~sys_clk_25M;  // 生成25MHz的时钟信号

initial begin
    sys_rst_n = 0;  // 将系统复位信号置为低电平
    #201;  // 等待一段时间
    sys_rst_n = 1;  // 将系统复位信号置为高电平
    #200000000;  // 等待一段时间进行仿真测试
    $stop;  // 停止仿真
end

always @(posedge sys_clk_25M or negedge sys_rst_n)
if (!sys_rst_n)
    Data_in <= 0;  // 复位时将数据输入信号置为零
else if (!VGA_BLK)
    Data_in <= Data_in;  // 在显示区域外保持数据输入信号不变
else
    Data_in <= Data_in + 1;  // 在显示区域内,数据输入信号递增1

endmodule

 首先简单计算一下VGA_HS的时间:3840/40 = 96   满足给定条件   其余同理皆满足条件

 

模拟验证完成。

五,VGA控制器板级验证

以640× 480,60 Hz显示模式为例。

颜色定义:

localparam      BLACK   =24'h000000,//黑色
                BLUE    =24'h0000FF,//蓝色
                RED     =24'hFF0000,//红色
                PURPPLE =24'hFF00FF,//紫色
                GREEN   =24'h00FF00,//绿色
                CYAN    =24'h00FFFF,//青色
                YELLOW  =24'hFFFF00,//黄色
                WHITE   =24'hFFFFFF;//白色

对屏幕进行相应划分(4×2):

wire C0_act = hcount >= 0   && hcount < 320;//正在扫描第0列
wire C1_act = hcount >= 320 && hcount < 640;//正在扫描第1列
wire R0_act = vcount >= 0   && vcount < 120;//正在扫描第0行
wire R1_act = vcount >= 120 && vcount < 240;//正在扫描第1行
wire R2_act = vcount >= 240 && vcount < 360;//正在扫描第2行
wire R3_act = vcount >= 360 && vcount < 480;//正在扫描第3行

wire R0_C0_act = R0_act & C0_act;//第0行0列像素块被扫描中
wire R0_C1_act = R0_act & C1_act;//第0行1列像素块被扫描中
wire R1_C0_act = R1_act & C0_act;//第1行0列像素块被扫描中
wire R1_C1_act = R1_act & C1_act;//第1行1列像素块被扫描中
wire R2_C0_act = R2_act & C0_act;//第2行0列像素块被扫描中
wire R2_C1_act = R2_act & C1_act;//第2行1列像素块被扫描中
wire R3_C0_act = R3_act & C0_act;//第3行0列像素块被扫描中
wire R3_C1_act = R3_act & C1_act;//第3行1列像素块被扫描中

对屏幕进行相应划分(2×4):

wire H_C0_act = hcount >= 0     && hcount < 160;//正在扫描第0列
wire H_C1_act = hcount >= 160   && hcount < 320;//正在扫描第1列
wire H_C2_act = hcount >= 320   && hcount < 480;//正在扫描第2列
wire H_C3_act = hcount >= 480   && hcount < 640;//正在扫描第3列
wire V_R0_act = vcount >= 0     && vcount < 240;//正在扫描第0行
wire V_R1_act = vcount >= 240   && vcount < 480;//正在扫描第1行

wire H_R0_C0_act = H_C0_act & V_R0_act;//第0行0列像素块被扫描中
wire H_R0_C1_act = H_C1_act & V_R0_act;//第0行1列像素块被扫描中
wire H_R0_C2_act = H_C2_act & V_R0_act;//第0行2列像素块被知描中
wire H_R0_C3_act = H_C3_act & V_R0_act;//第0行3列像素块被扫描中
wire H_R1_C0_act = H_C0_act & V_R1_act;//第1行0列像素块被扫描中
wire H_R1_C1_act = H_C1_act & V_R1_act;//第1行1列像素块被扫描中
wire H_R1_C2_act = H_C2_act & V_R1_act;//第1行2列像素块被扫描中
wire H_R1_C3_act = H_C3_act & V_R1_act;//第1行3列像素块被扫描中

下面是实现屏幕每一秒切换上述彩图的verilg(VGA_TEXT) (配合上面的VGA_CTRL模块使用)

module VGA_TEXT(
input   sys_clk_50M     ,
input   sys_rst_n       ,
output  VGA_HS          ,
output  VGA_VS          ,
output  VGA_BLK         ,
output  VGA_CLK         ,
output  [23:0]  VGA_DATA

);

 
reg [23:0]  Data_in ;
wire    sys_clk_25M ;           
wire    locked      ;
           
reg [11:0]  hcount_r;
reg [11:0]  vcount_r;
reg [31:0]  cnt     ;
reg en ;



always @(posedge sys_clk_50M or negedge sys_rst_n)
if(!sys_rst_n)
    cnt <= 0;
else if(cnt == 99_999_999)
    cnt <= 0 ;
else
    cnt <= cnt + 1'd1;
    
always @(posedge sys_clk_50M or negedge sys_rst_n)
if(!sys_rst_n)
    en <= 0;
else if(cnt >= 99_999_999)
    en <= 1 ;
else
    en <= 0 ;
    
localparam      BLACK   =24'h000000,//黑色
                BLUE    =24'h0000FF,//蓝色
                RED     =24'hFF0000,//红色
                PURPPLE =24'hFF00FF,//紫色
                GREEN   =24'h00FF00,//绿色
                CYAN    =24'h00FFFF,//青色
                YELLOW  =24'hFFFF00,//黄色
                WHITE   =24'hFFFFFF;//白色


  pll_25M pll_25M
   (
    // Clock out ports
    .clk_out1(sys_clk_25M),     // output clk_out1
    // Status and control signals
    .reset(sys_rst_n), // input reset
    .locked(locked),       // output locked
   // Clock in ports
    .clk_in1(sys_clk_50M));      // input clk_in1


 VGA_CTRL VGA_CTRL(
.  sys_clk_25M  (sys_clk_25M)   ,
.  sys_rst_n    (sys_rst_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)

);

wire C0_act = hcount >= 0   && hcount < 320;//正在扫描第0列
wire C1_act = hcount >= 320 && hcount < 640;//正在扫描第1列
wire R0_act = vcount >= 0   && vcount < 120;//正在扫描第0行
wire R1_act = vcount >= 120 && vcount < 240;//正在扫描第1行
wire R2_act = vcount >= 240 && vcount < 360;//正在扫描第2行
wire R3_act = vcount >= 360 && vcount < 480;//正在扫描第3行

wire R0_C0_act = R0_act & C0_act;//第0行0列像素块被扫描中
wire R0_C1_act = R0_act & C1_act;//第0行1列像素块被扫描中
wire R1_C0_act = R1_act & C0_act;//第1行0列像素块被扫描中
wire R1_C1_act = R1_act & C1_act;//第1行1列像素块被扫描中
wire R2_C0_act = R2_act & C0_act;//第2行0列像素块被扫描中
wire R2_C1_act = R2_act & C1_act;//第2行1列像素块被扫描中
wire R3_C0_act = R3_act & C0_act;//第3行0列像素块被扫描中
wire R3_C1_act = R3_act & C1_act;//第3行1列像素块被扫描中




wire H_C0_act = hcount >= 0     && hcount < 160;//正在扫描第0列
wire H_C1_act = hcount >= 160   && hcount < 320;//正在扫描第1列
wire H_C2_act = hcount >= 320   && hcount < 480;//正在扫描第2列
wire H_C3_act = hcount >= 480   && hcount < 640;//正在扫描第3列
wire V_R0_act = vcount >= 0     && vcount < 240;//正在扫描第0行
wire V_R1_act = vcount >= 240   && vcount < 480;//正在扫描第1行

wire H_R0_C0_act = H_C0_act & V_R0_act;//第0行0列像素块被扫描中
wire H_R0_C1_act = H_C1_act & V_R0_act;//第0行1列像素块被扫描中
wire H_R0_C2_act = H_C2_act & V_R0_act;//第0行2列像素块被知描中
wire H_R0_C3_act = H_C3_act & V_R0_act;//第0行3列像素块被扫描中
wire H_R1_C0_act = H_C0_act & V_R1_act;//第1行0列像素块被扫描中
wire H_R1_C1_act = H_C1_act & V_R1_act;//第1行1列像素块被扫描中
wire H_R1_C2_act = H_C2_act & V_R1_act;//第1行2列像素块被扫描中
wire H_R1_C3_act = H_C3_act & V_R1_act;//第1行3列像素块被扫描中



always @(posedge sys_clk_50M)
if (en == 1) begin
case({R3_C1_act, R3_C0_act, R2_C1_act,R2_C0_act,R1_C1_act, R1_C0_act, R0_C1_act,R0_C0_act} )
8'b0000_0001: Data_in <= BLACK;
8'b0000_0010: Data_in <= BLUE;
8'b0000_0100: Data_in <= RED;
8'b0000_1000: Data_in <= PURPPLE;
8'b0001_0000: Data_in <= GREEN;
8'b0010_0000: Data_in <= CYAN;
8'b0100_0000: Data_in <= YELLOW;
8'b1000_0000: Data_in <= WHITE;
endcase
end
else if (en == 0) begin
case ({ H_R1_C3_act,H_R1_C2_act,H_R1_C1_act,H_R1_C0_act,H_R0_C3_act,H_R0_C2_act,H_R0_C1_act,H_R0_C0_act})
8'b0000_0001:   Data_in <= BLACK;
8'b0000_0010:   Data_in <= BLUE;
8'b0000_0100:   Data_in <= RED;
8'b0000_1000:   Data_in <= PURPPLE;
8'b0001_0000:   Data_in <= GREEN;
8'b0010_0000:   Data_in <= CYAN;
8'b0100_0000:   Data_in <= YELLOW;
8'b1000_0000:   Data_in <= WHITE;
endcase 
end
else
Data_in <= 24'h000000;

 
endmodule
    
    

(条件不允许  没做实践  不知可行否,)故无实践图片

六,多分辨率适配VGA控制器设计 

  

 应用条件编译来实现要求

了解条件编译:

http://t.csdnimg.cn/1cxcAicon-default.png?t=N7T8http://t.csdnimg.cn/1cxcA

参数定义关系:

parameter   VGA_HS_end  =   `H_Sync_Time - 1                                             ,      //H_Sync_Time -1
            hdat_begin  =   `H_Sync_Time + `H_Back_Porch + `H_Left_Border                  ,     //H_Sync_Time + H_Back_Porch + H_Left_Border
            hdat_end    =   `H_Sync_Time + `H_Back_Porch + `H_Left_Border + `H_Data_Time    ,     //H_Sync_Time + H_Back_Porch + H_Left_Border + H_Data_Time
            hpixel_end  =   `H_Total_Time - 1                                            ,     //hdat_end +H_Right_Border + H_Front_Porch - 1
            VGA_VS_end  =   `V_Sync_Time - 1                                             ,      //V_Sync_Time -1
            vdat_begin  =   `V_Sync_Time + `V_Back_Porch + `V_Top_Border                   ,     //V_Sync_Time + V_Back_Porch + V_Top_Border
            vdat_end    =   `V_Sync_Time + `V_Back_Porch + `V_Top_Border + `V_Data_Time     ,     //vdat_begin + V_Data_Time
            vline_end   =   `V_Total_Time - 1                                            ;     //vdat_end + V_Bottom_Border + V_Front_Porch - 1
            

参数定义文件:(disp_parameter_cfg.v)根据自己的需求选择分辨率

//`define Resolution_480x272 1  //时钟为9MHz// 
//`define Resolution_640x480 1    //时钟为25MHz
//`define Resolution_800x480 1  //时钟为33MHz//
//`define Resolution_800x600 1  //时钟为40MHz// 
//`define Resolution_1024x600 1 //时钟为51MHz// 
//`define Resolution_1024x768 1 //时钟为65MHz// 
//`define Resolution_1280x720 1 //时钟为74.25MHz//
`define Resolution_1920x1080 1//时钟为148.5MHz//


`ifdef Resolution_480x272
    `define H_Right_Border 0
    `define H_Front_Porch 2
    `define H_Sync_Time 41
    `define H_Back_Porch 2
    `define H_Left_Border 0
    `define H_Data_Time 480
    `define H_Total_Time 525
    
    `define V_Bottom_Border 0
    `define V_Front_Porch 2
    `define V_Sync_Time 10
    `define V_Back_Porch 2
    `define V_Top_Border 0
    `define V_Data_Time 272
    `define V_Total_Time 286


`elsif Resolution_640x480
    `define H_Total_Time 12'd800
    `define H_Data_Time 12'd640
    `define H_Right_Border 12'd8
    `define H_Front_Porch 12'd8
    `define H_Sync_Time 12'd96
    `define H_Back_Porch 12'd40
    `define H_Left_Border 12'd8
    
    `define V_Total_Time 12'd525
    `define V_Data_Time 12'd480
    `define V_Bottom_Border 12'd8
    `define V_Front_Porch 12'd2
    `define V_Sync_Time 12'd2
    `define V_Back_Porch 12'd25
    `define V_Top_Border 12'd8

`elsif Resolution_800x480
    `define H_Total_Time 12'd1056
    `define H_Data_Time 12'd800
    `define H_Right_Border 12'd0
    `define H_Front_Porch 12'd40
    `define H_Sync_Time 12'd128
    `define H_Back_Porch 12'd88
    `define H_Left_Border 12'd0
    
    `define V_Total_Time 12'd525
    `define V_Data_Time 12'd480
    `define V_Bottom_Border 12'd8
    `define V_Front_Porch 12'd2
    `define V_Sync_Time 12'd2
    `define V_Back_Porch 12'd25
    `define V_Top_Border 12'd8

    
`elsif Resolution_800x600
    `define H_Total_Time 12'd1056
    `define H_Data_Time 12'd800
    `define H_Right_Border 12'd0
    `define H_Front_Porch 12'd40
    `define H_Sync_Time 12'd128
    `define H_Back_Porch 12'd88
    `define H_Left_Border 12'd0
    
    `define V_Total_Time 12'd628
    `define V_Data_Time 12'd600
    `define V_Bottom_Border 12'd0
    `define V_Front_Porch 12'd1
    `define V_Sync_Time 12'd4
    `define V_Back_Porch 12'd23
    `define V_Top_Border 12'd0


`elsif Resolution_1024x600
    `define H_Total_Time 12'd1344
    `define H_Data_Time 12'd1024
    `define H_Right_Border 12'd0
    `define H_Front_Porch 12'd24
    `define H_Sync_Time 12'd136
    `define H_Back_Porch 12'd160
    `define H_Left_Border 12'd0
    
    `define V_Total_Time 12'd628
    `define V_Data_Time 12'd600
    `define V_Bottom_Border 12'd0
    `define V_Front_Porch 12'd1
    `define V_Sync_Time 12'd4
    `define V_Back_Porch 12'd23
    `define V_Top_Border 12'd0



`elsif Resolution_1024x768
    `define H_Total_Time 12'd1344    
    `define H_Data_Time 12'd1024
    `define H_Right_Border 12'd0
    `define H_Front_Porch 12'd24
    `define H_Sync_Time 12'd136
    `define H_Back_Porch 12'd160
    `define H_Left_Border 12'd0
    
    `define V_Total_Time 12'd806
    `define V_Data_Time 12'd768
    `define V_Bottom_Border 12'd0
    `define V_Front_Porch 12'd3
    `define V_Sync_Time 12'd6
    `define V_Back_Porch 12'd29
    `define V_Top_Border 12'd0


`elsif Resolution_1280x720
    `define H_Total_Time 12'd1650
    `define H_Data_Time 12'd1280
    `define H_Right_Border 12'd0
    `define H_Front_Porch 12'd110
    `define H_Sync_Time 12'd40
    `define H_Back_Porch 12'd220
    `define H_Left_Border 12'd0
    
    `define V_Total_Time 12'd750
    `define V_Data_Time 12'd720
    `define V_Bottom_Border 12'd0
    `define V_Front_Porch 12'd5
    `define V_Sync_Time 12'd5
    `define V_Back_Porch 12'd20
    `define V_Top_Border 12'd0



`elsif Resolution_1920x1080
    `define H_Total_Time 12'd2200
    `define H_Data_Time 12'd1920
    `define H_Right_Border 12'd0
    `define H_Front_Porch 12'd88
    `define H_Sync_Time 12'd44
    `define H_Back_Porch 12'd148
    `define H_Left_Border 12'd0
    
    `define V_Total_Time 12'd1125
    `define V_Data_Time 12'd1080
    `define V_Bottom_Border 12'd0
    `define V_Front_Porch 12'd4
    `define V_Sync_Time 12'd5
    `define V_Back_Porch 12'd36
    `define V_Top_Border 12'd0
`endif










对VGA_CTRL进行更改后为:

`include "disp_parameter_cfg.v"

module VGA_CTRL(
input   sys_clk_25M     ,
input   sys_rst_n       ,
input   [23:0]  Data_in ,
output  [11:0]  hcount  ,
output  [11:0]  vcount  ,
output  VGA_HS          ,
output  VGA_VS          ,
output  VGA_BLK         ,
output  VGA_CLK         ,
output  [23:0]  VGA_DATA

);

parameter   VGA_HS_end  =   `H_Sync_Time - 1                                             ,      //H_Sync_Time -1
            hdat_begin  =   `H_Sync_Time + `H_Back_Porch + `H_Left_Border                  ,     //H_Sync_Time + H_Back_Porch + H_Left_Border
            hdat_end    =   `H_Sync_Time + `H_Back_Porch + `H_Left_Border + `H_Data_Time    ,     //H_Sync_Time + H_Back_Porch + H_Left_Border + H_Data_Time
            hpixel_end  =   `H_Total_Time - 1                                            ,     //hdat_end +H_Right_Border + H_Front_Porch - 1
            VGA_VS_end  =   `V_Sync_Time - 1                                             ,      //V_Sync_Time -1
            vdat_begin  =   `V_Sync_Time + `V_Back_Porch + `V_Top_Border                   ,     //V_Sync_Time + V_Back_Porch + V_Top_Border
            vdat_end    =   `V_Sync_Time + `V_Back_Porch + `V_Top_Border + `V_Data_Time     ,     //vdat_begin + V_Data_Time
            vline_end   =   `V_Total_Time - 1                                            ;     //vdat_end + V_Bottom_Border + V_Front_Porch - 1
            
reg [11:0]  hcount_r;
reg [11:0]  vcount_r;


always @(posedge sys_clk_25M or negedge sys_rst_n)
if(!sys_rst_n)
    hcount_r <= 11'd0;
else if(hcount_r == hpixel_end)
    hcount_r <= 11'd0 ;
else
    hcount_r <= hcount_r + 1'd1;

always @(posedge sys_clk_25M or negedge sys_rst_n)
if(!sys_rst_n)   
    vcount_r <= 11'd0;
else if(hcount_r == hpixel_end)
begin
    if(vcount_r == vline_end)
        vcount_r <= 11'd0;
    else
        vcount_r <= vcount_r + 1'd1;
end
else
    vcount_r <= vcount_r ;

assign VGA_CLK = ~sys_clk_25M ;
assign VGA_BLK = ((hcount_r >= hdat_begin)&&(hcount_r < hdat_end)&&(vcount_r >= vdat_begin)&&(vcount_r < vdat_end))?1'b1:1'b0;
assign hcount  = VGA_BLK ? (hcount_r - hdat_begin) : 10'd0;
assign vcount  = VGA_BLK ? (vcount_r - vdat_begin) : 10'd0;
assign VGA_HS  = (hcount_r > VGA_HS_end) ? 1'b1 : 1'b0 ;
assign VGA_VS  = (vcount_r > VGA_VS_end) ? 1'b1 : 1'b0  ;
assign VGA_DATA= (VGA_BLK)?Data_in : 24'h000000;


endmodule
    
    

如选择1920×1080的分辨率其仿真为:

满足理想要求。。

 如要实现上述彩色条纹切换只需将划分区域该为:

wire C0_act = hcount >= 0 && hcount < `H_Data_Time/2;               //正在扫描第0列
wire C1_act = hcount >= `H_Data_Time/2 && hcount < `H_Data_Time;    //正在扫描第1列
wire R0_act = vcount >= 0 && vcount < `V_Data_Time/4;               //正在扫描第o行
wire R1_act = vcount >= `V_Data_Time/4 && vcount < `V_Data_Time/2;  //正在扫描第1行
wire R2_act = vcount >= `V_Data_Time/2 && vcount < `V_Data_Time/4*3;//正在扫描第2行
wire R3_act = vcount >= `V_Data_Time/4*3 && vcount <`V_Data_Time;   //正在扫描第3行


wire R0_C0_act = R0_act & C0_act;//第0行0列像素块被扫描中
wire R0_C1_act = R0_act & C1_act;//第0行1列像素块被扫描中
wire R1_C0_act = R1_act & C0_act;//第1行0列像素块被扫描中
wire R1_C1_act = R1_act & C1_act;//第1行1列像素块被扫描中
wire R2_C0_act = R2_act & C0_act;//第2行0列像素块被扫描中
wire R2_C1_act = R2_act & C1_act;//第2行1列像素块被扫描中
wire R3_C0_act = R3_act & C0_act;//第3行0列像素块被扫描中
wire R3_C1_act = R3_act & C1_act;//第3行1列像素块被扫描中



wire H_C0_act = hcount >=  0 && hcount< `H_Data_Time/4;                 //正在扫描第0列
wire H_C1_act = hcount >=  `H_Data_Time/4 && hcount < `H_Data_Time/2;   //正在扫描第1列
wire H_C2_act = hcount >=  `H_Data_Time/2 && hcount < `H_Data_Time/4*3; //正在扫描第2列
wire H_C3_act = hcount >=  `H_Data_Time/4*3 && hcount < `H_Data_Time;   //正在扫描第3列
wire V_R0_act = vcount >=  0 && vcount< `V_Data_Time/2;                 //正在扫描第0行
wire V_R1_act = vcount >=  `V_Data_Time/2 && vcount < `V_Data_Time;     //正在扫描第1行


wire H_R0_C0_act = H_C0_act & V_R0_act;//第0行0列像素块被扫描中
wire H_R0_C1_act = H_C1_act & V_R0_act;//第0行1列像素块被扫描中
wire H_R0_C2_act = H_C2_act & V_R0_act;//第0行2列像素块被知描中
wire H_R0_C3_act = H_C3_act & V_R0_act;//第0行3列像素块被扫描中
wire H_R1_C0_act = H_C0_act & V_R1_act;//第1行0列像素块被扫描中
wire H_R1_C1_act = H_C1_act & V_R1_act;//第1行1列像素块被扫描中
wire H_R1_C2_act = H_C2_act & V_R1_act;//第1行2列像素块被扫描中
wire H_R1_C3_act = H_C3_act & V_R1_act;//第1行3列像素块被扫描中

 注意:disp_parameter_cfg.v 与VGA_CTRL等等应在同一目录下

                上述代码可能有大小写错误

板机验证待完成...

参考:


http://t.csdnimg.cn/qUD1d

https://zh.wikipedia.org/wiki/VGA%E7%AB%AF%E5%AD%90

https://www.baike.com/wikiid/7289585183740198931?ug_source=seo_juhe&anchor=lnrlbiwrkht

B站小梅哥视频 

等等.........

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值