DPI ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ FPGA ๋ณด๋“œ๋ฅผ ํ†ตํ•ด Raspberry Pi3์— ๋Œ€ํ•œ ๋‘ ๋ฒˆ์งธ HDMI ๋ชจ๋‹ˆํ„ฐ


์ด ๋น„๋””์˜ค๋Š” GPIO ์ปค๋„ฅํ„ฐ๋ฅผ ํ†ตํ•ด FPGA Mars Rover3rpi(Cyclone IV) ๋ณด๋“œ๊ฐ€ ์—ฐ๊ฒฐ๋˜๊ณ  HDMI ๋ชจ๋‹ˆํ„ฐ๊ฐ€ ์—ฐ๊ฒฐ๋œ Raspberry Pi2 ๋ณด๋“œ๋ฅผ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ๋ชจ๋‹ˆํ„ฐ๋Š” ํ‘œ์ค€ Raspberry Pi3 HDMI ์ปค๋„ฅํ„ฐ๋ฅผ ํ†ตํ•ด ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋‘ ํ•จ๊ป˜ ๋“€์–ผ ๋ชจ๋‹ˆํ„ฐ ์‹œ์Šคํ…œ์ฒ˜๋Ÿผ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์Œ์œผ๋กœ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

๋„๋ฆฌ ์‚ฌ์šฉ๋˜๋Š” Raspberry Pi3 ๋ณด๋“œ์—๋Š” ์„ผ์„œ, LED, ์Šคํ…Œํผ ๋ชจํ„ฐ ๋“œ๋ผ์ด๋ฒ„ ๋“ฑ ๋‹ค์–‘ํ•œ ํ™•์žฅ ๋ณด๋“œ๋ฅผ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” GPIO ์ปค๋„ฅํ„ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปค๋„ฅํ„ฐ์— ์žˆ๋Š” ๊ฐ ํ•€์˜ ํŠน์ • ๊ธฐ๋Šฅ์€ ํฌํŠธ ๊ตฌ์„ฑ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. GPIO ALT2 ๊ตฌ์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ปค๋„ฅํ„ฐ๋ฅผ DPI ์ธํ„ฐํŽ˜์ด์Šค ๋ชจ๋“œ์ธ ๋””์Šคํ”Œ๋ ˆ์ด ๋ณ‘๋ ฌ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. DPI๋ฅผ ํ†ตํ•ด VGA ๋ชจ๋‹ˆํ„ฐ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ํ™•์žฅ ๋ณด๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ฒซ์งธ, VGA ๋ชจ๋‹ˆํ„ฐ๋Š” ๋” ์ด์ƒ HDMI๋งŒํผ ์ผ๋ฐ˜์ ์ด์ง€ ์•Š์œผ๋ฉฐ ๋‘˜์งธ, ๋””์ง€ํ„ธ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์•„๋‚ ๋กœ๊ทธ๋ณด๋‹ค ์ข‹์•„์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด๋Ÿฌํ•œ VGA ํ™•์žฅ ์นด๋“œ์˜ DAC๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ R-2-R ์ฒด์ธ ํ˜•ํƒœ๋กœ ๋งŒ๋“ค์–ด์ง€๋ฉฐ ์ข…์ข… ์ƒ‰์ƒ๋‹น 6๋น„ํŠธ๋ฅผ ๋„˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ALT2 ๋ชจ๋“œ์—์„œ GPIO ์ปค๋„ฅํ„ฐ์˜ ํ•€์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์˜๋ฏธ๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.

DPI ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ FPGA ๋ณด๋“œ๋ฅผ ํ†ตํ•ด Raspberry Pi3์— ๋Œ€ํ•œ ๋‘ ๋ฒˆ์งธ HDMI ๋ชจ๋‹ˆํ„ฐ

์—ฌ๊ธฐ์—์„œ๋Š” ์ปค๋„ฅํ„ฐ์˜ RGB ํ•€์„ ๊ฐ๊ฐ ๋นจ๊ฐ„์ƒ‰, ๋…น์ƒ‰ ๋ฐ ํŒŒ๋ž€์ƒ‰์œผ๋กœ ์ฑ„์ƒ‰ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ์ค‘์š”ํ•œ ์‹ ํ˜ธ๋Š” V-SYNC ๋ฐ H-SYNC ์Šค์œ• ๋™๊ธฐ ์‹ ํ˜ธ์™€ CLK์ž…๋‹ˆ๋‹ค. CLK ํด๋ก ์ฃผํŒŒ์ˆ˜๋Š” ํ”ฝ์…€ ๊ฐ’์ด ์ปค๋„ฅํ„ฐ๋กœ ์ถœ๋ ฅ๋˜๋Š” ์ฃผํŒŒ์ˆ˜์ด๋ฉฐ ์„ ํƒํ•œ ๋น„๋””์˜ค ๋ชจ๋“œ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

๋””์ง€ํ„ธ HDMI ๋ชจ๋‹ˆํ„ฐ๋ฅผ ์—ฐ๊ฒฐํ•˜๋ ค๋ฉด DPI ์ธํ„ฐํŽ˜์ด์Šค ์‹ ํ˜ธ๋ฅผ ์บก์ฒ˜ํ•˜์—ฌ HDMI ์‹ ํ˜ธ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด FPGA ๋ณด๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ Mars Rover2rpi ๋ณด๋“œ๊ฐ€ ์ด๋Ÿฌํ•œ ๋ชฉ์ ์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ํŠน์ˆ˜ ์–ด๋Œ‘ํ„ฐ๋ฅผ ํ†ตํ•ด ์ด ๋ณด๋“œ๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ์ฃผ์š” ์˜ต์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

DPI ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ FPGA ๋ณด๋“œ๋ฅผ ํ†ตํ•ด Raspberry Pi3์— ๋Œ€ํ•œ ๋‘ ๋ฒˆ์งธ HDMI ๋ชจ๋‹ˆํ„ฐ

์ด ๋ณด๋“œ๋Š” GPIO ํฌํŠธ ์ˆ˜๋ฅผ ๋Š˜๋ฆฌ๊ณ  ๋ผ์ฆˆ๋ฒ ๋ฆฌ์— ๋” ๋งŽ์€ ์ฃผ๋ณ€ ์žฅ์น˜๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋™์‹œ์— ์ด ์—ฐ๊ฒฐ์ด ์žˆ๋Š” 4๊ฐœ์˜ GPIO ์‹ ํ˜ธ๊ฐ€ JTAG ์‹ ํ˜ธ์— ์‚ฌ์šฉ๋˜๋ฏ€๋กœ ๋ฐฐํฌํŒ์˜ ํ”„๋กœ๊ทธ๋žจ์ด FPGA ํŽŒ์›จ์–ด๋ฅผ FPGA์— ๋กœ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ๋ฌธ์— ์ด๋Ÿฌํ•œ ์ผ๋ฐ˜ ์—ฐ๊ฒฐ์ด ๋‚˜์—๊ฒŒ ์ ํ•ฉํ•˜์ง€ ์•Š๊ณ  4 DPI ์‹ ํ˜ธ๊ฐ€ ๋–จ์–ด์ง‘๋‹ˆ๋‹ค. ์šด ์ข‹๊ฒŒ๋„ ๋ณด๋“œ์˜ ์ถ”๊ฐ€ ๋น—์—๋Š” Raspberry ํ˜ธํ™˜ ํ•€์•„์›ƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณด๋“œ๋ฅผ 90๋„ ํšŒ์ „ํ•˜๊ณ  ์—ฌ์ „ํžˆ ๋‚ด ๋ผ์ฆˆ๋ฒ ๋ฆฌ์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋„๋ก:

DPI ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ FPGA ๋ณด๋“œ๋ฅผ ํ†ตํ•ด Raspberry Pi3์— ๋Œ€ํ•œ ๋‘ ๋ฒˆ์งธ HDMI ๋ชจ๋‹ˆํ„ฐ

