Cómo usar constantes y mapas genéricos en VHDL
La creación de módulos es una excelente manera de reutilizar el código, pero a menudo necesita el mismo módulo con variaciones más pequeñas a lo largo de su diseño. Para eso están los genéricos y el mapa genérico. Le permite configurar ciertas partes del módulo en tiempo de compilación.
Las constantes se utilizan cuando queremos evitar escribir el mismo valor una y otra vez. Se pueden usar para definir anchos de bits de vectores de señal en tiempo de compilación, e incluso se pueden asignar a constantes genéricas. Las constantes se pueden usar en lugar de señales y variables en cualquier parte del código, pero sus valores no se pueden cambiar después del tiempo de compilación.
Esta publicación de blog es parte de la serie Tutoriales básicos de VHDL.
En el tutorial anterior, creamos un módulo multiplexor de 4 entradas con un ancho de bus de 8 bits. Pero, ¿y si también necesitamos un MUX similar con un ancho de bus diferente? ¿La única solución es copiar y pegar el código en un módulo nuevo y cambiar los números?
Afortunadamente, no.
Es posible crear constantes en VHDL usando esta sintaxis:constant <constant_name> : <type> := <value>;
Las constantes se pueden declarar junto con las señales en la parte declarativa de un archivo VHDL, o se pueden declarar junto con las variables en un proceso.
Las constantes se pueden pasar a un módulo a través de la entidad usando el generic
palabra clave. La sintaxis para crear una entidad para un módulo que acepta constantes genéricas es:entity <entity_name> is
generic(
<entity_constant_name> : <type> [:= default_value];
...
);
port(
<entity_signal_name> : in|out|inout <type>;
...
);
end entity;
La sintaxis para instanciar un módulo genérico en otro archivo VHDL es:<label> : entity <library_name>.<entity_name>(<architecture_name>)
generic map(
<entity_constant_name> => <value_or_constant>,
...
)
port map(
<entity_signal_name> => <local_signal_name>,
...
);
Ejercicio
En este video tutorial aprenderemos a crear e instanciar un módulo con constantes genéricas en VHDL:
El código final para el testbench genérico de MUX :
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;
El código final para el módulo MUX genérico :
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;
La ventana de forma de onda en ModelSim después de presionar Ejecutar y hacer zoom en la línea de tiempo:
Análisis
Creamos un módulo MUX con un ancho de bus configurable. Ahora, el ancho del bus se especifica en un solo lugar, en el archivo del banco de pruebas. Podemos cambiarlo fácilmente para crear un MUX con un ancho de bus diferente.
Si comparamos la forma de onda con la del tutorial anterior, podemos ver que el comportamiento es idéntico. Esto se debe a que no hemos cambiado el comportamiento del código en absoluto.
Para llevar
- Se pueden usar constantes para evitar codificar valores en varios lugares
- Los genéricos se pueden usar para hacer que los módulos sean más adaptables
Ir al siguiente tutorial »
VHDL
- Cómo usar un procedimiento en un proceso en VHDL
- Cómo usar una función impura en VHDL
- Cómo usar una función en VHDL
- Cómo usar un procedimiento en VHDL
- Cómo usar constantes y mapas genéricos en VHDL
- Cómo usar la creación de instancias de mapas de puertos en VHDL
- Cómo usar una instrucción Case-When en VHDL
- Cómo usar Firmado y Sin firmar en VHDL
- Cómo usar sentencias condicionales en VHDL:If-Then-Elsif-Else
- Cómo instalar un simulador y editor VHDL gratis
- Microcontrolador PIC18:qué es y cómo usarlo