Генератор Видеосигнала на NIOS II
Статьи по теме

Разработка генератора видеосигнала на плате Altera DE2 на базе NIOS II
Генераторы видеосигнала широко используются при тестировании различной видео аппаратуры. Разработанное устройство может использоваться для измерения разрешающей способности, оценки цветопередачи видеоизображения в видеорегистраторах или видеосерверах и системах нелинейного монтажа после оцифровки и сжатия.
Зачастую для решения таких задач используется видеокамера, однако в этом случае изначально закладывается ошибка при позиционировании испытательной таблицы, освещенности и всего тракта обработки изображения, начиная с объектива и заканчивая преобразованиями сигнала. Другое дело – тестовый генератор с образцовыми сигналами испытательных таблиц и разными видами реальных сцен.
Такие генераторы имеют широкую область применения, которая охватывает:
-
Оценка качества воспроизведения видеомониторов, включая такие характеристики, как: линейность, гамма-коррекция, оптимальная контрастность и яркость видеосигнала
-
Визуальный контроль за качеством сигнала при коммутации длинных кабелей (согласованность волнового сопротивления, наличие отраженного сигнала от конца линии и т.д.);
-
Оценка геометрических искажений после оцифровки видеоизображения;
-
Определение динамического диапазона и уровня видеосигнала.
Для демонстрации возможностей генерации видеосигналов, представляемых отладочным модулем DE2, было решено составить несложную видео игру, описанию которой и посвящена работа.
Структурная схема генератора видеосигнала
Приступая к разработке, первой необходимостью является составление структурной схемы. Постановка задачи сама по себе определяет набор компонентов, необходимых для успешной реализации проекта. Так, например, однозначно понадобится процессорное ядро и блок памяти для хранения программы. Было решено поместить программу в блок SDRAM, так как она имеет значительный объем и средств On-Chip memory для этого недостаточно
Для реализации анимации, используется interval timer. Особенностью этого таймера является возможность генерировать прерывание по истечению заданного интервала. Также источником прерываний является параллельный порт ввода/вывода, через который к ядру подключаются кнопки управления.
Очевидно, что необходимо позаботиться и о хранилище отображаемых на экране кадров. Для этих целей используется пиксельный буфер, реализованный на блоке памяти SDRAM. Передача кадров, сохраненных в пиксельном буфере на VGA контроллер с последующим отображением на мониторе, производится посредством шины Avalon-ST. Преобразование кадров в форму, пригодную для передачи по шине Avalon-ST, производится Pixel buffer DMA контроллером, который благодаря прямому доступу к пиксельному буферу через шину Avalon ST эффективно обрабатывает кадры, не нагружая при этом основную шину, на которой мастером является ядро NIOS II.
Все что осталось сделать – привести кадры к формату, требуемому VGA контроллером, для качественного отображения на мониторе. Эта задача решается с использованием блоков Pixel RGB resampler, pixel scaler и dual clock fifo. Описание настроек этих блоков описано в последующих разделах. Общая структурная схема генератора приведена на рис. 1. Так понятно?
Рис. 1. Структурная схема генератора видеосигналов
СОЗДАНИЕ ВСТРОЕННОГО ЯДРА В УТИЛИТЕ SOPC BUILDER
Девиз проектирования в среде SOPC builder – «От концепции к системе за несколько минут». Концепция нами была разработана в предыдущем разделе, результатом чего является структурная схема. На основании этого простроена конфигурация встроенного ядра в среде SOPC builder. Результат конфигурирования представлен на рис. 2.
Рис. 2. Конфигурация встроенного ядра в утилите SOPC builder
Необходимо отметить, что для создания данной конфигурации был использован пакет дополнительных компонентов University program. Если у Вас эти компоненты не установлены, необходимо провести инсталляцию этого пакета. Для этого нужно запустить файл altera_upds_setup_verilog.exe, который приложен к проекту.
Настройка процессора представлена на рис.3. На этом этапе важно указать место, где размещена программа (смещение вектора сброса и вектора прерываний).
Рис. 3. Конфигурация процессора Nios II
При конфигурировании блока SDRAM контролера, необходимо указать адрес контроллера, равный 0x00800000
и зафиксировать его. Более подробную информацию о необходимых настройках контроллера SDRAM можно узнать из технической документации на микросхему памяти (SDRAM 8MB), которая находится в папке Documentation. Настройки, использованные в проекте, приведены на рис. 4.
Рис. 4. Настройки блока SDRAM контроллера
Для формирования тактовых сигналов для разных блоков внутреннего ядра, а также памяти SDRAM, используется блок PLL, конфигурация которого представлена на рис. 5. Этот блок поставляется вместе с пакетом компонентов University program и очень прост в конфигурировании: необходимо указать, что в качестве отладочного модуля используется плата Altera DE2 и нужно сформировать сигналы тактирования для SDRAM и VGA контроллера. Интеллектуальный модуль сам установит частоту тактирования SDRAM модуля равной 50 МГц, VGA контроллера – 25 МГц.
Конфигурирование блока параллельного ввода/вывода, подключающего кнопки управления к внутреннему ядру, представлено на рис 6. Порт настраивается только на ввод и имеет разрядность, равную четырем битам (количеству кнопок на модуле DE2).
Рис. 5. Конфигурирование блока PLL
В закладке Input options указано, что порт является синхронным. Таким образом, по каждому положительному фронту в Edge capture регистре параллельного порта ввода/вывода будет отмечено, номер линии, где произошло изменение уровня. Также по этому событию будет сгенерировано прерывание.
Параллельный порт ввода/вывода для подключения блока индикации конфигурируется аналогично, за исключением того, что настройки в закладке input options остаются без изменения, а порт настраивается только на выход и имеет разрядность 16 бит.
Для реализации анимации используется блок interval timer. На рисунке 7 показано окно конфигурирования таймера. Важной настройкой является указание времени, через которое происходит переполнение таймер.
Рис. 6. Конфигурирование блока PIO для кнопок управления
Это время влияет на частоту обновления изображения при анимированнии. В разрабатываемом проекте оно равняется одной секунде.
Рис. 7. Конфигурирование блока interval timer
Пиксельный буфер размещен в SRAM памяти. Для реализации контроллера SRAM используется компонент из пакета University program. При конфигурировании компонента необходимо просто указать название отладочного модуля (DE2) и его назначение (поставить галочку в поле “use as a pixel buffer for video out”). Окно конфигураций блока показано на рис. 8.
Рис. 8. Конфигурирование блока SRAM контроллера
Настройка DMA контроллера для пиксельного буфера представлена на рис.9. Плата DE2 располагает небольшим объемом SRAM памяти – 512 Кб. Таким образом, изначально выбирается небольшое разрешение кадра – 320х240 пикселей. Также для экономии места, кодирование производится в формате 5-6-5, поэтому в поле pixel format, color space выбран равный 16 бит.
Для нормального отображения кадров используется pixel scaler с масштабирующем фактором равным 2 по ширине и высоте. Таким образом, кадр на выходе имеет разрешение 640х480. Настройки компонента Pixel scaler представлены на рис. 10.
Рис. 9 Конфигурирование компонента pixel buffer DMA controller
Рис. 10. Конфигурирование компонента Pixel Scaler.
РАЗРАБОТКА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ДЛЯ ГЕНЕРАТОРА ВИДЕОСИГНАЛА НА NIOS II
Разработанную программу можно условно разбить на 2 части: инициализация рабочей среды и обработка управляющих сигналов с последующей отрисовкой. Первая задача решается путем регистрации обработчиков прерываний от таймера и параллельного порта ввода/вывода, вторая – реализацией самих обработчиков. Таким образом, блок диаграмма, описывающая функционирование программы представлена на рис. 11.
Рис. 11. Блок диаграмма основной подпрограммы
Приведем краткое описание каждого из блоков.
Разрешение всех прерываний проводится с помощью встроенной функции alt_irq_cpu_enable_interrupts();
Формирование объектов модели заключается в создании объекта змейки. Змейка представляет собой массив структур типа Point. Следовательно, формирование змейки заключается просто в заполнении массива тремя точками (изначально змейка имеет длину в три точки). «Еда» для змейки – структура типа Point, объект которой генерируется случайно.
Инициализация таймера заключается в регистрации обработчика прерываний от таймера. На этом месте необходимо остановиться немного поподробнее. Перед вызовом стандартной функции регистрации обработчика прерываний (alt_ic_isr_register), необходимо в регистре управления таймером разрешить прерывания, установить бит повторного счета и запустить таймер. Все это можно выполнить с помощью команды
1 2 3 4 5 6 7 |
IOWR_ALTERA_AVALON_TIMER_CONTROL (ANIMATIONTIMER_BASE, ALTERA_AVALON_TIMER_CONTROL_ITO_MSK | ALTERA_AVALON_TIMER_CONTROL_CONT_MSK | ALTERA_AVALON_TIMER_CONTROL_START_MSK); |
Также в регистре статуса таймера необходимо сбросить бит переполнения. Для этого используется команда:
1 |
IOWR_ALTERA_AVALON_TIMER_STATUS(ANIMATIONTIMER_BASE, 2); |
Порты ввода вывода инициализируются аналогично таймеру, за исключением того, что перед регистрацией обработчика прерывания, необходимо разрешить прерывания от всех линий порта и очистить edge capture регистр. Этого можно достичь, выполнив команды:
1 2 3 |
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTONS_BASE, 0xf); IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTONS_BASE, 0x0); |
Сигнал alive по умолчанию установлен равным логической единице. Он сбрасывается только в случае, если змейка сталкивается с краем игрового поля или сама с собой, что приводит к завершению игры.
Обработчик прерывания от порта параллельного ввода/вывода определяет направление движения змейки при следующем тике таймера. Блок схема обработчика прерываний от порта приведен на рис. 12
Рис. 12. Блок схема обработчика прерываний параллельного порта.
Переменная moveDirection определяет направление, в котором будет произведено движение змейки при следующем тике таймера.
Обработчик прерывания от таймера анализирует переменную moveDirection и в зависимости от ее значения модифицирует объект типа змея (модифицирует массив точек). Новое состояние массива, из которого состоит змея, анализируется и модифицируется (если змея столкнулась сама с собой или краем игрового поля) переменная alive, или увеличивается счет, если точка первого элемента массива (голова змеи) совпала с точкой, которая представляет собой «еду».
ВЫВОДЫ
В ходе расчетно-графической работы решалась задача проектирования генератора видеосигнала. Для демонстрации возможностей отладочного модуля DE2 в этом направлении было решено создать простую видео игру.
Проектирование аппаратной части проводилось в среде САПР Quartus II c помощью утилиты SOPC builder на основании структурной схемы представленной на рис. 1.
Программная часть реализовывалась в среде Nios II. Работоспособность устройства проверена на отладочном модуле Altera DE2. Испытания проекта показали, что задание на расчетно графическую работу было решено в полном объеме. Единственным изъяном остается непредсказуемая работа проекта при выполнении аппаратного сброса системы.
Файл верхнего уровня проекта генератора, описанный на Verilog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
module DE2_VGA_Pixel_Buffer ( CLOCK_50, KEY, SW, SRAM_DQ, SRAM_ADDR, SRAM_CE_N, SRAM_WE_N, SRAM_OE_N, SRAM_UB_N, SRAM_LB_N, VGA_CLK, VGA_HS, VGA_VS, VGA_BLANK, VGA_SYNC, VGA_R, VGA_G, VGA_B, //SDRAM DRAM_ADDR, DRAM_CAS_N, DRAM_CKE, DRAM_CS_N, DRAM_DQ, DRAM_RAS_N, DRAM_WE_N, DRAM_CLK, DRAM_LDQM, DRAM_UDQM, DRAM_BA_0, DRAM_BA_1, //7SEG HEX0, HEX1, HEX2, HEX3, HEX4, HEX5, HEX6, HEX7 ); // Inputs input CLOCK_50; input [3:0] KEY; input [17:0] SW; // Bidirectionals // Memory (SRAM) inout [15:0] SRAM_DQ; output [17:0] SRAM_ADDR; output SRAM_CE_N; output SRAM_WE_N; output SRAM_OE_N; output SRAM_UB_N; output SRAM_LB_N; // VGA output VGA_CLK; output VGA_HS; output VGA_VS; output VGA_BLANK; output VGA_SYNC; output [ 9: 0] VGA_R; output [ 9: 0] VGA_G; output [ 9: 0] VGA_B; //SDRAM output DRAM_BA_0; output DRAM_BA_1; output DRAM_CAS_N; output DRAM_CKE; output DRAM_CLK; output DRAM_CS_N; inout [15: 0] DRAM_DQ; output DRAM_LDQM; output DRAM_RAS_N; output DRAM_UDQM; output DRAM_WE_N; output [11: 0] DRAM_ADDR; //7_SEG output reg [6:0] HEX0; output reg [6:0] HEX1; output reg [6:0] HEX2; output reg [6:0] HEX3; output reg [6:0] HEX4; output reg [6:0] HEX5; output reg [6:0] HEX6; output reg [6:0] HEX7; always begin HEX4 = 7'b1111111; HEX5 = 7'b1111111; HEX6 = 7'b1111111; HEX7 = 7'b1111111; end wire niosReset; wire [15:0] hexInput; Video_System Pixel_Buffer_System ( // 1) global signals: .clk_0 (CLOCK_50), .reset_n (niosReset), .sys_clk (), .vga_clk (), .sdram_clk (DRAM_CLK), // the_Pixel_Buffer .SRAM_DQ_to_and_from_the_Pixel_Buffer (SRAM_DQ), .SRAM_ADDR_from_the_Pixel_Buffer (SRAM_ADDR), .SRAM_LB_N_from_the_Pixel_Buffer (SRAM_LB_N), .SRAM_UB_N_from_the_Pixel_Buffer (SRAM_UB_N), .SRAM_CE_N_from_the_Pixel_Buffer (SRAM_CE_N), .SRAM_OE_N_from_the_Pixel_Buffer (SRAM_OE_N), .SRAM_WE_N_from_the_Pixel_Buffer (SRAM_WE_N), // the_vga_controller .VGA_CLK_from_the_VGA_Controller (VGA_CLK), .VGA_HS_from_the_VGA_Controller (VGA_HS), .VGA_VS_from_the_VGA_Controller (VGA_VS), .VGA_BLANK_from_the_VGA_Controller (VGA_BLANK), .VGA_SYNC_from_the_VGA_Controller (VGA_SYNC), .VGA_R_from_the_VGA_Controller (VGA_R), .VGA_G_from_the_VGA_Controller (VGA_G), .VGA_B_from_the_VGA_Controller (VGA_B), // the SDRAM controller .zs_addr_from_the_sdram_0 (DRAM_ADDR), .zs_ba_from_the_sdram_0 ({DRAM_BA_1, DRAM_BA_0}), .zs_cas_n_from_the_sdram_0 (DRAM_CAS_N), .zs_cke_from_the_sdram_0 (DRAM_CKE), .zs_cs_n_from_the_sdram_0 (DRAM_CS_N), .zs_dq_to_and_from_the_sdram_0 (DRAM_DQ), .zs_dqm_from_the_sdram_0 ({DRAM_UDQM, DRAM_LDQM}), .zs_ras_n_from_the_sdram_0 (DRAM_RAS_N), .zs_we_n_from_the_sdram_0 (DRAM_WE_N), .in_port_to_the_buttons (KEY), .out_port_from_the_S7SEG (hexInput) ); Reset_Delay( .iRST (SW[0]), .iCLK (CLOCK_50), .oRESET (niosReset) ); SEG7_LUT_4( .iDIG (hexInput), .oSEG0 (HEX0), .oSEG1 (HEX1), .oSEG2 (HEX2), .oSEG3 (HEX3) ); endmodule |
Автор: Таценко, гр. ДКм-71.