0
こんにちは、DE2_LCM2 (vhdl) という LCM のメイン プログラム構造をコーディングしています。

メイン構造内には、PLL2 (verilog)I2S_LCM_Config ( verilog) を呼び出すクロック分周器があります。私の PLL2.v と I2S_LCM.v はベンダーから提供されていますが、DE2_LCM.vhd は自分でコーディングしています。コンパイルは成功しましたが、刺激に失敗しました。

ご参考までに:

水平スキャン:

1 水平ライン、DCLK の 1171 カウントまたはサイクルがあります。LCM_HSYNC は、DCLK の立ち下がりエッジで 1 サイクル間 Low になります。最初の 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.vI2S_LCM_Config.vが必要かどうか教えてください。メールでお送りします。

前もって感謝します:)

4

1 に答える 1

0

PLL または I2C をチェックしないと、垂直カウンターはラインではなくクロックをカウントしているように見えます。

垂直カウンタ カウント CLK_18 を示す LCM_TB

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 に範囲制約付き整数を使用できない理由もわかりません。

補遺

答えが混乱を引き起こしたので:

申し訳ありませんが、率直に言って、何を達成しようとしているのかは理解していますが、あなたのコードは理解できません。– user317130 13時間前

std_logic パッケージの Synopsys バージョンを使用して、ソリューションをやり直すことにしました。これにより、変更がより簡単になり、見やすくなります。

まず、ローカルで CLK_18 を生成する CLOCK プロセスを作成しました。これはテスト ベンチにあり、単純に CLK_18 を CLK_50 で駆動することもできたので、名前を混乱させたくありませんでした。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)。少なくとも半分に減らすことができます。

シノプシスの標準ロジック ライブラリを使用すると、バーティカル カウンターの動作の変更がより明確になります。

    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 カウンターのみを操作することで構成されているため、カウンターはスキャン ラインごとに 1 回しか操作しません。

追加されたテスト ベンチ:

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 シノプシスの標準ロジック パッケージを使用

GTKWave の水平スクロール バーから、シミュレーションが必要な時間の 2 倍になっていることがわかります。

また、std_logic_vector 値を使用する代わりに、IEEE 標準準拠のパッケージ numeric_std で符号なしを使用して、わずかな変更を加えたり、H_Cont と V_Cont を範囲制約付き整数に変換したり (これにより問題なく合成されます)、"00000000000"0 と適切... + '1'+ 1場所への変換を忘れずに行うことができます。

もっと早く戻ってきたかったのですが、タイムゾーンは GMT-12 です (ここは明日です)。

于 2014-07-30T05:25:36.040 に答える