查看: 4759|回复: 6

basys2心得5,最后一篇

[复制链接]
  • TA的每日心情

    2013-8-4 18:50
  • 签到天数: 6 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    发表于 2012-12-3 15:39:32 | 显示全部楼层 |阅读模式
    分享到:
    从拿到BASYS2到现在差不多有2个月的时间了。eeboard和le printemps给了我很多的时间。但是我一直都没好好把它用起来,挺对不住论坛的  。这就是我的最后一篇心得吧,完了我会把板子第一时间寄回给论坛,有需要的朋友可以找eeboard借来玩玩。今天借了显示器,倒腾了一下板子上最后一块大的外设VGA。还是先科普一下有关VGA显示的一些常识。
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    VGA显示
    VGA(Video Graphics Array)作为一种标准的显示接口得到了广泛的应用。v(3A在任何时刻都必须工作在某一显示模式之下,其显示模式分为字符显示模式和图形显示模式。而在应用中,讨论的都是图形显示模式。VGA的图形模式分为三类:CGA、EGA兼容的图形模式;标准的VGA图形模式;VGA扩展图形模式。后两种图形模式统称为VGA图形模式。文中基于标准VGA模式来实现。工业标准的VGA显示模式为:640*480*16色*60Hz。常见的彩色显示器一般都是由CRT(阴极射线管)构成,每一个像素的色彩由R(红,Red)、G(绿,Green)、B(蓝,Blue)三基色构成。显示时采用的是逐行扫描的方式。由VGA显示模块产生的水平同步信号和垂直同步信号控制阴极射线管中的电子枪产生电子束,轰击涂有荧光粉的屏幕,产生RGB三基色,于显示屏上合成一个彩色像素点。图3表示的是VGA显示模块与CRT显示器的控制框图【3J。电子束扫描一幅屏幕图像上的各个点的过程称为屏幕扫描。现在显示器都是通过光栅扫描方式来进行
    file:///C:/Users/zcat/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg
    file:///C:/Users/zcat/AppData/Local/Temp/msohtmlclip1/01/clip_image004.jpg
    通常情况下,对 VGA 显示器进行驱动只需要 5 个信号即可,包括:行、场帧同步信号,红、绿、兰三色信号。其中行、场同步信号为数字信号,红、绿、兰三色信号为模拟信号。 三色信号的输入电压范围是 0.0V~0.7V, 采用DAC来产生此信号时,应考虑到这个问题。
    VGA时序分析
    显示器采用光栅扫描方式,即轰击荧光屏的电子束在CRT(阴极射线管)屏上从左到右(受水平同步信号HSYNC控制)、从上到下(受垂直同步信号VSYNC控制)做有规律的移动。光栅扫描又分逐行扫描和隔行扫描。隔行扫描指电子束在扫描时每隔一行扫一线,完成一屏后再返回来扫描剩下的线。与电视机的原理一样。隔行扫描的显示器扫描闪烁的比较厉害,会让使用者的眼睛疲劳。目前微机所用显示器几乎都是逐行扫描。逐行扫描是指扫描从屏幕左上角一点开始,从左向右逐点进行扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,CRT对电子束进行消隐,每行结束时,用行同步信号进行行同步;当扫描完所有行,形成一帧时,用场同步信号进行场同步,并使扫描回到屏幕的左上方,同时进行行场消隐,开始下一帧的扫描。完成一行扫描所需时间称为水平扫描时间,其倒数称为行频率;完成一帧(整屏)扫描所需的时问称为垂直扫描时间,其倒数为垂直扫描频率,又称刷新频率,即刷新一屏的频率。常见的有60Hz、75Hz等。VGA显示器要正确显示图像关键还是如何实现VGA时序。视频电子标准协会(VESA,VideoElectronics Standards Association)对显示器时序进行了规范。VGA的标准参考显示时序如图
    file:///C:/Users/zcat/AppData/Local/Temp/msohtmlclip1/01/clip_image006.jpg
                             3   VGA的行时序
    file:///C:/Users/zcat/AppData/Local/Temp/msohtmlclip1/01/clip_image008.jpg
    4   VGA的场时序
    VGA的行时序可知:没一行都有一个负极性行同步脉冲(Sync a),是数据行的结束标志,同时也是下一行的开始标志。在同步脉冲之后为显示后沿(Back porch b),在显示时序段(Display interval c)显示器为亮的过程,RGB数据驱动一行上的每一个像素点,从而显示一行。在一行的最后为显示前沿(Frontporch d)。在显示时间段(Display interval c)之外没有图像投射到屏幕是插入消隐信号。同步脉冲(Sync a)、显示后沿(Back porch b)和显示前沿(Front porch d)都是在行消隐间隔内(Horizontal BlankingInterval),当消隐有效时,RGB信号无效,屏幕不显示数据。VGA的场时序与行时序基本一样,每一帧的负极性脉冲(Sync a)是一帧的结束标志,同时也是下一帧的开始标志。而显示数据是一帧的所有行数据。
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~分割线~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    做好了VGA的时序,那么就成功了一半。而时序可以参照上面的时序图和官方例程就可以写出。另外可以看到是“从一点到一行到一页”的显示方式。于是乎,要实现如下图形的显示只需要把整个页面分为4个大行和4个大纵,然后分别在应该的时间操作RGB三个数据线的模拟电压即可。
    file:///C:/Users/zcat/AppData/Local/Temp/msohtmlclip1/01/clip_image010.jpg
    在看一看原理图
    file:///C:/Users/zcat/AppData/Local/Temp/msohtmlclip1/01/clip_image012.jpg
    BASYS2的板子上,分别用了3个引脚控制红色,3个引脚控制绿色,2个引脚控制蓝色。所以引脚如下设置:
    entity DispCtrl is
    Port (ck: in std_logic;  -- 50MHz
    --        Hcnt: in std_logic_vector(9 downto0);      -- horizontal counter
    --        Vcnt: in std_logic_vector(9 downto0);      -- verical counter
            HS: out std_logic;                             -- horizontalsynchro signal                             
            VS: out std_logic;                             -- verical synchrosignal
            outRed : out std_logic_vector(2 downto 0); -- final color
            outGreen: out std_logic_vector(2 downto0);    -- outputs
            outBlue : out std_logic_vector(2 downto1)
                    );
    end DispCtrl;
    然后定义常量和信号量:
    architecture Behavioral ofDispCtrl is
    -- constants for Synchro module
    constant PAL:integer:=640;           --Pixels/ActiveLine (pixels)--行图像
    constant LAF:integer:=480;           --Lines/ActiveFrame (lines)--场图像
    constant PLD: integer:=800;   --Pixel/LineDivider--行周期
    constant LFD: integer:=521;   --Line/FrameDivider--场周期
    constant HPW:integer:=96;            --Horizontalsynchro Pulse Width (pixels)--行同步头
    constant HFP:integer:=16;             --Horizontalsynchro Front Porch (pixels)--显示前沿
    --  constant HBP:integer:=48;          --Horizontal synchro Back Porch(pixels)
    constant VPW:integer:=2;              --Vericalsynchro Pulse Width (lines)--场同步头
    constant VFP:integer:=10;             --Vericalsynchro Front Porch (lines)
    --  constant VBP:integer:=29;          --Verical synchro Back Porch (lines)
    -- signals for VGA Demo
    signal Hcnt: std_logic_vector(9 downto 0);      -- horizontal counter
    signal Vcnt: std_logic_vector(9 downto 0);      -- verical counter
    signal intHcnt: integer range 0 to 800-1; --PLD-1 - horizontal counter
    signal intVcnt: integer range 0 to 521-1; -- LFD-1 - verical counter
    signal ck25MHz: std_logic;            --ck 25MHz
    做一次分频,得到需要的25MHZ,可以看出demo的分频方式非常的巧妙
    begin
    -- divide 50MHz clock to 25MHz
      div2: process(ck)
      begin
        if ck'event andck = '1' then
          ck25MHz <= not ck25MHz;
          
        end if;
      end process;   
    接下来是操作VGA的核心时序了!!
      syncro: process (ck25MHz)
    begin
    if ck25MHz'event and ck25MHz='1' then
        if intHcnt=PLD-1 then
           intHcnt<=0;
          if intVcnt=LFD-1 then intVcnt<=0;
          else intVcnt<=intVcnt+1;
          end if;
        else intHcnt<=intHcnt+1;
        end if;
          
           --Generates HS - active low
           ifintHcnt=PAL-1+HFP then
                  HS<='0';
           elsifintHcnt=PAL-1+HFP+HPW then
                  HS<='1';
           endif;
           --Generates VS - active low
           ifintVcnt=LAF-1+VFP then
                  VS<='0';
           elsifintVcnt=LAF-1+VFP+VPW then
                  VS<='1';
           endif;
    end if;
    end process;
    -- mapping itnernal integers tostd_logic_vector ports
    Hcnt <= conv_std_logic_vector(intHcnt,10);
    Vcnt <= conv_std_logic_vector(intVcnt,10);
    最后是显示如上图所示的格子的代码:
    mixer: process(ck25MHz,intHcnt,intVcnt)
    begin
        if intHcnt < PAL and intVcnt < LAFthen       -- in the active screen
    --
                  ifVcnt(8 downto 7) = "00" then
             
             outGreen <= "000";
             outBlue <= "00";
                         ifHcnt(8 downto 7) = "00" then
                         
                          outRed <= "100";
                         elsifHcnt(8 downto 7) = "11" then
                         
                          outRed <= "110";
                         
                          else
                         
                          outRed <= "000";
                          end if;
                         
          elsif Vcnt(8 downto 7) = "01"then
                         ifHcnt(8 downto 7) = "01" then
             outRed <= "000";
             outGreen <= Vcnt(5 downto 3);
             outBlue <= "00";
                         elsifHcnt(8 downto 7) = "10" then
                         outRed<= "000";
             outGreen <= "000";
             outBlue <= "01";
                         else
                         outGreen<= "000";
             outBlue <= "00";
                         outRed<= "000";
                         endif;
          elsif Vcnt(8 downto 7) = "10"then
             if Hcnt(8 downto 7) = "01"then
             outRed <= Vcnt(5 downto 3);
             outGreen <= Vcnt(5 downto 3);
             outBlue <= Vcnt(5 downto 4);
                         
                         elsifHcnt(8 downto 7) = "10" then
                         outRed<= "000";
             outGreen <= "000";
             outBlue <= "11";
                         else
                         outGreen<= "000";
             outBlue <= "00";
                         outRed<= "000";
                         endif;
          else
             outGreen <= "000";
             outBlue <= "00";
                         ifHcnt(8 downto 7) = "00" then
                         
                          outRed <= "100";
                         elsif Hcnt(8 downto 7) = "11" then
                         
                          outRed <= "110";
                         
                          else
                         
                          outRed <= "000";
                          end if;
          end if;
        else
             outRed <= (others => '0');
             outGreen <= (others => '0');
             outBlue <= (others => '0');
        end if;  
    end process;
    有几点心得可以分享一下,
    1、 时序必须严格,否则会显示不正常
    2、 由于是640*480,所以长宽比例不是1:1在显示器上显示的格子会多显示其他部分,这个需要做修正。
    3、 当药静态显示某个画面的时候,每一个点的在变换的时候必须在每页刷新的的频率的倍数,否则会跳动。
    4、 本来想做字符显示的,但是貌似需要外扩RAM,不知道说得对不对。

    无标题.png


    新建 Microsoft Word 文档5.pdf (294.43 KB, 下载次数: 70)
    回复

    使用道具 举报

  • TA的每日心情
    奋斗
    2014-7-16 09:10
  • 签到天数: 361 天

    连续签到: 1 天

    [LV.8]以坛为家I

    发表于 2012-12-3 16:17:00 | 显示全部楼层
    {:soso_e179:}{:soso_e179:}{:soso_e179:}支持支持
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2020-3-19 13:22
  • 签到天数: 805 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2012-12-3 18:42:28 | 显示全部楼层
    {:soso_e179:}    有空先按这个做一次  呵呵
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2015-8-7 21:35
  • 签到天数: 340 天

    连续签到: 1 天

    [LV.8]以坛为家I

    发表于 2012-12-3 20:12:46 | 显示全部楼层
    刷铜板……
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2020-3-19 13:22
  • 签到天数: 805 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2012-12-13 11:25:30 | 显示全部楼层
    请教个问题  这个50M时钟是怎么得到的啊?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2013-8-4 18:50
  • 签到天数: 6 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    发表于 2012-12-13 21:22:10 | 显示全部楼层
    swustlx86 发表于 2012-12-13 11:25
    请教个问题  这个50M时钟是怎么得到的啊?

    芯片产生。。。。。。。。。。。。。。。。。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2020-3-19 13:22
  • 签到天数: 805 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2012-12-14 08:43:14 | 显示全部楼层
    zca123 发表于 2012-12-13 21:22
    芯片产生。。。。。。。。。。。。。。。。。

    mclk吗?                     
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-12-25 21:35 , Processed in 0.172105 second(s), 27 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.