以前自己调试过视频信号,无非就时钟加行场同步加数据线,如果视频信号出问题,第一看现象,第二测频率,反正出问题不是消隐信号出问题,就是时钟频率出问题。通过这种方式也调试成功过几个显示屏,然后就以为自己对视频信号的调试已经有丰富的经验了,直到这次需要自己用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. 某毒霸网站存在信息泄露和sql注入

    通过钟馗之眼搜索目标网站的证书使用者找到信息泄露的网站, 点击上图中的edit会跳转 手工注入sql发现有效 that's all

  2. css做keylogger

    下载keylogger:https://github.com/maxchehab/css-keylogging 参考讲解:https://blog.csdn.net/weixin_34138139/a ...

  3. 在linux下搭建NFS服务器实现文件共享

    目录 一.关于NFS 二.搭建一台NFS服务器共享特定资源 三.调优 一.关于NFS 1.NFS是Network File System的简写,即网络文件系统.网络文件系统是FreeBSD支持的文件系 ...

  4. 利用Python将PDF文档转为MP3音频

    1. 转语音工具 微信读书有一个功能,可以将书里的文字转换为音频,而且声音优化的不错,比传统的机械朗读听起来舒服很多. 记得之前看到过Python有一个工具包,可以将文字转换为语音,支持英文和中文,而 ...

  5. oracle 19c dataguard silent install (oracle 19c dataguard 静默安装)

    环境说明 1.关闭透明大页 RHEL  6: # cat /sys/kernel/mm/redhat_transparent_hugepage/enabled [oracle@rhel 6 ~]$ c ...

  6. 利用 Watermill 实现 Golang CQRS

    CQRS CQRS 的意思是"命令-查询责任隔离".我们分离了命令(写请求)和查询(读请求)之间的责任.写请求和读请求由不同的对象处理. 就是这样.我们可以进一步分割数据存储,使用 ...

  7. 关于django的坑(一)

    关于django orm 的坑: 关于设置数据库表自动更新 django的orm关于更新数据库的方法有update和save两种方法.想要表中自动更新需要一下几个条件: 使用 DateTimeFiel ...

  8. ES标签搜索并解决评分排序问题

    一.概述 需求: 最近在做一个新闻项目,有这样一个需求,如下: 用户根据视频内容手动创建标签,标签个数不限 在视频详情页提供根据标签推荐视频功能,即按本视频的标签进行搜索,标签匹配多的排在前面,匹配少 ...

  9. 【代码周边】-GitHub笔记

    ------------恢复内容开始------------ 程序员的宝库github是个好东西,其中开源的项目足够我们的使用,但是如何去精准的获取我们的项目是很多初学者的问题.特别是英语不好的我,一 ...

  10. hive中笛卡尔积的优化

    由于一个业务,必须要进行笛卡尔积,但是速度太慢了,left join时左表大概4万条数据,右表大概 3000多条数据,这样大概就是一亿多条数据, 这在大数据领域其实不算很大的数据量,但是hive中跑的 ...