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:height
    for 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) begin
    if(!rst_n)
        cnt_h <= 0;
    else if( cnt_h == H_Total - 1 )
        cnt_h <= 0;
    else
        cnt_h <= cnt_h + 1;
end

//场周期计数
always @(posedge pclk) begin
    if(!rst_n)
        cnt_v <= 0;
    else if( cnt_h == H_Total - 1 ) begin
        if( cnt_v == V_Total - 1 )
            cnt_v <= 0;
        else
            cnt_v <= cnt_v + 1; 
    end
    else
        cnt_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) begin
    if( !rst_n )
        data_reg <= 0;
    else if (De) begin
        if ((X >= data_x && X <= SIZE + data_x) && (Y >= data_y && Y <= data_y + WIDE))
				data_reg <= q;
        else
				data_reg <= 16'hffff;
    end
    else
        data_reg <= 0;
end

//控制地址
always @(posedge clk) begin
    if(!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;
    else
        address <= address;
end


assign data_rgb = data_reg;

rom	rom_inst (
	.aclr ( !rst_n ),
	.address ( address ),
	.clock ( clk ),
	.q ( q )
	);


endmodule

五、现象


以上就是VGA静态显示图片。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值