Forum: FPGA, VHDL & Co. in VHDL 50MHz auf 2 Mhz runterteilen?


von Olli R. (downunderthunder42)


Lesenswert?

Hallo,

ich bin gerad dabei eine kleine Übungsaufgabe in VHDL zu machen.
Es handelt sich dabei um eine Steuerung für eine Ampelkreuzung.

Als Hardware soll der Spartan 3 verwendet werden, dem ein 50MHz 
Taktsignal zugeführt wird.

Da bei meiner "Ampel" die kleinste vorkommende Zeit bei 0,5s liegt, 
wollte ich aus den 50MHz den erforderlichen Takt von 2Hz ableiten.

mit diesem 2Hz-Takt würde ich dann einen Vorwärtszähler programmieren, 
so dass ich definierte Eingangswerte habe, mit denen ich dann die 
Zustandsübergänge realisieren kann.

Ist dieser Ansatz prinzipiell so richtig/gut?


Als momentan frage ich mich, wie ich konkret den 2Hz-Takt ableiten kann?

Ich müsste eine Prozess konstruieren, in dem nur bei jedem 25*10^6 
Aufruf ein neues Takt-Signal "2HZCLK" gesetzt wird?
also brauche ich da irgendwie einen "sehr großen" Zähler?

kann man so einen Takt nicht auch anders ableiten?

von D. I. (Gast)


Lesenswert?

Olli R. schrieb:
> also brauche ich da irgendwie einen "sehr großen" Zähler?
>
> kann man so einen Takt nicht auch anders ableiten?

Ein 17bit Zähler ist ein Klacks. Ja so macht mans achte aber darauf dass 
du das heruntergeteilte Signal als Clock Enable und nicht als Takt 
verwendest

von Chris (Gast)


Lesenswert?

Du kannst auch ein 25bit LFSR nehmen, ihn auf 25*10^6 zyklen verkürzen 
und
so deinen 2Hz Takt herleiten, oder auch gleich ein 27bit LFSR nehmen und
damit dein 0.5Hz Takt herleiten. Wie man da auf einen 17bit Zähler kommt 
weiß ich nicht, einfacher zu kodieren ist aber ein Zähler welcher die
25*10^6 direkt zählt, normalerweise hast du in diesem Baustein genügend 
resourcen dass du dir da keine Gedanken machen musst.

von D. I. (Gast)


Lesenswert?

Chris schrieb:
> Wie man da auf einen 17bit Zähler kommt
> weiß ich nicht, einfacher zu kodieren ist aber ein Zähler welcher die
> 25*10^6 direkt zählt, normalerweise hast du in diesem Baustein genügend
> resourcen dass du dir da keine Gedanken machen musst.

Ich habe mich im Eifer des Gefechts auch um 2^8 vertan und meinte diese 
Lösung ;)

von Olli R. (downunderthunder42)


Lesenswert?

D. I. schrieb:
> Ja so macht mans achte aber darauf dass
> du das heruntergeteilte Signal als Clock Enable und nicht als Takt
> verwendest

Ok d.h. ich nehme meinen Ursprünglichen Clock von 50MHz und würde eine 
Abfrage inetwa wie folgt machen:

if CLK = '1' and CLK'event then
if ENABLE = '1' then
...

...

d.h. ich mache mit meinem "ENABLE" also dem 2Hz Signal keine 
Flankenabfrage?

warum kann ich den das nicht direkt verwendet bzw. wie sähe das den 
richtig aus?

von D. I. (Gast)


Lesenswert?

Olli R. schrieb:
> d.h. ich mache mit meinem "ENABLE" also dem 2Hz Signal keine
> Flankenabfrage?

genau so ist es.

Naja was kein Takt ist soll man nicht als Takt verwenden, gibt gneug 
threads hier im Forum die das Problem dabei beleuchten.

Aber vielleicht kaut es dir Lothar zum 1466325784. Mal auch nochmal vor 
;) so eine Buddhageduld habe ich leider nicht

von Olli R. (downunderthunder42)


Lesenswert?

D. I. schrieb:
> Aber vielleicht kaut es dir Lothar zum 1466325784. Mal auch nochmal vor
> ;) so eine Buddhageduld habe ich leider nicht

Ok nee kein Thema dann werde ich das mal nächste Woche in ner Vorlesung 
fragen ;)


kann ich meine zählvariable, die ich z.B. wie folgt deklariere:

" signal  COUNTER2HZ: bit_vector(24 downto 0); "

ähnlich wie in C "auch innerhalb eines Prozesses" mit z.B.

COUNTER2HZ <= COUNTERHZ +1;

-- inkrementieren?

if COUNTER2HZ='25000000' then -- kann ich '25000000' so schreiben?
ENABLE2HZ ='1';
COUNTER2HZ <= '0';
elsif
ENABLE2HZ = '0'

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


Lesenswert?

Olli R. schrieb:
> Da bei meiner "Ampel" die kleinste vorkommende Zeit bei 0,5s liegt
Dann hast du offenbar noch keine Fußgängertaste...  ;-)

Olli R. schrieb:
> kann ich meine zählvariable, die ich z.B. wie folgt deklariere:
> " signal  COUNTER2HZ: bit_vector(24 downto 0); "
Vergiss das bit und den bit_vector am besten gleich wieder und verwende 
die "üblichen" Vektoren: std_logic, unsigend, signed. Und zum Zählen am 
einfachsten einen integer...
http://www.lothar-miller.de/s9y/archives/14-Numeric_Std.html

