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

如何在 VHDL 中使用过程

程序是 VHDL 中的一种子程序,可以帮助我们避免重复代码。有时需要在整个设计中的多个位置执行相同的操作。虽然创建一个模块对于小操作来说可能是多余的,但过程通常是你想要的。

可以在任何声明区域内声明过程。该过程的范围将仅限于它被声明的地方、架构、包或流程。每当您调用该过程时,它的行为就像该过程的代码插入到调用它的位置一样。

过程不像函数那样返回值,但您可以通过声明 out 来返回值 或 inout 参数列表中的信号。

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

创建过程的基本语法是:
procedure <procedure_name> (signal|variable|constant <name1> : in|out|inout <type>;
                            signal|variable|constant <name2> : in|out|inout <type>;
                            ... ) is
    <declarations_for_use_within_the_procedure>
begin
    <code_performed_by_the_procedure_here>
end procedure;

一个过程的参数列表定义了它的输入和输出,有点像一个迷你模块。它可以是信号或常数,但与模块不同的是,它也可以是变量。您可以在“is”和“begin”关键字之间声明对象,这些关键字仅在过程内部有效。这些可能包括常量、变量、类型、子类型和别名,但不包括信号。

与函数不同,过程可能包含等待语句。因此,它们通常用于简单的 BFM 等测试平台中,用于模拟接口或检查被测设备 (DUT) 的输出。

运动

在之前的教程中,我们使用嵌套的 If-Then-Else 语句创建了一个计时器模块。另一个 If-Then-Else 中的每个级别的 If-Then-Else 都会增加设计的复杂性,并且可读性会降低。在每个逻辑级别上,我们基本上对不同的信号集执行相同的操作。难道没有更好的办法吗?

在本视频教程中,我们将学习如何在 VHDL 中创建程序:

testbench 过程的最终代码 :

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

entity T19_ProcedureTb is
end entity;

architecture sim of T19_ProcedureTb is

    -- We're slowing down the clock to speed up simulation time
    constant ClockFrequencyHz : integer := 10; -- 10 Hz
    constant ClockPeriod : time := 1000 ms / ClockFrequencyHz;

    signal Clk     : std_logic := '1';
    signal nRst    : std_logic := '0';
    signal Seconds : integer;
    signal Minutes : integer;
    signal Hours   : integer;

begin

    -- The Device Under Test (DUT)
    i_Timer : entity work.T19_Timer(rtl)
    generic map(ClockFrequencyHz => ClockFrequencyHz)
    port map (
        Clk     => Clk,
        nRst    => nRst,
        Seconds => Seconds,
        Minutes => Minutes,
        Hours   => Hours);

    -- 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 T19_Timer is
generic(ClockFrequencyHz : integer);
port(
    Clk     : in std_logic;
    nRst    : in std_logic; -- Negative reset
    Seconds : inout integer;
    Minutes : inout integer;
    Hours   : inout integer);
end entity;

architecture rtl of T19_Timer is

    -- Signal for counting clock periods
    signal Ticks : integer;

    procedure IncrementWrap(signal   Counter   : inout integer;
                            constant WrapValue : in    integer;
                            constant Enable    : in    boolean;
                            variable Wrapped   : out   boolean) is
    begin
        Wrapped := false;
        if Enable then
            if Counter = WrapValue - 1 then
                Wrapped := true;
                Counter <= 0;
            else
                Counter <= Counter + 1;
            end if;
        end if;
    end procedure;

begin

    process(Clk) is
        variable Wrap : boolean;
    begin
        if rising_edge(Clk) then

            -- If the negative reset signal is active
            if nRst = '0' then
                Ticks   <= 0;
                Seconds <= 0;
                Minutes <= 0;
                Hours   <= 0;
            else

                -- Cascade counters
                IncrementWrap(Ticks, ClockFrequencyHz, true, Wrap);
                IncrementWrap(Seconds,             60, Wrap, Wrap);
                IncrementWrap(Minutes,             60, Wrap, Wrap);
                IncrementWrap(Hours,               24, Wrap, Wrap);

            end if;
        end if;
    end process;

end architecture;

ModelSim 中的波形窗口,放大了 Minutes 所在的时间轴 信号正在包装:

分析

我们可以从波形中看到,信号的环绕仍然像在上一个教程中那样工作。那是因为我们实际上并没有改变模块上的功能,只是改变了它的实现方式。

IncrementWrap 参数列表中的第一项 程序是 Counter 信号。它使用方向 inout 声明 使程序能够读取和设置其值。

参数列表中的第二项和第三项是常量。这意味着您在此处输入的值将显示为常量inside 的程序。 WrapValueEnable 一起输入 输入确定 Counter 信号增加或包装。

参数列表最后一项是方向为out的变量 .此输出的目的是通知调用者计数器包装的过程。我们在这里使用它有点像返回值。

在主进程中,我们对 IncrementWrap 进行了四次调用 程序。随后的每个调用都使用 Wrap 变量以启用计数。如果我们使用信号而不是变量,它就不会起作用,因为信号值仅在进程进入睡眠状态时更新。我们需要将一个过程调用的输出值用作下一行调用的输入。因此,它必须是一个变量。

外卖

转到下一个教程 »


VHDL

  1. 过程语句 - VHDL 示例
  2. 我们如何使用钼?
  3. 如何在 VHDL 中创建字符串列表
  4. 如何在 VHDL 测试平台中停止仿真
  5. 如何在 VHDL 中创建 PWM 控制器
  6. 如何在 VHDL 中生成随机数
  7. 如何在 VHDL 中的进程中使用过程
  8. 如何在 VHDL 中使用不纯函数
  9. 如何在 VHDL 中使用函数
  10. 如何在 VHDL 中创建有限状态机
  11. 如何在 VHDL 中创建计时器
  12. 如何使用刀具磨床