2012-04-03 14 views
5

Spartan 3E kartı için VGA denetleyicisi için VHDL kodu yazdım. Kod, aşağıdaki kodda sıfırlama ve clk işlemi olmaksızın iyi çalışır ve çalışır. Ancak işlemi (reset, clk) ekledikten sonra h_count ve v_count sayaçlarının sayımını durdurur ve simülasyonda undefined olan XXXXX'e sürülür. Nerede yanlış gidiyorum. Kod, clk olmadan mükemmel bir şekilde çalışır, sıfırlama işlemi (kalın olarak yorumlanmıştır), ayrıca koddaki yazılımları da test ettim.VHDL: CLK ve RESET işlemi nasıl kullanılır?

VGA Denetleyicisi

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.NUMERIC_STD.ALL; 

entity vga_controller is 
    port(clk   : inout std_logic; 
     clk_50  : in std_logic; 
     hsync, vsync : out std_logic; 
     video_on  : out std_logic; 
     x_pos, y_pos : out std_logic_vector(9 downto 0); 
     sw   : in std_logic_vector(2 downto 0) := "100"; 
     rgb   : out std_logic_vector(2 downto 0) 
    ); 

end vga_controller; 

architecture Behavioral of vga_controller is 
    signal h_count, v_count : unsigned(9 downto 0) := (others => '0'); 

begin 
    -- Frequency divider to get 25 MHz clk from 50 MHz clock of Spartan 3E ** 
    freq_dividr : entity work.t_ff port map(clk_50, clk); 
    -- If i remove this process everyting works fine. Why ????** 
    process(clk, reset) 
    begin 
     if reset = '1' then 
      h_count <= (others => '0'); 
      v_count <= (others => '0'); 
      video_on <= '0'; 
     elsif clk'event and clk = '1' then 
      h_count <= h_count; 
      v_count <= v_count; 
     end if; 
    end process; 

    process(clk)      -- Process for horizontal counter 
    begin 
     if clk'event and clk = '1' then 
      if h_count = 799 then 
       h_count <= (others => '0'); 
      else 
       h_count <= h_count + 1; 
      end if; 
     end if; 
    end process; 

    process(clk)      -- Process for vertical counter 
    begin 
     if clk'event and clk = '1' and h_count = 799 then 
      if v_count = 524 and h_count = 799 then 
       v_count <= (others => '0'); 
      else 
       v_count <= v_count + 1; 
      end if; 
     end if; 
    end process; 

    hsync <= '0' when (h_count >= 656 and h_count <= 751) else '1'; 
    vsync <= '0' when (v_count >= 490 and v_count <= 491) else '1'; 
    video_on <= '1' when (h_count <= 649 and v_count <= 479) else '0'; 
    rgb <= sw when (h_count <= 649 and v_count <= 479) else "000"; 

    x_pos <= std_logic_vector(h_count); 
    y_pos <= std_logic_vector(v_count); 

end Behavioral; 
+1

Lütfen kodunuzu yeniden biçimlendirebilir misiniz, bu yüzden diğer tüm satırları alamadı mı? Ve girintileri olması gerektiği şekilde yerleştirin! –

cevap

10

için kod Yalnızca bir süreç bir sinyal kullanmalıyım. Sadece sıfırlama işlevinizi karşı işlemlere sokun ve işe yaramalı.

process(clk) -- Process for horizontal counter 
begin 
    if(rising_edge(clk)) then 
    if(rst = '1') then 
     h_count <= 0; 
    else 
     if h_count = 799 then 
     h_count <= (others => '0'); 
     else 
     h_count <= h_count + 1; 
     end if; 
    end if; 
    end if; 
end process; 

Birkaç diğer notlar: Örneğin

Gördüğünüz gibi, yukarıdaki pasajına bir senkron sıfırlama kullandım. Asenkronize olmayan sıfırlamaya kesinlikle ihtiyacınız olmadıkça, bunun yerine senkronize sıfırları kullanın. Asenkronize sıfırlar kullanılmayan bazı özel yapılar olduğu için sentezleyiciye yardımcı olur ve tasarımınız büyüdüğünde sorunların önlenmesine yardımcı olur (ve flip-floplar aniden sinyal çarpmasından dolayı farklı zamanlarda sıfırlanmaya başlar). Ayrıca, bir saat işleminin ilk if deyiminde kenarlardan (veya sıfırdan) bir şey olup olmadığına bakmayın.

process(clk) 
begin 
    if(rising_edge(clk)) then 
    if(h_count = 799) then 
    (...) 

Çok daha net ve hatalar kadar yatkın değil: dikey sayaç için, = 799. yerine aşağıdaki Do h_count bir çek var.

Son olarak, clk'event and clk=1 değerini daha modern bir şekilde değiştirdim, rising_edge(clk). Çok fazla fark yaratmamalı (simulasyonda belirli önlemler altında değilse), ancak rising_edge'un aslında bir kenara sahip olduğunuzdan emin olmak için birkaç ekstra kontrolü vardır.

+0

VHDL kitaplarının çoğu sadece sözdizimi kurallarını açıklar :(Bu tür pratik sorunlara hitap eden herhangi bir katı VHDL kitabı var mı? Lütfen bir öneride bulunabilir misiniz? – Sumanth

+0

Pong P. Chu tarafından "VHDL kullanarak RTL Donanım tasarımı" kullandım previousl :, http://www.amazon.com/RTL-Hardware-Design-Using-VHDL/dp/0471720925 Ayrıca Xilinx, FPGA kullanımının çeşitli yönlerini tanımlayan büyük miktarda Whitepapers'a sahiptir. Burada: http://www.xilinx.com/support/documentation/white_papers.htm – sonicwave

+0

Teşekkürler bhai! (Hindi (Hindistan) 'da broker) – Sumanth

0

Tek bir sinyal için birden fazla sürücünüz olamaz. (clk, reset) işleminiz yoksa, hcount ve vcount sinyallerinin her biri yalnızca bir işlem tarafından yürütülür. Ancak, (clk, reset) işlemini eklediğinizde, eşzamanlı sürücülere sahip olur.

+0

VHDL kitaplarının çoğu yalnızca sözdizimi kurallarını açıklar :(Bu tür pratik sorunlara hitap eden herhangi bir katı VHDL kitabı var mı? Bir öneride bulunabilir misiniz? – Sumanth

+1

Evet, siz _can_ bir sinyal için birkaç sürücünüz var (veri türü çözülmüşse) Bu durum üç-durumlu otobüsleri modellemek için kullanılabilir. Fakat genellikle, birden fazla sürücüye sahip olamazsınız, çünkü üç-durumlu bir veriyolunu modellemeye çalışmıyorsunuz. – Philippe

+0

@Philippe Birden fazla sürücü var ama bu OP'nin problemi ile alakalı değil: Onun kodundaki problem, iki sürücünün aynı (gergin olmayan) sinyali sürmesidir - bu yüzden simülatör onu 'X' 'e koyar. – bmk

İlgili konular