Forum: FPGA, VHDL & Co. Process - Idiotenfrage


von Thomas L. (tom)


Lesenswert?

Hallo

Ich bins schon wieder und habe eine kleine Verständnisfrage.

Angenommen ich habe einen Process, der auf den clock sensitiv ist. Nun
ist dieser process jedoch etwas länger. Das heisst ja in der
Zwischenzeit können mehrere clock - ticks auftreten - korrekt? Oder ist
dann mit diesem langem Prozess meine maximale Taktfrequenz gegeben?

von TheMason (Gast)


Lesenswert?

hallo tom,

zu den "mehreren clock ticks" : nein.
der prozess wird (um es mal softwaretechnisch zu sagen) über die clock
angetriggert. wenn dein prozess "länger" braucht (bedenke das "nur"
die gatterlaufzeiten deinen maximalen takt bestimmten) wird deine
mögliche takt-frequenz niedriger.
wenn es erforderlich ist das der prozess "wartet" lässt sich das nur
durch zählen der takte machen.

gruß
rene

von Ayhan (Gast)


Lesenswert?

Hallo Thomas,

soweit mir bekannt ist, wird nachdem ein Prozess mit clk aktiviert
wurde, dieser solange sequentiell ausgeführt, bis der Prozess beendet
ist. Weitere Clk´s während der Ausführungsdauer des Prozesses werden
ignoriert, da es ein sequentieller Vorgang ist.

MFG

von Ayhan (Gast)


Lesenswert?

ups! Da war einer wohl schneller :)

von Thomas L. (tom)


Lesenswert?

Hm? Kann es sein, dass sich die beiden Antworten widersprechen?

von FPGAküchle (Gast)


Lesenswert?

jedesmal wenn sich das clock signal ÄNDERT wird der process angestartet
und sofort komplett abgearbeitet. Zumindest tut der Simulator so. wobei
abarbeiten meint; er berechnet für jede Zuweisung
wann und welchen Wert diese erhält. dabei lässt er sich auch nicht von
neuen Flanken stören, weil die treffen erst nach einem delta delay ein,
genau solange braucht er für die Ausführung der zuweisungen. Also für
die Simu heisst die Antwort Nein.
In der (funktionalen) Simu kannst die taktfrequenz beleibig hochsetzen
und der Simulator wird simulieren. Die "Warning: clock to fast" musst
du selber in den VHDL code schreiben.

In echt gibt es keine Processe und nix wird sofort abgearbeitet.
Die taktfrequenz wird (grob) durch die zeit bestimmt die ein Signal
vom FF output zum FF input braucht. Diese zeit wird durch die Logik und
verdrahtung zw. den FF bestimmt. ein getakter process ist in Echt die
Eingangsbeschaltung eines FF, also kann man aus den Zuweisungen
innerhalb eines process schon abschätzen wie lang der Pfad zw. den FF
ist und somit wie schnell der FPGA/ASIC getaktet werden kann. Also man
kann schon einem Process ansehen wie schnell die Hardware ist. Des
hat aber nix mit der Länge des Codes zu tun. Du kannst in einem Process
mehr code als text in der Bibel steht reinschreiben und der
synthetisierte FPGA läuft mit 300 MHZ. Und du kannst 5 zeil reinpacken
und das design läuft nur mit 1.2345 MhZ.

Also VHDL ist nicht Software, aus der Anzahl der Codezeilen kann nicht
zwingend auf die geschwindigkeit der realisierung geschlossen werden.
Bei Software in Assembler auf "ein Takt ein befehl Machienen" wie AVR
ist das anders, (schleifen entsprechend beachtet).

von Xenu (Gast)


Lesenswert?

>Also VHDL ist nicht Software

VHDL ist schon Software, aber die digitale Hardware, die damit
beschrieben wird, ist es nicht.

von Alex H. (alex123)


Lesenswert?

Hallo Thomas,

> Hm? Kann es sein, dass sich die beiden Antworten widersprechen?

Ja ... (scheint so ;-)

