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

Prozeduren in VHDL: Wiederverwendbaren Code für einfachere Designs

In VHDL sind Prozeduren Subprogramme, die wiederkehrende Codeblöcke vermeiden. Wenn dieselbe Operation an mehreren Stellen benötigt wird, ist ein vollständiges Modul oft überdimensioniert. Eine Prozedur bietet eine leichte, wiederverwendbare Lösung.

Prozeduren können in jedem deklarativen Bereich stehen – Architektur, Package, Prozess – und ihr Gültigkeitsbereich ist auf diesen Bereich beschränkt. Beim Aufruf wird der Prozedurkörper ausgeführt, als stünde der Code an der Aufrufstelle – Modularität ohne Komponenten-Overhead.

Im Gegensatz zu Funktionen geben Prozeduren keinen direkten Rückgabewert. Aber über out oder inout Parameter können Werte zurückgegeben werden – die Prozedur verhält sich wie ein Mini-Modul mit Ein- und Ausgängen.

Teil der Basic VHDL Tutorials Serie.

Syntax

procedure <name> (
  signal|variable|constant <name1> : in|out|inout <type>;
  signal|variable|constant <name2> : in|out|inout <type>;
  ...
) is
  <lokale Deklarationen>
begin
  <Prozedurcode>
end procedure;

Parameterliste definiert Ein-/Ausgänge wie ein Mini-Modul. Parameter können Signals, Variablen, Konstanten sein. Lokale Objekte (Konstanten, Variablen, Typen, Subtypen, Aliases) erlaubt; Signale nicht. Da Prozeduren wait Statements enthalten dürfen, eignen sie sich ideal für Testbenches (BFM-Treiber, DUT-Ausgabeprüfung).

Übung

Im vorherigen Tutorial wurde ein Timer mit tief verschachtelten if-then-else Blöcken gebaut. Jede Verschachtelung erhöhte Komplexität und verringerte Lesbarkeit, obwohl dieselbe Operation auf verschiedenen Signalen ausgeführt wurde. Besser: Wiederkehrende Logik in Prozedur kapseln.

Video-Tutorial zur VHDL-Prozedur:

Beispiel: Prozedur-basierter Timer

Testbench unverändert, außer Prozeduraufruf für DUT:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity T19_ProcedureTb is
end entity;

architecture sim of T19_ProcedureTb is
  constant ClockFrequencyHz : integer := 10;
  constant ClockPeriod : time := 1000 ms / ClockFrequencyHz;
  signal Clk : std_logic := '1';
  signal nRst : std_logic := '0';
  signal Seconds : integer;
  signal Minutes : integer;
  signal Hours : integer;
begin
  i_Timer : entity work.T19_Timer(rtl)
    generic map(ClockFrequencyHz => ClockFrequencyHz)
    port map (Clk => Clk, nRst => nRst, Seconds => Seconds, Minutes => Minutes, Hours => Hours);
  Clk <= not Clk after ClockPeriod / 2;
  process is
  begin
    wait until rising_edge(Clk);
    wait until rising_edge(Clk);
    nRst <= '1';
    wait;
  end process;
end architecture;

Timer-Modul nutzt Prozedur für Zähler-Inkrement:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity T19_Timer is
  generic(ClockFrequencyHz : integer);
  port(
    Clk : in std_logic;
    nRst : in std_logic;
    Seconds : inout integer;
    Minutes : inout integer;
    Hours : inout integer
  );
end entity;

architecture rtl of T19_Timer is
  signal Ticks : integer;
  procedure IncrementWrap(
    signal Counter : inout integer;
    constant WrapValue : in integer;
    constant Enable : in boolean;
    variable Wrapped : out boolean
  ) is
  begin
    Wrapped := false;
    if Enable then
      if Counter = WrapValue - 1 then
        Wrapped := true;
        Counter <= 0;
      else
        Counter <= Counter + 1;
      end if;
    end if;
  end procedure;
begin
  process(Clk) is
    variable Wrap : boolean;
  begin
    if rising_edge(Clk) then
      if nRst = '0' then
        Ticks <= 0; Seconds <= 0; Minutes <= 0; Hours <= 0;
      else
        IncrementWrap(Ticks, ClockFrequencyHz, true, Wrap);
        IncrementWrap(Seconds, 60, Wrap, Wrap);
        IncrementWrap(Minutes, 60, Wrap, Wrap);
        IncrementWrap(Hours, 24, Wrap, Wrap);
      end if;
    end if;
  end process;
end architecture;

Wellenform bestätigt: Minuten-Zähler wrappt korrekt bei 60 Minuten.

Prozeduren in VHDL: Wiederverwendbaren Code für einfachere Designs

Analyse

Verhalten identisch zum ursprünglichen verschachtelten if-Ansatz – nur strukturelle Änderung.

Im Hauptprozess vier aufeinanderfolgende IncrementWrap-Aufrufe kaskadieren die Zähler. Wrap-Variable des vorherigen Aufrufs speist Enable des nächsten. Variable essenziell, da Signal-Updates erst nach Prozess-Suspend sichtbar; Variable liefert sofortigen Datenfluss.

Prozeduren in VHDL: Wiederverwendbaren Code für einfachere Designs

Merksätze

Nächstes Tutorial »

VHDL

  1. VHDL Procedure Beispiel: Inkrementieren eines Standard Logic Vectors
  2. Wie Molybdän die moderne Industrie formt: Nutzung, Vorteile und Versorgungsdynamik
  3. String-Listen in VHDL erstellen: Best Practices & Beispiel
  4. VHDL-Testbench-Simulation sauber beenden
  5. PWM-Controller in VHDL implementieren: Design, Simulation & FPGA-Demo
  6. Zufallszahlen in VHDL generieren: Von Uniform zu OSVVM
  7. In-Prozess-Prozeduren für saubere VHDL-FSM-Entwürfe nutzen
  8. Impure Functions in VHDL nutzen: FSM-Lesbarkeit und Wartbarkeit steigern
  9. VHDL-Funktionen meistern: Praktischer Leitfaden für effizientes Design
  10. Schleiftechniken für Werkzeugschleifmaschinen meistern: Praktischer Leitfaden