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 procedure gebruiken in een proces in VHDL

Het is mogelijk om vanuit een procedure externe signalen aan te sturen. Zolang het signaal binnen het bereik van de procedure valt, is het toegankelijk voor lezen of schrijven, zelfs als het niet in de parameterlijst staat.

Procedures die zijn gedeclareerd in het declaratieve gebied van de architectuur, kunnen geen externe signalen aansturen. Dit komt simpelweg omdat er tijdens het compileren geen signalen in het bereik zijn. Een procedure die binnen een proces is gedeclareerd, heeft daarentegen toegang tot alle signalen die het proces kan zien.

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

Dergelijke procedures kunnen worden gebruikt voor het opruimen van algoritmen in processen waarin dezelfde bewerkingen meerdere keren plaatsvinden. We zouden een normale procedure kunnen gebruiken waarbij alle in- en uitgangen worden toegewezen aan lokale signalen wanneer je die oproept, maar daar gaat het niet om. Door de invoer- en uitvoersignalen van de procedureaanroep weg te laten, hoeven we minder te typen, en belangrijker nog, we maken de code leesbaarder.

Stel je een proces voor dat een complex communicatieprotocol implementeert. Het zou een stuk gemakkelijker zijn om de uitvoeringsstroom van het hoofdalgoritme te begrijpen als sommige bewerkingen zouden worden vervangen door procedureaanroepen zoals RequestToSend() of SendAutorizationHeader() . Je zou weten wat die regels deden door alleen maar naar de namen van de procedures te kijken.

Oefening

In de vorige zelfstudie hebben we onze finite-state machine (FSM) -code vereenvoudigd door een onzuivere functie te gebruiken. We reden de Counter signaal van de onzuivere functie, en we hebben de retourwaarde gebruikt om te bepalen wanneer de status moet worden gewijzigd. Maar wat als we de toewijzing van de State . willen verplaatsen signaal ook naar de functie en negeer de geretourneerde waarde?

Het is niet mogelijk om een ​​functie aan te roepen zonder de retourwaarde toe te wijzen aan iets in VHDL. Als we dit proberen, zal ModelSim de compileerfout produceren:Geen haalbare vermeldingen voor subprogramma "CounterExpired".

In plaats daarvan kunnen we hiervoor een procedure gebruiken. Een procedure die binnen een proces is gedeclareerd, heeft toegang tot elk signaal binnen de reikwijdte van dat proces. Dit is vergelijkbaar met de onzuivere functie, maar omdat het een procedure is, is er geen retourwaarde.

In deze video-tutorial zullen we de FSM-code vereenvoudigen door een procedure te gebruiken die in een proces is gedeclareerd:

De definitieve code voor de Procedure in Process testbench :

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

entity T23_ProcedureInProcessTb is
end entity;

architecture sim of T23_ProcedureInProcessTb 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.T23_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 Traffic Lights module :

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

entity T23_TrafficLights is
generic(ClockFrequencyHz : integer);
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 T23_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;

    -- Counter for counting clock periods, 1 minute max
    signal Counter : integer range 0 to ClockFrequencyHz * 60;

begin

    process(Clk) is

        -- Procedure for changing state after a given time
        procedure ChangeState(ToState : t_State;
                              Minutes : integer := 0;
                              Seconds : integer := 0) is
            variable TotalSeconds : integer;
            variable ClockCycles  : integer;
        begin
            TotalSeconds := Seconds + Minutes * 60;
            ClockCycles  := TotalSeconds * ClockFrequencyHz -1;
            if Counter = ClockCycles then
                Counter <= 0;
                State   <= ToState;
            end if;
        end procedure;

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

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

                Counter <= Counter + 1;

                case State is

                    -- Red in all directions
                    when NorthNext =>
                        NorthRed <= '1';
                        WestRed  <= '1';
                        ChangeState(StartNorth, Seconds => 5);

                    -- Red and yellow in north/south direction
                    when StartNorth =>
                        NorthRed    <= '1';
                        NorthYellow <= '1';
                        WestRed     <= '1';
                        ChangeState(North, Seconds => 5);

                    -- Green in north/south direction
                    when North =>
                        NorthGreen <= '1';
                        WestRed    <= '1';
                        ChangeState(StopNorth, Minutes => 1);

                    -- Yellow in north/south direction
                    when StopNorth =>
                        NorthYellow <= '1';
                        WestRed     <= '1';
                        ChangeState(WestNext, Seconds => 5);

                    -- Red in all directions
                    when WestNext =>
                        NorthRed <= '1';
                        WestRed  <= '1';
                        ChangeState(StartWest, Seconds => 5);

                    -- Red and yellow in west/east direction
                    when StartWest =>
                        NorthRed   <= '1';
                        WestRed    <= '1';
                        WestYellow <= '1';
                        ChangeState(West, Seconds => 5);

                    -- Green in west/east direction
                    when West =>
                        NorthRed  <= '1';
                        WestGreen <= '1';
                        ChangeState(StopWest, Minutes => 1);

                    -- Yellow in west/east direction
                    when StopWest =>
                        NorthRed   <= '1';
                        WestYellow <= '1';
                        ChangeState(NorthNext, Seconds => 5);

                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:

Analyse

We hebben het gedrag van de module niet veranderd en we kunnen zien dat de golfvorm ongewijzigd is.

Vergeleken met de code uit de tutorial waarin we aanvankelijk de verkeerslichtenmodule hebben gemaakt, is de FSM-code nu veel beter leesbaar. U kunt het algoritme dat het implementeert eenvoudig volgen door de code te lezen. Het is handig om de logica voor het wijzigen van timer en status in één procedure te hebben, omdat het ervoor zorgt dat het overal gelijk wordt geïmplementeerd.

Afhaalmaaltijden

  • Een procedure die in een proces is gedeclareerd, heeft toegang tot elk signaal binnen de reikwijdte van dat proces
  • Procedures binnen processen kunnen worden gebruikt om de leesbaarheid van de code te verbeteren

VHDL

  1. Zelfstudie - Inleiding tot VHDL
  2. Procedureverklaring - VHDL-voorbeeld
  3. Hoe gebruiken we molybdeen?
  4. Een lijst met strings maken in VHDL
  5. Een onzuivere functie gebruiken in VHDL
  6. Een functie gebruiken in VHDL
  7. Een procedure gebruiken in VHDL
  8. Een timer maken in VHDL
  9. Een geklokt proces maken in VHDL
  10. Hoe Port Map-instantiatie te gebruiken in VHDL
  11. Hoe een snijmolen te gebruiken