> ähnlich wie in C
Vergiss C und die dahinterstehende Denkweise sofort. Versuch nicht 
mal, nur wegen einer syntaktischen Nähe auch eine funktionale Nähe zu 
suchen.
> "auch innerhalb eines Prozesses" mit z.B.
(Vorerst) eigentlich nur dort...
> COUNTER2HZ <= COUNTERHZ +1;
So wirst du noch öfter über die sehr strenge Typprüfung stolpern
Mit einem Integer geht das aber problemlos.

> if COUNTER2HZ='25000000' then -- kann ich '25000000' so schreiben?
Nein.
> ENABLE2HZ ='1';
Falsch.
> COUNTER2HZ <= '0';
hmm...
> elsif
> ENABLE2HZ = '0'
Und jetzt?

Sieh dir mal mein Beispiel eines Lauflichts an (eine Ampel ohne 
Fußgängertaste ist eigenlich nichts anderes):
http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html

Und vor ichs vergesse. Leih dir ein Buch zum Thema VHDL aus:
VHDL-Synthese Reichardt&Schwarz

D. I. schrieb:
> Aber vielleicht kaut es dir Lothar zum 1466325784. Mal auch nochmal vor
Du hast mitgezählt...  :-o
Ich verweise auf die Suche mit den Begriffen "Anfänger Postulate" hier 
im Forum:
http://www.mikrocontroller.net/search?query=anf%C3%A4nger+postulate&forums[]=9&max_age=-&sort_by_date=1

von Olli R. (downunderthunder42)


Angehängte Dateien:

Lesenswert?

OK ich hab jetzt mal einen Frequenzteiler 50MHz auf 2Hz auf Grundlage 
von Lothar Millers Frequenzteiler für das Lauflicht.

Jetzt müsst' ich doch mit diesem CLKENABLE einen Binärvorwärtszähler 
realisieren können, dessen Zählwerte für den Übergang von Zustand zu 
Zustand dienen können?

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


Lesenswert?

Olli R. schrieb:
> auf Grundlage von Lothar Millers Frequenzteiler für das Lauflicht.
Nein. Hast du nicht.
Denn sowas findest du bei mir nicht:
1
   if  CLK = '1' and CLK'event then
Was, wenn CLK vorher 'H' war oder 'X' oder 'U'?
Richtig: deine Simulation sieht einen Takt, wo keiner ist...

Deshalb: rising_edge() oder falling_edge().

Olli R. schrieb:
> Jetzt müsst' ich doch mit diesem CLKENABLE einen Binärvorwärtszähler
> realisieren können, dessen Zählwerte für den Übergang von Zustand zu
> Zustand dienen können?
Ja, das ist soweit die richtige Vorgehensweise...

von abc (Gast)


Lesenswert?

>ich bin gerad dabei eine kleine Übungsaufgabe in VHDL zu machen.
>Es handelt sich dabei um eine Steuerung für eine Ampelkreuzung.
>
>Als Hardware soll der Spartan 3 verwendet werden, dem ein 50MHz
>Taktsignal zugeführt wird.
>
>Da bei meiner "Ampel" die kleinste vorkommende Zeit bei 0,5s liegt,
>wollte ich aus den 50MHz den erforderlichen Takt von 2Hz ableiten.


DY, erster Versuch  @ Fitz? HAW-Hamburg?

von Olli R. (downunderthunder42)


Lesenswert?

abc schrieb:
> DY, erster Versuch  @ Fitz? HAW-Hamburg?

korrekt aber ich denke, dass ich die Lösung bald hab ;)

von Olli R. (downunderthunder42)


Angehängte Dateien:

Lesenswert?

OK irgendwie ist mir das alles doch noch ziemlich befremdlich.

Ich das ganze nochmal überdacht und den Versuch eines "Zustanddiagrammes 
gemacht (siehe Anhang). Die Aufgabe ist hier zu finden:
http://users.etech.haw-hamburg.de/users/fitz/DY_FTZ_Labor_1.pdf
( Ich möchte hier natürlich kein komplette Lösung vorgekaut bekommen, 
sonst wäre der Lernerfolg -> 0 aber ein paar Ansätze wären nicht 
schlecht)

Also wie man den Folgezustand berechnet, kann ich mir denken bzw. das 
ist mir soweit klar.
Bei einem Takt alle 0,5 s muss ich ja die meisten Zustände mehrfach 
hintereinander haben.
Dies könnte man ja wie in dem hier angefügten Diagramm mit Zählern 
realisieren.
Aber wie kann ich die Abhängigkeit von 4 externen Signal da einbringen.
z.B. möchte ich die Zähler für die beiden Grünphasen von 4 Sensoren in 
der Fahrbahn abhängig machen?

Dann gibt es die Grünanforderung von Fußgänger, d.h. während eines 
regulären Durchlaufs soll ein "Signal" gesetzt werden, das dann 
dazuführt, dass am Ende des Durchlaufs einmal eine "Fußgängergrünphase" 
durchlaufen wird.

wie kann man so ein Signal, dass von 2 Eingänge abhängig ist setzen und 
speichern und dann am Ende der Fußgängergrünphase wieder zurücksetzen?

Der RESET soll, wenn er gesetzt ist dazuführen, dass (egal in welchem 
Zustand ich mich befinde) in den Gelb-Blink-Modus gewechselt wird!
wenn RESET wieder 0 ist soll diese Blinkphase nach 1,5s Dauergelb wieder 
verlassen werden.




Wie könnte ich die genannte Abhängigkeit von Eingangssignal in das 
Zustandsdiagramm aufnehmen?

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


Lesenswert?

