以前自己调试过视频信号,无非就时钟加行场同步加数据线,如果视频信号出问题,第一看现象,第二测频率,反正出问题不是消隐信号出问题,就是时钟频率出问题。通过这种方式也调试成功过几个显示屏,然后就以为自己对视频信号的调试已经有丰富的经验了,直到这次需要自己用FPGA写一个VGA的驱动程序,才发现原来自己还是半桶水。

  这次谈一下将RGB888的视频信号转换为VGA信号时的调试心得,使用ADV7123将数字信号转换为VGA信号。

  首先谈一下VGA,在这个网站上可以能看到各种VGA信号的标准:http://tinyvga.com/vga-timing

  以1600*1200分辨率为例(这次我就是要产生一个这样的视频)

  假如1秒显示60场,一场是1200行,一行有1600个像素点,那么时钟频率就是60*1200*1600=115.2MHz,但是实际上不能这样满打满算。如果从现在的思维来考虑,因为行和场同步信号需要一定的建立时间,因此需要的时钟频率会更高一些,但是只要高一点点,给行场同步信号一定的建立时间就可以了,但是实际频率162MHz与计算得到的115.2MHz差别未免也太大了吧。因为这是一个历史问题,以前的显示器是用电子枪扫描的,电子枪扫完一行后需要回到行首,这段时间叫行消隐时间,电子枪扫完一场(到达屏幕的右下角)后需要回到左上角,这段时间叫场消隐时间。由于行消隐和场消隐的存在,以至于实际扫描一帧的时间要比算出来的满打满算的时间要多。

  消隐时间在以前是为了让电子枪归位而设定的,今天虽然行场同步的建立时间可以很短,但是毕竟是一代标准,不能轻易改变,因此消隐信号仍然保留了。

  在网上很多地方可以找到VGA的时序说明,我这边粗略说一下。

  一个行同步周期内包含4个段:行消隐前肩、行同步时间、行消隐后肩、行有效时间,如上图所示,1600*1200的标准中,行有效时间包含了1600个时钟,对应了1600个有效像素点,行消隐前肩包含64个时钟,行同步时间包含192个时钟,行消隐后肩包含304个时钟,所以一行加起来一共2160个时钟。

  同样的,一个场同步周期内包含4个段:场消隐前肩、场同步时间、场消隐后肩、场有效时间,如上图所示,1600*1200的标准中,场有效时间包含了1200个行周期,对应显示器能显示出来的1200行,场消隐前肩包含1个行周期,场同步时间包含3个行周期,场消隐后肩包含46个行周期,所以一场加起来一共有1250个行周期。

  接下来是重点了,行和场都包含有4个时间段,这4个时间段究竟是怎么排布的,网上我找到两种说法:

  我使用这两种时序产生VGA信号,然后我用ADV7604来采,结果显示老不正常,我一直以为是BLANK信号(ADV7123有个BLANK信号,其实就是消隐信号)的原因,改来改去总不对,但是它采标准的1600*1200的图像是正常的,因此我干脆直接自己采一下标准的1600*1200的VGA信号。

  我使用逻辑分析仪采行场同步和红色通道的(也可以是其他通道)信号,行场同步可以直接接逻辑分析仪,而彩色信号是一个模拟信号,最大电压是0.714V,逻辑分析仪采不到。当红色通道为0.714V时表示的是最红的那个颜色,因此我使用了一个放大器,将0.714V放大到5V,然后再接入逻辑分析仪。接着只要采一个纯红的视频就OK了,但问题是纯红的视频哪里来,我找到一个很妙的办法,我外接了一个HDMI转VGA的接头,这样相当于外扩了一个VGA的显示器,然后新建1个PPT,把背景改为纯红,然后PPT设定为演讲者模式(具体操作我忘了,我是早就设好的,这个网上一搜就能搜到),按win+R键将投影选择扩展,然后放映PPT。这个时候神奇的事情来了,第二显示器显示的是纯红的,没有半点杂质,而我的主显示器的可以将PPT最小化,这样就能在主显示器中运行逻辑分析仪软件了。

  运行之后,采到的波形如下图所示:

  注意到1个问题,场同步的同步时间段中包含有3个完整的行同步,同步时间段之前有1个没有数据的行同步,同步时间段之后包含46个没有数据的行同步,那这不就水落石出了吗,4个时间段的排序如下图,前肩后面是同步时间,接着是后肩,然后是有效数据,所以之前找到的那两种说法似乎不太对。

  同样的,行同步信号中的4个时间段也是这样排的。

