Dezyèm HDMI pou kontwole Franbwaz Pi3 atravè koòdone DPI ak tablo FPGA


Videyo sa a montre: yon tablo Franbwaz Pi3, ki konekte ak li atravè konektè GPIO a se yon tablo FPGA Mas Rover2rpi (Cyclone IV), ak yon monitè HDMI konekte. Dezyèm monitè a konekte atravè konektè HDMI estanda nan Franbwaz Pi3 la. Tout travay ansanm tankou yon sistèm monitè doub.

Apre sa, mwen pral di w kouman sa a aplike.

Komisyon Konsèy Raspberry Pi3 popilè a gen yon konektè GPIO kote ou ka konekte plizyè kat ekspansyon: detèktè, LED, chofè motè stepper ak plis ankò. Fonksyon egzak chak peny sou yon konektè depann de konfigirasyon pò a. Konfigirasyon GPIO ALT2 pèmèt ou chanje konektè a nan mòd koòdone DPI, Display Parallel Interface. Gen kat ekspansyon pou konekte monitè VGA atravè DPI. Sepandan, premyèman, monitè VGA yo pa komen tankou HDMI, ak dezyèmman, koòdone dijital la se de pli zan pli pi bon pase yon sèl analòg. Anplis, DAC a sou tablo ekspansyon VGA sa yo anjeneral fèt nan fòm lan nan chenn R-2-R e souvan pa plis pase 6 Bits pou chak koulè.

Nan mòd ALT2, broch konektè GPIO yo gen siyifikasyon sa a:

Dezyèm HDMI pou kontwole Franbwaz Pi3 atravè koòdone DPI ak tablo FPGA

Isit la mwen te kolore broch yo RGB nan konektè a wouj, vèt ak ble respektivman. Lòt siyal enpòtan yo se siyal V-SYNC ak H-SYNC, osi byen ke CLK. Frekans revèy CLK la se frekans kote valè pixel yo soti nan konektè a; li depann de mòd videyo ki chwazi a.

Pou konekte yon monitè HDMI dijital, ou bezwen pran siyal DPI nan koòdone a epi konvèti yo nan siyal HDMI. Sa a ka fè, pou egzanp, lè l sèvi avèk kèk kalite tablo FPGA. Kòm li vire soti, tablo a Mas Rover2rpi se apwopriye pou rezon sa yo. An verite, opsyon prensipal la pou konekte tablo sa a atravè yon adaptè espesyal sanble sa a:

Dezyèm HDMI pou kontwole Franbwaz Pi3 atravè koòdone DPI ak tablo FPGA

Yo itilize tablo sa a pou ogmante kantite pò GPIO ak konekte plis aparèy periferik ak Franbwaz la. An menm tan an, 4 siyal GPIO ak koneksyon sa a yo itilize pou siyal JTAG, se konsa ke pwogram nan soti nan Franbwaz ka chaje firmwèr FPGA la nan FPGA la. Poutèt sa, koneksyon estanda sa a pa adapte m '; 4 siyal DPI abandone. Erezman, peny adisyonèl sou tablo a gen yon Pinout Franbwaz-konpatib. Se konsa, mwen ka vire tablo a 90 degre epi toujou konekte li nan Franbwaz mwen an:

Dezyèm HDMI pou kontwole Franbwaz Pi3 atravè koòdone DPI ak tablo FPGA

Natirèlman, ou pral oblije sèvi ak yon pwogramè JTAG ekstèn, men sa a se pa yon pwoblèm.

Gen yon ti pwoblèm toujou. Se pa tout PIN FPGA ka itilize kòm yon opinyon revèy. Gen sèlman kèk broch dedye ki ka itilize pou rezon sa yo. Se konsa, li te tounen soti isit la ke siyal la GPIO_0 CLK pa rive nan opinyon FPGA, ki ka itilize kòm yon opinyon revèy FPGA. Se konsa, mwen toujou te oblije mete yon sèl fil sou echap la. Mwen konekte GPIO_0 ak siyal KLE[1] tablo a:

Dezyèm HDMI pou kontwole Franbwaz Pi3 atravè koòdone DPI ak tablo FPGA

Koulye a, mwen pral di ou yon ti kras sou pwojè a FPGA. Difikilte prensipal la nan génération siyal HDMI se frekans trè wo. Si ou gade pinout konektè HDMI a, ou ka wè ke siyal RGB yo kounye a se siyal diferans seri:

Dezyèm HDMI pou kontwole Franbwaz Pi3 atravè koòdone DPI ak tablo FPGA