Olli R. schrieb:
> Ich das ganze nochmal überdacht und den Versuch eines "Zustanddiagrammes
> gemacht (siehe Anhang).
Das was da links unten steht "asynchron hierher, wenn Reset ='1'" und 
"solange Reset = '1' wird zwischen diesen 2 Zuständen gewechselt" lässt 
sich für mich nicht in Deckung bringen...  :-o

Und zudem wird in der Aufgabenstellung nichts von einem asynchronen 
Reset erwähnt. Dann lass den ganz einfach weg.

> wie kann man so ein Signal, dass von 2 Eingänge abhängig ist setzen und
> speichern
Du nimmst ein Flipflop, das mit 50 MHz getaktet wird (Einsynchronisieren 
des asynchronen externen Signals nicht vergessen)
> und dann am Ende der Fußgängergrünphase wieder zurücksetzen?
Du setzt das FF einfach wieder zurück.

Immer im Hinterkopf behalten:
In der Hardware wird das alles komplett parallel abgebildet. Du hast 
also gleichzeitig die Abfrage der Fußgängertaster und die Abarbeitung 
deiner FSM.

von Olli R. (downunderthunder42)


Lesenswert?

Lothar Miller schrieb:
> Das was da links unten steht "asynchron hierher, wenn Reset ='1'" und
> "solange Reset = '1' wird zwischen diesen 2 Zuständen gewechselt" lässt
> sich für mich nicht in Deckung bringen...  :-o
>
> Und zudem wird in der Aufgabenstellung nichts von einem asynchronen
> Reset erwähnt. Dann lass den ganz einfach weg.

Ich beziehe mich auf die Blinkanforderung für die Nacht:

Heißt das, dass ich dafür einen Eingang (Taster) nehme, der mir ein 
Flipflop setzt (wenn Eingang = 1) und das FF zurücksetzt, wenn Eingang = 
0?
FF-Signal wird dann für die Verzweigung im Automatengraph verwendet!


zu den Fahrbahnsensoren bzw. Fußgängergrünanforderung:

Heißt das, dass ich die Eingangssignale (die 4 Fahrbahnsensoren) als 
nebenläufige Anweisung bzw. als Prozeß der mit 50MHz getakt wird (z.B. 
indem ich ein FF realisere) "verarbeite" und somit ein weiteres Signal 
"Hauptstraße länger Grün" generiere?

Lothar Miller schrieb:
>> und dann am Ende der Fußgängergrünphase wieder zurücksetzen?
> Du setzt das FF einfach wieder zurück.

Kann ich für dieses Zurücksetzen soetwas z.B. schreiben:
if zustand = 12 and zaehler = 14 then
-- "Zustand12 = Fußgängerampeln Grün; letzte Durchlauf des Zustandes 12 
--> Zähler = 12"

fuss_anforderung = 0; end if;

