Forum: FPGA, VHDL & Co. VHDL Anfänger braucht Unterstützung (keine Lösung)


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von Tobi A. (tobi_python)


Angehängte Dateien:

Lesenswert?

Hey Leute,
ich bin gerade dabei mich mit FPGA Programmierung zu beschäftigen und 
komme von C-Welt, kenne mich einigermaßen mit objektorientierten 
Sprachen (Modelica) und Ingenieurszeugs wie MATLAB.

Jetzt bin ich auf VHDL gestoßen und konnte nach langem Hin und Her die 
ersten Texte verstehen lernen. Ein eigenes Programm auf „Blanko“ zu 
schreiben fällt mir noch schwer, da muss ich noch sehr oft auf fertig 
geschriebene Quellcodes zurückgreifen.

So zum aktuellen Stand: ich habe jetzt eigene Zustandsdiagramme erstellt 
für Bitmustererkennungen oder sonstiges also einfache Mealy/Moore 
Automaten etc. Kann ich noch realisieren.

Jetzt bin ich auf eine synchrone sequenzielle Schaltung gestoßen und 
frage mich echt was hier abgeht. Im Internet finde ich einfach keine 
Erklärung, die mich weiter bringt…

EDIT: habe ein Bild hinterlassen, da der Code sonst nicht lesbar ist!

library IEEE;
  use IEEE.STD_LOGIC_1164.ALL;
  use IEEE.NUMERIC_STD.ALL;
  entity aufgabe3 is
      Port ( CLK, S0, S1, S2, S4, S3 : in std_logic;
             D : in unsigned(4 downto 0);
             Q : out unsigned(4 downto 0));
  end aufgabe3;
  architecture Behavioral of aufgabe3 is
      signal QINT: unsigned(4 downto 0);
  begin
      P1: process(S0, CLK)
      begin
          if S0 = '1' then
              QINT <= "0000";
          elsif rising_edge(CLK) then
              if S1 = '1' then
                  QINT <= "0000";
              else
                  if S2 = '0' then
                      QINT <= D;
                  else
                      if S3 = '1' then
                          if S4 = '0' then
                              QINT <= QINT - 2;
                          else
                              QINT <= QINT + 1;
                          end if;
                      end if;
                  end if;
              end if;
          end if;
      end process P1;
      Q  <= QINT;
  end Behavioral;

Das ist der Quelltext und ich bin baff. Ich würde gerne gemeinsam mit 
euch erarbeiten, was hier eigentlich passiert und was das ganze für 
einen Sinn hat, wenn es überhaupt einen hat?

Ist jemand bereit mir dabei zu helfen ? Ich verlange ausdrücklich keine 
Lösung im Sinne von ihr sagt mir was passiert ist (könnt ihr gerne 
machen für Kontrollzwecke machen), sondern würde ich lieber das ganze 
erarbeiten, damit der Lerneffekt auch entsprechend gegeben ist.

Ich wäre extrem dankbar für jeden Hinweis, jede Anregung, jede Idee!!!

Mein Problem beginnt schon bei der Variablendeklaration, ich verstehe 
nicht wieso wir jetzt hier zwei mal Inputs definieren, geschweige denn 
was die Clock da abstellt. Die vorherigen Programme waren viel 
einfacher…

: Bearbeitet durch User
von Herbert (Gast)


Lesenswert?

>Jetzt bin ich auf VHDL gestoßen und konnte nach langem Hin und Her die
>ersten Texte verstehen lernen. Ein eigenes Programm auf „Blanko“ zu
>schreiben fällt mir noch schwer, da muss ich noch sehr oft auf fertig
>geschriebene Quellcodes zurückgreifen.

Das erste, was du verstehen musst, ist, dass du mit VHDL kein Programm 
schreibst, sondern eine Schaltung beschreibst.
z.B.

if S4 = '0' then
   QINT <= QINT - 2;
else
   QINT <= QINT + 1;
end if;

Hier wird abhängig von der Eingangsleitung "S4" entwder der 
Schalungspfad gewählt, der QINT um zwei erniedrigt oder QINT um 1 
erhöht. Das passiert jeweils abhängig vom Taktsignal CLK bei der 
steigenden Flanke.

von Tobi A. (tobi_python)


Lesenswert?

Hey, vielen Dank erstmal für die Antwort!

Ja ich bin leider etwas „voreingenommen“ durch meine alten Erfahrungen, 
danke erst mal für den Hinweis, ich habe es nämlich als ein Programm 
betrachtet.

Also ist das im Ansatz grob gesagt, ein Vorwärts Rückwärtszähler ?

Kann man hierzu eig auch die sogenannten Karnaugh Tafeln zu malen? 
Immerhin haben wir ja jetzt Zwei Deklarationen, die sich auf Inputs 
beziehen?

Hoffe meine Fragen sind nicht allzu blöd, das ist alles Neuland für mich 
…

von Martin S. (strubi)


Lesenswert?

