Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Industrial programming >> VHDL

Como usar um procedimento em VHDL


Um procedimento é um tipo de subprograma em VHDL que pode nos ajudar a evitar a repetição de código. Às vezes surge a necessidade de realizar operações idênticas em vários lugares ao longo do projeto. Embora a criação de um módulo possa ser um exagero para operações menores, um procedimento geralmente é o que você deseja.

Os procedimentos podem ser declarados dentro de qualquer região declarativa. O escopo do procedimento será limitado a onde for declarado, arquitetura, pacote ou processo. Sempre que você chamar o procedimento, ele se comportará como se o código do procedimento fosse inserido de onde foi chamado.

Um procedimento não retorna um valor como uma função, mas você pode retornar valores declarando out ou inout sinais na lista de parâmetros.

Esta postagem do blog faz parte da série de tutoriais básicos de VHDL.

A sintaxe básica para criar um procedimento é:
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;


A lista de parâmetros de um procedimento define suas entradas e saídas, como um minimódulo. Pode ser um sinal ou uma constante, mas ao contrário de um módulo, também pode ser uma variável. Você pode declarar objetos entre as palavras-chave “is” e “begin” que são válidos apenas dentro do procedimento. Estes podem incluir constantes, variáveis, tipos, subtipos e aliases, mas não sinais.

Ao contrário das funções, os procedimentos podem conter instruções de espera. Portanto, eles são frequentemente usados ​​em testbenches como BFMs simples para simular interfaces ou para verificar a saída do dispositivo em teste (DUT).

Exercício


No tutorial anterior, criamos um módulo de timer usando instruções If-Then-Else aninhadas. Cada nível de If-Then-Else dentro de outro If-Then-Else adiciona complexidade ao design e torna-se menos legível. Em cada nível de lógica, estamos basicamente fazendo a mesma operação em um conjunto diferente de sinais. Não existe uma maneira melhor de fazer isso?

Neste vídeo tutorial vamos aprender como criar um procedimento em VHDL:



O código final para o procedimento 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;

O código final para o módulo do temporizador usando um procedimento:
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;

A janela de forma de onda no ModelSim, ampliada na linha do tempo onde o Minutes sinal está quebrando:





Análise


Podemos ver pela forma de onda que o encapsulamento de sinais ainda funciona como no tutorial anterior. Isso porque na verdade não alteramos a função no módulo, apenas a maneira como ela é implementada.

O primeiro item na lista de parâmetros para o IncrementWrap procedimento é o Counter sinal. É declarado usando a direção inout para que o procedimento seja capaz de ler e definir seu valor.

O segundo e terceiro itens na lista de parâmetros são constantes. Isso significa que os valores que você colocar aqui aparecerão como constantes dentro do procedimento. O WrapValue entrada junto com o Enable input determina se o Counter sinal é incrementado ou encapsulado.

O último item da lista de parâmetros é uma variável com direção out . O objetivo dessa saída é informar ao chamador do procedimento que o contador envolveu. Nós o usamos aqui como um valor de retorno.

No processo principal temos quatro chamadas para o IncrementWrap procedimento. Cada uma das chamadas subsequentes usa o Wrap variável para habilitar a contagem. Não teria funcionado se tivéssemos usado um sinal em vez de uma variável, porque os valores do sinal são atualizados apenas quando um processo entra em suspensão. Precisamos que o valor de saída de uma chamada de procedimento seja usado como entrada para uma chamada na próxima linha. Assim, tem que ser uma variável.


Retirada


Ir para o próximo tutorial »

VHDL

  1. Declaração de Procedimento - Exemplo de VHDL
  2. Como usamos o molibdênio?
  3. Como criar uma lista de strings em VHDL
  4. Como parar a simulação em um testbench VHDL
  5. Como criar um controlador PWM em VHDL
  6. Como gerar números aleatórios em VHDL
  7. Como usar um procedimento em um processo em VHDL
  8. Como usar uma função impura em VHDL
  9. Como usar uma função em VHDL
  10. Como usar um moedor de corte