Kormeeraha labaad ee HDMI ee Raspberry Pi3 iyada oo loo sii marayo interface DPI iyo guddiga FPGA


Fiidiyowgaan wuxuu muujinayaa: looxa Raspberry Pi3, oo ku xiran xiriiriyaha GPIO waa guddiga FPGA Mars Rover2rpi (Cyclone IV), kaas oo kormeeraha HDMI uu ku xiran yahay. Kormeeraha labaad wuxuu ku xiran yahay isku xirka HDMI caadiga ah ee Raspberry Pi3. Wax kastaa waxay u wada shaqeeyaan sida nidaamka kormeerka laba-geesoodka ah.

Marka xigta waxaan kuu sheegi doonaa sida tan loo fuliyo.

Boodhka caanka ah ee Raspberry Pi3 waxa uu leeyahay xidhiidhiyaha GPIO kaas oo aad ku xidhi karto kaadhadhka ballaadhinta ee kala duwan: dareemayaasha, LED-yada, darawalada mootooyinka iyo qaar kaloo badan. Shaqada saxda ah ee biin kasta oo ku xiran xiriiriyaha waxay ku xiran tahay qaabka dekedda. Qaabeynta GPIO ALT2 waxay kuu ogolaaneysaa inaad isku xiraha u beddesho qaabka interface DPI, Bandhig Isbarbardhigga. Waxaa jira kaarar balaadhin ah oo loogu xidhayo kormeerayaasha VGA iyada oo loo sii marayo DPI. Si kastaba ha ahaatee, marka hore, kormeerayaasha VGA hadda uma badna sida HDMI, iyo marka labaad, interface-ka dhijitaalka ah ayaa si sii kordheysa uga fiican midka analoogga ah. Intaa waxaa dheer, DAC ee looxyada ballaarinta VGA ee noocan oo kale ah waxaa badanaa lagu sameeyaa qaabka silsiladaha R-2-R oo inta badan aan ka badnayn 6 bits halkii midab.

Habka ALT2, biinanka isku xirka GPIO waxay leeyihiin macnaha soo socda:

Kormeeraha labaad ee HDMI ee Raspberry Pi3 iyada oo loo sii marayo interface DPI iyo guddiga FPGA

Halkan waxaan ku midabeeyay biinanka RGB ee xiriiriyaha casaan, cagaar iyo buluug siday u kala horreeyaan. Calaamadaha kale ee muhiimka ah waa calaamadaha V-SYNC iyo H-SYNC, iyo sidoo kale CLK. Inta jeer ee saacada CLK waa inta jeer ee ay qiyamka pixel u soo saaraan isku xirka; waxay kuxirantahay qaabka fiidiyowga ee la doortay.

Si aad ugu xidho kormeeraha HDMI dhijitaalka ah, waxaad u baahan tahay inaad qabsato calaamadaha DPI ee is-dhexgalka oo aad u beddesho calaamadaha HDMI. Tan waxaa la samayn karaa, tusaale ahaan, iyadoo la isticmaalayo nooc ka mid ah guddiga FPGA. Sida ay soo baxday, guddiga Mars Rover2rpi ayaa ku habboon ujeedooyinkan. Run ahaantii, ikhtiyaarka ugu weyn ee isku xirka boodhkan iyada oo loo marayo adabtarada gaarka ah waxay u egtahay sidan:

Kormeeraha labaad ee HDMI ee Raspberry Pi3 iyada oo loo sii marayo interface DPI iyo guddiga FPGA

Boodhkan waxa loo isticmaalaa in lagu kordhiyo tirada dekedaha GPIO iyo in lagu xidho aalado badan oo durugsan raspberry-ga. Isla mar ahaantaana, 4 calaamadaha GPIO ee xidhiidhkan leh ayaa loo isticmaalaa calaamadaha JTAG, si barnaamijka Raspberry uu ugu shubo FPGA firmware FPGA. Sababtan awgeed, xidhiidhkan caadiga ahi iguma habboona; 4 calaamadaha DPI way baxaan. Nasiib wanaag, shanlooyinka dheeraadka ah ee sabuuraddu waxay leeyihiin pinout ku habboon Raspberry. Markaa waxaan u rogi karaa looxa 90 digrii oo wali waxaan ku xidhi karaa raspberry-kayga:

