Como usar constantes e mapa genérico em VHDL
Criar módulos é uma ótima maneira de reutilizar código, mas geralmente você precisa do mesmo módulo com variações menores em todo o design. É para isso que servem os genéricos e o mapa genérico. Ele permite que você torne certas partes do módulo configuráveis em tempo de compilação.
Constantes são usadas quando queremos evitar digitar o mesmo valor repetidamente. Eles podem ser usados para definir larguras de bits de vetores de sinal em tempo de compilação e também podem ser mapeados para constantes genéricas. Constantes podem ser usadas no lugar de sinais e variáveis em qualquer lugar do código, mas seus valores não podem ser alterados após o tempo de compilação.
Esta postagem do blog faz parte da série de tutoriais básicos de VHDL.
No tutorial anterior, criamos um módulo multiplexador de 4 entradas com largura de barramento de 8 bits. Mas e se também precisarmos de um MUX semelhante com uma largura de barramento diferente? A única solução é copiar e colar o código em um novo módulo e alterar os números?
Felizmente, não.
É possível criar constantes em VHDL usando esta sintaxe:
constant <constant_name> : <type> := <value>;
Constantes podem ser declaradas junto com sinais na parte declarativa de um arquivo VHDL, ou podem ser declaradas junto com variáveis em um processo.
Constantes podem ser passadas para um módulo através da entidade usando o
generic
palavra-chave. A sintaxe para criar uma entidade para um módulo que aceita constantes genéricas é:entity <entity_name> is
generic(
<entity_constant_name> : <type> [:= default_value];
...
);
port(
<entity_signal_name> : in|out|inout <type>;
...
);
end entity;
A sintaxe para instanciar um módulo genérico em outro arquivo VHDL é:
<label> : entity <library_name>.<entity_name>(<architecture_name>)
generic map(
<entity_constant_name> => <value_or_constant>,
...
)
port map(
<entity_signal_name> => <local_signal_name>,
...
);
Exercício
Neste tutorial em vídeo vamos aprender como criar e instanciar um módulo com constantes genéricas em VHDL:
O código final para o MUX genérico testbench :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T16_GenericMapTb is end entity; architecture sim of T16_GenericMapTb is constant DataWidth : integer := 8; signal Sig1 : signed(DataWidth-1 downto 0) := x"AA"; signal Sig2 : signed(DataWidth-1 downto 0) := x"BB"; signal Sig3 : signed(DataWidth-1 downto 0) := x"CC"; signal Sig4 : signed(DataWidth-1 downto 0) := x"DD"; signal Sel : signed(1 downto 0) := (others => '0'); signal Output : signed(DataWidth-1 downto 0); begin -- An Instance of T16_GenericMux with architecture rtl i_Mux1 : entity work.T16_GenericMux(rtl) generic map(DataWidth => DataWidth) port map( Sel => Sel, Sig1 => Sig1, Sig2 => Sig2, Sig3 => Sig3, Sig4 => Sig4, Output => Output); -- Testbench process process is begin wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= Sel + 1; wait for 10 ns; Sel <= "UU"; wait; end process; end architecture;
O código final para o módulo genérico do MUX :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T16_GenericMux is generic(DataWidth : integer); port( -- Inputs Sig1 : in signed(DataWidth-1 downto 0); Sig2 : in signed(DataWidth-1 downto 0); Sig3 : in signed(DataWidth-1 downto 0); Sig4 : in signed(DataWidth-1 downto 0); Sel : in signed(1 downto 0); -- Outputs Output : out signed(DataWidth-1 downto 0)); end entity; architecture rtl of T16_GenericMux is begin process(Sel, Sig1, Sig2, Sig3, Sig4) is begin case Sel is when "00" => Output <= Sig1; when "01" => Output <= Sig2; when "10" => Output <= Sig3; when "11" => Output <= Sig4; when others => -- 'U', 'X', '-', etc. Output <= (others => 'X'); end case; end process; end architecture;
A janela de forma de onda no ModelSim depois que pressionamos executar e ampliamos a linha do tempo:
Análise
Criamos um módulo MUX com largura de barramento configurável. Agora, a largura do barramento é especificada em apenas um local, no arquivo testbench. Podemos alterá-lo facilmente para criar um MUX com uma largura de barramento diferente.
Se compararmos a forma de onda com a do tutorial anterior, podemos ver que o comportamento é idêntico. Isso ocorre porque não alteramos o comportamento do código.
Retirada
- As constantes podem ser usadas para evitar valores codificados em vários lugares
- Os genéricos podem ser usados para tornar os módulos mais adaptáveis
Ir para o próximo tutorial »
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 procedimento em VHDL
- Como usar constantes e mapa genérico em VHDL
- Como usar a instanciação do mapa de portas em VHDL
- Como usar uma instrução Case-When em VHDL
- Como usar assinado e não assinado em VHDL
- Como instalar um simulador e editor VHDL gratuitamente
- Microcontrolador PIC18:o que é e como usá-lo