完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
2)摘自《开拓者FPGA开发指南》关注官方微信号公众号,获取更多资料:正点原子
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-13912-1-1.html 第二十一章 VGA图片显示实验(基于ROM) 我们在“VGA字符显示实验”中利用一个二维数组存储字符的点阵数据,进而实现汉字的 显示。字符显示时每个像素点采用二维数组中的1位(bit)数据来表示,只有0和1的差别,即 只能区分两种颜色。然而在显示图片时,由于1bit的数据无法区分各像素点的色彩差异,因此 二维数组已经不能满足图片存储的需要。本章我们将通过例化IP核来实现使用ROM存储图片, 并将ROM中存储的图片通过VGA接口显示到屏幕上。 本章包括以下几个部分: 21.1 VGA简介 21.2 实验任务 21.3 硬件设计 21.4 程序设计 21.5 下载验证 VGA简介 我们在“VGA彩条显示实验”中对VGA视频传输标准作了详细的介绍,包括VGA接口定义、 行场同步时序、以及显示分辨率等。如果大家对这部分内容不是很熟悉的话,请参考“VGA彩 条显示实验”中的VGA简介部分。 实验任务 本章的实验任务是使用开拓者开发板上的VGA接口在显示器的屏幕中心位置显示彩色图片。 显示分辨率为640*480,刷新速率为60hz,图片的大小为100*100。 硬件设计 VGA接口部分的硬件设计原理及本实验中各端口信号的管脚分配与“VGA彩条显示实验”完 全相同,请参考“VGA彩条显示实验”中的硬件设计部分。 程序设计 图 21.4.1是根据本章实验任务画出的系统框图。其中,时钟分频模块负责产生像素时钟, VGA驱动模块产生行场同步信号及像素点的纵横坐标,VGA显示模块输出图像数据,ROM用于存 储需要显示的图片。 图 21.4.1 基于ROM的VGA图片显示实验系统框图 VGA显示模块中的ROM是通过例化IP核来实现的只读存储器,它使用FPGA的片上存储资源。 由于FPGA的片上存储资源有限,所以ROM中存储的图片大小也受到限制。由于开拓者开发板上 的VGA接口采用RGB565数据格式,即每个像素点的颜色用16bit的数据来表示,因此大小为100*100的图片占用的存储空间为100*100*16bit=160000bit=156.25Kbit(1Kbit=1024bit)。 而开拓者开发板上的FPGA片上存储资源为414Kbit,能够满足实验任务中的图片存储需求。 ROM作为只读存储器,在调用IP核时需要指定初始化文件,在这里就是写入存储器中的图 片数据,各种格式的图片(bmp、jpg等)都是以MIF文件的形式导入到ROM中的。MIF是一种Quartus 工具能识别的文件格式,在文件的开头定义了存储器的位宽和深度、地址格式、数据格式等信 息,紧接着列出了存储单元地址以及写入各地址的数据。例如,一个位宽为16,深度为5的MIF 文件内容如下图所示: 图 21.4.2 MIF文件示例 当需要存储的数据量较小时,如果我们知道数据的内容,那么就可以仿照图 21.4.2的格 式手动编写MIF文件。但是由于图片的数据量较大,并且我们无法直接看出各个像素点对应的 颜色数据,因此需要借助工具来实现图片到MIF文件的转换。在这里我们使用正点原子提供的 工具“PicToMif”来实现这一转换过程,该工具位于开发板所随附的资料中“6_软件资料/1_ 软件/PicToMif”目录下。 我们在Windows自带的“画图”工具中将正点原子的LOGO图片大小调整100*100,并利用工 具PicToMif转换得到MIF文件“ZDYZ.mif”。 双击运行“PicToMif.exe”,点击“加载图片”并在弹出的界面中选择需要转换的图片 (注意:待转换图片分辨率的大小必须是100*100),图片加载成功后工具会在图片属性中指示 出图片的文件名和大小;接下来选择图片转换的数据格式为RGB565;最后点击“一键转换”按 钮,在弹出的界面中选择MIF文件的存放路径并输入文件名。PicToMif转换过程中的软件界面 如图 21.4.3所示: 图 21.4.3 PicToMif转换界面 最终转换得到的MIF文件部分截图如下所示: 图 21.4.4 转换得到的MIF文件 程序中各模块端口及信号连接如图 21.4.5所示: 图 21.4.5 顶层模块原理图 图 21.4.5中的顶层模块(vga_blockmove)、时钟分频模块(vga_pll)以及VGA驱动模块 (vga_driver)均与“VGA彩条显示实验”完全相同,只对VGA显示模块(vga_display)作了 修改。因此,这里我们重点讲解VGA显示模块,其他部分大家可以参考“VGA彩条显示实验”。 VGA显示模块的代码如下: 1 module vga_display( 2 input vga_clk, //VGA驱动时钟 3 input sys_rst_n, //复位信号 4 5 input [ 9:0] pixel_xpos, //像素点横坐标 6 input [ 9:0] pixel_ypos, //像素点纵坐标 7 output [15:0] pixel_data //像素点数据 8 ); 9 10 //parameter define 11 parameter H_DISP = 10'd640; //分辨率——行 12 parameter V_DISP = 10'd480; //分辨率——列 13 14 localparam POS_X = 10'd270; //图片区域起始点横坐标 15 localparam POS_Y = 10'd190; //图片区域起始点纵坐标 16 localparam WIDTH = 10'd100; //图片区域宽度 17 localparam HEIGHT = 10'd100; //图片区域高度 18 localparam TOTAL = 14'd10000; //图案区域总像素数 19 localparam BLACK = 16'b00000_000000_00000; //屏幕背景色 20 21 //reg define 22 wire rom_rd_en; //读ROM使能信号 23 reg [13:0] rom_addr; //读ROM地址 24 reg rom_valid; //读ROM数据有效信号 25 26 //wire define 27 wire [15:0] rom_data; //ROM输出数据 28 29 //***************************************************** 30 //** main code 31 //***************************************************** 32 33 //从ROM中读出的图像数据有效时,将其输出显示 34 assign pixel_data = rom_valid ? rom_data : BLACK; 35 36 //当前像素点坐标位于图片显示区域内时,读ROM使能信号拉高 37 assign rom_rd_en = (pixel_xpos >= POS_X) && (pixel_xpos < POS_X + WIDTH) 38 && (pixel_ypos >= POS_Y) && (pixel_ypos < POS_Y + HEIGHT) 39 ? 1'b1 : 1'b0; 40 41 //控制读地址 42 always @(posedge vga_clk or negedge sys_rst_n) begin 43 if (!sys_rst_n) begin 44 rom_addr <= 14'd0; 45 end 46 else if(rom_rd_en) begin 47 if(rom_addr < TOTAL - 1'b1) 48 rom_addr <= rom_addr + 1'b1; //每次读ROM操作后,读地址加1 49 else 50 rom_addr <= 1'b0; //读到ROM末地址后,从首地址重新开始读操作 51 end 52 else 53 rom_addr <= rom_addr; 54 end 55 56 //从发出读使能到ROM输出有效数据存在一个时钟周期的延时 57 always @(posedge vga_clk or negedge sys_rst_n) begin 58 if (!sys_rst_n) 59 rom_valid <= 1'b0; 60 else 61 rom_valid <= rom_rd_en; 62 end 63 64 //通过调用IP核来例化ROM 65 pic_rom pic_rom_inst( 66 .clock (vga_clk), 67 .address (rom_addr), 68 .rden (rom_rd_en), 69 .q (rom_data) 70 ); 71 72 endmodule 代码中14至19行声明了一系列的变量,方便大家修改图片的大小、在屏幕上显示的位置等, 其中图片显示的位置由图片显示区域左上角的纵横坐标来指定。 由于图片存储在ROM中,因此VGA显示模块的主要任务就是控制ROM的读使能及读地址,从 而在合适的时间段将ROM中的图片数据读出并显示。代码的36至39行判断当前像素点的纵横坐 标,当其位于图片显示区域时将ROM读使能信号rom_rd_en拉高。第41至54行在读操作过程中将 读地址依次累加,从而将图片数据顺序读出;当读到未地址后读地址清零,重新从ROM中图像 的第一个像素点数据开始读取。 读ROM的过程中,从发出读使能到ROM输出有效数据存在一个时钟周期的延时,因此ROM数 据有效信号rom_valid需要由rom_rd_en延迟一个时钟周期,如程序第56至62行所示。 程序第64~70行例化了ROM IP核,在工程中调用IP核时,需要设置ROM位宽为16bit,深度为 选择16384(不能低于100*100),如图 21.4.7所示。此外,为了保证从ROM的读使能信号拉高 到有效数据输出之间仅存在一个时钟周期的延时,需要取消寄存端口输出,如图 21.4.8红色 方框所示。 图 21.4.6 新建ROM IP核 图 21.4.7 配置ROM位宽及深度 图 21.4.8 取消寄存端口输出 最后,在“Mem Init”页选择前面生成的初始化文件“ZDYZ.mif”,如图 21.4.9所示。 注意需要将该MIF文件置于工程目录下,本工程中的MIF文件位于vga_rom_pic/doc文件夹下。 图 21.4.9 选择存储器初始化文件 图 21.4.10为VGA显示模块显示图片时SignalTap抓取的波形图。从图中可以看到,在ROM 读使能信号rom_rd_en拉高时,读地址rom_addr依次累加。同时数据有效信号rom_valid相对于 rom_rd_en延时一个时钟周期。 图 21.4.10 VGA显示模块SignalTap波形图 下载验证 基于ROM的VGA图片显示实验的工程位于vga_rom_pic/par文件夹下,工程打开后如图 21.5.1所示: 图 21.5.1 基于ROM的VGA图片显示 请大家参考VGA彩条显示实验中的下载验证方法,将vga_rom_pic/par/output_files目录 下的“vga_rom_pic.sof”文件下载至开发板。下载完成后在VGA显示器上观察显示的图片如图 21.5.2所示,说明基于ROM的VGA图片显示程序下载验证成功。 图 21.5.2 基于ROM的VGA图片显示效果图 |
|
相关推荐
|
|
飞凌嵌入式ElfBoard ELF 1板卡-移植前准备之git管理内核源码
403 浏览 0 评论
702 浏览 0 评论
迅为RK3568开发板篇OpenHarmony实操HDF驱动控制LED-接口函数
752 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡-本地仓库管理之分支间的操作
667 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡-本地仓库管理之当前分支内的操作
1005 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-23 04:41 , Processed in 0.506466 second(s), Total 65, Slave 48 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号