0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

FPGA实现一个VGA/LCD显示控制器的实例

FPGA技术江湖 来源:FPGA技术江湖 作者:FPGA技术江湖 2022-08-01 10:49 次阅读

今天给大侠带来基于FPGA的VGA/LCD显示控制器设计,由于篇幅较长,分三篇。今天带来第三篇,下篇,程序的仿真与测试以及总结话不多说,上货。

导读

VGA (Video Graphics Array) 即视频图形阵列,是IBM于1987年随PS/2机(PersonalSystem 2)一起推出的使用模拟信号的一种视频传输标准。这个标准对于现今的个人电脑市场已经十分过时。但在当时具有分辨率高、显示速率快、颜色丰富等优点,在彩色显示器领域取得了广泛的应用,是众多制造商所共同支持的一个低标准。

LCD ( Liquid Crystal Display 的简称)液晶显示器。LCD 的构造是在两片平行的玻璃基板当中放置液晶盒,下基板玻璃上设置TFT(薄膜晶体管),上基板玻璃上设置彩色滤光片,通过TFT上的信号与电压改变来控制液晶分子的转动方向,从而达到控制每个像素点偏振光出射与否而达到显示目的。按照背光源的不同,LCD可以分为CCFL显示器和LED显示器两种。LCD已经替代CRT成为主流,价格也已经下降了很多,并已充分普及。

在之前的文章中介绍了如何获取、处理摄像头提供的视频信号,在实际应用中还需要将经过处理的信号显示在显示器上。这个过程与信号处理中的过程上是相反的,将数字信号按照电视信号的制式组成合乎时序、格式要求的信号,并加入用于控制的各种同步信号。本篇将通过 FPGA实现一个 VGA/LCD 显示控制器的实例,并详细介绍实现过程。

第三篇内容摘要:本篇会介绍程序的仿真与测试以及总结等相关内容。

四、程序的仿真与测试

为了检验程序是否实现预先设定的功能,需要编写仿真程序。仿真程序的主要代码如下:


module test;    //寄存器    reg clk;    reg rst;    //参数    parameter LINE_FIFO_AWIDTH = 7;    //wire 申明    wire int;    wire [31:0] wb_addr_o;    wire [31:0] wb_data_i;    wire [31:0] wb_data_o;    wire [3:0] wb_sel_o;    wire wb_we_o;    wire wb_stb_o;    wire wb_cyc_o;    wire [2:0] wb_cti_o;    wire [1:0] wb_bte_o;    wire wb_ack_i;    wire wb_err_i;    wire [31:0] wb_addr_i;    wire [31:0] wbm_data_i;    wire [3:0] wb_sel_i;    wire wb_we_i;    wire wb_stb_i;    wire wb_cyc_i;    wire wb_ack_o;    wire wb_rty_o;    wire wb_err_o;    reg pclk_i;    wire pclk;    wire hsync;    wire vsync;    wire csync;    wire blanc;    wire [7:0] red;    wire [7:0] green;    wire [7:0] blue;    wire dvi_pclk_p_o;    wire dvi_pclk_m_o;    wire dvi_hsync_o;    wire dvi_vsync_o;    wire dvi_de_o;    wire [11:0] dvi_d_o;    wire vga_stb_i;    wire clut_stb_i;    reg scen;        // 测试程序变量    integer wd_cnt;    integer error_cnt;        reg [31:0] data;    reg [31:0] pattern;    reg int_warn;        integer n;    integer mode;        reg [7:0] thsync, thgdel;    reg [15:0] thgate, thlen;    reg [7:0] tvsync, tvgdel;    reg [15:0] tvgate, tvlen;    reg hpol;    reg vpol;    reg cpol;    reg bpol;    integer p, l;    reg [31:0] pn;    reg [31:0] pra, paa, tmp;    reg [23:0] pd;    reg [1:0] cd;    reg pc;    reg [31:0] vbase;    reg [31:0] cbase;    reg [31:0] vbara;    reg [31:0] vbarb;    reg [7:0] bank;        // 常量定义    `define CTRL 32'h0000_0000    `define STAT 32'h0000_0004    `define HTIM 32'h0000_0008    `define VTIM 32'h0000_000c    `define HVLEN 32'h0000_0010    `define VBARA 32'h0000_0014    `define VBARB 32'h0000_0018    `define USE_VC 1    parameter PCLK_C = 20;        //测试内容    initial        begin            $timeformat (-9, 1, " ns", 12);            $display("

