Forum: FPGA, VHDL & Co. Variable vs Signal


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von thomas (Gast)


Lesenswert?

Hallo,

ich hab es mir angewöhnt Variablen in Prozesse zu verwenden, weil es zum 
Einen übersichtlicher ist, wenn die Deklarationen direkt beim Prozess 
stehen und zum Anderen, weil man aktuell zugewiesene Werte gleich wieder 
lesen kann.

Ich hab mitgekriegt, dass immer davon abgeraten wird, dass man das macht 
und man soll Signale stattdessen verwenden.

Ich programmiere VHDL seit 2 Jahren und auch deutlich mehr als nur 
irgendwelche Blinklichter und hab z.B. FIR-Filterbänke mit Variablen usw 
implementiert und nie Probleme festgestellt.

Woher kommt es, dass jeder so gegen Variablen ist? Ich finde es 
übersichtlicher, einfacher zu verwenden und es ist klarer, was passiert.

Weiß jemand was dazu?

Grüße
thomas

von Falk B. (falk)


Lesenswert?

@thomas (Gast)

>Woher kommt es, dass jeder so gegen Variablen ist? Ich finde es
>übersichtlicher, einfacher zu verwenden und es ist klarer, was passiert.

Weil Variablen ein anderes Zuweisungsverhalten als Signale haben, und 
das von Anfängern gern missverstanden wird. Hatte ich vor einiger Zeit 
schon mal am Beispiel dargestellt, musst du mal suchen.

MFG
Falk

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


Angehängte Dateien:

Lesenswert?

Ich bevorzuge die uniforme Verwendung von Signalen zur Synthese,
weil sonst solche Ammenmärchen auftauchen:
http://esd.cs.ucr.edu/labs/tutorial/
unter "Discussion I: Signal vs. Variable".

Da wird z.B. behauptet, die Ergebnisse der beiden Prozesse 
(http://esd.cs.ucr.edu/labs/tutorial/sig_var.vhd) seien anders, weil das 
in der Simulation so aussieht 
(http://esd.cs.ucr.edu/labs/tutorial/sig_var.jpg). Der Fehler liegt hier 
aber nicht im unterschiedlichen Verhalten von Signalen und Variablen, 
sondern schlicht und einfach in der unvollständigen Sens-List vom proc2. 
Und das passiert leicht, wenn man einen Prozess erst mal mit Variablen 
beschreibt, und dann dieses prozessinterne Ergebnis global haben möchte. 
Beim anschliessenden manuellen Ersetzen der Variable durch ein Signal 
wird schon mal die Sens-List vergessen.
In der Hardware werden beide Prozesse (abgesehen von einer Warnung wegen 
der unvollständigen Sens-List) sowieso identisch realisiert (Bild).

Korrekt müsste die Sens-List vom proc2 so heissen:
1
  proc2: process(d1,d2,d3,sig_s1)
Dann stimmt auch das Verhalten der beiden Prozesse überein.


In der Simulation, wo ich ja mal den gesamten Syntaxumfang von VHDL 
ausschöpfen darf, sind mir Variablen gern gesehen.
Auch zur Beschreibung und Bearbeitung von Schleifen in der Synthese sind 
sie (oft) unumgänglich.

Aber für Anfänger (und auch für mich, obwohl kein Anfänger mehr) gilt:
Versuche, die Aufgabe mit Signalen zu lösen.
Wenn es tatsächlich nicht anders geht, nimm Variable.

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


Lesenswert?

Etwas OT:
Dieses "Vergessen" von Signalen passiert übrigens recht gern und z.B. 
auch im Beispiel:
http://toolbox.xilinx.com/docsan/xilinx4/data/docs/sim/coding4.html

Dort ist im Prozess SIG das Signal D vergessen worden.
1
 SIG:process (A,B,C) 
2
   :
3
        X <= C xor D; 
4
   :
5
        Y <= C xor D;
Fazit: Hardware ok, Simulation falsch   :-o

von Falk B. (falk)


Lesenswert?

@Lothar Miller (lkmiller)

>Versuche, die Aufgabe mit Signalen zu lösen.
>Wenn es tatsächlich nicht anders geht, nimm Variable.

GENAU!

von thomas (Gast)


Lesenswert?

Ich hab solche Prozesse mit was anderem als das Taktsignal in der 
Sensitivity-List eigentlich überhaupt ... Mach ich irgendwas falsch?

Grüße
thomas

von thomas (Gast)


Lesenswert?

überhaupt nie, sollte es oben heißen ...

Immer nur:
process (clk)
begin
  if rising_edge(clk) then
    if reset='1' then
      ...
    else
      ...
    end if;
  end if;
end process;

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


Lesenswert?

> Mach ich irgendwas falsch?
Nein.

Nur gibt es in Prozessen andere syntaktische Elemente als bei 
Concurrent-Zuweisungen. Und manchmal liest sich eine kombinatorische 
Beschreibung dadurch einfach besser.

Du könntest deine getakteten Prozesse mit synchronem Reset noch schöner 
schreiben:
1
process begin
2
  wait until rising_edge(clk);
3
  ... -- "normale" Anweisungen
4
  if reset='1' then
5
      ... -- Resetzuweisungen: höher priorisiert, weil am Ende des Prozesses
6
  end if;
7
end process;

Wobei "Schönheit" von Mensch zu Mensch anders definiert ist :-)

von Ratzeputz (Gast)


Lesenswert?

Wie werden denn eigentlich Variablen bei der Synthese verarbeitet, 
einfach als (dem Datentyp entsprechend konvertierte) ungetaktete 
Signale? Denn letztendlich sind es doch alles Signale, die im FPGA sind, 
oder?

von Falk B. (falk)


Lesenswert?

@Ratzeputz (Gast)

>einfach als (dem Datentyp entsprechend konvertierte) ungetaktete
>Signale?

Nöö. Als Variablen ;-)

> Denn letztendlich sind es doch alles Signale, die im FPGA sind,
>oder?

Physikalisch schon, aber logisch nicht.

http://www.mikrocontroller.net/articles/VHDL#Wann_und_warum_verwendet_man_Variablen.3F

Ist doch alles schon direkt und einfach aufgeschrieben :-0

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


Angehängte Dateien:

Lesenswert?

> Wie werden denn eigentlich Variablen bei der Synthese verarbeitet,
> einfach als (dem Datentyp entsprechend konvertierte) ungetaktete
> Signale?
Du kannst auch Variable speichernd machen. Du mußt sie nur dem 
entsprechend bechreiben:
1
  process(clk)
2
  variable var: std_logic;
3
  begin
4
     if rising_edge(clk) then
5
        res1 <= var;
6
        var  := din;
7
        res2 <= var;
8
     end if;
9
  end process;
Wird hier eine Variable vor der ersten Zuweisung verwendet, muß sie 
speichernd sein.

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


Lesenswert?

Wo wir gerade so schön dabei sind:
Was macht die Synthese aus folgender Beschreibung?
Und was die Simulation?
1
  process(din)
2
  variable var: std_logic;
3
  begin
4
     res1 <= var;
5
     var  := din;
6
     res2 <= var;
7
  end process;

von Ratzeputz (Gast)


Lesenswert?

>> Denn letztendlich sind es doch alles Signale, die im FPGA sind,
>>oder?

>Physikalisch schon, aber logisch nicht.

Na wenn physikalisch ja, dann haben sie doch das gleiche zeitliche 
Verhalten wie ungetaktet veränderte Signale, also alles geht so schnell, 
wie es die Laufzeiten im FPGA erlauben?!

Dann ändern sich ihre Werte nicht "sofort" sondern halt doch so schnell 
wie ungetaktete Signale, oder?

Anders gefragt, welche ungetaktete Addierung ist schneller?

Signal c <= Signal a + Signal b;
oder
Variable z := Variable x + Variable y;

?

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


Lesenswert?

> Anders gefragt, welche ungetaktete Addierung ist schneller?
> Signal c <= Signal a + Signal b;
> oder
> Variable z := Variable x + Variable y;
Antwort: kann man so nicht sagen. Das hängt von der Synthese ab.
Variable sind "nur" Platzhalter für Zwischenergebnisse. Sie sind 
ausserhalb eines Prozesses unbekannt. Signale werden zum "Verdrahten" 
von Komponenten verwendet.
Sowohl Signale als auch Variable sind nur logische Beschreibungen 
einer Verknüpfung/Berechnung. Deshalb ändern sie ihren Wert in der 
Theorie sofort. Wie das allerdings in der Hardware implementiert wird, 
steht dem Synthesizer frei.


Gegeben sei z.B. folgender Code, was kommt dabei heraus?
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity VarSig is
6
    Port ( din : in   STD_LOGIC_VECTOR (3 downto 0);
7
           dos : out  STD_LOGIC_VECTOR (3 downto 0);
8
           dop : out  STD_LOGIC_VECTOR (3 downto 0);
9
           dov : out  STD_LOGIC_VECTOR (3 downto 0));
10
end VarSig;
11
12
architecture Behavioral of VarSig is
13
signal s : std_logic_vector(3 downto 0);
14
signal p : std_logic_vector(3 downto 0);
15
begin
16
   process(din, s, p) 
17
   variable var : std_logic_vector(3 downto 0);
18
   begin
19
      -- [1] wird parallel implementiert
20
      var(0) :=            din(0);
21
      var(1) := var(0) and din(1); -- 2-fach AND
22
      var(2) := var(1) and din(2); -- 3-fach AND
23
      var(3) := var(2) and din(3); -- 4-fach AND
24
      dov <= var;
25
      
26
      -- [2] wird sequentiell implementiert 
27
      s(0) <=          din(0);
28
      s(1) <= s(0) and din(1); -- 2-fach AND
29
      s(2) <= s(1) and din(2); -- 2-fach AND
30
      s(3) <= s(2) and din(3); -- 2-fach AND
31
      dos  <= s;
32
      
33
      -- [3] wird parallel implementiert 
34
      p(0) <= din(0);                                  -- 1:1 verbunden
35
      p(1) <= din(0) and din(1);                       -- 2-fach AND
36
      p(2) <= din(0) and din(1) and din(2);            -- 3-fach AND
37
      p(3) <= din(0) and din(1) and din(2) and din(3); -- 4-fach AND
38
      dop  <= p;
39
   end process;
40
end Behavioral;
Die Ergebnisse sind in der Verhaltens-Simulation absolut identisch, dort 
sind keine Laufzeiten im Spiel.

In der Praxis sind dov(0), dos(0) und dop(0) identisch als 1:1 
Verbindung (Alias) ausgeführt. dov(1), dos(1) und dos(1) sind ebenfalls 
gleich implementiert (2-fach AND). Ab Index 2 unterscheiden sich die 
Lösungen:
die Beschreibung mit der Variablen (1] und den "ausführlich 
geschriebenen" Signalen [3] ist parallel implementiert.
Die Beschreibung mit dem "mit sich selbst verknüpften" Signal [2] 
sequentiell.
Dabei sind [1] und [3] identisch.

Die Laufzeit sequentieller Logik ist natürlich länger, da für das 
Ergenbnis dos(3) 3 von den AND-Gattern durchlaufen werden müssen.

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


Angehängte Dateien:

Lesenswert?

Lothar Miller wrote:
> Wo wir gerade so schön dabei sind:
> Was macht die Synthese aus folgender Beschreibung?
> Und was die Simulation?
>
1
>   process(din)
2
>   variable var: std_logic;
3
>   begin
4
>      res1 <= var;
5
>      var  := din;
6
>      res2 <= var;
7
>   end process;
8
>
Hier die Lösung: Die Synthese setzt alle 3 Signale (din, res1 und res2) 
gleich und macht einfach eine Verbindung.