> Angenommen ich habe einen Process, der auf den clock
> sensitiv ist. Nun ist dieser process jedoch etwas
> länger. Das heisst ja in der Zwischenzeit können
> mehrere clock - ticks auftreten - korrekt? Oder ist
> dann mit diesem langem Prozess meine maximale
> Taktfrequenz gegeben?

Es gibt in VHDL in einem Prozess 2 Arten, einen
"zeitlichen" Ablauf zu spezifizieren:
- Sensitivity List
- Wait Statement

Die Sensitivity List startet einen Prozess jedesmal,
wenn sich ein Signal darin ändert. Danach wird der
Prozess in Nullzeit ausgeführt und wartet wieder
auf die nächste Änderung in der Sensitivity List.
Im Prozess wird keine weitere Zeit "verbraucht".
Der zeitliche Ablauf wird dabei im Prinzip über die
Signale gesteuert, die in der Sensitivity List sind.
Beschreibt man einen synchronen Prozess, hat man
darin i.d.R. Clock und Reset. Mit "jeder" Clockflanke
wird der Prozess erneut gestartet.
Wievie Logik Du dann reinpackst ist dem Prozess egal
(ist nur später wichtig, wenn Du eine Synthese für
ein bestimmtes Device/Target Library machst und die
Taktfrequenz festlegst, ob dies zusammenpasst).

Wait statements:
Alternativ dazu kannst Du in einem Prozess wait
statements verwenden. Der Prozess läuft dann in
Nullzeit bis zum nächsten Waitstatement und wartet,
bis die Bedingung erfüllt ist (kann Event sein oder
Abfrage eines Signalwertes oder feste Zeit). Ist
diese erfüllt, läuft er bis zum nächsten Wait. Ist
der Prozess am Ende angekommen, fängt er wieder von
vorne an.
Schreibst Du z.B.
wait until Clock='1';
...
wait for 100 ns;
...
wait until clock='1';
würde beim warten auf die 100 ns der Clock ignoriert.
(Ich würde aber nicht so beschreiben.)

In einem Prozess mit Sensitivity List dürfen KEINE
wait statements vorkommen (und umgekehrt).

Gruss,

Alex

von Thomas L. (tom)


Lesenswert?

Also gut. Der Code soll später auch synthetisiert werden, daher ist die
Simulation für mich mal zweitrangig. Ich würde schon gerne Code
erzeugen der auch synthetisiert werden kann.
@FpgaKüchle: Das mit der Anzahl an Codezeilen ist mir klar. Die beiden
Extrema die ich mir vorstelle sind z.B. eine einfache Zuweisung oder
100 Zuweisungen (sehr kurz) und eine Art Register, das mehrmals
verändert wird, weil hier die Anweisungen nicht parallel laufen können
(korrekt?). Du stimmst also mit der Antwort von TheMason überein. Sehe
ich das richtig?

@Alex H.: Für mich ist besonders wichtig, dass der Code auch
synthetisiert werden kann. Das mit dem wait for 100ns wusste ich, wobei
ich noch nicht heraus gefunden habe, wie ich am besten eine
(synthetisierbare) wartezeit von ... sagen wir mal 10 Sekunden basteln
kann ... aber das bekomm ich sicher auch noch raus. Es geht bei mir
natürlich nur um eine synchrone Schaltung. Im Prinzip stimmt deine
Meinung also mit TheMason und FpgaKüchle überein?

@Xenu: VHDL ist doch auch keine Software sondern nur eine
Beschreibungssprache (oder Programmiersprache) ;)

von Sven Johannes (Gast)


Lesenswert?

Moin...

bevor ihr da was versucht was nicht geht: "wait for .." ist eine
Simulationsanweisung und kann NICHT synthetisiert werden!

Feste Zeiten warten geht eigentlich nur über Zähler und bekannten
Takt.

--
 SJ

von Alex H. (alex123)


Lesenswert?

Hallo Thomas,

> Im Prinzip stimmt deine
> Meinung also mit TheMason und FpgaKüchle überein?

