Cómo usar una instrucción Case-When en VHDL
La declaración Case-When hará que el programa tome una de varias rutas diferentes, según el valor de una señal, variable o expresión. Es una alternativa más elegante a una instrucción If-Then-Elsif-Else con múltiples Elsif.
Otros lenguajes de programación tienen construcciones similares, usando palabras clave como switch , caso o seleccionar . Entre otras cosas, las declaraciones Case-When se usan comúnmente para implementar multiplexores en VHDL. ¡Sigue leyendo o mira el video para descubrir cómo!
Esta publicación de blog es parte de la serie Tutoriales básicos de VHDL.
La sintaxis básica para la instrucción Case-When es:case <expression> is
when <choice> =>
code for this branch
when <choice> =>
code for this branch
...
end case;
El <expression>
suele ser una variable o una señal. La declaración Case puede contener múltiples when
opciones, pero solo se seleccionará una opción.
El <choice>
puede ser un valor único como "11"
:when "11" =>
O puede ser un rango como 5 to 10
:when 5 to 10 =>
Puede contener varios valores como 1|3|5
:when 1|3|5 =>
Y lo más importante, el others
elección. Se selecciona siempre que no coincida ninguna otra opción:when others =>
El others
opción es equivalente al Else
rama en la sentencia If-Then-Elsif-Else.
Ejercicio
En este video tutorial aprenderemos a crear un multiplexor usando la instrucción Case-When en VHDL:
El código final que creamos en este tutorial:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T14_CaseWhenTb is end entity; architecture sim of T14_CaseWhenTb is signal Sig1 : unsigned(7 downto 0) := x"AA"; signal Sig2 : unsigned(7 downto 0) := x"BB"; signal Sig3 : unsigned(7 downto 0) := x"CC"; signal Sig4 : unsigned(7 downto 0) := x"DD"; signal Sel : unsigned(1 downto 0) := (others => '0'); signal Output1 : unsigned(7 downto 0); signal Output2 : unsigned(7 downto 0); begin -- Stimuli for the selector signal 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; -- MUX using if-then-else process(Sel, Sig1, Sig2, Sig3, Sig4) is begin if Sel = "00" then Output1 <= Sig1; elsif Sel = "01" then Output1 <= Sig2; elsif Sel = "10" then Output1 <= Sig3; elsif Sel = "11" then Output1 <= Sig4; else -- 'U', 'X', '-' etc. Output1 <= (others => 'X'); end if; end process; -- Equivalent MUX using a case statement process(Sel, Sig1, Sig2, Sig3, Sig4) is begin case Sel is when "00" => Output2 <= Sig1; when "01" => Output2 <= Sig2; when "10" => Output2 <= Sig3; when "11" => Output2 <= Sig4; when others => -- 'U', 'X', '-', etc. Output2 <= (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:
La salida a la consola del simulador cuando presionamos el botón ejecutar en ModelSim:
VSIM 2> run # ** Warning: NUMERIC_STD."=": metavalue detected, returning FALSE # Time: 50 ns Iteration: 1 Instance: /t14_casewhentb # ** Warning: NUMERIC_STD."=": metavalue detected, returning FALSE # Time: 50 ns Iteration: 1 Instance: /t14_casewhentb # ** Warning: NUMERIC_STD."=": metavalue detected, returning FALSE # Time: 50 ns Iteration: 1 Instance: /t14_casewhentb # ** Warning: NUMERIC_STD."=": metavalue detected, returning FALSE # Time: 50 ns Iteration: 1 Instance: /t14_casewhentb
Análisis
Primero, creamos un proceso usando If-Then-Elsif-Else que enviaría una de las señales Sig1
, Sig2
, Sig3
, o Sig4
, basado en el valor de la señal del selector Sel
.
Luego creamos un proceso que hizo exactamente lo mismo, usando la instrucción Case-When. Podemos ver en la forma de onda que las señales de salida de los dos procesos, Output1
y Output2
, se comporta exactamente igual.
En nuestro ejemplo, el Sel
la señal tiene sólo cuatro valores legales. Pero si hubiera habido un mayor número de posibilidades, podemos ver fácilmente que la instrucción Case-When puede ayudar a que el código sea más legible. Esta es la forma preferida de crear dicho componente por la mayoría de los diseñadores de VHDL.
Comprensión del multiplexor fue el punto extra de este ejercicio. Los multiplexores, o MUX para abreviar, son componentes centrales en el diseño digital. Es simplemente un interruptor que selecciona una de varias entradas y la envía a la salida.
Esta es una ilustración de cómo nuestro MUX reenvía la señal de entrada seleccionada:
Usamos el others
cláusula para capturar todos los valores de Sel
que no eran unos ni ceros. Como aprendimos en el tutorial de std_logic, estas señales pueden tener una cantidad de valores que no son '0'
o '1'
. Es una buena práctica de diseño tratar con estos valores generando 'X'
. Esto indica un valor desconocido en esta señal y también será visible en la lógica descendente.
Podemos ver en la forma de onda que cuando el Sel
la señal se volvió roja, Output1
y Output2
también cambió a "XX"
. Este es when others =>
en acción.
Además, la salida de la consola en ModelSim muestra una advertencia debido al Sel
la señal se establece en "UU"
. Los mensajes “** Advertencia:NUMERIC_STD.”=”:metavalor detectado, devolviendo FALSO” aparecen en el tiempo de simulación de 50 ns, que es exactamente cuando las señales se vuelven rojas.
Para llevar
- Case-When se puede usar en lugar de múltiples declaraciones If-Then-Elsif
- El
when others =>
se puede usar para implementar una opción predeterminada - Los multiplexores se crean preferiblemente usando declaraciones Case-When
Ir al siguiente tutorial »
VHDL
- Declaración de procedimiento:ejemplo de VHDL
- ¿Cómo utilizamos el molibdeno?
- Cómo crear una lista de cadenas en VHDL
- Cómo detener la simulación en un banco de pruebas VHDL
- Cómo crear un controlador PWM en VHDL
- Cómo generar números aleatorios en 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 crear una máquina de estados finitos en VHDL
- Cómo usar una amoladora cortadora