๋ฌผ๋ก  ์™ธ๋ถ€ JTAG ํ”„๋กœ๊ทธ๋ž˜๋จธ๋ฅผ ์ด์šฉํ•ด์•ผ ํ•˜๊ฒ ์ง€๋งŒ ์ด๊ฒƒ์€ ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š๋Š”๋‹ค.

์—ฌ์ „ํžˆ ์ž‘์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  FPGA ํ•€์„ ํด๋ก ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ์ด ์šฉ๋„๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ „์šฉ ํ•€์€ ๋ช‡ ๊ฐœ๋ฟ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์—ฌ๊ธฐ์—์„œ GPIO_0 CLK ์‹ ํ˜ธ๊ฐ€ FPGA ํด๋Ÿญ ์ž…๋ ฅ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” FPGA ์ž…๋ ฅ์— ๋„๋‹ฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ด ๋ฐํ˜€์กŒ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ ๋˜‘๊ฐ™์ด ์Šค์นดํ”„์— ํ•˜๋‚˜์˜ ๊ฒŒ์‹œ๋ฌผ์„ ๋˜์ ธ์•ผํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ณด๋“œ์˜ GPIO_0๊ณผ KEY[1] ์‹ ํ˜ธ๋ฅผ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค.

DPI ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ FPGA ๋ณด๋“œ๋ฅผ ํ†ตํ•ด Raspberry Pi3์— ๋Œ€ํ•œ ๋‘ ๋ฒˆ์งธ HDMI ๋ชจ๋‹ˆํ„ฐ

์ด์ œ FPGA์˜ ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•ด ์กฐ๊ธˆ ๋ง์”€๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. HDMI ์‹ ํ˜ธ ํ˜•์„ฑ์˜ ์ฃผ์š” ์–ด๋ ค์›€์€ ๋งค์šฐ ๋†’์€ ์ฃผํŒŒ์ˆ˜์ž…๋‹ˆ๋‹ค. HDMI ์ปค๋„ฅํ„ฐ์˜ ํ•€์•„์›ƒ์„ ๋ณด๋ฉด RGB ์‹ ํ˜ธ๊ฐ€ ์ด์ œ ์ง๋ ฌ ์ฐจ๋™ ์‹ ํ˜ธ์ž„์„ โ€‹โ€‹์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

DPI ์ธํ„ฐํŽ˜์ด์Šค ๋ฐ FPGA ๋ณด๋“œ๋ฅผ ํ†ตํ•ด Raspberry Pi3์— ๋Œ€ํ•œ ๋‘ ๋ฒˆ์งธ HDMI ๋ชจ๋‹ˆํ„ฐ