Ja, mit dem Wort 'Programm' und 'Variablen' wirst du hier wieder eine 
Menge sophistischer Kommentare triggern...
Tips in Kurzform:
- Such' dir eine Simulationsumgebung (z.B. GHDL, diverse 
Online-hdlplaygrounds)
- Probiere Testbenches aus mit diversen Stimuli (
- Uebe Reverse-Engineering an (noch) 'obskuren' Schaltungen wie oben
- Erst mal Signal-Typen verwenden, dann Variablen

Bei VHDL ist grundsaetzlich viel Verwirrung mit im Spiel (Signale vs. 
Variablen), dazu kommt, dass du eine Menge in VHDL modellieren kannst, 
was die Tools nicht (oder nicht korrekt) in Hardware umsetzen.
Gibt da inzwischen modernere Ansaetze fuer den Einstieg. Allerdings 
schadet es laengerfristig nicht, wenn du VHDL oder Verilog lesen kannst.

von Gustl B. (-gb-)


Angehängte Dateien:

Lesenswert?

Tobi A. schrieb:
> Also ist das im Ansatz grob gesagt, ein Vorwärts Rückwärtszähler ?

Bingo! Man sollte den S0 ... S4 dazu sinnvollere Namen geben.

Außerdem enthält die Aufgabenstellung einen Fehler:

Bei
QINT <= "0000";
fehlt eine Null.

Zum besseren Verständnis hab ich mal eine Testbench hochgeladen. Damit 
kannst du das simulieren und siehst schön das Verhalten von der 
Beschreibung.

von tobi.python (Gast)


Lesenswert?

Danke dir für die Rückmeldung!

Das kann gut sein haha. Dafür bin ich jetzt etwas schlauer und kann auf 
meine Wortwahl in Zukunft achten =D

Ich habe mir bereits Vivado von Xilinx runtergeladen und kopiere da 
manche Quellcodes rein, da sie dort entspannter zu lesen sind und die 
Plattform auch VHDL konform ist.

Habt ihr vielleicht Tipps, wie ihr solche Schaltungen, die von fremder 
Hand verfasst sind, versteht? Für mich ist das immer bisschen schwierig, 
da jeder seinen eigenen Stil mit sich bringt …

von tobi.python (Gast)


Lesenswert?

Hey Wow vielen Dank !!! Das ganze auch mal visuell zu sehen hilft enorm, 
da man sich die ganzen Signalläufe schlecht vorstellen kann !!!

Was ist denn der Sinn von einem Vorwarts Rückwärts Zähler, also wo 
findet sowas seine Anwendung, wenn ich fragen darf ?

Wozu braucht man eine Clock dafür, lässt sich das nicht ohne realisieren 
? Indem man zB das ganze flankensteuert? Und wieso haben wir hier zwei 
mal Inputs generiert, die Schaltungen, die ich bis jetzt gesehen habe, 
hatten lediglich 1 Eingang und ein Ausgang und falls man mal mehrere 
gebraucht hat, wurde das entsprechend als Vector definiert.

von Gustl B. (-gb-)


Lesenswert?

tobi.python schrieb:
> Ich habe mir bereits Vivado von Xilinx runtergeladen und kopiere da
> manche Quellcodes rein, da sie dort entspannter zu lesen sind und die
> Plattform auch VHDL konform ist.

Das geht auch gut mit Notepad++ den finde ich sogar dem Editor in Vivado 
überlegen.
Simulieren kannst du schön mit der gratis Version von Modelsim.

tobi.python schrieb:
> Habt ihr vielleicht Tipps, wie ihr solche Schaltungen, die von fremder
> Hand verfasst sind, versteht?

Übung. Sehr viel Übung. Lese einfach regelmäßig hier im Forum mit und 
löse die Probleme Anderer. Das ist ein prima Training.

von Jennifer S. (Firma: privat) (jennys) Benutzerseite


Lesenswert?

Hallo Tobi,
ich glaube, den besten Einstieg bekommst Du, wenn Du Dir erst einmal 
klar machst, was der Unterschied zwischen Programmieren eines 
Mikroprozessors/-controllers und dem Programmieren eines FPGAs ist.
Beim Mikroprozessor hast Du eine CPU-Einheit, und Du fütterst mit Deinem 
Programm sequenzielle Anweisungen (tu dies, tu das) in die CPU. Die 
arbeitet alles nacheinander ab.
Beim VHDL ist es so, dass wie Herbert es geschrieben hat, im FPGA 
funktionsfreie Einheiten (Flip Flops, Logik) mit Verdrahtungswegen vor 
liegen. Der Chip macht so erst einmal gar nichts.
Im VHDL beschreibst Du dann, erst einmal eine Grundfunktionalität, wie 
eine dieser Einheiten fiktiv zu einer Schaltung zusammen geschaltet 
werden (zum Beispiel Zähler, Multiplexer, Vergleicher....). In der 
Mechanik ist das wie eine Zeichnung einer Schraube. Man sieht wie so was 
funktioniert, aber es ist noch nicht real vorhanden, sondern nur eine 
Skizze.
Im zweiten Schritt Instanzierst Du dann diese Definition, d.h. Du sagst 
mit dem VHDL wie viel von Deinen Zählern, Multiplexern usw. real im FPGA 
zusammen gebaut werden sollen und wie die Verdrahtet werden müssen. Das 
ist fast wie beim Schaltplan-Zeichnen, wo Du auch die Komponenten IC1 
mit IC2 mit einem Strich verbindest. In der Mechanik ist das wie eine 
Zusammenbauanleitung, und der Compiler baut dann das "Schränkchen" mit 
x-Schrauben (gemäß Zeichnung aus Schritt eins) zusammen.
Im dritten Schritt verbindest Du dann die Eingangs- und Ausgangssignale 
mit den Pins des FPGAs (Pin-Mapping).
Ganz wichtiger Unterschied zwischen Mikroprozessor und 
FPGA-Programmierung:
Beim Mikroprozessor ergibt sich eine sequenzielle Abarbeitung des Codes 
automatisch durch das Programm. Gleichzeitigkeit ist erst einmal was 
exotisches und schafft Probleme (Mutex, Semaphore...).
Beim FPGA passiert grundsätzlich alles gleichzeitig, d.h. wenn Du einen 
Addierer definierst und instanzierst, dann gibt der auch schon ein 
Ergebnis raus, wenn noch gar keine Operanden zum addieren da waren. Da 
musst Du aktiv Vorgänge sequenzialisieren (z.B. über eine 
Statemaschine), um ungewollte Effekte zu vermeiden. Der Vorteil der 
Gleichzeitigkeit ist, natürlich, dass es rasend schnell geht, und die 
Realität ist ja auch ein Ort, wo vieles gleichzeitig passiert. Da kann 
ein FPGA auch ohne Verklemmung so was verarbeiten. Wenn man das mit dem 
Umdenken geschafft hat, ist VHDL ganz witzig.

von Gustl B. (-gb-)


Lesenswert?

tobi.python schrieb:
> Was ist denn der Sinn von einem Vorwarts Rückwärts Zähler, also wo
> findet sowas seine Anwendung, wenn ich fragen darf ?

Vielleicht Uhr und Stoppuhr? Wobei hier beim runterzählen immer -2 
gerechnet wird.

tobi.python schrieb:
> Wozu braucht man eine Clock dafür, lässt sich das nicht ohne realisieren
> ? Indem man zB das ganze flankensteuert?

Woher sollen die Flanken denn kommen?
elsif rising_edge(CLK) then
macht genau das, es reagiert auf Flanken. Eine Clock hat den Vorteil, 
dass die Flanken einigermaßen den gleichen Abstand haben, also die 
Frequenz fest ist. Du kannst statt Clock natürlich auch einen Taster 
verwenden und da händisch draufdrücken.

tobi.python schrieb:
> Und wieso haben wir hier zwei
> mal Inputs generiert, die Schaltungen, die ich bis jetzt gesehen habe,
> hatten lediglich 1 Eingang und ein Ausgang und falls man mal mehrere
> gebraucht hat, wurde das entsprechend als Vector definiert.

Ein Vector ist quasi ein Bündel aus Leitungen. Hier sind D und Q jeweils 
ein Bündel aus 5 Leitungen die gleich als vorzeichenlose Zahl, unsigned, 
interpretiert werden.
Die anderen Eingänge CLK, S0, ... haben jeweils unterschiedliche 
Aufgaben in der Beschreibung. Aber natürlich könnte man auch diese zu 
einem Vektor zusammenfassen. Dann leidet aber die Lesbarkeit deutlich. 
Also lieber die Ein- und Ausgänge nach Funktion zusammenfassen.
Wie du siehst ist so Code oft schwer zu verstehen, also schreibe lieber 
etwas längeren, einfach zu verstehenden Code als kryptischen kurzen 
Code.

Jennifer S. schrieb:
> Wenn man das mit dem
> Umdenken geschafft hat, ist VHDL ganz witzig.

Exakt! Die Lernkurve ist recht mühsam, aber es lohnt sich.

: Bearbeitet durch User
von tobi.python (Gast)


Lesenswert?

Danke dir Gustl, das sind sehr hilfreiche Tipps!

von Tobi A. (tobi_python)


Lesenswert?

Hey Jennifer vielen Dank für die ausführliche Erörterung, das hat mir 
vieles in einer verständlichen Sprache rübergebracht, auch die Beispiele 
fand ich super. Ja da sagst du was der Umstieg ist nicht so leicht!

Okay das macht tatsächlich Sinn! Ich bin wirklich sehr dankbar Gustl für 
die vielen Erklärungen und für eure (deine) Zeit. Da frage ich mich, 
muss das nicht irgendwie aufhören, also gibt es einen Reset in dieser 
Schaltung oder läuft diese einfach endlos ab ?

von Tobi A. (tobi_python)


Lesenswert?

Eines ist auch noch bisschen schwammig: was sind denn die ganzen S 
Signale S1-S4.reicht der D-Vector nicht um Von 0-15 zu zählen vollkommen 
aus ?

von Gustl B. (-gb-)


Angehängte Dateien:

Lesenswert?

Tobi A. schrieb:
> Da frage ich mich,
> muss das nicht irgendwie aufhören, also gibt es einen Reset in dieser
> Schaltung oder läuft diese einfach endlos ab ?

Nein, das hört nicht auf. Das ist Hardware, eben eine Schaltung.
Aber ob diese Schaltung etwas tut oder nicht hängt natürlich von den 
Eingangssignalen ab. Wenn du da den Takt wegnimmst oder den Reset 
einschaltest, dann macht die nicht mehr viel. Wenn das im FPGA steckt 
dann kannst du den Strom wegnehmen.

Tobi A. schrieb:
> was sind denn die ganzen S
> Signale S1-S4.reicht der D-Vector nicht um Von 0-15 zu zählen vollkommen
> aus ?

Nein mit D wird nicht gezählt. QINT wird als Zähler verwendet.
D wird als Zahl angesehen die man in den Zähler mit S2 = '0' hineinladen 
kann. Damit kann man also von außen einen Zählerstand setzen.

Die anderen Sx Signale werden zur Steuerung verwendet, die haben alle 
ihre Funktion, siehe die Testbench datei die ich oben hochgeladen hatte:

S0  <= counter_reset;
S1  <= counter_clear;
S2  <= counter_not_load;
S3  <= counter_enable;
S4  <= counter_direction;

Aber hier ist auch noch ein Bild mit den benannten Signalen statt den Sx 
Signalen.

von tobi.python (Gast)


Lesenswert?

Ich bin dir sehr dankbar für den Aufwand, das ist sehr lieb, dass du 
nochmal die Signale mit Passenderen Namen benannt hast. Ich bin glaub 
ich auch kurz davor die Schaltung zu verstehen, habe aber noch 
Rückfragen:

„ S0 <= counter_reset; S1 <= counter_clear; S2 <= counter_not_load; S3 
<= counter_enable; S4 <= counter_direction;“

• Also der Reset bedeutet ja, dass wir wieder bei 0 anfangen zu zählen.

• Dasselbe passiert aber auch beim Clear, was ist denn der Unterschied ?

• Counter Not load habe ich überhaupt nicht verstanden… Sorgt der bei 
einer 0 für eine zufällige Zahl bei der wir die Zählung beginnen ?

• Counter Enable heißt dann, solange es auf 1 ist, dass er zählt und 
während er 0 ist, wird nicht gezählt, deswegen z.B. der lange Übergang 
von 29 auf 0.

• Counter Direction bestimmt die Zählrichtung.

Ich hoffe, dass ich es einigermaßen verstanden habe.

von Gustl B. (-gb-)


Lesenswert?

tobi.python schrieb:
> „ S0 <= counter_reset; S1 <= counter_clear; S2 <= counter_not_load; S3
> <= counter_enable; S4 <= counter_direction;“

Das ist nur eine Zuordnung in der Testbench. Denn ich wollte in der 
Testbench nicht S0 ... S4 verwenden sondern sprechendere Namen.

tobi.python schrieb:
> Also der Reset bedeutet ja, dass wir wieder bei 0 anfangen zu zählen.

Ja, und zwar unabhängig davon was alle anderen Signale (auch der Takt) 
machen. Das nennt man asynchronen Restet weil der zu jedem Zeitpunkt und 
unabhängig vom Rest ausgeführt wird.

tobi.python schrieb:
> • Dasselbe passiert aber auch beim Clear, was ist denn der Unterschied ?

Clear ist abhängig vom Takt. Also auch eine Art Reset, aber synchron. 
Eben zu dem Takt. Wenn kein Takt anliegt, also keine Flanken an CLK 
ankommen, dann funktioniert auch das Clear nicht.

tobi.python schrieb:
> • Counter Not load habe ich überhaupt nicht verstanden… Sorgt der bei
> einer 0 für eine zufällige Zahl bei der wir die Zählung beginnen ?

Nein. Das ist das Signal um dem am Eingang D anliegenden Wert als 
aktuellen Zählerstand zu laden. Und zwar active low. Sprich das wird 
gemacht wenn das SIgnal '0' ist. Daher habe ich das not_load genannt 
weil es eben den Wert von D in den Zähler lädt wenn es '0' ist.
Die Zahl ist auch nicht zufällid sondern eben genau das was an D 
anliegt. In meiner Testbench habe ich vorher die 26 an D angelegt
D <= to_unsigned(26,5);
dann warte ich einen Takt
wait for 10 ns;
setze not_load auf '0' damit es D in den Zähler legt
counter_not_load <= '0';
warte wieder einen Takt
wait for 10 ns;
und höre auf mit dem Laden, setze not_load also nach einem Takt wieder 
auf '1'. Damit ist not_load genau für einen Takt lang auf '0' und somit 
aktiv.
counter_not_load <= '1';

tobi.python schrieb:
> • Counter Enable heißt dann, solange es auf 1 ist, dass er zählt und
> während er 0 ist, wird nicht gezählt, deswegen z.B. der lange Übergang
> von 29 auf 0.

Genau.

tobi.python schrieb:
> • Counter Direction bestimmt die Zählrichtung.

Exakt!

tobi.python schrieb:
> Ich hoffe, dass ich es einigermaßen verstanden habe.

Sieht ganz gut aus (-:

von Jennifer S. (Firma: privat) (jennys) Benutzerseite


Lesenswert?

Gustl B. schrieb:
> tobi.python schrieb:
>> Wozu braucht man eine Clock dafür, lässt sich das nicht ohne realisieren
>> ? Indem man zB das ganze flankensteuert?
>
> Woher sollen die Flanken denn kommen?
> elsif rising_edge(CLK) then
> macht genau das, es reagiert auf Flanken. Eine Clock hat den Vorteil,
> dass die Flanken einigermaßen den gleichen Abstand haben, also die
> Frequenz fest ist. Du kannst statt Clock natürlich auch einen Taster
> verwenden und da händisch draufdrücken.

Der Clock ist eigentlich eine total praktische Sache. Die Transistoren 
im Sizlizum des FPGAs haben ein paar bemerkenswerte physikalische 
Eigenschaften. So haben die eine "Propagation Delay" d.h. eine 
Durchlaufzeit, die abhängig von der Zelle ist. Nun sind die Zellen alle 
im gleichen Prozess gemacht und viele auch gleich groß, d.h. sie sind 
sehr ähnlich schnell. Allerdings werden die Zellen bei kälte schneller 
und bei Wärme langsamer. Vor vielen Jahren hatten wir einmal einen 
Grafikkontroller mit Grafikbeschleunigung in einem FPGA implementiert. 
Wir haben die Kiste gequält und im Klimaschrank bei 85°C laufen lassen 
und freuten uns, dass alles stabil lief - bis einer auf die Idee kam, 
das Teil einmal bei -40°C zu testen. Das RAM-Timing verschob sich und 
nichts ging mehr.
Jetzt kommt die Magie mit dem Clock ins Spiel. Wenn die einzelnen 
Funktionalen Einheiten immer wieder mit einem Clock auf ein gemeinsames 
Verständnis von Zeit und Zeitpunkt eingeschworen werden, verschwinden 
(bei konsequenter Benutzung) diese thermischen (auch Exemplarstreuung 
usw.) Effekte, so lange der Clock etwas langsamer wie die Gatter laufen 
und für Synchronität sorgen. Das ist wie beim Tanzen: ohne Musik macht 
jeder wie er mag, sieht lustig aus, aber ab und an gibt es 
Zusammenstöße. Mit dem Takt der Musik geht es dann besser.
Erkauft wird dieser Effekt damit, dass der Clock natürlich die 
Performance des FPGAs mindert. Es gab einmal in der FAU Erlangen 
Studenten, die sich mit der asynchronen Programmierung von FPGAs 
beschäftigt haben. Dabei laufen die Signale wie Wellen durch das FPGA, 
limitiert nur von der Laufzeit der Gatter. An den Grenzen der 
Funktionsdomänen wird es dann interessant, denn da treten dann die 
Problematiken auf, wann man alle Signale zur Weiterverarbeitung hat. Das 
ist wohl beherrschbar, aber deutlich schwieriger zu beherrschen und Du 
musst damit leben, dass Deine Applikation wie ein Thermometer 
funktioniert, mal schneller mal langsamer und bei einem anderen 
Speedgrade eines anderen FPGAs geht es dann wieder los...No Gain without 
Pain...

von Tobi A. (tobi_python)


Lesenswert?

ICH DANKE EUCH ALLEN VIELMALS, IHR HABT MEINEN LERNERFOLG ENORM ERHÖHT 
!!! Wünsche euch allen noch ein angenehmes Wochenende, passt auf euch 
auf!

von Jennifer S. (Firma: privat) (jennys) Benutzerseite


Lesenswert?

Gustl B. schrieb:
> Tobi A. schrieb:
>> Da frage ich mich,
>> muss das nicht irgendwie aufhören, also gibt es einen Reset in dieser
>> Schaltung oder läuft diese einfach endlos ab ?

Der Reset ist ein Hilfsmittel um einmal geordnete Verhältnisse 
herzustellen. Das hilft beim Konstruieren/Programmieren und beim Testen.
Wenn Du mehrere Statemaschines hast, die miteinander interagieren und am 
Anfang stehen die Zustands-Flip Flops irgend wie, dann kannst Du graue 
Haare bekommen. Entweder die Teile entwirren sich mit der Zeit (Wenn 
dahinter eine Steuerung für eine Walzstraße ist, könnte das zu spät 
sein) oder Du kommst in nicht vorher gesehene Zustände wo der eine 
Teilnehmer sagt: "Leg auf" und der andere sagt "Nein, leg Du auf" und 
der erste sagt "Nein, leg Du auf" und so fort. Bei Prozessoren gibt es 
den Brownout (Angelehnt an den Blackout), der tritt auf, wenn die 
Spannungsversorgung eines Prozessors so weit ab sinkt, dass er unter der 
Spezifikation ist, aber der Resetcontroller es dummerweise nicht mit 
bekommen hat. Dann kann es passieren, dass große Teile des Prozessors 
dank Designreserve gar nichts mit bekommen, aber andere Teile, die 
gerade ihre Energie mit Flankenwechseln verbraten haben, plötzlich ins 
leere Spannungsversorgungsregal greifen. Einige Flip Flops sind dann 
angepisst und nehmen irgend einen Zustand ein. Wenn das ein Funktionaler 
Teil ist, den man nicht benutzt, Glück gehabt, beim nächsten Reset ist 
wieder alles in Ordnung. Wenn das aber ein Interface, ein 
Speichercontroller oder das Interruptregister ist, dann Hängt der 
Rechner ganz jämmerlich. Kurzer Exkurs in ein real existierendes 
Problem.

Jetzt zurück zu unserem FPGA-Reset. Wenn Du den Reset nicht nutzt, 
bekommst Du bei komplexen Designs solche zufälligen Zustände wie sie 
beim Brownout vor kommen können als default, also immer. Das willst Du 
nicht wirklich.
Der Reset ist also für den definierten Anfang, nicht um eine Arbeit im 
FPGA zu beenden (aber man kann das Teil natürlich am Schluß im Reset 
halten, macht aber niemand). Dann lieber intern eine Variable definieren 
und wenn die gesetzt ist, dann gehen alle Zustandautomaten in den 
Zustand Halt und die Ausgänge sind definiert. Ein erneuter Reset weckt 
dann die Schaltung wieder auf - deutlich eleganter.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Jennifer S. schrieb:
> Jetzt zurück zu unserem FPGA-Reset. Wenn Du den Reset nicht nutzt,
> bekommst Du bei komplexen Designs solche zufälligen Zustände
Nein, das passiert nicht.
Beim Powerup wird ein RAM-basiertes FPGA (also fast alle bis auf 
Microsemi/Actel) aus einem Flash mit definierten Werten geladen. Nach 
diesem Ladevorgang hat jedes Flipflop eine definierten Zustand und läuft 
immer gleich los.

Kein einziges meiner Designs hat einen Reset-Knopf und deshalb auch 
keinen dedizierten Reset. Nötigenfalls wird einfach das FPGA neu 
geladen.

Und wenn du einen Reset einbaust, dann sorge unbedingt dafür, dass der 
taktsynchron inaktiv wird. Denn sonst bekommst du Designs, die ab&zu 
gleich beim Start austicken,wenn die aber mal gestartet sind, dann 
laufen sie tagelang problemlos.

Zum Hintergrund siehe dort: 
http://www.lothar-miller.de/s9y/categories/35-Einsynchronisieren

Mein Tipp: lass dich nicht von gleichen Namen verführen. Die Begriffe, 
die du von C oder SONST einer prozeduralen Programmiersprache kennst, 
"funktionieren" in VHDL oft anders. Eine VHDL for-Schleife wird in der 
erzeugten Hardware "aufgerollt" und führt zu paralleler Hardware.

Und noch ein Tipp: sieh dir hin&wieder den RTL-Schaltplan des 
Synthesizers an und kontrolliere, ob der deine Hardwarebeschreibung 
verstanden und in die gewünschte Schaltung umgesetzt hat.

von tobi.python (Gast)


Lesenswert?

Ein paar Begriffe, die du verwendet hast, müsste ich jetzt erstmal 
nachschlagen =D danke dir für den zusätzlichen Input! Leider ist das 
tatsächlich bisschen umständlich, wenn man eine andere Sprache gewohnt 
war….

von Duke Scarring (Gast)


Lesenswert?

Tobi A. schrieb:
> Da frage ich mich,
> muss das nicht irgendwie aufhören, also gibt es einen Reset in dieser
> Schaltung oder läuft diese einfach endlos ab?
Endlos? Fast. Das läuft solange, bis jemand kommt und den Stecker zieht 
:-)

Diskrete Schaltungen, z.B. aus 7400-Gattern, hören auch nicht irgendwie 
auf.

Duke

von Tobi A. (tobi_python)


Lesenswert?

Danke für die Ergänzung :-)

