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

之前也有图像处理以及VGA显示相关的文章,这里给个超链接,给各位大侠作个参考。

源码系列:基于FPGA的VGA驱动设计(附源工程)

基于FPGA的实时图像边缘检测系统设计(上)

基于FPGA的实时图像边缘检测系统设计(中)

基于FPGA的实时图像边缘检测系统设计(下)

导读

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("\n\n");            $display("******************************************************");            $display("*VGA/LCD Controller Simulation started ... *");            $display("******************************************************");            $display("\n");                `ifdef WAVES        $shm_open("waves");        $shm_probe("AS",test,"AS");        $display("INFO: Signal dump enabled ...\n\n");      `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("\n\n");    $display("*****************************************************");    $display("*** XXX Test ***");    $display("*****************************************************\n");            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<tvgate+1;l=l+1)    // For each Pixel    for(p=0;p<thgate+1;p=p+1)        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("*****************************************************\n\n");   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("\n\n*************************************\n");                $display("ERROR: Watch Dog Counter Expired\n");                $display("*************************************\n\n\n");                $finish;            end                always @(posedge int)        if(int_warn)            begin                $display("\n\n*************************************\n");                $display("WARNING: Recieved Interrupt (%0t)", $time);                $display("*************************************\n\n\n");            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 显示控制器提供了一个可以使用的方案。

本篇到此结束,各位大侠,有缘再见!

END

后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。

大侠们,江湖偌大,继续闯荡,愿一切安好,有缘再见!

精彩推荐

FPGA零基础学习:SPI 协议驱动设计

《Verilog HDL高级数字设计》(第2版)(英文版)电子版

FPGA零基础学习:Intel FPGA 开发流程

数字电子技术基础(第六版)教材 闫石 电子版

基于FPGA的VGA/LCD显示控制器设计(下)相关推荐

  1. 基于FPGA的VGA/LCD显示控制器设计(中)

    今天给大侠带来基于FPGA的VGA/LCD显示控制器设计,由于篇幅较长,分三篇.今天带来第二篇,中篇,VGA 显示原理以及VGA/LCD 显示控制器的基本框架,话不多说,上货. 之前也有图像处理以及V ...

  2. imut FPGA课设 基于FPGA的VGA弹球游戏设计 *秋昊

    写在前面的话: 本文主要呈现了一篇IMUT的FPGA课设报告. 课设报告内容(word版),视频演示,程序源码,专业创新实践简介,专业创新实践指导书均已放入下面的百度云链接中,也不大,总共不到20MB ...

  3. 基于FPGA的VGA接口设计(三)

    关于VGA系列文章的所有链接: 基于FPGA的VGA接口设计(一) 基于FPGA的VGA接口设计(二) 基于FPGA的VGA接口设计(三) 结篇   在之前的文章中介绍了有关VGA的扫描方式.行场同步 ...

  4. 基于FPGA的VGA显示对贪吃蛇游戏的设计

    基于FPGA的VGA显示对贪吃蛇游戏的设计 摘要 目前,电子数码产品已经进入了人生活的方方面面,而大多数电子产品都依靠显示屏来传递信息,由此可见用电路对显示屏进行控制的研究有很大的实用价值和市场需求. ...

  5. 基于FPGA的数字视频信号处理器设计(下)

    基于FPGA的数字视频信号处理器设计(下) 今天给大侠带来基于FPGA的数字视频信号处理器设计,由于篇幅较长,分三篇.今天带来第三篇,下篇,程序测试与运行.话不多说,上货. 导读 图像是用各种观测系统 ...

  6. 基于FPGA的遥控数字时钟设计

    基于FPGA的遥控数字时钟设计报告 ​ ​ Author:张宏宇 摘要 ​ 数字时钟是一种通过数字显示时间的计时装置,本次项目采用Cyclone Ⅳ系列芯片,使用QuartusII开发环境,使用Ver ...

  7. 基于FPGA的VGA协议实现

    基于FPGA的VGA协议实现 一.VGA简述 1.VCG接口 2.原理 3.显示器扫描 4.VGA时序分析 5.VGA时钟计算 6.不同分辨率的VGA参数 二.显示彩条 1.色彩原理 2.彩条输出 三 ...

  8. 基于 FPGA 的数字抢答器设计

    下面是基于 FPGA 的数字抢答器设计,在quartusII下,modelsim下仿真,编程语言VHDL.   1.抢答器的工作原理 主持人宣布可以抢答后,在 20s 的定时时间内若有人按键抢答,则这 ...

  9. 基于 FPGA 的智力抢答器设计

    本文设计文档及源码将在公众号 果冻空间 免费公布,关注公众号回复A-001获取,博文展示过少,有需要公众号获取,目前公众号仅仅作为资源管理的平台,提供资料链接 基于 FPGA 的智力抢答器设计 题目简 ...

  10. 小数分频器vhdl实现_基于FPGA的小数分频器的设计与实现.doc

    基于FPGA的小数分频器的设计与实现.doc 基于FPGA的小数分频器的设计与实现 [摘要]本文首先分析了现有小数分频器的优缺点,在此基础上提出了一种改进型小数分频器的设计方法.同时结合VHDL文本输 ...

最新文章

  1. 关于兔子的一些往事~
  2. 变压器的同名端,以及判别方法
  3. MSU 出品的 H.264 编码器比较 (2011.5)
  4. count(1)与count(id)与count(*)效率,以及覆盖索引,索引下推
  5. git init github
  6. 专访飞康新任CEO:云时代下,我们更懂数据保护
  7. Shell中的Quoting
  8. Effective Java 第三版 中文翻译
  9. 800万像素摄像头,评估可以看到多远的红绿灯【1】?
  10. 历代治国理政者的教科书——金木水火土的起源之书:周朝的统治大法——《洪范》...
  11. 爸爸是个计算机工程师,作文:我的爸爸是工程师
  12. 小米手机显示无法连接服务器错误代码,来电转接出现连接问题或MMI码无效的解决方法...
  13. 使用 className 修改样式属性
  14. z变换判断稳定性和因果性_判断因果性.PPT
  15. WM_INITDIALOG与WM_CREATE消息的区别
  16. 记一次腾讯TBS浏览服务集成实践
  17. 其实macbook装win7很简单
  18. 【设计模式】用英雄联盟来解释代理模式
  19. excel 从身份证号中提取性别,年龄
  20. TensorFlow2.0--Chapter01环境搭建

热门文章

  1. js string转json有斜杠_json 带斜杠时如何解析的实现
  2. scanf格式符 linux,Linux scanf使用情况
  3. 只你一招,解决NAS噪音及速度问题!
  4. plc编程语言有几种?plc常用的编程语言
  5. android逆向基础教程一
  6. android基础教程:多个页面时如何设置首页
  7. 网络ip功放连接图_ip网络功放
  8. 网银汇款提示服务器无响应,为什么我的网上银行支付页面总是未响应
  9. Phaserjs基础教程第八节:Weapon对象
  10. Windows server 2008 R2 微软官方下载地址