์ฐจ๋™ ์‹ ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ „์†ก ๋ผ์ธ์˜ ๊ณตํ†ต ๋ชจ๋“œ ๋…ธ์ด์ฆˆ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ๊ฐ ์ƒ‰์ƒ ์‹ ํ˜ธ์˜ ์›๋ž˜ 10๋น„ํŠธ ์ฝ”๋“œ๋Š” 10๋น„ํŠธ TMDS(Transition-minimized Differential Signaling)๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์‹ ํ˜ธ์—์„œ DC ์„ฑ๋ถ„์„ ์ œ๊ฑฐํ•˜๊ณ  ์ฐจ๋™ ๋ผ์ธ์—์„œ ์‹ ํ˜ธ ์ „ํ™˜์„ ์ตœ์†Œํ™”ํ•˜๊ธฐ ์œ„ํ•œ ํŠน์ˆ˜ ์ธ์ฝ”๋”ฉ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์ด์ œ ์ง๋ ฌ ํšŒ์„ ์„ ํ†ตํ•ด ์ƒ‰์ƒ ๋ฐ”์ดํŠธ๋‹น 10๋น„ํŠธ๋ฅผ ์ „์†กํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ์˜ ํด๋ก ์ฃผํŒŒ์ˆ˜๋Š” ํ”ฝ์…€์˜ ํด๋ก ์ฃผํŒŒ์ˆ˜๋ณด๋‹ค 1280๋ฐฐ ๋†’์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋น„๋””์˜ค ๋ชจ๋“œ๊ฐ€ 720x60 74,25Hz์ธ ๊ฒฝ์šฐ ์ด ๋ชจ๋“œ์˜ ํ”ฝ์…€ ์ฃผํŒŒ์ˆ˜๋Š” 742,5MHz์ž…๋‹ˆ๋‹ค. ์ง๋ ฌ ๋ณ€ํ™˜๊ธฐ๋Š” XNUMXMHz์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ถˆํ–‰ํ•˜๊ฒŒ๋„ ๊ธฐ์กด์˜ FPGA๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹คํ–‰์Šค๋Ÿฝ๊ฒŒ๋„ FPGA์—๋Š” DDIO ํ•€์ด ๋‚ด์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์ด๋ฏธ 2-to-1 serializer์ธ ๊ฒฐ๋ก ์ž…๋‹ˆ๋‹ค. ์ฆ‰, ์ƒ์Šน ๋ฐ ํ•˜๊ฐ• ํด๋Ÿญ ์ฃผํŒŒ์ˆ˜๋ฅผ ๋”ฐ๋ผ 740๋น„ํŠธ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ FPGA ํ”„๋กœ์ ํŠธ์—์„œ 370MHz๊ฐ€ ์•„๋‹Œ 370MHz๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ FPGA์—์„œ DDIO ์ถœ๋ ฅ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•จ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ 1280MHz๋Š” ์ด๋ฏธ ๋‹ฌ์„ฑ ๊ฐ€๋Šฅํ•œ ์ฃผํŒŒ์ˆ˜์ž…๋‹ˆ๋‹ค. ์•ˆํƒ€๊น๊ฒŒ๋„ 720ร—2 ๋ชจ๋“œ๊ฐ€ ํ•œ๊ณ„์ž…๋‹ˆ๋‹ค. RoverXNUMXrpi ๋ณด๋“œ์— ์„ค์น˜๋œ FPGA Cyclone IV์—์„œ๋Š” ๋” ๋†’์€ ํ•ด์ƒ๋„๋ฅผ ์–ป์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ํ”„๋กœ์ ํŠธ์—์„œ ์ž…๋ ฅ ํ”ฝ์…€ ์ฃผํŒŒ์ˆ˜ CLK๋Š” PLL์— ๊ณต๊ธ‰๋˜๋ฉฐ ์—ฌ๊ธฐ์— 5๊ฐ€ ๊ณฑํ•ด์ง‘๋‹ˆ๋‹ค. ์ด ์ฃผํŒŒ์ˆ˜์—์„œ R, G, B ๋ฐ”์ดํŠธ๋Š” ๋น„ํŠธ ์Œ์œผ๋กœ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด TMDS ์ธ์ฝ”๋”๊ฐ€ ํ•˜๋Š” ์ผ์ž…๋‹ˆ๋‹ค. Verilog HDL์˜ ์†Œ์Šค ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

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

๊ทธ๋Ÿฐ ๋‹ค์Œ ์ถœ๋ ฅ ์Œ์ด DDIO ์ถœ๋ ฅ์œผ๋กœ ๊ณต๊ธ‰๋˜์–ด ์ƒ์Šน โ€‹โ€‹๋ฐ ํ•˜๊ฐ• ์‹œ XNUMX๋น„ํŠธ ์‹ ํ˜ธ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

DDIO ์ž์ฒด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด Verilog ์ฝ”๋“œ๋กœ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

ํ•˜์ง€๋งŒ ์•„๋งˆ ๊ทธ๋Ÿฐ ์‹์œผ๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ DDIO ์ถœ๋ ฅ ์š”์†Œ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Altera์˜ ALTDDIO_OUT ๋ฉ”๊ฐ€ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ํ”„๋กœ์ ํŠธ์—์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๊ตฌ์„ฑ ์š”์†Œ ALTDDIO_OUT์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

์กฐ๊ธˆ ๊นŒ๋‹ค๋กœ์›Œ ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

Verilog HDL๋กœ ์ž‘์„ฑ๋œ ์ „์ฒด ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์—ฌ๊ธฐ github์—์„œ.