von Carsten H. (echtzeit)


Lesenswert?

Hallo liebe VHDLer, ich oute mich auch gleich mal als Anfänger und lese 
mich gerade in die Thematik ein.
Erlaubt mir bitte gleich mal eine Frage zu dem oben genannten 
Beispiel-VHDL.

Warum wird der Umweg über das “interne” Signal QINT gemacht und nicht 
direkt mit dem Port Signal Q gearbeitet?

Danke schon mal!

von Gustl B. (-gb-)


Lesenswert?

Carsten H. schrieb:
> Warum wird der Umweg über das “interne” Signal QINT gemacht und nicht
> direkt mit dem Port Signal Q gearbeitet?

Weil ein Port normalerweise kein speicherndes Verhalten besitzt, das ist 
nur ein Draht/Drahtbündel.
Für einen Zähler braucht man aber Speicher, hier Flipflops. Die 
entstehen (werden verwendet) wenn man Signale getaktet verwendet.

Mit den Ports ginge das auch wenn man Buffer verwendet. Das ist aber 
keine übliche Beschreibung.

von Georg A. (georga)


Lesenswert?

Irgendwie kommt mir der Codeschnippsel bekannt vor. Wo kommt der denn 
her? Kann es sein, dass der zufälligerweise aus einer Klausur von der 
TU-Informatik stammt?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Carsten H. schrieb:
> Warum wird der Umweg über das “interne” Signal QINT gemacht und nicht
> direkt mit dem Port Signal Q gearbeitet?
Weil out-Ports nicht rücklesbar sind und man den out-Port sonst 
fälschlicherweise als inout oder buffer deklarieren müsste. Es gilt 
zurecht als fristloser Kündigungsgrund, wenn man sowas nur aus 
Schreibfaulheit macht.

