Å ajÄ video redzams: Raspberry Pi3 plate, kurai caur GPIO savienotÄju ir pievienota FPGA Mars Rover2rpi (Cyclone IV) plate, kurai pievienots HDMI monitors. Otrais monitors ir pievienots, izmantojot standarta Raspberry Pi3 HDMI savienotÄju. Tas viss kopÄ darbojas kÄ divu monitoru sistÄma.
TÄlÄk es jums pastÄstÄ«Å”u, kÄ tas tiek Ä«stenots.
PopulÄrajai Raspberry Pi3 platei ir GPIO savienotÄjs, caur kuru var pieslÄgt dažÄdas paplaÅ”inÄÅ”anas plates: sensorus, LED, pakÄpju motora draiverus un daudz ko citu. Katras savienotÄja tapas Ä«paÅ”Ä funkcija ir atkarÄ«ga no porta konfigurÄcijas. GPIO ALT2 konfigurÄcija ļauj pÄrslÄgt savienotÄju uz DPI interfeisa režīmu Display Parallel Interface. Ir paplaÅ”inÄÅ”anas plates VGA monitoru pievienoÅ”anai, izmantojot DPI. TomÄr, pirmkÄrt, VGA monitori vairs nav tik izplatÄ«ti kÄ HDMI, un, otrkÄrt, digitÄlais interfeiss kļūst labÄks par analogo. TurklÄt Å”Ädu VGA paplaÅ”inÄÅ”anas karÅ”u DAC parasti tiek izgatavots R-2-R Ä·Äžu veidÄ un bieži vien ne vairÄk kÄ 6 biti katrÄ krÄsÄ.
ALT2 režīmÄ GPIO savienotÄja tapÄm ir Å”Äda nozÄ«me:
Å eit es krÄsoju savienotÄja RGB tapas attiecÄ«gi sarkanÄ, zaÄ¼Ä un zilÄ krÄsÄ. Citi svarÄ«gi signÄli ir V-SYNC un H-SYNC slaucÄ«Å”anas sinhronizÄcijas signÄli, kÄ arÄ« CLK. CLK pulksteÅa frekvence ir frekvence, kurÄ pikseļu vÄrtÄ«bas tiek izvadÄ«tas uz savienotÄju, un tas ir atkarÄ«gs no izvÄlÄtÄ video režīma.
Lai pievienotu digitÄlo HDMI monitoru, ir jÄuztver DPI interfeisa signÄli un jÄpÄrvÄrÅ” tie par HDMI signÄliem. To var izdarÄ«t, piemÄram, izmantojot jebkuru FPGA plati. KÄ izrÄdÄ«jÄs, Mars Rover2rpi dÄlis ir piemÄrots Å”im nolÅ«kam. PatiesÄ«bÄ galvenÄ Å”Ä«s plates pievienoÅ”anas iespÄja caur Ä«paÅ”u adapteri izskatÄs Å”Ädi:
Å o plati izmanto, lai palielinÄtu GPIO portu skaitu un pievienotu vairÄk perifÄrijas ierÄ«Äu aveÅu. TajÄ paÅ”Ä laikÄ JTAG signÄliem tiek izmantoti 4 GPIO signÄli ar Å”o savienojumu, lai programma no izplatÄ«Å”anas varÄtu ielÄdÄt FPGA programmaparatÅ«ru FPGA. SakarÄ ar to tik regulÄrs savienojums man neder, izkrÄ«t 4 DPI signÄli. Par laimi, papildu Ä·emmÄm uz dÄļa ir ar Raspberry saderÄ«gs spraudnis. Lai es varÄtu pagriezt dÄli par 90 grÄdiem un joprojÄm savienot to ar savu aveÅu:
Protams, jums bÅ«s jÄizmanto ÄrÄjs JTAG programmÄtÄjs, taÄu tÄ nav problÄma.
JoprojÄm ir neliela problÄma. Ne katru FPGA tapu var izmantot kÄ pulksteÅa ieeju. Å im nolÅ«kam var izmantot tikai dažas Ä«paÅ”as tapas. TÄtad Å”eit izrÄdÄ«jÄs, ka GPIO_0 CLK signÄls nenokļūst FPGA ieejÄ, kuru var izmantot kÄ FPGA pulksteÅa ieeju. TÄpÄc man nÄcÄs uzmest vienu sludinÄjumu uz Å”alles. Es savienoju plates GPIO_0 un KEY[1] signÄlu:
Tagad es jums pastÄstÄ«Å”u nedaudz par projektu FPGA. GalvenÄs grÅ«tÄ«bas HDMI signÄlu veidoÅ”anÄ ir ļoti augstas frekvences. AplÅ«kojot HDMI savienotÄja spraudni, varat redzÄt, ka RGB signÄli tagad ir seriÄlie diferenciÄlie signÄli:
DiferenciÄlÄ signÄla izmantoÅ”ana ļauj tikt galÄ ar kopÄja režīma troksni pÄrvades lÄ«nijÄ. Å ajÄ gadÄ«jumÄ katra krÄsu signÄla sÄkotnÄjais astoÅu bitu kods tiek pÄrveidots par 10 bitu TMDS (minimizÄta pÄrejas diferenciÄlÄ signalizÄcija). Å Ä« ir Ä«paÅ”a kodÄÅ”anas metode, lai noÅemtu lÄ«dzstrÄvas komponentu no signÄla un samazinÄtu signÄla pÄrslÄgÅ”anu diferenciÄlajÄ lÄ«nijÄ. TÄ kÄ tagad ir 10 biti, kas jÄpÄrraida uz vienu krÄsas baitu pa seriÄlo lÄ«niju, izrÄdÄs, ka serializÄtÄja takts frekvencei jÄbÅ«t 10 reizes lielÄkai par pikseļu takts frekvenci. Ja Åemam, piemÄram, video režīmu 1280x720 60Hz, tad Ŕī režīma pikseļu frekvence ir 74,25MHz. Serializatoram jÄbÅ«t 742,5 MHz.
DiemžÄl parastie FPGA parasti to nespÄj. TomÄr mÅ«su veiksmei FPGA ir iebÅ«vÄtas DDIO tapas. Tie ir secinÄjumi, kas jau it kÄ ir serializÄtÄji 2 pret 1. Tas nozÄ«mÄ, ka tie var izvadÄ«t divus bitus pÄc kÄrtas pa pieaugoÅ”Äm un krÄ«toÅ”Äm pulksteÅa frekvencÄm. Tas nozÄ«mÄ, ka FPGA projektÄ jÅ«s varat izmantot nevis 740 MHz, bet 370 MHz, bet jums ir jÄizmanto DDIO izvades elementi FPGA. Å eit 370 MHz jau ir diezgan sasniedzama frekvence. DiemžÄl 1280 Ć 720 režīms ir ierobežojums. AugstÄku izŔķirtspÄju nevar sasniegt ar mÅ«su FPGA Cyclone IV, kas uzstÄdÄ«ts uz Rover2rpi plates.
TÄtad projektÄ ievades pikseļu frekvence CLK tiek ievadÄ«ta PLL, kur to reizina ar 5. Å ajÄ frekvencÄ R, G, B baiti tiek pÄrvÄrsti bitu pÄros. To dara TMDS kodÄtÄjs. Verilog HDL avota kods izskatÄs Å”Ädi:
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
PÄc tam izejas pÄri tiek ievadÄ«ti DDIO izejÄ, kas secÄ«gi rada viena bita signÄlu pieauguma un krituma laikÄ.
DDIO paÅ”u var aprakstÄ«t ar Verilog kodu Å”Ädi:
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
Bet droÅ”i vien tas nedarbosies tÄ. Lai faktiski izmantotu DDIO izvades elementus, jums ir jÄizmanto Altera ALTDDIO_OUT megafunkcija. ManÄ projektÄ tiek izmantots bibliotÄkas komponents ALTDDIO_OUT.
Tas viss var izskatīties nedaudz sarežģīti, bet tas darbojas.
Varat skatīt visu Verilog HDL rakstīto avota kodu
ApkopotÄ programmaparatÅ«ra FPGA ir iegulta EPCS mikroshÄmÄ, kas uzstÄdÄ«ta uz Mars Rover2rpi plates. TÄdÄjÄdi, kad FPGA platei tiek pieslÄgta strÄva, FPGA tiks inicializÄts no zibatmiÅas un sÄksies.
Tagad mums nedaudz jÄparunÄ par paÅ”a Raspberry konfigurÄciju.
Es veicu eksperimentus ar Raspberry PI OS (32 bitu), pamatojoties uz Debian Buster, versija: 2020. gada augusts,
IzlaiŔanas datums: 2020-08-20, Kodola versija: 5.4.
Jums ir jÄdara divas lietas:
- rediÄ£Ät failu config.txt;
- izveidot X servera konfigurÄciju darbam ar diviem monitoriem.
RediÄ£Äjot failu /boot/config.txt, jums ir nepiecieÅ”ams:
- atspÄjot i2c, i2s, spi lietoÅ”anu;
- iespÄjot DPI režīmu ar pÄrklÄjumu dtoverlay=dpi24;
- iestatÄ«t video režīmu 1280Ć720 60Hz, 24 biti uz punktu vienÄ DPI;
- norÄdiet nepiecieÅ”amo kadru buferu skaitu 2 (max_framebuffers=2, tikai tad parÄdÄ«sies otrÄ ierÄ«ce /dev/fb1)
Pilns faila config.txt teksts izskatÄs Å”Ädi.
# 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Äc tam jums ir jÄizveido konfigurÄcijas fails X serverim, lai izmantotu divus monitorus divos kadru buferos /dev/fb0 un /dev/fb1:
Mans konfigurÄcijas fails ir /usr/share/x11/xorg.conf.d/60-dualscreen.conf kÄ Å”is
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
Nu, ja vÄl nav instalÄts, tad jums ir jÄinstalÄ Xinerama. PÄc tam darbvirsmas vieta tiks pilnÄ«bÄ paplaÅ”inÄta lÄ«dz diviem monitoriem, kÄ parÄdÄ«ts iepriekÅ” esoÅ”ajÄ demonstrÄcijas videoklipÄ.
Tas laikam arÄ« viss. Tagad Raspberry Pi3 Ä«paÅ”nieki varÄs izmantot divus monitorus.
Mars Rover2rpi dÄļa apraksts un diagramma var bÅ«t
Avots: www.habr.com