编程Altera DE2,用于在VHDL中显示LCM上的颜色

时间:2014-07-30 03:23:25

标签: vhdl quartus

嗨,我正在编写我的LCM的主程序结构,称为DE2_LCM2(在vhdl中)。

在主结构中,有一个时钟分频器调用 PLL2(在verilog中)和一个 I2S_LCM_Config(在verilog中)。 我的PLL2.v和I2S_LCM.v由供应商提供,除了我的DE2_LCM.vhd,我自己编码。编译成功,但刺激失败。

供参考:

横向扫描:

1水平线,有1171个DCLK计数或周期。 LCM_HSYNC在DCLK的下降沿期间变为低电平,持续1个周期。对于前152个周期,LCM_DATA总线上的数据无效,从周期153到1112开始有效,从周期1112到1171无效。

垂直扫描(非隔行扫描):

在水平线的最后一个循环之后,垂直计数器应增加1。该LCM总共有262条垂直线,但只显示第15行到第(15 + 240)= 255行。

LCM_PLL.v:

此文件有助于将系统时钟50MHz转换为18.42MHz。 DCLK或LCM_DCLK将用于水平和垂直计数器。

以下是我的DE2_LCM.vhd代码,无法找到我的代码出错的地方。我的老师还有一些休假。

library ieee;
use ieee.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;

entity DE2_LCM2 is port(CLOCK_50 : in std_logic;
                   KEY0 : in std_logic;
                   SW : in std_logic_vector(1 downto 0);
                   LCM_DATA : out std_logic_vector(7 downto 0);
                   LCM_DCLK, LCM_HSYNC, LCM_VSYNC,LCM_SCLK,LCM_SDAT,LCM_SCEN,LCM_GRST,LCM_SHDB : out std_logic
                    );
end DE2_LCM2;

architecture rtl of DE2_LCM2 is
  constant H_SYNC_CYC: integer:=1;
  constant H_SYNC_BACK: integer:=152;
  constant H_SYNC_ACT: integer:=960;
  constant H_SYNC_FRONT: integer:=59;
  constant H_SYNC_TOTAL: integer:=1171;

  constant V_SYNC_CYC: integer:=1;
  constant V_SYNC_BACK: integer:=14;
  constant V_SYNC_ACT: integer:=240;
  constant V_SYNC_FRONT: integer:=8;
  constant V_SYNC_TOTAL: integer:=262;

  signal H_Cont: std_logic_vector(10 downto 0);
  signal V_Cont: std_logic_vector(10 downto 0);
  signal MOD_CNT: std_logic_vector(1 downto 0);
  signal Tmp_DATA1: std_logic_vector(11 downto 0);
  signal CLK_18: std_logic;
  signal mSEL: std_logic_vector(1 downto 0);
  signal iRST_N: std_logic;
  signal I2S_SDAT: std_logic;

component LCM_PLL2 port(inclk0: in std_logic;
                      c0: out std_logic);
end component;

component I2S_LCM_Config is port(iCLK: in std_logic;
                             iRST_N: in std_logic;
                             I2S_SCLK: out std_logic;
                             I2S_SDAT: inout std_logic;
                             I2S_SCEN: out std_logic);
end component;

begin
  LCM_GRST<=KEY0;
  LCM_DCLK<=not(CLK_18);
  LCM_SHDB<='1';
  iRST_N<=KEY0;
  LCM_SDAT<=I2S_SDAT; --add on

  process(SW,MOD_CNT )
    begin
      if(SW="00")then 
        if(MOD_CNT="00")then
          LCM_DATA<="01111111";
        else LCM_DATA<="00000000";
        end if;
      elsif(SW="01")then
        if(MOD_CNT="01")then
          LCM_DATA<="01111111";
            else LCM_DATA<="00000000";
        end if;
      elsif(SW="10")then
        if(MOD_CNT="10")then
          LCM_DATA<="01111111";
        else LCM_DATA<="00000000";
        end if;
      else LCM_DATA<="00000000";
      end if;
  end process;