Die Simulation macht etwas anderes: Mit jedem Wechsel an din wird der 
prozess aufgerufen und der gespeicherte Wert von var an res1 
ausgegeben.

Und es hilft nichts: var kann nicht in die Sensitivity-List des 
Prozesses aufgenommen werden (Syntax-Fehler).

Fazit: Vorsicht mit Variablen ;-)

von Falk B. (falk)


Lesenswert?

@ Lothar Miller (lkmiller)

>Fazit: Vorsicht mit Variablen ;-)

GAAAANZ neue Erkenntnis! ;-)

von Ratzeputz (Gast)


Lesenswert?

Ok, letzte Frage zur Klärung:
Gibt es etwas, was man in der Synthese(!) NICHT mit Signalen, seien sie 
getaktet oder ungetaktet, hinkriegt, wofür man unbedingt Variablen 
braucht? Oder lässt sich letztendlich alles auf std_logic-Signale 
zurückführen?

von Morin (Gast)


Lesenswert?

> Gibt es etwas, was man in der Synthese(!) NICHT mit Signalen, seien sie
> getaktet oder ungetaktet, hinkriegt

Ja, sicher. VHDL lässt dich sehr viel mehr hinschreiben als 
synthetisierbar ist.

> , wofür man unbedingt Variablen braucht?

Nein. Was mit Signalen nicht synthetisierbar ist, das geht auch mit 
Variablen nicht.

> Oder lässt sich letztendlich alles auf std_logic-Signale zurückführen?

Alles was synthetisierbar ist, ja.

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


Lesenswert?

> Gibt es etwas, was man in der Synthese(!) NICHT mit Signalen, seien
> sie getaktet oder ungetaktet, hinkriegt, wofür man unbedingt Variablen
> braucht?
Nein, nur lässt sich mit Variablen u.U. eine Logik kompakter 
beschreiben.

Zum Schluss wird die beschriebene Hardware im FPGA in LUTs und FFs 
abgebildet. Was sich darauf nicht abbilden lässt, lässt sich nicht 
realisieren.

Wobei es dabei natürlich Ausnahmen gibt, in Form von speziellen 
Hardwarkomponenten, die aber idR. von Hand instantiiert werden müssen 
(DDR-FFs, Serielle Sender und Empfänger, Prozessorkerne...).

@ Morin:
>> Gibt es etwas, was man in der Synthese(!) NICHT mit Signalen, seien sie
>> getaktet oder ungetaktet, hinkriegt
> Ja, sicher. VHDL lässt dich sehr viel mehr hinschreiben
> als synthetisierbar ist.
Das stimmt schon, aber hast du da nicht den Zusammenhang verloren?
M.E. ist die Fragestellung eine andere ;-)
Es geht darum, ob man irgendwelche Sachen nur mit Variablen 
beschreiben könnte.

von Ratzeputz (Gast)


Lesenswert?

Richtig, Lothar, so war es gemeint. Und danke für eure Antworten zur 
Klärung. :)

von Morin (Gast)


Lesenswert?

> Das stimmt schon, aber hast du da nicht den Zusammenhang verloren?

In gewisser Hinsicht ja, aber andersrum wäre die Antwort evtl 
mißverständlich gewesen :/ Naja, hat ja jeder verstanden, was gemeint 
war.

von Xilitera (Gast)


Lesenswert?

>Autor: Falk Brunner (falk)
>Datum: 25.11.2008 10:18
>> Denn letztendlich sind es doch alles Signale, die im FPGA sind,
>>oder?
>
>Physikalisch schon, aber logisch nicht.
So ein Schwachsinn. Wenn du nur rumschwurbeln willst, halt bitte die 
Klappe.

>http://www.mikrocontroller.net/articles/VHDL#Wann_...
>Ist doch alles schon direkt und einfach aufgeschrieben :-0

Du musst es ja noetig haben. Stinkts bei dir nicht gewaltig vor lauter 
Eigenlob?
Einfach im Sinne von primitiv ist es schon, da gebe ich dir recht. Aber 
in der Praxis vollkommen unbrauchbar.