Ja. Meine Antwort hat sich mit FpgaKüchle überschnitten.
> ... wird nachdem ein Prozess mit clk aktiviert wurde,
> dieser solange sequentiell ausgeführt, bis der Prozess
> beendet ist. Weitere Clk´s während der Ausführungsdauer
> des Prozesses werden ignoriert, da es ein sequentieller
> Vorgang ist.
Hat der Prozess eine Sensitivity List, stimmt das so
nicht. Dann werden alle Anweisungen im Prozess nach
dem Starten des Prozesses in Nullzeit ausgeführt.

> Das mit dem wait for 100ns wusste ich,
> wobei ich noch nicht heraus gefunden habe, wie ich am
> besten eine (synthetisierbare) wartezeit von ... sagen
> wir mal 10 Sekunden basteln kann

Das Prinzip ist anders. Wie Du schon sagtest, möchtest
Du synchron arbeiten.
D.h. Du hast irgendwo einen Takt, der eine bestimmte
Taktfrequenz hat, z.B. 100 ns. Dazu implementierst zu
z.B. in Deiner Testbench einen Prozess, der diesen
erzeugt:

process
begin
  Clock <= '1';
  wait for 50 ns;
  Clock <= '0';
  wait for 50 ns;
end process;

Das ganze läuft nun immer im Kreis herum.
Am besten noch nen reset, der zu Beginn aktiv ist
und dann irgendwann mal inaktiv wird.

In Deiner Schaltung beschreibst Du dann das, was Du
machen möchtest, in einem Prozess, der von Clock und
Reset abhängt:
process (Clock, Reset)
begin
  if Reset='1' then
    Ausgang <= '0'; -- Initialisierung
  elsif Clock'event and Clock='1' then
    -- nun kommt das was Du machen möchtest ...
    Ausgang <= ...
    ...
  end if;
end process;

Alles, was im Elsif-Zweig steht, wird in "einem"
Taktzyklus ausgeführt. Willst Du hier komplexe
Berechnungen machen, dann erreichst Du entweder
nur eine niedrige Taktfrequenz, oder Du musst
versuchen, nur einen Teil zu berechnen und in
einem Register (FlipFlop) zwischenzuspeichern und
im nächsten Takt den Rest zu berechnen.

> 10 Sekunden warten ...
Macht man über einen Timer. Rechne aus, wieviele
Taktzyklen dies z.B. bei 100 ns Taktperiode sind
(100 Mio) und beschreibe einen Timer, der mit einem
Startsignal auf Null gesetzt wird und nach Ablauf
der Zeit dann beispielsweise ein Triggersignal für
den Rest der Schaltung erzeugt.

Gruss,

Alex

von Thomas L. (tom)


Lesenswert?

@SvenJohannes: Ja, ist klar :)

@Alex H: Das mit dem Takt in der Testbench habe ich verstanden. Habe
ich auch schonmal gemacht. Im Reset würde ich mal den Signalen fixe
Werte zuweisen, sodass die Signale vom Start weg definiert sind
(zumindest wurde es uns erklärt, dass dies auf jeden Fall nicht
schlecht ist, für mich machts auch Sinn).
Bzgl. Elsif - Zweig: Dann ist das also so wie ich es mir vorgestellt
habe. Genau das wollte ich wissen. Das mit dem Timer habe ich mir auch
schon überlegt. Mein Gedankengang war eben, dass der Timer (wenn
abgelaufen) ein Signal ändert, welches in der Sensitivity List eines
(anderen) Prozesses steht. Dieser würde dann die entsprechende Aktion
vornehmen. Klingt für mich als könnte es funktionieren oder siehst du
einen groben Denkfehler? Achja nochwas. Wie zähle ich denn am besten so
weit hinauf .. da bräuchte ich ja einen 27 bit Zähler. Wird das in der
Realität so gemacht?

von Alex H. (alex123)


Lesenswert?

Hallo Thomas,

> Mein Gedankengang war eben, dass der Timer (wenn
> abgelaufen) ein Signal ändert, welches in der
> Sensitivity List eines (anderen) Prozesses steht.
> Dieser würde dann die entsprechende Aktion
> vornehmen.

Nicht in der Sensitivity List.
Die Sensitivity List von einem getakteten Prozess
hat nur Clock und Reset :-)

Wenn Du das Trigger-Signal erzeugt hast, dann frägst
Du es innerhalb des elsif-Bereiches ab. Dort können
beliebig (naja fast) viele Ifs und Cases usw. stehen.
D.h.
  elsif Clock'event and Clock='1' then
    -- nun kommt das was Du machen möchtest ...
    if Trigger = '1' then
      Ausgang <= ...
    ...
  end if;

> Achja nochwas. Wie zähle ich denn am besten so
> weit hinauf .. da bräuchte ich ja einen 27 bit Zähler.
> Wird das in der Realität so gemacht?

Spricht nix dagegen ...
(Musst nur schauen, dass Du das ganze noch auf
Dein FPGA synthetisieren kannst. Bin kein FPGA-Experte,
aber 27-Bit sollten noch machbar sein.)

Gruss,

Alex

von FPGAküchle (Gast)


Lesenswert?

-Nicht in der Sensitivity List.
-Die Sensitivity List von einem getakteten Prozess
-hat nur Clock und Reset :-)

FF mit async. reset -> clk und rst in SensList
FF mit  sync. reset -> clk         in SensList

von Thomas L. (tom)


Lesenswert?

Moment mal. Ich darf nur Prozesse haben, die auf Clock getriggert
werden? Nicht oder?
Dass der getaktete Prozess nur von clk/rst abhängig ist, ist mir klar.
Dort starte ich dann auch den Timer, bzw. inkrementiere diesen. Darf
nun der Prozess, der auf eine bestimmte Timerstellung wartet nun nicht
sensitiv auf ein Signal "TimerHatOberesEndeErreicht" sein?

von FPGAküchle (Gast)


Lesenswert?

#Moment mal. Ich darf nur Prozesse haben, die auf Clock getriggert
#werden? Nicht oder?

Nein du kannst auch sogenannte konbinatorische Prozesse schreiben. Zum
beispiel ein NAND:

[vhdl]
Process(nand_a,nand_b)
begin
   if nand_a = '1' and nand_b = '1' then
     nand_res <= '0'
  else
    nand_res <= '1';
  end if;
end process;
[\vhdl]


FF werden synthetisiert, wenn der process auf clk getriggert wird. Also
das taktnetzwerk am clk input des FF hängt. Man sollte nur ein
Taktnetzwerk benutzen,
aber falls man weiss was man tut kann man auch andere Signale auf
'event abfragen (z.B. ripple counter).

Als Anfänger solltest du nur ein Signal auf Flanke ('event) testen,
und da ist der Takt.

von Thomas L. (tom)


Lesenswert?

Also das verstehe ich jetzt nicht ganz.
Obiger Code hat die beiden Operanden des Nand in der Sensitivity List -
klar. Ändert sich einer, wird dieser Prozess getriggert und ausgeführt.

Angenommen ich schreibe in meinem Code so etwas (bei dem signal ist mir
noch nicht klar, was ich hier nehme, das muss ich noch nachschlagen):

signal befehlsnummer : std_logic (7 downto 0)
signal a : std_logic
signal counter : std_logic_vector (27 downto 0)

basic : Process (clk, rst)
  begin
    if clk'event and clk = '1' then
      if befehl = "0011" then -- opcode fuer wait
        counter <= counter + 1;  -- Zuweisung erfolgt sowieso erst am
Schluss
        if counter = "111111111111111..." then
        a <= "0";

      elseif befehl = "0100" then -- Opcode für DEC
        befehlsnummer <= befehlsnummer + 1;
        akku <= akku - 1;
      ...
      end if
    end if
  end

timertop : process (a)
begin
  befehlsnummer <= befehlsnummer + 1;
end


Wäre das jetzt beispielsweise erlaubt? Konkret gehts darum, dass ich
wenn ich in einem bestimmten State bin (wait), solange keinen anderen
Befehl ausführe, bis der Timer abgelaufen ist.

ich komme von der Softwareschiene und tue mir daher mit der Vorstellung
noch etwas schwer. Ausserdem ist es mein erstes Projekt, daher bitte
nicht auf den Code schauen ;)

von FPGAküchle (Gast)


Lesenswert?

hM befehlscounter wird in zwei processen zugewiesen, das geht net ...

