0
嗨,我正在为我的 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 无效。

垂直扫描(逐行扫描):

在水平线的最后一个周期之后,垂直计数器应加一。这个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.vI2S_LCM_Config.v ,请告诉我。我会通过电子邮件发送给你。

提前致谢:)

4

1 回答 1

0

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

LCM_TB 显示垂直计数器计数 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;

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

这给了你一些看起来更合理的东西(但还没有真正被检查过,毕竟这是你的设计):

垂直计数器正确递增

以及下一个垂直事件:

在此处输入图像描述

我也看不出有任何理由不能对 H_Cont 和 V_Cont 使用范围受限的整数。

附录

因为答案引起了混乱:

抱歉,坦率地说,我确实了解 ru 试图实现的目标,但我不了解您的代码。– 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;

The build process:

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

And because this is a Mac open *.ghw, or after establishing a save file open *.gtkw. (OS X claims suffixes like Windows, the open command tells it to...).

And all this gives the same answer as the version using package numeric_std:

lcm_tb 使用 Synopsys 标准逻辑包

From the horizontal scroll bar in GTKWave you can see the simulation was twice as long as needed.

而不是使用 std_logic_vector 值,您可以使用 unsigned 与 IEEE 标准兼容包 numeric_std 稍作修改或将 H_Cont 和 V_Cont 转换为范围受限的整数(合成得很好),不要忘记转换"00000000000"为 0 和适当... + '1'+ 1地方。

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

于 2014-07-30T05:25:36.040 回答