0

現在、VHDL で画面バッファを作成しようとしています (VGA 経由でビデオ データを送信するデバイス用)。Xilinx ISE 13.1 を使用しており、VHDL の初心者です。

私の考えは、各ピクセルの RGB 値 (8 ビット) を含む大きな二次元配列を作成することでした。

問題なく配列に書き込むことはできますが、読み取る必要がある場合はさらに複雑になります。合成は非常に長くなり、コンピューターが自動的にシャットダウンするまで、XST はメモリを完全に飽和させます。

これは私のコードの簡略版で、赤い 45° の線を描こうとしているだけです:

entity Pilotage_ecran is
port(clk25  : in std_logic; --25MHz clock
   red_out   : out std_logic; --Untill the problem is solved, i use only 1 bit to set colors
   green_out : out std_logic;
   blue_out  : out std_logic;
   hs_out    : out std_logic;
   vs_out    : out std_logic);
end Pilotage_ecran;

architecture Behavioral of Pilotage_ecran is


signal horizontal_counter : std_logic_vector (9 downto 0);
signal vertical_counter   : std_logic_vector (9 downto 0);
signal drawing   : std_logic; --Signal that is set to 1 when the active video area is reached
signal busy   : std_logic;  --Signal to avoid launching the drawing process twice in parallel


--The array (actually containing single bits instead of vectors untill I solve the problem)
type TAB_BUFFER is array(0 to 1023, 0 to 1023) of std_logic; 

signal Ecran :  TAB_BUFFER := (others=>'0');


begin

主な工程:

process (clk25)  

variable coordX : integer; 
variable coordY : integer;

begin
  if clk25'event and clk25 = '1' then


    if (horizontal_counter >= "0010010000" ) -- 144 : limits of active video area
    and (horizontal_counter < "1100010000" ) -- 784 
    and (vertical_counter >= "0000100111" ) -- 39
    and (vertical_counter < "1100010000" ) -- 519 
    then

        drawing <= '1';

     coordX := conv_integer (horizontal_counter);
     coordY := conv_integer (vertical_counter);


         if Ecran(coordX,coordY) = '1' then  --Here is the problem
            red_out <= '1'; 
                    green_out <= '0';
            blue_out <= '0';
         else
            red_out <= '0'; 
                    green_out <= '0';
            blue_out <= '0';
         end if;



     else
       drawing <= '0';

    end if;




     --Hsync and Vsync come after, but the code is safe and tested

end if;   
end process;

描画プロセス(実際には醜い方法で線を描画しますが、バッファに何かを入れたかっただけです)。

draw : 
process (drawing, clk25, busy)


 --Coordinates of the starting point (actually random values...)

variable i : integer;
variable j : integer;

begin

    if (drawing = '1') and clk25 = '1' and busy = '0' then

        busy <= '1';

        i :=300;
        j :=300;

        --The loop setting the coordinates of the line to '1'

        loopx : while (i<=350)  loop
            Ecran(i,j) <= '1';
            i := i+1;
            j := j+1;

        end loop loopx;

        busy <='0';
    end if; 


end process draw;



end Behavioral;

問題を引き起こす行は、バッファ内のいくつかの座標で値にアクセスしようとする行です:

Ecran(coordX,coordY) = '1' の場合

私もこのようにしようとしました:

red_out <= Ecran(coordX,coordY);

coordX または coordY のいずれかを整数値に置き換えると、正常に動作します (表示はバッファーと一致しませんが動作します) が、両方に変数を使用すると、合成中にクラッシュします。いくつかの作業コードと一致しているように見えても、配列に何か問題があったと確信しています (配列の使用方法を学んだばかりです)。また、(そしておそらく)大きすぎる配列を使用している可能性もあります。

私が何を間違えたのか、またはvhdlでスクリーンバッファを作成する方法についてより良い方法を知っている人がいれば、どんな助けでも大歓迎です。

事前にどうもありがとうございました。

4

2 に答える 2

2

VGA がどのように機能するかはわかりませんが、コードを見ると、「描画プロセス」に根本的な問題があると思います。ハードウェア開発者ではなく、ソフトウェア開発者として何かをしようとしています。

つまり、ほとんどのプロセスをこの if ステートメントの下にネストします。

if (drawing = '1') and clk25 = '1' and busy = '0' then

あなたの問題です。私が見ることができる2つの理由。まず、クロックに対して完全に非同期のレートでループ内のカウンターをインクリメントしています(クロック= '1'の場合)、これは非有限期間高いです。したがって、そのインクリメンタの更新は、カウンタを介した伝搬遅延によってのみ制限されます。すべてのカウンターは同期している必要があります (rising_edge(clk) の場合) または (clock = 1 および clk'event の場合)。

もう 1 つのエラーは、現在の組み合わせ設定 (非同期) に関係しており、これを同期プロセスにすると解消されます。組み合わせロジックの if ステートメントの直後に busy <= '1' を実行することで、ハードウェアでそのブロックを本質的に非アクティブにしています。同期ソリューションのコーディング方法によっては、これが問題になる場合とそうでない場合があります。

最後に、これは、ハードウェアではなくソフトウェアのプログラミングを考えているためです。if ステートメントの最初で busy<='1' を実行し、最後に busy<='0' を実行します。同期設計でも非同期設計でも、ビジー <='0' という結果になります。代わりに、(同期する場合) if ステートメントの外側でビジー <= '0' を使用し、if ステートメントの内側でビジー <= '1' を使用します。ステートメントが実行されるたびに、クロック信号全体でビジーが 1 になります。

VHDL をプログラムするときは、すべてのコマンドが継続的に (非同期) または定期的に (クロックと同期して) 実行されることを考慮する必要があります。if ステートメント内のイベントが true でなくても、if ステートメント内のすべてのイベントが実行されています。if ステートメントは単に「有効」として機能します。以上のことをすべて言いましたが、次のコードはあなたが望むことをしているかもしれません。

draw : process (clk25)
    --Coordinates of the starting point (actually random values...)
    variable i : integer := 300;
    variable j : integer := 300;

begin

    if (rising_edge(clk)) then
        busy <= '0';
        if (i<=350) then
            busy <= '1';
            Ecran(i,j) <= '1';
            i := i+1;
            j := j+1;
        end if; 
    end if;
end process draw;

あなたの「引き出し」は実際には大きな配列を事前にロードしているだけで、色を設定している他のプロセスは実際にはあなたのライターだと思いますか? 画面に赤/緑/青のビットを書き込むときに、行全体をインクリメントしてから列を下にシフトしているという印象を受けましたか? 繰り返しますが、VGAについては何も知りません

于 2012-01-18T20:53:37.373 に答える
1

coordX または coordY のいずれかを整数値に置き換えると、正常に動作します (表示はバッファーと一致しませんが動作します) が、両方に変数を使用すると、合成中にクラッシュします。いくつかの作業コードと一致しているように見えても、配列に何か問題があったと確信しています (配列の使用方法を学んだばかりです)。また、(そしておそらく)大きすぎる配列を使用している可能性もあります。

問題は、RAM の小さなブロックで構成される大きなメモリ用の読み取りマルチプレクサを構築しようとしていることです。十分なブロックがあれば、特定のビルド プラットフォームにとって問題は扱いにくくなります。

ビデオ タイミング ジェネレーターを変更して、ディスプレイの読み取りアドレスを切り離すことができます。この場合、TAB_BUFFER をより小さく (0 ~ 639、0 ~ 479) 定義して、メモリの 3 分の 2 (307,200 対 1 M ピクセル) を節約できます。それが問題を合成するのに十分なほど小さくスケールダウンするかどうかは明らかではありません。

また、別のディスプレイ アドレス カウンターを使用するか、またはラインの最初の可視ピクセルまたはディスプレイの最初の可視ラインとして 0 を通過させることにより、現在の水平および垂直カウンターからフレーム バッファー アドレスを分離することもお勧めします。これにより、書き込み中にアドレス変換を行う必要がなくなります。

メモリ設計を定義して、合成できないことを克服することができます。これは、配置を行うのと同じくらい簡単な場合もあれば、階層を作成するのと同じくらい複雑な場合もあります。アイデアは、行う作業を減らすことで、合成からハードワークの一部を取り除くことです。

于 2012-01-19T08:05:28.127 に答える