--> Ich hab ja bei meinen ersten Versuchen gemerkt, dass ich versucht 
habe, in mehr als einem Prozeß ein Signal gleichzeitig zu definieren!
Dass das nicht geht ist mir jetzt so langsam klar, da ja alles quasi 
gleichzeitig läuft.
Aber eine Abfrage von Signalen ist doch auch parallel möglich (also 
mehrere Prozesse können dasselbe Signal als "Bedingung" nutzen? (ist ja 
quasi nur "ein Stück Draht, dass auf mehrere Eingänge zugleich gelegt 
wird"?!

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


Lesenswert?

Olli R. schrieb:
> Kann ich für dieses Zurücksetzen soetwas z.B. schreiben:
Grundsätzlich ja.
Ich würde diese Fußgängeranforderung also grog etwa so machen:
1
signal sr_ft : std_logic_vector (2 downto 0) := "000"; -- Schieberegister zum Eintakten und Flankenerkennung Fussgaengertaste
2
  process begin
3
     wait until rising_edge(the_one_and_only_clock);
4
     sr_ft <= sr_ft(1 downto 0) & eingang_fussgaengertaste;
5
     if (sr_ft(2 downto 1) = "01") then -- steigende Flanke an der Fussgaengertaste
6
        fuss_anforderung <= '1';
7
     end if;
8
     if (zustand = 12 and zaehler = 14) then -- dein Beispiel
9
        fuss_anforderung <= '0';
10
     end if;
11
  end process;

Olli R. schrieb:
> Aber eine Abfrage von Signalen ist doch auch parallel möglich (also
> mehrere Prozesse können dasselbe Signal als "Bedingung" nutzen?
Ja richtig.

> FF-Signal wird dann für die Verzweigung im Automatengraph verwendet!
Du verknüpfst hier 2 komplett unterschiedliche Abstaktionsebenen. Im 
Automatengraph interessiert nur die theoretische Schrittfolge. Wie das 
irgendwie auf Hardware abgebildet wird, ist zu der Zeit noch 
uninteressant.

Dein Automat wird später sowieso in irgendwelche FFs abgebildet...

> Heißt das, dass ich die Eingangssignale (die 4 Fahrbahnsensoren) als
> nebenläufige Anweisung bzw. als Prozeß der mit 50MHz getakt wird (z.B.
> indem ich ein FF realisere) "verarbeite" und somit ein weiteres Signal
> "Hauptstraße länger Grün" generiere?
Die Fussgängertaste und die Fahrbahnsensoren sind nur Hilffsignale, 
deren Erzeugung im "großen" Automatendiagramm gar nicht auftauchen. Wenn 
du willst, kannst du den VHDL-Code von oben auch in ein Zustandsdiagramm 
malen...

> als Prozeß der mit 50MHz getakt wird
JEDER getaktete Prozess wird mit diesem Takt angesteuert. Es gibt nur 1 
Takt im ganzen Design...

von Olli R. (downunderthunder42)


Lesenswert?

sorry aber irgendwie muss ich zu diesem Teil nochmal was fragen:

also du deklarierst einen std_logic_vector mit der Länge 3Bit!
dann verkettest du die unteren beiden Bit dieses Vektors "sr_ft" mit
eingang_fussgaengertaster!
> sr_ft <= sr_ft(1 downto 0) & eingang_fussgaengertaste; --> speichert er jetzt 
eingang_fussgangertaster in sr_ft(2)?
dann fragst du ab, ob die oberen Bits von "sr_ft" "01" sind?
wie was hätte denn nicht auch eine einfache Bit-Variable oder std_logic
Variable gereicht?
>     if (sr_ft(2 downto 1) = "01") then -- steigende Flanke an der
also nur if eingang_fussgaengertaste = "1" then   ??
>         fuss_anforderung <= '1';


Moment jetzt glaube ich es zu verstehen:

sr_ft <= sr_ft(1 downto 0) & eingang_fussgaengertaste;

hiermit wird also "eingang_fussgaengertaste an die Stelle 0 von sr_ft 
gepackt. korrekt?

dadurch fällt der höchste Wert in sr_ft weg!

if (sr_ft(2 downto 1) = "01") then -- steigende Flanke an der 
Fussgaengertaste

Der Wert der Fussgaengertaste wird also wie folgt durch geschoben:

sr_ft:   Bit 2  1   0
             0  0   1  <-- Fussgängertaste gedrückt
             0  1   1  <-- Taste immer noch gedrückt und  Ausgang wird 
gesetzt      1  1   1  <-- Ausgang ist gesetzt und Taste gedrückt
             1  1   0  <-- Taste wird losgelassen
             1  0   0  <-- Taste losgelassen; ausgang bleibt die ganze 
Zeit gesetzt 0  0   0  <-- Taste losgelassen ("komplett durchgelaufen")


Somit wird das FlipFlop nur einmal gesetzt während
sr_ft =   0 1 1 oder 0 1 0 (der zweite Zustand ist aber 
unwahrscheinlich, dann müsste die Person, die drück schon nach 20 bis 40 
ns wieder losgelassen haben! ;)


Ich hoffe meine "Verständniserläuterung" war verständlich.

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


Lesenswert?

Olli R. schrieb:
> Somit wird das FlipFlop nur einmal gesetzt während
> sr_ft =   0 1 1 oder 0 1 0
Richtig. Nur an der steigenden Flanke wird das FF gesetzt.
> (der zweite Zustand ist aber unwahrscheinlich, dann müsste die Person,
> die drück schon nach 20 bis 40 ns wieder losgelassen haben! ;)
Oder die Taste müsste einen (anfangs) schlechten Kontakt haben, oder 
prellen, oder wasweißich...

> Ich hoffe meine "Verständniserläuterung" war verständlich.
Ich habe verstanden, dass du ein Schieberegister und die 
Flankenauswertung verstanden hast.

> oder 0 1 0
Wenn du jetzt noch ein klitzekleinwenig weiter gedacht hättest... :-/

... dann wäre dir aufgefallen, dass diese mitllere '1' auch nur ein 
kleiner Störspike sein könnte...  :-o
Aus diesem Grund ist es in der harten Praxis ratsam, eine Taste/Sensor 
nicht direkt mit dem Systemtakt einzulesen, sondern mit z.B. 10ms 
Abstand zwischen den "Schiebeoperationen" abzuwarten.
Und zudem das Schieberegister etwas breiter zu machen und mehr Bits 
abzufragen. Also z.B. auf "01111" zu vergleichen. Bei diesem 
Schieberegister müsste das Signal also mindestens 40ms stabil angelegen 
haben (4 x '1')...
Siehe dort: http://www.lothar-miller.de/s9y/categories/5-Entprellung

von Olli R. (downunderthunder42)


Lesenswert?

Lothar Miller schrieb:
> Aus diesem Grund ist es in der harten Praxis ratsam, eine Taste/Sensor
> nicht direkt mit dem Systemtakt einzulesen, sondern mit z.B. 10ms
> Abstand zwischen den "Schiebeoperationen" abzuwarten.

Ok klar also habe ich so schon mal ne leichte Entprellung!
ok für das halten von 10ms müsste ich in diesem Fall eine Zähler haben, 
der den Wert 500 hat (bei Takt alle 20ns).

Ok ich werd die Tage mich dann auf das eigentliche Programm 
konzentrieren und dann das Entprellen mit einbauen!

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


Lesenswert?

Olli R. schrieb:
> ok für das halten von 10ms müsste ich in diesem Fall eine Zähler haben,
> der den Wert 500 hat (bei Takt alle 20ns).
Noch ein paar Nullen (3 Stück) dazu, aber die Idee passt... ;-)
Und dieses "heruntergeteilte" Signal verwendest du dann aber nicht als 
Takt, sondern als Clock-Enable!

> Ok klar also habe ich so schon mal ne leichte Entprellung!
Damit?
>> Also z.B. auf "01111" zu vergleichen.
Richtig. Aber eben nur eine sehr sehr kurze...

von Olli R. (downunderthunder42)


Angehängte Dateien:

Lesenswert?

OK jetzt habe ich es mal versucht umzusetzen.
Ich kann es leider nicht kompilieren.
Ich bekomme vom ModelSim kompiler diverse Fehlermeldungen, die ich so
nicht genau interpretieren kann.

Des weiteren ist mir noch nicht genau klar, wie ich es schaffe, das 
quasi
asynchron in den Blink-Nacht-Modus gewechselt wird?

Quasi wie ich über "NACHT_ANF" das erste Mal in den Zustand NACHT1 
kommen kann?


Achso ich gehe nun von einem Systemtakt von f = 1KHz aus!

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


Lesenswert?

Olli R. schrieb:
> Ich bekomme vom ModelSim kompiler diverse Fehlermeldungen, die ich so
> nicht genau interpretieren kann.
Welche denn?

> --- nicht synthetisierbare Testbench Prozesse:---
So ist das zumindest sehr unüblich.
IdR. ist eine Testbench ein VHDL-Modul ohne Ports. In dieses Modul wird 
die zu testende Komponente eingebunden...

> ANFORDERUNG_FUSS: process(GN_FU_ANF_H, GN_FU_ANF_N)
>     begin
>        if CLK = '1' and CLK'event then ...
>
> FAHRBAHNSENS: process(SENS1, SENS2, SENS3, SENS4)
>    variable SENSKOMB: bit_vector (3 downto 0);
>    begin
>      if CLK = '1' and CLK'event then ...
Diese Prozesse sind AUSSCHIESSLICH auf den CLK sensitiv, denn NUR eine 
Änderung von CLK kann ein neues Ergebnis bewirken. Also ist die 
Sensitivliste falsch!

>    variable SENSKOMB: bit_vector (3 downto 0);
>         SENSKOMB <= SENS1 & SENS2 & SENS3 & SENS4;
>         case SENSKOMB is
Das ginge ohne Variable auch so:
>         case SENS1 & SENS2 & SENS3 & SENS4 is

Und der Klassiker bei der Zwei-Prozess-Schreibweise:
Eine kombinatorische Schleife... ;-)
1
-- Übergangsschaltnetz (Folgezustandsberechnung)
2
UE_SN: process (ZAEHLER,ZUSTAND,FU_ANF_SET, H_ZAHL, N_ZAHL)   -- hier fehlt noch AUSGANG, denn eine ÄNDERUNG von AUSGANG ändert auch AMPEL_H, AMPEL_N...
3
    begin                                                            
4
     AUSGANG <= ALLEAN;
5
     AMPEL_H <= AUSGANG(9 downto 7);
6
     AMPEL_N <= AUSGANG(6 downto 4);
7
     :
8
     FOLGE_Z <= INIT;
9
     case ZUSTAND is 
10
        when INIT => AUSGANG <= ALLEAN;
11
                     -- Achtung, jetzt kommt ein Zähler im kombinatorischen Teil einer 2-Prozess-FSM
12
                     if (ZAEHLER <=7) 
13
                     then FOLGE_Z <= INIT;        -- solange der Zähler kleiner gleich 7 ist wird im Zustand INIT verweilt
14
                          zaehler <= ZAEHLER +1;  -- der Zähler wird inkrementiert
15
                          -- ^--- Zähler können nur im getakteten Teil realisiert werden !!!!
Zähler können nur im getakteten Teil realisiert werden, denn die müssen 
ja speichern können. Und speichernde Elemente sind getaktete Elemente 
und damit Flipflops (kommm mir jetzt bloß keiner mit Latches, damit kann 
man keine Zähler bauen).
http://www.lothar-miller.de/s9y/categories/36-Kombinatorische-Schleife

von Olli R. (Gast)


Lesenswert?

Lothar Miller schrieb:
> when INIT => AUSGANG <= ALLEAN;
>                      -- Achtung, jetzt kommt ein Zähler im kombinatorischen Teil 
einer 2-Prozess-FSM


könnte ich diesen Zähler dann in dem getakteten Prozess, in dem ich auch 
sage:

ZUSTAND <= FOLGE_Z
inkrementieren:
ZAEHLER = ZAEHLER +1?


und dann durch eine abfrage z.b zaehler_reset = 1
dann ZAEHLER = 0;

wobei ich "zaehler_reset" bei der zustands_zuweisung gegebenenfalls 
setze?

     AUSGANG <= ALLEAN;
     AMPEL_H <= AUSGANG(9 downto 7);
     AMPEL_N <= AUSGANG(6 downto 4);

dieser Teil ist so auch nicht möglich:
Ich möchte doch nur die jeweiligen Bits einem AMPEL_SIGNAL zuweisen?


aber abgesehen von dem Zähler kann ich das so machen? (ich habe leider 
gerade keine Möglichkeit zu testen)

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


Lesenswert?

Olli R. schrieb:
> dieser Teil ist so auch nicht möglich:
Die Punkte : sind Abkürzungspunkte, Fortsetzungspunkte wie die hier ...
Ich muß ja nicht deinen ganzen Quelltext kopieren, wenn ich nur Teile 
davon anspreche...

> könnte ich diesen Zähler dann in dem getakteten Prozess...
Ja, und nur dort.

Und sieh dir wie gesagt die Sensitivlisten nochmal an, sonst ist deine 
Simulation (und nur die interessiert sich dafür) schlicht falsch!

von Olli R. (Gast)


Lesenswert?

Olli R. schrieb:
> AMPEL_H <= AUSGANG(9 downto 7);
>      AMPEL_N <= AUSGANG(6 downto 4);

Die Punkte : sind Abkürzungspunkte, Fortsetzungspunkte wie die hier ...

ich meinte,dass AMPEL_N <= AUSGANG(6 downto 4);
nicht wie von mir gewünscht BIt 6 bis Bit 4 an AMPEL_N "gibt".

> könnte ich diesen Zähler dann in dem getakteten Prozess...
Ja, und nur dort.

ok das Inkrementieren kann ich also im getakteten Prozess machen.
Könnte ich aber das Rücksetzen des ZAEHLERS (ZAEHLER <= 0); trotzdem 
noch
im Prozeß für die Zustandsberechnung machen? oder hätte ich dann wieder 
die Kombinatorische Schleife?

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


Lesenswert?

Olli R. schrieb:
> Könnte ich aber das Rücksetzen des ZAEHLERS (ZAEHLER <= 0); trotzdem
> noch im Prozeß für die Zustandsberechnung machen?
Nein, denn auf das Signal ZAHLER darf nur 1 Prozess treiben.
> oder hätte ich dann wieder die Kombinatorische Schleife?
Wenn das ginge, dann hättest du einen asynchronen kombinatorischen 
Reset. Und den kannst du brauchen wie ein Stück Hundesche..e am Schuh. 
Glaubs mir.

Aber zum Glück gehts gar nicht... ;-)

