Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Industrial programming >> VHDL

Impure functies in VHDL gebruiken: FSM-leesbaarheid en onderhoudbaarheid verbeteren

In VHDL kan een impure functie toegang krijgen tot of wijzigen in elk signaal binnen zijn lexicale bereik, inclusief signalen die niet als parameters zijn opgesomd. Deze mogelijkheid geeft de functie bijwerkingen – de returnwaarde kan variëren zelfs wanneer dezelfde argumenten worden geleverd, en het kan externe signalen wijzigen die niet direct worden geretourneerd.

Terwijl pure functies beperkt zijn tot deterministisch gedrag, zijn impure functies onmisbaar voor het opschonen van complexe toestandsmachinelogica door herhalende of bijwerkende taken in een enkele, goed genaamde subprogramma te verplaatsen.

Let op: Impure functies worden het beste binnen een proces gedeclareerd. Het declareren ervan op architectuur- of pakketniveau biedt geen voordeel, omdat de bereik van de functie beperkt zou zijn tot de signalen die al op compiletijd in bereik zijn.

Wanneer en waarom impure functies gebruiken

Typische scenario's zijn:

  • Een teller resetten wanneer een timer verloopt.
  • Controleren of een aftelling voltooid is zonder de teller-vergelijkingslogica te dupliceren.
  • Signaalmanipulatie encapsuleren die de hoofd-FSM anders zou verwarren.

Het gebruik van een impure functie houdt de kern-toestandsmachinelogica leesbaar terwijl de benodigde bijwerkende gedraging behouden blijft.

Syntax

Om een impure functie te declareren, voeg je simpelweg het sleutelwoord impure voor function:

 impure function CounterExpired(Minutes : integer := 0; Seconds : integer := 0) return boolean; 

Raadpleeg de functie-tutorial voor volledige syntaxisdetails.

Oefening: FSM-herstructurering met een impure functie

Eerder berekenden we tijdvertragingen met een pure functie CounterVal en resetten we de teller handmatig wanneer de timer verloopt. De volgende impure functie consolideert deze logica:

Testbench (T22_ImpureFunctionTb)

 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T22_ImpureFunctionTb is end entity; architecture sim of T22_ImpureFunctionTb is -- Lage klokfrequentie om simulatie te versnellen constant ClockFrequencyHz : integer := 100; -- 100 Hz constant ClockPeriod : time := 1000 ms / ClockFrequencyHz; signal Clk : std_logic := '1'; signal nRst : std_logic := '0'; signal NorthRed : std_logic; signal NorthYellow : std_logic; signal NorthGreen : std_logic; signal WestRed : std_logic; signal WestYellow : std_logic; signal WestGreen : std_logic; begin -- DUT-instantiatie i_TrafficLights : entity work.T22_TrafficLights(rtl) generic map(ClockFrequencyHz => ClockFrequencyHz) port map ( Clk => Clk, nRst => nRst, NorthRed => NorthRed, NorthYellow => NorthYellow, NorthGreen => NorthGreen, WestRed => WestRed, WestYellow => WestYellow, WestGreen => WestGreen); -- Klokgeneratie Clk <= not Clk after ClockPeriod / 2; -- Testbench-sequentie process is begin wait until rising_edge(Clk); wait until rising_edge(Clk); -- Reset vrijgeven nRst <= '1'; wait; end process; end architecture; 

