Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Industrial programming >> VHDL

Beispiel für einen Anweisungsentpreller

Die Generate-Anweisung in VHDL kann automatisch einen Codeblock in Closures mit identischen Signalen, Prozessen und Instanzen duplizieren. Es ist eine for-Schleife für die Architekturregion, die verkettete Prozesse oder Modulinstanzen erstellen kann.

Im Gegensatz zu einer regulären for-Schleife, die nur in einem Prozess oder einem Unterprogramm vorhanden sein kann, wird die generate-Anweisung direkt in den Architekturbereich der VHDL-Datei gestellt. Wenn es zusammen mit Generika verwendet wird, wird es zu einem leistungsstarken Tool zum Entwerfen anpassbarer VHDL-Module, die eine Wiederverwendung in verschiedenen Designs ermöglichen.

Anweisungssyntax generieren

Die Syntax der Generate-Anweisung lautet wie folgt:

[label :] for <constant_name> in <range> generate
  [declarations_local_to_each_loop_iteration]
[begin]
  <processes_and_instantiations>
end generate [label];

Die in eckigen Klammern eingeschlossenen Teile sind optional. Daher können Sie den deklarativen Bereich und den begin weglassen -Schlüsselwort, wenn Sie keine lokalen Objekte deklarieren möchten. Der Der Platzhalter repräsentiert einen Standard-Ganzzahlbereich mit to oder downto .

Ein-Bit-Switch-Debouncer

Bevor wir mit der generate-Anweisung beginnen, werde ich ein einfaches Modul vorstellen, das wir in diesem Artikel als Beispiel verwenden werden. Es ist ein Entpreller, der einen einzelnen Schaltereingang entprellen kann.

Um es für jede Taktgeschwindigkeit nutzbar zu machen, habe ich eine generische Eingabe namens timeout_cycles hinzugefügt . Diese Konstante gibt an, wie viele Taktzyklen das Timeout sein wird, nachdem sich der Schaltereingang geändert hat. Der Entpreller ignoriert während der Zeitüberschreitung jede weitere Änderung des Schalterwerts.

Die folgende Auflistung zeigt die Entität des Entprellers Modul. Es gibt einen hüpfenden Schalter Eingabe, und dann gibt es das saubere switch_debounced Ausgabe.

entity debouncer is
  generic (
    timeout_cycles : positive
    );
  port (
    clk : in std_logic;
    rst : in std_logic;
    switch : in std_logic;
    switch_debounced : out std_logic
  );
end debouncer;

Das Debouncer-Modul verlässt sich auf einen ganzzahligen Zähler, um die Timeout-Periode zu erreichen. Die Länge des Zählers Signal folgt der generischen Konstante. Das bewirkt die bei der Instanziierung angegebene Timeout-Dauer.

Weil wir den Wert von switch_debounced lesen müssen intern auszugeben, habe ich ein Shadow-Signal namens debounced deklariert , die wir stattdessen verwenden werden. Das ist eine sauberere Lösung als die andere Option, die darin besteht, inout festzulegen Modus auf switch_debounce in der Entität.

Schließlich implementieren wir das Entprellverhalten in einem einzigen Prozess, wie im folgenden Code gezeigt.

architecture rtl of debouncer is

  signal debounced : std_logic;
  signal counter : integer range 0 to timeout_cycles - 1;

begin

  -- Copy internal signal to output
  switch_debounced <= debounced;

  DEBOUNCE_PROC : process(clk)
  begin
    if rising_edge(clk) then
      if rst = '1' then
        counter <= 0;
        debounced <= switch;
        
      else
        
        if counter < timeout_cycles - 1 then
          counter <= counter + 1;
        elsif switch /= debounced then
          counter <= 0;
          debounced <= switch;
        end if;

      end if;
    end if;
  end process;

end architecture;

Die Wellenform unten zeigt eine Simulation der Entprellung Modul in ModelSim. Wir können sehen, dass switch_debounced Ausgang folgt dem Schalter Eingang, aber es ignoriert das unmittelbare Prellverhalten nach der ersten Änderung – es entprellt das Signal.

Verwenden Sie das folgende Formular, um den VHDL-Code aus diesem Artikel herunterzuladen. Wenn Sie Ihre E-Mail-Adresse eingeben, erhalten Sie eine ZIP-Datei, die das gesamte ModelSim-Projekt mit Testbenches und einem Quick-Run-Skript enthält. Sie erhalten zukünftige Updates von VHDLwhiz und können sich jederzeit abmelden.

For-Schleife mit Instanziierungen erzeugen

Um einen Debouncer für ein Array von Schaltern zu erstellen, verwenden wir eine generate-Anweisung, um mehrere Instanzen unseres Ein-Bit-Debouncer-Moduls zu erstellen.

Die folgende Auflistung zeigt die Einheit unseres neuen Array- oder Vektor-Entprellmoduls. Es ähnelt dem Ein-Bit-Debouncer, aber es gibt eine zusätzliche generische Eingabe:switch_count . Es gibt an, wie viele Instanzen des Debouncer-Moduls erstellt werden sollen. Es sollte einen für jeden Schalter geben.

Außerdem habe ich den Eingang und Ausgang des Schalters in die Pluralversionen des Wortes umbenannt, und es handelt sich jetzt um Vektoren statt um einzelne Bits.

