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
- Os procedimentos podem ser usados como minimódulos para evitar copiar e colar código
- Parâmetros (entradas/saídas) para um procedimento podem ser sinais, variáveis ou constantes
- Ao contrário das funções, os procedimentos podem conter instruções de espera
Ir para o próximo tutorial »
VHDL
- Declaração de Procedimento - Exemplo de VHDL
- Como usamos o molibdênio?
- Como criar uma lista de strings em VHDL
- Como parar a simulação em um testbench VHDL
- Como criar um controlador PWM em VHDL
- Como gerar números aleatórios em VHDL
- Como usar um procedimento em um processo em VHDL
- Como usar uma função impura em VHDL
- Como usar uma função em VHDL
- Como usar um moedor de corte