Mache gerade ein paar erste Schritte mit FPGAs. Habe mir ein
Lattice-Demoboard beschafft. Das funktioniert soweit (wenngleich der
Linux-Support leider lausig ist: Active-HDL gibt's gleich nur für
Windows, und der Programmer, ein simpler FT2232, wird zwar von Linux
erkannt, aber nicht vom Programming Tool). Die erste blinkende LED ist
geschafft, nun möchte ich gern mal paar Schritte mehr machen und dabei
auch was simulieren.
Das funktioniert soweit, wenn ich die Simulation mit dem "Simulation
Wizard" im Lattice Radiant starte. Wenn ich dagegen im Aldec selbst
nochmal was simuliere, bekomme ich im Waveform-Viewer irgendwie nichts
mehr angezeigt. Die Simulation selbst ist gelaufen (mit "Run to" ... "1
ms" – man sieht in den Meldungen, dass der Simulator die Millisekunde
abgearbeitet hat).
Wie zum Geier™ bekomme ich die Waveforms da angezeigt?
Never ever both together!
Denn wenn du der std_logic_unsigned über die std_logic_arith ihre
Arthmetikfunktionen mitgibst, dann bekommst du eigenartige Fehler mit
doppelten Typdeklarationen bekommen:
# Error: COMP96_0272: toplevel.vhd : (10, 15): Ambiguous reference to
type "UNSIGNED".
# Error: COMP96_0064: toplevel.vhd : (10, 15): Unknown type.
Vergiss die obsolete std_logic_math. Die numeric_std hat alles, was du
brauchst:
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std
Wenn du für interne Zähler integer mit passendem Range verwendest, wird
das Ganze wesentlich leserlicher. Ich frage solche Zähler vor dem
Hochzählen auf das Erreichen des Bereichsendes ab, dann muss ich keine
Angst vor dem Überlauf haben:
1
ifcnt<768then
2
cnt<=cnt+1;
3
else
4
cnt<=0;
5
endif;
Ich nehme auch eher ungern solche verschachtelten if-Strukturen, sondern
handle im Prozess ein (Ausgangs-)Signal nach dem anderen ab. Das ist
kein Problem, denn während des gesamten Prozesses ändert keines der
Signale seinen (Eingangs-)Wert. Wenn der Prozess mit linectr=768
begonnen wird, dann ist während des gesamten Prozessdurchlaufs der Wert
vom linectr = 768. Erst am Ende des Prozesses übernimmt dieses Signal
den zuletzt zugewiesenen Wert. Deshalb bekommst du einen Überlauf auf
769, obwohl du ja "sofort" auf 768 abgefragt hast.
Danach noch muss noch die Resetpolarität angepasst werden und dann tut
sich schon was.
Beim Compilieren darauf achten, dass die Testbench als "Top-Level"
gesetzt ist.
Du kannst "interne Signale" mit in die Waveform aufnehmen, wenn du in
der Hierarchie ein wenig nach unten gehst.
Markus F. schrieb:> Im elsif-Zweig reset nochmal (verkehrt herum) abzufragen, scheint mir> wenig zielführend.
Wird hoffentlich wegoptimiert, weil redundant... ;-)
Wenn er nicht wegoptimiert wird, ist es noch schlimmer als es aussieht,
denn durch diesen "invertierten" Reset im synchronen Pfad und den
vorrangigen "normalen" Reset im asynchronen Pfad kann es sicher urige
Effekte/Raceconditions geben. Da kann man nur hoffen, dass der Reset
hübsch einsynchronisiert wurde. Sonst passiert sicher das hier:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html
Solche Reset-wurde-nicht-einsynchronisiert-Geschichten sind leicht daran
zu erkennen, dass das Design manchmal nach dem Reset seltsame Dinge tut.
Aber wenn es mal richtig gestartet ist, dann läuft es tagelang
problemlos.
Lothar M. schrieb:> Never ever both together!
Gut, verstanden.
Hätte mir wohl deine Seite zuerst durchlesen sollen, ist aber insgesamt
ein bissel viel und für den Anfang etwas "querbeet". ;-)
> Wenn du für interne Zähler integer mit passendem Range verwendest, wird> das Ganze wesentlich leserlicher. Ich frage solche Zähler vor dem> Hochzählen auf das Erreichen des Bereichsendes ab, dann muss ich keine> Angst vor dem Überlauf haben:
Ja, verstanden.
Dass die Signale innerhalb des Prozesses ihren Wert nicht ändern
(sondern erst mit dem nächsten Takt), war mir im Prinzip klar, aber das
hatte ich noch nicht so verinnerlicht. Da ist meine Denke noch zu sehr
in klassischer Programmiersprache verhaftet.
> Ich nehme auch eher ungern solche verschachtelten if-Strukturen
Das war jetzt auch eher ein Anfang. Um eine etwas sinnvollere Anwendung
als den LED-Blinker zu haben (der natürlich trotzdem noch schön im
Sekundenrhythmus blinkt, damit man "was sieht" ;-), wollte ich mir mal
ein BAS-Signal vornehmen. Damit man am Ende auch tatsächlich was sehen
kann, ist da nun sowas wie eine Grautreppe. Da die 8 Graustufen
gleichmäßig verteilt sind, kann man da vermutlich auch viel mehr durch
den VHDL-Compiler rechnen lassen, statt sich die 8 Teile vorab mit der
Hand auszurechnen.
Es kommt am DAC auch sowas wie eine Treppe raus, aber sie entspricht
nicht den Erwartungen (und jetzt auch nicht der Simulation), insofern
muss ich wohl meine Pin-Zuweisungen nochmal verifizieren.
> Beim Compilieren darauf achten, dass die Testbench als "Top-Level"> gesetzt ist.
Das hatte ich schon so (hat ja auch nur so Sinn, wenn man drüber
nachdenkt).
Insgesamt habe die Funktionsweise von Simulator und Waveform-Display
irgendwie ganz anders erwartet. Ich dachte, man simuliert da was, und
danach kann man sich die Signale auswählen, die man angezeigt bekommen
möchte. Bzw., wenn man sie früher schon mal gewählt hatte, werden sie
bei einer neuen Simulation automatisch wieder da aufgenommen.
Wie ich nun tatsächlich etwas sehe: Toplevel festlegen, "Initialize
simulation". Ab da sind die Signale links unten (Structure view) nicht
mehr "Unavailable", und man kann sie in die Waveform-Anzeige ziehen.
Danach dann "Run to". Etwas verwirrend für mich, dass man während der
Simulation rein gar nichts sieht. Ich hätte erwartet, dass die
Waveform-Anzeige zumindest gelegentlich mal aktualisiert wird, oder man
sonst irgendwie in der Console eine Fortschrittsanzeige in Form einer
mitlaufenden Simulationszeit hat.
So sehe ich nun zumindest überhaupt was, danke! Habe auch schon einen
Bug entdeckt: nach der Simulation von 1,01 s ging der LED-Ausgang auf
"U", weil der interne ledstate zwar getoggelt wird, aber nie
initialisiert worden ist. Klar, in der Realität blinkt die LED natürlich
:), denn das Flipflop kann nicht "U" sein.
Markus F. schrieb:> Im elsif-Zweig reset nochmal (verkehrt herum) abzufragen, scheint mir> wenig zielführend.
Stimmt, danke. War bisschen ein Denkfehler.
Eine Frage habe ich nun doch noch speziell zum Simulator: wenn ich bei
oben gezeigtem Bild "Export Waveform" als VCD mache und "All signals"
wähle – warum bekomme ich dann immer nur dut:newline im VCD-File?
Wollte mir das gern mal im GTKwave ansehen …
Ah falsch verstanden. waveform_tb enthält LED, clk und reset im Export,
dut ist dagegen ein Submodule davon und enthält newline.
Aber: "waveout" bekomme ich irgendwie nicht in den Export rein.
So, nun erstmal wieder Homeoffice …
Warum da dies oder jenes an Signalen manchmal im VCD drin ist und
manchmal nicht, bleibt mir vorerst ein Rätsel. Vielleicht gucke ich ja
demnächst nochmal, ob ich das auch alles in GVHDL simuliert bekomme.
Allein sowas ist doch wiedermal einfach nur lästig:
1
# KERNEL: Warning: You are using the Active-HDL Lattice Edition. The performance of simulation is running at a reduced rate.
2
# KERNEL: Warning: Contact Aldec for available upgrade options - sales@aldec.com.
Anyway, habe mit der Generierung eines rudimentären Fernsehsignals
bisschen weiter gebastelt. Jetzt ist da ganz viel integer drin, Vektoren
werden dann erst bei der Ausgabe draus gemacht. Simulation sieht auch
schlüssig aus.
Weitere Kritik willkommen. ;-)
Jörg W. schrieb:> Allein sowas ist doch wiedermal einfach nur lästig:> # KERNEL: Warning: You are using the Active-HDL Lattice Edition. The> performance of simulation is running at a reduced rate.
Das Problem gibt es bei GHDL nicht. Dafür ist es nicht ganz so bunt ;-)
> Anyway, habe mit der Generierung eines rudimentären Fernsehsignals> bisschen weiter gebastelt. Jetzt ist da ganz viel integer drin, Vektoren> werden dann erst bei der Ausgabe draus gemacht.
Ja, solange die integer eingeschrängte Bereiche haben ist das o.k.
Ich empfehle auch, gerade in der Anfangsphase, mal zu schauen, was der
Synthesizer vom Code verstanden hat. Bei Diamond geht das mit dem
Netlist Analyzer.
> Simulation sieht auch schlüssig aus.
Und was macht die Hardware daus? Synchronisiert sich der Bildschirm
schon?
Duke Scarring schrieb:> Das Problem gibt es bei GHDL nicht. Dafür ist es nicht ganz so bunt ;-)
Das allein wäre Grund genug, sich den mal anzusehen. :)
Allerdings habe mit gvhdl bislang noch kein Simulationsergebnis zustande
bekommen für die gleiche Konfiguration.
Ist irgendwie für 1 ms Simulationszeit nicht so richtig viel, was da
drin steht …
> Ich empfehle auch, gerade in der Anfangsphase, mal zu schauen, was der> Synthesizer vom Code verstanden hat. Bei Diamond geht das mit dem> Netlist Analyzer.
Ja, habe ich im Blick, hatte mir Lothar schon mal empfohlen.
>> Simulation sieht auch schlüssig aus.> Und was macht die Hardware daus? Synchronisiert sich der Bildschirm> schon?
Bin ich noch nicht dazu gekommen, wird heute abend.
Unter Windows das gleiche wie unter Linux.
Das FPGA selbst lässt sich mit der letzten im Flash hinterlegten
Konfiguration noch konfigurieren, daran scheint es nicht zu liegen.
Duke Scarring schrieb:> Und was macht die Hardware daus? Synchronisiert sich der Bildschirm> schon?
Ich denke, dass man das durchgehen lassen kann. ;-)
Musste erst noch einen Impedanzwandler hinter meinen recht hochohmigen
R-2R-DAC setzen, um damit einen Video-Eingang anzusteuern.
(Der schräge Streifen ist ein Artefakt der Handy-Belichtung.)
Gustl B. schrieb:> Ist das Pal?
Reines CCIR. Der Gucki ist ohnehin nur S/W.
Der Aufwand für PAL dürfte sich nicht lohnen. Wenn, würde man ja eher
über VGA oder SCART an so eine Farbglotze einspeisen und RGB separat
führen.
Ist im Moment auch erstmal einfach 312 Zeilen mit 50 Hz, ohne
Zeilensprung. Das ist einfacher zu implementieren, so hat auch die
Videoaufbereitung meines ersten Eigenbaucomputers vor 35 Jahren
gearbeitet. Man könnte natürlich noch Zeilensprung implementieren (in
realer Hardware wäre das Aufwand gewesen, im FPGA sind es nur ein paar
Zeilen mehr), aber da stellt sich die Frage der Anwendung. Zeilensprung
bringt flimmernde horizontale Linien, lohnt daher eigentlich wirklich
nur für echte Bilder, nicht für Strich- oder Pixelgrafiken.
Eine Schwarzwert-Klemmung werde ich aber noch probieren. Wenn man das
Signal nur wechselspannungsmäßig aufbereitet, hat man das Problem, dass
bei Bildern mit viel hellem Anteil (wie hier) die 0 V für schwarz nicht
erreicht werden. DC-Kopplung würde eine negative Versorgung für den
Ausgangsverstärker brauchen. Wenn ich aber den Ausgangskondensator
während der Austastlücken mit einem Transistor entlade, sollte sich das
verbessern lassen. Ich weiß ja im FPGA, wenn es wirklich 0 V sein
sollen, und kann in dieser Zeit ein Steuersignal für einen Transistor
separat ausgeben.
Jörg W. schrieb:> DC-Kopplung würde eine negative Versorgung für den> Ausgangsverstärker brauchen. Wenn ich aber den Ausgangskondensator> während der Austastlücken mit einem Transistor entlade, sollte sich das> verbessern lassen. Ich weiß ja im FPGA, wenn es wirklich 0 V sein> sollen, und kann in dieser Zeit ein Steuersignal für einen Transistor> separat ausgeben.
Kann man bestimmt machen. Aber braucht man wirklich diesen Verstärker?
VGA habe ich nur mit einem R2R DAC gemacht.
Gustl B. schrieb:> Aber braucht man wirklich diesen Verstärker?
Ich habe nur 50-kΩ-Netzwerke für den R-2R-DAC gerade da. Da sah man
selbst mit der Oszi-Tastspitze schon arg verschliffene Flanken. Ich
denke nicht, dass das ohne einen Impedanzwandler Sinn gehabt hätte.