2014-10-15 2 views
7

Я пытаюсь изучить VHDL-программирование с помощью некоторых книг и комплекта разработчика Altera DE1 от Terasic.VGA-контроллер с VHDL

Проблема в том, что я пытаюсь запрограммировать VGA-контроллер для работы с разрешением 640x480 (хотя мой экран - TFT-дисплей с разрешением 1280x1024).

У меня возникли проблемы с кодом.

Я использую FSM для создания вертикальных и горизонтальных сигналов, еще один блок для управления входами RGB, а также часы 27 МГц от DE1.

Я думаю, что с кодом должно быть что-то неправильно, потому что изображение, которое я печатаю на экране, не соответствует размеру (640x480), но больше (приблизительно 1174x980).

К настоящему моменту я пытаюсь поместить только один цвет на экране, чтобы упростить его, пока не обнаружу ошибку.

Мой проект имеет 3 файла, 1 для блока RGB, 1 для FSM и еще один экземпляр для обоих из них.

Я был бы признателен за помощь в решении этой проблемы, потому что я попытался понять это, но я не вижу, где ошибки.

Большое спасибо!

Омар

файл 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; 

ВГД дисплей файл

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; 
+1

Вы уверены, что это не ваш монитор, масштабирующий вход 640x480 до 1280x960 (т. Е. 2x2 пикселя), чтобы заполнить панель? – NPE

+0

Одной из больших проблем с 2-процессорным автоматом является сложность получения списка чувствительности. Я не смотрел ваш код подробно (я не делаю 2-процессорных SM), но выглядит неправильно в 'list_state_ *' в списке чувствительности, а затем проверять 'present_state_ *' в выражении case. Могут быть и другие проблемы с списком чувствительности. –

+1

В двух процессах, представляющих список чувствительности Брайана, относятся 'upper_part_1' и' upper_part_2'. Я не верю, что это проблема синтеза, списки чувствительности, как правило, игнорируются. Вы должны исправить их все равно. – user1155120

ответ

0

Подробнее о теории VGA и коде VHDL для VGA-контроллеров в главе 15 «Проектирование и моделирование схем с VHDL», 2-е издание (только во 2-м издании), 2010 г., В. А. Педрони.

+0

Существует также прототипирование FPGA Pong Chu по VHDL-примерам: версия Xilinx Spartan-3] (http://academic.csuohio.edu/chu_p/rtl/fpga_vhdl.html), где примеры VGA-контроллера главы 12 можно найти в [ код zip-файла] (http://academic.csuohio.edu/chu_p/rtl/fpga_vhdl_book/fpga_vhdl_src.zip), написанный в аналогичном стиле для участников опроса. См. Также 3.6.6 VGA на плате [DE1] (http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English & КатегорияNo = 165 & No = 836 & PartNo = 4) и найдите VGA в теге VHDL на Stack Exchange. – user1155120

+0

Спасибо за ответ! Я, наконец, смог это исправить, поэтому теперь я контролирую экран 1280x1024 при 60 Гц :) Книга Понга Чу была очень полезной. – osuarez

2

Я думаю, что ваш монитор синхронизироваться с выходом и просто дисплей во весь экран видео, так же, как ваш телевизор может со вспомогательным входом.

Я разработал ваши тарифы H и V с точки зрения ваших зарегистрированных 27 МГц (~ 37 нс) и посмотрю, смогу ли я найти ЖК-монитор 1280 x 1024, который бы их принял.

Ваш горизонтальный счетчик - счетчик2, который отсчитывает от 0 до number_pixelsMAX_H - 1 (799), а ваш вертикальный счетчик - счетчик3, который составляет от 0 до number_pixelsMAX_V - 1 (524).

Это дает вам горизонтальную скорость 800 x 37 ns = 29,600 us и вертикальную скорость 15,54 мс. 33,8 кГц H, В 64 Гц.

Не зная конкретного монитора, который вы используете, я огляделся по любой спецификации для одного и нашел спецификацию AMOLED , которая определяет диапазон скоростей синхронизации.

На странице 14 есть таблица, показывающая H и V диапазонов:

Table 6-4 AC Characteristics

Это показывает, что этот конкретный ЖК-панель может отображать частоту кадров. Как часы пикселов для него будут восстановлены из сигналов синхронизации, зависит от сборки монитора с использованием этого конкретного дисплея.

Все версии платы DE1, похоже, используют тот же ADV7123, чтобы преобразовать SVGA-сигнал в аналоговый, передаваемый через 15-контактный разъем VGA.

Я думаю, что это очень вероятно, ваш монитор скорости SXGA способен отображать SVGA.

Похоже, что 17-дюймовый V173L Acer синхронизируется с ним, например, имеет 3 режима VGA (60 Гц, 72 Гц и 75 Гц) и режим Mac для 640 x 480 (66 Гц).

Возможность синхронизации с несколькими частотами сканирования очень часто встречается в мониторах в эти дни.

Мой шестилетний Dell 2208WP говорит мне, что я вводил DVI-D сигнал 1680x1050 при 60 Гц. Я могу сказать, что мой Mac переключит разрешение и будет верно следовать, придерживаясь пресетов, передаваемых интерфейсом DVI, в этом случае ограничено 1024x640 (что изменило размеры всех моих открытых окон, сглаживая их).

В зависимости от вашего монитора вы должны получать многосинхронизацию в широком диапазоне с аналоговым входом (который предоставляет DE1).

Механизм, который заставляет его работать для аналогового видеовхода, - это то, что пиксельные часы на ЖК-панели связаны с незаполненной частью горизонтальной линии, обеспечивая при этом количество пиксельных часов в течение этого интервала, который соответствует разрешению панели , преобразование аналогового видео в цифровое со скоростью, которая заполняет все (или почти все) пиксели экрана.