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

VHDL에서 함수를 사용하는 방법

함수는 자주 사용되는 알고리즘을 구현하는 데 사용할 수 있는 VHDL의 하위 프로그램입니다. 함수는 0개 이상의 입력 값을 사용하며 항상 값을 반환합니다. 반환 값 외에도 함수를 프로시저와 구분하는 것은 Wait 문을 포함할 수 없다는 것입니다. 이는 함수가 항상 시뮬레이션 시간을 0으로 소비한다는 것을 의미합니다.

다른 프로그래밍 언어의 함수나 메서드에 익숙하다면 VHDL 함수를 이해하기 쉬워야 합니다. VHDL에서는 반환 값을 생략하거나 void를 반환할 수 없으며, 함수는 항상 무언가를 반환해야 하고 반환 값은 무언가에 할당되어야 합니다.

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

VHDL에는 두 가지 유형의 함수가 있습니다. 순수 그리고 불순한 기능. 함수가 순수하다는 것은 외부 신호를 수정하거나 읽을 수 없다는 것을 의미합니다. 특정 인수를 사용하여 순수 함수를 호출하면 항상 동일한 값을 반환할 것임을 확신할 수 있습니다. 이 기능에는 부작용이 없습니다. .

VHDL에서 함수를 선언하는 구문은 다음과 같습니다.

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

순수/불순한 키워드는 선택 사항이지만 키워드가 생략되면 기본적으로 순수로 설정됩니다. 모든 매개변수는 함수 내에서 상수로 처리됩니다. 따라서 변경할 수 없습니다. 기본값은 선택 사항이며 함수는 항상 return에서 종료되어야 합니다. 성명서.

함수에는 in 사이에 고유한 선언 영역이 있습니다. 및 begin 키워드. 여기에 선언된 상수, 신호 또는 변수는 함수 자체 내에서만 유효하며 함수에 대한 후속 호출을 통해 값을 유지하지 않습니다.

운동

이 튜토리얼에서는 순수 함수에 초점을 맞출 것입니다. 순수 함수는 이 시리즈의 이후 튜토리얼에서 다룰 것입니다.

이전 자습서에서는 FSM(유한 상태 머신)을 사용하여 신호등 컨트롤러 모듈을 만들었습니다. 타이머 계산이 포함된 많은 줄을 한 상태에서 다른 상태로 복사하여 붙여넣고 하나의 상수만 약간 변경했습니다.

다음 함수를 사용하여 상태 기계어 코드를 단순화하는 방법을 알아보십시오.

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;

신호등 모듈의 최종 코드 :

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;

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

StartNorth로/부터 전환할 때 커서가 추가된 파형 상태:

분석

이전 튜토리얼 if Counter = ClockFrequencyHz * 5 -1 then의 타이머 계산을 대체했습니다. 새로운 CounterVal 호출로 우리가 만든 함수:if Counter = CounterVal(Seconds => 5) then .

첫 번째 파형 스크린샷에서 모듈의 기능이 변경되지 않았음을 알 수 있습니다. 반복적인 작업에 함수를 사용하는 것은 좋은 디자인 방법입니다. 특히 Minutes와 같은 용어가 포함된 더 읽기 쉬운 행으로 계산을 대체할 수 있는 경우 및 Seconds .

함수를 사용하는 또 다른 이점은 한 줄씩 수행하는 대신 모든 타이머의 구현을 한 번에 변경할 수 있다는 것입니다. 예를 들어 return TotalSeconds * ClockFrequencyHz;를 작성했다면 CounterVal 기능이 없으면 모든 타이머가 한 클럭 주기를 너무 오래 지속했을 것입니다. 그런 다음 이것을 return TotalSeconds * ClockFrequencyHz -1;로 변경할 수 있습니다. CounterVal 기능을 사용하면 모든 타이머가 한 번에 고정됩니다.

마지막 파형 스크린샷을 살펴보면 CounterVal에서 반환된 타이머 값에서 1을 빼야 하는 이유를 알 수 있습니다. 기능. 이 파형은 StartNorth 정확히 5초 동안 지속되어야 합니다. State StartNorth로 신호 변경 , Counter 값은 0이고 다음 클럭 사이클 이후에만 변경됩니다. 따라서 최대 500개의 클록 주기를 계산했다면 StartNorth 상태는 실제로 501주기 동안 지속되었을 것입니다. 100Hz에서 실행되는 테스트벤치에서 500클럭 사이클은 정확히 5초입니다.

테이크아웃

다음 튜토리얼로 이동 »


VHDL

  1. 몰리브덴은 어떻게 사용합니까?
  2. VHDL에서 문자열 목록을 만드는 방법
  3. VHDL 테스트벤치에서 시뮬레이션을 중지하는 방법
  4. VHDL에서 PWM 컨트롤러를 만드는 방법
  5. VHDL에서 난수를 생성하는 방법
  6. VHDL의 프로세스에서 프로시저를 사용하는 방법
  7. VHDL에서 불순 함수를 사용하는 방법
  8. C 라이브러리의 realloc() 함수:어떻게 사용합니까? 구문 및 예
  9. C 라이브러리의 free() 함수:어떻게 사용합니까? 예제로 배우기
  10. 커터 그라인더 사용 방법