Na biyu HDMI saka idanu zuwa Rasberi Pi3 ta hanyar dubawar DPI da allon FPGA


Wannan bidiyon yana nuna: allon Rasberi Pi3, wanda, ta hanyar haɗin GPIO, an haɗa allon FPGA Mars Rover2rpi (Cyclone IV), wanda aka haɗa na'urar duba HDMI. Ana haɗa na'ura ta biyu ta hanyar daidaitaccen mahaɗin Rasberi Pi3 HDMI. Gabaɗaya yana aiki kamar tsarin kulawa biyu.

Na gaba zan gaya muku yadda ake aiwatar da shi.

Shahararriyar hukumar Raspberry Pi3 tana da mai haɗin GPIO wanda ta inda zaku iya haɗa allon faɗaɗa daban-daban: na'urori masu auna firikwensin, LEDs, direbobin injin stepper da ƙari mai yawa. Takamaiman aikin kowane fil akan mai haɗawa ya dogara da daidaitawar tashar jiragen ruwa. Tsarin GPIO ALT2 yana ba ka damar sauya mai haɗa zuwa yanayin dubawar DPI, Nuni Parallel Interface. Akwai allon faɗaɗa don haɗa masu saka idanu na VGA ta hanyar DPI. Koyaya, da farko, masu saka idanu na VGA ba su zama gama gari kamar HDMI ba, na biyu kuma, ƙirar dijital tana samun inganci fiye da analog. Bugu da ƙari, DAC akan irin waɗannan katunan fadada VGA yawanci ana yin su ta hanyar sarƙoƙi na R-2-R kuma galibi ba su wuce 6 rago kowane launi ba.

A cikin yanayin ALT2, fil ɗin mai haɗin GPIO suna da ma'ana mai zuwa:

Na biyu HDMI saka idanu zuwa Rasberi Pi3 ta hanyar dubawar DPI da allon FPGA

Anan na canza fil ɗin RGB na mahaɗin ja, kore da shuɗi bi da bi. Sauran mahimman sigina sune siginar daidaitawa na V-SYNC da H-SYNC, da kuma CLK. Mitar agogon CLK shine mitar da ƙimar pixel ke fitarwa zuwa mai haɗawa kuma ya dogara da yanayin bidiyo da aka zaɓa.

Don haɗa na'urar duba HDMI na dijital, kuna buƙatar ɗaukar siginar dubawar DPI kuma canza su zuwa siginar HDMI. Ana iya yin wannan, misali, ta amfani da kowane allon FPGA. Kamar yadda ya juya, allon Mars Rover2rpi ya dace da wannan dalili. A gaskiya, babban zaɓi don haɗa wannan allo ta hanyar adaftar ta musamman yayi kama da haka:

Na biyu HDMI saka idanu zuwa Rasberi Pi3 ta hanyar dubawar DPI da allon FPGA

Ana amfani da wannan allon don ƙara yawan tashar jiragen ruwa na GPIO da kuma haɗa ƙarin abubuwan haɗin kai zuwa rasberi. A lokaci guda, ana amfani da siginar GPIO 4 tare da wannan haɗin don siginar JTAG, ta yadda shirin daga rarraba zai iya ɗaukar firmware FPGA cikin FPGA. Saboda wannan, irin wannan haɗin kai na yau da kullum bai dace da ni ba, 4 DPI siginar ya fita. Sa'ar al'amarin shine, ƙarin combs a kan allo suna da nau'in Rasberi mai jituwa. Don in iya jujjuya allon digiri 90 kuma har yanzu haɗa shi zuwa rasberi na:

Na biyu HDMI saka idanu zuwa Rasberi Pi3 ta hanyar dubawar DPI da allon FPGA

Tabbas, dole ne ku yi amfani da shirye-shiryen JTAG na waje, amma wannan ba matsala bane.

Har yanzu akwai karamar matsala. Ba kowane fil na FPGA ba ne za a iya amfani da shi azaman shigar da agogo. Akwai ƴan filaye da aka keɓe waɗanda za a iya amfani da su don wannan dalili. Don haka ya juya a nan cewa siginar GPIO_0 CLK ba ta isa ga shigarwar FPGA ba, wanda za a iya amfani da shi azaman shigar da agogon FPGA. Don haka duk daya, sai da na jefa rubutu daya a kan gyale. Na haɗa siginar GPIO_0 da KEY[1] na allo:

Na biyu HDMI saka idanu zuwa Rasberi Pi3 ta hanyar dubawar DPI da allon FPGA

Yanzu zan gaya muku kadan game da aikin a cikin FPGA. Babban wahalar samuwar siginar HDMI shine mitoci masu yawa. Idan aka kalli madaidaicin mai haɗin HDMI, zaku iya ganin cewa siginar RGB yanzu sigina ne na daban:

Na biyu HDMI saka idanu zuwa Rasberi Pi3 ta hanyar dubawar DPI da allon FPGA

Amfani da sigina na banbanta yana ba ku damar magance hayaniyar yanayin gama gari akan layin watsawa. A wannan yanayin, ainihin lambar takwas-bit na kowace siginar launi tana jujjuya zuwa 10-bit TMDS (alamar siginar da aka rage minimized). Wannan wata hanya ce ta ɓoyewa ta musamman don cire ɓangaren DC daga siginar kuma rage girman sauya sigina a cikin layin banbanta. Tunda a yanzu akwai ragi 10 don watsa kowane byte na launi akan layin serial, ya zama cewa mitar agogo na serializer dole ne ya ninka mitar agogon pixels sau 10. Idan muka ɗauki misali yanayin bidiyo 1280x720 60Hz, to pixel mita na wannan yanayin shine 74,25MHz. Serializer ya kamata ya zama 742,5 MHz.

FPGAs na al'ada gabaɗaya ba su iya yin hakan, abin takaici. Koyaya, ga sa'ar mu, FPGAs suna da fitilun DDIO na ciki. Waɗannan ƙarshe ne waɗanda suka riga sun kasance, kamar yadda suke, serializers 2-to-1. Wato suna iya fitar da rago biyu a jere tare da mitocin agogo masu tasowa da faɗuwa. Wannan yana nufin cewa a cikin aikin FPGA ba za ku iya amfani da 740 MHz ba, amma 370 MHz, amma kuna buƙatar amfani da abubuwan fitarwa na DDIO a cikin FPGA. Anan 370 MHz ya riga ya zama mitar da za a iya samu. Abin takaici, yanayin 1280 × 720 shine iyaka. Ba za a iya samun ƙuduri mafi girma a cikin FPGA Cyclone IV da aka shigar a kan allon Rover2rpi.

Don haka, a cikin aikin, ana ciyar da mitar pixel na shigarwar CLK zuwa PLL, inda aka ninka ta 5. A wannan mitar, R, G, B bytes ana canza su zuwa bit-biyu. Wannan shine abin da TMDS encoder ke yi. Lambar tushe akan Verilog HDL tayi kama da haka:

module hdmi(
	input wire pixclk,		// 74MHz
	input wire clk_TMDS2,	// 370MHz
	input wire hsync,
	input wire vsync,
	input wire active,
	input wire [7:0]red,
	input wire [7:0]green,
	input wire [7:0]blue,
	output wire TMDS_bh,
	output wire TMDS_bl,
	output wire TMDS_gh,
	output wire TMDS_gl,
	output wire TMDS_rh,
	output wire TMDS_rl
);

wire [9:0] TMDS_red, TMDS_green, TMDS_blue;
TMDS_encoder encode_R(.clk(pixclk), .VD(red  ), .CD({vsync,hsync}), .VDE(active), .TMDS(TMDS_red));
TMDS_encoder encode_G(.clk(pixclk), .VD(green), .CD({vsync,hsync}), .VDE(active), .TMDS(TMDS_green));
TMDS_encoder encode_B(.clk(pixclk), .VD(blue ), .CD({vsync,hsync}), .VDE(active), .TMDS(TMDS_blue));

reg [2:0] TMDS_mod5=0;  // modulus 5 counter
reg [4:0] TMDS_shift_bh=0, TMDS_shift_bl=0;
reg [4:0] TMDS_shift_gh=0, TMDS_shift_gl=0;
reg [4:0] TMDS_shift_rh=0, TMDS_shift_rl=0;

wire [4:0] TMDS_blue_l  = {TMDS_blue[9],TMDS_blue[7],TMDS_blue[5],TMDS_blue[3],TMDS_blue[1]};
wire [4:0] TMDS_blue_h  = {TMDS_blue[8],TMDS_blue[6],TMDS_blue[4],TMDS_blue[2],TMDS_blue[0]};
wire [4:0] TMDS_green_l = {TMDS_green[9],TMDS_green[7],TMDS_green[5],TMDS_green[3],TMDS_green[1]};
wire [4:0] TMDS_green_h = {TMDS_green[8],TMDS_green[6],TMDS_green[4],TMDS_green[2],TMDS_green[0]};
wire [4:0] TMDS_red_l   = {TMDS_red[9],TMDS_red[7],TMDS_red[5],TMDS_red[3],TMDS_red[1]};
wire [4:0] TMDS_red_h   = {TMDS_red[8],TMDS_red[6],TMDS_red[4],TMDS_red[2],TMDS_red[0]};