u0:LCM_PLL2 port map(inclk0=>CLOCK_50,
                c0=>CLK_18);
u1:I2S_LCM_Config port map(iCLK=>CLOCK_50,
                       iRST_N=>KEY0,
                       I2S_SCLK=>LCM_SCLK,
                       I2S_SDAT=>I2S_SDAT,
                       I2S_SCEN=>LCM_SCEN);

process(CLK_18,iRST_N)
  begin
    if(rising_edge(CLK_18))then
      if iRST_N = '0'then
      MOD_CNT <= "11";
      H_Cont <= "00000000000";
      LCM_HSYNC <= '0';
      V_Cont <= "00000000000";
      LCM_VSYNC <= '0';
      else
        if((H_Cont >= H_SYNC_BACK) and (H_Cont<(H_SYNC_TOTAL-H_SYNC_FRONT)))then
          if(MOD_CNT < "10") then 
          MOD_CNT <= MOD_CNT + '1';
          else
          MOD_CNT <= "00";
          end if;
        else MOD_CNT <= "11";
        end if;

        if(H_Cont < (H_SYNC_TOTAL-1)) then
        H_Cont <= H_Cont + '1';
        else H_cont <= "00000000000";
        end if;

        if(H_Cont < H_SYNC_CYC)then
        LCM_HSYNC <= '0';
        else LCM_HSYNC <= '1';
        end if;

        if(V_Cont <(V_SYNC_TOTAL-1)) then
          V_Cont <= V_Cont+'1';
        else V_Cont <= "00000000000";
        end if;

        if(V_Cont < V_SYNC_CYC) then
        LCM_VSYNC <= '0';
        else LCM_VSYNC <= '1';
        end if;
      end if; 
    end if;
end process;                                                      
end rtl;

应该是我的编码风格,不适合硬件编程。如果您的测试需要 PLL2.v I2S_LCM_Config.v ,请告诉我们。我会通过电子邮件发送给您。

提前致谢:)

1 个答案:

答案 0 :(得分:0)

在不检查PLL或I2C的情况下,垂直计数器似乎是计数时钟而不是行:

LCM_TB showing vertical counter counting CLK_18

当H_Cont是最大计数(1170)时,需要额外的限定符才能增加V_cont。

有些事情:

            if H_Cont = std_logic_vector (to_unsigned (H_SYNC_TOTAL-1,11)) then

                if V_Cont < std_logic_vector(to_unsigned (V_SYNC_TOTAL-1, 11)) then
                    V_Cont <= std_logic_vector(unsigned(V_Cont) + 1);
                else 
                    V_Cont <= (others => '0');
                end if;
            end if;

(Ya,我使用了包numeric_std,起诉我。重新格式化你的代码以使其可读)。

这会给你一些看起来更合理的东西(但实际上并没有经过检查,毕竟这是你的设计):

vertical counter incrementing properly

下一个垂直事件:

enter image description here

我也没有看到任何理由不能为H_Cont和V_Cont使用范围约束整数。

<强>附录

因为答案引起了混淆:

  抱歉,坦率地说,我明白你想要实现的目标,但是我   不明白你的代码。 - user317130 13小时前

我想我会使用Synopsys版本的std_logic软件包重做解决方案。它使更改更简单,更容易看到。

首先,我创建了一个在本地生成CLK_18的CLOCK进程。这可能是在测试台上,只是用CLK_50驱动CLK_18,我不想让任何名字混淆。我还将I2C和PLL注释为未提供/未提供:

signal CLK_18: std_logic := '0';  -- default value to allow not in CLOCK process to run

删除未提供的组件:

-- component LCM_PLL2 port(inclk0: in std_logic;
--                       c0: out std_logic);
-- end component;
--
-- component I2S_LCM_Config is port(iCLK: in std_logic;
--                              iRST_N: in std_logic;
--                              I2S_SCLK: out std_logic;
--                              I2S_SDAT: inout std_logic;
--                              I2S_SCEN: out std_logic);
-- end component;