Kormeeraha labaad ee HDMI ee Raspberry Pi3 iyada oo loo sii marayo interface DPI iyo guddiga FPGA

Dabcan, waa inaad isticmaashaa barnaamijka JTAG ee dibadda ah, laakiin tani dhibaato maaha.

Weli dhib yar baa jirta. Biin kasta oo FPGA ah looma isticmaali karo gelinta saacadda. Waxaa jira biinno gaar ah oo yar oo loo isticmaali karo ujeedooyinkan. Markaa waxa halkan ka soo baxay in calaamada GPIO_0 CLK aanay gaadhin gelinta FPGA, taas oo loo isticmaali karo gelinta saacada FPGA. Markaa weli waxay ahayd inaan hal silig dul dhigo shaadhka. Waxaan isku xiraa GPIO_0 iyo calaamada KEY ee guddiga:

Kormeeraha labaad ee HDMI ee Raspberry Pi3 iyada oo loo sii marayo interface DPI iyo guddiga FPGA

Hadda waxaan wax yar kaaga sheegi doonaa mashruuca FPGA. Dhibaatada ugu weyn ee soo saarista calaamadaha HDMI waa soo noqnoqoshada aad u sarreeya. Haddii aad eegto pinout xiriiriyaha HDMI, waxaad arki kartaa in calaamadaha RGB ay hadda yihiin calaamado kala duwan:

Kormeeraha labaad ee HDMI ee Raspberry Pi3 iyada oo loo sii marayo interface DPI iyo guddiga FPGA

Isticmaalka calaamad ka duwan waxay kuu ogolaaneysaa inaad la dagaallanto faragelinta habka caadiga ah ee khadka gudbinta. Xaaladdan oo kale, koodka siddeed-bit ee asalka ah ee calaamad kasta oo midab ah ayaa loo beddelaa 10-bit TMDS (calaamadaha kala-soocidda-yar-yar ee kala-guurka). Kani waa hab kood gaar ah si looga saaro qaybta DC ee calaamada oo la yareeyo beddelka signalka ee xariiq kala duwan. Maadaama 10 bits hadda loo baahan yahay in lagu kala qaado xariiqda taxanaha ah ee hal bayt oo midab ah, waxaa soo baxday in xawaaraha saacadda serializer uu 10 jeer ka sarreeyo xawaaraha saacadda pixel. Haddii aan tusaale ahaan u soo qaadanno qaabka muuqaalka 1280x720 60Hz, markaa xajmiga pixel ee qaabkani waa 74,25 MHz. Serializer-ku waa inuu ahaado 742,5 MHz.

FPGA-yada joogtada ah, nasiib darro, ma awoodaan tan. Si kastaba ha ahaatee, nasiib wanaag anaga, FPGA waxay leedahay biinanka DDIO ee ku dhex-yaalla. Kuwani waa gabagabo kuwaas oo horeyba u ahaa, sida ay ahaayeen, 2-ilaa-1 taxaneyaal. Taasi waa, waxay soo saari karaan laba qaybood oo isku xiga oo kor u kacaya iyo geesaha dhacaya ee inta jeer ee saacadda. Tani waxay ka dhigan tahay in mashruuca FPGA aadan isticmaali karin 740 MHz, laakiin 370 MHz, laakiin waxaad u baahan tahay inaad isticmaasho walxaha wax soo saarka DDIO ee FPGA. Hadda 370 MHz horeba waa soo noqnoqoshada gebi ahaanba la gaari karo. Nasiib darro, qaabka 1280x720 waa xadka. Xallin sare laguma gaadhi karo Cyclone IV FPGA ee ku rakiban sabuuradda Mars Rover2rpi.

