Suche…


Bemerkungen

D-Flip-Flops (DFF) und Latches sind Speicherelemente. Ein DFF tastet seine Eingabe an der einen oder anderen Flanke des Taktgebers ab (nicht bei beiden), während ein Latch auf der einen Ebene seiner Freigabe und auf der anderen Ebene transparent ist. Die folgende Abbildung veranschaulicht den Unterschied:

DFF vs. Latch-Verhalten

Die Modellierung von DFFs oder Latches in VHDL ist einfach, es gibt jedoch einige wichtige Aspekte, die berücksichtigt werden müssen:

  • Die Unterschiede zwischen VHDL-Modellen von DFFs und Latches.

  • Beschreiben der Flanken eines Signals.

  • So beschreiben Sie synchrones oder asynchrones Setzen oder Zurücksetzen.

D-Flip-Flops (DFF)

In allen Beispielen:

  • clk ist die uhr,
  • d ist die Eingabe,
  • q ist die Ausgabe,
  • srst ist ein aktiver srst Reset,
  • srstn ist ein aktiver niedriger synchroner Reset,
  • arst ist ein aktiver hoher asynchroner Reset.
  • arstn ist ein aktiver niedriger asynchroner Reset.
  • sset ist ein aktiver sset Satz,
  • ssetn ist ein aktiver niedriger synchroner Satz.
  • aset ist ein aktiver hoher asynchroner Satz.
  • asetn ist ein aktiver niedriger asynchroner Satz

Alle Signale sind vom Typ ieee.std_logic_1164.std_ulogic . Die verwendete Syntax führt zu korrekten Syntheseergebnissen bei allen Logiksynthesizern. Weitere Informationen zur alternativen Syntax finden Sie im Beispiel zur Erkennung der Taktflanke.

Uhr mit steigender Flanke

process(clk)
begin
  if rising_edge(clk) then
    q <= d;
  end if;
end process;

Fallende rand uhr

process(clk)
begin
  if falling_edge(clk) then
    q <= d;
  end if;
end process;

Anstiegsflankentakt, synchron aktiver High-Reset

process(clk)
begin
  if rising_edge(clk) then
    if srst = '1' then
      q <= '0';
    else
      q <= d;
    end if;
  end if;
end process;

Takt mit steigender Flanke, asynchroner aktiver High-Reset

process(clk, arst)
begin
  if arst = '1' then
    q <= '0';
  elsif rising_edge(clk) then
    q <= d;
  end if;
end process;

Fallender Flankentakt, asynchroner aktiver Low-Reset, synchroner aktiver High-Satz

process(clk, arstn)
begin
  if arstn = '0' then
    q <= '0';
  elsif falling_edge(clk) then
    if sset = '1' then
      q <= '1';
    else
      q <= d;
    end if;
  end if;
end process;

Takt mit steigender Flanke, asynchroner aktiver High-Reset, asynchroner aktiver Low-Satz

Hinweis: Set hat höhere Priorität als Reset

process(clk, arst, asetn)
begin
  if asetn = '0' then
    q <= '1';
  elsif arst = '1' then
    q <= '0';
  elsif rising_edge(clk) then
    q <= d;
  end if;
end process;

Latches

In allen Beispielen:

  • en ist das Freigabesignal,
  • d ist die Eingabe,
  • q ist die Ausgabe,
  • srst ist ein aktiver srst Reset,
  • srstn ist ein aktiver niedriger synchroner Reset,
  • arst ist ein aktiver hoher asynchroner Reset.
  • arstn ist ein aktiver niedriger asynchroner Reset.
  • sset ist ein aktiver sset Satz,
  • ssetn ist ein aktiver niedriger synchroner Satz.
  • aset ist ein aktiver hoher asynchroner Satz.
  • asetn ist ein aktiver niedriger asynchroner Satz

Alle Signale sind vom Typ ieee.std_logic_1164.std_ulogic . Die verwendete Syntax führt zu korrekten Syntheseergebnissen bei allen Logiksynthesizern. Weitere Informationen zur alternativen Syntax finden Sie im Beispiel zur Erkennung der Taktflanke.

Aktiv hoch aktivieren

process(en, d)
begin
  if en = '1' then
    q <= d;
  end if;
end process;

Aktiv low aktivieren

process(en, d)
begin
  if en = '0' then
    q <= d;
  end if;
end process;

Active-High-Freigabe, synchrones Active-High-Reset

process(en, d)
begin
  if en = '1' then
    if srst = '1' then
      q <= '0';
    else
      q <= d;
    end if;
  end if;
end process;

Active-High-Freigabe, asynchroner Active-High-Reset

process(en, d, arst)
begin
  if arst = '1' then
    q <= '0';
  elsif en = '1' then
    q <= d;
  end if;
end process;

Aktiv-Low-Freigabe, asynchrones Active-Low-Reset, synchrones Active-High-Set gesetzt

process(en, d, arstn)
begin
  if arstn = '0' then
    q <= '0';
  elsif en = '0' then
    if sset = '1' then
      q <= '1';
    else
      q <= d;
    end if;
  end if;
end process;

