FPGA实现“打字机”(VGA & UART)
看到标题中的“打字机”三个字,你是不是脑补了下面这幅图像。这是二战电影中常出现的道具,现在恐怕都见不到了。
●电影道具“打字机”
我要实现的当然不是这个样子,只是功能上与之相似。先让你们看看实现的效果,直接上图。
●这是串口发的字符串
●显示屏显示的字符
之所以要写这个“打字机”工程,那是因为我在学习FPGA的道路上,它是我重要的一关。我一开始学FPGA,是从数字电路开始入门的,然后就是学习使用QuartusII,编写Verilog代码。我写的第一个工程是数字时钟(6个数码管两个一组实现时钟、分钟、秒钟的计时),通过它我学会了基本的逻辑(时序逻辑、组合逻辑,以及我们用的最频繁的译码器和选择器)。接下来就是这个“打字机”了,其实一开始这是学长给我布置的一个任务(现在想想学长也是用心良苦),通过它我基本上领会了如何驱动外设以及用各个外设组合成我们需要的工程(也就是模块化设计)。我相信,对于很多还在朝FPGA入门的同学来说,通过这个工程,你们的能力能获得显著提升。
好了,话就不多说了,接下来就来看看这个工程是怎么实现的。我们先来看看RTL视图:
●RTL视图
从该图中可以看到,这里一共有5个模块:PLL模块、UARTRX接收模块、DISMEM显存模块、GETZIMO字模译码模块、VGA显示模块。PLL模块产生VGA(800*600@60Hz)所需的40M时钟,UARTRX模块接收上位机发来的数据,显存模块保存需要显示的字符,字模模块将显存的字符译码成VGA模块需要的数据。PLL、UARTRX、VGA这三个模块就不讲了,这是学习FPGA必然要遇到的模块(网上有很多代码),接下来就给大家重点分析一下显存模块和字模译码模块。
显存模块,顾名思义就是仿造显卡的显存,将显示的内容保存起来,当显示模块需要的时候再取出来。当我们按顺序将UART接收到的字符放入RAM中时,有一个问题,如果写满了RAM怎么办?当然,可以这么做,从头开始写,一直循环。那么读操作也按顺序读就会有问题了,这时如果写满了,之前显示的内容就突然没了。可是我们希望当写满时所有行都能往上卷一行,这样就和我们平时打字的效果一样了。解决这个问题的办法是改变读地址和写地址的映射关系。通常,读写地址是这么映射的:
为了解决该问题,映射关系改成这样:
每当写满一页,读地址就往上卷动一行(也就是减去一行)。具体的代码就是:
//从串口来一个数据就加1,直到计满清零
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
RAM_WP <= 'h0;
else
RAM_WP <= RAM_WP_N;
end always @ (*)
begin
if(RAM_WP == 'd3699 && DATAFLAG)
RAM_WP_N = 'h0;
else if(DATAFLAG)
RAM_WP_N = RAM_WP + 'h1;
else
RAM_WP_N = RAM_WP;
end //RAM_WP对100取模得RAM_WP100,可以作为写指针的列
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
RAM_WP100 <= 'h0;
else
RAM_WP100 <= RAM_WP100_N;
end
always @ (*)
begin
if(RAM_WP100 == 'd99 && DATAFLAG)
RAM_WP100_N = 'h0;
else if(DATAFLAG)
RAM_WP100_N = RAM_WP100 + 'h1;
else
RAM_WP100_N = RAM_WP100;
end //以下实现卷行 //判断页尾,判断成功则一直保持
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
sroll_flag <= 'b0;
else
sroll_flag <= sroll_flag_n;
end
always @ (*)
begin
if(RAM_WP == 'd3699 && DATAFLAG)
sroll_flag_n = 'b1;
else
sroll_flag_n = sroll_flag;
end
字模译码模块就是将从显存RAM中的字符译码得到VGA需要显示的数据,这是因为字符是不能直接给VGA显示的,所以有这个译码的过程。译码过程需要根据显示的位置得到VGA显示的像素,也就是根据字符从ROM中(里面存有字模信息)取得字符的字模,其过程见代码:
//得到需要输出的字模数据的哪行,打一拍
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
linechar <= 'h0;
else
linechar <= position_VS[:];
end
//得到该行数据
GETLINE getlineA
(
.CLK_50M (CLK_50M ),
.CHAR (CHAR ),
.linechar (linechar ),
.dataline (dataline )
); //得到需要输出字模数据的某列
always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
bitcnt <= 'h0;
else
bitcnt <= bitcnt_n;
end always @ (posedge CLK_50M or negedge RST_N)
begin
if(!RST_N)
bitcnt_n <= 'h0;
else
bitcnt_n <= position_HS[:];
end //得到字模数据某行某列上的值,并将这一位值译成8位数据(8'hff或8'h0)
DECODEPIXEL decodeA
(
.datain (dataline ),
.bitcnt (bitcnt ),
.dataout (databit )
); assign DATAOUT = databit;
这个“打字机”的工作流程可以通过下图来理解,数据由上位机发过来,UART模块接收,当接收到一个完整字符时,将这个字符写入到RAM。RAM中的数据读出后经过ROM译码,最后通过VGA送给显示器显示。
●字符信息流
“打字机”的具体实现就是上面将的这些,有兴趣的朋友可以在此基础上改进,改进的内容可以是增加控制字符的操作,也可以是将显示的字符保存到SDRAM中这样就可以容纳更多的字符了。另外,需要源码的朋友可以在这个地址下载: https://pan.baidu.com/s/1jIqnI1C。
让大家看一下我的实物,最近入手了一块锆石科技出品的A4开发板。在这块开发板上搭载了一颗Altera公司的EP4CE10F17C8,功能强大并且外设齐全,非常适合初学者。
需要说明一下,这篇文章是仅仅我发的第一篇博文,而且只是一个小工程,也是让大家在学习FPGA的过程中有一个很好的练手的机会。在后面,我还会定期推出更多的自己在FPGA学习道路上的经验心得,而且绝对是干货(比如USB2.0、USB3.0、DDR2、SDcard、摄像头等等)哦!小伙伴们可以持续关注我,更多惊喜等着你。
FPGA实现“打字机”(VGA & UART)的更多相关文章
- 模拟摄像头解码模块最新测试 TVP5150模块 FPGA+SDRAM+TVP5150+VGA 实现PAL AV输入 VGA视频输出
模拟摄像头解码模块最新测试 TVP5150模块 FPGA+SDRAM+TVP5150+VGA 实现PAL AV输入 VGA视频输出 测试使用电视机顶盒的AV模拟信号输入,VGA显示器输出测试,效 ...
- 从FPGA搞定OV7670 VGA显示 移植到 STM32F10x TFT显示 总结及疑问(高手请进)
OV7670不愧是最便宜的摄像头了最大显示像素:640*480(在VGA显示器上显示效果还不赖,用usb模块采集显示依然显著) 第一步:VGA显示 视频图像(实时)FPGA+SDRAM+OV7670= ...
- 基于FPGA的VGA显示实验设计
基于FPGA的VGA显示实验设计 成果展示(优酷视频): 视频: 基于FPGA的VGA显示技术(手机控制) http://v.youku.com/v_show/id_XNjk4ODE3ODUy.htm ...
- 202-基于TI DSP TMS320C6678、Xilinx K7 FPGA XC7K325T的高速数据处理核心板
该DSP+FPGA高速信号采集处理板由我公司自主研发,包含一片TI DSP TMS320C6678和一片Xilinx FPGA K7 XC72K325T-1ffg900.包含1个千兆网口,1个FMC ...
- VGA调试心得
以前自己调试过视频信号,无非就时钟加行场同步加数据线,如果视频信号出问题,第一看现象,第二测频率,反正出问题不是消隐信号出问题,就是时钟频率出问题.通过这种方式也调试成功过几个显示屏,然后就以为自己对 ...
- 基于TI DSP TMS320C6678、Xilinx K7 FPGA XC7K325T的高速数据处理核心板
一.板卡概述 该DSP+FPGA高速信号采集处理板由我公司自主研发,包含一片TI DSP TMS320C6678和一片Xilinx FPGA K7 XC72K325T-1ffg900.包含1个千兆网口 ...
- 数控AGC实现(转)
相关链接: 一种混合式高动态范围AGC算法与FPGA实现 http://www.sohu.com/a/221438387_781333 基于FPGA的快速自动增益控制系统设计 ...
- MATLAB串口操作和GUI编程
程序说明 V1.0 2015/2/08 MATLAB串口操作和GUI编程 概述 本文介绍了程序AD9512_Serial_GUI的编程思路和功能.该程序设计到MATLAB的图像用户界面编程的基 ...
- 【扫盲贴】为什么屏幕分辨率是 640x480
本文原地址:http://www.easyx.cn/skills/View.aspx?id=172 常见的屏幕分辨率很奇怪,为什么总用一些不零不整的数字?比如以前最常见的分辨率是 640x480,当初 ...
随机推荐
- 每天一个JS 小demo之商品下架特效制作,主要知识点:定时器,倒计时,抖动特效。PS:由于不方便上传文件夹,只能上传效果图,图片等素材需自寻哟。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- jquery+js实现鼠标位移放大镜效果
jQuery实现仿某东商品详情页放大镜效果 用jquery+js实现放大镜效果,效果大概如下图! 效果是不是大家很感兴趣,放大镜查看细节,下边大家可以详细看一看具体是怎么实现的.下边直接看代码! HT ...
- nodejs零基础详细教程1:安装+基础概念
第一章 建议学习时间2小时 课程共10章 学习方式:详细阅读,并手动实现相关代码 学习目标:此教程将教会大家 安装Node.搭建服务器.express.mysql.mongodb.编写后台业务逻辑. ...
- 在.net下打造mongoDb基于官方驱动最新版本
还是一如既往先把结构图放出来,上上个版本添加了redis的缓存,但是不满足我的需求,因为公司有项目要求是分布式所以呢,这里我就增加了mongoDb进行缓存分布式,好了先看结构图. 总的来说比较蛋疼,因 ...
- 关于Eclipse+SVN 开发配置
入职快一个月,学的比较慢,但学的东西很多,受益匪浅.有时候真正意义上,感受到:代码使我快乐,我爱编程. 好久没有开笔,不知道说些什么,也不知道应该说什么. 但总觉得有些东西,很想说出来,不用理会他人的 ...
- MVC 树节点Table格式授权
这几夜心里颇不平静, 奈何 JS水平有限,前台效果耗时四天,后台传值一天,直至昨夜丑时测试初步完成,其实就是一个给tree来授权,网上开源的插件很多,如treejs.easyui 等等,只是这里授权稍 ...
- html锚点 点击跳转到页面指定位置
本来是在看阮大神写的ajax教程,突然发现点击目录文字会跳转到相对应的文本内容,于是乎激发了我的兴趣. 这个究竟怎么做的,刚开始看的时候一知半解,找度娘就是:"点击跳转到页面指定位置&quo ...
- JS事件及其兼容用法
JavaScript与HTML之间的交互是通过事件实现的.事件,就是文档或浏览器窗口中发生的一些特定的交互瞬间. 1.事件流:描述的是从页面中接收事件的顺序. IE提出的事件冒泡流:事件开始由最具体的 ...
- [0] C#软件项目版本号的命名规则及格式介绍
版本控制比较普遍的 3 种命名格式 : 一.GNU 风格的版本号命名格式 : 主版本号 . 子版本号 [. 修正版本号 [. 编译版本号 ]] 英文对照 : Major_Version_Number. ...
- 【译】Reflection.Emit vs. CodeDOM
原文:http://ayende.com/blog/1606/reflection-emit-vs-codedom Both technologies allow you to generate ex ...