上图中abcd4个段分别表示行消隐前肩、行同步时间、行消隐后肩和行有效时间。

还有一个比较重要的点,之前没提到,就是ADV7123的BLANK信号,这个信号用于关断输出,当BLANK信号为低时,关断输出,当BLANK信号为高时才能有输出,当然如果此时RGB信号本来就为0那肯定还是没有输出的,因此如果把RGB信号控制好,是完全不需要BLANK信号的。

  有了这个,那程序就好写了,直接附上程序:

  1 module vga_out (
2 input sys_clk,
3 input sys_rst_n,
4
5 output vga_clk,
6 output reg vga_hs,
7 output reg vga_vs,
8 output reg vga_blk,
9
10 output reg [7:0] vga_r,
11 output reg [7:0] vga_g,
12 output reg [7:0] vga_b
13 );
14
15 wire locked;
16 wire rst_n;
17
18 reg [11:0] hcnt;
19 reg [11:0] vcnt;
20
21 assign rst_n = sys_rst_n & locked;
22
23 pll_clk u_pll_clk (
24 .areset (~sys_rst_n),
25 .inclk0 (sys_clk),
26 .c0 (vga_clk),
27 .locked (locked)
28 );
29
30 //162M标准,1600*1200*60 75KHz
31 parameter H_DISP = 12'd1600; // 有效行数
32 parameter H_FRONT = 12'd64; // 行消隐前肩
33 parameter H_SYNC = 12'd192; // 行同步
34 parameter H_BACK = 12'd304; // 行消隐后肩
35 parameter H_TOTAL = 12'd2160; // 行总数
36
37 parameter V_DISP = 12'd1200; // 有效列数
38 parameter V_FRONT = 12'd1; // 列消隐前肩
39 parameter V_SYNC = 12'd3; // 列同步
40 parameter V_BACK = 12'd46; // 列消隐后肩
41 parameter V_TOTAL = 12'd1250; // 列总数
42
43
44 //行同步信号发生器
45 always @ (posedge vga_clk or negedge rst_n)
46 begin
47 if (!rst_n) begin
48 hcnt <= 0;
49 vga_hs <= 1;
50 end
51
52 else begin
53 if (hcnt < H_TOTAL-1)
54 hcnt <= hcnt+1'b1;
55 else
56 hcnt <= 0;
57
58 if((hcnt >= H_FRONT) && (hcnt < H_FRONT+H_SYNC))
59 vga_hs <= 0;
60 else
61 vga_hs <= 1;
62 end
63 end
64
65 // 场同步信号发生器
66 always @ (negedge vga_hs or negedge rst_n)
67 begin
68 if (!rst_n) begin
69 vcnt <= 0;
70 vga_vs <= 1;
71 end
72
73 else begin
74 if (vcnt < V_TOTAL-1)
75 vcnt <= vcnt+1'b1;
76 else
77 vcnt <= 0;
78
79 if((vcnt >= V_FRONT) && (vcnt < V_FRONT+V_SYNC))
80 vga_vs <= 0;
81 else
82 vga_vs <= 1;
83 end
84 end
85
86 //消影信号
87 always @(posedge vga_clk or negedge rst_n) begin
88 if (!rst_n)
89 vga_blk <= 1'b0;
90
91 if (vga_clk) begin
92 if (vcnt < V_FRONT + V_SYNC + V_BACK)
93 vga_blk <= 1'b0;
94 else if (hcnt < H_FRONT + H_SYNC + H_BACK)
95 vga_blk <= 1'b0;
96 else
97 vga_blk <= 1'b1;
98 end
99 end
100
101 /*
102 //横条纹
103 always @(posedge vga_clk) begin
104 if (vcnt < (V_DISP >> 3) * 1 + V_FRONT + V_SYNC + V_BACK) begin
105 vga_r <= 8'b1111_1111;
106 vga_g <= 8'b0000_0000;
107 vga_b <= 8'b1000_0000;
108 end
109
110 else if (vcnt < (V_DISP >> 3) * 2 + V_FRONT + V_SYNC + V_BACK) begin
111 vga_r <= 8'b0000_0000;
112 vga_g <= 8'b0000_0000;
113 vga_b <= 8'b1111_1111;
114 end
115
116 else if (vcnt < (V_DISP >> 3) * 3 + V_FRONT + V_SYNC + V_BACK) begin
117 vga_r <= 8'b0000_0000;
118 vga_g <= 8'b1111_1111;
119 vga_b <= 8'b0000_0000;
120 end
121
122 else if (vcnt < (V_DISP >> 3) * 4 + V_FRONT + V_SYNC + V_BACK) begin
123 vga_r <= 8'b0000_0000;
124 vga_g <= 8'b1111_1111;
125 vga_b <= 8'b1111_1111;
126 end
127
128 else if (vcnt < (V_DISP >> 3) * 5 + V_FRONT + V_SYNC + V_BACK) begin
129 vga_r <= 8'b1111_1111;
130 vga_g <= 8'b0000_0000;
131 vga_b <= 8'b0000_0000;
132 end
133
134 else if (vcnt < (V_DISP >> 3) * 6 + V_FRONT + V_SYNC + V_BACK) begin
135 vga_r <= 8'b1111_1111;
136 vga_g <= 8'b0000_0000;
137 vga_b <= 8'b1111_1111;
138 end
139
140 else if (vcnt < (V_DISP >> 3) * 7 + V_FRONT + V_SYNC + V_BACK) begin
141 vga_r <= 8'b1111_1111;
142 vga_g <= 8'b1111_1111;
143 vga_b <= 8'b0000_0000;
144 end
145
146 else if (vcnt < V_TOTAL) begin
147 vga_r <= 8'b1111_1111;
148 vga_g <= 8'b1111_1111;
149 vga_b <= 8'b1111_1111;
150 end
151 end
152 */
153
154
155 //竖条纹
156 always @(posedge vga_clk) begin
157 if (hcnt < H_FRONT + H_SYNC + H_BACK) begin //前消隐+同步时间段+后消隐期无颜色(黑色)
158 vga_r <= 8'b0000_0000;
159 vga_g <= 8'b0000_0000;
160 vga_b <= 8'b0000_0000;
161 end
162
163 else if (hcnt < (H_DISP >> 3) * 1 + H_FRONT + H_SYNC + H_BACK) begin
164 vga_r <= 8'b1111_1111;
165 vga_g <= 8'b0000_0000;
166 vga_b <= 8'b1000_0000;
167 end
168
169 else if (hcnt < (H_DISP >> 3) * 2 + H_FRONT + H_SYNC + H_BACK) begin
170 vga_r <= 8'b0000_0000;
171 vga_g <= 8'b0000_0000;
172 vga_b <= 8'b1111_1111;
173 end
174
175 else if (hcnt < (H_DISP >> 3) * 3 + H_FRONT + H_SYNC + H_BACK) begin
176 vga_r <= 8'b0000_0000;
177 vga_g <= 8'b1111_1111;
178 vga_b <= 8'b0000_0000;
179 end
180
181 else if (hcnt < (H_DISP >> 3) * 4 + H_FRONT + H_SYNC + H_BACK) begin
182 vga_r <= 8'b0000_0000;
183 vga_g <= 8'b1111_1111;
184 vga_b <= 8'b1111_1111;
185 end
186
187 else if (hcnt < (H_DISP >> 3) * 5 + H_FRONT + H_SYNC + H_BACK) begin
188 vga_r <= 8'b1111_1111;
189 vga_g <= 8'b0000_0000;
190 vga_b <= 8'b0000_0000;
191 end
192
193 else if (hcnt < (H_DISP >> 3) * 6 + H_FRONT + H_SYNC + H_BACK) begin
194 vga_r <= 8'b1111_1111;
195 vga_g <= 8'b0000_0000;
196 vga_b <= 8'b1111_1111;
197 end
198
199 else if (hcnt < (H_DISP >> 3) * 7 + H_FRONT + H_SYNC + H_BACK) begin
200 vga_r <= 8'b1111_1111;
201 vga_g <= 8'b1111_1111;
202 vga_b <= 8'b0000_0000;
203 end
204
205 else if (hcnt < H_TOTAL) begin
206 vga_r <= 8'b1111_1111;
207 vga_g <= 8'b1111_1111;
208 vga_b <= 8'b1111_1111;
209 end
210 end
211
212 endmodule

