2016-02-06 5 views
-1

Я моделировал интерфейс VGA на плате DE0. У меня есть следующая модель для 640х480 дисплей, который обновляет на 60Hz:VGA-интерфейс VHDL

Основная модель:

LIBRARY IEEE; 
USE IEEE.std_logic_1164.ALL; 
USE IEEE.numeric_std.ALL; 

ENTITY VGA is 
    PORT (clk      : IN std_logic; -- demo had 2 bit vector 
     vga_hs, vga_vs   : OUT std_logic; 
     vga_r, vga_g, vga_b : OUT std_logic_vector(3 DOWNTO 0)); 
END ENTITY VGA; 

ARCHITECTURE A1 OF VGA IS 
    SIGNAL rst, clk25 : std_logic; -- rst only resets pixel clock 
BEGIN 
    SYNC1 : ENTITY work.sync(A1) 
      PORT MAP (clk25, vga_hs, vga_vs, vga_r, vga_g, vga_b); 
    CLK_25 : ENTITY work.PLL(rtl) 
      PORT MAP (clk, rst, clk25); 
END ARCHITECTURE A1; 

Синхронизировать модель:

LIBRARY IEEE; 
USE IEEE.std_logic_1164.ALL; 
USE IEEE.numeric_std.ALL; 

ENTITY SYNC IS 
PORT(
    clk    : IN std_logic; 
    h_sync, v_sync  : OUT  std_logic; 
    r, g, b   : OUT std_logic_vector(3 DOWNTO 0) 
    ); 
END ENTITY SYNC; 

ARCHITECTURE A1 OF SYNC IS 
    SIGNAL h_pos: integer RANGE 0 TO 800:=0; 
    SIGNAL v_pos : integer RANGE 0 TO 520:=0; 
BEGIN 
    TIMING :PROCESS(clk) IS 
BEGIN 
    IF rising_edge(clk) THEN 
     IF (h_pos = 480 or v_pos = 280) THEN -- middle of the screen is pic res/2 + (FP + sync + BP) 
      r <= (OTHERS => '1'); 
      g <= (OTHERS => '1'); 
      b <= (OTHERS => '1'); 
     ELSE 
      r <= (OTHERS => '0'); 
      g <= (OTHERS => '0'); 
      b <= (OTHERS => '0'); 
     END IF; 

     IF (h_pos < 800) THEN 
      h_pos <= h_pos + 1; 
      ELSE 
       h_pos <= 1; 
      IF (v_pos < 520) THEN 
       v_pos <= v_pos + 1; 
       ELSE 
       v_pos <= 1; 
      END IF; 
     END IF; 


    IF (h_pos > 16 and h_pos < 112) THEN -- H_POS between end of FP and the end of H_SYNC 
     h_sync <= '0'; -- H_SYNC needs to stay low during display 
    ELSE 
     h_sync <= '1'; 
    END IF; 

    IF (v_pos > 8 and v_pos < 10) THEN --V_POS between end of FP and the end of V_SYNC 
     v_sync <= '0'; -- V_SYNC needs to stay low during display 
    ELSE 
     v_sync <= '1'; 
    END IF; 

    IF ((h_pos > 0 and h_pos < 160) or (v_pos > 0 and v_pos < 40)) THEN--During all of SYNC i.e FP + SYNC + BP colour signals stay low 
     r <= (OTHERS => '0'); 
     g <= (OTHERS => '0'); 
     b <= (OTHERS => '0'); 
    END IF; 
    END IF; 
END PROCESS TIMING; 
END ARCHITECTURE A1; 
----------Amendments made to model 09/02 13:42---------- 

Другой прямой Инстанциация для PLL генерируется из Quartus II так ли кажется, хорошо работает .. спасибо г-н Zilmer :). Модель отлично компилируется. Я загружаю его в DE0. Затем подключите его к монитору и ничего не получите на дисплее. Он должен отображать крест в центре экрана. Дисплей, который я использую, - это Samsung с разрешением 1920x1080. Это остановит мою модель от отображения чего-нибудь? Или я допустил явную ошибку в своей модели. Я изменил некоторые стандартные временные значения, чтобы соответствовать обновлению на 60 Гц с 25Mz clk. Спасибо D

+0

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

+0

Привет, Martin, я обновил модель с несколькими изменениями целых значений для h_pos и v_pos. Это видно из модели. Кроме того, и самое главное изменение в выражении IF (я никогда не знал, что вы можете вложить инструкцию IF, добавляющую инструкцию ELSE!) Ну, модель компилируется, и на этот раз я получаю свой samsung 1920x1080, чтобы сказать мне, что это не оптимальный режим! ... Когда я пытаюсь моделировать модель в ModSim, опция имитации моего VGA-файла не является тем, что там есть файл, но значок расширения отсутствует. Надеюсь, это имеет смысл, и спасибо за ответ. – hoboBob

+0

. Пожалуйста, проверьте данные вашего монитора, чтобы проверить, поддерживается ли ваш видеорежим. –

ответ

4

Ваш код VHDL для синхронизации сущности не анализирует. Вы пропускаете end if и ваши начальные значения для h_sync и v_sync нарушают ограничение подтипа:

signal h_pos: integer range 1 to 800 := 0; 
    signal v_pos: integer range 1 to 520 := 0; 

Где 0 находится за пределами 1 to 800 или 1 to 520.

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

Мы можем использовать испытательный стенд для демонстрации того, что синхронизация делает при моделировании с тактовой 25 МГц:

library ieee; 
use ieee.std_logic_1164.all; 
--use ieee.numeric_std.all; 

