以前自己调试过视频信号,无非就时钟加行场同步加数据线,如果视频信号出问题,第一看现象,第二测频率,反正出问题不是消隐信号出问题,就是时钟频率出问题。通过这种方式也调试成功过几个显示屏,然后就以为自己对视频信号的调试已经有丰富的经验了,直到这次需要自己用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. (三)、vim的移动(旋转,跳跃)

    一.以word为单位的移动 1.w 向后移动到后一个单词词头,取自"word" This is a line with example text ----->--->- ...

  2. TreeMap集合根据指定元素,进行删除和修改的两种方式实现及bug梳理

    TreeMap根据key中的指定元素进行删除修改的两种方式实现及注意事项: 方式一:利用增强for进行删除和修改 总结:逻辑简单,但是局限性太强,如果排序规则是从小到大进行排序的,则该方法不能进行删除 ...

  3. 转载--对batch normalization的理解

    转载的大神的: https://www.cnblogs.com/guoyaohua/p/8724433.html 上边这个应该是抄的下边这个原文,但是上边的有重点标记 https://blog.csd ...

  4. 简述java多态

    一.多态性: 1.java实现多态的前提:继承.覆写: 2.覆写调用的前提:看new是哪个类的对象,而后看方法是否被子类覆写,若覆写则调用覆写的方法,若没覆写则调用父类的方法: 二.多态性组成: 1方 ...

  5. 多媒体开发(4):在视频上显示文字或图片--ffmpeg命令

    小白:我录了段视频,里面用的音乐是有版权的,而且快过期了,能把音乐去掉吗? 小程拿到视频后,一个快捷键打开命令终端,快速打下一行命令: ffmpeg -i 小白.flv -vcodec copy -a ...

  6. TurtleBot3使用课程-第二节a(北京智能佳)

    目录 1.[第3类]LRF(LDS)传感器 2 1.1 传感器包安装 2 1.1.1 传感器端口访问设置 2 1.1.2 运行hlds_laser_publisher节点 2 1.1.3 在RViz中 ...

  7. 软件“美不美”,UI测试一下就知道

    摘要:软件测试的最高层次需求是:UI测试,也就是这个软件"长得好不好看". 为了让读者更好地理解测试,我们从最基础的概念开始介绍.以一个软件的"轮回"为例,下图 ...

  8. 项目实战--Stream流实现字符串拼接

    需求说明 概述:前端页面查询列表中有个"二级类目"的多选下拉框,用户选择二级类目后,需要从后台数据库查询条件内的数据.  目标:将前端页面传入后端的字符串例如"女性护理, ...

  9. R语言学习笔记-单一决策树

    决策树比较简单明晰,但存在不稳定的风险,数据的微小变化会导致最佳决策树结构的巨大变化,且决策树可能会变得比较复杂. 其算法原理参见https://zhuanlan.zhihu.com/p/148010 ...

  10. TypeLoadException: 未能从程序集“ECS.GUI.Define, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null”中加载类型“ECS.GUI.Define.ArmgAimPos”,因为它在 4 偏移位置处包含一个对象字段,该字段已由一个非对象字段不正确地对齐或重叠

    TypeLoadException: 未能从程序集"ECS.GUI.Define, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null ...