Abgesehen davon bekommt man in der Simulation ab&zu seltsame Effekte, 
wenn ein Port unnötigerweise als bidirektionaler inout deklariert wird. 
Aber das muss wohl jeder selbst herausfinden...

von Lerninstructor (Gast)


Lesenswert?

Carsten H. schrieb:
> Warum wird der Umweg über das “interne” Signal QINT gemacht und nicht
> direkt mit dem Port Signal Q gearbeitet?

weil Port und signal zwei grundverschiedene Dinge sind. Bei Port kann 
die Eigenschaft 'Richtung' unterschiedliche Eigenschaften haben, ein 
Signal ist prinzipiell immer bidirektional . Ferner kann ein port auf 
ein Signal richtungs-konform gemappt werden, während es bei signalen nur 
die unidirektionale Zuweisung ('<=') gibt .

Man beachte also den Unterschied zwischen dem '<=' als Signal assignment 
und dem '=>' in einer 'port map'.

Deshalb verlangen VHDL Styleguides oft das port-namen je nach Richtung 
auf einen Suffix _o, _i, oder '_io' enden, während signale den Präfix s_ 
erhalten:
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
USE ieee.numeric_std.ALL;
4
5
ENTITY e_aufgabe3 IS
6
  PORT (clk, s0_i, s1_i, s2_i, s4_i, s3_i : IN  std_logic;
7
        d_i                               : IN  unsigned(4 DOWNTO 0);
8
        q_o                               : OUT unsigned(4 DOWNTO 0));
