VGA显示图片

vga · 浏览次数 : 0

小编点评

**1. VGA 显示图片的原理** - VGA 显示的色块和字符的数据量比之前更大,因此使用 ROM 来存储图片。 - ROM IP 可以存放mif和hex 格式的图片数据。 **2. 制作 mif 文件** - 打开图片,调整大小后保存为 24 位的 BMP 格式。 - 利用网络下载格式转换工具,将图片转换为 mif 格式。 - 将mif 文件复制到工程目录下。 **3. 使用 ROM IP 在 IP 窗口搜所 ROM** - 设置位宽 24 位,深度 32768 字节。 - 选择 ROM 1 port。 **4. 代码设计** - 在 VGA_control.v 中添加中间变量: - `flag_clear_rom_address` 用于记录 ROM 地址计数器的清零值。 - `cnt_rom_address` 用于记录 rom 中数据的有效地址。 - 图片的定位: - `flag_begin_h` 和 `flag_begin_v` 用于记录图片的有效行和列起始坐标。 - 循环读取 ROM 中的图片数据,并发送到 VGA 显示。 - 标记图片显示有效区: - 根据图片显示有效信号 `picture_flag_enable` 确定区域是否有效。 - 设置 `flag_begin_h` 和 `flag_begin_v` 用于记录有效区域的起始坐标。 **5. 代码片段** ```v // picture and rom address counter assign flag_clear_rom_address=(cnt_rom_address==height*width-1); assign flag_begin_h=pos_x>((640-width)/2) && pos_x<((640-width)/2+width+1); assign flag_begin_v=pos_y>((480-height)/2) && pos_y<((480-height)/2+height+1); assign picture_flag_enable=flag_begin_h&&flag_begin_v; // rom inis rom rom_inst(.address(cnt_rom_address),.clock(clk),.q(rom_data)); // loop and send data while (1)begin always @ (posedge clk, negedge rst_n)if (!rst_n)cnt_rom_address<=0;else if(flag_clear_rom_address)cnt_rom_address<=0;else if(picture_flag_enable)cnt_rom_address<=cnt_rom_address+1;elsecnt_rom_address<=cnt_rom_address; // read rom data vga_rgb <= 24'b000000000000000000000000; if(picture_flag_enable)vga_rgb <= rom_data; else vga_rgb <= 24'b000000000000000000000000; } ```

正文

VGA显示图片

1. VGA显示图片的原理

图片比之前显示的色块和字符的数据量大,所以使用rom来存储图片。用到ROM IP。可以存放mifhex格式,需要先把图片转换成mif格式。

 

2. 如何制作mif文件

先用windows自带的画图工具打开图片,调整大小。步骤:点击重新调整大小,不勾选“保持从横比”,输入像素(如:160*120.最后,另存为,选择24bitbmp格式。利用网络下载的格式转换工具,把图片转换成mif格式,注意。图片格式选RGB88824位。将mif文件复制到工程目录下。图片格式转换工具,经实测,推荐BMP2MIF

 

3. 调用ROM IP

IP窗口搜所rom,选择ROM 1 port。(1)设置位宽24位,深度32768字节。

 

 

 

 

深度大小设置为比图片大即可。可以自行换算,图片的每个点都是24位,160*120=19200个,所以这里选择32768,才装的下这个图片的数据。也就是,rom可以够大,但不能小。连续点Next,直到下图,选择mif文件。

 

 

4. 代码设计

先在VGA_control.v中添加中间变量:

显示图片,需要先定义图片的大小,即长和宽,160*120;然后定义一个计数器cnt_rom_address,用来取rom里的数据,计数器的最大值就是160*120-1,用flag_clear_rom_address表示。图片的定位,还需要考虑图片的坐标,分为行有效和列有效,即flag_begin_hflag_begin_v。把这两个综合起来的矩形区域就是图片的显示范围。

后面控制图片显示的逻辑,就是先取地址,在图片区域时,递增取地址,循环操作。按地址读取的数据,送到VGA显示。也就是划范围,取地址,读内存,送显。

 

再标记图片显示有效区:

 

 

根据图片显示有效信号picture_flag_enable生产ROM地址计数器:

 

 

 

 

例化ROM IP,按照地址计数顺序输出图片:

 

 

 

 

 

画面停留时间约6S,因为25MHz的时钟换算得来。

 

修改的代码片段:

// picture

 assign flag_clear_rom_address=(cnt_rom_address==height*width-1);

 

 assign flag_begin_h=pos_x>((640-width)/2) && pos_x<((640-width)/2+width+1);

 assign flag_begin_v=pos_y>((480-height)/2) && pos_y<((480-height)/2+height+1);

 assign picture_flag_enable=flag_begin_h&&flag_begin_v;

 

 //picture rom address counter

 always @ (posedge clk, negedge rst_n)

if (!rst_n)

cnt_rom_address<=0;

else if(flag_clear_rom_address)

cnt_rom_address<=0;

else if(picture_flag_enable)

cnt_rom_address<=cnt_rom_address+1;

else

cnt_rom_address<=cnt_rom_address;

 

//rom inis

 rom rom_inst(

.address(cnt_rom_address),

.clock(clk),

.q(rom_data));

 

    always @ (posedge clk, negedge rst_n)

        if (!rst_n)

            vga_rgb <= 24'b000000000000000000000000;

        else if(picture_flag_enable)

vga_rgb <= rom_data;

  else

vga_rgb <= 24'b000000000000000000000000;

 

参考:

https://mp.weixin.qq.com/s/OzBL4HQdLOLQvRbBKuUpxA

 

与VGA显示图片相似的内容: