2012-01-18 2 views
0

В настоящее время я пытаюсь создать экранный буфер в VHDL (для устройства, которое отправляет видеоданные через VGA). Я использую Xilinx ISE 13.1, и я начинаю в VHDL.Экранный буфер в vhdl, приводящий к сбою во время синтеза

Моя идея состояла в том, чтобы создать большой двумерный массив, содержащий значение RGB каждого пикселя (по 8 бит).

Я могу написать в массиве без проблем, но мне становится сложнее, когда я должен его прочитать: Синтез становится чрезвычайно длинным, и XST просто полностью насыщает память, пока компьютер не выключится сам по себе.

Вот упрощенная версия моего кода, просто пытается нарисовать красный 45 ° линии:

entity Pilotage_ecran is 
port(clk25 : in std_logic; --25MHz clock 
    red_out : out std_logic; --Untill the problem is solved, i use only 1 bit to set colors 
    green_out : out std_logic; 
    blue_out : out std_logic; 
    hs_out : out std_logic; 
    vs_out : out std_logic); 
end Pilotage_ecran; 

architecture Behavioral of Pilotage_ecran is 


signal horizontal_counter : std_logic_vector (9 downto 0); 
signal vertical_counter : std_logic_vector (9 downto 0); 
signal drawing : std_logic; --Signal that is set to 1 when the active video area is reached 
signal busy : std_logic; --Signal to avoid launching the drawing process twice in parallel 


--The array (actually containing single bits instead of vectors untill I solve the problem) 
type TAB_BUFFER is array(0 to 1023, 0 to 1023) of std_logic; 

signal Ecran : TAB_BUFFER := (others=>'0'); 


begin 

Основной процесс:

process (clk25) 

variable coordX : integer; 
variable coordY : integer; 

begin 
    if clk25'event and clk25 = '1' then 


    if (horizontal_counter >= "0010010000") -- 144 : limits of active video area 
    and (horizontal_counter < "1100010000") -- 784 
    and (vertical_counter >= "0000100111") -- 39 
    and (vertical_counter < "1100010000") -- 519 
    then 

     drawing <= '1'; 

    coordX := conv_integer (horizontal_counter); 
    coordY := conv_integer (vertical_counter); 


     if Ecran(coordX,coordY) = '1' then --Here is the problem 
      red_out <= '1'; 
        green_out <= '0'; 
      blue_out <= '0'; 
     else 
      red_out <= '0'; 
        green_out <= '0'; 
      blue_out <= '0'; 
     end if; 



    else 
     drawing <= '0'; 

    end if; 




    --Hsync and Vsync come after, but the code is safe and tested 

end if; 
end process; 

Drawing процесс (на самом деле рисование линии в уродливый но я просто хотел получить что-нибудь в буфере).

draw : 
process (drawing, clk25, busy) 


--Coordinates of the starting point (actually random values...) 

variable i : integer; 
variable j : integer; 

begin 

    if (drawing = '1') and clk25 = '1' and busy = '0' then 

     busy <= '1'; 

     i :=300; 
     j :=300; 

     --The loop setting the coordinates of the line to '1' 

     loopx : while (i<=350) loop 
      Ecran(i,j) <= '1'; 
      i := i+1; 
      j := j+1; 

     end loop loopx; 

     busy <='0'; 
    end if; 


end process draw; 



end Behavioral; 

Линия, которая вызывает у меня неприятности есть один, где я пытаюсь получить доступ к значению в некоторых координатах в буфере:

если ECRAN (coordX, coordY) = «1», то

Я также пытался сделать так:

< red_out = Ecran (coordX, coordY);

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

Если у кого-то есть представление о том, что я сделал неправильно, или у вас есть лучший способ создания экранного буфера в vhdl, любая помощь будет очень оценена.

спасибо, что заранее.

ответ

2

Я не уверен, как работает VGA, но смотрит на ваш код. Я считаю, что в вашем «процессе рисования» есть что-то принципиально неправильное. Вы пытаетесь сделать что-то, как разработчик программного обеспечения, а не разработчик аппаратного обеспечения.

Короче говоря, гнездящихся большую часть процесса при этом, если оператор

if (drawing = '1') and clk25 = '1' and busy = '0' then 

