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

Een functie gebruiken in VHDL

Functies zijn subprogramma's in VHDL die kunnen worden gebruikt voor het implementeren van veelgebruikte algoritmen. Een functie heeft nul of meer invoerwaarden en retourneert altijd een waarde. Wat een functie behalve de retourwaarde onderscheidt van een procedure, is dat deze geen Wait-statements kan bevatten. Dit betekent dat functies altijd nul simulatietijd verbruiken.

Als u bekend bent met functies of methoden uit andere programmeertalen, moeten VHDL-functies gemakkelijk te begrijpen zijn. In VHDL kunnen we de returnwaarde of return void niet weglaten, een functie moet altijd iets teruggeven en de returnwaarde moet ergens aan worden toegewezen.

Deze blogpost maakt deel uit van de serie Basic VHDL Tutorials.

In VHDL zijn er twee soorten functies, puur en onzuiver functies. Dat een functie puur is, betekent dat het niet is toegestaan ​​om een ​​extern signaal te wijzigen of uit te lezen. We kunnen er zeker van zijn dat wanneer we een pure functie aanroepen met bepaalde argumenten, deze altijd dezelfde waarde zal retourneren. We zeggen dat de functie geen bijwerkingen heeft .

De syntaxis voor het declareren van een functie in VHDL is:

[pure|impure] function <function_name> (<parameter1_name> : <parameter1_type> := <default_value>;
                                        <parameter2_name> : <parameter2_type> := <default_value>;
                                        ... ) return <return_type> is
    <constant_or_variable_declaration>
begin
    <code_performed_by_the_function>
    return <value>
end function;

Het trefwoord pure/onzuiver is optioneel, hoewel het standaard wordt ingesteld op pure als het trefwoord wordt weggelaten. Alle parameters worden behandeld als constanten binnen de functie. Ze kunnen dus niet worden gewijzigd. De standaardwaarden zijn optioneel en de functie moet altijd eindigen op een return verklaring.

Functies hebben hun eigen declaratieve regio tussen de in en begin trefwoorden. Hier gedeclareerde constanten, signalen of variabelen zijn alleen geldig binnen de functie zelf, en ze behouden hun waarden niet bij latere aanroepen van de functie.

Oefening

In deze tutorial gaan we ons concentreren op de pure functie, onzuivere functies komen aan bod in een latere tutorial in deze serie.

In de vorige zelfstudie hebben we een verkeerslichtcontroller-module gemaakt met behulp van een eindige-toestandsmachine (FSM). We hebben veel van de regels met timerberekeningen van de ene toestand naar de andere gekopieerd en geplakt, waarbij we slechts één constante lichtjes hebben gewijzigd.

Ontdek hoe u de toestandsmachinecode kunt vereenvoudigen door een functie te gebruiken:

De definitieve code voor de functie testbench :

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

entity T21_FunctionTb is
end entity;

architecture sim of T21_FunctionTb is

    -- We are using a low clock frequency to speed up the simulation
    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

    -- The Device Under Test (DUT)
    i_TrafficLights : entity work.T21_TrafficLights(rtl)
    generic map(ClockFrequencyHz => ClockFrequencyHz)
    port map (
        Clk         => Clk,
        nRst        => nRst,
        NorthRed    => NorthRed,
        NorthYellow => NorthYellow,
        NorthGreen  => NorthGreen,
        WestRed     => WestRed,
        WestYellow  => WestYellow,
        WestGreen   => WestGreen);

    -- Process for generating clock
    Clk <= not Clk after ClockPeriod / 2;

    -- Testbench sequence
    process is
    begin
        wait until rising_edge(Clk);
        wait until rising_edge(Clk);

        -- Take the DUT out of reset
        nRst <= '1';

        wait;
    end process;

end architecture;

De definitieve code voor de verkeerslichten module :

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

