1 图片预处理
在本次实验中,我们用来存储图片的ROM是通过调用IP核,利用FPGA片上资源生成的只读存储器,但FPGA片上资源有限,生成ROM的存储空间也会受限,存储于ROM的图片大小也受到限制。
FPGA开发板上使用的芯片为Altera公司的EP4CE15F23C8芯片,存储空间为414Kbit;本次实验显示图片分辨率为100*100,色彩格式为RGB565,存储于ROM所占空间为100*100*16=160000bit=156.25Kbit。通过比较发现,芯片可生成满足要求的ROM 用来存储图片。
ROM作为只读存储器,在进行IP核设置时需要指定初始化文件, 即写入存储器中的图片数据,图片要以规定的格式才能正确写入ROM,这种格式就是MIF文件。MIF是Quartus规定的一种文件格式,文件格式示意图,具体见图:
若存储数据量较小,我们可以参照上图,手动写入数据。但如果存储量较大,手动输入不太现实。本次实验中要写入100*100个数据,不可能使用手动输入,在这里我们使用Matlab软件将图片转化为MIF文件,具体步骤如下。
clear %清理命令行窗口
clc %清理工作区
% 使用imread函数读取图片,并转化为三维矩阵
image_array = imread('D:\FPGA\FPGA_Basic_Pro\vga_rom_pic\matlab\curry.bmp');
% 使用size函数计算图片矩阵三个维度的大小
% 第一维为图片的高度,第二维为图片的宽度,第三维为图片维度
[height,width,z]=size(image_array); % 100*100*3
red = image_array(:,:,1); % 提取红色分量,数据类型为uint8
green = image_array(:,:,2); % 提取绿色分量,数据类型为uint8
blue = image_array(:,:,3); % 提取蓝色分量,数据类型为uint8
% 使用reshape函数将各个分量重组成一个一维矩阵
%为了避免溢出,将uint8类型的数据扩大为uint32类型
r = uint32(reshape(red' , 1 ,height*width));
g = uint32(reshape(green' , 1 ,height*width));
b = uint32(reshape(blue' , 1 ,height*width));
% 初始化要写入.mif文件中的RGB颜色矩阵
rgb=zeros(1,height*width);
% 导入的图片为24bit真彩色图片,每个像素占用24bit,RGB888
% 将RGB888转换为RGB565
% 红色分量右移3位取出高5位,左移11位作为ROM中RGB数据的第15bit到第11bit
% 绿色分量右移2位取出高6位,左移5位作为ROM中RGB数据的第10bit到第5bit
% 蓝色分量右移3位取出高5位,左移0位作为ROM中RGB数据的第4bit到第0bit
for i = 1:height*width
rgb(i) = bitshift(bitshift(r(i),-3),11) + bitshift(bitshift(g(i),-2),5) + bitshift(bitshift(b(i),-3),0);
end
fid = fopen( 'D:\FPGA\FPGA_Basic_Pro\vga_rom_pic\matlab\image.mif', 'w+' );
% .mif文件字符串打印
fprintf( fid, 'WIDTH=16;n');
fprintf( fid, 'DEPTH=%d;nn',height*width);
fprintf( fid, 'ADDRESS_RADIX=UNS;n');
fprintf( fid, 'DATA_RADIX=HEX;nn');
fprintf(fid,'%snt','CONTENT');
fprintf(fid,'%sn','BEGIN');
% 写入图片数据
for i = 1:height*width
fprintf(fid,'\t\t%d\t:%x\t;\n',i-1,rgb(i));
end
% 打印结束字符串
fprintf(fid,'\tEND;');
fclose( fid ); % 关闭文件指针
2 模块框图
3 模块波形图
第一部分:彩条背景色彩信息(pi_data)波形图绘制思路
根据输入像素点坐标(pix_x,pix_y),在有效显示区域,将pix_x计数范围十等分,在不同的计数部分给pix_data赋值对应的色彩信息,因为采用时序逻辑的赋值方式,pix_data滞后pix_x、pix_y信号一个时钟周期。信号波形图如下:
第二部分:ROM读使能(rd_en)、ROM地址(rom_addr)波形图绘制思路
我们将要显示的的图片数据是事先写入ROM,ROM为调用IP核生成,写入照片分辨率为100*100。要想将写入ROM的图片读取出来,使能信号和地址信号必不可少,所以模块内部要声明ROM读使能信号(rd_en)和ROM地址(rom_addr)信号。
我们可以在图片显示区域拉高使能信号,将要读取数据地址写入ROM地址端口,读取地址对应图像数据。但有一点要注意,自ROM读取的数据是滞后使能信号和地址信号一个时钟周期的,比如,当使能信号为高电平,地址写入为999,但与地址999同步输出的数据为地址998的数据,所以ROM读使能信号(rd_en)和RO M地址(rom_addr)信号均要超前图片显示区域一个时钟周期,信号波形图绘制如下:
第三部分:图片显示有效信号(pic_valid)、待显示图像数据(pic_data_out)波形图绘制思路
想要在彩条图像背景上显示要显示的图片,我们需要在图片显示区域,使用图片数据覆盖彩条背景,那么如何确定图像显示区域呢?我们需要声明一个内部信号,那就是图片显示有效信号(pic_valid),在有效信号为高电平时,将自ROM读出的图片数据赋值给待显示图像数据(pic_data_out),覆盖彩条背景。
上文中我们提到ROM读使能信号(rd_en)超前图片显示区域一个时钟周期,可以利用此信号 延迟一个时钟周期生成图片显示有效信号(pic_valid);在有效信号为高电平时,将自ROM读出的图片数据赋值给待显示图像数据(pic_data_out),覆盖彩条背景。信号波形图如下:
3 程序资源
见压缩包。