Forum: FPGA, VHDL & Co. Mein eigener TFT-Controller


von Franz (Gast)


Lesenswert?

Hallo Leute,
so ich will mich mal, wie der Titel schon sagt, mit einem TFT versuchen.
Und zwar möchte ich gerne einen FPGA einsetzen als Controller. Ich hätte 
hier noch Muster rumliegen von einem Altera Cyclone II.
Für den FPGA wäre es ja kein Problem, alle die notwendigen Signale 
(Pixel Clock, HSync, VSync etc) zu generieren.
Mein FPGA hat zu wenig internen RAM; deshalb würde ich extern mal ein 
SRAM mit 512 kB anschliessen, damit könnte ich dann 2 vollständige 
Bilder speichern (ich möchte 320 x 240 Px, bei 24 Bit).
Also, ansich wäre das ja machbar - mit dem FPGA die Daten aus dem SRAM 
zum TFT schaufeln und das richtige Timing einhalten.
Soweit so gut, nun plagen mich aber noch zwei Fragen, bevor ich mich an 
sowas komplexes wage:

- Wenn man das Gerät einschaltet, dann dauert es ja erst eine gewisse 
Zeit (x Millisekunden), bis der FPGA configuriert ist. Wöhrend dieser 
Zeit kann er ja keine Daten an das Display rausgeben. Die Frage ist 
jetzt, ob das dem Display schadet, wenn es nach dem Power Up jeweils für 
diese kurze Zeit keinen Clock und keine Daten kriegt? Weil, man muss das 
Display ja kontinuierlich takten, sonst zeigt es nichts an und geht 
kaputt.

- Wie könnte ich elegant die Daten, die ich anzeigen möchte, in das SRAM 
bringen? irgend eine Schnittstelle muss das ja noch haben.

Als FPGA möchte ich, wie gesagt, einen Altera Cyclone II einsetzen. 
Eigentlich müsste das ja mit einem EP2C8T144 gehen (solche habe ich 
nämlich einige hier). Der hat 8k LEs.

von Morin (Gast)


Lesenswert?

> Weil, man muss das Display ja kontinuierlich takten, sonst zeigt es
> nichts an und geht kaputt.

Diese Aussage würde ich erstmal prüfen. "Keine Pixelclock" gibt es 
schließlich auch, wenn der Stecker draußen ist. Notfalls ist es sicher 
nicht schwer, einen gezogenen Stecker zu simulieren (Tristate-Treiber), 
wobei das der FPGA in der Config-Phase evtl. eh macht.

> - Wie könnte ich elegant die Daten, die ich anzeigen möchte, in das SRAM
> bringen? irgend eine Schnittstelle muss das ja noch haben.

Hängt von der Anwendung ab. Standbilder? Textmatrix? Textmatrix und 
Sprites? 2d-Rendering? 3d-Rendering?

Bedenke gleichzeitig die max. Übertragungsgeschwindigkeit des Speichers, 
da du gleichzeitig ein dargestelltes Bild auslesen und evtl ein neues 
reinschreiben musst.

von Franz (Gast)


Lesenswert?

Hi Morin,
Also ich möchte grundsätzlich Standbilder anzeigen. Rendering und solche 
Geschichten habe ich nicht vor; es wäre aber doch schon ganz nützlich, 
wenn ich eine ordentliche Bildwiederholrate erzielen könnte (ich sag mal 
so 10..15 Bilder pro Sekunde sollten es schon sein).
Es soll unter anderem Text dargestellt werden; aber auch Grafik (ein 
Diagramm). Text und Diagramm werden von einem Mikroprozessor als Daten 
geliefert, der FPGA muss also wirklich nichts weiter tun, als das Zeug 
im RAM zu speichern und das, was im RAM ist, auf dem Display anzuzeigen 
(vorerst jedenfalls).
Später wäre es natürlich schon praktisch, wenn er z.B. Text selber 
generieren könnte; das interessiert mich im Moment aber nicht wirklich.

