====== Видеоадаптер VGA для проекта БК-FPGA ====== Экран БК-0010 имеет разрешение 512x256 точек. Для отображения на стандартном мониторе возьмем за основу временную диаграмму [[http://www.epanorama.net/documents/pc/vga_timing.html | режима 640x480]] и немного изменим ее. Увеличим разрешение по вертикали до 512 и будем отображать каждую строку дважды. Для облегчения расчетов существует удобный [[http://www.tkk.fi/Misc/Electronics/faq/vga2rgb/calc.html | калькулятор видеорежимов]]. Есть полезная статья [[http://www.xess.com/appnotes/an-101204-vgagen.html | VGA Generator for the XSA Boards]] с примером [[http://www.xess.com/projects/an-101204-vgagen.zip | кода на VHDL]]. ===== Горизонтальная развертка ===== ^ VGA 640x480 ^ БК 512x512 ^ Параметр ^ | 25.175 | 25.00 | Pixel clock frequency, MHz | | NEG | NEG | Horizontal Sync Polarity | | 31.46 kHz | 36.23 kHz | Horizontal Frequency | | 800 / 31.78 | 690 | A (pixels/us) -- Scanline | | 96 / 3.81 | 50 / 2.00 | B (pixels/us) -- Sync pulse length | | 48 / 1.91 | 92 | C (pixels/us) -- Back porch | | 640 / 25.42 | 512 | D (pixels/us) -- Active video | | 16 / 0.64 | 36 | E (pixels/us) -- Front porch |
______________________ ________ ________| VIDEO |________| VIDEO (next line) |-C-|----------D-----------|-E-| __ ______________________________ ___________ |_| |_| |B| |---------------A----------------|===== Вертикальная развертка ===== ^ VGA 640x480 ^ БК 512x512 ^ Параметр ^ | 25.175 MHz | 25.00 MHz | Pixel clock frequency | | NEG | NEG | Vertical Sync Polarity | | 59.94 Hz | 59.59 Hz | Vertical Frequency | | 525 / 16.68 | 614 | O (pixels/ms) -- Total frame | | 2 / 0.064 | 4 / 0.11 | P (pixels/ms) -- Sync length | | 31 / 0.99 | 61 | Q (pixels/ms) -- Back porch | | 480 / 15.25 | 512 | R (pixels/ms) -- Active video | | 11 / 0.35 | 31 | S (pixels/ms) -- Front porch |
______________________ ________ ________| VIDEO |________| VIDEO (next frame) |-Q-|----------R-----------|-S-| __ ______________________________ ___________ |_| |_| |P| |---------------O----------------|===== Как это выглядит ===== В качестве тестового изображения выбрана такая картинка: {{512x256.png}} Вот как это выглядит на экране: {{vga-photo.jpg}} ===== Исходные тексты ===== Исходные тексты теста можно скачать здесь: {{vga512x256.zip}}. Всего 176 строчек на Верилоге.
//
// Videoadapter 512x256 one bit per pixel.
// Clock 25 MHz.
// Uses 16 kbytes of video memory: 8192 words of 16 bit each
//
module vga512x256 (
input wire clk,
input wire rst,
output wire [12:0] maddr, // address to video memory
input wire [15:0] mdata, // data from video memory
output wire red,
output wire green,
output wire blue,
output wire hsync,
output wire vsync);
//
// Horizontal timing
//
parameter B = 50; // Sync pulse length
parameter C = 92; // Back porch
parameter D = 512; // Active video
parameter E = 36; // Front porch
//
// Vertical timing
//
parameter P = 4; // Sync length
parameter Q = 61; // Back porch
parameter R = 512; // Active video
parameter S = 31; // Front porch
// Current pixel's X-Y position.
reg [9:0] cnt_x;
reg [9:0] cnt_y;
// Video data shift register.
reg [15:0] word;
// Video output bits.
assign red = word[0];
assign green = word[0];
assign blue = word[0];
// Address of video memory.
assign maddr = { cnt_y[8:1], cnt_x[8:4] };
// Delay hsync by 1 clock.
assign hsync = ~(cnt_x > (D + E) && cnt_x <= (D + E + B));
assign vsync = ~(cnt_y >= (R + S) && cnt_y < (R + S + P));
always @(posedge clk) begin
// Horizontal dot counter.
if (rst || cnt_x == (B + C + D + E - 1))
cnt_x <= 0;
else
cnt_x <= cnt_x + 1;
// Vertical line counter.
if (rst)
cnt_y <= 0;
else if (cnt_x == (B + C + D + E - 1)) begin
if (cnt_y == (P + Q + R + S - 1))
cnt_y <= 0;
else
cnt_y <= cnt_y + 1;
end
// Video data shift register.
// Reading from memory must be delayed by 1 clock.
if (cnt_x[3:0] == 1) begin
if (cnt_x <= D && cnt_y < R)
word <= mdata;
else
word <= 0;
end else
word <= { 1'b0, word[15:1] };
end
endmodule