9
END e_aufgabe3;
10
11
ARCHITECTURE behavioral OF e_aufgabe3 IS
12
  SIGNAL s_qint : unsigned(4 DOWNTO 0);
13
14
BEGIN
15
  P1 : PROCESS(s0_i, clk)
16
  BEGIN
17
    IF s0_i = '1' THEN
18
      s_qint <= "0000";
19
    ELSIF rising_edge(clk) THEN
20
      IF s1_i = '1' THEN
21
        s_qint <= "0000";
22
      ELSE
23
        IF s2_i = '0' THEN
24
          s_qint <= d_i;
25
        ELSE
26
          IF s3_i = '1' THEN
27
            IF s4_i = '0' THEN
28
              s_qint <= s_qint - 2;
29
            ELSE
30
              s_qint <= s_qint + 1;
31
            END IF;
32
          END IF;
33
        END IF;
34
      END IF;
35
    END IF;
36
  END PROCESS P1;
37
  q_o <= s_ qint;
38
END behavioral;

wie man sieht macht eine style guide regel nicht gleich einen besser 
lesparen Code, aber es ist schon mal ein Anfang.




--
PS: der berühmt-berüchtigte E.W. Djistrka würde wahrscheinlich in 
Anlehnung am sein Zitat zu BASIC und professinelles Programmieren sagen:

“It is practically impossible to teach good FPGA/ASIC-design to students 
that have had a prior exposure to C-programming: as potential 
programmers they are mentally mutilated beyond hope of regeneration.” 
(engl. "mentally mutilated" -> dt. "geistig verzogen") ;-)

https://www.goodreads.com/quotes/79997-it-is-practically-impossible-to-teach-good-programming-to-students

von Carsten H. (echtzeit)


Lesenswert?

Verstanden - Danke für die zahlreichen Antworten und dass ihr mich vor 
einer fristlosen Kündigung gerettet habt ;-)

von Georg A. (georga)


Lesenswert?

Georg A. schrieb:
> Irgendwie kommt mir der Codeschnippsel bekannt vor. Wo kommt der denn
> her? Kann es sein, dass der zufälligerweise aus einer Klausur von der
> TU-Informatik stammt?

Ich bin mir inzwischen recht sicher, dass die Aufgabe von mir ist. Ist 
mein Coding-Style und auch mein typisches TeX-Layout der Klausuren 
ERA/ETI (Einführung in die Rechnerarchitektur bzw. Technische 
Informatik). Die habe ich von 1997 bis 2013 an der TUM verbrochen, also 
VIELE (inkl. Unteraufgaben und natürlich auch Wiederholungsklausuren), 
daher kann ich mich so ganz konkret nicht mehr dran erinnern ;) Ist 
übrigens Erstsemesterstoff.