需要注意的是,PLL锁相环产生的时钟要是162MHz。

VGA调试心得的更多相关文章

  1. LPC2478_调试心得(转)

    1.在调试“E:\htwang\smart2200v201\ARM嵌入式系统实验教程(二)\开发板出厂编程程序\液晶显示程序\LCM_Disp”的程序时,想使用外部RAM进行仿真调试,在将ADS1.2 ...

  2. MIPI接口LCD屏调试心得(转)

    源: MIPI接口LCD屏调试心得

  3. js断点调试心得

    虽然网上已经有多的数不清的调试教程了,但仍然没有发现哪篇文章写的通俗易懂,索性自己尝试写写自己的一些使用习惯或者说是心得,希望对那些还不是很懂得使用断点调试的孩子有一些帮助(大神请无视~). 1.断点 ...

  4. React Native调试心得

    在做React Native开发时,少不了的需要对React Native程序进行调试.调试程序是每一位开发者的基本功,高效的调试不仅能提高开发效率,也能降低Bug率.本文将向大家分享React Na ...

  5. Pycharm Debug调试心得

    1.操作步骤: 1-1.添加断点:直接在标记处点击鼠标左键即可.(删除断点只需再点击断点处即可) 1-2.Debug下运行代码 1-3.按照所需调试进行代码调试.Debug的调试方式如下所示: 分别为 ...

  6. IE漏洞的调试心得

    在调试漏洞的过程中,个人感觉最棘手的就是ie浏览器的漏洞和flash player的漏洞了.这里打算记录一下学习过程中的心得(主要是基于uaf类),以方便新人学习. 首先,ie漏洞与众不同的是,程序的 ...

  7. iOS 调试心得

    修复 bug 占用我们日常开发的大部分时间,熟练的使用调试工具可以给我们节约大部分的时间. LLDB 的常用命令 expression expresion 是一个非常常用的命令,我们可以通过这个命令来 ...

  8. (原)阅读Android-Camera2Video的demo源码和调试心得

    转载请注明出处:http://www.cnblogs.com/lihaiping/p/6142512.html   最近因为项目需要使用到camera的功能,所以针对官方的demo源码进行一番阅读,并 ...

  9. LCD屏背光驱动调试心得---血的教训

    开发板:明远智睿MY-IMX6-EK140 内核源码:linux-3.14.52 背光驱动IC:MP3202 调光原理:通过开发板的核心板PWM4引脚控制MP3202的EN脚,输出不同的占空比从而达到 ...