entity debouncer_gen_inst is
  generic (
    switch_count : positive;
    timeout_cycles : positive
    );
  port (
    clk : in std_logic;
    rst : in std_logic;
    switches : in std_logic_vector(switch_count - 1 downto 0);
    switches_debounced : out std_logic_vector(switch_count - 1 downto 0)
  );
end debouncer_gen_inst;

In der Architektur ist es an der Zeit, die generate-Anweisung zu verwenden. Es funktioniert wie eine normale for-Schleife, nur dass das Wort „generate“ das Wort „loop“ ersetzt. Aber im Gegensatz zu einer regulären for-Schleife kann sie Modul-Instanziierungen enthalten.

Die for-Schleife wird zur Kompilierzeit ausgeführt und generiert für jede Iteration eine Instanz des Debouncer-Moduls. Da die „i“-Konstante jedoch für jede Iteration unterschiedlich ist, können wir sie verwenden, um die Ein- und Ausgänge der Debouncer einzelnen Bits auf den Schaltervektoren zuzuordnen, wie unten gezeigt.

architecture rtl of debouncer_gen_inst is
begin

  MY_GEN : for i in 0 to switch_count - 1 generate

    DEBOUNCER : entity work.debouncer(rtl)
    generic map (
      timeout_cycles => timeout_cycles
    )
    port map (
      clk => clk,
      rst => rst,
      switch => switches(i),
      switch_debounced => switches_debounced(i)
    );

  end generate;

end architecture;

Beachten Sie, dass es optional ist, die generate-Anweisung zu beschriften, aber es kann sinnvoll sein, dies zu tun. Das Label erscheint in der Simulatorhierarchie und im Syntheseprotokoll, wodurch die spezifische Instanz beim Debuggen leichter identifiziert werden kann.

Die Wellenform unten zeigt eine Simulation des Vektorentprellers. Wir können sehen, dass das Label „MY_GEN“ hier wieder erscheint, mit hinzugefügten Indizes für jede der acht Debouncer-Instanzen.

Diese Testbench ändert nur den Eingang von Schalter Nummer 3, das sehen Sie in der Wellenform und weshalb ich nur die Gruppe MY_GEN(3) erweitert habe.

Sie können dieses Beispiel schnell auf Ihrem Computer ausführen, wenn Sie ModelSim installiert haben. Verwenden Sie das folgende Formular, um den Quellcode und das ModelSim-Projekt herunterzuladen!

For-Schleife erzeugen, die Prozesse enthält

Im letzten Beispiel dieses Artikels verwenden wir eine generate-Anweisung, um eine Reihe identischer Prozesse zu erstellen. Anstatt Instanzen des Ein-Bit-Debouncer-Moduls zu erstellen, habe ich den VHDL-Code daraus entfernt. Die Entität ist dieselbe wie im vorherigen Beispiel, ebenso das Verhalten, aber die Implementierung ist anders.

Wir können sehen, dass ich den DEBOUNCE_PROC-Prozess innerhalb der Generate-Anweisung verschoben und im folgenden Code leicht geändert habe. Dieses Mal deklariere ich zwei lokale Signale innerhalb der Generate-Anweisung:debounced und Zähler .

Jede Iteration der for-Schleife erstellt eine zusätzliche Kopie der Signale und des Prozesses. Durch die Verwendung dieser Signalnamen innerhalb des Prozesses wird auf diejenigen verwiesen, die auf das Gehäuse dieser bestimmten Schleifeniteration beschränkt sind.

Schließlich weise ich das entprellte zu std_logic Signal an das richtige Bit von switches_debounced Modulausgabe mit einer gleichzeitigen Anweisung über dem Prozess.

architecture rtl of debouncer_gen_proc is
begin

  MY_GEN : for i in 0 to switch_count - 1 generate

    signal debounced : std_logic;
    signal counter : integer range 0 to timeout_cycles - 1;

  begin

    switches_debounced(i) <= debounced;

    DEBOUNCE_PROC : process(clk)
    begin
      if rising_edge(clk) then
        if rst = '1' then
          counter <= 0;
          debounced <= switches(i);

        else

          if counter < timeout_cycles - 1 then
            counter <= counter + 1;
          elsif switches(i) /= debounced then
            counter <= 0;
            debounced <= switches(i);
          end if;

        end if;
      end if;
    end process;

  end generate;

end architecture;

Ich habe die Simulationswellenform weggelassen, da sie genau so aussieht wie im vorherigen Beispiel mit Modulinstanziierung. Das Verhalten ist identisch.

Sie können den gesamten Code mit dem unten stehenden Formular herunterladen. Wenn Sie Ihre E-Mail-Adresse eingeben, abonnieren Sie Updates von VHDLwhiz. Aber keine Sorge, in jeder E-Mail, die ich versende, befindet sich ein Link zum Abbestellen.

Hinterlassen Sie unten einen Kommentar, wenn Sie eine weitere nützliche Anwendung zum Generieren von Anweisungen zum Teilen haben! ?


VHDL

  1. Prozeduranweisung – VHDL-Beispiel
  2. Aufzeichnungen - VHDL-Beispiel
  3. Variablen – VHDL-Beispiel
  4. Schaltung mit Schalter
  5. Analyseoptionen
  6. Schaltertypen
  7. C#-switch-Anweisung
  8. C# break-Anweisung
  9. C#-Continue-Anweisung
  10. C++ Switch Case-Anweisung mit BEISPIEL