");            $display("******************************************************");            $display("*VGA/LCD Controller Simulation started ... *");            $display("******************************************************");            $display("
");                `ifdef WAVES        $shm_open("waves");        $shm_probe("AS",test,"AS");        $display("INFO: Signal dump enabled ...

");      `endif        scen = 0;        error_cnt = 0;        clk = 0;        pclk_i = 0;        rst = 0;        int_warn=1;        repeat(20) @(posedge clk);        rst = 1;        repeat(20) @(posedge clk);            if(0)        begin                end    else    if(1)        begin            `ifdef VGA_12BIT_DVI        dvi_pd_test;    `endif            end    else        begin                // 测试区域    $display("

");    $display("*****************************************************");    $display("*** XXX Test ***");    $display("*****************************************************
");            s0.fill_mem(1);        repeat(10) @(posedge clk);        //参数设置        vbara = 32'h0000_0000;        vbarb = 32'h0001_0000;        m0.wb_wr1( `VBARA, 4'hf, vbara );        m0.wb_wr1( `VBARB, 4'hf, vbarb );        thsync = 0;        thgdel = 0;        thgate = 340;        thlen = 345;        tvsync = 0;        tvgdel = 0;        tvgate = 240;        tvlen = 245;                /*        thsync = 0;        thgdel = 0;        thgate = 63;        thlen = 70;        tvsync = 0;        tvgdel = 0;        tvgate = 32;        tvlen = 36;        */                hpol = 0;        vpol = 0;        cpol = 0;        bpol = 0;        m0.wb_wr1( `HTIM, 4'hf, {thsync, thgdel, thgate} );        m0.wb_wr1( `VTIM, 4'hf, {tvsync, tvgdel, tvgate} );        m0.wb_wr1( `HVLEN, 4'hf, {thlen, tvlen} );
    mode = 2;
    for(bank=0;bank<3;bank=bank + 1)        begin            case(mode)            0:            begin                cd = 2'h2;                pc = 1'b0;            end                        1:            begin                cd = 2'h0;                pc = 1'b0;            end                        2:            begin                cd = 2'h0;                pc = 1'b1;            end                        3:            begin                cd = 2'h1;                pc = 1'b0;            end                    endcase        m0.wb_wr1( `CTRL, 4'hf, {        16'h0, // Reserved        bpol, cpol,        vpol, hpol,        pc, // 1'b0, // PC        cd, // 2'h2, // CD        2'h0, // VBL        1'b0, // Reserved        1'b1, // CBSWE        1'b1, // VBSWE        1'b0, // BSIE        1'b0, // HIE        1'b0, // VIE        1'b1 // Video Enable      });          $display("Mode: %0d Screen: %0d", mode, bank);    //repeat(2) @(posedge vsync);    @(posedge vsync);        // 每一行数据    for(l=0;l    // For each Pixel    for(p=0;p        begin            while(blanc) @(posedge pclk);                        if(bank[0]) vbase = vbarb[31:2];            else vbase = vbara[31:2];            if(bank[0]) cbase = 32'h0000_0c00;            else cbase = 32'h0000_0800;                        // 各种显示模式            //像素数目 = 行数* (thgate + 1) + p            pn = l * (thgate + 1) + p;                        case(mode)                0: // 24 位模式                begin                    pra = pn[31:2] * 3;                    paa = pra + vbase; // 像素决定地址                                // 像素数据                case(pn[1:0])                    0:                    begin                        tmp = s0.mem[paa];                        pd = tmp[31:8];                    end                    1:                        begin                            tmp = s0.mem[paa];                            pd[23:16] = tmp[7:0];                            tmp = s0.mem[paa+1];                            pd[15:0] = tmp[31:16];                        end                    2:                        begin                            tmp = s0.mem[paa+1];                            pd[23:8] = tmp[15:0];                            tmp = s0.mem[paa+2];                            pd[7:0] = tmp[31:24];                        end                    3:                    begin                        tmp = s0.mem[paa+2];                        pd = tmp[23:0];                    end                endcase            end                        1: // 8 位灰度模式                begin                    pra = pn[31:2]; // 像素相对地址                    paa = pra + vbase; // 像素绝对地址                    case(pn[1:0])                        0:                            begin                                tmp = s0.mem[paa];                                pd = { tmp[31:24], tmp[31:24], tmp[31:24] };                            end                        1:                            begin                                tmp = s0.mem[paa];                                pd = { tmp[23:16], tmp[23:16], tmp[23:16] };                            end                        2:                            begin                                tmp = s0.mem[paa];                                pd = { tmp[15:8], tmp[15:8], tmp[15:8] };                            end                        3:                            begin                                tmp = s0.mem[paa];                                pd = { tmp[7:0], tmp[7:0], tmp[7:0] };                            end                    endcase                end            2: // 8 位伪彩色模式                begin                    pra = pn[31:2]; //像素相对地址                    paa = pra + vbase; //像素绝对地址                    case(pn[1:0])                        0:                            begin                                tmp = s0.mem[paa];                                tmp = s0.mem[cbase[31:2] + tmp[31:24]];                                pd = tmp[23:0];                            end                        1:                            begin                                tmp = s0.mem[paa];                                tmp = s0.mem[cbase[31:2] + tmp[23:16]];                                pd = tmp[23:0];                            end                        2:                            begin                                tmp = s0.mem[paa];                                tmp = s0.mem[cbase[31:2] + tmp[15:8]];                                pd = tmp[23:0];                            end                        3:                            begin                                tmp = s0.mem[paa];                                tmp = s0.mem[cbase[31:2] + tmp[7:0]];                                pd = tmp[23:0];                            end                    endcase                end                          3: // 16 位模式              begin                  pra = pn[31:1]; //像素相对地址                  paa = pra + vbase; //像素绝对地址                  case(pn[0])                      0:                          begin                              tmp = s0.mem[paa];                              tmp[15:0] = tmp[31:16];                              pd = {tmp[15:11], 3'h0, tmp[10:5], 2'h0, tmp[4:0], 3'h0};                          end                      1:                          begin                              tmp = s0.mem[paa];                              pd = {tmp[15:11], 3'h0, tmp[10:5], 2'h0, tmp[4:0], 3'h0};                          end                  endcase              end      endcase      if(pd !== {red, green, blue} )          begin              $display("ERROR: Pixel Data Mismatch: Expected: %h, Got: %h %h %h",              pd, red, green, blue);              $display(" pixel=%0d, line=%0d, (%0t)",p,l,$time);              error_cnt = error_cnt + 1;          end                    @(posedge pclk);      end  end       show_errors;  $display("*****************************************************");  $display("*** Test DONE ... ***");  $display("*****************************************************

");   end        repeat(10) @(posedge clk);      $finish;  end    //同步监视    `ifdef VGA_12BIT_DVI    sync_check #(PCLK_C*2) ucheck(    `else    sync_check #(PCLK_C) ucheck(    `endif        .pclk( pclk ),        .rst( rst ),        .enable( scen ),        .hsync( hsync ),        .vsync( vsync ),        .csync( csync ),        .blanc( blanc ),        .hpol( hpol ),        .vpol( vpol ),        .cpol( cpol ),        .bpol( bpol ),        .thsync( thsync ),        .thgdel( thgdel ),        .thgate( thgate ),        .thlen( thlen ),        .tvsync( tvsync ),        .tvgdel( tvgdel ),        .tvgate( tvgate ),        .tvlen( tvlen ) );            // 视频数据监视    wb_b3_check u_wb_check (        .clk_i ( clk ),        .cyc_i ( wb_cyc_o ),        .stb_i ( wb_stb_o ),        .cti_i ( wb_cti_o ),        .bte_i ( wb_bte_o ),        .we_i ( wb_we_o ),        .ack_i ( wb_ack_i ),        .err_i ( wb_err_i ),        .rty_i ( 1'b0 ) );
    //看门狗计数器    always @(posedge clk)        if(wb_cyc_i | wb_cyc_o | wb_ack_i | wb_ack_o | hsync)            wd_cnt <= #1 0;        else            wd_cnt <= #1 wd_cnt + 1;                always @(wd_cnt)        if(wd_cnt>9000)            begin                $display("

*************************************
");                $display("ERROR: Watch Dog Counter Expired
");                $display("*************************************


");                $finish;            end                always @(posedge int)        if(int_warn)            begin                $display("

*************************************
");                $display("WARNING: Recieved Interrupt (%0t)", $time);                $display("*************************************


");            end        always #2.5 clk = ~clk;    always #(PCLK_C/2) pclk_i = ~pclk_i;        //模块原型    vga_enh_top #(1'b0, LINE_FIFO_AWIDTH) u0 (        .wb_clk_i ( clk ),        .wb_rst_i ( 1'b0 ),        .rst_i ( rst ),        .wb_inta_o ( int ),        //从信号        .wbs_adr_i ( wb_addr_i[11:0] ),        .wbs_dat_i ( wb_data_i ),        .wbs_dat_o ( wb_data_o ),        .wbs_sel_i ( wb_sel_i ),        .wbs_we_i ( wb_we_i ),        .wbs_stb_i ( wb_stb_i ),        .wbs_cyc_i ( wb_cyc_i ),        .wbs_ack_o ( wb_ack_o ),        .wbs_rty_o ( wb_rty_o ),        .wbs_err_o ( wb_err_o ),        //主信号        .wbm_adr_o ( wb_addr_o[31:0] ),        .wbm_dat_i ( wbm_data_i ),        .wbm_sel_o ( wb_sel_o ),        .wbm_we_o ( wb_we_o ),        .wbm_stb_o ( wb_stb_o ),        .wbm_cyc_o ( wb_cyc_o ),        .wbm_cti_o ( wb_cti_o ),        .wbm_bte_o ( wb_bte_o ),        .wbm_ack_i ( wb_ack_i ),        .wbm_err_i ( wb_err_i ),        //VGA 信号        .clk_p_i ( pclk_i ),    `ifdef VGA_12BIT_DVI        .dvi_pclk_p_o ( dvi_pclk_p_o ),        .dvi_pclk_m_o ( dvi_pclk_m_o ),        .dvi_hsync_o ( dvi_hsync_o ),        .dvi_vsync_o ( dvi_vsync_o ),        .dvi_de_o ( dvi_de_o ),        .dvi_d_o ( dvi_d_o ),    `endif        .clk_p_o ( pclk ),        .hsync_pad_o ( hsync ),        .vsync_pad_o ( vsync ),        .csync_pad_o ( csync ),        .blank_pad_o ( blanc ),        .r_pad_o ( red ),        .g_pad_o ( green ),        .b_pad_o ( blue )    );        wb_mast m0( .clk( clk ),            .rst( rst ),            .adr( wb_addr_i ),            .din( wb_data_o ),            .dout( wb_data_i ),            .cyc( wb_cyc_i ),            .stb( wb_stb_i ),            .sel( wb_sel_i ),            .we( wb_we_i ),            .ack( wb_ack_o ),            .err( wb_err_o ),            .rty( 1'b0 )        );        wb_slv #(24) s0(.clk( clk ),            .rst( rst ),            .adr( {1'b0, wb_addr_o[30:0]} ),            .din( 32'h0 ),            .dout( wbm_data_i ),            .cyc( wb_cyc_o ),            .stb( wb_stb_o ),            .sel( wb_sel_o ),            .we( wb_we_o ),            .ack( wb_ack_i ),            .err( wb_err_i ),            .rty( )        );        `include "tests.v"    endmodule

五、总结

本篇介绍了一个 VGA/LCD 显示控制器的实例。首先介绍了 VGA/LCD 显示的相关知识,然后介绍了程序的主要结构和主要功能模块的实现过程。最后用一个测试程序验证程序的功能是否满足要求。本章为各位大侠设计自己的 VGA/LCD 显示控制器提供了一个可以使用的方案。

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FPGA
    +关注

    关注

    1602

    文章

    21308

    浏览量

    593119
  • 控制器
    +关注

    关注

    112

    文章

    15213

    浏览量

    171135
  • lcd
    lcd
    +关注

    关注

    34

    文章

    4276

    浏览量

    164050

原文标题:系统设计精选 | 基于FPGA的VGA/LCD显示控制器设计(附代码)

文章出处:【微信号:HXSLH1010101010,微信公众号:FPGA技术江湖】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    液晶显示控制器LCDC

    液晶显示控制器
    Piezoman压电侠
    发布于 :2024年01月23日 15:43:34

    内存显示控制器介绍

    内存显示控制器
    Piezoman压电侠
    发布于 :2024年01月23日 11:33:39

    液晶显示控制器LCDC

    LCD显示控制器
    Piezoman压电侠
    发布于 :2024年01月10日 15:45:45

    如何实现StarterWare开发环境下的LCD触摸控制

    实现LCD显示与触摸,主要需要LCD驱动器和LCD控制器
    发表于 10-08 17:32 391次阅读
    如何<b class='flag-5'>实现</b>StarterWare开发环境下的<b class='flag-5'>LCD</b>触摸<b class='flag-5'>控制</b>?

    步进电机控制器FPGA实现

    电子发烧友网站提供《步进电机控制器FPGA实现.pdf》资料免费下载
    发表于 10-07 16:29 1次下载
    步进电机<b class='flag-5'>控制器</b>的<b class='flag-5'>FPGA</b>的<b class='flag-5'>实现</b>

    Mojo v3 FPGA板与16x2 LCD模块是如何进行连接的呢?

    在本教程中,我们将使用Verilog HDL设计一个数字电路,该电路与基于HD44780 LCD控制器/驱动芯片的通用LCD模块连接。Mojo V3 FPGA板将用于
    发表于 09-20 10:25 552次阅读
    Mojo v3 <b class='flag-5'>FPGA</b>板与16x2 <b class='flag-5'>LCD</b>模块是如何进行连接的呢?

    AMBA彩色LCD控制器数据表

    配合使用,以足以支持所选显示模式和分辨率的速率向LCD控制器数据路径前端的FIFO提供数据。 面板大小是可编程的,可以是16到1024像素之间的任何宽度(线长),以16像素为增量。 行数通过对
    发表于 08-21 07:05

    41 23E 多分辨率适配VGA控制器设计 - 第4节

    控制器VGA
    充八万
    发布于 :2023年08月19日 11:37:57

    41 23E 多分辨率适配VGA控制器设计 - 第3节

    控制器VGA
    充八万
    发布于 :2023年08月19日 11:37:07

    41 23E 多分辨率适配VGA控制器设计 - 第2节

    控制器VGA
    充八万
    发布于 :2023年08月19日 11:36:17

    40 23D VGA控制器板级验证方法 - 第7节

    控制器VGA
    充八万
    发布于 :2023年08月19日 11:22:55

    40 23D VGA控制器板级验证方法 - 第5节

    控制器VGA
    充八万
    发布于 :2023年08月19日 11:21:15

    40 23D VGA控制器板级验证方法 - 第4节

    控制器VGA
    充八万
    发布于 :2023年08月19日 11:20:25

    掌握VGA显示的原理并实现VGA显示图像数据

    控制VGA的管脚是VPIF总线,和控制LCD显示的管脚是复用的
    的头像 发表于 08-16 14:57 2562次阅读
    掌握<b class='flag-5'>VGA</b><b class='flag-5'>显示</b>的原理并<b class='flag-5'>实现</b><b class='flag-5'>VGA</b><b class='flag-5'>显示</b>图像数据

    嵌入式教程_DSP教学实验箱:2-9 VGA显示实验

    实验目的 本节视频的目的是了解VGA接口的功能和使用,掌握VGA显示的原理并实现VGA显示图像数
    发表于 08-16 11:47