always @(posedge clk_TMDS2)
begin
	TMDS_shift_bh <= TMDS_mod5[2] ? TMDS_blue_h  : TMDS_shift_bh  [4:1];
	TMDS_shift_bl <= TMDS_mod5[2] ? TMDS_blue_l  : TMDS_shift_bl  [4:1];
	TMDS_shift_gh <= TMDS_mod5[2] ? TMDS_green_h : TMDS_shift_gh  [4:1];
	TMDS_shift_gl <= TMDS_mod5[2] ? TMDS_green_l : TMDS_shift_gl  [4:1];
	TMDS_shift_rh <= TMDS_mod5[2] ? TMDS_red_h   : TMDS_shift_rh  [4:1];
	TMDS_shift_rl <= TMDS_mod5[2] ? TMDS_red_l   : TMDS_shift_rl  [4:1];
	TMDS_mod5 <= (TMDS_mod5[2]) ? 3'd0 : TMDS_mod5+3'd1;
end

assign TMDS_bh = TMDS_shift_bh[0];
assign TMDS_bl = TMDS_shift_bl[0];
assign TMDS_gh = TMDS_shift_gh[0];
assign TMDS_gl = TMDS_shift_gl[0];
assign TMDS_rh = TMDS_shift_rh[0];
assign TMDS_rl = TMDS_shift_rl[0];

endmodule

module TMDS_encoder(
	input clk,
	input [7:0] VD,	// video data (red, green or blue)
	input [1:0] CD,	// control data
	input VDE,  	// video data enable, to choose between CD (when VDE=0) and VD (when VDE=1)
	output reg [9:0] TMDS = 0
);

wire [3:0] Nb1s = VD[0] + VD[1] + VD[2] + VD[3] + VD[4] + VD[5] + VD[6] + VD[7];
wire XNOR = (Nb1s>4'd4) || (Nb1s==4'd4 && VD[0]==1'b0);
wire [8:0] q_m = {~XNOR, q_m[6:0] ^ VD[7:1] ^ {7{XNOR}}, VD[0]};

reg [3:0] balance_acc = 0;
wire [3:0] balance = q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7] - 4'd4;
wire balance_sign_eq = (balance[3] == balance_acc[3]);
wire invert_q_m = (balance==0 || balance_acc==0) ? ~q_m[8] : balance_sign_eq;
wire [3:0] balance_acc_inc = balance - ({q_m[8] ^ ~balance_sign_eq} & ~(balance==0 || balance_acc==0));
wire [3:0] balance_acc_new = invert_q_m ? balance_acc-balance_acc_inc : balance_acc+balance_acc_inc;
wire [9:0] TMDS_data = {invert_q_m, q_m[8], q_m[7:0] ^ {8{invert_q_m}}};
wire [9:0] TMDS_code = CD[1] ? (CD[0] ? 10'b1010101011 : 10'b0101010100) : (CD[0] ? 10'b0010101011 : 10'b1101010100);

always @(posedge clk) TMDS <= VDE ? TMDS_data : TMDS_code;
always @(posedge clk) balance_acc <= VDE ? balance_acc_new : 4'h0;

endmodule

Sa'an nan kuma ana ciyar da nau'i-nau'i na fitarwa zuwa fitowar DDIO, wanda a jere yana samar da sigina-biti ɗaya akan tashi da faɗuwa.

Ana iya siffanta DDIO kanta da lambar Verilog kamar haka:

module ddio(
	input wire d0,
	input wire d1,
	input wire clk,
	output wire out
	);

reg r_d0;
reg r_d1;
always @(posedge clk)
begin
	r_d0 <= d0;
	r_d1 <= d1;
end
assign out = clk ? r_d0 : r_d1;
endmodule

Amma mai yiwuwa ba zai yi aiki haka ba. Kuna buƙatar amfani da Altera's ALTDDIO_OUT megafunction don a zahiri amfani da abubuwan fitarwa na DDIO. A cikin aikina, ana amfani da bangaren laburare ALTDDIO_OUT.

Yana iya yin kama da ɗan wayo, amma yana aiki.

Kuna iya duba duk lambar tushe da aka rubuta a cikin Verilog HDL a nan kan github.

Haɗaɗɗen firmware don FPGA an saka shi cikin guntu EPCS da aka sanya akan allon Mars Rover2rpi. Don haka, lokacin da aka yi amfani da wutar lantarki zuwa allon FPGA, FPGA za ta fara daga ƙwaƙwalwar filasha kuma ta fara.

Yanzu muna buƙatar magana kaɗan game da daidaitawar Rasberi kanta.

Ina yin gwaje-gwaje akan Rasberi PI OS (32 bit) dangane da Debian Buster, Sigar: Agusta 2020,
Ranar fitarwa: 2020-08-20, Sigar Kernel: 5.4.