von Morin (Gast)


Lesenswert?

Was ist dir denn für ne Laus über die Leber gelaufen? :)

> >Physikalisch schon, aber logisch nicht.
> So ein Schwachsinn. Wenn du nur rumschwurbeln willst, halt bitte die
> Klappe.

Wie du dir sicher denken kannst, meinte Falk damit, dass man durchaus in 
anderen Konstrukten (z.B. Variablen) das Design beschreibt, während 
letztendlich alle Hardwarebeschreibungen in Netzlisten mit Signalen (und 
ohne Variablen) umgewandelt werden, bevor die endgültige Synthese 
stattfindet.

> Du musst es ja noetig haben. Stinkts bei dir nicht gewaltig vor lauter
> Eigenlob?
> Einfach im Sinne von primitiv ist es schon, da gebe ich dir recht. Aber
> in der Praxis vollkommen unbrauchbar.

Hier basiert alles auf freiwilliger Mitarbeit. Du hast also keinerlei 
Ansprüche zu stellen. Lern lieber erst mal, dich zu benehmen.

von U.G. L. (dlchnr)


Lesenswert?

Lothar M. schrieb:
> Du könntest deine getakteten Prozesse mit synchronem Reset noch schöner
> schreiben:process begin
>   wait until rising_edge(clk);
>   ... -- "normale" Anweisungen
>   if reset='1' then
>       ... -- Resetzuweisungen: höher priorisiert, weil am Ende des
> Prozesses
>   end if;
> end process;

Ich versuche gerade mir das "höher priorisiert, weil am Ende des 
Prozesses" durch weitere Literatur klarer zu machen, denn es 
widerspricht doch etwas meiner Intuition. Bei einem if, wie im Beispiel 
darüber, ist ja wohl das oberste Statement priorisiert, insofern sollten 
sich die beiden Implementierungen von der Priorisierung nicht 
unterscheiden.
Ich konnte aber bislang nichts finden, wo die Priorisierung von 
Concurrent-Zuweisungen beschrieben ist (vermutlich hab' mich noch nicht 
die richtigen Suchworte verwendet) -  kann jemand mir 'nen Link auf 
entsprechende Beschreibungen geben?

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


Lesenswert?

U.G. L. schrieb:
> denn es widerspricht doch etwas meiner Intuition.
Es ist einfach so, dass sich der Wert eines Signals während des 
Prozesses nicht ändert, sondern der im Verlauf des Prozesses gern auch 
wiederholt neu berechnete Wert dem Signal erst am Ende des Prozesses 
zugewiesen wird.

> Ich konnte aber bislang nichts finden, wo die Priorisierung von
> Concurrent-Zuweisungen beschrieben ist
Wie der Name schon sagt, gibt es da keine Priorisierung, weil die 
Zuweisungen ja "nebenläufig", also "gleichzeitig", stattfinden.

> Bei einem if, wie im Beispiel darüber, ist ja wohl das oberste
> Statement priorisiert
Weil die if-Abfrage einen neuen Block markiert, ist dieses "die letzte 
Zuweisung an ein Signal gewinnt" da natürlich nachrangig, weil ein Teil 
der Zuweisungen gar nicht durchlaufen wird.

Mal abseits der ganze Theorie ein Beispiel:
1
  process begin
2
     wait until rising_edge(clk);
3
     signalA <= '1';
4
     signalA <= '0';
5
  end process;
Klar, dass dabei das signalA niemals einen Wert ungleich '0' einnehmen 
wird.
Jetzt das:
1
  process begin
2
     wait until rising_edge(clk);
3
     signalA <= '1';
4
     if signalA='1' then
5
        signalB <= not signalB;
6
     end if;
7
     signalA <= '0';
8
  end process;
Hier wird das signalB niemals toggeln, weil das signalA immer den Wert 
'0' hat ("die letzte Zuweisung gewinnt").

