本帖最后由 fp3136 于 2013-1-10 20:58 编辑
我是一名应届毕业生,还有半年的时间可能就要离开大学的校门。自己学的是电子专业,因此FPGA也是我们的一门必修课。在我们系有个电子创新开放实验室,这里为学校爱好电子的同学提供了一个学习交流的平台,而我是大一的时候把电脑搬进了这个实验室,并且一直到现在还没有离开,平时的时候课余时间一般都会来这里学习。来到这里刚开始还是从电子基础知识学习,先是从学习单片机开始,由于我们是大二才开单片机C语言以这两门课,因此刚开始主要还是自学。一学期下来已经掌握了基本的编程,大二时与其他刚开始学的同学相比自己已经比较突出了,因此有了更多的时间学习其它的东西。我们是在大三时开设FPGA这门课,因此当时实验室一个老师建议我学习FPGA,当时实验室学的东西分好多方向,许多学习资料和工具老师都给免费提供的,像FPGA,Arm,STM32等老师那分别都有几套开发板,于是自己便开始用老师借给的一个Xilinx的FPGA开发板学习了入门知识。当时学这个主要有两个语言,一个是基于VHDL,另一个是基于Vrilog Hdl,老师说一般后面的那个现在用的比较多,而且它和C语言也有点类似,学着应该比较方便,于是我便开始学习了基于Verilog Hdl编程的FPGA历程。由于大二时有自学的C语言基础,因此刚开始学编程的时候不算太吃力,但是好多时序图当时不怎么理解,不过困难总是哟解决办法的,遇到难懂的问题便向实验室学的好的学长或者老师请教,慢慢的自己也有了进步。就这样学习了一个学期,基本知识包括编程已经画时序图已经比较熟悉了。这学期的时候我们有个FPGA的实训,当时我们是两个人一组,我和班里一个同学做的项目是基于VGA的液晶汉子显示,就是通过写程序可以在电脑显示器上显示出汉子。当时实训是两个周的时间,我们用了不到一个周的时间就完成了,嘿嘿。当然在完成那个实训的过程也是遇到一些问题的,不过经过这次实训,对VGA则有了更加深刻的认识,下面就谈一下实训时碰到的问题以及怎样解决的。
首先就是vga驱动的时序问题。其实时序也并不难,大部分网上找的资料也都讲的很明白,后来我发现自己编写的代码不显示完全不是因为时序问题,而是忽略了一个资料上根本都没提到过的问题。vga一般显示的话5根线就够了。分别是horizontal sync 和vertical sync,翻译后就是“水平同步(行同步)”和“垂直同步(也称为场同步)”。实际上它们的变化是按照一定的规律周期性变化的,也就是它们的时序。“水平同步”按字面也能理解就是控制水平方向的,它的一个周期就是扫描一行所用的时间。而“场同步”的周期却要比行的周期长,也是行周期的整数倍,它的周期是扫描整个屏幕所用的时间。编程时所说的时序控制就是控制这两根信号。另外三根就是RGB三色信号,他们实际上是模拟信号,控制颜色就是看这几根线输进去的电压的大小,比如我们把GB两根线都接地,那么给R加电压越大红色就越深,越小红色越前,当然有个限度大概就是1点多v左右,加个几百v显示器还不爆了。所以想控制显示什么颜色就控制他们的三根信号的电压就可以。我编写的是640*480分辨率,60hz刷新频率的信号控制,显示屏用一般的电脑液晶显示器,按照标准来计算需要的时钟信号是25mhz(具体标准网上资料很多的)。这25MHz也可以理解为每一个像素点的刷新频率。然后就是分别编写行同步信号和场同步信号代码。
always @(posedge vga_clk) begin
if (hcnt<800) begin hcnt<=hcnt + 1 ; end
else begin hcnt <= {10{1'b0}} ; end
end
assign HS=(hcnt<96)?0:1;
assign henable=((hcnt>10'd144)&&(hcnt<10'd784))?1:0;
行同步信号被分为四个时期,而这四个时期中真正能显示在屏幕上的只有一个时期,我们称之为有效期。也就是计数从144到783这段时间,这段时间我们另heable置1。其余时间是用来消隐的。最难理解的应该在HS信号的输出上,行同步信号既然有四个不同的时期,那么是不是在HS输出上能反映出这四个时期呢,其实不然,HS输出只在第一个时期为低电平,其他三个时期是高电平,而显示屏区分这三个时期仅仅是通过时间来区分的。
always @(posedge vga_clk) begin
if (hcnt == (799))
begin
if (vcnt < 525) begin vcnt <= vcnt + 1 ; end
else begin vcnt <= {10{1'b0}} ; end
end
end
assign VS=(vcnt<2)?0:1;
assign venable=((vcnt>10'd35)&&(vcnt<10'd515))?1:0;
场同步和行同步类似,仅仅是行同步是以一个像素变化为单位,而场同步是以行同步变化为单位的。他的计数加1是在一行扫描完。其他分析都一样。当然他也有有效期,在这期间令venable置1.接下来的也是一个关键问题,也就是我出错的地方。我以为rgb信号可以一直送进去,屏幕他会自己舍去忽略除了有效期其他时间段(即消隐时期)内送进去的RGB信号,所我我想让屏幕整屏显示红色就把R接上高电平而GB接地。但实际上上每次下进去之后屏幕总是漆黑一片。直到写成这样:
assign R = 1’b1 & henable & venable ;
assign G = 1’b0 & henable & venable ;
assign B = 1’b0 & henable & venable ;
意思就是仅仅在航扫描和场扫描的有效期内给RGB送进去信号,而在消隐时期不送信号。分析一下其实也不难理解,消隐期本来就是让屏幕原本显示的都消去,而这时候RGB端还有信号输入屏幕当然消隐就起不到作用。所以RGB信号智能在有效期输出数据,其他时期不能有……网上那么多资料却没有一个提出这个问题,呵呵也算自己的一点成果。接下来向现实什么内容就在有效期内扫描不同的像素点时送上不同的RGB信号就可以够成画面了。
基本的问题解决了,当然后面就比较顺利了,实训时用的是学校的实验箱,不过功能和Xilinx的板子上的功能基本视功能是相似的。后面再给大家看一下实训时各个模块的时序图以及程序吧 虽然自己即将毕业,但是学习的进程却不会止步,自己还会更加努力的。有什么不足之处,还望大家批评指正,提出建议,谢谢! |