VHDL: как использовать CLK и RESET в процессе - PullRequest
5 голосов
/ 03 апреля 2012

Я написал код VHDL для контроллера VGA для спартанской платы 3E.Код имитирует и работает хорошо без сброса и процесса clk в приведенном ниже коде.Но после вставки процесса (reset, clk) счетчики h_count и v_count перестают считать и приводятся к XXXXX, неопределенному в симуляции.Куда я иду не так?Код отлично работает без clk, процесс сброса (тот, что выделен жирным шрифтом), я также протестировал код на аппаратном обеспечении.

Код для VGA Controller

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;

Ответы [ 2 ]

10 голосов
/ 03 апреля 2012

Вы должны управлять сигналом только одного процесса. Просто поместите свою функцию сброса в счетчик процессов, и она должна работать. Например:

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;

Несколько других заметок:

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

Кроме того, не проверяйте ничего, кроме ребер (или сброса) в исходном операторе if синхронизированного процесса. Для вашего вертикального счетчика у вас есть чек для h_count = 799. Вместо этого выполните следующее:

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

Это намного понятнее и не так подвержено ошибкам.

Наконец, я изменил clk'event and clk=1 на более современный способ, rising_edge(clk). Это не должно иметь большого значения (если только не при определенных условиях в симуляции), но rising_edge имеет несколько дополнительных встроенных проверок, чтобы убедиться, что у вас действительно есть преимущество.

0 голосов
/ 03 апреля 2012

Вы не можете иметь несколько драйверов для одного сигнала.Если у вас нет процесса (clk, reset), то сигналы hcount и vcount управляются только одним процессом.Но когда вы добавляете процесс (clk, reset), он имеет одновременные драйверы.

...