Aber evtl. zur Einordnung: Immer gab es da Aufgaben, irgendeine Logik 
und Automaten aus einer mehr oder weniger sinnvollen technischen 
Anforderung zu erstellen. Je nach Lust und Laune aber auch mal etwas 
drüber hinaus, hier also aus einem gegebenen Code das Verhalten 
nachzuvollziehen. Deswegen auch die aussagelosen Steuersignale S*. Wäre 
ja langweilig, wenn die schon CLEAR, LOAD, ENABLE, ADD1 oder SUB2 
heissen würden...

Vermutlich gab es eine Skizze mit einem vorgegebenen Diagramm für alle 
Eingangssignale, und man sollte dann den jeweiligen Stand von QINT 
hinzeichnen.

Da in Vorlesung/Übungen kein Tristate für VHDL in der "echten" Anwendung 
erklärt wurde, gabs auch immer nur in oder out als Portmode. Daher der 
Umweg über das interne QINT-Signal, damit man nicht mit inout oder 
buffer rumspielen muss. Haben aber egal bei welcher Aufgabe eh immer 
irgendwelche Knalltüten ohne technischen Zwang gemacht. Keine Ahnung wer 
ihnen das beigebracht hat, ich jedenfalls nicht ;)

Es kann auch sehr gut sein, dass das mit dem QINT<="0000" kein 
unbeabsichtigter Fehler in der Angabe war, sondern tatsächlich noch eine 
kleine 1Punkt-Zusatzaufgabe ala "der Code enthält einen kleinen Fehler, 
wo?". Die meisten dieser Zählautomaten waren nämlich immer mit 4 Bit (3 
downto 0). Deswegen ist es spannend, wer bei Abweichung von den üblichen 
Aufgaben was merkt (d.h. verstanden hat) oder wer nur auswendig gelernt 
hat.

