HDMI выход на FPGA плате Марсоход3GW

hdmi 800x600

Читатели нашего блога уже наверняка знают, что плата Марсоход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

Этот блок OSER10 берет 10ти битный параллельный код D[9:0] и выдает его в последовательном виде на выход Q. При этом, на блок нужно подавать две частоты. Главная частота PCLK и частота в 5 раз выше FCLK. На выходе Q данные будут выходить и по фронту и по спаду тактовой частоты FCLK.

После сериализатора OSER10 можно сразу поставить выходной модуль ELVDS (или TLVDS):

ELVDS

Модуль 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.

 

Добавить комментарий