Kuna buƙatar yin abubuwa biyu:

  • gyara fayil ɗin config.txt;
  • ƙirƙirar saitin uwar garken X don yin aiki tare da masu saka idanu biyu.

Lokacin gyara fayil ɗin /boot/config.txt, kuna buƙatar:

  1. hana amfani da i2c, i2s, spi;
  2. kunna yanayin DPI tare da overlay dtoverlay=dpi24;
  3. saita yanayin bidiyo 1280 × 720 60Hz, 24 ragowa a kowace aya ta DPI;
  4. saka adadin da ake buƙata na framebuffers 2 (max_framebuffers=2, kawai sai na'urar / dev/fb1 ta biyu zata bayyana)

Cikakken rubutun fayil ɗin config.txt yayi kama da wannan.

# For more options and information see
# http://rpf.io/configtxt
# Some settings may impact device functionality. See link above for details

# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1

# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan
disable_overscan=1

# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=16
#overscan_right=16
#overscan_top=16
#overscan_bottom=16

# uncomment to force a console size. By default it will be display's size minus
# overscan.
#framebuffer_width=1280
#framebuffer_height=720

# uncomment if hdmi display is not detected and composite is being output
hdmi_force_hotplug=1

# uncomment to force a specific HDMI mode (this will force VGA)
#hdmi_group=1
#hdmi_mode=1

# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
#hdmi_drive=2

# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
#config_hdmi_boost=4

# uncomment for composite PAL
#sdtv_mode=2

#uncomment to overclock the arm. 700 MHz is the default.
#arm_freq=800

# Uncomment some or all of these to enable the optional hardware interfaces
#dtparam=i2c_arm=on
#dtparam=i2s=on
#dtparam=spi=on

dtparam=i2c_arm=off
dtparam=spi=off
dtparam=i2s=off

dtoverlay=dpi24
overscan_left=0
overscan_right=0
overscan_top=0
overscan_bottom=0
framebuffer_width=1280
framebuffer_height=720
display_default_lcd=0
enable_dpi_lcd=1
dpi_group=2
dpi_mode=87
#dpi_group=1
#dpi_mode=4
dpi_output_format=0x6f027
dpi_timings=1280 1 110 40 220 720 1 5 5 20 0 0 0 60 0 74000000 3

# Uncomment this to enable infrared communication.
#dtoverlay=gpio-ir,gpio_pin=17
#dtoverlay=gpio-ir-tx,gpio_pin=18

# Additional overlays and parameters are documented /boot/overlays/README

# Enable audio (loads snd_bcm2835)
dtparam=audio=on

[pi4]
# Enable DRM VC4 V3D driver on top of the dispmanx display stack
#dtoverlay=vc4-fkms-v3d
max_framebuffers=2

[all]
#dtoverlay=vc4-fkms-v3d
max_framebuffers=2

Bayan haka, kuna buƙatar ƙirƙirar fayil ɗin sanyi don uwar garken X don amfani da masu saka idanu biyu akan framebuffer biyu / dev/fb0 da / dev/fb1:

Fayil ɗin daidaitawa na shine /usr/share/x11/xorg.conf.d/60-dualscreen.conf kamar wannan

Section "Device"
        Identifier      "LCD"
        Driver          "fbturbo"
        Option          "fbdev" "/dev/fb0"
        Option          "ShadowFB" "off"
        Option          "SwapbuffersWait" "true"
EndSection

Section "Device"
        Identifier      "HDMI"
        Driver          "fbturbo"
        Option          "fbdev" "/dev/fb1"
        Option          "ShadowFB" "off"
        Option          "SwapbuffersWait" "true"
EndSection

Section "Monitor"
        Identifier      "LCD-monitor"
        Option          "Primary" "true"
EndSection

Section "Monitor"
        Identifier      "HDMI-monitor"
        Option          "RightOf" "LCD-monitor"
EndSection

Section "Screen"
        Identifier      "screen0"
        Device          "LCD"
        Monitor         "LCD-monitor"
EndSection

Section "Screen"
        Identifier      "screen1"
        Device          "HDMI" 
	Monitor         "HDMI-monitor"
EndSection

Section "ServerLayout"
        Identifier      "default"
        Option          "Xinerama" "on"
        Option          "Clone" "off"
        Screen 0        "screen0"
        Screen 1        "screen1" RightOf "screen0"
EndSection

To, idan ba a riga an shigar ba, to kuna buƙatar shigar da Xinerama. Sannan sararin tebur ɗin zai kasance cikakke cikakke zuwa masu saka idanu biyu, kamar yadda aka nuna a cikin bidiyon demo da ke sama.

Wataƙila wannan duka. Yanzu, masu Raspberry Pi3 za su iya amfani da na'urori biyu.

Bayani da zane na allon Mars Rover2rpi na iya zama gani nan.

source: www.habr.com