Hallo, ich möchte mal einen Thread für Einsteiger in die VHDL-Programmierung aufmachen in dem eine Sammlung von "Do's und Do not's" enstehen soll. Es ist (gerade) für Leute die sich mit Software beschäftigen und dann mit VHDL in Berührung kommen eine kleine Hilfe aufwendige Fehlersuche zu vermeiden. Ich mache mal den anfang : (man möge mich korrigieren wenn ich quark-mist erzähle ...) Do Not : -------- process (...) begin if clk'event and clk = '1' and clk_enable = '1' then ... end if; end process; Das ist ein gated Clock. Führt dazu das glitches auftreten können und der "gegatete" Clock nicht mehr 100% synchron zum eigentlichen Clock ist (lautzeit des und gatters). Böse Falle. Do Not : -------- Bsp : signal a : std_logic; signal b : std_logic; signal c : std_logic; process (clk) begin if clk'event and clk = '1' then begin a <= b and c; end if; end; Man sollte immer alle beteiligten (eingangs-)signale in der sensivity list eines prozesses haben. Sonst kann es passieren das der Synthesizer was anderes synthetisiert als man ursprünglich vorhatte zu implementieren (Beispiel Latch <-> Flipflop). Es sollte dann heißen : process (clk, b, c) ...
Erstes Don't stimmt so. Man sollte noch hinzufügen dass bei gated Clocks A) Glitches auftreten können und b) Clock Skew. Beides ist böse ;-) Und man sollte noch die korrekte Version hinschreiben. Das zweite ist falsch! Es gibt praktisch nur zwei Sorten von Prozessen, getaktete und rein kombinatorische. Erstere brauchen nur den Takt und ein evtl. vorhandenes asynchrones reset in der Sensitivity List, der Rest ist vollkommen egal und korrekt! Kombinatorische Prozesse brauchen natürlich alle Eingangsvariablen in der Sensitivity List, sonst gibts böse Simulationsfehler !!! (IIRC, Modelsim meldet keine Fehler bei fehlenden Signalen in der Sensitivity List, was auch vom Konzept von VHDL vollkommen in Ordnung ist). Das Syntheseergebnis wird AFAIK dadurch nicht verfälscht, weil die Compiler meist gutmütig genug sind, und "intern" alle Eingangsvariablen in die Sensitivity List eintragen (während der Synthese). MfG Falk
Ich bin absolut dafür, daß nur KOMPETENTE Personen sich aufschwingen, und dd-Listen in Newsgroups posten, sodaß nichr diskutiert werden muss. sonst bringt man den Leuten noch einen Mist bei
> sonst bringt man den Leuten noch einen Mist bei
so what?
TheMason bekommt seine Selbstbestätigung, ein Neuling glaubt etwas Mist.
Maßt du dir an zu beurteilen ob die Nachteile die Vorteile überwiegen?
Ohne Anspruch auf allgeingültiges "mach immer" oder "Mach Nie" Für VHDL Code der zu FPGA/CPLD synthetisiert wird: -Nur Richtung IN und OUT an Ports verwenden, bei der Top Entity an Tristate-Bussen auch IONOUT. -Zuweisung auf Z nur in der architecture der TOP Entity. (das thema interne Tristates bei Spartan2/2E lassen wir hier aus) -Genau eine Bibliothek mit unsigned verwenden. (also nicht USE IEEE.numeric_std.all,USE IEEE.std_logic_arith.all, ... in einem File oder in mehreren Files zu einem Design) mischen -Möglichst Nur prozesse mit Takt und evt. asynchronen reset verwenden Siehe Vorredner. Kombinatorische Prozesse (prozess ohne clk, aber allen anderenEingangssignalen in der sense list) nur bei Strukturen mit wählbarer Bitbreite einsetzen. -für Indezies von vectoren Zählrichtung und grenze nicht mischen. ( also nur ...(.. DOWNTO 0) verwenden. -feldattribute wie 'range 'low 'high benutzen -die feldattribute 'left 'right nicht benutzen -eigene Typen definieren, nicht nur für FSM:
1 | ausgang_o <= adu1_wert_i when mux_select = ADU else |
2 | Status_reg_q when mux_select = STATUS else |
3 | C_Version_number when mux_select = VERSION; |
-beautifier benutzen (z.b Emacs vhdl mode) -Prä/postfixe an signal namen etc. verwenden z.B. o für Ausgangsport _i für Eingänge _q für Signale aus FF V für variablen ...
Die Signalnamen auf den verschiedenen Designebenen geignet benennen, sodaß z.B: verbindende Signale auf der top level Ebene immer mit tl_ anfangen, in einem modul, daß z.B. uart realisiert, alle signale mit ua_. Richtungskritsche Signale , die Instanzen verbinden immer als "from-to", d..h. tl_data_mctrl_ram wäre ein top level Datensignal VOM main controller ZUM Ram. Damit verdeutlichlicht sich die Datenrichtung. Vermeiden sollte man betrachtungsabhängige Bezeichung, wie IN und OUT, sondern lieber "to_modul_x" oder "from_data_modul_x". Damit ist die Flussrichtung klar und man kann auch anonym deklarierte Ports iwe "in, out" fehlerfrei ohne Nachzudenken andrahten. Optimal ist es natürlich, wenn auch die Ports der Komponenten und Instanzen einddeutige Ins und Outs haben. Oft sehe ich aber leider designs, wo Ins mit Ins und Ins mit Outs verbunden sind, die Betrachtung als mischt. Für Komponenten empfiehlt sich eine Gruppierung der Ports in System, In, InOut und Out, bei "System" die für den Betrieb und Test nötigen Signale enthält, während die anderen 3 echte logische Datenpfade sind. So kennt ein Videocontroller (vc), der einen Datentakt aber natürlich auch noch einen FPGA-Systemtakt hat und zu Testzwecken abgeschaltet und paramteriert werden kann, folgende Signale: (downtos für Buse weggelassen und auch suffixe _i, _o fallen an den ports dann weg, dann in und out ja klar wird) -- system vc_fpgaclock_i, vc_test_enable_i, vc_testpattern_i, vc_test_error_o -- inputs vc_ videoclock, vc_data_from_adc, vc_from_dsp_chain, vc_adr_from_dsp, vc_test_image -- inouts vc_video_databus -- outputs vc_vid_signals_out, vc_to_statusreg, vc_to_dsp_chain, vc_error_out Man beachte z.B. die dsp_chain Verdrahtung sowie die Tatsache, daß der FGPA-Clock ein FPGA-Signals, während der Videotakt ein Applikationssignal darstellt, das es auch in einer Analogelektronik gäbe. Man unterscheide vor allem auch die Testmuster, die man in jedem Modul eines jeden FPGA-Designs anlegen könnte, um Module anzuregen, Standarddaten zu senden (System) und das Videotestmuster, dass es nur in einem Video-FPGA gibt, ergo bei den operational signals steht. Das, was hier im Bereich System steht, könnte (und sollte?) also in JEDEM FGPA-Desing zu finden sein, zumindest bei logisch komplex agierenden Modulen mit vielen Zustanden und Datenoperationen.
Bei größeren Designs lohnt der Einsatz von Mentor's FLI. Ersatzmodelle in C können aufwendige Simulationen deutlich beschleunigen (natürlich ist ein Ersatzmodell immer mit Vorsicht zu behandeln). Ausserdem lassen sich per FLI sehr bequem große Datenmengen in das eigene Design einspeisen bzw. daraus abführen (z.B. Videosequenzen).
Sinnvoll: * Lesbaren Code schreiben - einheitliche Notation - sinnvolle Signalnamen - alles ordentlich einrücken - Kommentare einfügen - File-Header mit Autor, Kurzbeschreibung, evt. History - kurze Bezeichner wählen - alle Möglichkeiten von VHDL konsequent nutzen - keinen Code schreiben, der aussieht wie von einem Tool erzeugt ;-) - rising_edge() falling_edge() anstelle des unsäglichen clk'EVENT and clk='1'... * Synchrone Designs erstellen - in einem synchr. Design sind alle Signale synchron zu einem Takt, auch die I/O-Signale - manchmal benötigt man mehrere Clocks, diese sollten ebenfalls alle synchron sein * sparsam mit Variablen umgehen - Variablen können zu unerwünschten Effekten führen, wenn man den Unterschied zu Signalen nicht verstanden hat. Deshalb so viele Signale wie möglich * Wiederverwendbaren VHDL-Code schreiben - mit Generics arbeiten - Konstanten in Packages verwenden - klare Gliederung des Codes - Bitbreiten sollten leicht anzupassen sein, also wie schon oben beschrieben mit Feldattributen arbeiten, dabei gibt es keine Verbote - wenn möglich und sinnvoll, dann alles parametrierbar machen ... die Liste ist unvollständig ... Noch ein paar Bemerkungen zu dem, was ich weiter oben gelesen habe: 'Zuweisung auf Z nur in der Top-architecture' ... was soll der Unfug, ich möchte im Prozessor-Interface oder im I2C-Core schon Z zuweisen können! 'Signalnamen mit Präfix für die Hierarchieebene' ... jedes Synthese- und Simulationstool kann mit Hierarchien umgehen, das habe ich noch nie benötigt Kombinatorische Prozesse sind genauso erlaubt wie getaktete. Wie soll man sonst z.B. den Adressdecoder für ein Prozessorinterface beschreiben? Dafür krieg ich jetzt bestimmt Klassenkeile, aber ich würde sagen: Leute die keine ausreichende Erfahrung mit VHDL haben, sollten keine DOs und DONTs schreiben. Das schafft mehr Verwirrung als Aufklärung und führt zu irgendwelchen Mythen.
FPGA-User schrieb: >- rising_edge() falling_edge() anstelle des unsäglichen clk'EVENT and >clk='1'... ...dagegen habe ich gerade heute bei einem kleinen Modul namens "simple_SPI" verstossen, denn mit > if clk'event and clk=activeClockLevel then ... liess sich schnell und einfach via Generic der SPI-Mode definieren. (Geht sicher auch anders, aber ich hab' das Modul nur schnell mal heruntergeklopft...)
Hi Stefan, klar, in dem Falle ist das sinnvoll - sind ja alles keine Gesetze, sondern nur Vorschläge. Aber da muss man wirklich wissen was man tut. Ich kenne das Design nicht, aber der Wechsel auf eine andere Taktflanke könnte auch dazu führen, dass nichts mehr geht. Die Code-Lesbarkeit halte ich übrigens für genauso wichtig wie synchrone Designs und Timing-Constraints, nichts ist schlimmer, als ein Stück VHDL bei dem man erst wieder Stunden braucht um durchzublicken.
> - manchmal benötigt man mehrere Clocks, diese sollten ebenfalls alle > synchron sein Das ist aber ein wenig unverständlich. Wenn ich mehrere Taktblöcke (Clock domains) habe, dann können die ruhig zueinander asynchron sein (sind es meist auch), allerding die einzelnen Blöcke an sich sind ein synchrones Design. Der Übergang von Daten und Steuersignalen muss dann vorichtig und gemäss bekanter Reglen erfolgen (Asynchrone FIFOs, Synchonizer FlipFlops, Gray Code, etc.) MFG Falk
"'Signalnamen mit Präfix für die Hierarchieebene' ... jedes Synthese- und Simulationstool kann mit Hierarchien umgehen, das habe ich noch nie benötigt" Das genau ist der häufig gemachte Denkfehler. Es geht nicht darum, daß das Tool es etwa nicht könnte oder man sich selber nicht zurecht findet, sondern um das Erkennen und Wiedererkennen durch andere Teamarbeiter, wenn sie sich in einem Design zurechtfinden müssen. In vielen Tools oder nach Export der Netzliste geht die vordergrüngie Hierarchie darüber hinaus verloren.
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.