Selles videos nĂ€idatakse: Raspberry Pi3 emaplaati, millele on lĂ€bi GPIO-pesa ĂŒhendatud FPGAplaat Marsrover2rpi (Cyclone IV), millele on ĂŒhendatud HDMI monitor. Teine monitor on ĂŒhendatud Raspberry Pi3 standardse HDMI-pesa kaudu. KĂ”ik koos töötab nagu kahes monitorisĂŒsteemis.
JÀtan edasi rÀÀkima, kuidas see on teostatud.
Populaarsel Raspberry Pi3 emaplaadil on GPIO-pesa, mille kaudu saab ĂŒhendada erinevaid laienduspaneele: andureid, LED-e, samm-mootorite juhtmeid ja palju muud. Iga vĂ€ljundi tĂ€pne funktsioon sĂ”ltub pordikonfiguratsioonist. GPIO ALT2 konfiguratsioon vĂ”imaldab pesa lĂŒlitada DPI liidese reĆŸiimi, Display Parallel Interface. On olemas laienduspaneele, mis vĂ”imaldavad VGA monitoride ĂŒhendamist DPI kaudu. Siiski, esiteks ei ole VGA monitorid enam nii laialt levinud kui HDMI ja teiseks on digitaalne liides jĂ€rjest parem kui analoogne. Eriti kuna selliste VGA laienduspaneelide DAC on tavaliselt teostatud R-2-R ahelates ja tihti ei ĂŒleta 6 bitti vĂ€rvi kohta.
ALT2 reĆŸiimis on GPIO-pesa pinside vÀÀrtus jĂ€rgmine:

Olen siin vĂ€rvinud RGB vĂ€ljundid vastavalt punasele, rohelisele ja sinisele vĂ€rvile. Teised olulised signaalid on V-SYNC ja H-SYNC kaitsesignaali signaalid, samuti CLK. CLK sagedus on sagedus, millega piksli vÀÀrtused edastatakse pesasse, see sĂ”ltub valitud videoreĆŸiimist.
Digitaalsete HDMI monitoride ĂŒhendamiseks tuleb DPI liidese signaalid kinni pĂŒĂŒda ja need HDMI-signaalideks muundada. Seda saab teha nĂ€iteks mĂ”ne FPGA ploogiga. TĂ”de on see, et Marsrover2rpi plaat sobib nende eesmĂ€rkide jaoks. TĂ”epoolest, selle plaadi ĂŒhendamise pĂ”hivĂ”imalus spetsiaalse adapteri kaudu nĂ€eb vĂ€lja selline:

See plaat on mĂ”eldud GPIO portide arvu suurendamiseks ja suurema arvu perifeersete seadmete ĂŒhendamiseks Raspberry Pi-le. Samal ajal kasutatakse 4 GPIO signaali selle ĂŒhendamise korral JTAG signaalidena, nii et Raspberry programm saab laadida FPGA tarkvara CPLD-sse. SeetĂ”ttu ei sobi see tavaline ĂŒhendus mulle, kuna kaob 4 DPI signaali. Ănneks on plaadi lisasildidel Raspberry pinoutiga ĂŒhilduvus. Nii et saan plaati pöörata 90 kraadi ja ikka ĂŒhendada seda minu Raspberryga:

Muidugi tuleb kasutada vÀlist JTAG programmeerijat, kuid see ei ole probleem.
Siiski on vĂ€ike probleem. Mitte iga FPGA vĂ€ljund ei saa kasutada kellosignaali sisendina. On vaid mĂ”ned pĂŒhendatud jalad, mida saab nende eesmĂ€rkide jaoks kasutada. Nii et siin juhtus, et GPIO_0 signaal CLK ei jĂ”udnud FPGA sisendisse, mida oleks saanud kasutada kellosignaali sisendina. Nii et pidin ikkagi ĂŒhe juheplaadi peale viskama. Ăhendan GPIO_0 ja signaali KEY[1] plaadil:

NĂŒĂŒd rÀÀgin natuke FPGA projektist. Peamine raskus HDMI signaalide genereerimisel on vĂ€ga kĂ”rged sagedused. Kui vaadata HDMI pistiku pinout'i, siis on nĂ€ha, et RGB signaalid on nĂŒĂŒd jĂ€rjestikused diferentielsignaalid:

Diferentielsignaali kasutamine aitab vĂ”idelda koherentsete hĂ€iretega edastusliinil. Sel juhul muudetakse iga vĂ€rvisignaali algne kaheksabitis muster 10-bitiseks TMDS (Transition-minimized differential signaling). See on spetsiaalne kodeerimismeetod, mille eesmĂ€rgiks on eemaldada signaalist pĂŒsiv komponent ja vĂ€hendada signaalide vahetusi diferentielliinil. Kuna ĂŒhe vĂ€rvibaiti edastamiseks on nĂŒĂŒd jĂ€rjestikusel edastusliinil vaja edastada 10 bitti, siis peab serialiseerija taktsagedus olema 10 korda kĂ”rgem kui pikselite taktsagedus. Kui vĂ”tta nĂ€iteks video reĆŸiim 1280x720 60Hz, siis on selle reĆŸiimi pikselite taktsagedus 74,25MHz. Serialiseerijal peab olema 742,5MHz.
Tavalised FPGA-d on kahjuks selliseks vĂ”imetuks. Siiski on meie Ă”nneks FPGA-del sisemised DDIO vĂ€ljundid. Need vĂ€ljundid on justkui 2-to-1 serialiseerijad. See tĂ€hendab, et nad saavad jĂ€rjepidevalt edastada kahte bitti kellosignaali tĂ”usul ja langusel. Seega vĂ”ib FPGA projektis kasutada mitte 740MHz, vaid 370MHz, kuid peab kasutama DDIO vĂ€ljundeid FPGA-s. 370MHz on juba hĂ€sti saavutatav sagedus. Kahjuks on 1280Ă720 suurus piir. Suuremat eraldusvĂ”imet meie FPGA Cyclone IV-l, mis on paigaldatud Marsrover2rpi plaadile, ei saavutata.
Nii et projektis satuvad pikselite sisendtaktsagedus CLK PLL-i, kus see korrutatakse 5-ga. Sellel sagedusel muudetakse R, G, B baitid bitipaarideks. Selle teeb TMDS kodeerija. Algne kood Verilog HDL-i jaoks nÀeb vÀlja selline:
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 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
SeejĂ€rel edastatakse vĂ€ljundpaaride signaal DDIO vĂ€ljundile, mis edastab jĂ€rjestikuse ĂŒhesuunalise signaali nii tĂ”usul kui ka langusel.
DDIO-d oleks vÔimalik kirjeldada jÀrgmise Verilog'i koodiga:
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;
endmoduleKuid tÔenÀoliselt ei toimi nii. Tuleb kasutada Alternova megafunktsiooni ALTDDIO_OUT, et tegelikult aktiveerida vÀljund DDIO elemendid. Minu projektis kasutatakse just seda raamatukogud komponenti ALTDDIO_OUT.
VÔib-olla nÀeb see kÔik natuke keeruline vÀlja, kuid see töötab.
Kogu Verilog HDL keeles kirjutatud allikakoodi saab vaadata .
Kompileeritud FPGA pĂŒsivara laetakse EPCS kiip, mis on paigaldatud Marsrover 2 rpi plaadile. Nii et kui toide antakse FPGA plaadile, siis FPGAs algatatakse flash-mĂ€lust.
NĂŒĂŒd tuleb rÀÀkida natuke Raspberry seadistamisest.
Katsetan Raspberry PI OS-i (32 bitti), mis pÔhineb Debian Busteril, versioon: August 2020,
VÀljalaskekuupÀev: 2020-08-20, Kerneli versioon: 5.4.
Peab tegema kaks asja:
- toimetama config.txt faili;
- looma X-serveri konfiguratsiooni, et töötada kahe monitoriga.
Faili /boot/config.txt toimetamisel tuleb:
- vĂ€lja lĂŒlitada i2c, i2s, spi kasutamine;
- aktiveerida DPI reĆŸiim dtoverlay=dpi24 overlay abil;
- seada video reĆŸiim 1280Ă720 60Hz, 24 bitti punkti kohta DPI-l;
- mÀÀrata vajalik frame bufferite arv 2 (max_framebuffers=2, ainult siis ilmub teine seade /dev/fb1)
config.txt faili tÀisteksti nÀeb vÀlja selline.
# 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
PĂ€rast seda tuleb luua X-serveri konfiguratsioonifail, et kasutada kahte monitori kahe frame bufferi /dev/fb0 ja /dev/fb1 jaoks:
Minu konfiguratsioonifail /usr/share/x11/xorg.conf.d/60-dualscreen.conf on selline
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
Ja kui Xinerama pole veel installitud, siis tuleb see paigaldada. Siis laieneb töölaua ruum tÀielikult kahe monitori peale, nagu eespool nÀidatud demovideol.
Siin on nĂŒĂŒd kĂ”ik. NĂŒĂŒd saavad ka Raspberry Pi3 omanikud kasutada kahte monitori.
Marsrover2rpi plaadi kirjeldust ja skeemi saab .
Allikas: habr.com
