FPGA学习笔记——VGA显示静态图片(ROM IP核)
目录
一、任务
二、分析
(1)分析
(2)用MATLAB创建.mif文件
三、配置
四、代码
五、现象
一、任务
将下面这幅图片用VGA进行显示,它的分辨为120x68,其中VGA的模式为640x480@60。
二、分析
(1)分析
首先,知道图片的分辨率,可以知道它的大小120x68 = 8160,在配置ROM IP核的深度的时候就是这么大。
其次,VGA的模式为640x480@60,它的行同步有效信号为640,场同步有效信号为480,如下图所示。
首先,先定义好图片的初始坐标X,Y,再根据图片的分辨率来写代码,再图片的有效图像里面给颜色赋值,其它位置就以其它颜色为底色。
(2)用MATLAB创建.mif文件
如何用上面给的图片创建出.mif文件:
我这里是用MATLAB来生成.mif文件,将上面的图片添加到对应的路径下面,然后运行对应的代码就能生成.mif文件。
代码只能生成RGB565格式的.mif文件
% 读取当前文件夹下名为14.bmp的文件
I = imread('2.jpg'); % 获取图像的尺寸
[height, width, ~] = size(I);% 计算总像素数
total_pixels = height * width;% 新建保存数据的mif文件
fid = fopen('2.mif', 'w+'); % 写入MIF文件的头部信息
fprintf(fid, 'DEPTH = %d;\n', total_pixels); % 存储单元数量
fprintf(fid, 'WIDTH = 16;\n'); % 每个存储单元的位数
fprintf(fid, 'ADDRESS_RADIX = HEX;\n'); % 地址的进制
fprintf(fid, 'DATA_RADIX = HEX;\n'); % 数据的进制
fprintf(fid, 'CONTENT BEGIN\n');% 像素索引
pixel_index = 0;% 遍历图像的每一个像素
for a = 1:heightfor b = 1:width% 提取当前像素的 RGB 通道值red = I(a, b, 1);green = I(a, b, 2);blue = I(a, b, 3);% 将 8 位通道值转换为 RGB565 对应的位数red_5bit = bitshift(red, -3); % 8 位转 5 位green_6bit = bitshift(green, -2); % 8 位转 6 位blue_5bit = bitshift(blue, -3); % 8 位转 5 位% 合并为 16 位的 RGB565 数据rgb565_pixel = bitshift(uint16(red_5bit), 11) + bitshift(uint16(green_6bit), 5) + uint16(blue_5bit);% 写入地址和数据fprintf(fid, '%04x : %04x;\n', pixel_index, rgb565_pixel);% 递增像素索引pixel_index = pixel_index + 1;end
end% 写入文件结尾信息
fprintf(fid, 'END;');% 关闭文件
fclose(fid);
三、配置
这里只配置ROM IP核,其它IP核配置可以看看FPGA学习笔记——VGA彩条显示-CSDN博客
注意:要是图片的分辨率太大了,你的ROM可能装不下。
四、代码
top.v
module top (
input wire clk ,
input wire rst_n ,
output wire [15:0] data_rgb ,
output wire Hsync ,
output wire Vsync
);//vga
wire De;
wire [9:0] X;
wire [9:0] Y;vga vga_u(
. pclk (pclk ) ,
. rst_n (locked) ,
. De (De ) , //数据有效信号
. X (X ) ,
. Y (Y ) ,
. Hsync (Hsync ) , //行同步信号
. Vsync (Vsync ) //场同步信号
);data1 data1_u(
. clk (pclk ) ,
. rst_n (locked ) ,
. X (X ) ,
. Y (Y ) ,
. De (De ) ,
. data_rgb (data_rgb )
);wire pclk;
wire locked;pll pll_inst (.areset ( !rst_n ),.inclk0 ( clk ),.c0 ( pclk ),.locked ( locked ));endmodule
vga.v
module vga (
input wire pclk ,
input wire rst_n ,
output wire [9:0] X ,
output wire [9:0] Y ,
output wire De , //数据有效信号
output wire Hsync , //行同步信号
output wire Vsync //场同步信号
);localparam H_Total = 800 ,//行总像素点H_Addr = 640 ,//有效像素点H_Right = 8 ,//右边框H_Front = 8 ,//前沿H_Sync = 96 , //同步H_Back = 40 , //后沿H_Left = 8 ;//左边框localparam V_Total = 525 ,//场总像素点V_Addr = 480 ,//有效像素点V_Bottom = 8 ,//底边框V_Front = 2 ,//前沿V_Sync = 2 , //同步V_Back = 25 , //后沿V_Top = 8 ; //上边框reg [9:0] cnt_h,cnt_v;//行周期计数
always @(posedge pclk) beginif(!rst_n)cnt_h <= 0;else if( cnt_h == H_Total - 1 )cnt_h <= 0;elsecnt_h <= cnt_h + 1;
end//场周期计数
always @(posedge pclk) beginif(!rst_n)cnt_v <= 0;else if( cnt_h == H_Total - 1 ) beginif( cnt_v == V_Total - 1 )cnt_v <= 0;elsecnt_v <= cnt_v + 1; endelsecnt_v <= cnt_v;
end//行场同步信号
assign Hsync = (cnt_h < H_Sync ) ? 1 : 0;
assign Vsync = (cnt_v < V_Sync ) ? 1 : 0;
assign De = ((cnt_h > H_Sync + H_Back + H_Left - 1) &&(cnt_h < H_Sync + H_Back + H_Left + H_Addr) &&(cnt_v >= V_Sync + V_Back + V_Top ) &&(cnt_v < V_Sync + V_Back + V_Top + V_Addr) ) ? 1 : 0;assign X = (De == 1) ? (cnt_h - H_Sync - H_Back - H_Left) : 0 ;
assign Y = (De == 1) ? (cnt_v - V_Sync + V_Back + V_Top ) : 0 ;endmodule
data1.v
module data1 (
input wire clk ,
input wire rst_n ,
input wire De ,
input wire [9:0] X ,
input wire [9:0] Y ,
output wire [15:0] data_rgb
);
//rom
reg [13:0] address;
wire [15:0] q;
reg [3:0] cnt;parameter SIZE = 119;//边长
parameter WIDE = 67 ;reg [15:0] data_reg ;localparam V_Addr = 480 ,//有效像素点H_Addr = 640 ;//有效像素点
parameter data_x = 100 ,data_y = 100 ;//首坐标//产生方格
always @(posedge clk) beginif( !rst_n )data_reg <= 0;else if (De) beginif ((X >= data_x && X <= SIZE + data_x) && (Y >= data_y && Y <= data_y + WIDE))data_reg <= q;elsedata_reg <= 16'hffff;endelsedata_reg <= 0;
end//控制地址
always @(posedge clk) beginif(!rst_n)address <= 0;else if ( (X >= data_x && X <= SIZE + data_x) && (Y >= data_y && Y <= data_y + WIDE) )address <= address + 1;else if ( X > SIZE + data_x && Y > data_y + WIDE )address <= 0;elseaddress <= address;
endassign data_rgb = data_reg;rom rom_inst (.aclr ( !rst_n ),.address ( address ),.clock ( clk ),.q ( q ));endmodule
五、现象
以上就是VGA静态显示图片。