Hmm, das mit der Übertragungsgeschwindigkeit ist ein wichtiger 
Knackpunkt. Ich Gedenke, ein SRAM einzusetzen, das 512 kB hat, sowie 
eine Zugriffszeit von 55 ns. Wenn der Pixelclock meines TFT's nominal 
5.33 MHz beträgt, dann entspricht dies einer Periodendauer von 187.6 ns; 
während dieser Zeit muss ich 3 Bytes aus dem Speicher auslesen -> ich 
habe also zum auslesen eines Bytes 62.5 ns Zeit, das sollte ja 
hinkommen. Allerdings kann ich dann nix mehr rein schreiben :-) Mist!
Wäre es evtl. klug, zwei SRAMs zu je 256 kB anzuschliessen, und diese 
abwechslungsweise zu benutzen? Das heisst - erst werden die Daten aus 
dem RAM1 angezeigt; in dieser Zeit kann man RAM2 füllen. Dann wird 
umgeschaltet - RAM2 wird angezeigt, während RAM1 gefüllt wird.
Aber nee - das ist auch Murks.
Ich guck mich gleich nach schnelleren SRAMs um, sowas muss es doch 
geben...

Gruss

von D. I. (Gast)


Lesenswert?

Die SRAM's auf dem Spartan3-Eval Board von Trenz laufen mit 10 ns. Habe 
sie aber mit meinem Controller nur mit max. 20ns ansprechen können, ein 
perfomanten Controller zu schreiben ist recht knifflig

von Franz (Gast)


Lesenswert?

Hallo,
ja mittlerweile habe ich mir auch ein SRAM mit 10ns rausgesucht. Das 
sollte nun also gehen.
Nun mache ich es wie folgt: ich schliesse einen 16 MHz Quarzoszillator 
am FPGA an. Bei jeder Taktflanke wird der Adresszähler fürs RAM um 1 
hochgezählt.
Nach der 1. Taktflanke wird das Datenbyte für R aus dem RAM geholt; eine 
weitere Taktflanke später das Grüne Datenbyte, danach das Blaue, und 
dann wird der Pixelclock generiert. Das sollte so also passen; mein 
beabsichtigtes TFT hat  wie gesagt einen Pixelclock von 5.33 MHz.
Was haltet ihr davon?
Nun muss ich nur noch ne kluge Idee finden, um Daten ins RAM zu 
bekommen. Am liebsten seriell.... Mal schauen. Ideen?

von TheMason (Gast)


Lesenswert?

@franz

ich hab mal vor längerer zeit sowas gemacht. bei mir waren es zwei 
getrennte projekte. zum einen die reine text-darstellung. da brauchst du 
keinen externen speicher. ich hab damals 3 block-rams (ich verwende 
xilinx, die blockrams haben eine größe von 2kB) verwendet. eins als 
char-rom (konnte man aber verändern, da die blockrams alle als dual-port 
ausgelegt sind), eines als text-speicher, und eins als farb-speicher.

die grafik-variante hatte es dann in sich :-))
auf dem spartan-3 board ist 1mb speicher organisiert als 256kx32 
vorhanden. ich habe immer 32 bit eingelesen, 4 pixel ausgegeben, und die 
zwischenzeit dafür genutzt ein byte in den speicher schreiben zu können.
dabei konnte ich entweder von einem mikrocontroller aus in den 
speicher-schreiben, oder aber (und das war das geniale daran) eine 
state-machine im fpga bemühen mir bestimmte grafik-operationen 
durchzuführen. dies waren dann operationen wie blöcke 
kopieren/modifizieren.
ich habe dann von dem mikrocontroller aus einen/mehrere zeichensätze in 
den speicher geschrieben (im nicht sichtbaren bereich) und später dann 
über die gme (so hab ich das teil genannt : graphics memory engine) 
einzelne zeichen  in den sichtbaren bereich kopiert. es gibt dann auch 
noch so operationen wie and/or/xor die sich auf die speicherbereiche 
anwenden lassen, und eben reine füll-operationen. das teil war schon 
recht gut, und der aufwand war relativ gering. einzig und allein das 
timing war was kniffelig, da ich nur mit den 50mhz gearbeitet hab, und 
das doch etwas wenig war, aber es hat funktioniert :-)

das ganze lief dann an einem vga-monitor, sollte aber auf jedem anderen 
tft-display auch lauffähig sein. hab später mal von einem bekannten 2 
tft's bekommen die mit pixclk, vsync und hsync und 9 bit rgb versorgt 
worden sind. und das display hats mir nicht übel genommen wenn da mal 
was nicht stimmte bzw beim einschalten keine signale anlagen.

also wenn du erstmal soweit bist das du daten ins ram schreiben bzw 
davon lesen kannst und gleichzeitig das bild ausgeben kannst ist der 
rest ein kinderspiel.

zum thema geschwindigkeit ein kleiner tipp :

wenn die zeit von deinem ram nicht ausreicht (also bytes auslesen und 
dann beschreiben) : lies einfach mehrere bytes/pixel ein und clocke sie 
dann später raus (so ähnlich hab ich es ja auch gemacht). dadurch 
bekommst du mehr zeit um das ram beschreiben zu können. wenn du 55ns 
rams hast und 62.5 ns zeit -> 7.5 ns übrig / 55ns ~ 8 bytes einlesen um 
eins schreiben zu können, oder aber 2 rams parallel -> 4 bytes einlesen 
um 2 schreiben zu können. (alle angaben ohne gewehr gg)

von Franz (Gast)


Lesenswert?

Hi Mason,
Danke erstmal für deine Erläuterungen!

Schau mal, ich will das Display hier ansteuern:
http://www.hitachi-displays-eu.com/doc/TX09D70VM1CCA.PDF

Ich hab das mit dem RGB-Interface noch nie gemacht, aber mal so als 
Verständnisfrage:
siehst du das auch so, dass ich jeweils die RGB-Daten an das Display 
anlege, und mit DCLK (Dot Clock heisst das hier) in das Display clocke, 
und nach 240 clocks wird mit DTMG (keine Ahnung was das heisst, das DB 
sagt nur "timing signal for data") die Zeile weitergeschaltet.
Und nach 320 Zeilen ne kurze Pause, und danach geht es von vorne in 
Zeile 1, Pixel Nr. 1, los. Richtig?

Viele Grüsse & Dank

von TheMason (Gast)


Lesenswert?

also wenn ich mir das timing so grob angucke passt deine geplante 
vorgehensweise. wichtig ist das du halt horizontal und verikalen sync 
bzw die timings einhälst (also ein paar pixel von jeder zeile als 
horiz.sync, und ein paar zeilen als vert.sync). in der zeit am besten 
die pixeldaten (rgb) alle auf null setzen (hatte da bei der 
vga-ansteuerung schonmal richtig schöne effekte wenn die nicht auf 0 
waren).

noch nen kleinen tipp : (so hab ichs zumindest gemacht)

geb erstmal nur feste muster (z.b. 4x4 oder 8x8 pixelblöcke) aus, um zu 
sehen ob das timing passt. dabei sieht man auch schon direkt schön alle 
darstellbaren farben. den farbwert kannst du dir am besten über die x 
und y zähler generieren lassen, die du später ja eh brauchst um das ram 
zu adressieren. und für das erste erfolgserlebnis sicherlich hilfreich 
:-)

von Franz (Gast)


Lesenswert?

Hi,
danke! die xy-Zähler als Mustergeneratoren zu benutzen ist ne gute Idee 
:-)
meinst du, vom Timing her reicht das dann auch noch, um Bild-Daten ins 
RAM zu schaufeln?
übrigens werde ich wohl einen einfachen 8bit-Datenbus verwenden, der 
FPGA hat genug Pins. Was ich mir nur nicht ganz sicher bin ist, ob die 
8k LEs auch reichen, wenn ich später paar simple Grafikfunktionen 
realisieren möchte (Linie, Kreis, Rechteck, Text). Hast du da vllt. eine 
Ahnung?

gruss

von TheMason (Gast)


Lesenswert?

>die xy-Zähler als Mustergeneratoren zu benutzen ist ne gute Idee

so hab ich die ersten geh-versuche gemacht :-)

