之前的基于友晶科技 FPGA开发板 DE2-115、DE1-SOC 和 DE10-Standard 的VGA彩条显示设计(ADV7123)设计是让VGA显示器显示彩条。 那如果显示图片呢?

那我们得调用一个ROM IP, 将图片存储在ROM里面, 显示的时候直接从ROM 里面读取出来。

ROM里面可以存放mif和hex格式的文件。 

获取mif文件

我们先把图片转换成mif文件。

找到一个你想显示的图片,通过Windows自带的画图工具打开它,调整大小(比如调整到48*48*24bit),去掉保持纵横比,选择像素。

 

然后另存为时选择24bit bmp格式:

 然后网络上下载一个bmp转mif的小工具(下载地址https://blog.csdn.net/baidu_34971492/article/details/106659642  或者  BMP2Mif.exe ):

调用ROM IP

得到mif文件以后。

在IP Catalog里面搜索ROM,选择ROM 1-PORT:

 

设置24位,4096字节(深度的设置一定要大于图片的大小,稍微设置大一点没关系)。

 

 

点击Browse,选择项目路径下mif文件,完成后点击next,最后点击Finish结束ROM IP 的设置并把该rom.qip文件添加到工程里面。

 

 代码分析

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 完整源码

 vga.v文件跟基于友晶科技 FPGA开发板 DE2-115、DE1-SOC 和 DE10-STANDARD 的VGA彩条显示设计(ADV7123)一样,无需更改。

module vga(

    input     wire                    clk,//系统参考时钟
    input     wire                    rst_n,//复位
     output    wire       [23:0]       vga_rgb,//输出给ADV7123的R、G、B三分量数据
    output    wire                    vga_hs,//行同步信号
    output    wire                    vga_vs,//场同步信号
     output    wire                    vga_clk,//像素时钟
    output    wire                    vga_blank_n,//消隐信号
    output    wire                    vga_sync_n//复合同步控制IOG输入
);

    wire                    clk_25m;
    wire                    pll_locked;
    
    pll pll_inst (//例化PLL
    
        .rst             ( ~rst_n     ),
        .refclk         ( clk         ),
        .outclk_0    ( clk_25m    ),
        .locked       ( pll_locked)
    );

    vga_ctrl vga_ctrl_inst (//例化VGA控制模块

        .clk                    (clk_25m        ),
        .rst_n                (pll_locked    ),
                         
        .vga_rgb                (vga_rgb        ),
        .vga_hs                (vga_hs        ),
        .vga_blanck_n        (vga_blank_n),
        .vga_vs                (vga_vs        )
    );

//If not IOG, Sync input should be tied to 0;
assign vga_sync_n=1'b0;    
assign vga_clk=clk_25m;
 
endmodule

 vga_ctl.v文件需要修改, 完整代码如下:

module vga_ctrl (

    input     wire                     clk,//像素时钟
    input     wire                    rst_n,//复位

    output    reg        [23:0]      vga_rgb,//输出给ADV7123的R、G、B三分量数据
     output    reg                    vga_hs,//行同步信号
     output    reg                    vga_vs,//场同步信号
    output    wire                   vga_blanck_n//消隐信号
);

//================ VGA PLL clk = 25M  640x480x60 =========================================================

    parameter            HS_A    =    96;                 // 行同步信号周期长
    parameter            HS_B    =    48;                 // 行同步后沿信号周期长
    parameter            HS_C    =    640;                // 行显示周期长
    parameter            HS_D    =    16;                 // 行同步前言信号周期长
    parameter            HS_E    =    800;                // 行周期长

    parameter            VS_A    =    2;                  // 场同步信号周期长
    parameter            VS_B    =    33;                 // 场同步后沿信号周期长
    parameter            VS_C    =    480;                // 行显示周期长   
    parameter            VS_D    =    10;                 // 场同步前言信号周期长    
    parameter            VS_E    =    525;                // 场周期长    
    
    parameter            HS_WIDTH =   10;                // 行周期计数器位宽
    parameter            VS_WIDTH =   10;                // 场周期计数器位宽

     
    parameter                 height = 48;                             // 图片高度
    parameter                 width  = 48;                             // 图片宽度
    
      reg        [HS_WIDTH - 1:0]        cnt_hs;           // 行周期计数器
    reg        [VS_WIDTH - 1:0]        cnt_vs;           // 场周期计数器

    reg              [13:0]                       cnt_rom_address;      // rom地址计数器
     reg            [11:0]                        addr_h;   //行地址
     reg            [11:0]                        addr_v;   //列地址
         
    wire       en_hs;             // 行显示使能
    wire       en_vs;             // 场显示使能
    wire       en;                // VGA 有效显示区使能信号
   
     wire           flag_clear_rom_address;//地址计数器清零标志
     wire           flag_begin_h;              //图片行显示有效标志
     wire           flag_begin_v;              //图片场显示有效标志
     wire           flag_enable_out2;          //图片的有效显示区标志
     
     wire        [23:0]        rom_data; // 图片数据

     // 行周期计数器的实现
    always @ (posedge clk, negedge rst_n)
        if (!rst_n)
            cnt_hs <= 0;
        else
            if (cnt_hs < HS_E - 1)
                cnt_hs <= cnt_hs + 1'b1;
            else
                cnt_hs <= 0;
                     
    // 场周期计数器的实现         
    always @ (posedge clk, negedge rst_n)
        if (!rst_n)
            cnt_vs <= 0;
        else
            if (cnt_hs == HS_E - 1)
                if (cnt_vs < VS_E - 1)
                    cnt_vs <= cnt_vs + 1'b1;
                else
                    cnt_vs <= 0;
            else
                cnt_vs <= cnt_vs;
                     
    // 行同步信号时序
    always @ (posedge clk, negedge rst_n)
        if (!rst_n)
            vga_hs <= 1'b1;
        else
            if (cnt_hs < HS_A - 1) //同步之前vga_hs信号都是低, 同步之后(a)vga_hs信号是高
                vga_hs <= 1'b0;
            else
                vga_hs <= 1'b1;
     
     // 场同步信号时序            
    always @ (posedge clk, negedge rst_n)
        if (!rst_n)
            vga_vs <= 1'b1;
        else
            if (cnt_vs < VS_A - 1) //同步之前vga_vs 信号都是低, 同步之后(a)vga_vs 信号是高
                vga_vs <= 1'b0;
            else
                vga_vs <= 1'b1;
        
     
//实例化ROM
    rom    rom_inst (
        .address    (cnt_rom_address),
        .clock      (clk),
        .q          (rom_data)
    );

    //读出ROM数据
    always @( posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        vga_rgb <= 24'b000000000000000000000000;
    end
    else if ( flag_enable_out2 ) begin
        vga_rgb <= rom_data;
    end
    else begin
        vga_rgb <= 24'b000000000000000000000000;
    end
end


    //ROM地址计数器
    always @( posedge clk or negedge rst_n ) begin
         if ( !rst_n ) begin
         cnt_rom_address <= 0;//复位地址清零
         end
         else if ( flag_clear_rom_address ) begin //计数满清零
              cnt_rom_address <= 0;
         end
              else if ( flag_enable_out2 ) begin  //在有效区域内+1
              cnt_rom_address <= cnt_rom_address + 1;
              end
              else begin  //无效区域内地址不变
              cnt_rom_address <= cnt_rom_address;
         end
    end


        // 对应有效区域行地址 1-640
        always @( posedge clk or negedge rst_n ) begin
             if ( !rst_n ) begin
                  addr_h <= 0;
             end
             else if ( en ) begin
                  addr_h <= cnt_hs - HS_A - HS_B + 1;
             end
             else begin
                  addr_h <= 0;
             end
        end
        // 对应有效区域列地址 1-480
        always @( posedge clk or negedge rst_n ) begin
             if ( !rst_n ) begin
                  addr_v <= 0;
             end
             else if ( en ) begin
                  addr_v <= cnt_vs -VS_A - VS_B + 1;
             end
             else begin
                  addr_v <= 0;
             end
        end
        
        //当地址计数器计数到48x48-1时 地址计数器计清零标志置1。
        assign flag_clear_rom_address = cnt_rom_address == height * width - 1;

        assign flag_begin_h = addr_h > ( ( 640 - width ) / 2 ) && addr_h < ( ( 640 - width ) / 2 ) + width + 1;
        assign flag_begin_v = addr_v > ( ( 480 - height )/2 ) && addr_v <( ( 480 - height )/2 ) + height + 1;
        assign flag_enable_out2 = flag_begin_h && flag_begin_v;
    
     assign en_hs = (cnt_hs > HS_A + HS_B - 1)&& (cnt_hs < HS_E - HS_D);//en_hs 将有效数据c段标出来了,有效数据c段en_hs 才为高,否则为低
     assign en_vs = (cnt_vs > VS_A + VS_B - 1) && (cnt_vs < VS_E - VS_D);//en_vs 将有效数据q段标出来了,有效数据q段en_hs 才为高,否则为低
     assign en = en_hs && en_vs;//将vga显示的有效像素点位置全部标注出来了
      assign vga_blanck_n = en;
 
endmodule

 

 

 引脚分配

 

 测试结果

 

 

 

往期相关

基于友晶科技FPGA开发板 DE0-CV、DE10-Lite 上实现VGA彩条显示设计(权电阻网络) - Doreen的FPGA自留地 - 博客园 (cnblogs.com)

基于友晶科技 FPGA开发板 DE2-115、DE1-SOC 和 DE10-Standard 的VGA彩条显示设计(ADV7123) - Doreen的FPGA自留地 - 博客园 (cnblogs.com)

测试DE10-Standard开发板VGA接口(基于ADV7123)输出RGB彩条时显示器显示“无信号”,调试请Signal Tap来帮忙! - Doreen的FPGA自留地 - 博客园 (cnblogs.com)

友晶科技FPGA开发板DE10-NANO开发板的HDMI 方块移动实验 - Doreen的FPGA自留地 - 博客园 (cnblogs.com)