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?
Jörg W. schrieb: > Wie zum Geier™ bekomme ich die Waveforms da angezeigt? Kannst du mal die VHDL-Dateien von Testbench und Prüfling posten?
1 | use ieee.std_logic_unsigned.all; |
2 | use ieee.numeric_std.all; |
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 | if cnt <768 then |
2 | cnt <= cnt+1; |
3 | else
|
4 | cnt <= 0; |
5 | end if; |
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.
:
Bearbeitet durch Moderator
tnx, schau ich mir heute Abend an. Jetzt bin ich erstmal im Homeoffice. :)
nur kurz draufgeguckt:
1 | if reset = '1' then |
2 | ...
|
3 | elsif rising_edge(clk) then |
4 | ...
|
5 | if ctr >= 12_000_000 and reset /= '0' then |
Im elsif-Zweig reset nochmal (verkehrt herum) abzufragen, scheint mir wenig zielführend.
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.
:
Bearbeitet durch Moderator
OK, nachdem es sich nun simulieren lässt, stimmt auch die Ausgabe. ;-)
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 …
:
Bearbeitet durch Moderator
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.
1 | j@wega 332% gvhdl tb.vhdl toplevel.vhdl --libieee |
2 | gvhdl: FreeHDL root path is '/usr'. |
3 | gvhdl: executing '/usr/bin/freehdl-v2cc -m tb._main_.cc -L /usr/share/freehdl/lib -o tb.cc tb.vhdl' |
4 | gvhdl: |
5 | gvhdl: ================================ |
6 | gvhdl: Compiling 'tb.cc'... |
7 | gvhdl: ================================ |
8 | gvhdl: x86_64-linux-gnu-g++ -I /usr/include -c tb.cc |
9 | gvhdl: executing '/usr/bin/freehdl-v2cc -m tb._main_.cc -L /usr/share/freehdl/lib -o toplevel.cc toplevel.vhdl' |
10 | gvhdl: |
11 | gvhdl: ================================ |
12 | gvhdl: Compiling 'toplevel.cc'... |
13 | gvhdl: ================================ |
14 | gvhdl: x86_64-linux-gnu-g++ -I /usr/include -c toplevel.cc |
15 | gvhdl: |
16 | gvhdl: ================================ |
17 | gvhdl: Compiling simulator main file 'tb._main_.cc'... |
18 | gvhdl: ================================ |
19 | gvhdl: x86_64-linux-gnu-g++ -I /usr/include -c tb._main_.cc |
20 | gvhdl: Linking simulator 'tb'... |
21 | gvhdl: libtool --mode=link --tag CXX x86_64-linux-gnu-g++ tb._main_.o tb.o toplevel.o -lm /usr/lib/libfreehdl-kernel.la /usr/lib/libfreehdl-std.la /usr/lib/freehdl/libieee.la -o tb |
22 | linker: libtool: link: x86_64-linux-gnu-g++ tb._main_.o tb.o toplevel.o -o tb -lm /usr/lib/libfreehdl-kernel.so /usr/lib/libfreehdl-std.so /usr/lib/freehdl/libieee.so -Wl,-rpath -Wl,/usr/lib/freehdl -Wl,-rpath -Wl,/usr/lib/freehdl |
23 | gvhdl: ================================ |
24 | gvhdl: Simulator 'tb' created. |
25 | gvhdl: ================================ |
26 | j@wega 333% ./tb -cmd 'd; r 1 ms; d; q' |
27 | Available commands: |
28 | h : prints list of available commands |
29 | c <number> : execute cycles = execute <number> simulation cycles |
30 | n : next = execute next simulation cycle |
31 | q : quit = quit simulation |
32 | r <time> : run = execute simulation for <time> |
33 | d : dump = dump signals |
34 | doff : dump off = stop dumping signals |
35 | don : dump on = continue dumping signals |
36 | s : show = show signal values |
37 | dv : dump var = dump a signal from the signal lists |
38 | ds : dump show = shows the list of dumped signals |
39 | nds : number show = shows the number of dumped signals |
40 | wdd : write binary design info |
41 | wddl : write design info using a CDFG style syntax |
42 | db_view : print kernel database |
43 | dc [-f <filename>] [-t <timescale> <time unit>] [-cfg <translation file>] [-q] :control waveform dumping |
44 | Simulation time = 0 fs + 0d |
45 | > > Run simulation for which time span? |
46 | Simulating model to time 1 ms |
47 | signal :wave changed |
48 | Simulation time = 0 fs + 1d |
49 | |
50 | 1 processes were executed. |
51 | 0 transaction were created. |
52 | > > j@wega 334% |
53 | j@wega 334% cat wa |
54 | wave.dmp waveform.pdc |
55 | j@wega 334% cat wave.dmp |
56 | $date |
57 | Aug 4 2015 00:39:09 |
58 | $end |
59 | $version |
60 | FREEHDL 0.0.8 |
61 | $end |
62 | $timescale |
63 | 1 ns |
64 | $end |
65 | $scope module behavioral $end |
66 | $var integer 24 ! ctr $end |
67 | $var trireg 1 " hsync $end |
68 | $var trireg 1 # in_hsync $end |
69 | $var trireg 1 $ in_vsync $end |
70 | $var trireg 1 % ledstate $end |
71 | $var integer 9 & linectr $end |
72 | $var trireg 1 ' newline $end |
73 | $var integer 10 ( pixelctr $end |
74 | $var trireg 1 ) vsync $end |
75 | $var integer 8 * waveout $end |
76 | $upscope $end |
77 | $var trireg 1 + clk $end |
78 | $var trireg 1 , led $end |
79 | $var trireg 1 - reset $end |
80 | $var reg 8 . wave[7:0] $end |
81 | $enddefinitions $end |
82 | #0 |
83 | $dumpvars |
84 | b0 ! |
85 | 0" |
86 | 0# |
87 | 0$ |
88 | X% |
89 | b0 & |
90 | X' |
91 | b0 ( |
92 | 0) |
93 | b0 * |
94 | X+ |
95 | X, |
96 | X- |
97 | bXXXXXXXX . |
98 | $end |
99 | #0 |
100 | b0 . |
101 | #0 |
102 | $dumpvars |
103 | b0 ! |
104 | 0" |
105 | 0# |
106 | 0$ |
107 | X% |
108 | b0 & |
109 | X' |
110 | b0 ( |
111 | 0) |
112 | b0 * |
113 | X+ |
114 | X, |
115 | X- |
116 | b0 . |
117 | $end |
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.
Jörg W. schrieb: > Bin ich noch nicht dazu gekommen, wird heute abend. Hmm, irgendwie habe ich wohl den Programmer auf dem Board gekillt. :-(
1 | Board with FTDI USB Host Chip detected. |
2 | |
3 | |
4 | Frequency setting= 15000000 Hz |
5 | Check configuration setup: Start. |
6 | Check configuration setup: Successful (Ignored JTAG Connection Checking). |
7 | Device1 iCE40UP5K: N25Q032A: Erase,Program,Verify |
8 | |
9 | Frequency setting= 29940 Hz |
10 | Initializing... |
11 | IDCode Checking... |
12 | Function:CHECK_ID |
13 | Data Expected: h16 Actual: hFF |
14 | Operation: unsuccessful. |
15 | Programming XCF Contents... Failed. |
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.)
:
Bearbeitet durch Moderator
Lob und Anerkennung! Ist das Pal? Sieht gut aus!
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.
:
Bearbeitet durch Moderator
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.