亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Industrial programming >> VHDL

如何在 VHDL 中的进程中使用过程

可以从程序驱动外部信号。只要信号在过程范围内,就可以对其进行读写访问,即使它没有在参数列表中列出。

在体系结构的声明区域中声明的过程不能驱动任何外部信号。这仅仅是因为在编译时其范围内没有信号。另一方面,在进程中声明的过程将可以访问该进程可以看到的所有信号。

这篇博文是基本 VHDL 教程系列的一部分。

此类程序可用于在多次发生相同操作的过程中对算法进行整理。我们可以使用一个正常的过程,当你调用它时,所有的输入和输出都分配给本地信号,但这不是重点。通过在过程调用中省略输入和输出信号,我们必须减少输入,更重要的是,我们使代码更具可读性。

想象一个实现复杂通信协议的进程。如果把一些操作换成像RequestToSend()这样的过程调用,就更容易理解主算法的执行流程了 或 SendAutorizationHeader() .只需查看过程名称,您就会知道这些行做了什么。

运动

在上一教程中,我们使用不纯函数简化了有限状态机 (FSM) 代码。我们驾驶的是 Counter 来自不纯函数的信号,我们使用返回值来确定何时更改状态。但是如果我们想移动 State 的赋值怎么办 信号也传入函数,忽略返回值?

如果不将返回值分配给 VHDL 中的某些内容,就不可能调用函数。如果我们尝试这样做,ModelSim 将产生编译错误:子程序“CounterExpired”没有可行的条目。

相反,我们可以为此使用一个过程。在进程中声明的过程可以访问该进程范围内的任何信号。这类似于不纯函数,但由于是过程,所以没有返回值。

在本视频教程中,我们将使用在进程中声明的过程来简化 FSM 代码:

进程中过程的最终代码 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. 如何在 VHDL 中使用常量和通用映射
  11. 如何在 VHDL 中使用端口映射实例化
  12. 如何使用刀具磨床