Verilog HDL那些事_建模篇笔记(实验九:VGA驱动)
1.了解VGA协议
VGA协议有5个输入信号,列同步信号(HSYNC Signal),行同步信号(VSYNC Signal),红-绿-蓝,颜色信号(RGB Signal)。
一帧屏幕的显示是由行从上至下扫描,列从左至右填充。
以800x600x60Hz为例:
对于列填充信号:a是拉低的128个列像素,b是拉高的88个列像素,c是拉高的800个列像素,d是拉高的40个列像素。
对于行扫描信号:o是拉低的4个行像素,p是拉高的23个行像素,q是拉高的600个行像素,r是拉高的1个行像素。
其中,橘色为有效显示区域
一个行像素是以列像素为单位来定义的:
1个行像素 = 1056个列像素 (即1行中有1056个像素需要填充)
一个列像素是以时间单位来定义的:
1个列像素 = 25ns。
2.VGA驱动建模
PLL是FPGA的重要硬件资源,PLL主要功能是对源时钟编程,翻频,分频。
同步模块实现对列填充信号与行扫描信号的控制,同时输出当前的地址(Column_Addr_Sig,Row_Addr_Sig)和有效区域信号(Ready_Sig)。
同步模块的输入只有CLK和RSTn信号,不需要外部输入其它信号,在模块里面编写一系列的驱动模型,并输出驱动信号。
首先,写一个列计数器与一个行计数器:
注意:时钟频率经过PLL倍频后,时钟周期达到了25ns,对比列计数器与行计数器的写法,列计数器是每来一个时钟上升沿,计数增加1,即每隔25ns,计数增加1。而行计数器,是当列填充完毕后(if(Count_H == 11’d1056)),计数增加1。这就解决了我刚才发现行扫描与列扫描不匹配的疑惑。
有效区域信号的产生:
根据有效区域产生有效区域信号(Ready_Sig)
首先定义了一个名为isRectangle的标志寄存器(有0和1两种状态),用来划定显示区域,即(Column_Addr_Sig>11’d0 && Row_Addr_Sig < 11’d100)当扫描到以上区域时,显示相应的颜色,其它区域则不显示。
3.总体描述
(1)整个系统由PLL模块将外部时钟倍频,得到同步扫描与填充模块与VGA显示控制模块所需要的时钟。
(2)同步扫描模块接收经过倍频后的时钟信号后,通过内部编写的行扫描计数器与列填充计数器来工作,通过编写Ready_Sig状态标志寄存器相关块语句(扫描到有效区域后置1,不在有效区域则置0),同时结合isReady与行扫描计数器,列扫描计数器,计算出Column_Addr_Sig(列地址),Row_Addr_Sig(行地址)信号。
(3)VGA显示控制模块中,需要接收Ready_Sig(有效区域信号),列地址,行地址信号。然后在相应的位置填充颜色。同时,我们也可以在有效区域内,自己划定显示区域(通过自定义状态标志寄存器和划定行地址与列地址的范围),并填充相应的颜色。
4.拓展一(向下兼容的概念)
640x480x60Hz的显示标准需要的时钟频率是25.175MHz,即填充1个列像素需要的时间是39.7ns。则可以用更高的源时钟求得39.7ns的定时。引出向下兼容的处理方法:将外部20MHz时钟源翻倍至100MHz,即1个时钟周期为10ns,因此可以用4个时钟周期40ns的时间来满足填充1个列像素所需要的时间。
//40ns_Count,main_source = 10ns
parameter T40NS = 'd3;
reg [:]count1;
always@(posedge CLK or negedge RSTn)
if(!RSTn)
count1 <= 'd0;
else if(count1 == T40NS)
count1 <= 'd0;
else
count1 <= count1 + 'b1;
reg [:]count_H;
always@(posedge CLK or negedge RSTn)
if(!RSTn)
count_H <= 'd0;
else if(count_H == 'd800)
count_H <= 'd0;
else if(count1 == T40NS)
count_H <= count_H + 'b1;
reg [:]count_V;
always@(posedge CLK or negedge RSTn)
if(!RSTn)
count_V <= 'd0;
else if(count_V == 'd625)
count_V <= 'd0;
else if(count_H == 'd800)
count_V <= count_V + 'b1;
在写代码的过程中,需要注意的是寄存器的位宽要定义好,在使用数据的时候也需要带上。计数器在进行加1操作的时候,加的是“1’b1”,即二进制加法运算,因为起先我们定义的是 reg [10:0]count_V 位宽为11。
还有,并不是所有更高时钟的频率就能向下兼容。
5.拓展二(点阵显示)
点阵编码的方式是:逐行显示,高位在前。
逐行显示:表示图像是逐行填充,完成完一行的填充后,再填充下一行。
高位在前:列填充从左往右填充,但最左边是列像素的最高位。即:
以上为一个16个列像素,它的编码为0xf738。
在点阵显示模型中,需要有图片ROM,存储图片(点阵)信息,VGA控制模块需要给出点阵地址,并读取点阵数据,点阵的数据是一行一行读取的,因此,每次从图片ROM模块中取一行的数据。
以下为部分VGA显示控制的代码,寄存器m存储的是同步扫描模块传过来的行地址,n存储的是同步扫描模块传过来的列地址。
行地址直接传给图片ROM模块,图片ROM模块接收到行地址后,给出相应行的像素信息ROM_Data,VGA控制模块根据传来的行像素信息,填充相应的颜色。
解释:
Red_Sig = Ready_Sig ? Rom_Data[6’d63 - n] : 1’b0;
VGA扫描控制模块接收到列地址后,读取Rom_Data中相应的列数据,即当n=0时,应该读取第0列的数据,即Rom_Data[63] 为第0列数据,符合高位在前的原则。
给出图片ROM模块的实例化代码:
Wire [:] Rom_Data;
Rom_module U3
(
.clock(CLK_40MHz);
.address(Rom_Addr);
.q(Rom_Data)
);
6.拓展三(图层显示建模)
关于图层显示的概论理解如下:
黄色是由红色图层与绿色图层叠加得到。
黑色是由红色图层,绿色图层和蓝色图层得到。
如若显示以下4个列像素的信息:
此表应该竖着和横着同时看,第1个列像素为红色,则图层显示码为:(第四位)红色层:1,绿色层:0,蓝色层:0;第2个列像素为黄色,则图层显示码为:(第三位)红色层:1,绿色层:1,蓝色层:0。
红色层:4’b1101
绿色层:4’b0101
蓝色层:4’b0001
在显示控制模块中,只需要将相同的行,相同的列,不同的层信息发送到相关的输出信号。
VGA控制模块给出行信号Rom_Addr,图片ROM(red),图片ROM(green),图片ROM(blue)给出对应行的数据。
体会:对于图片ROM模块,需要同步时钟,不需要复位信号处理,里面应该事先存储好图片的数据信息,等待VGA显示控制模块来读取。
图层的概念,就是通过使用不同颜色叠加,来产生我们需要的颜色。
7.拓展四(帧的概念)
在VGA显示标准中,如:800x600x60Hz,最后的“60Hz”,表示显示标准,意味着在1s内可以显示60帧图像。
60Hz的来历:1个行像素为1056个列像素,一个列像素需要25ns,则1帧的图像需要628*1056*25ns的时间,则1s内显示(1/(628*1056*25ns) = 60)帧图片。
显示动态图片的时候,对于图片ROM模块怎样存放图片的点阵信息,我们需要做如下处理:
假设每张图片都是16x16x1Bit,共有6张图片。则,一张图片有16行,16列,保持这6张图片列对齐,0~15行放置第一张图片,16~31行放置第二张图片.....以此类推。
等待显示完第一张图片后,再显示第二张图片,怎样判断一帧图片是否显示完全呢?需要同步扫描填充模块输出一个显示完成信号(Frame_Sig,)。
assign Frame_Sig = (Count_V == 11’d628) ? 1’b1 : 1’b0;
Frame_Sig并没有在always块语句中做处理,只是需要使用已经经过处理的信号,做出判断就可以得出准确的Frame_Sig(也算是一种算法吧)。
在VGA显示控制模块中,定义了一个FRAME常量,和一个Count_Frame计数器,每当Frame_Sig高电平时,计数器加1,计数周期为60个,表明,每张图片需要显示60次。
以上always块语句的作用是一个图片翻页模块,自带状态机与处理功能。初始化状态为i = 0,rAddr = 0,表示显示第一张图片。
对比以前实验的写法:状态机与处理分开写。
不同点:状态跳变条件与需要处理的动作条件相同,即状态跳变时刻,应当有一个响应对应状态的变化。本实验的状态变化不是一个完整的回路。分析本实验case里面的语句,实质上还是一个查表的思想,当条件Count_Frame == FRAME;条件满足时,状态发生跳变,而没有做出相应的响应。而rAddr <= 7’d0,是当Count_Frame == FRAME;这一条件不满足时,做出的响应。
额外体会:本实验中的case/endcase模块中:
’d0: If( Count_Frame == FRAME ) i <= ’d1; else rAddr <= ’d0;
之所以两条语句不分开写(状态机与响应分开的形式),还有一部分原因是里面是一个if/else条件判断语句,两条语句只执行其中的一条,并不是都会执行。
assign Rom_Addr = rAddr + m;
rAddr表示为显示第几张图片,即ROW的区域。
m表示行偏移量,从同步扫描填充模块获得。
总结:
对于动态图片的显示(多张图片)形成的动画,在同步行扫描,列填充的模块中,需要对一副图画扫描完成与否做出处理,最后提供一个扫描完成信号。
在VGA显示控制模块中,首先要划定显示区域,根据行与列扫描地址(确定一个显示范围)。如果对同一副图片扫描次数有要求,则需要用到Frame_Sig扫描完成信号,设定一个计数器,记录扫描完成信号产生的次数。在设定不同图片行地址时,使用了case/endcase结构,集中包含了状态机。
Verilog HDL那些事_建模篇笔记(实验九:VGA驱动)的更多相关文章
- Verilog HDL那些事_建模篇笔记(实验一,实验二)
实验一:永远的流水灯 扫描频率配置为100Hz,即是说扫描周期为10ms.这里需要注意的是扫描周期的概念.流水灯嘛,顾名思义,扫描周期指的是流水灯扫一轮所需要的时间.听到说周期,就应该想到在建模的时候 ...
- Verilog HDL那些事_建模篇笔记(实验八:键盘解码)
1.PS2接口与协议时序图 对于PS2的接口来说,需要额外关注的是PIN5与PIN1,一个是时钟,一个是数据.PS2协议对数据的移位是“CLOCK下降沿”有效,其CLOCK的频率通常在10KHz左右. ...
- Verilog HDL那些事_建模篇笔记(实验七:数码管电路驱动)
1.同步动态扫描 多个数码管的显示采用的是同步动态扫描方法,同步动态扫描指的是:行信号和列信号同步扫描,是一种并行操作. 2.数码管驱动电路实现思路 如果要求数码管显示我们想要的数字,首先需 ...
- Verilog HDL那些事_建模篇笔记(实验三:按键消抖)
实验三:按键消抖 首先将按键消抖功能分成了两个模块,电平检查模块和10ms延迟模块.电平检测模块用来检测按键信号的变化(是否被按下),10ms延迟模块用来稳定电平检查模块的输入,进而稳定按键信号,防止 ...
- 基于Verilog HDL 的数字时钟设计
基于Verilog HDL的数字时钟设计 一.实验内容: 利用FPGA实现数字时钟设计,附带秒表功能及时间设置功能.时间设置由开关S1和S2控制,分别是增和减.开关S3是模式选择:0是正常时钟 ...
- 【黑金教程笔记之003】【建模篇】akuei2的Verilog hdl心路
Verilog hdl不是“编程”是“建模” Verilog hdl语言是一种富有“形状”的语言. 如果着手以“建模”去理解Verilog hdl语言,以“形状”去完成Verilog hdl语言的设计 ...
- 【转】Verilog HDL常用建模方式——《Verilog与数字ASIC设计基础》读书笔记(四)
Verilog HDL常用建模方式——<Verilog与数字ASIC设计基础>读书笔记(四) Verilog HDL的基本功能之一是描述可综合的硬件逻辑电路.所谓综合(Synthesis) ...
- Verilog HDL实用教程笔记
Verilog HDL实用教程笔记 DRC - Design Rule Check 几何规则检查ERC - Electrical Rule Check 电学规则检查自动参数提取LVS - Logic ...
- 【黑金教程笔记之003】【建模篇】【Lab 02 闪耀灯和流水灯】—笔记
(1) 扫描频率和闪耀频率? 模块: /**************************************** module name:flash_module function ...
随机推荐
- Python学习路程day19
Python之路,Day19 - Django 进阶 本节内容 自定义template tags 中间件 CRSF 权限管理 分页 Django分页 https://docs.djangoproj ...
- Java网络编程及安全
一.实验内容: 1.运行教材上TCP代码,结对进行,一人服务器,一人客户端: 2.利用加解密代码包,编译运行代码,一人加密,一人解密: 3.集成代码,一人加密后通过TCP发送: 注:加密使用AES或者 ...
- 2016-08-05(1) ng-options的用法详解
http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/ng-options-usage/
- 从service弹出系统级自定义提示框,可在任意页面弹出
添加权限 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> // 显示 ...
- android4.4以上,快捷实现标题栏透明
方法很简单写一个values-v19的文件夹,当安卓版本大于4.4时便会调用该文件夹下的styles.xml文件 结构如图: styles.xml <resources> <!-- ...
- centos7下安装nodejs
http://www.runoob.com/nodejs/nodejs-install-setup.html这个教程中注明 注意:Linux上安装Node.js需要安装Python 2.6 或 2.7 ...
- (zhuan)Python 虚拟环境:Virtualenv
Python 虚拟环境:Virtualenv zhuanzi: http://liuzhijun.iteye.com/blog/1872241 virtualenv virtualenv用于创建独立的 ...
- DIPHA
https://github.com/DIPHA/dipha http://www.rkwitt.org/blog/topological_machine_learning.html 一.预装软件 1 ...
- 十个最适合 Web 和 APP 开发的 NodeJS 框架
在浏览器以外运行 JavaScript 对于 JavaScript 爱好者来说非常神奇,同时也肯定是 web 应用程序开发界最受欢迎的进步之一.全球各地的开发者张开双臂拥抱 NodeJS. 对于新手来 ...
- android沉浸式状态栏设置(4.4以上版本)
其实设置比较简单,我用了小米和htc的几款机型都可以用. 主要代码就是这个(注意要在Activity的setContentView之前调用才行) /** * 开启沉浸式状态栏 * */ public ...