Aktive Hochfreigabe, asynchroner aktiver Hochreset, asynchroner aktiver Niedrigsatz

Hinweis: Set hat höhere Priorität als Reset

process(en, d, arst, asetn)
begin
  if asetn = '0' then
    q <= '1';
  elsif arst = '1' then
    q <= '0';
  elsif en = '1' then
    q <= d;
  end if;
end process;

Taktflankenerkennung

Die Kurzgeschichte

Mit VHDL 2008 und wenn der Typ der Uhr bit , boolean , ieee.std_logic_1164.std_ulogic oder ieee.std_logic_1164.std_logic , kann eine Taktflankenerkennung für die steigende Flanke codiert werden

  • if rising_edge(clock) then
  • if clock'event and clock = '1' then -- type bit, std_ulogic or std_logic
  • if clock'event and clock then -- type boolean

und für fallende Kante

  • if falling_edge(clock) then
  • if clock'event and clock = '0' then -- type bit, std_ulogic or std_logic
  • if clock'event and not clock then -- type boolean

Dies wird sich erwartungsgemäß sowohl für die Simulation als auch für die Synthese verhalten.

Hinweis: Die Definition einer steigenden Flanke eines Signals vom Typ std_ulogic ist etwas komplexer als die einfache, if clock'event and clock = '1' then . Beispielsweise hat die Standard- rising_edge Funktion eine andere Definition. Selbst wenn es für die Synthese wahrscheinlich keinen Unterschied macht, könnte es einen für die Simulation ergeben.

Die Verwendung der Standardfunktionen rising_edge und falling_edge wird dringend falling_edge . Bei früheren Versionen von VHDL die Verwendung dieser Funktionen erfordert explizit die Verwendung von Standardpaketen zu deklarieren (zB ieee.numeric_bit für Typ - bit ) oder sogar in einem benutzerdefinierten Paket zu definieren.

Hinweis: Verwenden Sie nicht die Standardfunktionen rising_edge und falling_edge , um Flanken von Nicht-Taktsignalen zu erkennen. Einige Synthesizer können daraus schließen, dass das Signal eine Uhr ist. Hinweis: Das Erkennen einer Flanke eines Nichttaktsignals kann häufig durch Abtasten des Signals in einem Schieberegister und Vergleichen der abgetasteten Werte in verschiedenen Stufen des Schieberegisters erfolgen.

Die lange Geschichte

Bei der Modellierung von D-Flip-Flops (DFF) ist es wichtig, die Erkennung der Flanken eines Taktsignals richtig zu beschreiben. Eine Kante ist definitionsgemäß ein Übergang von einem bestimmten Wert zu einem anderen. Zum Beispiel können wir die ansteigende Flanke eines Signals vom Typ bit (der Standard-VHDL-Aufzählungstyp, der zwei Werte akzeptiert: '0' und '1' ) als Übergang von '0' nach '1' . Für den Typ boolean wir es als Übergang von false nach true .

Häufig werden komplexere Typen verwendet. Der Typ ieee.std_logic_1164.std_ulogic ist beispielsweise ebenso wie bit oder boolean ein Aufzählungstyp, hat aber 9 statt 2:

Wert Bedeutung
'U' Nicht initialisiert
'X' Forcieren unbekannt
'0' Niedriger Pegel erzwingen
'1' Hohe Ebene erzwingen
'Z' Hohe Impedanz
'W' Schwach unbekannt
'L' Schwaches niedriges Niveau
'H' Schwaches hohes Niveau
'-' Kümmere dich nicht

Das Definieren einer ansteigenden Flanke für einen solchen Typ ist etwas komplexer als für bit oder boolean . Wir können zum Beispiel entscheiden, dass es sich um einen Übergang von '0' nach '1' . Wir können aber auch entscheiden, dass es sich um einen Übergang von '0' oder 'L' zu '1' oder 'H' .

Hinweis: Es ist diese zweite Definition ist , dass der Standard für den uses rising_edge(signal s: std_ulogic) Funktion in definierten ieee.std_logic_1164 .

Bei der Erörterung der verschiedenen Möglichkeiten zum Erkennen von Kanten ist es daher wichtig, die Art des Signals zu berücksichtigen. Es ist auch wichtig, das Modellierungsziel zu berücksichtigen: nur Simulation oder Logiksynthese? Lassen Sie uns das an einigen Beispielen veranschaulichen:

Anstiegsflanke DFF mit Typbit

signal clock, d, q: bit;
...
P1: process(clock)
begin
  if clock = '1' then
    q <= d;
  end if;
end process P1;

Aus reiner Simulationssemantik betrachtet, modelliert der Prozess P1 eine durch eine steigende Flanke ausgelöste DFF. Die Zuordnung q <= d wird genau dann ausgeführt, wenn:

  • clock geändert (dies ist, was die Empfindlichkeitsliste ausdrückt) und
  • Der aktuelle Wert der clock ist '1' .

Da clock vom Typ bit ist und type bit nur die Werte '0' und '1' , haben wir genau dies als steigende Flanke eines Signals vom Typ bit definiert. Jeder Simulator behandelt dieses Modell wie erwartet.

