2014-10-15 11 views
7

Tôi đang cố gắng học lập trình VHDL với một số sách và bộ phát triển Altera DE1 từ Terasic.Bộ điều khiển VGA với VHDL

Vấn đề ở đây là tôi đang cố gắng lập trình bộ điều khiển VGA để làm việc với độ phân giải 640x480 (mặc dù màn hình của tôi là màn hình LCD TFT có 1280x1024).

Tôi gặp một số sự cố với mã.

Tôi đang sử dụng FSM để tạo tín hiệu dọc và ngang, một khối khác để điều khiển đầu vào RGB và đồng hồ 27 MHz từ DE1.

Tôi nghĩ rằng phải có điều gì đó sai với mã vì hình ảnh tôi in trên màn hình không đúng kích thước (640x480) nhưng lớn hơn (khoảng 1174x980).

Hiện tại, tôi đang cố gắng đặt một màu duy nhất trên màn hình để đơn giản hóa màu cho đến khi tôi có thể phát hiện ra lỗi.

Dự án của tôi có 3 tệp, 1 cho khối RGB, 1 cho FSM và một tệp khác để khởi tạo cả hai tệp.

Tôi sẽ đánh giá cao một số loại trợ giúp để giải quyết vấn đề này bởi vì tôi đã cố gắng hết sức để tìm ra nhưng tôi không thể nhìn thấy đâu là những sai lầm.

Cảm ơn rất nhiều!

Omar

tập tin điều khiển 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; 

tập tin FSM sync

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 tập tin hiển thị

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

Bạn có chắc chắn màn hình của bạn không thu nhỏ kích thước 640x480 đến 1280x960 (tức là 2x2 pixel) để lấp đầy bảng điều khiển không? – NPE

+0

Một trong những vấn đề lớn với máy xử lý 2 trạng thái là khó khăn trong việc lấy danh sách độ nhạy chính xác. Tôi đã không xem xét mã của bạn một cách chi tiết (tôi không làm 2 quy trình SM) nhưng có vẻ sai khi đặt 'next_state_ *' trong danh sách độ nhạy và sau đó kiểm tra 'present_state_ *' trong trường hợp câu lệnh. Cũng có thể có các vấn đề về danh sách nhạy cảm khác. –

+1

Hai quy trình thể hiện mối quan tâm của danh sách độ nhạy của Brian là 'upper_part_1'and' upper_part_2'. Tôi không tin rằng họ là một vấn đề tổng hợp, danh sách nhạy cảm có xu hướng bị bỏ qua. Bạn nên sửa chữa tất cả như nhau. – user1155120

Trả lời

0

Xem chi tiết đầy đủ về lý thuyết VGA và mã VHDL cho bộ điều khiển VGA trong chương 15 của "Thiết kế vi mạch và mô phỏng với VHDL", ấn bản thứ 2 (chỉ trong ấn bản thứ 2), 2010, của V. A. Pedroni.

+0

Ngoài ra, cũng có thể tìm thấy các ví dụ về bộ điều khiển VGA của Chương 12 trong [Các ví dụ về VHDL của FPGA Chu]: Ví dụ: Xilinx Spartan-3 Version (http://academic.csuohio.edu/chu_p/rtl/fpga_vhdl.html) tệp zip danh sách mã] (http://academic.csuohio.edu/chu_p/rtl/fpga_vhdl_book/fpga_vhdl_src.zip), được viết theo kiểu tương tự cho người hỏi. Xem thêm 3.6.6 VGA trong [DE1 board] (http://www.terasic.com.tw/cgi-bin/page/archive.pl?Language=English & CategoryNo = 165 & No = 836 & PartNo = 4) hướng dẫn sử dụng và tìm kiếm VGA trong thẻ VHDL trên Stack Exchange. – user1155120

+0

Cảm ơn bạn đã trả lời !! Cuối cùng tôi có thể sửa chữa nó vì vậy bây giờ tôi đang kiểm soát một màn hình 1280x1024 tại 60Hz :) Cuốn sách của Pong Chu rất hữu ích. – osuarez

2

Tôi nghĩ rằng màn hình của bạn được đồng bộ với đầu ra của bạn và đơn giản trưng bày nhập toàn màn hình video, nhiều như TV của bạn có thể có đầu vào phụ.

Tôi đã tính ra giá H và V của bạn theo báo cáo 27 MHz (~ 37 ns) và xem liệu tôi có thể tìm thấy màn hình LCD 1280 x 1024 chấp nhận chúng hay không.

truy cập ngang của bạn là counter2 mà đếm 0-number_pixelsMAX_H - 1 (799), và truy cập thẳng đứng của bạn là counter3 mà đếm 0-number_pixelsMAX_V - 1 (524).

Điều đó mang lại cho bạn tốc độ ngang là 800 x 37 ns = 29.600 chúng tôi và tốc độ dọc là 15,54 ms. 33,8 KHz H, V 64 Hz.

Không biết màn hình cụ thể bạn đang sử dụng, tôi đã xem xét bất kỳ thông số kỹ thuật nào và tìm thông số hiển thị SXGA AMOLED xác định phạm vi tỷ lệ đồng bộ hóa.

Trên trang 14 có một bảng hiển thị H và V dao động:

Table 6-4 AC Characteristics

Nó cho thấy rằng màn hình LCD đặc biệt này có thể hiển thị tốc độ khung hình. Cách đồng hồ điểm ảnh cho nó sẽ được phục hồi từ các tín hiệu đồng bộ phụ thuộc vào việc xây dựng màn hình bằng cách sử dụng màn hình cụ thể này.

Tất cả các phiên bản của bảng DE1 xuất hiện để sử dụng cùng một ADV7123 để chuyển đổi tín hiệu SVGA sang tín hiệu tương tự được truyền qua đầu nối VGA 15 pin.

Tôi nghĩ rằng rất có khả năng màn hình tỷ lệ SXGA của bạn có khả năng hiển thị SVGA.

Dường như một chiếc 17 inch V173L của Acer sẽ đồng bộ với nó, ví dụ có 3 chế độ VGA (60 Hz, 72 Hz và 75 Hz) và chế độ Mac với độ phân giải 640 x 480 (66 Hz).

Khả năng đồng bộ hóa với nhiều tốc độ quét rất phổ biến trong màn hình những ngày này.

Máy tính Dell 2208WP sáu tuổi của tôi cho tôi biết tôi đang nhập tín hiệu DVI-D 1680x1050 ở 60 Hz. Tôi có thể yêu cầu máy Mac của tôi chuyển đổi độ phân giải và tuân theo các cài đặt trước được chuyển tải bởi giao diện DVI, trong trường hợp này giới hạn ở 1024x640 (đã thay đổi kích thước tất cả cửa sổ đang mở của tôi, làm phẳng chúng).

Tùy thuộc vào màn hình của bạn, bạn sẽ nhận được đa đồng bộ hóa trên phạm vi rộng hơn với đầu vào tương tự (mà DE1 cung cấp).

Cơ chế làm cho đầu vào video tương tự là đồng hồ điểm ảnh trên màn hình LCD có liên quan đến phần không được làm tròn của đường ngang, cung cấp một số đồng hồ pixel trong khoảng thời gian đó phù hợp với độ phân giải của bảng điều khiển , chuyển đổi lại video analog thành kỹ thuật số với tốc độ lấp đầy tất cả (hoặc gần như tất cả) pixel màn hình.

Các vấn đề liên quan