zoukankan      html  css  js  c++  java
  • fpga 通过vga模块使电脑显示图片

      对vga模块搞了好几天,vga接口时序不难,就是行计数,列计数,对应到每一个像素上去。这里我先把vga控制模块的程序付上。采用的是小梅哥的程序。屏幕是800X600,配置的时钟是40M.注意改变屏幕尺寸时记得重新配置pll.我就是拿着小梅哥的例子直接用,结果屏幕显示输入信号超出范围。

    /*============================================================================
    *
    * LOGIC CORE: VGA驱动模块
    * MODULE NAME: VGA_CTRL()
    * COMPANY: 芯航线电子工作室
    * http://xiaomeige.taobao.com
    * author: 小梅哥
    * author QQ Group:472607506
    * REVISION HISTORY:
    *
    * Revision 1.0 01/01/2016 Description: Initial Release.
    *
    * FUNCTIONAL DESCRIPTION:
    ===========================================================================*/
    module VGA_CTRL(
    Clk_40M, //系统输入时钟25MHZ
    Rst_n, //复位输入,低电平复位
    data_in, //待显示数据
    hcount, //VGA行扫描计数器
    vcount, //VGA场扫描计数器
    VGA_RGB, //VGA数据输出
    VGA_HS, //VGA行同步信号
    VGA_VS, //VGA场同步信号
    VGA_BLK, //VGA 场消隐信号
    VGA_CLK //VGA DAC输出时钟
    );

    //----------------模块输入端口----------------
    input Clk_40M; //系统输入时钟25MHZ
    input Rst_n;
    input [23:0]data_in; //待显示数据

    //----------------模块输出端口----------------
    output [10:0]hcount;
    output [9:0]vcount;
    output [23:0]VGA_RGB; //VGA数据输出
    output VGA_HS; //VGA行同步信号
    output VGA_VS; //VGA场同步信号
    output VGA_BLK; //VGA 场消隐信号
    output VGA_CLK; //VGA DAC输出时钟


    //将VGA控制器时钟信号取反输出,作为DAC数据锁存信号
    assign VGA_CLK = ~Clk_40M;

    //----------------内部寄存器定义----------------
    reg [10:0] hcount_r; //VGA行扫描计数器
    reg [9:0] vcount_r; //VGA场扫描计数器
    //----------------内部连线定义----------------
    wire hcount_ov;
    wire vcount_ov;
    wire dat_act;//有效显示区标定

    //VGA行、场扫描时序参数表
    parameter VGA_HS_end=10'd127,
    hdat_begin=10'd216,
    hdat_end=10'd1016,
    hpixel_end=11'd1055,
    VGA_VS_end=10'd3,
    vdat_begin=10'd26,
    vdat_end=10'd626,
    vline_end=10'd627;

    assign hcount=dat_act?(hcount_r-hdat_begin):11'd0;
    assign vcount=dat_act?(vcount_r-vdat_begin):10'd0;

    //**********************VGA驱动部分**********************
    //行扫描
    always@(posedge Clk_40M or negedge Rst_n)
    if(!Rst_n)
    hcount_r<=11'd0;
    else if(hcount_ov)
    hcount_r<=11'd0;
    else
    hcount_r<=hcount_r+11'd1;

    assign hcount_ov=(hcount_r==hpixel_end);

    //场扫描
    always@(posedge Clk_40M or negedge Rst_n)
    if(!Rst_n)
    vcount_r<=10'd0;
    else if(hcount_ov) begin
    if(vcount_ov)
    vcount_r<=10'd0;
    else
    vcount_r<=vcount_r+10'd1;
    end
    else
    vcount_r<=vcount_r;

    assign vcount_ov=(vcount_r==vline_end);

    //数据、同步信号输出
    assign dat_act=((hcount_r>=hdat_begin)&&(hcount_r<hdat_end))
    &&((vcount_r>=vdat_begin)&&(vcount_r<vdat_end));

    assign VGA_BLK = dat_act;

    assign VGA_HS=(hcount_r>VGA_HS_end);
    assign VGA_VS=(vcount_r>VGA_VS_end);
    assign VGA_RGB=(dat_act)?data_in:24'h000000;

    endmodule

    接下来是图片的处理,我选着了一张自己喜欢的图片,从jpg->bmp->mif文件,也是费了一点功夫。而且bmp文件应再处理一次,我把像素变为100X56,rgb888格式。这样配置rom时可以节省不少资源(也可以配置成rgb565)。但还是最后用了46%的存储资源,我用的芯片是ep4cf10c8n.

    rom和pll的配置大家自己去弄。

    接下来是图片数据如何输入到屏幕上。这个方法是在规定的像素点,对应的去读取相应地址rom的数据。

    接下来我贴一下代码。

    module imgdata_send(
    Clk,
    Rst_n,

    hcount,//行
    vcount,//列
    data_in

    );

    input Clk;
    input Rst_n;

    input [10:0]hcount;
    input [9:0]vcount;

    output [23:0]data_in;


    wire img_ack;//图片数据使能

    localparam img_h = 100,//图片横向像素电个数。
    img_v = 56,//图片竖向像素电个数。
    vga_hm=800,//屏幕横向像素电个数
    vga_vm= 600,//屏幕竖向像素电个数

    img_hbegin = 250,//图片显示横向初始位置

    reg [13:0]addr;     //rom的地址
    wire [23:0]img_data;   //地址的内容

    vga_rom vga_rom(
    .address(addr),
    .clock(Clk),
    .q(img_data)
    );

    assign img_ack = ((hcount >= img_hbegin && hcount < img_hbegin + img_h)|| && (vcount >= img_vbegin && vcount < img_vbegin + img_v))?1'b1:1'b0;     //我们想要图片显示位置区域内,信号为高

    always@(posedge Clk or negedge Rst_n)
    if(!Rst_n)
    addr <= 14'd0;  //初始化
    else if(img_ack)
    addr <= ((hcount - img_hbegin) + (vcount - img_vbegin)*img_h);//计算地址,
    else
    addr <= 14'd0;


    assign data_in = img_ack ? img_data : 24'h0;//数据赋值

    endmodule

    下面是效果。原图我找不到了,只能用bmp文件再一次转为png文件。所以图片很小。

    下面是编译之后的顶层文件netlist  viewer.一开始我还很担心vga_ctrl模块与rom模块形成一个反馈,但是发现担心是多余的。接下来我当时学习一下sdrom模块的使用。如何让电脑显示更清晰的图片。

    附上顶层模块描述:

    module vga_top(
    Clk,
    Rst_n,
    VGA_RGB,
    VGA_HS,
    VGA_VS,
    VGA_BLK,
    VGA_CLK

    );

    input Clk;
    input Rst_n;
    output [23:0]VGA_RGB;
    output VGA_HS;
    output VGA_VS;
    output VGA_BLK;
    output VGA_CLK;

    wire Clk_40M;
    wire [10:0]hcount;
    wire [9:0]vcount;
    wire [23:0]data_in;
    VGA_CTRL VGA_CTRL(
    .Clk_40M(Clk_40M), //系统输入时钟25MHZ
    .Rst_n(Rst_n), //复位输入,低电平复位
    .data_in(data_in), //待显示数据
    .hcount(hcount), //VGA行扫描计数器
    .vcount(vcount), //VGA场扫描计数器
    .VGA_RGB(VGA_RGB), //VGA数据输出
    .VGA_HS(VGA_HS), //VGA行同步信号
    .VGA_VS(VGA_VS), //VGA场同步信号
    .VGA_BLK(VGA_BLK), //VGA 场消隐信号
    .VGA_CLK (VGA_CLK) //VGA DAC输出时钟
    );

    imgdata_send imgdata_send(
    .Clk(Clk),
    .Rst_n(Rst_n),
    .hcount(hcount),
    .vcount(vcount),
    .data_in(data_in)

    );

    vga_pll vga_pll(
    .inclk0(Clk),
    .c0(Clk_40M)
    );

    endmodule

      

  • 相关阅读:
    ExcelDataReader read excel file
    DocumentFormat.OpenXml read excel file
    java高并发系列
    java高并发系列
    java高并发系列
    java高并发系列
    java高并发系列
    java高并发系列
    java高并发系列
    java高并发系列
  • 原文地址:https://www.cnblogs.com/wyjalx/p/13341966.html
Copyright © 2011-2022 走看看