Procedures in VHDL gebruiken: je ontwerp vereenvoudigen met herbruikbare code
In VHDL zijn procedures subprogramma's die ontwerpers in staat stellen herhalende codeblokken te vermijden. Wanneer dezelfde operatie op meerdere plekken nodig is, kan het maken van een volledige module overkill zijn. Een procedure biedt een lichtgewicht, herbruikbare oplossing.
Procedures mogen in elk declaratief gebied gedeclareerd worden – architectuur, package of proces – en hun bereik is beperkt tot dat gebied. Wanneer aangeroepen, wordt de body van de procedure uitgevoerd alsof de code op die plek geschreven was, wat je de voordelen van modulariteit geeft zonder de overhead van een apart component.
In tegenstelling tot functies retourneren procedures geen waarde direct. Je kunt echter waarden teruggeven door out of inout signalen in de parameterlijst te declareren, wat de procedure effectief laat fungeren als een kleine module met in- en outputs.
Deze post is onderdeel van de Basic VHDL Tutorials-reeks.
De canonische syntax voor het definiëren van een procedure is geïllustreerd hieronder:
procedure <procedure_name> (signal|variable|constant <name1> : in|out|inout <type>; signal|variable|constant <name2> : in|out|inout <type>; ... ) is <declarations_for_use_within_the_procedure> begin <code_performed_by_the_procedure_here> end procedure;
De parameterlijst definieert de in- en outputs van de procedure – net als een mini-module. Parameters mogen signalen, variabelen of constanten zijn. Binnen de procedure kun je additionele objecten declareren (constanten, variabelen, types, subtypes, aliases) die alleen binnen dat blok geldig zijn; signalen mogen niet lokaal gedeclareerd worden.
Omdat procedures wait-statements mogen bevatten, zijn ze vooral nuttig in testbenches – bijvoorbeeld als eenvoudige BFM-drivers of voor het controleren van DUT-outputs.
Oefening
In de voorgaande tutorial werd een timermodule gebouwd met diep geneste if-then-else-statements. Elk genest niveau voegde complexiteit toe en verminderde de leesbaarheid, zelfs als dezelfde operatie op verschillende signaalsets werd uitgevoerd. Een betere benadering is om de herhalende logica in een procedure te encapsuleren.
De volgende videotutorial loopt door het maken van een VHDL-procedure:
Voorbeeld: Procedure-gebaseerde timer
De testbench-code blijft ongewijzigd, behalve de toevoeging van een procedure-aanroep om de DUT aan te sturen:
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; -- 10 Hz 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;
De timermodule zelf gebruikt nu een procedure voor het incrementeren van de teller:
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; -- Negatieve reset 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;
De golfform hieronder bevestigt dat de minuutteller correct wrapt wanneer de timer 60 minuten bereikt:

Analyse
Uit de golfform zien we dat de wrap-functionaliteit identiek gedraagt aan de oorspronkelijke geneste-if-implementatie. De verandering is puur structureel – geen wijziging in de onderliggende logica.
De eerste parameter, Counter, is een inout-signaal, wat de procedure in staat stelt om de waarde te lezen en bij te werken. De tweede en derde parameters, WrapValue en Enable, zijn constanten; ze worden binnen de procedure als compile-time constanten behandeld.
De laatste parameter, Wrapped, is een variable gedeclareerd als out. Het fungeert als een pseudo-retourwaarde, die aangeeft of de teller tijdens die aanroep gewrapt is.
In het hoofdproces koppelen vier opeenvolgende aanroepen van IncrementWrap de tellers aan elkaar. De Wrap-variabele van de vorige aanroep voedt de volgende aanroep's Enable-input. Het gebruik van een variabele is essentieel hier omdat signaalupdates pas zichtbaar zijn nadat het proces suspendeert; een variabele biedt directe, procedurale dataflow.

Kernpunten
- Procedures fungeren als herbruikbare subprogramma's, die dubbele code elimineren.
- Parameters kunnen signalen, variabelen of constanten zijn, wat flexibiliteit biedt.
- In tegenstelling tot functies mogen procedures
wait-statements bevatten, wat ze ideaal maakt voor testbench-drivers.
Ga door naar de volgende tutorial »
VHDL
- Freesmes Slijper Technieken Beheersen: Een Praktische Gids
- Hoe molybdeen de moderne industrie vormt: toepassingen, voordelen en leveringsdynamiek
- VHDL Procedure Voorbeeld: Een Standard Logic Vector Incrementeren
- Dynamische string-lijsten in VHDL: Best Practices & Voorbeeld
- Een VHDL-testbench netjes beëindigen: methoden en best practices
- Een PWM-controller implementeren in VHDL: Ontwerp, Simulatie en FPGA-demo
- Willekeurige getallen genereren in VHDL: Van Uniform naar OSVVM
- In-process procedures benutten voor schonere VHDL FSM-ontwerpen
- Impure functies in VHDL gebruiken: FSM-leesbaarheid en onderhoudbaarheid verbeteren
- VHDL-functies onder de knie krijgen: een praktische gids voor efficiënt ontwerp
- Een eindige-toestandsmachine in VHDL ontwerpen: een praktisch verkeerslichtvoorbeeld