Olli R. schrieb:
> ich meinte,dass AMPEL_N <= AUSGANG(6 downto 4);
> nicht wie von mir gewünscht BIt 6 bis Bit 4 an AMPEL_N "gibt".
Warum nicht?
Was tut er denn?

Wie schon erwähnt ist deine Sensitivliste unvollständig:
1
UE_SN: process (ZAEHLER,ZUSTAND,FU_ANF_SET, H_ZAHL, N_ZAHL)   -- hier fehlt noch AUSGANG, denn eine ÄNDERUNG von AUSGANG müsste auch AMPEL_H, AMPEL_N... ändern

von Olli R. (downunderthunder42)


Lesenswert?

Lothar Miller schrieb:
>> ich meinte,dass AMPEL_N <= AUSGANG(6 downto 4);
>> nicht wie von mir gewünscht BIt 6 bis Bit 4 an AMPEL_N "gibt".
> Warum nicht?
> Was tut er denn?

Error: ampels.vhd(65): Prefix of slice name must be an array.

Ich kann diese Kompiler-Meldung nicht einordnen. (Auch Google half mir 
noch nicht!)?

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


Lesenswert?

Olli R. schrieb:
> AMPEL_N <= AUSGANG(6 downto 4);
Jetzt seh ichs erst: du willst hier den Typ AUSGABE zerteilen:
1
type AUSGABE is (ALLEAN, ALLEROT, ALLEAUS, GELB, H_GRUEN, N_GRUEN, H_GELB, N_GELB, H_GE_RT, N_GE_RT, FUSS_GRUEN);
Das geht erst mal natürlich nicht:
Denn was wäre dann eigentlich AUSGANG(6 downto 4)?

Nein, mit deinen ENCODING geht das nicht!
Das ist lediglich ein kleiner Hinweis an das Synthesetool, doch bitte 
die Codierung der oben angeführten Zustände so auszuführen:
1
attribute ENUM_ENCODING of AUSGABE: type is "1111111111 1001001010 0000000000 0100100000 0011001010 1000011010 0101001010 1000101010 1101001010 1001101010 1001000101";
Die Simulation kann damit nichts anfangen...

Und dazu kommt noch:
AUSGABE hat mit std_logic(_vector) überhaupt NICHTS gemeinsam
1
subtype std_logic_vector is array (NATURAL range <>) of std_logic;
Deshalb kann ohne Konvertierung vom einen Signal nichts auf das Andere 
zugewiesen werden!


Machs wie der Rest der Welt:
Lass den Synthesizer seine FSM selber optimieren und weise die 
Lampensignale abhängig von den Zuständen direkt zu (z.B. mit einem CASE 
oder WHEN)...

: Bearbeitet durch Moderator
von Olli R. (downunderthunder42)


Angehängte Dateien:

Lesenswert?

Lothar Miller schrieb:
> attribute ENUM_ENCODING of AUSGABE: type is "1111111111 1001001010 0000000000 
0100100000 0011001010 1000011010 0101001010 1000101010 1101001010 1001101010 
1001000101";
> Die Simulation kann damit nichts anfangen...
>
> Machs wie der Rest der Welt:
> Lass den Synthesizer seine FSM selber optimieren und weise die
> Lampensignale abhängig von den Zuständen direkt zu (z.B. mit einem CASE
> oder WHEN)...

OK ja das ist mir jetzt auch gerad klar geworden also
dieses ENUM_ENCODING ist nur eine Anweisung an den Präprozessor!

Jetzt habe ich das Programm zumindest schon soweit gelöst, dass es 
kompiliert wird.

Leider ist es so, dass das Programm nach dem es den Zustand "INIT" nach 
7s das erste Mal verlassen hat, in den Zustand "REG1" wechselt dann geht 
es aber aus irgendeinem Grund wieder in den Zustand INIT und dann wieder 
in den Zustand REG1.
Er pendelt quasi nur zwischen den Zuständen INIT und REG1??

von Olli R. (downunderthunder42)


Angehängte Dateien:

Lesenswert?

hier noch ein Auszug aus dem Impulsdiagramm

ich habe die Simulation mit den folgenden Parametern gestartet:


vcom ampels.vhd
vsim work.AMPELSTEUERUNG
add wave sim:/AMPELSTEUERUNG/CLK
add wave sim:/AMPELSTEUERUNG/CLKENABLE
add wave sim:/AMPELSTEUERUNG/SENS1
add wave sim:/AMPELSTEUERUNG/SENS2
add wave sim:/AMPELSTEUERUNG/SENS3
add wave sim:/AMPELSTEUERUNG/SENS4
add wave sim:/AMPELSTEUERUNG/GN_FU_ANF_H
add wave sim:/AMPELSTEUERUNG/GN_FU_ANF_N
add wave sim:/AMPELSTEUERUNG/NACHT_ANF
add wave sim:/AMPELSTEUERUNG/RESET
add wave sim:/AMPELSTEUERUNG/AMPEL_H
add wave sim:/AMPELSTEUERUNG/AMPEL_N
add wave sim:/AMPELSTEUERUNG/AMPEL_FUSS_H
add wave sim:/AMPELSTEUERUNG/AMPEL_FUSS_N
run 500000 ms

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