Hinweis: Bei Logik-Synthesizern sind die Dinge etwas komplexer, wie wir später sehen werden.

Anstiegsflanke DFF mit asynchronem aktivem High-Reset und Typbit

Um einen asynchronen aktiven High-Reset unserer DFF hinzuzufügen, könnte man Folgendes versuchen:

signal clock, reset, d, q: bit;
...
P2_BOGUS: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif clock = '1' then
    q <= d;
  end if;
end process P2_BOGUS;

Das funktioniert aber nicht . Die Bedingung für die q <= d Zuweisung q <= d sollte lauten: eine steigende Flanke der clock beim reset = '0' . Was wir modelliert haben, ist jedoch:

  • clock oder reset oder beides geändert und
  • reset = '0' und
  • clock = '1'

Das ist nicht dasselbe: Wenn sich reset von '1' auf '0' ändert '0' während clock = '1' die Zuweisung ausgeführt, solange es keine steigende Flanke der clock .

Tatsächlich gibt es keine Möglichkeit, dies in VHDL ohne die Hilfe eines Signalattributs zu modellieren:

P2_OK: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif clock = '1' and clock'event then
    q <= d;
  end if;
end process P2_OK;

Das clock'event ist das Signal Attribut event zu signalisieren angewandt clock . Es wird als boolean ausgewertet und true nur dann zu, wenn sich der Signaltakt während der clock geändert hat, die gerade der aktuellen Ausführungsphase vorausging. Dank diesem Prozess P2_OK jetzt perfekt, was wir in der Simulation (und Synthese) wollen.

Synthese-Semantik

Viele Logiksynthesizer erkennen Signalflankendetektionen basierend auf syntaktischen Mustern, nicht auf der Semantik des VHDL-Modells. Mit anderen Worten, sie berücksichtigen, wie der VHDL-Code aussieht, und nicht, welches Verhalten er modelliert. Eines der Muster, die sie alle kennen, ist:

if clock = '1' and clock'event then

Selbst im Beispiel des Prozesses P1 sollten wir es verwenden, wenn unser Modell für alle Logiksynthesizer synthetisierbar sein soll:

signal clock, d, q: bit;
...
P1_OK: process(clock)
begin
  if clock = '1' and clock'event then
    q <= d;
  end if;
end process P1_OK;

Der Teil and clock'event der Bedingung ist mit der Sensitivitätsliste völlig überflüssig, aber da einige Synthesizer es benötigen ...

std_ulogic DFF mit asynchronem aktivem High-Reset und Typ std_ulogic

In diesem Fall kann das Ausdrücken der ansteigenden Flanke der Uhr und der Rücksetzbedingung kompliziert werden. Wenn wir die Definition einer ansteigenden Flanke beibehalten, die wir oben vorgeschlagen haben, und wenn wir annehmen, dass der Reset aktiv ist, wenn er '1' oder 'H' , wird das Modell zu:

library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4: process(clock, reset)
begin
  if reset = '1' or reset = 'H' then
    q <= '0';
  elsif clock'event and
        (clock'last_value = '0' or clock'last_value = 'L') and
        (clock = '1' or clock = 'H') then
    q <= d;
  end if;
end process P4;

Hinweis: 'last_value ist ein weiteres 'last_value , das den Wert zurückgibt, den das Signal vor der letzten Wertänderung hatte.

Hilfsfunktionen

Der VHDL 2008-Standard bietet mehrere Hilfsfunktionen, um die Erkennung von Signalflanken zu vereinfachen, insbesondere bei mehrwertigen Aufzählungsarten wie std_ulogic . Das Paket std.standard definiert die Funktionen rising_edge und falling_edge für die Typen bit und boolean ieee.std_logic_1164 Paket ieee.std_logic_1164 definiert sie für die Typen std_ulogic und std_logic .

Hinweis: Bei früheren Versionen von VHDL muss die Verwendung dieser Funktionen die Verwendung von Standardpaketen (z. B. ieee.numeric_bit für Typbit) explizit deklarieren oder sogar in einem Benutzerpaket definieren.

Gehen wir die vorherigen Beispiele noch einmal durch und verwenden Sie die Hilfsfunktionen:

signal clock, d, q: bit;
...
P1_OK_NEW: process(clock)
begin
  if rising_edge(clock) then
    q <= d;
  end if;
end process P1_OK_NEW;
signal clock, d, q: bit;
...
P2_OK_NEW: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif rising_edge(clock) then
    q <= d;
  end if;
end process P2_OK_NEW;
library ieee;
use ieee.std_logic_1164.all;
...
signal clock, reset, d, q: std_ulogic;
...
P4_NEW: process(clock, reset)
begin
  if reset = '1' then
    q <= '0';
  elsif rising_edge(clock) then
    q <= d;
  end if;
end process P4_NEW;

Hinweis: In diesem letzten Beispiel haben wir auch den Test beim Zurücksetzen vereinfacht. Floating, hochohmige Resets sind ziemlich selten und in den meisten Fällen funktioniert diese vereinfachte Version für Simulation und Synthese.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow