Forum: FPGA, VHDL & Co. Kombinatorik und Takt trennen?


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Dussel (Gast)


Lesenswert?

Moin,
letztens hatte ich eine Diskussion über VHDL-Beschreibungsarten. Ich 
habe mir VHDL selber beigebracht, der andere hat es im Studium gelernt.
Darf man getaktete Zuweisung und Kombinatorik mischen oder sollte das in 
zwei Prozessen getrennt sein.
Ein Beispiel habe ich hier anhand eines einfachen Zählers, der ständig 
bis zum Maximalwert hochzählt und dann wieder bei 0 anfängt.
Ich würde das in einen Prozess schreiben
1
entity Gemeinsam is
2
    port(
3
        clk     : in std_ulogic;
4
        reset   : in std_ulogic;
5
        Wert    : out std_ulogic_vector(7 downto 0)
6
    );
7
end entity Gemeinsam;
8
9
architecture Verhalten of Gemeinsam is
10
    signal Zaehler      : integer range 0 to 255;
11
    constant Maximal    : integer:=20;
12
begin
13
    process(clk)
14
    begin
15
        if rising_edge(clk) then
16
            if reset='1' then
17
                Zaehler<=0;
18
            else
19
                if Zaehler=Maximal then
20
                    Zaehler<=0;
21
                else
22
                    Zaehler<=Zaehler+1;
23
                end if;
24
            end if;
25
        end if;
26
   end process;
27
  
28
   Wert<=std_ulogic_vector(to_unsigned(Zaehler,8));
29
end Verhalten;

Im Studium wurde es wohl so gelehrt, mit zwei Prozessen
1
entity Getrennt is
2
    port(
3
        clk     : in std_ulogic;
4
        reset   : in std_ulogic;
5
        Wert    : out std_ulogic_vector(7 downto 0)
6
    );
7
end entity Getrennt;
8
9
architecture Verhalten of Getrennt is
10
    signal Zaehler        : integer range 0 to 255;
11
    signal Zaehler_nach   : integer range 0 to 255;
12
    constant Maximal      : integer:=20;
13
begin
14
    process(clk)
15
    begin
16
        if rising_edge(clk) then
17
            Zaehler<=Zaehler_nach;
18
        end if;
19
    end process;
20
  
21
    process(reset,Zaehler)
22
    begin
23
        if reset='1' then
24
            Zaehler_nach<=0;
25
        else
26
            if Zaehler=Maximal then
27
                Zaehler_nach<=0;
28
            else
29
                Zaehler_nach<=Zaehler+1;
30
            end if;
31
        end if;
32
    end process;
33
  
34
    Wert<=std_ulogic_vector(to_unsigned(Zaehler,8));
35
end Verhalten;

Ob ich das in der zweiten Version so richtig hinbekommen habe, weiß ich 
nicht ganz genau, weil ich diese Schreibweise eigentlich nicht verwende. 
Zumindest funktioniert es in der Simulation.
Es geht darum, ob in diesem Beispiel das Zaehler+1 in dem getakteten 
Teil stehen soll oder in einem eigenen Prozess.
Es gibt die Regel, dass man rein kombinatorische Prozesse oder rein 
sequentielle Prozesse verwenden soll, aber das bezieht sich doch eher 
auf sowas wie
1
process(clk)
2
begin
3
    if rising_edge(clk,[andere Signale]) then
4
        [Anweisungen]
5
    end if;
6
7
    Signal<=[Kombinatorik aus anderen Signalen]
8
end process;
oder?

Mir fällt auf, dass die zweite Variante eine Verzögerung von einem Takt 
hat. Außerdem muss der kombinatorische Prozess eine Senstitivity-List 
mit vielen Signalen haben, wodurch es leicht zu Fehlern kommen kann. 
Deshalb bevorzuge ich die erste Version. Aber irgendeinen Grund muss es 
doch geben, dass die zweite gelehrt wird.
Was meint ihr, welche ist besser, welche benutzt ihr, welchen Grund gibt 
es, die eine zu benutzen und nicht die andere?

von Stefan (Gast)


Lesenswert?

Geht beides. Ist nur eine andere Art der StateMachine. Und ich finde 
gerade bei großen Programmen die Trennung übersichtlicher

von Rolf E. (Firma: Appsys ProAudio) (roffez)


Lesenswert?

Ich persönlich finde die 1-Prozess-Methode leichter lesbar (komme aber 
von C her und habe deshalb vielleicht andere Präferenzen).

Ansonsten kann ich noch den Guru (Lothar Miller) zitieren, er sagt über 
die 2-Prozess-Darstellung: "Aber wer sich den Code ein halbes Jahr 
später anschaut, wird den Kopf schütteln, und sich fragen, wie und was 
da wann wozu verwendet wird". Der vollständige Text, sehr lesenswert 
(wie auch alles andere auf seiner Seite):

http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html

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


Lesenswert?

Dussel schrieb:
> Darf man getaktete Zuweisung und Kombinatorik mischen oder sollte das in
> zwei Prozessen getrennt sein.
Man darf im Prinzip, was man will...

Aber man sollte es nicht "mischen" in dem Sinn, dass Takte und 
Kombinatorik im Prozess beliebig durcheinander kommen (aus wenn das 
tatsächlich umgesetzt werden könnte):
1
entity Gemeinsam is
2
    port(
3
        clk     : in std_ulogic;
4
        reset   : in std_ulogic;
5
        Wert    : out std_ulogic_vector(7 downto 0)
6
    );
7
end entity Gemeinsam;
8
9
architecture Verhalten of Gemeinsam is
10
    signal Zaehler      : integer range 0 to 255;
11
    constant Maximal    : integer:=20;
12
begin
13
    process(clk, Zaehler)
14
    begin
15
        if rising_edge(clk) then
16
            if reset='1' then
17
                Zaehler<=0;
18
            else
19
                if Zaehler=Maximal then
20
                    Zaehler<=0;
21
                else
22
                    Zaehler<=Zaehler+1;
23
                end if;
24
            end if;
25
        end if;
26
        Wert<=std_ulogic_vector(to_unsigned(Zaehler,8));
27
   end process;
28
  
29
end Verhalten;

Der Rest ist die Dskussion um die 1-Prozess vs. 2-Prozess-Beschreibung. 
Hierzu ein paar Worte:
http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html


> Mir fällt auf, dass die zweite Variante eine Verzögerung von einem Takt > hat.
Das kommt darauf an, welches Signal du ansiehst: den Eingang des 
Flipflops oder seinen Ausgang. Solche unerwartete "Latency" hast du eher 
mal, wenn du mit der 1-Prozess-Schreibweise neu beginnst...

von Rolf E. (Firma: Appsys ProAudio) (roffez)


Lesenswert?

Lothar, Du warst zu langsam!

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

Jetzt schreib ich mal meine Variante.
1
  process(clk)
2
    begin
3
      if rising_edge(clk) then
4
5
        if Zaehler=Maximal then
6
          Zaehler<=0;
7
        else
8
          Zaehler<=Zaehler+1;
9
        end if;
10
11
12
        if reset='1' then
13
          Zaehler<=0;               
14
        end if;
15
16
      end if;
17
   end process;

Die letzt Zuweisung gewinnt.
Wenn der Reset am Ende des Process ist, dann enfällt das else in der 
höchsten if-Ebene.

von Rolf E. (Firma: Appsys ProAudio) (roffez)


Lesenswert?

How about that one? Nice, short and clean...

1
p : process 
2
begin
3
    wait until rising_edge(clk);
4
    if (reset = '1') or (zaehler = maximal) then
5
       zaehler <= 0;
6
    else 
7
       zaehler <= zaehler+1;
8
    end if;
9
end process;

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


Lesenswert?

Rolf E. schrieb:
> How about that one?
Die Vermischung von Reset und Funktion ist verwirrend. Ich nehme den 
goldenen Zwischenweg:
1
  process begin
2
      -- beim nächsten Takt
3
      wait until rising_edge(clk);
4
5
      -- Funktion bearbeiten
6
      if Zaehler=Maximal then  Zaehler<=0;
7
      else                     Zaehler<=Zaehler+1;
8
      end if;
9
10
      -- Zum Schluss: Reset, weil die letzte Signalzuweisung "gewinnt"
11
      if reset='1' then        Zaehler<=0;               
12
      end if;
13
   end process;

Siehe dort unten:
http://www.lothar-miller.de/s9y/categories/34-Getakteter-Prozess

Rolf E. schrieb:
> Lothar, Du warst zu langsam!
Schlags kaputt... ;-)

: Bearbeitet durch Moderator
von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

Heute is mal wieder mal was im Forum los. Macht richtig Spaß.

Gibt es einen Unterschied zwischen den beiden Anweisungen?
1
      wait until rising_edge(clk);
2
3
      if rising_edge(clk) then

von Markus F. (Gast)


Lesenswert?

Rolf E. schrieb:
> Appsys ProAudio

René D. schrieb:
> Gibt es einen Unterschied zwischen den beiden Anweisungen?

Das mit dem "wait" kapiert nicht jeder Synthesizer. Simutechnisch ist es 
dasselbe. Meine ich.

von Markus F. (mfro)


Lesenswert?

René D. schrieb:
> Heute is mal wieder mal was im Forum los. Macht richtig Spaß.
>
> Gibt es einen Unterschied zwischen den beiden Anweisungen?
>
>
1
>       wait until rising_edge(clk);
2
> 
3
>       if rising_edge(clk) then
4
>

wenn ein wait im Prozess vorkommt, muss die Sensitivliste leer sein.
wenn keins vorkommt, sollte was drinstehen...

von Dussel (Gast)


Lesenswert?

Die Ein-, Zwei- und Dreiprozessschreibweise für Zustandsautomaten kenne 
ich, aber handelt es sich bei dem gezeigten denn um einen 
Zustandsautomaten?
Man kann natürlich die einzelnen Zählerstände als Zustände auffassen, 
aber ein praktischer Zustandsautomat wird es dadurch doch noch nicht, 
oder?

Rolf E. schrieb:
> Ich persönlich finde die 1-Prozess-Methode leichter lesbar (komme aber
> von C her und habe deshalb vielleicht andere Präferenzen).
Das geht mir genauso.

René D. schrieb:
> Gibt es einen Unterschied zwischen den beiden Anweisungen?
Gibt's da auch was von Lothar Miller?
Selbstverständlich: 
http://www.lothar-miller.de/s9y/archives/16-Takt-im-Prozess.html ;-)

von Matthias (Gast)


Lesenswert?

Wir verwenden die 2Prozess-Methode ala Gaisler.

@TO:
Signale nicht in Sensitivity List:
Deshalb benutzt oben genannte Methode Records.

Ein Takt Delay:
Du machst eine Zuweisung von "Zaehler" statt "Zaehler_nach"

Das Reset kann/muss/sollte dann oben asynchron im clocked process 
stehen. Der Reset Release  muss synchron erfolgen.

von Markus F. (Gast)


Lesenswert?

Matthias schrieb:
> Wir verwenden die 2Prozess-Methode ala Gaisler.
Ist das von denen so definiert worden? Ich kenne das ebenfalls als 
zwei-Prozess-Beschreibung, schon aus der Software - ganz ohne Gaisler.

von Matthias (Gast)


Lesenswert?

Ja, ist Teil des Coding Styles.

Ich weiß auch dass andere Riesen nicht nach 2 Prozess machen.

Es ist halt, wie so oft, Religion. Clock Domain Crossing erhöht 
natürlich die Zahl an Prozessen...

von Matthias (Gast)


Lesenswert?

In den Coding Standard steht nicht "tu es wie gaisler", aber ich würde 
meinen, dass wir im Wesentlichen dem folgen.
Ich kenne beides und finde auch beides ok. Beides hat +\-, wobei mir 
momentan die 2 Prozess Methode gut gefällt.

Wie gesagt: gefallen... kommt eh dasselbe raus, meistens hoffe ich.

von Novice (Gast)


Lesenswert?

Ich hab mich mit dem Thema auch schon öfters bschäftigt (meistens mit 
Focus auf SV, aber das ist ja nur die Sprache), deshalb hier meine 
(etwas längeren) 2Cents:

Ich bin auch ein Anhänger des "Gaisler Styles" 
(http://www.gaisler.com/doc/vhdl2proc.pdf). Die wichtigsten Vorteile für 
mich:
- im kombinatorischen Prozess steht rein die funktionale Beschreibung 
des Moduls, clock und reset sehen im eigenen Prozess. Durch die 
Schreibweise mit records entsteht nicht mehr Code als beim 1 
Prozessmodell.
- ich kann auch nicht getaktete Signale steuern
- im kombinatorischen Prozess kann ich zugewiesene Variablen 
weiterverwenden (ja, das wird selten benötigt)
- im Simulator kann ich sehr einfach zwischen Registern (alles was in 
dem Register record ist) und kombinatorischen Signalen unterscheiden.
- Manchmal ist es hilfreich in der Simulation die next state signale 
beobachten zu können
- ich definiere die Resetwerte als Konstante des Registerrecords, somit 
kann ich die Resetwerte gleich unterhalb von der Definiton des 
Registerrecords machen. Weiters kann ich den Reset öfters zuweisen ohne 
alles neu zu schreiben. Z.B. wenn es neben dem asynchronen Reset noch 
einen Synchronen (Soft) Reset gibt.

Das Problem mit dem Verwalten der Sensitivitylist gibts seit VHDL 2008 
eigentlich nicht mehr. Es gibt "process(all)"

Die Argumente hier von Lothar 
(http://www.lothar-miller.de/s9y/archives/43-Ein-oder-Zwei-Prozess-Schreibweise-fuer-FSM.html) 
kann ich nicht nachvollziehen. Meiner Meinung nach wird in diesem Post 
das 2 Prozessmodell nicht konsequent angewendet. Denn 'delay' ist das 
einzige Signal, das im getakteten Prozess maintained wird. Warum? Hier 
sollte nur "delay <= next_delay;" stehen und alles weitere wieder im 
kombinatorischen.

von Weltbester FPGA Pongo (Gast)


Lesenswert?

Novice schrieb:
> Ich hab mich mit dem Thema auch schon öfters bschäftigt (meistens mit
> Focus auf SV,
Das scheint mir Wesentlich. Wenn SW angekoppelt wird, sind 
zusammengefasste Datentypen vorteilhaft, da stimme ich zu. Allerdings in 
Designs, in denen ein hartes timing im Modul generiert wird, nicht. 
Alles, was IO ist, bekommt da nur einen Mehraufwand.

> - im Simulator kann ich sehr einfach zwischen Registern (alles was in
> dem Register record ist) und kombinatorischen Signalen unterscheiden.
Das ist aber eine Frage der Beschreibung:
Wenn man Präfixes sauber benutzt, hat man keinen Nachteil, es bleibt 
aber der Vorteil, dass es zwischen Record-Signalen und Variablen 
ausserhalb von Records keinen Unterschied gibt.

>  Z.B. wenn es neben dem asynchronen Reset noch
> einen Synchronen (Soft) Reset gibt.
Etwas, was es in einem sinnvoll aufgezogenen FPGA-Design niemals gibt 
:-)

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


Lesenswert?

Markus F. schrieb:
> Das mit dem "wait" kapiert nicht jeder Synthesizer.
Doch, inzwischen schon.  Vor 10 Jahren war das noch neu. Da gab es noch 
welche,  die Probleme hatten. Z.B. auch mit der Initialzuweisung an 
Signale...

Novice schrieb:
> Meiner Meinung nach wird in diesem Post das 2 Prozessmodell nicht
> konsequent angewendet. Denn 'delay' ist das einzige Signal, das im
> getakteten Prozess maintained wird. Warum? Hier sollte nur "delay <=
> next_delay;" stehen und alles weitere wieder im kombinatorischen
Richtig, und genau  das verstehen offenbar viele Anfänger nicht.  Such 
einfach mal hier im Forums nach "kombinatorische Schleife" oder 
"combinatorial loop". Dieser Fehler taucht laufend auf. Und zu 99% warst 
dann eben ein Zähler im kombinatorischen Prozess...

Novice schrieb:
> . Z.B. wenn es neben dem asynchronen Reset noch einen Synchronen (Soft)
> Reset gibt.
Welches FPGA kann das? Oder andersrum: warum sollte man etwas 
beschreiben, was hinterher nur umständlich und aufwändig in Hardware 
umgesetzt werden kann?
Ich sehe hier das selbe Problem wie bei der Softwareentwicklung: obwohl 
die Prozessoren schneller werden, werden die Programme langsamer und 
"fetter"...

: Bearbeitet durch Moderator
von Novice (Gast)


Lesenswert?

Weltbester FPGA Pongo schrieb im Beitrag #4605911:
> Novice schrieb:
>> Ich hab mich mit dem Thema auch schon öfters bschäftigt (meistens mit
>> Focus auf SV,
> Das scheint mir Wesentlich. Wenn SW angekoppelt wird, sind
> zusammengefasste Datentypen vorteilhaft, da stimme ich zu. Allerdings in
> Designs, in denen ein hartes timing im Modul generiert wird, nicht.
> Alles, was IO ist, bekommt da nur einen Mehraufwand.
Mit SV meinte ich SystemVerilog.

von Novice (Gast)


Lesenswert?

@Lothar:
Aja, den entscheidenden Satz hab ich vorher überlesen:
>Jetzt könnte ich das Spiel genauso wie mit counter und next_counter machen,
>aber diesmal bin ich zu faul und nehme den Verzögerungszähler delay einfach
>gleich in den getakteten Teil:
Naja, mit dem Gaisler Style wird die Faulheit umgangen, da man das 
Signal auch nur einmal definieren muss.
Aber wie schon weiter oben erwähnt, 1 vs. 2 Prozesse ist eine 
Entscheidung des Entwicklers. Ein richtig oder falsch gibts nicht.

von Matthias (Gast)


Lesenswert?

@Lothar:
Wird die 2 Prozess Methode richtig angewendet, gibt's die 
Kombinatorische Schleife gar nicht, da typischerweise stehen sollte:

S.count := Reg.count + 1;

Aber ja, weißt ja eh, "wenn man es richtig macht"... ;-)

von Markus F. (mfro)


Lesenswert?

Lothar M. schrieb:
> Markus F. schrieb:
>> Das mit dem "wait" kapiert nicht jeder Synthesizer.

Niemals nicht hab' ich das geschrieben!

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


Lesenswert?

Markus F. schrieb:
> Niemals nicht hab' ich das geschrieben!
Richtig, da zitiert die Foren-SW ein wenig ungünstig:
Markus F. schrieb:
> Meine
Markus F. schrieb:
> Niemals

Matthias schrieb:
> Wir verwenden die 2Prozess-Methode ala Gaisler.
Gaisler schafft es hier, einen Beschreibungsstil (genau diese 
2-Prozessmethode mit getrennter Weiterschaltlogik und Registern) der 
schon früh am Ende des letzten Jahrtausends in jedem Lehrbuch stand, im 
Jahre 2010 in neue Schläuche zu füllen und als frischen (und vor Allem: 
eigenen) Wein zu verkaufen...

von J. S. (engineer) Benutzerseite


Lesenswert?

Dann wird es jetzt wohl Zeit, die Prozesslandschaft 4.0 zu definieren 
und noch eine weitere kompliziertere Methode als NEU einzuführen. Immer 
mal was Neues.


René D. schrieb:
> Die letzt Zuweisung gewinnt.
> Wenn der Reset am Ende des Process ist, dann enfällt das else in der
> höchsten if-Ebene.

Das ist eine Sache, die viele Firmen in ihren Richtlinien ausschließen, 
nämlich, dass die Reihenfolge der Anweisungen eine Rolle spielen darf.

Bevorzugt werden ALLE Signale in allen Zweigen klar und ausdrücklich 
beschrieben. Wenn es zu kompliziert wird und die Bedinungen zu unschön 
überlappen, dann werden eben mehrere Prozesse definiert und zwar einer 
für jedes Signal.

Das erleichtert das Debuggen, weil explizite Zuweisungen existieren und 
Denkfehler bei der manuellen Simulation, die man ja quasi durchführen 
muss, nicht aufkommen oder ausdrüclich einprogrammiert hätten werden 
müssen.

In der Gesamtbetrachtung ist es so, daß es momenten noch recht egal ist, 
welche Schreibweisen der oberen verwendet wird, aber das ändert sich, 
wenn komplexe Rechenalgorithmen eingebaut werden sollen.

In der Mehrprozessschreibweise muss man dann immer die 
Vorher-Nachhersignale definieren. Braucht kein Mensch.Wir benutzten ja 
die Hochsprache, um Zuweisungen implizit zu vollziehen und nicht die 
FF-Struktur aufmalen zu müssen.

von Novice (Gast)


Lesenswert?

Jürgen S. schrieb:
> In der Mehrprozessschreibweise muss man dann immer die
> Vorher-Nachhersignale definieren. Braucht kein Mensch.Wir benutzten ja
> die Hochsprache, um Zuweisungen implizit zu vollziehen und nicht die
> FF-Struktur aufmalen zu müssen.
Naja, schau dir mal den Gaisler Style genauer an.

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


Lesenswert?

Novice schrieb:
> Naja, schau dir mal den Gaisler Style genauer an.
In welcher Hinsicht? Auf was sollte man da genauer schauen?

von Novice (Gast)


Lesenswert?

Durch die Schreibweise mit den records muss jedes Signal auch nur einmal 
im Code definiert werden.

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


Lesenswert?

Mal davon abgesehen, dass auch ich jedes Signal nur 1 mal definiere: was 
haben Records jetzt mit der 2-Prozess-Schreibweise zu tun?

von Weltbester FPGA-Pongo (Gast)


Lesenswert?

Die Querverbindung kam über die Gaisler-Pamphlete und die fragwürdige 
Schlussfolgerung einiger Jünger, daß wenn eine Gaisler-Idee gut ist, der 
Rest auch gut sein müsse.

Eine spontane Umfrage in der hiesigen Abteilung ergab im Übrigen:

3 kennen das gar nicht
4 kennen das, benutzen es aber nicht
2 kennen das, benutzen es nur teilweise
1 kennt es und hält sich weitgehend dran

Das ist ein Anteil von 14% derer, die es kennen. In ganz Deutschland 
gibt es also unter allen 44000 embedded Ingenieuren rund 6000 
Gaisler-Jünger.

Bagwhan hatte zu seinen Besten Zeiten 100mal mehr. Da gibt es also noch 
Überzeugungsarbeit zu leisten :D

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.