Lesenswert?

Olli R. schrieb:
> dieses ENUM_ENCODING ist nur eine Anweisung an den Präprozessor!
Einen Präprozessor gibt es nicht.
Es ist ein Wunsch an den Synthesizer. Wenn der das versteht, setzt er 
die Zustände so um. Wenn nicht, dann nicht. Aber normalerweise gibts 
dann eine passende Warning/Info...

> Er pendelt quasi nur zwischen den Zuständen INIT und REG1??
Warum?
Um das herauszufinden ist eine Testbench da. Da kannst du ja sehen, was 
kurz vor dem fehlerhaften Zustand passiert ist...

Mach mal deine "Testbench" aus der Beschreibung raus. Das ist so extrem 
verwirrend...

BTW:
                      if ZAEHLER_RESET = '0'
                            then ZAEHLER <= ZAEHLER +1; end if;
                            if ZAEHLER_RESET = '1'
                            then ZAEHLER <= 0;
                            end if;
Das kannst du ohne jegliche Verhaltensänderung so schreiben:
                      if ZAEHLER_RESET = '0' then
                          ZAEHLER <= ZAEHLER +1;
                      else
                          ZAEHLER <= 0;
                      end if;
Oder gar so:
                      ZAEHLER <= ZAEHLER +1;
                      if ZAEHLER_RESET = '1' then
                          ZAEHLER <= 0;
                      end if;

von Olli R. (downunderthunder42)


Angehängte Dateien:

Lesenswert?

Lothar Miller schrieb:
> Mach mal deine "Testbench" aus der Beschreibung raus. Das ist so extrem
> verwirrend...

Ok ich hab es jetzt so umgeformt, das es für die Synthese taugt, 
allerdings
weiss ich jetzt nicht genau, wie man da die Testbenches macht.

Das war dann irgendwie mit force bei Modelsim?

Wie geht man da am besten vor?




P.S. sorry, dass ich so häufig hier nachfrage aber die Ampel ist ja 
quasi mein erstes VHDl-Programm. ;)

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


Lesenswert?

Olli R. schrieb:
> weiss ich jetzt nicht genau, wie man da die Testbenches macht.
2 Sachen sind nötig:
1. Eine Testbench hat keine Ports.
2. In diese Testbench (die den vollen Sprachumfang von VHDL nutzen kann)
   wird dein Modell als Komponente eingebunden.

Sieh dir mal die PS2-Schnittstelle da an:
http://www.lothar-miller.de/s9y/archives/75-PS2-Tastatur.html
Da gibt es die eigentliche Entity PS2_Keyboard,
die in der Entity PS2_tb als Komponente eingebunden und stimuliert 
wird...

> Das war dann irgendwie mit force bei Modelsim?
Das ist Murks. Ich habe das noch nie verwendet... :-/

BTW:
> Ok ich hab es jetzt so umgeformt, das es für die Synthese taugt,
Du hast dir aber beim Prozess
FAHRBAHNSENS: process(SENS1, SENS2, SENS3, SENS4)
Latches eingefangen. Das mag man nicht auf einem FPGA. Und die Synthese 
weist dich darauf hin, ob du die Dinger tatsächlich willst und du dir 
der Konsequenzen bewusst bist...
Latches gibt es, wenn in einer kombinatorischen Zuweisung nicht alle 
Pfade auscodiert sind, und auch keine Defaultzuweisung da ist. Lies mal 
VHDL-Synthese von Reichardt&Schwarz...

Die Konsequenzen von Latches sind (insbesondere, wenn sie wie bei dir) 
kombinatorisch angesteuert werden, dass die Laufzeit nicht mehr 
berechenbar und daher nicht mehr kontrollierbar ist.

EDIT:
> die Ampel ist ja quasi mein erstes VHDl-Programm. ;)
Ja, du machst zwei Schritte auf einmal und fällst aufs Maul (in Prosa 
gesprochen). Besser hättest du zum Lernen erst mal ein Lauflicht (in 
allen Variationen) beschrieben und verstanden...
http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html

von Olli R. (downunderthunder42)


Lesenswert?

Lothar Miller schrieb:
> Du hast dir aber beim Prozess
> FAHRBAHNSENS: process(SENS1, SENS2, SENS3, SENS4)
> Latches eingefangen. Das mag man nicht auf einem FPGA. Und die Synthese
> weist dich darauf hin, ob du die Dinger tatsächlich willst und du dir
> der Konsequenzen bewusst bist...
> Latches gibt es, wenn in einer kombinatorischen Zuweisung nicht alle
> Pfade auscodiert sind, und auch keine Defaultzuweisung da ist. Lies mal
> VHDL-Synthese von Reichardt&Schwarz...

Ich glaube so sollte das "Latch" weg sein mit dem else habe ich doch 
alle mögliche Fälle abgedeckt?

FAHRBAHNSENS: process(SENS1, SENS2, SENS3, SENS4)
    begin
           if ((SENS1 = '1' or SENS2 = '1') and SENS3 = '0' and SENS4 = 
'0')
           then H_ZAHL <= 11;
                N_ZAHL <= 3;
           else
                H_ZAHL <= 9;
                N_ZAHL <= 7;
           end if;

    end process FAHRBAHNSENS;


