Hallo,
ich habe gestern mein VGA Projekt wieder ausgekramt und wollte mal
wieder etwas daran weiter arbeiten (das lag jetzt eine ganze Weile).
Aber irgendwie funktioniert das nicht....ich möchte den Bildschirm
einfach einfarbig machen...
Wo steckt der Fehler im Code?
Die Komponente "System" ist ein RAM + Clock Manager für den VGA Takt.
VGA Top
Kampi schrieb:> Hallo,>> ich habe gestern mein VGA Projekt wieder ausgekramt und wollte mal> wieder etwas daran weiter arbeiten (das lag jetzt eine ganze Weile).> Aber irgendwie funktioniert das nicht....ich möchte den Bildschirm> einfach einfarbig machen...> Wo steckt der Fehler im Code?
Der fehler steckt erst mal in deiner Vorgehensweise:
-Es fehlt eine genaue Beschreibung des Fehlerbildes - Was passiert am
Monitor
-Es fehlt eine Simulation.
So mit drüberschauen hab ich nicht erkennen wann welche synxs wie lange
aktiv sind und ob im nicht sichtbaren Feld die Daten auch auf 0 gezogen
werden.
Besser ist IMHO zwei counter für horizontal und vertikal durchlaufen
lassen und dann mit komperatoren syncs und enable zu setzen.
MfG,
Hallo,
danke für die Antworten.
Also zum Fehlerbild:
Ich habe einen kleinen 640x480 Monitor den ich an das FPGA anschließe.
Sobald kein Kabel angeschlossen ist, gibt er eine Meldung "No Signal"
aus....diese verschwindet beim FPGA, aber der Monoitor bleibt schwarz.
Daraufhin habe ich mit meinem LA mal HS und VS durchgemessen und die
Signale laufen und auch die Timings stimmen.
Es kann daher eigentlich nur an den Farben liegen (ich probiere mal
zweifarbig).
Was meinst du genau mit den zwei Countern?
Im Moment habe ich es ja so gelöst, dass ein Counter das Zählen
übernimmt und dann mit Hilfe zweier Vergleichswerte die Synchs
geschaltet werden (VGA-Controller ist für das Timing da....VGA Top soll
die Farben darstellen - im Idealfall aus dem RAM :) ).
Fpga Kuechle schrieb:> -Es fehlt eine Simulation.
Das würde ich auch sagen. Denn gerade so ein unidirektionales Interface
wie hier ist doch in Sekundenschnelle wenigstens bis zur Waveform
simuliert: Takt anlegen und zuschauen. Dann sieht man blitzschnell, ob
die Timings grundlegend passen...
BTW: du hattest das Zeug im Beitrag "Kein Bild bei eigenem VGA"
doch schon am Laufen. Warum geht das nicht mehr?
Du musst das Farbsignal während der Austastlücken unbedingt auf 0
setzen.
Bei aktuellen Monitoren kann man im OSD nachschauen was für eine
Auflösung erkannt wurde. Steht dort was?
Mike schrieb:> Du musst das Farbsignal während der Austastlücken unbedingt auf 0> setzen.>> Bei aktuellen Monitoren kann man im OSD nachschauen was für eine> Auflösung erkannt wurde. Steht dort was?
Ah der Tipp ist gut....
Bei dem Monitor handelt es sich um einen VGA/LVDS Konverter +
Display...da habe ich leider nicht die entsprechende Platine mit Knöpfen
um das zu sehen.
Btw...ich versuche gerade das ganze zu simulieren, bekomme bei VSync und
HSync die ganze Zeit nur ein "U" im Simulator (hab erst einmal nur den
VGA-Controller für die Timings).
Da ich gestern mit dem LA gemessen habe weiß ich, dass es
funktioniert....aber warum nicht in der Simulation?
Edit:
Problem gefunden.... -.-
Der Simulator hat die längere Simulationszeit nicht akzeptiert :D
Anbei die Screenshots der Simulation vom Controller
Daniel K. schrieb:> Mike schrieb:>> Du musst das Farbsignal während der Austastlücken unbedingt auf 0>> setzen.>>>> Bei aktuellen Monitoren kann man im OSD nachschauen was für eine>> Auflösung erkannt wurde. Steht dort was?>> Ah der Tipp ist gut....> Bei dem Monitor handelt es sich um einen VGA/LVDS Konverter +> Display...da habe ich leider nicht die entsprechende Platine mit Knöpfen> um das zu sehen.>> Btw...ich versuche gerade das ganze zu simulieren, bekomme bei VSync und> HSync die ganze Zeit nur ein "U" im Simulator (hab erst einmal nur den> VGA-Controller für die Timings).> Da ich gestern mit dem LA gemessen habe weiß ich, dass es> funktioniert....aber warum nicht in der Simulation?>> Edit:> Problem gefunden.... -.-> Der Simulator hat die längere Simulationszeit nicht akzeptiert :D> Anbei die Screenshots der Simulation vom Controller
Sorry Timings sind auf den Screens falsch...
VSync: 16,7047ms, Breite Low Level: 63,597us
HSync: 35,632us, Breite Low Level: 3,813us
Hallo,
ich habe gestern noch mal die Timins gecheckt...sowohl in der Simulation
als auch in der Hardware. Beide waren für einen 640x480 Monitor in
Ordnung.
Jetzt will ich einfach eine Farbe am Monitor ausgeben....:
Ich habe jetzt auch mal einen anderen Monitor genommen
(testweise)...dort ist das selbe Verhalten zu erkennen...es passiert
nichts....keine Farben, nur die Meldung "No Signal" verschwindet :/
Wie ist bei dir RGB aufgeteilt?
Bei meinem DE0 ist es zb:
red : OUT STD_LOGIC_VECTOR(3 downto 0);
green : OUT STD_LOGIC_VECTOR(3 downto 0);
blue : OUT STD_LOGIC_VECTOR(3 downto 0);
Meine Abfrage für ein Farbkästchen zb:
if Counterx >=230 and Counterx < 245 then
if Countery >=20 and Countery < 40 then
red <="0011";
blue <="0011";
green <="0011";
Gruss
Ok! Ich habe es hinbekommen.
Ich habe noch mal den VGA-Controller simuliert, die Timings gecheckt,
paar kleine Änderungen vorgenommen und dann das Top Design simuliert.
Wie sich herausgestellt hat, hat der Core nicht die x und y Koordinaten
hochgezählt, da ich die Bedingung vor dem Hochzählen immer vorher zurück
gesetzt habe.
Danke für die Hilfe! Es war zudem eine schöne Übung für den
Simulator....und wie ich gesehen habe mag der Simulator keinen DCM, da
ich immer keinen Takt hatte sobald dieser im Design war.
Daniel K. schrieb:> wie ich gesehen habe mag der Simulator keinen DCM, da> ich immer keinen Takt hatte sobald dieser im Design war.
Du mußt möglicherweise die Zeitauflösung des Simulators auf ps
(Picosekunden) stellen, damit die DCm richtig simuliert wird.
Duke
Lothar Miller schrieb:> Diese beiden Zähler würde ich sowieso als Integer> ausführen, damit diese Umwandlungsorgie entfällt:
Oder einfach das to_integer weglassen.
Rechnen kann man auch mit unsigned.
Josef G. schrieb:> Lothar Miller schrieb:>> Diese beiden Zähler würde ich sowieso als Integer>> ausführen, damit diese Umwandlungsorgie entfällt:>> Oder einfach das to_integer weglassen.> Rechnen kann man auch mit unsigned.
Ich habe nun einfach einen Integer genommen :)
Funktioniert genau so gut
Josef G. schrieb:> Oder einfach das to_integer weglassen.> Rechnen kann man auch mit unsigned.
Bringt nichts, denn der Vergleich ist dann genauso unleserlich:
Hallo,
so ich habe gestern noch etwas weiter gewerkelt...
Mittlerweile läuft der Core richtig gut...Timing Probleme sind alle
behoben und ich kann über Positionen zwischen 0-79 und 0-59 die Position
des Zeichens auf dem Monitor angeben.
Ein FONT-Rom ist auch weitestgehend vorhanden und ich bin schon in der
Lage Buchstaben und Zahlen auszugeben.
Leider sind das erst einzelne Zahlen und Buchstaben.
Ich möchte nun mal zusammenhängende Zahlen und Worte (z.B. ein "Hello
World") ausgeben.
Da muss ich ja einfach nur Zeichen x ausgeben, Zähler inkrementieren,
Zeichen x+1 an Position+1 ausgeben, etc.
Das ganze wollte ich mal für die Buchstabenkombi "ABCD" probieren:
Die Buchstaben sind nach ASCII-Wert in meinem ROM hinterlegt, sprich 65
ist A etc.
Clock_1 ist einfach ein 1Hz Takt (etwa 1Hz :) ).
Leider wird mir auf dem Bildschirm nur der Buchstabe "A" angezeigt.
Ich gehe mal davon aus, dass ich die Schleife falsch benutzt habe...aber
wie mache ich es richtig :)
Danke für die Hilfe!
Daniel K. schrieb:> Ich gehe mal davon aus, dass ich die Schleife falsch benutzt habe
Hast Du. Was passiert innerhalb eines Prozesses?
Alles was da steht. Und zwar alles gleichzeitig. Innerhalb eines Taktes.
Eine FOR-Schleife ist damit prinzipiell nur eine verkürzte Schreibweise
gegenüber der "ausgerollten" Form:
1
PROCESS(Clock1)
2
BEGIN
3
FORiIN0TO3LOOP
4
a<=i;
5
ENDLOOP;
6
ENDPROCESS;
ist also genau dasselbe wie
1
PROCESS(Clock1)
2
BEGIN
3
a<=0;
4
a<=1;
5
a<=2;
6
a<=3;
7
ENDPROCESS;
Nur daß Du letzteres wahrscheinlich gar nicht erst hinschreiben würdest,
weil dir sofort klar ist, daß das irgendwie keinen großen Sinn macht...
Hallo,
so ich habe noch etwas weiter gemacht...
Jetzt habe ich einen Display-RAM gemacht und diesen mit drei Zeichen
gefüllt (jeweils Pixel 0, 1 und 2):
Dieses Display-RAM soll meinen aktuellen Bildschirminhalt darstellen
Jetzt habe ich mein Top Design mit dem Display-RAM und meinem
VGA-Controller, der ein bestimmtes, gegebenes Zeichen an einer
bestimmten Stelle auf dem Monitor ausgibt.
Aber ich bekomme immer einen Implementierungsfehler:
[Place 30-640] Place Check : This design requires more F7 Muxes cells
than are available in the target device. This design requires 69904 of
such cell types but only 8800 compatible sites are available in the
target device. Please analyze your synthesis results and constraints to
ensure the design is mapped to Xilinx primitives as expected. If so,
please consider targeting a larger device.
Im Prinzip muss ich doch nur die Pixel zählen (mit jedem Clock einen
Pixel) und bei 8 Pixeln wird eine Stelle im RAM weiter gesprungen.
Aber wo ist der Fehler?
Danke für die Hilfe!
Daniel K. schrieb:> -- Target Devices: XC7Z010CLG400-1
Wenn dies das richtige Device ist, hast Du laut Datenblatt 240 KB(yte)
bzw. 60 BRAMs.
> Addr_Width : integer := 20;> Data_Width : integer := 8
...
> type Display_RAM_Type is array (0 to (2**Address'length) - 1) of> std_logic_vector(Data_In'range);
Hier verlangst Du vom Tool, Dir einen Speicher mit 2^20 Bytes zu
erzeugen.
Den Rest darfst Du selber rechnen...
Duke
Ahh danke :)
Hab mal einen Blick auf die Post-Synthese geworfen und da wurde es auch
angezeigt...konnte den Fehler halt nicht zuordnen...
Wie kann ich den dann jetzt einen Displayinhalt vernünftig anzeigen
lassen, wenn ich kein RAM im FPGA implementieren kann?
Gibt es da eine Möglichkeit?
Daniel K. schrieb:> Gibt es da eine Möglichkeit?
Ja, z.B. mit einem Zeichengenerator.
Oder man nutzt externen RAM.
Oder eine 'Funktion', die das Bild bei jedem Durchlauf neu generiert.
Duke
SRAM von außen zuführen evtl.
Eigentlich brauchst du Screenram 4800 Byte, wo der AScii drin steht zb
für A = 65, B = 66 usw. , alle Ramzellen (4800 Byte) füllen. Dann ein
RAM , für 256 Zeichen sind das 8x256=2048 Byte wenn ein Zeichen 8 Byte
hoch ist.
Mehr brauchst du nicht.
Ist merkwürdig, das dein Ding nicht soviel BRAM anlegen kann.
Gruss
peter schrieb:> SRAM von außen zuführen evtl.>> Eigentlich brauchst du Screenram 4800 Byte, wo der AScii drin steht zb> für A = 65, B = 66 usw. , alle Ramzellen (4800 Byte) füllen. Dann ein> RAM , für 256 Zeichen sind das 8x256=2048 Byte wenn ein Zeichen 8 Byte> hoch ist.>> Mehr brauchst du nicht.> Ist merkwürdig, das dein Ding nicht soviel BRAM anlegen kann.>> Gruss
Ja genau so habe ich es bisher gemacht.
Ich habe mein Font-ROM da stehen die ASCII Zeichen drin (auch nach ASCII
Tabelle). Dieses ROM ist 8x8096 groß (meine Zeichen sind 8x8 groß und
ich habe die untersten drei Bits der Adresse vom Font-ROM für die Zeilen
der Zeichen genommen und dann die obersten 8 Bits für die 256 Zeichen).
Wenn ich an meinem VGA-Controller nun als Zeichen die 65 angebe, so gibt
er mir auf dem Display den Buchstaben "A" aus.
In meinem Display-RAM soll nun mein Bild stehen für ein 640x480 Monitor
und idealerweise steht an jeder Stelle im RAM das Zeichen für 1 Zeichen
(also ein 8x8 Feld) und diese Felder adressiere ich dann, lese das
Zeichen aus und gib das Zeichen in den VGA-Controller, der es mir
anzeigt.
Edit:
Mir ist gerade eingefallen....wenn ich ein 8x8 großes Zeichen habe, dann
kann mein Bildschirm ja nur 80x60 Zeichen anzeigen.
Ich brauche also nur ein RAM, welches 80*60 groß ist mit einer Bitbreite
von 8 (erst einmal Text only)
....Jetzt verstehe ich auch wo der Wert 4800 her kommt :/
Ok ich habe meinen Display-RAM nun implementiert bekommen und am
Bildschirm werden jetzt auch vier Zeichen ausgegeben. Allerdings sieht
es so aus, als ob die von unten nach oben aufgebaut werden und das immer
abwechselnd, sprich erst Zeichen 1, dann Zeichen zwei, etc.
Wie bekomme ich das nun "schöner" hin? Ich kann ja keinen schnelleren
Takt als die 25MHz vom VGA nehmen oder?
Du kannst auch ander Pixelclocks wählen. Dann bist du bei anderen VGA
Modi, die auch andere Auflösungen zulassen aber auch andere timings
haben.
http://martin.hinner.info/vga/timing.html
--Display_Address <= "000" & std_logic_vector(to_unsigned((Pixel_x mod 8), 10));
127
128
-- Farbausgabe
129
process(Reset,Clock_VGA)
130
begin
131
if(rising_edge(Clock_VGA))then
132
if(Reset='0')then
133
RGB<=x"0000";
134
else
135
if(Pixel_xmod8=7)then
136
Cursor<=Cursor+1;
137
endif;
138
139
if(Cursor=79)then
140
Cursor<=0;
141
endif;
142
143
if((Position_Flag='1')and(ROM_Bit='1'))then
144
RGB<=Color;
145
else
146
RGB<=x"0000";
147
endif;
148
endif;
149
endif;
150
endprocess;
151
152
endVGA_Arch;
Ich versuche nun das zweite Zeichen aus dem Display RAM auszulesen und
dieses Zeichen auf der kompletten Displayreihe darzustellen (das ist ein
A). Das Auslesen klappt schon mal und auch die Darstellung klappt mehr
oder weniger gut (siehe Foto).
Leider flackern die Buchstaben noch recht stark und sind schwer zu
erkennen...
Ich habe den Code auch mal simuliert und alle 8 Pixel wird der Cursor um
eins hoch gezählt und dort soll dann der neue Buchstabe gezeichnet
werden.
Leider klappt das nicht ganz so wunderbar....
Woran könnte das liegen?
Hallo Duke,
ja aber nur die ersten paar Mikrosekunden. :) (im Anhang ist noch mal
eine längere Simulation) - vielleicht wäre es besser dem Signal noch
einen Startwert von '1' zu geben?.
Ich habe meinen Code noch mal etwas überarbeitet, nachdem ich von
funkheld mal ein lauffähiges Beispiel bekommen habe, welches ich
erfolgreich auf mein Board portieren konnte.
Ich habe nun für die x- und y-Koordinaten einen Typ "unsigned"
genommen...laut Internet soll der Typ ohnehin besser zum Rechnen sein
(?).
Das oben gezeigte Beispiel gibt nun lauter "L" auf dem Bildschirm aus
(da nutze ich noch die feste Adresse 0000000000010 um das dritte Zeichen
im Displayspeicher auszulesen).
Jetzt habe ich aber ein Problem mit dem automatischen Auslesen des
Displayspeichers.
Wenn ich nun statt "0000000000010" das Signal ""000000" &
std_logic_vector(Zeichen_Address)" einsetze, bekomme ich das auf dem
zweiten Foto gezeigte Phänomen, obwohl der komplette Displayspeicher
leer ist (bis auf das zweite Zeichen, was immer noch ein "L" ist).
Wenn ich die Adressierung der Zeilen weg lasse müsste ich doch in jeder
Zeile an der zweiten Stelle ein "L" stehen haben, da ja der Zähler
"Zeichen_Address" jede Zeile von neuem anfängt zu zählen.
Aber anscheinend habe ich da noch einen Versatz drin und ich habe keine
Idee wo der her kommt (in der Simulation ist das auch zu erkennen).
Vielleicht hat ja jemand eine Idee woher das kommen könnte :)
In der Zwischenzeit suche ich schon mal weiter :o
Das ist ein typischer Latenzfehler: Du liest das Zeichen
aus einem Speicher (BlockRAM?) und dann das Zeichenpixel
aus einen Anderen (ebenfalls BlockRAM?).
Für das Zeichenpixel werden aber noch X- und Y-Koordinate
verwendet. Durch das Zeichen-RAM hst du jetzt eine Latenz
zu den Koordinaten. Aufheben kannst Du das, indem die
X- und Y-Koordinate (d.h. je 3 Bits) einmal (oder evtl.
mehrmals) pipelinest. Das "hebt" die Latenz auf.
So neues update :)
Das Timing-Problem ist nun behoben....ich habe die x und y Koordinaten
einmal durch nen Clock verzögert und dann war es weg (danke für den
Tipp).
Bin auch schon fast am Ziel...ich habe jetzt mal das Wort "Hallo" 17x in
das Display-RAM geschrieben (17*5 Zeichen = 85 Zeichen = 1 komplette
Zeile + 1 Wort), aber das letzte "o" wird nicht angezeigt (dafür am
Anfang ein "H" mehr), in der zweiten Zeile wird kein "Hallo" angezeigt
und unten am Bildschirm habe ich weiße Punkte (siehe Screenshot).
Die Sourcen habe ich mal angehängt, da das sonst zu lang wird wenn ich
diese immer poste...
Ich habe auch mal mein VGA Timing an das hier angepasst:
http://www.ece.unm.edu/~jimp/vhdl_fpgas/slides/VGA.pdf
Als Startpunkt für den Zähler habe ich jeweils die steigende Flanke vom
Sync genommen, sprich in x-Richtung 48 Pixel, dann 640 sichtbare, dann
16 nicht sichtbare und dann der Sync für 96 Pixel.
Analog bin ich beim V-Sync vorgegangen. Eventuell steckt da ja der
Fehler?
Hallo, das sieht ja gut aus.
Warum hast du VGA_Timing 2x drin?
Kannst du die VHD Font-Rom auch mal reinsetzen. Dann könnte man es mal
als ganzes Testen.
Danke.
GRuss
Wenn der Text nicht stimmt, musst du hier ein bisschen mit rumspielen.
Kann sein das der Monitor zu pingelig ist.
Gruss
WholeLine : integer := 800;
VisibleArea_H : integer := 640;
BackPorch_H : integer := 40;
SyncPulse_H : integer := 96;
Hallo,
peter schrieb:> Hallo, das sieht ja gut aus.> Warum hast du VGA_Timing 2x drin?>> Kannst du die VHD Font-Rom auch mal reinsetzen. Dann könnte man es mal> als ganzes Testen.>> Danke.>> GRuss
mist...ich hatte da noch was an der Datei geändert...dachte er hätte die
vorhandene Datei überschrieben.
Ich habe es im Anhang noch mal komplett als ZIP-Datei hochgeladen.
Zu dem 80x40...da habe ich mich verschrieben :)
Es ist alles für 80x60 Zeichen ausgelegt.
Ich probiere in der Zeit mal etwas weiter :)
Daniel K. schrieb:> Hallo,>> peter schrieb:>> Hallo, das sieht ja gut aus.>> Warum hast du VGA_Timing 2x drin?>>>> Kannst du die VHD Font-Rom auch mal reinsetzen. Dann könnte man es mal>> als ganzes Testen.>>>> Danke.>>>> GRuss>> mist...ich hatte da noch was an der Datei geändert...dachte er hätte die> vorhandene Datei überschrieben.> Ich habe es im Anhang noch mal komplett als ZIP-Datei hochgeladen.>> Zu dem 80x40...da habe ich mich verschrieben :)> Es ist alles für 80x60 Zeichen ausgelegt.> Ich probiere in der Zeit mal etwas weiter :)
HA ein Problem habe ich schon mal gelöst :)
Im VGA-Timing musste
Hallo, warum hastdu hier noch color drin:
Color : in STD_LOGIC_VECTOR(15 downto 0);
Da steht doch schon RGB?
Wofür ist das?
Danke.
Gruss
Port ( Clock_VGA : in STD_LOGIC;
-- Taktsignal für VGA-Logik
Reset : in STD_LOGIC;
-- Reset für VGA-Logik
Mode : in STD_LOGIC;
-- Auswahl Betriebsmodus, 0 -> Grafik, 1 -> Text
Color : in STD_LOGIC_VECTOR(15 downto 0);
HSync : out STD_LOGIC;
-- Ausgang für H-Sync Signal
VSync : out STD_LOGIC;
-- Ausgang für V-Sync Signal
RGB : out STD_LOGIC_VECTOR((Color_Width - 1) downto
0) -- RGB Ausgang für das VGA-Signal
);
Hallo,
das ist quasi die Farbe die ich in dem Top_Design übergebe. RGB ist der
Ausgang der auf den DAC geht und über Color sage ich welche Farbe er auf
den DAC gibt.
Das kommt aber noch raus, wenn der Text + RAM läuft landet die Farbe mit
im RAM und dann hole ich mir die da her.
Im Moment ist das einfach nur zum ausprobieren :)
Daniel K. schrieb:> Das Timing-Problem ist nun behoben....ich habe die x und y Koordinaten> einmal durch nen Clock verzögert und dann war es weg
So wie ich das auf die Schnelle sehe, hast Du die X-/Y-Koordinaten
gepipelined, aber nicht die ROW-/COL-Koordinaten wie von mir
vorgeschlagen (ROW bzw. COL werden aus Pixel_x/Pixel_y generiert).
Du hast also eine weitere Latenz drin.
Und: Du müsstest für exaktes Timing auch HSYNC/VSYNC zweimal
verzögern, denn dein Zeichenpixel kommt zwei Takte später an.
Mach Dir am Besten dazu ein einfachen Datengraph, bei dem jeder
Kante die Anzahl Verzögerungen zugeordnet werden. Dann muss in
jeden Knoten alle einlaufenden Pfade die selbe Gesamtzahl an
Verzögerungen aufweisen, ansonsten muss gepipelined werden.
Kleine Nebenbemerkung: Dein Font-RAM hat 8 Bits für Datenausgang,
ändere das doch auf ein Bit um, dann ist die Ansteuerung evtl.
einfacher.
Aber das hat die ganze Sache nur verschlimmert, wodurch der Text gar
nicht mehr lesbar war :(
Das mit dem Datengraph verstehe ich nicht so ganz. Hast du da vielleicht
mal ein Beispiel für mich, wo ich sehe wie du das meinst?
Also wenn der Text überhaupt nichtmehr lesbar ist, dann sind
noch ein paar grössere Hauer drin.
Aber zum Graph bzw. zur Analyse (Ann.: Pixel-ROM liefert nur
ein Bit zurück), Ansätze bzw. Interpretationen gibt es so
viele wie Lehr/Leerbücher:
Ein Zustand sei eine Menge von Signalwerten, ein Übergang/Kante
sei die Verarbeitung inkl. Speicherung(en) und Weitergabe an den
nächsten Zustand (dann ist ein einfache Register eine Kante mit
Verzögerung 1, die Eingabe-/Ausgabe-Werte die Zustände).
Bei Dir besteht dann auf VGA_top-Ebene der Startzustand S1 aus
HSync, VSync, Pixel_x, Pixel_y. Das Auslesen des Zeichens
ist dann eine Kante zum nächsten Zustand S2 (Zeichen-Code), mit
D1 Latenz. Von da dann eine Kante für das Auslesen des
Font-Pixels (D2 latenz) nach S3 mit Font-Pixel. Jetzt hast Du
aber noch eine Kante von S1 nach S3, denn Pixel_x und Pixel_y
werden als ROW und COL für dein Font-ROM verwendet.
Jetzt gilt für Pixel:
S1->S2->S3 hat D1+D2 Delay
S1->S3 hat D1 Delay,
d.h. für dein Zeichen-Pixel werden Signalwerte von t-D1-D2
als auch von t-D1 verwendet, also müssen ROW und COL und D2
verzögert werden. Für HSync und VSync hast du 0 Latenz, d.h
beide Signale müssen um D1+D2 verzögert werden.
Für Dein Problem bzw. Design ist das natürlich übertrieben,
ein erfahrener Designer eine trivale Geschichte.
Wenn Du aber mehr als 10 Komponenten mit unterschiedlichsten
Delays hast, dann kommst Du um eine formalere Beschreibung
nicht rum.
nur als komplexeres Beispiel: Ich habe eine komplette
Graphikanwendung mit Text, Graphik, Overlay, Windows und
verschiedensten Algos wie Linie, Dreieck, Z/W-Buffer etc. mit
den unterschiedlichsten Verzögerungen. Ohne einen solchen
Ansatz wäre das nur noch ein wildes Basteln, und das für jede
beliebige Konfiguration (ich habe bestimmt schon >= 50 Stück).
Versuch Dir also die Abläufe bzw. Delays klarzumachen und
entsprechend zu korigieren.
Hallo Sigi,
danke für die ausführliche Erklärung :)
Das Verfahren wird mir aber leider noch nicht so recht deutlich. Hat
dieses Verfahren einen speziellen Namen, welchen ich mal googlen könnte?
Dann kann ich mir ein bisschen dazu durchlesen :)
In der Zwischenzeit lasse ich das erstmal so "unsauber" und konzentriere
mich darauf die Zeilenproblematik zu lösen (habe da gestern im Simulator
schon die Ursache gefunden und muss nun nur noch eine Lösung
erarbeiten).
Wenn das Ding dann so funktioniert werde ich die Timings schön machen.
Habe gestern nämlich gemerkt, dass das Bild bei einem anderen Monitor
etwas verschoben ist und so das erste "H" nur halb dargestellt wird.
Das verschieben der Zeilen kann von Monitor zu Monitor verschieden sein.
Da musst du an deinen Timingschrauben drehen.
Mit deinem Clock verschlimmert es sich noch wenn du später dein VGA
erweitern möchtest, PS2-Tastatur , Grafikausgabe und RS232
(Datenübertragung vom PC)
Ich habe nur 80x30 Auflösung mit funktionierender PS2 Tastatur. Wenn ich
mein ROM auf 2400 Zeichen erweitere (19200 Byte , geht noch mit dem DE0)
dann kann ich sogar ein Bild ins ROM ablegen und die Screenbelegung wird
einfach immer von 0-2400 hochgezählt statt einen bestimmten Text
auszugeben.
Weiterhin habe ich es mal übertrieben und noch RS232-RX eingebaut und
kann jetzt auch ein Grafikbild mit 640X240 übertragen vom PC aus zum ROM
und es wird sauber dargestelt. Die Grafik-Bytes werden als
Ascii-Zeichen(8 byte 1 Zeichen) übertragen.
GRuss.
Hallo,
danke für die Ausführliche Erklärung. Ich schaue mal ob ich das so
verstanden habe...
Ich nehme mein VGA-Timing als Basis, da dort zu jedem Clockzeitpunkt
(die Zeiten t0 - tn) eine x und eine y Koordinate erzeugt werden.
Warum wird dann aber der H- und V-Sync mitgezogen? Der wird doch erst
nach x-Takten ausgelöst?
Die Punkte delay 1-3 verzögern die entsprechenden Signale einfach um 1-3
Zyklen. Die werden dann später gebraucht um aus dem RAMs die richtigen
Daten zu holen.
Da die RAMs geclockt sind, kommen die Daten immer einen Taktzyklus
später. Die Signale, welche als Vektoren genutzt werden, werden dabei
als einzelnes Bit dargestellt. Bei meinem Font-RAM müssen dem
entsprechen die Vektoren für Zeile 0 und Spalte 0, sowie das
entsprechende Zeichen bei den Koordinaten (also meine erste Stelle aus
dem Display-RAM) eingegeben werden. Einen Clockzyklus später kommt dann
meine entsprechende Pixelzeile (also Pixel 7-0) aus dem RAM.
Da dieses Pixel dann aber jetzt schon mehrere Zyklen zu spät kommt
(bedingt durch die RAMs) muss ich die entsprechenden Koordinaten für
dieses Pixel so lange verzögern bis ich wieder ein Signal erhalte, was
zeitgleich mit dem entsprechenden Pixel läuft (in dem Beispiel wäre es
eine Verzögerung von 2 für die Koordinaten).
Und mit diesen verzögerten x-y Koordinaten erzeuge ich dann meine
Synchronisationssignale, die auch noch durch einen Takt verzögert
werden, damit sie mit der Farbe überein stimmen (aber wofür sind dann
h0.... und v0...? Bei den Syncs komme ich noch etwas durcheinander).
Ist das so korrekt?
Wenn ja, dann mache ich das mal für mein Design neu und schaue ob ich es
hin bekomme und danach versuche ich das mal umzusetzen.
Ist zwar wahrscheinlich bissl Overhead für sowas "simples" wie VGA, aber
so lerne ich das wahrscheinlich am besten :)
Hi,
so wie ich das auf die Schnelle sehe, hast Du es fast korrekt
wiedergegeben. Nur die Verzögerung der HSync-/VSync arbeitet
anders: Dein VGA_Timing generiert schon HSync und VSync, es
wird später nicht noch einmal generiert/berechnet, sondern nur
verzögert. Die Verzögerung ist wieder so eine Korrektheitsgeschichte.
Denn wenn Du Dein Design änderst (andere BRAMs mit mehr Latenz,
dann änder sich auch die Bildlage (Bild schiebt sich nach Rechts),
und genau das verhinderst Du mit einer flexiblen Verzögerung der
Sync-Signale. Du änderst also nur Dein Design, sondern passt die
Pipelines an die neue Latenz an und erhältst an immer der selben
Stelle auf dem TFT dein Bild.
Und ob Dein RAM jetzt getacktet ist oder nicht, spielt auch keine
Rolle. Nimm mal an, die RAMs sind ungetacktetes SRAM, dann erzeugt
Dein Design einen irre langen kombinatorischen Pfad (>>30-40 ns),
zwar mit den "zeitkorrekten" Werten, aber für höhere Auflösungen
viel zu langsam.
Dir scheint das jetzt als zu kompliziert für so eine "einfache"
Geschichte wie VGA-Textausgabe, aber bei vielen Designs kommt
es immer wieder vor, dass mehrerte Komponenten mit unterschiedlichen
Latenzen Signale liefern, die wieder in Phase gebracht werden
müssen, z.B. durch Pipelining.
Und für ein Neudesign: Nenn VGA_timing in VGA_CoreController um,
der erzeugt für eine vielzahl von neuen VGA-Controller (z.B.
Textausgabe, Graphikausgabe, einfache Farbbalken, SDRAM-Ansteuerung
etc.) die Basis-Signale (X-Pos,Y-Pos,H-Sync,V-Sync). Diese Signale
werden dann durch weitere Komponenten in die Farbsignale und die
verzögerten Sync-Signale transformiert, und zwar so, dass Dein
Bild immer konstant an einer exakten Stelle auf dem TFT erscheint.
P.S.: ich habe noch mal nach der Bezeichnung für obige Automaten
gesucht. Die werden z.B. auch gewertete/bewertete Automaten
genannt. E-Tech hat Schnittstellen zum MachBau und zur InfTech.
Da gibt's ähnliche Ansätze/Modelle. Die sind aber oft viel zu
kompliziert für so ein einfaches Problem, ich hab versucht, es
einfacher zu machen.
Ok wunderbar :)
Jetzt nur noch eine theoretische Frage...
Solche Analysen über Delays etc. werden wann im Design Flow gemacht?
Ich denke mal die macht man dann während der Entwicklung des Designs
oder, da man vor der Entwicklung des Designs, also quasi bei der
Überlegung was das Design können muss, ja nicht genau weiß was sich wie
verzögert (außer man hat RAMs etc. wo man weiß das die ein Delay
verursachen).
Hallo,
ich bin gerade dabei mir die Simulation mit Hilfe deiner Tabelle genauer
anzusehen und mittlerweile wird das doch schon recht deutlich wo die
Probleme stecken :)
Ich habe mir auch noch mal im Vivado den Block-Memory angeschaut (siehe
Screenshot).
Der hat anscheinend zwei Clocks als Delay...mal schauen ob ich das noch
bisschen gedrückt bekomme.
Daniel K. schrieb:> Hallo,>> ich bin gerade dabei mir die Simulation mit Hilfe deiner Tabelle genauer> anzusehen und mittlerweile wird das doch schon recht deutlich wo die> Probleme stecken :)> Ich habe mir auch noch mal im Vivado den Block-Memory angeschaut (siehe> Screenshot).> Der hat anscheinend zwei Clocks als Delay...mal schauen ob ich das noch> bisschen gedrückt bekomme.
Hallo,
so anhand deiner Vorlage habe ich mir mal einen Ablauf erstellt (dort
sind auch die zwei Zyklen Block Memory Latenz mit drin)....siehe Anhang
(ist eine Textdatei).
Zudem habe ich mal versucht das ganze dann im Code einzubauen (siehe
ebenfalls Anhang).
Aktuell habe ich auf dem Bildschirm noch Pixelfehler drin (ich gebe erst
einmal wieder eine Zeile aus dem RAM auf der kompletten Bildschirmhöhe
aus)...ich bin da noch am suchen aber vielleicht kannst du dir das ja
schon mal anschauen, damit ich weiß ob ich damit richtig liege :)
Und schon wird der Text schön angezeigt (sieht sogar besser aus als
vorher...) :)
Wunderbar....noch ein paar mal mit dieser "Buchführung" arbeiten und
dann sollte das sicher funktionieren.
Jetzt kann ich mich darauf konzentrieren die Sache rund zu machen etc.
:)
Btw:
Gibt es eine Möglichkeit die ganzen Signale, die ich zum Verzögern
verwende, schöner darzustellen bzw. zusammenzufassen?
Heyho,
noch mal ein kurzes Update :)
Habe gestern noch etwas am Timing-Controller rum gearbeitet, da der
Zeilenwechsel nicht geklappt hat....der hat mehrfach einen Offset von 80
drauf gehauen, was daran lag, dass ich geschaut habe wann x(2 downto 0)
= 0 war und diese Bedingung war über mehrere Taktzyklen aktuell...
Daher habe ich es jetzt so gemacht, dass der Counter pro Takt von 0-639
zählt und dann bei 640 stehen bleibt und 640 quasi der "Reset"-Wert
ist...
Jetzt klappt auch der Zeilenwechsel (siehe Fotos).
Ich habe nur noch am ersten Zeichen ein Pixel was zuviel ist (unter dem
"H")...da muss ich noch schauen woher das kommt...ich denke aber mal das
kommt vom Timing, da durch die getaktete Adresserzeugung ist alles
wieder um einen Takt verschoben, aber das ist schnell behoben :)
Ich habe mal den Code ebenfalls hochgeladen, falls jemand Interesse hat!
Der nächste Schritt wird (neben der Behebung des Pixelfehlers) das
einbringen von Farbiinformationen + Beschreiben des Display-RAMs und
korrigieren der ASCII-Tabelle im Font-ROM sein.....aber es nimmt schon
Formen an :)
Hallo zusammen,
so ich habe das Display-RAM jetzt auch als BRAM ausgelegt, da ich
ansonsten bei 51% Auslastung für Memory Lut gekommen wäre....
Bis auf einen kleinen Pixelfehler beim ersten Zeichen...aber da finde
ich den Fehler nicht :( ... mal schauen...
Ich habe jetzt mal einen Zähler aufgebaut, der einen festen Text aus dem
Initialisierungsfile für das Display-RAM ausgibt und einen veränderbaren
Text (einen Zähler) der ins Display-RAM geschrieben und danach angezeigt
wird.
Ich lade es mal hoch, falls es sich jemand anschauen möchte.
Im Großen und Ganzen ist das Thema VGA damit für mich abgeschlossen
(Grafikausgabe lasse ich erst einmal weg :) ).
Danke nochmal an alle beteiligten für eure Hilfe, wodurch ich ein ganzes
Stück weiter gekommen bin!
So, nach der Zeichen-/Font-RAM-Latenz-Problematik kann's ja weiter
gehen. Dein Problem ist jetzt, dass Du die Zeichen-Addresse korrekt
(bzw. Wert/Latenz) bestimmen musst. "VGA-Timing" liefert x/y-Pos,
aus den unteren 3 Bits wird das Pixel, aus den Bits 3..n-1 die
Zeichenaddresse. Und dass impliziert wieder Latenz.
Es gibt zwei einfache Möglichkeiten:
1. Je Zeile Wird ein Zähler, startend mit Offset, inkrementiert.
Nach 8 Zeilen wird dann der Offset um z.B. 40 inkrementiert
etc.
2. Du bestimmst aus den höheren Bits die Addresse direkt:
2.1.: per einfacher Multiplikation (Verschwendung einer MULT-Unit)
2.2.: bei z.B. 40 kann 40 in 32+8 zerlegt werden, d.h. die Mult
kann durch 2 ADD ersetzt werden. Damit hat man nach
2 Taktzyklen die Zeichenaddresse.
Also hast du 3 Aufgaben:
1. Zeichenaddresse bestimmen (1-2 Takte)
2. Zeichen lesen (1-2 Takte)
3. Font-Pixel lesen (1-2 Takte)
Plus jeweils x-/y-Pos-Pipelining.
Für 1. werden Bits 3..n benötigt, für 3. Bits 0..2, d.h. nur die
ersten 3 Bits der x-/y-Pos werden für's Pipelining benötigt. Gibt
also im Extremfall 6*2*3 Bits zum Speichern (HSync/VSync exkl.).
Hallo Peter,
ist alles in dem ZIP-File.
Unter VGA.srcs\sources_1\imports\new sind die beiden VHDL Files für den
VGA.
Das Font-ROM und das Display-RAM ist als Block Memory ausgelegt. Da habe
ich keine VHDL Files für, da ich das mit dem IP-Designer gemacht habe.
Unter VGA\VGA.srcs\constrs_1\new ist das entsprechende XDC-File für die
IO Belegung.