>meinst du, vom Timing her reicht das dann auch noch, um Bild-Daten ins
>RAM zu schaufeln?

ich habe bei meinem vga-controller nen pixeltakt von 25 mhz gehabt. also 
ich denke wenn du nen pixeltakt von 5,33 mhz hast dürftest du bei 10ns 
rams looocker zeit haben da was zu machen ... aber nimm dann vllt lieber 
nen schnelleren quarz, vor allem hast du dann die möglichkeit mehr als 
einen schreibzyklus pro pixeltakt zu machen.
generell würd ich das mit dem interface so vorschlagen :
baue dir eine statemachine die ein bzw mehrere bytes in einen puffer 
einliest und dann als pixel ausgibt (ich hab z.b. nur mit 8 bit 
gearbeitet, aber konnte mittels einer farbtabelle (palette) trotzdem 
alle farbwerte erreichen (wenn auch nicht gleichzeitig) ).
in der zeit wo du die pixel ausgibst, die du zwischengespeichert hast, 
kannst du deine ram-zugriffe machen. hier empfiehlt es sich je nachdem 
wieviele zugriffe du pro gelesenem und ausgegebenem buffer-inhalt machen 
kannst, mehrere zugriffe zu machen. so kannst du über ein mikroprozessor 
interface und gleichzeitig über eine kleine grafik-engine (wie ich das 
bei mir gemacht hab) den bild-speicher bearbeiten.
eine grafik-engine würde im einfachsten falle auch aus einer 
state-machine bestehen die dann rechtecke u.s.w. füllt.
funktionen wie kreise oder linien sind sicherlich auch drin, aber das 
hängt davon ab wie groß dein fpga ist. also ich hab meine engine in 
einen spartan-3-200 bekommen und hatte noch einiges an platz ...
aber ich weiß nicht wie weit sich die spartans und die alteras 
vergleichen lassen.
wenn du wie gesagt erstmal soweit bist das du a) nen stehendes bild 
erzeugen kannst b) ein bild aus dem ram darstellen kannst, und 
gleichzeitig dieses ram noch beschreiben kannst (bestenfalls von 
mehreren seiten aus) dann bist du schon sehr weit ...
eine grafik-engine ist zwar nicht in 5 min programmiert, aber wenn man 
sich ein paar gedanken macht ist das ganze recht schnell umgesetzt. ich 
hatte da z.b. 3 adress-generatoren (bei 2 davon hab ich eine 
start-adresse, ein breiten-register und 2 zähler gehabt, damit ließen 
sich virtuelle zeichenflächen erstellen in denen man rummalen konnte, 
und dann später einfach wieder in den sichtbaren bereich verschoben hat)
und eine relativ große statemachine die das ganze dann gesteuert hat.
aber ich habs ohne großartig simulieren zu müssen hinbekommen. es war 
sogar nen mauszeiger als hardware-sprite mit drin :-) (hat aber nicht so 
ganz funktioniert, ist noch nen fehler drin gewesen)

soviel mal als anregung ...

von Franz (Gast)


Lesenswert?

Hi Mason,
Vielen Dank!
Deine Grafik-Engine interessiert mich sehr. Kannst du hierzu mal ein 
paar Codeschnipsel posten? Würde mich sehr interessieren, wie das so 
aussieht bei dir.

Wenn ich dann erst mal so weit bin mit dem TFT-Controller, werde ich, 
sofern Interesse da ist, das hier veröffentlichen oder einen 
Wiki-Artikel bauen. Was meinst du?
TFT-Controller könnte ja auch für die vielen AVR-Bastler hier 
interessant sein; damit kann man schon viele tolle Dinge machen.

Grüsse

von Kest (Gast)


Lesenswert?

Ein Paar Gedanken zu Deinem Vorhaben:
wiso nimmst Du SRAM und nicht SDRAM? Da Du Altera FPGA verwendest ist 
ein SDRAM Controller (für umsonst) mit dem SOPC Builder schnell 
implementiert. Dann hast Du viel Speicher für z.B. mehrere Pages und so 
weiter. Danach baust Du einfach einen AVALON-Master, der die Daten aus 
dem Speicher liest und diese anzeigt. Danach baust Du noch einen 
AVALON-Master, der die Daten über SPI oder was weis ich vom uC nimmt und 
in den Speicher schreibt.

