2012-04-03 5 views
5

Ho scritto codice VHDL per controller VGA per scheda spartan 3E. Il codice simula e funziona bene senza il processo di reset e clk nel codice sottostante. Ma dopo aver inserito il processo (reset, clk) i contatori h_count e v_count smettono di contare e vengono guidati su XXXXX indefiniti nella simulazione. Dove sto andando storto. Il codice funziona perfettamente senza il clk, processo di reset (quello commentato in grassetto), ho anche testato il codice sul harware.VHDL: Come utilizzare CLK e RESET in elaborazione

Il codice per controller VGA

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

Per favore potresti riformattare il tuo codice in modo che non abbia ricevuto un altro balnk di linea? E metti i trattini nel modo in cui dovrebbe essere! –

risposta

10

Si dovrebbe guidare solo un segnale da un processo. Basta inserire la funzionalità di ripristino nei processi contatore e dovrebbe funzionare. Per esempio:

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; 

Poche altre note:

Come potete vedere, ho usato un reset sincrono in questo frammento di codice. A meno che non sia assolutamente necessario il ripristino asincrono, utilizzare invece le reimpostazioni sincrone. Aiuta il sintetizzatore, dato che ci sono alcuni costrutti speciali che non sono disponibili usando le reimpostazioni asincrone, e aiuta a prevenire i problemi quando il disegno diventa grande (e le flip-flop iniziano improvvisamente a essere resettate in momenti diversi a causa della mancanza di segnale).

Inoltre, non controllare nulla tranne bordi (o reset) nell'istruzione if iniziale di un processo con clock. Per il vostro contatore verticale si dispone di un assegno di h_count = 799. Procedere come segue invece:

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

E 'molto più chiaro, e non come soggetto a errori.

Come ultima cosa, ho modificato il clk'event and clk=1 nel modo più moderno di farlo, rising_edge(clk). Non dovrebbe fare molta differenza (a meno che non ci siano particolari problemi di simulazione), ma lo rising_edge ha alcuni controlli extra integrati per assicurarti di avere effettivamente un vantaggio.

+0

La maggior parte dei libri VHDL spiega solo le regole di sintassi :(. Esistono libri VHDL solidi che affrontano questo tipo di problemi pratici? Potete suggerirne uno? – Sumanth

+0

Ho usato "RTL Hardware design using VHDL" di Pong P. Chu previousl :, http://www.amazon.com/RTL-Hardware-Design-Using-VHDL/dp/0471720925 Inoltre, Xilinx ha una grande quantità di white paper, che descrivono vari aspetti dell'uso FPGA. qui: http://www.xilinx.com/support/documentation/white_papers.htm – sonicwave

+0

Grazie bhai! (fratello in Hindi (India)) – Sumanth

0

Non è possibile avere più driver per un segnale. Se non si dispone del processo (clk, reset), i segnali hcount e vcount sono gestiti ciascuno da un solo processo. Ma quando aggiungi il processo (clk, reset) ha driver simultanei.

+0

La maggior parte dei libri VHDL spiega solo le regole di sintassi :(. Esistono libri VHDL solidi che affrontano questo tipo di problemi pratici? Puoi suggerirne uno? – Sumanth

+1

Sì, puoi _can_ avere più driver per un segnale (se il tipo di dati è stato risolto ; questo può essere usato per modellare i bus a tre stati), ma, di solito, non dovresti avere più driver, perché non stai provando a modellare un bus a tre stati. – Philippe

+0

@Philippe: hai ragione che i segnali tristate possono avere più di un driver, ma questo non è rilevante per il problema dell'OP. Il problema nel suo codice è che due driver pilotano lo stesso segnale (non tristato) - quindi il simulatore lo metterà in "X". – bmk