von Thomas L. (tom)


Lesenswert?

Das ist dann schlecht ... dann werde ich die Idee mal kübeln. Ich hoffe
auf der Uni-Bibliothek ist bald das (von dir?) empfohlene Buch
verfügbar. Dann könnte ichs mir endlich mal ansehen. Werde mich wohlin
der Zwischenzeit mal mit einem anderen Teilbereich beschäftigen.
Aber durch den Thread wurde mir das eine oder andere schonmal deutlich
klarer :)
Ich danke daher derweil mal recht herzlich und wünsche euch schönen
Urlaub ohne mich. Nutzt ihn, denn wenn wieder Fragen auftauchen, ist er
zu Ende :)

von TheMason (Gast)


Lesenswert?

@thomas

so wie du es vor hast (ein prozess -> timer, anderer prozess ->
befehlszähler) ist schon richtig, du mußt halt nur den takt im 2.
prozess mit einbeziehen :

-- timer
process (clk,res)
...
  if clk'event and clk = '1' then
  ...
    if timer = "111111111111" then
      a <= '1';
    else
      a <= '0';
    end if;
  ...
  end if;
...

-- befehlszähler
process (clk,res)
...
  if clk'event and clk = '1' then
  ...
    if a = '1' then
      befehlscounter <= befehlscounter + '1';
    end if;
  ...
  end if;
...

was zu beachten ist (wie fpgaküchle schon meinte) :
du darfst signale (z.b. befehlszähler) NICHT aus zwei prozessen
gleichzeitig heraus verändern. (das funzt nicht)
d.h. du kannst zwar aus jedem prozess jedes signal lesen, aber
verändern nur aus einem prozess heraus.
mache es über flags (wenn der ausdruck so passt) die du in einem
prozess setzt und in einem anderen prozess abfragst.
bsp :

signal inkr_bef_zaehl : std_logic;
signal res_bef_zaehl : std_logic;
signal setze_bef_zaehl : std_logic;
signal bef_zaehl     : std_logic_vector (xx downto 0);
signal timer_zaehl   : std_logic_vector (xx downto 0);

signal neu_bef_zaehl  : std_logic_vector (xx downto 0);

-- steuerung für befehlszähler
process (clk,res)
...
  if res = '1' then
    inkr_bef_zaehl <= '0';
    res_bef_zaehl  <= '0';
  elsif clk'event and clk = '1' then
    timer_zaehl <= timer_zaehl + '1';

    if timer_zaehl = max_timer_wert then
      inkr_bef_zaehl <= '1';
    else
      inkr_bef_zaehl <= '0';
    end if;

    ...

    if irgendwas then
      neu_bef_zaehl <= "1010101010"; -- beispielsweise konstanter
wert
      setze_bef_zaehl <= '1'; -- hier muß nur dafür gesorgt werden
das im nächsten takt das setze_bef_zaehl zurückgenommen wird !!!
    end if;

  end if;
...

-- befehlszähler selbst
process (clk,res)
...
  if res = '1' then
    bef_zaehl <= (others => '0');
  elsif clk'event and clk = '1' then

    -- wir können den befehlszähler resetten
    if res_bef_zaehl = '1' then
      bef_zaehl <= (others => '0');
    end if;

    -- wir können den befehlszähler inkrementieren
    if inkr_bef_zaehl = '1' then
      bef_zaehl <= bef_zaehl + '1';
    end if;

    -- wir können den befehlszähler auf festen wert setzen
    if setze_bef_zaehl = '1' then
      bef_zaehl <= neu_bef_zaehl;
    end if;


  end if;
...

so würde es aussehen wenn du einen befehlszähler komplett unabhängig
implementierst, und von einem anderen prozess heraus (über
steuersignale) verändern kannst.
du mußt nur dafür sorgen das wenn du signale, die in anderen prozessen
werte verändern, setzt, diese auch wieder zurücknimmst. (wichtig, sonst
sucht man sich nen wolf, und es klappt nichts. dann kommt man ums
simulieren nicht drum herum)
hoffe ich konnte dir was weiterhelfen

gruß
rene

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.