ваша проблема. Две причины, которые я вижу. Сначала вы увеличиваете счетчики в цикле со скоростью, полностью асинхронной к часам (вы говорите, если clock = '1'), которая высока в течение неопределенного периода. Обновление этого приращения ограничено только задержкой пропусков через счетчик. Все счетчики должны быть синхронными (если raise_edge (clk)) или (если часы = 1 и clk'event).

Другая ошибка связана с вашей текущей комбинаторной настройкой (асинхронной), которая исчезнет, ​​если вы сделаете это синхронным процессом.Выполняя занятие < = '1' сразу после инструкции if в комбинаторной логике, вы по существу дезактивируете этот блок на аппаратном уровне. В зависимости от того, как вы кодируете свое синхронное решение, это может быть или не быть проблемой для вас.

И, наконец, это связано с тем, что вы думаете о программном обеспечении, которое не является аппаратным, вы заняты < = '1' в начале и заняты < = '0' в конце инструкции if. Для синхронизации или асинхронного проектирования это приведет к занятости < = '0' независимо от того, что. Вместо этого (когда вы идете синхронно) заняты < = '0' вне вашего оператора if и заняты < = '1' внутри вашего оператора if. Каждый раз, когда оператор выполняет занятый, будет равен 1 для всего тактового сигнала.

Когда вы программируете VHDL, вам нужно подумать о каждой команде, выполняющей либо непрерывно (асинхронный), либо периодически (синхронно с часами). Даже если событие в выражении if не соответствует действительности, все события в операторе if выполняются. Утверждение if просто действует как «enable». Сказав все это, следующий код может делать то, что вы хотите.

draw : process (clk25) 
    --Coordinates of the starting point (actually random values...) 
    variable i : integer := 300; 
    variable j : integer := 300; 

begin 

    if (rising_edge(clk)) then 
     busy <= '0'; 
     if (i<=350) then 
      busy <= '1'; 
      Ecran(i,j) <= '1'; 
      i := i+1; 
      j := j+1; 
     end if; 
    end if; 
end process draw; 

Я думаю, что ваш «ящик» на самом деле просто предварительно загружая большой массив, и что ваш другой процесс, который устанавливает цвета, на самом деле ваш писатель? У меня создалось впечатление, что вы увеличивали всю строку, а затем меняли столбец, когда пишете красные/зеленые/синие биты на экране? Опять я ничего о VGA

+0

спасибо. Это не решило мою первую проблему, но это помогло мне улучшить мой процесс и мое понимание vhdl в любом случае. Вы правы в своем последнем абзаце, процесс рисования сохраняет значения каждого пикселя в буфере, тогда как основной процесс считывает значения RGB каждого пикселя в буфере, отправляет его на кабель VGA, а затем переходит к следующему пикселю. –

+0

Первой проблемой является то, что вы все еще не можете синтезировать этот код? Я не думаю, что размер массива должен быть проблемой, если вы не используете совершенно бесполезную коробку. ваш массив эквивалентен 128 КБ памяти. Это может быть невозможно для некоторых FPGA, но это звучит не так, как будто вы его используете. Вы уверены, что это не что-то еще, что несинтезируемо. Получаете ли вы какие-либо сообщения об ошибках до того, как все будет закрыто? –

+0

Я использую FPGA (спартанскую плату разработки) для перевода входящих данных в видеосигнал, поэтому память будет проблемой. У меня нет ошибок/предупреждений, и синтез застрял в анализе HDL после этого журнала: Анализ объекта в библиотеке (Архитектура ). –

1

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

Проблема заключается в том, что вы пытаетесь построить считываемый мультиплексор для большой памяти, состоящей из небольших блоков ОЗУ. Достаточно блоков, и проблема становится неразрешимой для вашей конкретной платформы сборки.

Вы можете изменить свой генератор синхронизации видеосигнала, чтобы разобрать отображаемые адреса чтения, позволяя в этом случае определить ваш TAB_BUFFER меньше (от 0 до 639, от 0 до 479), сохранив две трети памяти (307,200 против 1 М пикселей) , Непонятно, что масштабирование проблемы будет достаточно маленьким, чтобы синтезировать ее, и если да, то будет ли она достаточно быстрой.

Возможно, вы также захотите разобрать адреса буфера кадров с нынешних горизонтальных и вертикальных счетчиков либо с помощью отдельных счетчиков отображаемых адресов, либо путем прохождения через нуль в качестве первого видимого пикселя на строке или первой видимой строке на дисплее , Идея заключается в том, что вам не придется делать перевод адресов во время записи.

Вы можете попытаться определить структуру памяти, чтобы преодолеть неспособность ее синтезировать. Это может быть так же просто, как сделать размещение или сложным, как создание иерархии. Идея заключается в том, что вы отнимаете часть сложной работы от синтеза, предоставляя ей меньше работы.

+0

Прежде всего, спасибо за ваш ответ. Я установил размер 1024 * 1024, так как мне, вероятно, придется увеличить разрешение позже. Я попытался разделить размер экрана на 2 640 * 240 (управляя верхней и нижней половиной экрана), и у меня больше нет проблем с сбоем, но синтез все еще не заканчивается. Разделение буфера в нескольких «зонах» упрощает работу с инструментом синтеза и улучшает управление памятью, или мне нужно найти другое решение? –

+0

@Mathieu C. Вы можете использовать генератор блоков памяти v6.1 в ISE 13.1. См. [V6.1 datasheet] (http://www.xilinx.com/support/documentation/ipmeminterfacestorelement_ramrom_blockmemgenerator.htm) (PDF). Компромисс здесь для функциональности и переносимости, генератор памяти может создавать как поведенческие, так и структурные модели VHDL сгенерированной памяти. Размер и производительность памяти зависят от семейства и устройства. Инструменты управляют иерархией и местом размещения для вас. Подразумевается, что вы выбрасываете функции, которые не соответствуют стоимости/производительности FPGA или возвращаются назад и получают большую лодку. – user1155120

Смежные вопросы