Um Timings zu entspannen brauchst Du Dual-Clock-FIFOs.

Wenn Du erstmal weist, wie man einen AVALON Master baut, dann kannst Du 
sehr schnell solche Projekte aufbauen. Sicherlich ist für Xilinx ein 
ähnliches Vorgehen angesagt, aber da kann ich nichts dazu sagen.
So ein TFT Controller habe ich oft gemacht und dank SOPC braucht man da 
nicht mal eine Stunden (eher weniger) um komplett alles "from scratch" 
zu schreiben.

Schaue Dir den BEispiel VGA-Controller von Altera an -- sehr hilfreich.

Das Linienzeichen und andere Grafikoperationen habe ich mit einem NIOS 
Prozessor gemacht, ist schnell genug und einfach (weil eben in C 
geschrieben).

Grüße,
Kest

von Franz (Gast)


Lesenswert?

Hi,
also so NIOS-Sachen wollte ich eigentlich vermeiden, da ich damit keine 
Erfahrung habe.
Und mit SDRAM habe ich am FPGA auch noch nie was gemacht, ich könnte mir 
vorstellen dass das nicht ganz so einfach ist.....

@TheMason:
kannst du nicht mal bisschen Code von deinem TFT-Controller posten? :D 
würde mich sehr interessieren, wie du das so gemacht hast.
Ich hab schon mal was zusammen gebastelt, was mir erstmal die richtigen 
Timing-Signale (HSYNC, DTMG, DCLK) generiert, das schaut am Oszi soweit 
gut aus. Jetzt muss nur noch diese RAM-Adressiererei dran gebaut werden, 
dann sollte das klappen ;)

Gruss

von TheMason (Gast)


Lesenswert?

@franz

kann ich gerne mal machen, allerdings ist das ganze eh noch ein bissl 
raw (also nicht so gut kommentiert usw) ...
den code vom generieren der signale bzw. das ram adressieren kann ich 
gerne mal posten, funktioniert aber nur auf dem spartan 3 board (bzw. 
wenn du ein 32-bit ram bzw. 2x16-bit rams dran hast)
der code von der memory-engine (also dem füllen bzw. modifzieren von 
blöcken) kann ich auch gerne posten, dieser sollte auch leichter 
anzupassen sein als der code zum generieren der vga-signale, allerdings 
bringt dir dieser code erst etwas wenn du wie gesagt selbst schon in den 
frame-buffer schreiben kannst und gleichzeitig bild dargestellt wird.

ich such dir die sachen mal raus ...

von Kest (Gast)


Angehängte Dateien:

Lesenswert?

NIOS brauchst Du doch gar nicht, sondern verwendest einfach 
SOPC-Builder. Da klickst Du einen SDRAM-Controller rein und das war's. 
Um aus dem Speicher zu lesen oder zu schreiben musst dann sehr wenig 
machen (halt AVALON Master). Wenn Du dann SDRAM nicht verwenden 
möchtest, klikst Du SDRAM Controller weg unf fügst von mir aus SRAM 
Controller ein. Da musst Du keine einzige Zeile Code schreiben.
Mach es Dir doch nicht so schwer :-)

Grüße,
Kest

p.s.: hier ist eine VGA Master Version ohne Kommentar(e). Vielleicht 
kannst Du was davon gebrauchen. Die kannst Du direkt bei SOPC einklinken 
-- Framebuffer ist dann irgendein Speicher ab addresse 0.

