大家好,欢迎来到IT知识分享网。
一,什么是VGA
VGA(Video Graphics Array)视频图形阵列是IBM于1987年提出的一个使用模拟信号的电脑显示标准。VGA接口即电脑采用VGA标准输出数据的专用接口。VGA接口共有15针,分成3排,每排5个孔,显卡上应用最为广泛的接口类型,绝大多数显卡都带有此种接口。它传输红、绿、蓝模拟信号以及同步信号(水平和垂直信号)。
DE15母接座(显卡端) | |||
引脚1 | RED | 红色视频 | |
---|---|---|---|
引脚2 | GREEN | 绿色视频 | |
引脚3 | BLUE | 蓝色视频 | |
引脚4 | ID2/RES | 过去为屏幕ID比特2;自DDC2起保留 | |
引脚5 | GND | 接地(水平同步) | |
引脚6 | RED_RTN | 红色接回 | |
引脚7 | GREEN_RTN | 绿色接回 | |
引脚8 | BLUE_RTN | 蓝色接回 | |
引脚9 | KEY/PWR | 过去为key;现为 +5V DC | |
引脚10 | GND | 接地(垂直同步,DDC) | |
引脚11 | ID0/RES | 过去为屏幕ID比特0;自E-DDC起保留 | |
引脚12 | ID1/SDA | 过去为屏幕ID比特1;自DDC2起为I²C数据 | |
引脚13 | HSync | 水平同步 | |
引脚14 | VSync | 垂直同步 | |
引脚15 | ID3/SCL | 过去为屏幕ID比特3;自DDC2起为I²C时钟 | |
图表中详叙了较新的15针VESA DDC2连接头。图标中的针脚编号是显卡常见的母接头;在公接头上的针脚相当于图例的左右镜像。 VGA的显示效果取决于RGB三个分量的位数,最高24位(即RGB各8位),16位,12位也都存在。 |
在一般应用中就是使用VGA显示器去显示图像传感器实时采集到的图像
比如用摄像头采集数据通过VGA显示器显示,
我们只需要去控制图像数据流的存储和传输就可以了。无需对图像数据进行加工处理,不需要FPGA主动生成数据。
二,VGA成像原理
在 VGA 标准兴起的时候,常见的彩色显示器一般由 CRT(阴极射线管)构成,色彩是由 RGB 三基色组成。显示是用逐行扫描的方式解决。阴极射线枪发出的电子束打在涂有荧光粉的荧光屏上,产生 RGB 三基色,合成一个彩色像素。
三,VGA时序分析
相关概念
VGA时序标准是指视频图像在VGA显示系统中的时序规范。它定义了图像信号的各种时序参数,包括水平同步信号、垂直同步信号、行频率、场频率等,以确保正确的图像显示。VGA扫描完一行所需要的时间为水平扫描时间,水平扫描时间的倒成为行频;完成一帧(全屏)扫描所需要的时间为垂直扫描时间,垂直扫描时间的倒数成为场频,即刷新一次显示屏的频率。在CRT显示中,为避免电子束扫描线的回归线产生的信号称为消隐信号,用于控制电子束的移动以避免破坏屏幕画面,有行消隐信号和场消隐信号两种,其存在的时间称为行消隐期和场消隐期[9]。
在行扫描完成后,需要信号对下一行的数据进行同步,所以称为行同步信号,同理,每完成一顿画面的扫描需要信号对下一帧的数据进行同步,这就是场同步信号。用来产生基准频率信号叫做时钟信号,在显示系统中用于同步VGA接口的时序操作,其频率取决于显示分辨率和刷新率的需求。
根据视频电子标准协会(VESA)的标准定义,行时序和场时序都必须包含同步脉冲、显示后沿、显示时序段和显示前沿四个部分。同时VGA工业标准显示模式对其进行了进步的规范:行同步信号、场同步信号都必须为负极性,也就是说同步脉冲要求必须是负脉冲。
时序分析
从时序图中可以看出,行扫描和场扫描都包括四个主要阶段:同步、消隐(前消隐和后消隐)、以及扫描阶段。同步阶段的目的是防止连续叠加、滞后或超前扫描;消隐阶段主要是为了老式阴极射线管显示而设计,以避免回扫描线干扰正常显示;扫描阶段就是对显示器上的实际像素单元进行显示操作。
行扫描周期由a、b、c、d四部分组成,其中行同步是最先进行的,然后才开始数据扫描,具体如下:
VGA时序标准(行扫描)
行扫描具体过程:
序号 |
步骤 |
名称 |
描述 |
---|---|---|---|
1 |
H_SYNC |
行同步时期 |
进行行扫描地址的复位 |
2 |
H_BACK |
行消隐后肩 |
扫描地址转移后稳定等待/准备期 |
3 |
H_DISP |
行显示时期 |
行地址扫描/显示期,此时数据有效 |
4 |
H_FRONT |
行消隐前肩 |
扫描地址转移的准备 |
5 |
H_TQTAL |
行扫描总时间 |
一行扫描的总时间(5个过程) |
场扫描时序与行扫描时序相似,但场扫描周期由多个行扫描周期组成,每个场扫描都有自己的时序,包括场消隐前肩、场同步时期、场消隐后肩和场总显示时间。在场消隐期间,H_SYNC时序保持不变,但数据输入被屏蔽。尽管显示器具有不同的分辨率,但扫描时序保持一致。场扫描周期也由a、b、c、d四部分组成,首先进行行同步操作,然后才开始数据扫描,具体如下:
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; // 将系统复位信号置为高电平 #; // 等待一段时间进行仿真测试 $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/1cxcAhttp://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/?ug_source=seo_juhe&anchor=lnrlbiwrkht
B站小梅哥视频
等等………
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/139598.html