Читатели нашего блога уже наверняка знают, что плата Марсоход3GW построена на основе платы Марсоход3. Мы заменили чип Intel MAX10 на чип китайской компании Gowin GW1NR. В остальном платы, как близнецы, похожи и по габаритам и по компоновке и наличием одинаковых разъемов для шилдов и выход HDMI.
Для платы Марсоход3 у нас когда-то уже был создан проект генерации сигнала HDMI. Можно попробовать адаптировать тот прежний проект к новому чипу. Собственно это мы и сделали. На картинке выше показан вывод вертикальных цветных полос на монитор через HDMI разъем платы Марсоход3GW.
Микросхема FPGA GW1NR-UV9QN88PC6/I5 китайской компании Gowin имеет много довольно интересных встроенных блоков. Сейчас в этом проекте HDMI мы сможем попробовать использовать встроенные в ПЛИС сериализаторы и LVDS блоки.
Кратко скажу, что в используемой нами микросхеме серии GW1NR есть сериализаторы из параллельного кода в последовательный, это такие блоки, как: OSER4, OSER8, OVIDEO, OSER10, OSER16. И есть десериализаторы, преобразующие последовательный код в параллельный, это блоки IDES4, IDES8, IVIDEO, IDES10 и IDES16.
Если бы мы делали проект захвата видео, тогда нужно было бы пытаться использовать модули IDES. Но в нашем проекте HDMI вывода нам нужны блоки преобразования из параллельного в последовательный, а именно OSER10. Используем их!
Этот блок OSER10 берет 10ти битный параллельный код D[9:0] и выдает его в последовательном виде на выход Q. При этом, на блок нужно подавать две частоты. Главная частота PCLK и частота в 5 раз выше FCLK. На выходе Q данные будут выходить и по фронту и по спаду тактовой частоты FCLK.
После сериализатора OSER10 можно сразу поставить выходной модуль ELVDS (или TLVDS):
Модуль ELVDS будет выдавать дифференциальный сигнал на два выходных пина ПЛИС, это как раз то, что нам нужно для реализации HTMI интерфейса. ELVDS обозначает Emulated LVDS (эмулированный), а TLVDS это TRUE LVDS (настоящий). Какой тип LVDS использовать в проекте зависит от типа конкретной микросхемы Gowin и от схемы и разводки платы. В нашем случае нужно использовать именно ELVDS.
Теперь Verilog модуль HDMI будет выглядеть вот так:
...
module HDMI(
input clk_pixel,
input clk_5x_pixel,
input hsync,
input vsync,
input active,
input [7:0]red,
input [7:0]green,
input [7:0]blue,
output tmds_clk_n,
output tmds_clk_p,
output [2:0] tmds_d_n,
output [2:0] tmds_d_p
);
wire [2:0] tmds_d0, tmds_d1, tmds_d2, tmds_d3, tmds_d4;
wire [2:0] tmds_d5, tmds_d6, tmds_d7, tmds_d8, tmds_d9;
wire [2:0] tmds_d;
svo_tmds svo_tmds_0 (
.clk( clk_pixel ),
.resetn( 1'b1 ),
.de( active ),
.ctrl( {vsync,hsync} ),
.din( red ),
.dout( {tmds_d9[0], tmds_d8[0], tmds_d7[0], tmds_d6[0], tmds_d5[0],
tmds_d4[0], tmds_d3[0], tmds_d2[0], tmds_d1[0], tmds_d0[0]} )
);
svo_tmds svo_tmds_1 (
.clk( clk_pixel ),
.resetn( 1'b1 ),
.de( active ),
.ctrl( 2'b0 ),
.din( green ),
.dout( {tmds_d9[1], tmds_d8[1], tmds_d7[1], tmds_d6[1], tmds_d5[1],
tmds_d4[1], tmds_d3[1], tmds_d2[1], tmds_d1[1], tmds_d0[1]} )
);
svo_tmds svo_tmds_2 (
.clk( clk_pixel ),
.resetn( 1'b1 ),
.de( active ),
.ctrl( 2'b0 ),
.din( blue ),
.dout( {tmds_d9[2], tmds_d8[2], tmds_d7[2], tmds_d6[2], tmds_d5[2],
tmds_d4[2], tmds_d3[2], tmds_d2[2], tmds_d1[2], tmds_d0[2]} )
);
OSER10 tmds_serdes [2:0] (
.Q(tmds_d),
.D0(tmds_d0),
.D1(tmds_d1),
.D2(tmds_d2),
.D3(tmds_d3),
.D4(tmds_d4),
.D5(tmds_d5),
.D6(tmds_d6),
.D7(tmds_d7),
.D8(tmds_d8),
.D9(tmds_d9),
.PCLK(clk_pixel),
.FCLK(clk_5x_pixel),
.RESET(1'b0)
);
ELVDS_OBUF tmds_bufds [3:0] (
.I({clk_pixel, tmds_d}),
.O({tmds_clk_p, tmds_d_p}),
.OB({tmds_clk_n, tmds_d_n})
);
endmodule
...
В этом модуле три экземпляра TMDS энкодера для кодирования RGB сигналов, три экземпляра сериалайзеров OSER10 для последовательной передачи и четыре ELVDS модуля для создания и вывода пар дифференциальных сигналов HDMI.
Весь проект можно взять в папке _hdmi_oser10-elvds нашего репозитория на github: https://github.com/marsohod4you/Marsohod3GW
Проект использует включаемый через `include "resolution.v" файл настройки, где определены вырианты разрешения видео 640x480 или 800x600:
//select one desired resolution
`define Res640x480 1
//`define Res800x600 1
В зависимости от этих настроек в топ модуль будет вставлен тот или иной экземпляр rPLL. Для разрешения 640x480 rPLL выдает 125МГц, а для разрешения 800x600 другой rPLL выдает 200МГц. Кроме того, в топ модуле установлен еще один интересный аппаратный блок CLKDIV который настроен делить частоту на 5. Так получится частота пикселей 25МГц или 40МГц для соответствующих разрешений. Далее в топ модуле установлен генератор строчных и кадровых синхросигналов hvsync. Он выдает так же значения счетчиков по пикселям и по строкам. Из этих счетчиков генерируются цветные полосы шириной в 64 пикселя.
Этот проект может служить отправной точкой для других более сложных проектов, которым требуется отображать видео информацию на мониторы HDMI.
Подробнее...