von TheMason (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal der VHDL Code von meinem Grafik-Controller. Ist vllt nicht 
alles zu 100% stabil, aber ich wollte es eh nochmal überarbeiten.

von Franz (Gast)


Lesenswert?

Hallo,
vielen dank für den Code.
Ich hab jetzt schon mal ein Schema gezeichnet mit allen nötigen 
Komponenten (FPGA, schnelles SRAM, ein kleiner Mikrocontroller zum 
Steuern & Konfigurieren des FPGA). Das Board habe ich auch begonnen zu 
layouten; dank dem FPGA, wo ich ja die Pinbelegung beliebig wählen kann 
ist das recht einfach. Dennoch habe ich ein "Problem" entdeckt, bin mir 
aber nicht ganz sicher ob es wirklich eines ist.
Und zwar ist die längste Datenleitung vom FPGA zum SRAM ca. 5 cm lang. 
Macht das wohl Probleme, so von wegen Laufzeit oder so?
Dass ich bei so langen Leitungen Terminierung brauche, steht ausser 
Frage.
Ich habe irgendwo mal gelesen, dass die Altera FPGA's interne 
Terminierungswiderstände haben, die man im Quartus II irgendwo 
aktivieren kann, aber ich finde keine entsprechende Option. Wo ist die 
versteckt?

Gruss

von TheMason (Gast)


Lesenswert?

@franz

also bei 5,33 mhz brauchst du dir um leitungslänge und terminierung 
erstmal keine sorgen machen ...
und selbst wenn du das ram mit 20-30 mhz ansprichst dürfte es bei der 
länge keine probleme geben.
im zweifelsfalle einfach ausprobieren. ich hab bei meinen ersten geh 
versuchen mit dem spartan 3 board auch erstmal versucht das ram per uC 
anzusprechen um zu gucken ob meine ram-statemachine richtig 
funktioniert.
so sieht man dann ob da noch ein fehler drin ist (zumindest ansatzweise)

von Falk B. (falk)


Lesenswert?

@  Franz (Gast)

>Und zwar ist die längste Datenleitung vom FPGA zum SRAM ca. 5 cm lang.
>Macht das wohl Probleme, so von wegen Laufzeit oder so?

Nöö. Aber bei schlechter Masseführung kann das klingeln.

>Dass ich bei so langen Leitungen Terminierung brauche, steht ausser
>Frage.

Nööö. Siehe Artikel Wellenwiderstand.

@ TheMason (Gast)

>also bei 5,33 mhz brauchst du dir um leitungslänge und terminierung
>erstmal keine sorgen machen ...
>und selbst wenn du das ram mit 20-30 mhz ansprichst dürfte es bei der
>länge keine probleme geben.

Auch du mein junger Freund solltest dich mit dem Artikel 
Wellenwiderstand befassen. Dann siehst du das Problem wahrscheinlich 
etwas anders.

MFG
Falk

von Franz (Gast)


Lesenswert?

@Falk
Danke.
Masseführung ist kein Problem, ich mache ein 4 Layer Board mit Ground 
Plane, dann sollte das ja passen.

von Michael X. (Firma: vyuxc) (der-michl)


Lesenswert?

Dann mach gleich einen ordentlichen Lagenaufbau. Pi x Daumen sind single 
ended Impedanzen 60R, differentielle 120R.

von Falk B. (falk)


Lesenswert?

@  Michael X. (Firma: vyuxc) (der-michl)

>Dann mach gleich einen ordentlichen Lagenaufbau. Pi x Daumen sind single
>ended Impedanzen 60R, differentielle 120R.

Na dann mal viel Spass beim Autobahnbau auf der vierlagigegn Platine ;-)

von Stefan W. (wswbln)


Lesenswert?

...ein dicker Kern und außen ganz dünne Prepregs, dann geht das schon. 
Ist aber nicht mehr Stangenware (und muß entsprechend bezahlt werden).

von Steffen H. (Gast)


Lesenswert?

Ist ja schon wieder ein weilchen her.. Aber wie ging denn nun dein 
Projekt weiter Franz? Hast du schon erste Erfolge verzeichnen können?

Habe jetzt selber ein Hitachi TFT TX14D12VM1CAA geschenkt bekommen. 
Möchte mir auch gerne einen TFT Controller dafür bauen.

Das TFT funktioniert zwar schon super an einem Sharp LH792525 
Controller, aber ich will mich jetzt nicht erst in die ARM7-Core 
programmierung incl. Tool Chain einarbeiten und doch lieber erst mal bei 
den AVR Controllern bleiben.

Grüße Steffen

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.