VHDL: Как я могу задержать сигналы VGA?

Я использую Basys3 FPGA и у меня есть генератор тестовых шаблонов, который отображает набор изображений на мониторе. Проблема в том, что каждое изображение "сбито", что означает, что первый пиксель в каждой горизонтальной строке - это пиксель из предыдущей строки. Например, если бы у меня был черно-белый экран с верхней половиной белого и нижней половиной черного, первый пиксель в первой черной линии был бы белым. По сути, похоже, что весь первый вертикальный столбец смещен вниз на один пиксель.

Из того, что мне сказал мой профессор, проблема вызвана тем фактом, что сигналы (h_sync, v_sync, RGB) не синхронизированы, h_sync и v_sync опережают на 1 бит из-за задержки сигналов RGB, когда Я делаю выбор изображений. Под выбором я подразумеваю, что у меня есть 4 активных переключателя, которые (в зависимости от их состояния ВКЛ / ВЫКЛ) выбирают изображения "двоичным способом". (пример: 4 переключателя находятся в состоянии 0101, затем отображается 5-е изображение. Состояние 0011, отображается 3-е изображение и т. д.)

Это код для выбора:

type Colors is array (0 to 15) of STD_LOGIC_VECTOR (7 downto 0);
signal redArr   : Colors;
signal greenArr : Colors;
signal blueArr  : Colors;

process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
    if flagAV = '1' then
        RED <= redArr (conv_integer (SW));
        GREEN <= greenArr (conv_integer (SW));
        BLUE <= blueArr (conv_integer (SW));
    else
        RED <= "00000000";
        GREEN <= "00000000";
        BLUE <= "00000000";
    end if;
LED <= SW;
end if;
end process;

Массив (Colors) имеет 16 элементов, потому что у меня 16 изображений, таким образом, для отображения всех из них достаточно 4 переключателей (SW). Я использовал 8 бит на цвет. flagAV это просто проверить, являюсь ли я активным регионом или нет.

У меня есть отдельный модуль (VGADraw) для этого выбора изображений, и еще один (VGADrive), где я определяю синхронизацию H/V, пустые сигналы H/V. Затем счетчики встраиваются в модуль выбора изображений с помощью сигналов холостого / высокого напряжения от VGADrive.

Синхронизация H/V и пустые сигналы, определенные в VGADrive:

HorizontalSync: process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
    if (inCntHor = RES.cstHorFP + RES.cstHorAL - 1) then
        inHS <= '0';
    elsif (inCntHor = RES.cstHorFP + RES.cstHorAL + RES.cstHorPW - 1) then
        inHS <= '1';
    end if;
end if;
end process;

HorizontalBlanking: process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
    if (inCntHor = RES.cstHorAL - 1) then
        inHBL <= '1';
    elsif (inCntHor = RES.cstHorTotSize - 1) then
        inHBL <= '0';
    end if;
end if;
end process;

VerticalSync: process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
    if (inCntVer = RES.cstVerFP + RES.cstVerAL - 1) then
        inVS <= '0';
    elsif (inCntVer < RES.cstVerFP + RES.cstVerAL + RES.cstVerPW - 1) then
        inVS <= '1';
    end if;       
end if;
end process;

VerticalBlanking: process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
    if (inCntVer = RES.cstVerAL - 1) then
        inVBL <= '1';
    elsif (inCntVer = RES.cstVerTotSize - 1) then
        inVBL <= '0';
    end if;
end if;
end process;

Счетчики встроены в модуль выбора изображений (VGADraw) с использованием сигналов гашения:

VerticalCounter: process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
    HBLold <= HBL;
    if HBL = '0' and HBLold = '1' then
        if VBL = '1' then
            incntVer <= 0;
        else
            incntVer <= incntVer + 1;
        end if;          
    end if;        
end if;
end process;

HorizontalCounter: process (CLK)
begin
if (CLK'EVENT and CLK = '1') then
    if HBL = '1' then
        incntHor <= 0;
    else
        incntHor <= incntHor + 1;
    end if;
end if;
end process;

cstHorAL - пиксели / активные линии

cstHorFP - пиксели / переднее крыльцо

cstHorPW - пиксели / ширина импульса

cstHorBP - пиксели / заднее крыльцо

cstHorTotSize - пиксели / общее количество строк

cstVerAL - линии / активные линии

cstVerFP - линии / переднее крыльцо

cstVerPW - ширина линии / импульса

cstVerBP - линии / задний подъезд

cstVerTotSize - строки / общее количество кадров

HBLold - используется для обнаружения падения края

Мой вопрос: как мне задержать сигналы h_sync и v_sync на этот 1 бит, чтобы изображения отображались правильно без смещения этих первых пикселей, и в каком модуле мне это делать?

1 ответ

Поскольку вы сказали, что реализовали задержку одного цикла, попробуйте больше задержек цикла, таких как:

process(CLK) is
begin
  if rising_edge(CLK) then
    a_q <= a;
    a_q_q <= a_q;
    a_q_q_q <= a_q_q;
    -- etc
  end if;
end process;

Если вы хотите более чистый код, вы можете использовать цикл FOR для задержки любого сигнала столько раз, сколько вы хотите, например

-- In Architecture
constant num_cycles : INTEGER := 3;
signal   a_v : std_logic_vector(num_cycles downto 0);

begin
  a_v(0) <= a;
  process(CLK) is
  begin
    if rising_edge(CLK) then
      for i in 0 to num_cycles loop
        a_v(i+1) <= a_v(i);
      end loop;
    end if;
  end process;
end architecture;

В этом случае a может быть h_sync или v_sync. num_cycles - это количество циклов, которое вы хотите отложить. a_v - это вектор. Чтобы использовать ваш задержанный сигнал просто используйте a_v(num_cycles)

Другие вопросы по тегам