FPGA์šฉ์œผ๋กœ ์ปดํŒŒ์ผ๋œ ํŽŒ์›จ์–ด๋Š” Mars Rover2rpi ๋ณด๋“œ์— ์„ค์น˜๋œ EPCS ์นฉ์— ๋‚ด์žฅ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ FPGA ๋ณด๋“œ์— ์ „์›์ด ๊ณต๊ธ‰๋˜๋ฉด FPGA๊ฐ€ ํ”Œ๋ž˜์‹œ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ดˆ๊ธฐํ™”๋˜๊ณ  ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.

์ด์ œ Raspberry ์ž์ฒด์˜ ๊ตฌ์„ฑ์— ๋Œ€ํ•ด ์กฐ๊ธˆ ์ด์•ผ๊ธฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Debian Buster, ๋ฒ„์ „: 32๋…„ 2020์›”,
์ถœ์‹œ์ผ:2020-08-20, ์ปค๋„ ๋ฒ„์ „:5.4.

๋‹ค์Œ ๋‘ ๊ฐ€์ง€๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

  • config.txt ํŒŒ์ผ์„ ํŽธ์ง‘ํ•ฉ๋‹ˆ๋‹ค.
  • ๋‘ ๋Œ€์˜ ๋ชจ๋‹ˆํ„ฐ์—์„œ ์ž‘๋™ํ•˜๋„๋ก X ์„œ๋ฒ„ ๊ตฌ์„ฑ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

/boot/config.txt ํŒŒ์ผ์„ ํŽธ์ง‘ํ•  ๋•Œ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  1. i2c, i2s, spi์˜ ์‚ฌ์šฉ์„ ๋น„ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค.
  2. ์˜ค๋ฒ„๋ ˆ์ด๋กœ DPI ๋ชจ๋“œ ํ™œ์„ฑํ™” dtoverlay=dpi24;
  3. ๋น„๋””์˜ค ๋ชจ๋“œ ์„ค์ • 1280ร—720 60Hz, DPI๋‹น ํฌ์ธํŠธ๋‹น 24๋น„ํŠธ;
  4. ํ•„์š”ํ•œ ํ”„๋ ˆ์ž„ ๋ฒ„ํผ ์ˆ˜ 2 ์ง€์ •(max_framebuffers=2, ๋‘ ๋ฒˆ์งธ ์žฅ์น˜ /dev/fb1์ด ํ‘œ์‹œ๋จ)

config.txt ํŒŒ์ผ์˜ ์ „์ฒด ํ…์ŠคํŠธ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

# 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

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‘ ๊ฐœ์˜ ํ”„๋ ˆ์ž„ ๋ฒ„ํผ /dev/fb0 ๋ฐ /dev/fb1์—์„œ ๋‘ ๊ฐœ์˜ ๋ชจ๋‹ˆํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด X ์„œ๋ฒ„์— ๋Œ€ํ•œ ๊ตฌ์„ฑ ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ๊ตฌ์„ฑ ํŒŒ์ผ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด /usr/share/x11/xorg.conf.d/60-dualscreen.conf์ž…๋‹ˆ๋‹ค.

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

์Œ, ์•„์ง ์„ค์น˜ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด Xinerama๋ฅผ ์„ค์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์œ„์˜ ๋ฐ๋ชจ ๋น„๋””์˜ค์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด ๋ฐ์Šคํฌํ†ฑ ๊ณต๊ฐ„์ด ๋‘ ๊ฐœ์˜ ๋ชจ๋‹ˆํ„ฐ๋กœ ์™„์ „ํžˆ ํ™•์žฅ๋ฉ๋‹ˆ๋‹ค.

๊ทธ๊ฒŒ ๋‹ค์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ œ Raspberry Pi3 ์†Œ์œ ์ž๋Š” ๋‘ ๊ฐœ์˜ ๋ชจ๋‹ˆํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Mars Rover2rpi ๋ณด๋“œ์˜ ์„ค๋ช… ๋ฐ ๋‹ค์ด์–ด๊ทธ๋žจ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์—ฌ๊ธฐ๋ฅผ ๋ณด์•„๋ผ.

์ถœ์ฒ˜ : habr.com