Itilizasyon yon siyal diferans pèmèt ou konbat entèferans mòd komen sou liy transmisyon an. Nan ka sa a, kòd orijinal uit-bit chak siyal koulè konvèti nan yon TMDS 10-bit (siyal diferans tranzisyon minimize). Sa a se yon metòd kodaj espesyal pou retire eleman DC nan siyal la epi minimize siyal chanje nan yon liy diferans. Depi 10 Bits kounye a bezwen transmèt sou liy lan seri pou yon byte nan koulè, li sanble ke vitès la revèy serilizer dwe 10 fwa pi wo pase vitès la revèy pixel. Si nou pran egzanp videyo mòd 1280x720 60Hz, Lè sa a, frekans pixel mòd sa a se 74,25 MHz. Serialize a ta dwe 742,5 MHz.

FPGA regilye yo, malerezman, yo pa kapab fè sa. Sepandan, erezman pou nou, FPGA a te bati-an broch DDIO. Sa yo se konklizyon ki deja, kòm li te, seri 2-a-1. Sa vle di, yo ka pwodiksyon de ti sekans sou kwen k ap monte ak tonbe nan frekans revèy la. Sa vle di ke nan yon pwojè FPGA ou ka itilize pa 740 MHz, men 370 MHz, men ou bezwen sèvi ak eleman pwodiksyon DDIO nan FPGA la. Koulye a, 370 MHz se deja yon frekans konplètman possible. Malerezman, mòd 1280x720 se limit la. Yon rezolisyon ki pi wo pa ka reyalize nan Cyclone IV FPGA nou an enstale sou tablo a Mas Rover2rpi.

Se konsa, nan konsepsyon an, frekans pixel D 'CLK ale nan PLL a, kote li miltipliye pa 5. Nan frekans sa a, R, G, B bytes yo konvèti nan pè ti jan. Sa a se sa ankode TMDS la fè. Kòd sous la nan Verilog HDL sanble sa a:

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

Lè sa a, pè yo pwodiksyon yo manje nan pwodiksyon an DDIO, ki sekans pwodui yon siyal yon sèl-ti jan sou kwen yo k ap monte ak tonbe.

DDIO tèt li ta ka dekri ak kòd Verilog sa a:

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

Men, li gen plis chans pa pral travay nan fason sa a. Ou bezwen sèvi ak megafonksyon ALTDDIO_OUT Alter pou aktyèlman pèmèt eleman pwodiksyon DDIO yo. Pwojè mwen an sèvi ak eleman bibliyotèk ALTDDIO_OUT.

Tout bagay sa a ka sanble yon ti kras difisil, men li travay.

Ou ka wè tout kòd sous ekri nan Verilog HDL isit la sou github.

Konpile firmwèr pou FPGA a parèt nan chip EPCS ki enstale sou tablo Mas Rover2rpi a. Kidonk, lè yo aplike pouvwa a nan tablo FPGA, FPGA a pral inisyalize nan memwa flash epi kòmanse.

Koulye a, nou bezwen pale yon ti kras sou konfigirasyon nan Franbwaz nan tèt li.

Mwen fè eksperyans sou Raspberry PI OS (32 bit) ki baze sou Debian Buster, Version:Out 2020,
Dat lage: 2020-08-20, Kernel vèsyon: 5.4.

Ou bezwen fè de bagay:

  • edite fichye a config.txt;
  • kreye yon konfigirasyon sèvè X pou travay avèk de monitè.

Lè w ap modifye fichye /boot/config.txt ou bezwen:

  1. enfim itilizasyon i2c, i2s, spi;
  2. pèmèt mòd DPI lè l sèvi avèk kouvri dtoverlay = dpi24;
  3. konfigirasyon mòd videyo 1280 × 720 60Hz, 24 bits pou chak pixel sou DPI;
  4. espesifye kantite framebuffers ki nesesè yo 2 (max_framebuffers = 2, sèlman lè sa a dezyèm aparèy /dev/fb1 ap parèt)

Tèks konplè fichye config.txt la sanble sa a.

# 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

Apre sa, ou bezwen kreye yon fichye konfigirasyon pou sèvè X la pou itilize de monitè sou de framebuffers /dev/fb0 ak /dev/fb1:

Fichye konfigirasyon mwen an /usr/share/x11/xorg.conf.d/60-dualscreen.conf se tankou sa a

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

Oke, si li pa deja enstale, Lè sa a, ou bezwen enstale Xinerama. Lè sa a, espas Desktop la pral konplètman elaji a de monitè, jan yo montre nan videyo Demo ki pi wo a.

Sa a se pwobableman tout. Koulye a, mèt Franbwaz Pi3 yo pral kapab sèvi ak de monitè.

Ou ka jwenn deskripsyon ak dyagram sikwi tablo Mas Rover2rpi a gade isit la.

Sous: www.habr.com