随机推荐

  1. Liunx运维(五)-信息显示与搜索文件命令

    文档目录: 一.uname:显示系统信息 二.hostname:显示或设置系统的主机名 三.dmesg:系统启动异常诊断 四.stat:显示文件或文件系统状态 五.du:统计磁盘空间使用情况 六.da ...

  2. 【PY从0到1】第六节 用户输入while循环

    # 6 第六节 用户输入while循环 # 1> 重要的函数--input() # 我们先讲解一下input():当Python碰到input()后会执行括号内的语句. # 随后等待用户的输入. ...

  3. [leetcode712]204. Count Primes寻找范围内的素数

    厄拉多塞筛选法,就是哈希表记录素数的倍数 public int countPrimes(int n) { /* 牛逼哄哄的厄拉多塞筛选法 就是从2开始,每找到一个素数,就把n以内的这个数的倍数排除 记 ...

  4. 01 . Go之从零实现Web框架(类似Gin)

    设计一个框架 大部分时候,我们需要实现一个 Web 应用,第一反应是应该使用哪个框架.不同的框架设计理念和提供的功能有很大的差别.比如 Python 语言的 django和flask,前者大而全,后者 ...

  5. 什么是CDN?哪些是流行的jQuery CDN?使用CDN有什么好处?

    内容传送网络或内容分发网络(CDN)是部署在因特网上的多个数据中心的大型分布式服务器系统.CDN的目标是为具有高可 用性和高性能的最终用户提供内容. 有3个流行的jQuery CDN:谷歌,微软jQu ...

  6. 关于if-else代码的优化

    if-else分支代码在我们日常开发中基本上是最常用的逻辑,但是,经常在if-else代码过多的情况下,代码会变得特别臃肿,并且代码的可扩展性会变得不好,所以,优化if-else代码逻辑是很有必要的. ...

  7. docker获取Let's Encrypt永久免费SSL证书

    一 起因 官方的cerbot太烦了,不建议使用 还不如野蛮生长的acme.sh,而这里介绍docker运行cerbot获取Let's Encrypt永久免费SSL证书 二 选型 cerbot的证书不会 ...

  8. 史上最全的pycharm快捷键!快进来点个收藏吧

    Alt+Enter 自动添加包 Ctrl+t SVN更新 Ctrl+k SVN提交 [编辑类:](https://link.zhihu.com/?target=https://www.jianshu. ...

  9. DHCP.md

    DHCP 主配置文件   从 /usr/share/doc/dhcp 复制 dhcpd.conf.sample 到/etc/dhcp下                                  ...

  10. Lesson_strange_words2

    cap 大写字母 mechanical 机械的,力学的 optical 光学的,视觉的 charge 电荷,负载 couple 耦合的,联接的,成对的 charge-coupled device 电荷 ...