entity sync is 
    port (
     clk:    in std_logic; 
     h_sync, v_sync: out std_logic; 
     r, g, b:   out std_logic_vector(3 downto 0) 
    ); 
end entity sync; 

architecture a1 of sync is 
    signal h_pos: integer range 1 to 800 := 1; -- was := 0; 
    signal v_pos: integer range 1 to 520 := 1; -- was := 0; 
begin 
timing: 
    process (clk) is 
     begin 
     if rising_edge(clk) then 
      if h_pos = 480 or v_pos = 280 then -- middle of the screen 
       r <= (others => '1'); 
       g <= (others => '1'); 
       b <= (others => '1'); 
      else 
       r <= (others => '0'); 
       g <= (others => '0'); 
       b <= (others => '0'); 
      end if; 

      if h_pos < 800 then 
       h_pos <= h_pos + 1; 
       else 
        h_pos <= 1; 
       if v_pos < 520 then 
        v_pos <= v_pos + 1; 
        else 
        v_pos <= 1; 
       end if; 
       if h_pos > 16 and h_pos < 112 then 
        h_sync <= '0'; -- h_sync low during display 
       else 
        h_sync <= '1'; 
       end if; 

       if v_pos > 8 and v_pos < 10 then 
        v_sync <= '0'; -- v_sync low during display 
       else 
        v_sync <= '1'; 
       end if; 

       if (h_pos > 1 and h_pos < 160) or 
        (v_pos > 1 and v_pos < 40) then -- black during blanking 
        r <= (others => '0'); 
        g <= (others => '0'); 
        b <= (others => '0'); 
       end if; 
      end if; 
     end if; -- added misssing end if 
    end process timing; 
end architecture a1; 

library ieee; 
use ieee.std_logic_1164.all; 

entity sync_tb is 
end entity; 

architecture foo of sync_tb is 
    signal clk:  std_logic := '0'; 
    signal h_sync: std_logic; 
    signal v_sync: std_logic; 
    signal r, g, b: std_logic_vector (3 downto 0); 
begin 
DUT: 
    entity work.sync 
     port map (
      clk => clk, 
      h_sync => h_sync, 
      v_sync => v_sync, 
      r => r, 
      g => g, 
      b => b 
     ); 
CLOCK: 
    process 
    begin 
     wait for 20 ns; -- clock period 25 MHz = 40 ns; 
     clk <= not clk; 
     if now > 20 ms then -- one frame time plus a bit 
      wait; 
     end if; 
    end process; 
end architecture; 

И теперь мы получаем для устранения:

sync_tb_1.png

Первое, что мы замечаем h_sync неверен. Также обратите внимание, что v_sync составляет около 16,667 мс (1/60 секунды).

Мы можем добавить счетчики h_pos и v_pos, чтобы мы могли посмотреть h_sync, мы знаем, что счетчик h_pos работает, чтобы получить v_sync, который мы можем увидеть в правой окрестности 60 Гц.

Поэтому я выбрал не то место, чтобы добавить end if. Исправление, которое также отделяет работу счетчиков от работы на их выходах (h_sync, v_sync и r, g, b).

timing: 
    process (clk) is 
     begin 
     if rising_edge(clk) then 
      if h_pos = 480 or v_pos = 280 then -- middle of the screen 
       r <= (others => '1'); 
       g <= (others => '1'); 
       b <= (others => '1'); 
      else 
       r <= (others => '0'); 
       g <= (others => '0'); 
       b <= (others => '0'); 
      end if; 

      if h_pos < 800 then 
       h_pos <= h_pos + 1; 
      else 
       h_pos <= 1; 
       if v_pos < 520 then 
        v_pos <= v_pos + 1; 
       else 
        v_pos <= 1; 
       end if; 
      end if; -- separate the counters for what they produce 
      -- HSYNC 
      if h_pos > 16 and h_pos < 112 then 
       h_sync <= '0'; -- h_sync low during display 
      else 
       h_sync <= '1'; 
      end if; 
      -- VSYNC 
      if v_pos > 8 and v_pos < 10 then 
       v_sync <= '0'; -- v_sync low during display 
      else 
       v_sync <= '1'; 
      end if; 
      -- BLANKING 
      if (h_pos > 1 and h_pos < 160) or 
       (v_pos > 1 and v_pos < 40) then 
       r <= (others => '0'); 
       g <= (others => '0'); 
       b <= (others => '0'); 
      end if; 
     end if; 
    end process timing; 

Мы h_sync Сейчас:

sync_tb_2.png

Заметьте, что мы можем видеть вертикальный интервал гашения и сейчас.

Изменение масштаба мы можем видеть, что есть горизонтальную белую линию на v_pos 280:

sync_tb_3.png

Наряду с вертикальной линией на h_pos 480 (+1):

sync_tb_4.png

И похоже, что это может сработать.

Единственное изменение в дизайне, которое я мог бы искусить, - это запустить видимую часть строки в h_pos = 0 и видимую часть кадра при v_pos = 0. Это позволит что-то еще адресовать пиксели для запись в буфер кадра без добавления дополнительных счетчиков пикселей или выполнение смещения арифметики. (Пиксельная адресация обычно начинается с 0 для оси x и y).

+0

Привет, Спасибо, что указали, где я сделал ошибки в коде. Я обновил их по оригинальному вопросу. – hoboBob

+0

Вопрос не нуждался в обновлении, чтобы исправить код. Если вы обновите код в своем вопросе, ошибка уже не может быть легко распознана, что делает вопрос и ответ менее полезным в качестве ресурса для других пользователей stackoverflow. – user1155120