Sidaa darteed, naqshadeynta, soo noqnoqda pixel-ka CLK wuxuu tagayaa PLL, halkaas oo lagu dhufto 5. Inta jeer, R, G, B bytes waxaa loo rogaa laba-labbo. Tani waa waxa TMDS codeerku sameeyo. Koodhka isha ee Verilog HDL wuxuu u eg yahay sidan:

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

Kadibna lamaanaha wax soo saarka waxaa lagu quudiyaa wax soo saarka DDIO, kaas oo si isdaba joog ah u soo saara calaamad hal-bit ah geesaha kor u kacaya iyo kuwa dhacaya.

DDIO lafteeda waxaa lagu sifayn karaa koodka Verilog ee soo socda:

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

Laakiin waxay u badan tahay inaysan sidaas u shaqeyn doonin. Waxaad u baahan tahay inaad isticmaasho Alter's megafunction ALTDDIO_OUT si aad dhab ahaantii awood ugu siiso walxaha wax soo saarka DDIO. Mashruucaygu waxa uu isticmaalaa ALTDDIO_OUT qaybta maktabadda.

Waxaas oo dhami waxay u ekaan karaan wax dhib yar, laakiin way shaqeysaa.

Waxaad arki kartaa dhammaan koodka isha ee ku qoran Verilog HDL halkan github.

Firmware-ka la soo ururiyey ee FPGA waxa lagu shiday chip EPCS oo ku rakiban sabuuradda Mars Rover2rpi. Markaa, marka korantada lagu dabaqo guddiga FPGA, FPGA waxa laga soo bilaabayaa xusuusta flashka oo waxa ay bilaabmaysaa.

Hadda waxaan u baahanahay inaan wax yar ka hadalno qaabeynta Raspberry lafteeda.

Waxaan sameynayaa tijaabooyin ku saabsan Raspberry PI OS (32 bit) oo ku saleysan Debian Buster, Nooca: Agoosto 2020,
Taariikhda la sii daayo: 2020-08-20, nooca Kernel: 5.4.

Waxaad u baahan tahay inaad sameyso laba shay:

  • wax ka beddel faylka config.txt;
  • samee qaabaynta server-ka X si aad ula shaqeyso laba kormeerayaal.

Markaad tafatirto faylka /boot/config.txt waxaad u baahan tahay:

  1. joojiso isticmaalka i2c, i2s, spi;
  2. awood habka DPI adoo isticmaalaya dulsaar dtoverlay=dpi24;
  3. habaynta qaabka muuqaalka 1280Γ—720 60Hz, 24 bits per pixel on DPI;
  4. cadee tirada loo baahan yahay ee framebuffers 2 (max_framebuffers=2, kaliya markaas ayaa aaladda labaad /dev/fb1 soo muuqan doonta)

Qoraalka buuxa ee faylka config.txt wuxuu u eg yahay sidan.

# 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

Taas ka dib, waxaad u baahan tahay inaad abuurto faylka qaabeynta ee server-ka X si uu u isticmaalo laba kormeerayaal laba framebuffers / dev / fb0 iyo / dev / fb1:

Faylkayga qaabeynta /usr/share/x11/xorg.conf.d/60-dualscreen.conf waa sidan oo kale

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

Waa hagaag, haddii aan hore loo rakibin, markaa waxaad u baahan tahay inaad ku rakibto Xinerama. Markaa booska desktop-ka ayaa si buuxda loogu balaadhin doonaa laba kormeerayaal, sida ka muuqata muuqaalka muuqaalka kore.

Malaha waa intaas. Hadda, mulkiilayaasha Raspberry Pi3 waxay awoodi doonaan inay isticmaalaan laba kormeerayaal.

Sharaxaada iyo jaantuska wareegga guddiga Mars Rover2rpi waa la heli karaa halkan ka eeg.

Source: www.habr.com