von raX (Gast)


Lesenswert?

Lothar M. schrieb:
> Weil out-Ports nicht rücklesbar sind und man den out-Port sonst
> fälschlicherweise als inout oder buffer deklarieren müsste.

Sie sind doch rücklesbar ab VHDL-2008.  Was spricht dagegen dieses 
Feature zu nutzen?

von Lerninstructor (Gast)


Lesenswert?

raX schrieb:

> Sie sind doch rücklesbar ab VHDL-2008.  Was spricht dagegen dieses
> Feature zu nutzen?

Synthetisierbarkeit!

Und Ausgangsport sind im real life nicht rücklesbar. Was rücklesbar ist, 
ist das out-FF das vor dem output-port liegt.

Nochmals VHDL ist für die Simualtion, aber nicht für die Synthese 
standardisiert.

von Gustl B. (-gb-)


Lesenswert?

Lerninstructor schrieb:
> Synthetisierbarkeit!

Schon ausprobiert? Geht mit Vivado ganz wunderbar.

von Tippgeber (Gast)


Lesenswert?

Lerninstructor schrieb:
> Was rücklesbar ist,
> ist das out-FF das vor dem output-port liegt.
wenn es benutzt wird, was im code ja explizit erzeugt werden muss, um zu 
verhindern, dass es dem routing zum opfer fällt und damit ein Signal 
vorliegt, an das man ankoppeln kann. Ich empfehle, sich NICHT an die 
Ausgänge von Modulen dranzuhängen, insbesondere dann nicht, wenn man die 
Module nur wegen der Übersichtlichkeit eingeführt hat und in 
Wirklichkeit alles plattoptimieren will.

von Georg A. (georga)


Lesenswert?

Ich habe solche "Tricks" den Studis nicht beigebracht, weil damit auch 
der Eindruck einer "normalen" Programmiersprachen erweckt wird. Es geht 
aber in der Vorlesung eben genau darum, die Unterschiede deutlich zu 
machen. Mit der Art der eventgesteuerten Signalverarbeitung inkl. 
Deltacycles als deren zwangsläufiger Entsprechung von realer HW haben 
die meisten Erstsemester ohnehin schon genug Probleme ("wie, ich kann 
nach einer <=-Zuweisung nicht gleich auf den aktuellen Wert 
zugreifen?"). Da brauch ich jetzt nicht noch irgendwelche nerdigen 
syntaktischen Vereinfachungen aus VHDL-4711, die Leute müssen die 
generelle Struktur kapieren.

Daher ist die Trennung von internem Zustand und der Ausgabe (die hier 
auch nur zufälligerweise mit dem internen Zustand identisch ist) auch 
nochmal etwas, um das hervorzuheben.

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.