VHDL-Synthese hab ich hier schon rum liegen und die ersten 150Seiten die 
letzten Tage gelesen und weitestgehend nachvollzogen.
Und dort wird das mit der Testbench allerdings so beschrieben, wie ich 
es zuvor schon inetwa gemacht hab:

STIMULI oder TAKTGEN erstellen, keine Ports verwende also die Eingänge 
vorrübergehend als Signale deklarieren.

Deine testbench bezogen auf Ps2 kann ich jetzt so nicht ganz 
nachvollziehen!

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


Angehängte Dateien:

Lesenswert?

Olli R. schrieb:
> VHDL-Synthese hab ich hier schon rum liegen und die ersten 150Seiten die
> letzten Tage gelesen und weitestgehend nachvollzogen.
> Und dort wird das mit der Testbench allerdings so beschrieben
Das ist auch kein buch, in dem die Feinheiten von Testbenches erklärt 
werden!
Es heißt nicht umsonst "VHDL-Synthese"...

> Ich glaube so sollte das "Latch" weg sein mit dem else habe ich doch
> alle mögliche Fälle abgedeckt?
Ja.

> STIMULI oder TAKTGEN erstellen, keine Ports verwende also die Eingänge
> vorrübergehend als Signale deklarieren.
Nein. Eine Testbench ändert überhaupt nichts am Testobjekt. Die 
Testbench wird aussenrum gebaut und beinhaltet dein synthesefähiges 
Modul. Die Testbench bildet/beschreibt die Umwelt deines Moduls (=Lampen 
+ Taster + Sensoren).

Hier mal ein einfaches Beispiel einer PWM und einer entsprechenden 
Testbench (=Takt und Comparewerte):
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity PWM is
6
    Port ( clk     : in  STD_LOGIC;
7
           compare : in  STD_LOGIC_VECTOR (7 downto 0);
8
           pwmout  : out  STD_LOGIC);
9
end PWM;
10
11
architecture Behavioral of PWM is
12
signal counter : unsigned(7 downto 0) := x"00";
13
begin
14
15
   process (clk) begin
16
      if rising_edge(clk) then
17
         counter <= counter+1;
18
      end if;
19
   end process;
20
21
   pwmout <= '1' when counter <= unsigned(compare) else '0';
22
   
23
end Behavioral;

Und hier die Testbench:
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
USE ieee.numeric_std.ALL;
4
 
5
ENTITY TB_PWM IS
6
   -- Eine Testbench hat keine Ports
7
END TB_PWM;
8
 
9
ARCHITECTURE behavior OF TB_PWM IS 
10
11
   -- meine zu testende Komponente
12
   COMPONENT PWM 
13
   PORT( clk : IN  std_logic;
14
         compare : IN  std_logic_vector(7 downto 0);
15
         pwmout : OUT  std_logic );
16
   END COMPONENT;
17
18
   -- Signale zur Verdrahtung
19
   signal clk : std_logic := '0';
20
   signal compare : std_logic_vector(7 downto 0) := (others => '0');
21
   signal pwmout : std_logic;
22
23
BEGIN
24
25
  -- hier wird eine Instanz "Mein_Pruefling" mit meiner Komponente angelegt
26
   Mein_Pruefling: PWM PORT MAP ( clk => clk, compare => compare, pwmout => pwmout);
27
28
   -- der Takt
29
   clk <= not clk after 250 ns;
30
31
   -- verschiedene Compare-Werte 
32
   stim_proc: process
33
   begin    
34
      compare <= x"01";
35
      wait for 1 ms;  
36
      compare <= x"3f";
37
      wait for 1 ms;  
38
      compare <= x"7f";
39
      wait for 1 ms;  
40
      compare <= x"bf";
41
      wait for 1 ms;  
42
      compare <= x"ff";
43
      wait;
44
   end process;
45
46
END;

Und heraus kommt dann z.B. so eine Waveform wie im Anhang.

Allerdings ist eine Waveform keine sinnvolle Sache, wenn irgendwas 
automatisiert geschen muß, weil z.B. die Compare-Daten aus einer Datei 
gelesen werden und anschliessend überwacht werden soll, ob die richtige 
Pulsweite herauskommt. Dafür gibt es dann Assertions und Text-IO und den 
ganzen Sprachumfang von VHDL...

von Olli R. (downunderthunder42)


Lesenswert?

Jo
Cool Vielen Dank Lothar.

Mit deinem kleinen PWM-Beispiel konnte ich ne Menge anfangen.

Ich hab für mein Proggi auch so eine testbench erstellt und ich muss 
sagen:
dadurch ist das alles ja weit übersichtlicher, da das eigentliche 
Programm so verbleibt, wie es dann auch synthetisiert wird.

Dennoch hat es noch eine Weile gedauert aber nur, weil mir einige Fälle 
in den Sinn gekommen sind, die bei so einer Ampel eher ungünstig sind. 
Z.B.

wenn Fußgänger gerade Grün hatten, ist soll doch wenn in der 
anschließenden Rot-Phase wieder eine Fußgänger-Grün-Anforderung kommt, 
wenigstens eine der beiden Straßen eine Grünphase gehabt haben.

Mit einer zusätzlichen, zwischen zu speichernden "Variablen" bzw. 
bit-signal ging das dann doch ganz gut.

Aber jetzt habe ich zumindest mal gesehen, welche Schwierigkeiten so bei 
der VHDL-Programmierung bestehen und werden dann auch mal tiefer in ein 
paar deiner Beispiele einsteigen.

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.