entity T21_TrafficLights is
generic(ClockFrequencyHz : natural);
port(
    Clk         : in std_logic;
    nRst        : in std_logic; -- Negative 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 T21_TrafficLights is

    -- Enumerated type declaration and state signal declaration
    type t_State is (NorthNext, StartNorth, North, StopNorth,
                        WestNext, StartWest, West, StopWest);
    signal State : t_State;

    -- Calculate the number of clock cycles in minutes/seconds
    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;

    -- Counter for counting clock periods, 1 minute max
    signal Counter : integer range 0 to CounterVal(Minutes => 1) +1;

begin

    process(Clk) is
    begin

        if rising_edge(Clk) then
            if nRst = '0' then
                -- Reset values
                NorthRed    <= '1';
                NorthYellow <= '0';
                NorthGreen  <= '0';
                WestRed     <= '1';
                WestYellow  <= '0';
                WestGreen   <= '0';
                State       <= NorthNext;
                Counter     <= 0;

            else
                -- Default values
                NorthRed    <= '0';
                NorthYellow <= '0';
                NorthGreen  <= '0';
                WestRed     <= '0';
                WestYellow  <= '0';
                WestGreen   <= '0';

                Counter <= Counter + 1;

                case State is

                    -- Red light in all directions
                    when NorthNext =>
                        NorthRed <= '1';
                        WestRed  <= '1';
                        -- If 5 seconds have passed
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= StartNorth;
                        end if;

                    -- Yellow light in north/south directions
                    when StartNorth =>
                        NorthRed    <= '1';
                        NorthYellow <= '1';
                        WestRed     <= '1';
                        -- If 5 seconds have passed
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= North;
                        end if;

                    -- Green light in north/south directions
                    when North =>
                        NorthGreen <= '1';
                        WestRed    <= '1';
                        -- If 1 minute has passed
                        if Counter = CounterVal(Minutes => 1) then
                            Counter <= 0;
                            State   <= StopNorth;
                        end if;

                    -- Red and yellow light in north/south direction
                    when StopNorth =>
                        NorthYellow <= '1';
                        WestRed     <= '1';
                        -- If 5 seconds have passed
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= WestNext;
                        end if;

                    -- Red light in all directions
                    when WestNext =>
                        NorthRed <= '1';
                        WestRed  <= '1';
                        -- If 5 seconds have passedf
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= StartWest;
                        end if;

                    -- Yellow light in west/east direction
                    when StartWest =>
                        NorthRed   <= '1';
                        WestRed    <= '1';
                        WestYellow <= '1';
                        -- If 5 seconds have passed
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= West;
                        end if;

                    -- Green light in west/east direction
                    when West =>
                        NorthRed  <= '1';
                        WestGreen <= '1';
                        -- If 1 minute has passed
                        if Counter = CounterVal(Minutes => 1) then
                            Counter <= 0;
                            State   <= StopWest;
                        end if;

                    -- Red and yellow light in west/east direction
                    when StopWest =>
                        NorthRed   <= '1';
                        WestYellow <= '1';
                        -- If 5 seconds have passed
                        if Counter = CounterVal(Seconds => 5) then
                            Counter <= 0;
                            State   <= NorthNext;
                        end if;

                end case;
            end if;
        end if;

    end process;

end architecture;

De golfvorm nadat we de run 5 min . hebben ingevoerd commando in de ModelSim-console:

De golfvorm met cursors toegevoegd bij de overgangen van en naar de StartNorth staat:

Analyse

We hebben de timerberekeningen uit de vorige tutorial vervangen if Counter = ClockFrequencyHz * 5 -1 then met een oproep naar de nieuwe CounterVal functie die we hebben gemaakt:if Counter = CounterVal(Seconds => 5) then .

We kunnen aan de eerste golfvorm-screenshot zien dat de functie van de module ongewijzigd is. Het gebruik van functies voor repetitieve taken is een goede ontwerppraktijk. Vooral als je berekeningen kunt vervangen door beter leesbare regels met termen als Minutes en Seconds .

Een ander voordeel van het gebruik van functies is dat we de implementatie van alle timers tegelijk kunnen wijzigen, in plaats van dit regel voor regel te doen. Als we bijvoorbeeld return TotalSeconds * ClockFrequencyHz; . hadden geschreven in de CounterVal functie, zouden alle timers een klokcyclus te lang hebben geduurd. We kunnen dit dan veranderen in return TotalSeconds * ClockFrequencyHz -1; in de CounterVal functie, en alle timers zouden in één keer worden vastgesteld.

Als we de laatste schermafbeelding van de golfvorm bekijken, kunnen we zien waarom we 1 moeten aftrekken van de timerwaarde die wordt geretourneerd uit de CounterVal functie. Deze golfvorm onderzoekt de duur van de StartNorth staat, zou het precies vijf seconden moeten duren. Wanneer de State signaal verandert in StartNorth , de Counter waarde is 0 en verandert pas na de volgende klokcyclus. Dus als we tot 500 klokcycli hadden geteld, zou de StartNorth toestand zou eigenlijk 501 cycli hebben geduurd. Met onze testbank op 100 Hz, zijn 500 klokcycli precies vijf seconden.

Afhaalmaaltijden

  • Functies kunnen nul of meer parameters hebben, maar ze retourneren altijd een waarde
  • Functies mogen geen wait . bevatten uitspraken
  • Pure functies kunnen geen bijwerkingen hebben, terwijl onzuivere functies dat wel kunnen.

Ga naar de volgende tutorial »


VHDL

  1. Hoe gebruiken we molybdeen?
  2. Een lijst met strings maken in VHDL
  3. Simulatie stoppen in een VHDL-testbench
  4. Een PWM-controller maken in VHDL
  5. Hoe willekeurige getallen te genereren in VHDL
  6. Een procedure gebruiken in een proces in VHDL
  7. Een onzuivere functie gebruiken in VHDL
  8. Een eindige-toestandsmachine maken in VHDL
  9. realloc() Functie in C Library:Hoe te gebruiken? Syntaxis en voorbeeld
  10. free() Functie in C-bibliotheek:Hoe te gebruiken? Leer met voorbeeld
  11. Hoe een snijmolen te gebruiken