§ Тайминги

Сегодня я хочу просто рассказать о том, как можно довольно легко и без проблем сделать вывод экрана спектрума на VGA монитор. Да, я как бы, говорю что легко, и без проблем, но это лишь потому, что я уже много раз делал этот видеовывод, да и сам он по себе простой.
Самая большая проблема заключается в другом. Тайминги, которые совершенно не совместимы между VGA 25 Мгц и телевизионным сигналом, который генерировал спектрум. Возьмем за основу самое стандартное разрешение VGA 640 x 480, и его тайминги.
                 |  HORIZ  VERT   | ZX HORIZ   VERT
Задний порожек   |   48    33     |    48      48
Видимая область  |   640   480    |    256     192
Передний порожек |   16    10     |    48      56
Синхронизация    |   96    2      |    96      16
ИТОГО            |   800   525    |    448     312
Итого, 800 пиксель-клоков на одну строку и 525 строк, 60 кадров в секунду. Красиво и быстро. А теперь, очень интересный момент. Надо сделать 50 кадров. Вот этот момент полон печали и тоски. Мало того, что надо сделать 50 кадров в секунду, так еще надо другие тайминги. Частота видеопроцессора у спектрума 7 Мгц.
В таблице у спектрума немного не так все работает. На самом деле, там 48 и 48 пиксельклока отведены для рисования бордера, а не порожеков, которые у VGA равны черному цвету, так что можно считать что общая область рисования картинки равна 352 пикселей и 96 это синхронизация. Высота картинки тоже составляет 296 пикселей. Это очень сильно много, так что вместить ничего не получится на VGA, чтобы было нормально, потому часть бордера придется скрыть. Например, слева и справа будет по 32 пикселя, а не по 48. А сверху и снизу, кстати говоря, 48 пикселей получится сделать (снизу все равно будет не 56).
Так что как бы я ни старался, уложить точно экран у меня не выйдет. Но ладно, я тогда буду просто пытаться делать максимально приблизительно и на 60 Гц вместо 50 Гц, что даст увеличение на 6/5 скорости работы процессора (+20%) чтобы четко и точно успевать бегать за лучом.

§ Видеоадаптер VGA

В любом случае, что бы там ни было, и как бы там ни было, надо сделать видеоадаптер, который будет выдавать стандартную картинку на VGA. Минимальный видеоадаптер будет выглядеть, в целом, вот так.
// verilator lint_off WIDTH

module video
(
    input               clock,
    output reg  [3:0]   r,
    output reg  [3:0]   g,
    output reg  [3:0]   b,
    output              hs,
    output              vs
);
// ---------------------------------------------------------------------
// Тайминги для горизонтальной|вертикальной развертки (640x400)
parameter
    hz_visible = 640, vt_visible = 480,
    hz_front   = 16,  vt_front   = 10,
    hz_sync    = 96,  vt_sync    = 2,
    hz_back    = 48,  vt_back    = 33,
    hz_whole   = 800, vt_whole   = 525;
// ---------------------------------------------------------------------
assign hs = x  < (hz_back + hz_visible + hz_front); // NEG.
assign vs = y >= (vt_back + vt_visible + vt_front); // POS.
// ---------------------------------------------------------------------
wire        xmax = (x == hz_whole - 1);
wire        ymax = (y == vt_whole - 1);
reg  [10:0] x    = 0;
reg  [10:0] y    = 0;
// ---------------------------------------------------------------------

// Вывод видеосигнала
always @(posedge clock)
begin

    {r, g, b} <= 12'h000;

    // Кадровая развертка
    x <= xmax ?         0 : x + 1;
    y <= xmax ? (ymax ? 0 : y + 1) : y;

    // Вывод окна видеоадаптера
    if (x >= hz_back && x < hz_visible + hz_back && y >= vt_back && y < vt_visible + vt_back)
    begin {r, g, b} <= 12'hFFF; end

end

endmodule