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
- Zelfstudie - Inleiding tot VHDL
- Procedureverklaring - VHDL-voorbeeld
- Hoe gebruiken we molybdeen?
- Een lijst met strings maken in VHDL
- Een onzuivere functie gebruiken in VHDL
- Een functie gebruiken in VHDL
- Een procedure gebruiken in VHDL
- Een timer maken in VHDL
- Een geklokt proces maken in VHDL
- Hoe Port Map-instantiatie te gebruiken in VHDL
- Hoe een snijmolen te gebruiken