Videos nĂ€itab: Raspberry Pi3 plaat, millele on lĂ€bi GPIO pesa ĂŒhendatud FPGA plaat Marsrover2rpi (Cyclone IV), millele on ĂŒhendatud HDMI monitor. Teine monitor on ĂŒhendatud lĂ€bi Raspberry Pi3 tavalise HDMI pessa. KĂ”ik koos töötab nagu kahe monitoriga sĂŒsteem.
Edasi rÀÀgin, kuidas see on teostatud.
Populaarsel Raspberry Pi3 plaadil on GPIO pesa, mille kaudu saab ĂŒhendada erinevaid laienduspaldasid: andureid, LED-e, samm-mootorite draivereid ja palju muud. Iga GPIO pesa vĂ€ljundi konkreetne funktsioon sĂ”ltub portide konfiguratsioonist. GPIO ALT2 konfiguratsioon lubab lĂŒlitada pesad DPI liidese reĆŸiimi, Display Parallel Interface. On olemas laiendusplaate VGA monitoride ĂŒhendamiseks lĂ€bi DPI. Kuid esiteks ei ole VGA monitorid enam nii levinud kui HDMI, ja teiseks on digitaalne liides kindlasti parem kui analoogne. Eriti kuna VGA laiendusplaatidel olev DAC on tavaliselt tehtud R-2-R ahelate kujul ja sageli mitte rohkem kui 6 bitti vĂ€rvi kohta.
ALT2 reĆŸiimis on GPIO pesa pinnihte jĂ€rgmised vÀÀrtused:

Siin ma vĂ€rvisin RGB vĂ€ljundite pistiku vastavalt punase, rohelise ja sinise vĂ€rviga. Teised olulised signaalid on V-SYNC ja H-SYNC skaneerimise sĂŒnkroonsignaalid, samuti CLK. CLK taktsagedus on sagedus, millega pikslite vÀÀrtused vĂ€ljundile edastatakse, see sĂ”ltub valitud videoreĆŸiimist.
Digitaalse HDMI monitori ĂŒhendamiseks tuleb pĂŒĂŒda DPI liidese signaale ja muundada need HDMI signaalideks. Selle saab teha nĂ€iteks mĂ”ne FPGA plaadi abil. Selgub, et Marsrover2rpi plaat sobib selleks otstarbeks. TĂ”ele au andes, selle plaadi peamine ĂŒhendusvariant spetsiaalse adapteriga nĂ€eb vĂ€lja selline:

See plaat on mĂ”eldud GPIO portide arvu suurendamiseks ning suurema hulga pĂ©riphĂ©rotehnika seadmete ĂŒhendamiseks Raspberry'ga. Samal ajal kasutatakse sellise ĂŒhenduse korral 4 GPIO signaali JTAG-signaalidena, nii et programm Raspberry'lt saab laadida FPGA pĂŒsivara PLIS-sse. Selle tĂ”ttu ei sobi mul see tavaline ĂŒhendus, kuna 4 DPI signaali jÀÀvad vĂ€lja. Ănneks on plaadil tĂ€iendavad konnektorid, millel on Raspberry'ga ĂŒhilduv pinout. Seega vĂ”in plaadi pöörata 90 kraadi ja ikka veel ĂŒhendada selle oma Raspberry'ga:

Loomulikult tuleb kasutada vÀlist JTAG programmeerijat, kuid see ei ole probleem.
Kuid siiski on ĂŒks vĂ€ike probleem. Mitte iga FPGA vĂ€ljund ei saa kasutada kui kellasignaali sisenemist. On ainult mĂ”ned dedikeeritud pin'id, mida saab selleks kasutada. Siin juhtus samuti niimoodi, et GPIO_0 signaal CLK ei lĂ€he FPGA sisendisse, mis saab olla kellasignaali sisend PLIS. Seega pidin siiski ĂŒhe juhe plaadile viskama. Ăhendame GPIO_0 ja plaadi signaali KEY[1]:

NĂŒĂŒd rÀÀgin natuke projektist PLIS. Peamine keerukus HDMI signaalide vormimisel on vĂ€ga kĂ”rged sagedused. Kui vaadata HDMI pistiku pinne, siis on nĂ€ha, et RGB signaalid on nĂŒĂŒd jĂ€rjestikused diferentsiaal-signaalid:

Diferentsiaalsignaali kasutamine vĂ”imaldab vĂ”idelda modaalsignaalide hĂ€iretega edastusliinil. Sellega muudetakse iga vĂ€rvi signaali algne kaheksa bitti 10-bitiseks TMDS (Transition-minimized differential signaling). See on spetsiaalne kodeerimise meetod, et eemaldada signaalist pĂŒsikomponent ja minimeerida signaalide lĂŒlitusi diferentsiaalliinil. Kuna nĂŒĂŒd peab jĂ€rkjĂ€rgulises edastusliinis edastama ĂŒhe vĂ€rvi jaoks 10 bitti, 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 sagedus 74,25MHz. Serialiseerijal peab olema 742,5MHz.
Tavalised FPGA-de vĂ”imekus ei ole sellele kahjuks piisav. Kuid meie Ă”nneks on FPGA-des sisseehitatud DDIO vĂ€ljundid. Need on vĂ€ljundid, mis toimivad juba mingil mÀÀral 2-k-1 serialiseerijatena. See tĂ€hendab, et nad saavad anda jĂ€rjestikku vĂ€lja kaks bitti kahe tunni taktsagedusel. Seega saab FPGA projektis kasutada mitte 740 MHz, vaid 370 MHz, kuid DDIO vĂ€ljundkomponente tuleb aktiivsena hoida. 370 MHz on juba tĂ€iesti saavutatav sagedus. Kahjuks on 1280Ă720 reĆŸiim piiriks. KĂ”rgemat eraldusvĂ”imet meie FPGA Cyclone IV-l, mis on paigaldatud Mars Rover 2rpi plaadile, ei ole vĂ”imalik saavutada.
Seega, projekti sisendtaktsagedus CLK siseneb PLL-i, kus see korrutatakse 5-ga. Sellel sagedusel muudetakse R, G, B baitideks paarideks bittideks. Seda teeb TMDS kodeerija. Verilog HDL algkood nÀeb vÀlja jÀrgmine:
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
JĂ€rgmine suvepuhkuste mĂ€rk on DDIO vĂ€ljund, mis jĂ€rjestikuliselt saadab ĂŒhe bitise signaali tĂ”usul ja langusel.
DDIO-d vÔiks kirjeldada jÀrgmise Verilog koodi abil:
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 see ei pruugi tÔenÀoliselt töötada. Tuleb kasutada Altera mÊgafunktsiooni ALTDDIO_OUT, et tÔeliselt aktiveerida DDIO vÀljundkomponendid. Minu projektis on kasutusel just see teegikomponent ALTDDIO_OUT.
VÔib-olla nÀeb see kÔik veidi keeruline vÀlja, kuid see tÔepoolest töötab.
Kogu Verilog HDL-s kirjutatud lÀhtekoodi saab vaadata .
Kompileeritud tarkvara FPGA-le laaditakse EPCS kiipisse, mis on paigaldatud Mars Rover 2 rpi plaadile. Sel viisil, kui toide on plaadile ĂŒhendatud, algatatakse FPGA vĂ€lkmĂ€lust ja kĂ€ivitatakse.
NĂŒĂŒd tuleb veidi rÀÀkida Raspberry enda konfiguratsioonist.
Teostan katseid Raspberry PI OS (32 bit) pÔhjal, mis pÔhineb Debian Busteril, versioon: August 2020,
VÀljalaske kuupÀev: 2020-08-20, kernel'i versioon: 5.4.
On vaja teha kaks asja:
- redigeerida faili config.txt;
- luua X serveri konfiguratsioon kahe monitori toetamiseks.
Faili /boot/config.txt redigeerimisel tuleks:
- vĂ€lja lĂŒlitada i2c, i2s, spi kasutamine;
- lubada DPI reĆŸiim dtoverlay=dpi24 abil;
- seada video reĆŸiimiks 1280Ă720 60 Hz, 24 bitti punkti kohta DPI-le;
- mÀÀrata vajalik raamibuffrute arv 2 (max_framebuffers=2, ainult siis kuvatakse teine seade /dev/fb1)
faili config.txt tÀisteksti nÀeb vÀlja niimoodi.
# 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 konfigureerimisfail X-serveri jaoks, et kasutada kahte monitori kahe raamibuffruga /dev/fb0 ja /dev/fb1:
Minu konfigureerimisfail /usr/share/x11/xorg.conf.d/60-dualscreen.conf on selline
Sektsioon "Seade"
Tuvastaja "LCD"
Draiver "fbturbo"
Valik "fbdev" "/dev/fb0"
Valik "ShadowFB" "vÀljas"
Valik "SwapbuffersWait" "tÔene"
LÔppSektsioon
Sektsioon "Seade"
Tuvastaja "HDMI"
Draiver "fbturbo"
Valik "fbdev" "/dev/fb1"
Valik "ShadowFB" "vÀljas"
Valik "SwapbuffersWait" "tÔene"
LÔppSektsioon
Sektsioon "Monitor"
Tuvastaja "LCD-monitor"
Valik "Esmane" "tÔene"
LÔppSektsioon
Sektsioon "Monitor"
Tuvastaja "HDMI-monitor"
Valik "Paremal" "LCD-monitor"
LÔppSektsioon
Sektsioon "Ekraan"
Tuvastaja "ekraan0"
Seade "LCD"
Monitor "LCD-monitor"
LÔppSektsioon
Sektsioon "Ekraan"
Tuvastaja "ekraan1"
Seade "HDMI"
Monitor "HDMI-monitor"
LÔppSektsioon
Sektsioon "ServeriPaigutus"
Tuvastaja "vaikimisi"
Valik "Xinerama" "sisse"
Valik "Kloon" "vÀljas"
Ekraan 0 "ekraan0"
Ekraan 1 "ekraan1" Paremal "ekraan0"
LÔppSektsioon
Kui Xinerama pole veel installitud, siis tuleb see paigaldada. Sellisel juhul laieneb töölaud tÀielikult kahele monitorile, nagu nÀidatud eelnevas demo videos.
See ongi kĂ”ik. NĂŒĂŒd saavad ka Raspberry Pi3 omanikud nautida kahte monitori.
Marsrover2rpi plaadi kirjeldust ja skeemi saab .
Allikas: habr.com