Verkeerslichten-module (T22_TrafficLights)

 library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T22_TrafficLights is generic(ClockFrequencyHz : integer); port( Clk : in std_logic; nRst : in std_logic; -- Negatieve reset NorthRed : out std_logic; NorthYellow : out std_logic; NorthGreen : out std_logic; WestRed : out std_logic; WestYellow : out std_logic; WestGreen : out std_logic); end entity; architecture rtl of T22_TrafficLights is -- Pure functie om klokcycli voor een gegeven tijd te berekenen function CounterVal(Minutes : integer := 0; Seconds : integer := 0) return integer is variable TotalSeconds : integer; begin TotalSeconds := Seconds + Minutes * 60; return TotalSeconds * ClockFrequencyHz -1; end function; -- FSM-toestandsdefinitie type t_State is (NorthNext, StartNorth, North, StopNorth, WestNext, StartWest, West, StopWest); signal State : t_State; -- Teller voor klokperiodes, tot één minuut signal Counter : integer range 0 to ClockFrequencyHz * 60; begin process(Clk) is -- Impure functie die Counter leest en aanstuurt impure function CounterExpired(Minutes : integer := 0; Seconds : integer := 0) return boolean is begin if Counter = CounterVal(Minutes, Seconds) then Counter <= 0; return true; else return false; end if; end function; begin if rising_edge(Clk) then if nRst = '0' then -- Reset toestand en signalen State <= NorthNext; Counter <= 0; NorthRed <= '1'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '1'; WestYellow <= '0'; WestGreen <= '0'; else -- Standaard outputs NorthRed <= '0'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '0'; WestYellow <= '0'; WestGreen <= '0'; Counter <= Counter + 1; case State is when NorthNext => NorthRed <= '1'; WestRed <= '1'; if CounterExpired(Seconds => 5) then State <= StartNorth; end if; when StartNorth => NorthRed <= '1'; NorthYellow <= '1'; WestRed <= '1'; if CounterExpired(Seconds => 5) then State <= North; end if; when North => NorthGreen <= '1'; WestRed <= '1'; if CounterExpired(Minutes => 1) then State <= StopNorth; end if; when StopNorth => NorthYellow <= '1'; WestRed <= '1'; if CounterExpired(Seconds => 5) then State <= WestNext; end if; when WestNext => NorthRed <= '1'; WestRed <= '1'; if CounterExpired(Seconds => 5) then State <= StartWest; end if; when StartWest => NorthRed <= '1'; WestRed <= '1'; WestYellow <= '1'; if CounterExpired(Seconds => 5) then State <= West; end if; when West => NorthRed <= '1'; WestGreen <= '1'; if CounterExpired(Minutes => 1) then State <= StopWest; end if; when StopWest => NorthRed <= '1'; WestYellow <= '1'; if CounterExpired(Seconds => 5) then State <= NorthNext; end if; end case; end if; end if; end process; end architecture; 

Golfform-inzicht

Na het uitgeven van het run 5 min-commando in ModelSim toont de simulatie identiek gedrag aan de oorspronkelijke FSM – alleen de code is schoner geworden. De teller-resetlogica is nu geencapsuleerd in CounterExpired, wat duplicatie en potentiële fouten vermindert.

Impure functies in VHDL gebruiken: FSM-leesbaarheid en onderhoudbaarheid verbeteren

Analyse

De impure functie verplaatst de teller-vergelijking en -reset van meerdere FSM-statussen naar een enkel subprogramma. Deze wijziging verbetert de leesbaarheid: CounterExpired(Seconds => 5) vermittelt duidelijk de intentie, terwijl Counter = CounterVal(Seconds => 5) meer uitgebreid is.

Hoewel impure functies bij overmatig gebruik bijwerkingen kunnen verbergen, zorgt het lokaal houden binnen een proces ervoor dat de omringende code deterministisch en makkelijk te auditen blijft. In de praktijk worden ze vaker in testbenches gebruikt waar correctheid belangrijk is maar het risico op subtiele bugs lager is dan in synthetiseerbare RTL.

Impure functies in VHDL gebruiken: FSM-leesbaarheid en onderhoudbaarheid verbeteren

Belangrijkste opmerkingen

  • Impure functies kunnen signalen lezen of aansturen die niet als parameters zijn opgesomd.
  • Declareer ze binnen een proces om de lokale signaalbereik te benutten.
  • Gebruik ze om herhalende bijwerkende logica te encapsuleren, wat de codehelderheid verbetert en duplicatie vermindert.

Ga door naar de volgende tutorial voor geavanceerde VHDL-technieken.

VHDL

  1. Freesmes Slijper Technieken Beheersen: Een Praktische Gids
  2. Hoe molybdeen de moderne industrie vormt: toepassingen, voordelen en leveringsdynamiek
  3. realloc() in C gebruiken: Syntaxis, best practices & voorbeeld
  4. Beheersing van C's free() functie: Praktische gids & voorbeeld
  5. Dynamische string-lijsten in VHDL: Best Practices & Voorbeeld
  6. Een VHDL-testbench netjes beëindigen: methoden en best practices
  7. Een PWM-controller implementeren in VHDL: Ontwerp, Simulatie en FPGA-demo
  8. Willekeurige getallen genereren in VHDL: Van Uniform naar OSVVM
  9. In-process procedures benutten voor schonere VHDL FSM-ontwerpen
  10. VHDL-functies onder de knie krijgen: een praktische gids voor efficiënt ontwerp
  11. Een eindige-toestandsmachine in VHDL ontwerpen: een praktisch verkeerslichtvoorbeeld