7

Terasic の本と Altera DE1 開発キットを使って VHDL プログラミングを学ぼうとしています。

ここでの問題は、640x480 の解像度で動作するように VGA コントローラーをプログラムしようとしていることです (私の画面は 1280x1024 の TFT LCD ですが)。

コードに問題があります。

FSM を使用して垂直信号と水平信号を作成し、別のブロックで RGB 入力を駆動し、DE1 から 27 MHz クロックも使用しています。

画面に印刷する画像は正しいサイズ (640x480) ではなく、大きい (約 1174x980) ため、コードに何か問題があると思います。

今のところ、間違いが見つかるまで画面を単純化するために、画面に 1 つの色のみを配置しようとしています。

私のプロジェクトには 3 つのファイルがあり、1 つはブロック RGB 用、1 つは FSM 用、もう 1 つはそれらの両方をインスタンス化するためのものです。

この問題を解決するために何らかの助けをいただければ幸いです。なぜなら、私はそれを理解しようと努力しましたが、どこに間違いがあるのか​​ わかりません。

どうもありがとう!

オマール

VGA コントローラ ファイル

library ieee;
use ieee.std_logic_1164.all;

entity VGA_controller is
     port(clk, reset : in std_logic;
        Hsync,Vsync : out std_logic;
        R,G,B : out std_logic_vector(3 downto 0));
end entity;

architecture arch of VGA_controller is

component FSM_sync is
    port(clk,reset : in std_logic;
        Hsync,Vsync,VIDON : out std_logic;
        Vcount,Hcount : out integer range 0 to 799);
end component;

component VGA_display is
    port(hcount,vcount : in integer range 0 to 799;
        r,g,b : out std_logic_vector(3 downto 0);
        video_on : in std_logic);
end component;

signal video : std_logic;
signal signal1 : integer range 0 to 799;
signal signal2 : integer range 0 to 799;

begin

maquinaestado_sync : FSM_sync port map (clk=>clk, reset=>reset, Hsync=>Hsync, Vsync=>Vsync, Vcount=>signal1, Hcount=>signal2, VIDON=>video);

salida_pantalla : VGA_display port map (r=>R, g=>G, b=>B, video_on=>video, vcount=>signal1, hcount=>signal2 );

end arch;

FSM 同期ファイル

library ieee;
use ieee.std_logic_1164.all;


entity FSM_sync is
    port(clk,reset : in std_logic;
        Hsync,Vsync,VIDON : out std_logic;
        Vcount,Hcount : out integer range 0 to 799);
end entity;


architecture arch of FSM_sync is
--constantes para definir los ciclos de reloj de cada señal del HSYNC
constant counterMAX : integer := 640;
constant counterSP : integer := 96;
constant counterBP : integer := 48;
constant counterHV : integer := 640;
constant counterFP : integer := 16;
--constantes para definir los ciclos de reloj de cada señal del VSYNC
constant counterMAX_V : integer := 384000;  -- calculamos estos valores multiplicando el numero de filas por los pixeles en cada fila horizontal (800)
constant counterSP_V : integer := 1600;     -- de manera que cada estado de la sincronizacion vertical dure todo el recorrido de los pixeles de cada fila
constant counterBP_V : integer := 26400;
constant counterVV : integer := 384000;
constant counterFP_V : integer := 8000;
--constantes para el numero de pixeles maximo que debemos controlar en horizontal y en vertical
constant number_pixelsMAX_H : integer := 800;
constant number_pixelsMAX_V : integer := 525;

type state is (SP_1,BP,HV,FP,reseteo);  --4 estados para cada maquina de estado de sincronizacion (vertical y horizontal)
signal present_state_H,next_state_H,present_state_V,next_state_V : state;

signal timer : integer range 0 to counterMAX ; -- señal para pasar el valor counterXX al proceso secuencial para compararlo con un contador y establecer el
                                                -- tiempo de duracion de cada estado
signal timer2 : integer range 0  to counterMAX_V ;  --lo mismo que la señal anterior pero para el sincronizacion vertical

signal video_1,video_2 : std_logic; 

signal hcount_reg,vcount_reg : integer range 0 to 799;

begin

--==============================================
--FSM para la sincronizacion del barrido HORIZONTAL
--===============================================

lower_part_1 : process (clk,reset)
                variable counter : integer range 0 to counterMAX - 1;   --variable para crear un contador de pulsos del clk
                variable counter2 : integer range 0 to number_pixelsMAX_H - 1;          --contador para los pixeles horizontales    
                variable counter3 : integer range 0 to number_pixelsMAX_V - 1;          --contador para los pixeles verticales
             begin                                                  --se cargan con 800 por que 800 son los pixeles que hay que leer en horizontal 
                if (reset = '1') then                               --esto implica contadores de al menos 10 bits para llegar a ese numero.
                                                                    --y para que los dos contadores sean del mismo numero de bits se cargan los dos igual   
                    counter := 0;                                   --realmente en vertical solo debemos contar hasta 521
                    counter2 := 0;          
                    counter3 := 0;
                    present_state_H <= reseteo;


                elsif (clk'event and clk = '1') then
                    counter := counter + 1;

                    if (counter2 < number_pixelsMAX_H-1) then
                        counter2 := counter2 + 1;
                    else
                        counter2 := 0;
                        if (counter3 < number_pixelsMAX_V-1) then
                            counter3 := counter3 + 1;
                        else
                            counter3 := 0;
                        end if;
                    end if;

                    hcount_reg <= counter2;
                    vcount_reg <= counter3;

                    if (counter = timer) then
                        present_state_H <= next_state_H;
                        counter := 0;
                    end if;
                end if;
                end process lower_part_1;


upper_part_1 : process (next_state_H)
             begin

                Hsync <= '1';
                next_state_H <= HV;

                case present_state_H is
                    when SP_1 =>
                        Hsync <= '0';
                        next_state_H <= BP;
                        timer <= counterSP;

                        video_1 <= '0';

                    when BP =>
                        Hsync <= '1';
                        next_state_H <= HV;
                        timer <= counterBP;

                        video_1 <= '0';

                    when HV =>
                        Hsync <= '1';
                        next_state_H <= FP;
                        timer <= counterHV;

                        video_1 <= '1';


                    when FP =>
                        Hsync <= '1';
                        next_state_H <= SP_1;
                        timer <= counterFP;

                        video_1 <= '0';

                    when reseteo =>
                        Hsync <= '1';
                        next_state_H <=HV;



                    end case;
                end process upper_part_1;

--==============================================
--FSM para la sincronizacion del barrido VERTICAL
--===============================================               


lower_part_2 : process (clk,reset)
                variable counter2 : integer range 0 to counterMAX_V;    --variable para crear un contador de pulsos del clk
             begin
                if (reset = '1') then
                    counter2 := 0;
                    present_state_V <= reseteo;



                elsif (clk'event and clk = '1') then
                    counter2 := counter2 + 1;



                    if (counter2 = timer2) then
                        present_state_V <= next_state_V;
                        counter2 := 0;
                    end if;
                end if;
                end process lower_part_2;


upper_part_2 : process (next_state_V)
             begin

                Vsync <= '1';
                next_state_V <= HV;

                case present_state_V is
                    when SP_1 =>
                        Vsync <= '0';
                        next_state_V <= BP;
                        timer2 <= counterSP_V;
                        video_2 <= '0';
                    when BP =>
                        Vsync <= '1';
                        next_state_V <= HV;
                        timer2 <= counterBP_V;

                        video_2 <= '0';

                    when HV =>
                        Vsync <= '1';
                        next_state_V <= FP;
                        timer2 <= counterVV;

                        video_2 <= '1';

                    when FP =>
                        Vsync <= '1';
                        next_state_V <= SP_1;
                        timer2 <= counterFP_V;

                        video_2 <= '0';

                    when reseteo =>
                        Vsync <= '1';
                        next_state_V <=HV;


                    end case;
                end process upper_part_2;


VIDON <= video_1 AND video_2;
Vcount <= vcount_reg;
Hcount <= hcount_reg;

        end arch;

VGD 表示ファイル

library ieee;
use ieee.std_logic_1164.all;


entity VGA_display is
    port(hcount,vcount : in integer range 0 to 799;
        r,g,b : out std_logic_vector(3 downto 0);
        video_on : in std_logic);
end entity;



architecture arch of VGA_display is

begin

process (video_on)
begin
    if video_on = '1' then  --solo activamos los pixeles cuando vidon esté a uno, es decir, esten en la fase HV y VV las sincronizaciones
            r <= "1111";
            g <= "0000"; 
            b <= "0000";

    else
        r <= (others => '0');
        g <= (others => '0');
        b <= (others => '0');
    end if;

end process;
end arch;
4

2 に答える 2

2

テレビが補助入力を備えているのと同じように、モニターは出力に同期していて、単にビデオを全画面表示していると思います。

報告された 27 MHz (~ 37 ns) に基づいて H レートと V レートを計算し、それらを受け入れる 1280 x 1024 LCD モニターを見つけられるかどうかを確認しました。

水平カウンターは 0 からnumber_pixelsMAX_H - 1(799) までカウントする counter2 で、垂直カウンターは 0 からnumber_pixelsMAX_V - 1(524) までカウントする counter3 です。

これにより、水平レートは 800 x 37 ns = 29.600 us、垂直レートは 15.54 ms になります。33.8KHz 水平、垂直 64Hz。

使用している特定のモニターを知らずに、仕様を調べたところ、同期レート範囲を定義するSXGA AMOLED ディスプレイ仕様が見つかりました。

14 ページに、H と V の範囲を示す表があります。

表 6-4 AC 特性

この特定の LCD パネルがフレーム レートを表示できることを示しています。ピクセル クロックが同期信号からどのように回復されるかは、この特定のディスプレイを使用するモニターのビルドによって異なります。

DE1ボードのすべてのバージョンは、同じ ADV7123 を使用して、SVGA 信号を 15 ピン VGA コネクタ経由で送信されるアナログに変換するようです。

SVGAを表示できるSXGAレートモニターの可能性が高いと思います。

Acer 17 インチ V173L は、たとえば 3 つの VGA モード (60 Hz、72 Hz、および 75 Hz) と 640 x 480 (66 Hz) の Mac モードと同期するようです。

最近のモニターでは、複数のスキャン レートに同期する機能が非常に一般的です。

私の 6 年前の Dell 2208WP は、60 Hz で 1680x1050 の DVI-D 信号を入力していると言っています。私は自分の Mac に解像度を切り替えるように指示することができ、DVI インターフェースによって伝えられるプリセットに忠実に従います。

モニターによっては、アナログ入力 (DE1 が提供) を使用して、より広い範囲でマルチ同期を取得する必要があります。

アナログ ビデオ入力を機能させるメカニズムは、LCD パネルへのピクセル クロックが水平ラインの非空白部分に関連しており、パネルの解像度に一致する間隔で多数のピクセル クロックを提供し、再変換します。画面のすべての (またはほぼすべての) ピクセルを満たす速度でアナログ ビデオをデジタルに変換します。

于 2014-10-15T22:32:12.210 に答える
1

VGA の理論と VGA コントローラーの VHDL コードの詳細については、VA Pedroni 著「Circuit Design and Simulation with VHDL」、第 2 版 (第 2 版のみ)、2010 年の第 15 章を参照してください。

于 2014-10-16T17:22:17.030 に答える