--
-- u0:LCM_PLL2 port map(inclk0=>CLOCK_50,
--                 c0=>CLK_18);
-- u1:I2S_LCM_Config port map(iCLK=>CLOCK_50,
--                        iRST_N=>KEY0,
--                        I2S_SCLK=>LCM_SCLK,
--                        I2S_SDAT=>I2S_SDAT,
--                        I2S_SCEN=>LCM_SCEN);

是的,这留下一些信号未被发现。我们将在本地驱动CLK_18:

-- Dummy up CLK_18:
CLOCK:
    process
    begin 
        wait for 27.15 ns;
        CLK_18 <= not CLK_18;
        if Now > 80 ms then
            wait;
        end if;
    end process;
-- Here instead of the test bench, could have jumpered CLOCK_50 to CLK_18

80毫秒相当过分(模拟将一直运行,直到没有事件发生,一切都被驱动掉时间)。花了相当长的时间来模拟并且波形转储很大(32 MB)。它至少可以减少一半。

使用Synopsys标准逻辑库,操作垂直计数器的变化更为明显:

    if H_Cont = H_SYNC_TOTAL - 1 then

        if(V_Cont <(V_SYNC_TOTAL-1)) then
          V_Cont <= V_Cont+'1';
        else V_Cont <= "00000000000";
        end if;
    end if;

它只包括在H_Cont的最后一次计数中操作V_Cont计数器,因此计数器每个扫描行只运行一次。

增加的测试平台:

library ieee;
use ieee.std_logic_1164.all;

entity LCM_TB is
end entity;

architecture foo of LCM_TB is
    signal CLOCK_50:   std_logic := 'H';
    signal KEY0:       std_logic := '0';
    signal SW:         std_logic_vector(1 downto 0) := "11";
    signal LCM_DATA:   std_logic_vector(7 downto 0);
    signal LCM_DCLK, 
           LCM_HSYNC, 
           LCM_VSYNC,
           LCM_SCLK,
           LCM_SDAT,
           LCM_SCEN,
           LCM_GRST,
           LCM_SHDB: std_logic;
begin

-- CLOCK process found in DUT

DUT:
    entity work.de2_lcm2
        port map (
            CLOCK_50 => CLOCK_50,
            KEY0 => KEY0,
            SW => SW,
            LCM_DATA => LCM_DATA,
            LCM_DCLK => LCM_DCLK,
            LCM_HSYNC => LCM_HSYNC, 
            LCM_VSYNC => LCM_VSYNC,
            LCM_SCLK => LCM_SCLK,
            LCM_SDAT => LCM_SDAT,
            LCM_SCEN => LCM_SCEN,
            LCM_GRST => LCM_GRST,
            LCM_SHDB => LCM_SHDB
        );

STIMULUS:  -- Just a reset
    process
    begin
        wait for 100 ns;
        KEY0 <= '1';
        wait;
    end process;

end architecture;

构建过程:

ghdl -a --ieee = synopsys -fexplicit de2_lcm2.vhdl
ghdl -e --ieee = synopsys -fexplicit lcm_tb
ghdl -r lcm_tb --wave = lcm_tb.ghw

因为这是Mac open *.ghw,或者在建立保存文件open *.gtkw之后。 (OS X声称像Windows这样的后缀,open命令告诉它......)。

所有这些都给出了与使用包numeric_std的版本相同的答案:

lcm_tb using Synopsys standard logic packages

从GTKWave的水平滚动条中,您可以看到模拟时间是所需时间的两倍。

而不是使用std_logic_vector值,你可以使用unsigned与IEEE标准兼容的包numeric_std进行一些轻微的修改,或者将H_Cont和V_Cont转换为范围约束的整数(它将合成得很好),不要忘记转换"00000000000"适当时为0和... + '1'+ 1

我会更快地回来,但我在时区GMT-12(明天就在这里)。