Und das ganze Concurrent:
1
   signalA <= '1';
2
   signalA <= '0';
Das gibt einen Fehler, weil einem Signal gleichzeitig unterschiedliche 
Werte zugewiesen werden.

: Bearbeitet durch Moderator
von U.G. L. (dlchnr)


Lesenswert?

Ok - da hat mich dann wohl das Wörtchen "priorisiert" auf einen 
"Holzweg" gelenkt :-).
In der Praxis werde ich keine sich widersprechende Angaben haben, die 
"priorisiert" werden müssen, sondern bestenfalls sich ergebende 
"Aktualisierungen", etwa wenn ich einen Default-Wert vorgebe und eine 
Berechnung diesen überschreibt.

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


Lesenswert?

U.G. L. schrieb:
> etwa wenn ich einen Default-Wert vorgebe und eine Berechnung diesen
> überschreibt.
Das ist letztlich auch nur eine Priorisierung, denn der berechnete Wert 
hat höhere Priorität als der Defaultwert.

von berndl (Gast)


Lesenswert?

U.G. L. schrieb:
> process begin
>   wait until rising_edge(clk);
>   ... -- "normale" Anweisungen
>   if reset='1' then
>       ... -- Resetzuweisungen: höher priorisiert
>   end if;
> end process;
> .....
> Ich konnte aber bislang nichts finden, wo die Priorisierung von
> Concurrent-Zuweisungen beschrieben ist

Das sind auch keine 'concurrent statements', sondern 'sequential 
statements' da sie in einem Prozess stehen.
Bei 'concurrent' darfst du (ausserhalb eines Prozesses) ein Signal genau 
an einer Stelle beschreiben.
Bei 'sequential' (innerhalb eines Prozesses) wird alles brav nach 
Reihenfolge abgearbeitet, du darfst X-mal das Signal innerhalb des 
Prozesses beschreiben. Und die letzte gueltige Zuweisung (die ganzen 
'if' oder 'case') gewinnt dann.
Deshalb gewinnt evtl. der oben gezeigte reset='1' und ueberschreibt 
alles, was da vorher steht.
Dein Stichwort in diesem Fall ist also 'sequential statement'

von dlchnr (Gast)


Lesenswert?

"concurrent" hatte ich Lothars Beiträgen entnommen und übersehen, dass 
er das (vermutlich) nicht auf die Anordnung innerhalb eines process 
gemünzt hatte. Das "priorisiert" hatte bei mir den Eindruck erwegt, dass 
es eine Regel/Definition gibt, von der ich nichts weiss - mittlerweile 
ist mir klar, dass es diese Regel nicht gibt bzw. geben muss, weil die 
"Priorisierung" eben durch die "sequential" Bearbeitung zustande kommt.

von Fragr (Gast)


Lesenswert?

Eine Frage von einem Anfänger.

>In der Simulation, wo ich ja mal den gesamten Syntaxumfang von VHDL ausschöpfen 
darf, sind mir Variablen gern gesehen.

Demzufolge schreibst du deine architectures zweimal? Einmal um es 
schnell zu simulieren und wenn es dann läuft schreibst du es komplett 
neu doch dieses Mal ohne Variablen? Warum sollte man nicht direkt alles, 
außer der Testbench, in synthetisierbarer Form aufschreiben?

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


Lesenswert?

Fragr schrieb:
> Demzufolge schreibst du deine architectures zweimal?
Nein. Dieser Schluss ist falsch.

> Warum sollte man nicht direkt alles, außer der Testbench, in
> synthetisierbarer Form aufschreiben?
Mit "in der Simulation" meine ich "in der Testbench".
Denn natürlich macht eine Simulation nur dann Sinn, wenn man genau die 
Beschreibung simuliert, die letztlich auf das FPGA synthetisiert wird.

Und natürlich gilt was ich gleich danach schrieb:
>>> Auch zur Beschreibung und Bearbeitung von Schleifen in der Synthese sind
>>> sie (oft) unumgänglich.

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.