산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Industrial programming >> VHDL

VHDL의 프로세스에서 프로시저를 사용하는 방법

프로시저에서 외부 신호를 구동할 수 있습니다. 신호가 프로시저 범위 내에 있는 한 매개변수 목록에 나열되지 않더라도 읽기 또는 쓰기를 위해 액세스할 수 있습니다.

아키텍처의 선언적 영역에 선언된 프로시저는 외부 신호를 구동할 수 없습니다. 이는 단순히 컴파일 시간에 해당 범위에 신호가 없기 때문입니다. 반면에 프로세스 내에서 선언된 프로시저는 프로세스가 볼 수 있는 모든 신호에 액세스할 수 있습니다.

이 블로그 게시물은 기본 VHDL 자습서 시리즈의 일부입니다.

이러한 절차는 동일한 작업이 여러 번 발생하는 프로세스에서 알고리즘을 정리하는 데 사용할 수 있습니다. 호출할 때 모든 입력과 출력이 로컬 신호에 할당되는 일반적인 절차를 사용할 수 있지만 그것이 요점이 아닙니다. 프로시저 호출에서 입력 및 출력 신호를 생략하여 입력을 줄여야 하며 더 중요하게는 코드를 더 읽기 쉽게 만들어야 합니다.

복잡한 통신 프로토콜을 구현하는 프로세스를 상상해 보십시오. 일부 작업이 RequestToSend()와 같은 프로시저 호출로 대체된다면 메인 알고리즘의 실행 흐름을 이해하는 것이 훨씬 쉬울 것입니다. 또는 SendAutorizationHeader() . 프로시저 이름만 보면 이 줄이 무엇을 했는지 알 수 있습니다.

운동

이전 자습서에서는 불순 함수를 사용하여 유한 상태 기계(FSM) 코드를 단순화했습니다. 우리는 Counter을(를) 운전하고 있었습니다. 불순한 함수에서 신호를 보내고 반환 값을 사용하여 상태를 변경할 시기를 결정했습니다. 하지만 State의 할당을 옮기고 싶다면 어떻게 해야 할까요? 함수에 신호를 보내고 반환 값을 무시합니까?

VHDL에서 반환 값을 할당하지 않고는 함수를 호출할 수 없습니다. 그렇게 하려고 하면 ModelSim에서 컴파일 오류가 발생합니다. 하위 프로그램 "CounterExpired"에 대한 실행 가능한 항목이 없습니다.

대신 이를 위한 절차를 사용할 수 있습니다. 프로세스 내에서 선언된 프로시저는 해당 프로세스 범위 내의 모든 신호에 액세스할 수 있습니다. 불순 함수와 비슷하지만 프로시저이므로 반환 값이 없습니다.

이 비디오 자습서에서는 프로세스에 선언된 프로시저를 사용하여 FSM 코드를 단순화합니다.

Process 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;

신호등 모듈의 최종 코드 :

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;

run 5 min를 입력한 후의 파형 ModelSim 콘솔의 명령:

분석

모듈의 동작을 변경하지 않았으며 파형이 변경되지 않은 것을 볼 수 있습니다.

처음에 신호등 모듈을 만든 튜토리얼의 코드와 비교하면 FSM 코드가 훨씬 더 읽기 쉽습니다. 코드를 읽으면 구현하는 알고리즘을 쉽게 따를 수 있습니다. 단일 프로시저에 타이머와 상태 변경 로직을 포함하는 것은 그것이 사용되는 모든 곳에서 동일하게 구현되도록 보장하기 때문에 유익합니다.

테이크아웃


VHDL

  1. 튜토리얼 - VHDL 소개
  2. 절차문 - VHDL 예
  3. 몰리브덴은 어떻게 사용합니까?
  4. VHDL에서 문자열 목록을 만드는 방법
  5. VHDL에서 불순 함수를 사용하는 방법
  6. VHDL에서 함수를 사용하는 방법
  7. VHDL에서 프로시저를 사용하는 방법
  8. VHDL에서 타이머를 만드는 방법
  9. VHDL에서 클럭 프로세스를 만드는 방법
  10. 커터 그라인더 사용 방법