Cómo usar Firmado y Sin firmar en VHDL
Los tipos con y sin signo en VHDL son vectores de bits, al igual que el tipo std_logic_vector. La diferencia es que, si bien std_logic_vector es excelente para implementar buses de datos, es inútil para realizar operaciones aritméticas.
Si intenta agregar cualquier número a un tipo std_logic_vector, ModelSim producirá el error de compilación:No hay entradas factibles para el operador infijo "+". Esto se debe a que el compilador no sabe cómo interpretar esta colección de bits que es el vector.
Esta publicación de blog es parte de la serie Tutoriales básicos de VHDL.
Debemos declarar nuestro vector como firmado o sin firmar para que el compilador lo trate como un número.
La sintaxis para declarar señales firmadas y no firmadas es:signal <name> : signed(<N-bits> downto 0) := <initial_value>;
signal <name> : unsigned(<N-bits> downto 0) := <initial_value>;
Al igual que con std_logic_vector, los rangos pueden ser to
o downto
cualquier rango Pero declarar señales con rangos distintos a downto 0
es tan poco común, que dedicar más tiempo al tema solo serviría para confundirnos. El valor inicial es opcional, por defecto es 'U'
para todos los bits.
Ya hemos estado usando el integer
type para operaciones aritméticas en tutoriales anteriores. Entonces, ¿por qué necesitamos los tipos firmados y sin firmar? Para la mayoría, a los diseñadores digitales les gusta tener más control sobre cuántos bits usa realmente una señal.
Además, los valores firmados y sin firmar se reinician, mientras que el simulador arrojará un error en tiempo de ejecución si un integer
se incrementa más allá de los límites. Finalmente, firmado y sin firmar puede tener otros valores como 'U'
y 'X'
, mientras que los enteros solo pueden tener valores numéricos. Estos metavalores pueden ayudarnos a descubrir errores en nuestro diseño.
Ejercicio
En este video, aprendemos cómo se comportan las señales firmadas y sin firmar, y cómo se comportan de manera diferente:
El código final que creamos en este tutorial:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T12_SignedUnsignedTb is end entity; architecture sim of T12_SignedUnsignedTb is signal UnsCnt : unsigned(7 downto 0) := (others => '0'); signal SigCnt : signed(7 downto 0) := (others => '0'); signal Uns4 : unsigned(3 downto 0) := "1000"; signal Sig4 : signed(3 downto 0) := "1000"; signal Uns8 : unsigned(7 downto 0) := (others => '0'); signal Sig8 : signed(7 downto 0) := (others => '0'); begin process is begin wait for 10 ns; -- Wrapping counter UnsCnt <= UnsCnt + 1; SigCnt <= SigCnt + 1; -- Adding signals Uns8 <= Uns8 + Uns4; Sig8 <= Sig8 + Sig4; end process; end architecture;
La ventana de forma de onda en ModelSim, ampliada en las partes interesantes:
Análisis
La raíz de todas las señales en la forma de onda se establece en hexadecimal para que podamos compararlas por igual.
En el ejemplo del contador envolvente, vemos que las señales firmadas y sin firmar se comportan exactamente de la misma manera. Ambos UnsCnt
y SigCnt
comienzan en 0 y se incrementan uno a uno hasta FF. Hex FF (decimal 255) es el valor más grande que pueden contener nuestras señales de 8 bits. Por lo tanto, el siguiente incremento los envuelve a ambos de nuevo a 0.
Creamos las dos señales de 4 bits Uns4
y Sig4
, y les dio a ambos un valor inicial de “1000”. Podemos ver en la forma de onda que ambos son solo 8 hexadecimales (1000 binario).
Las últimas dos señales de 8 bits que creamos fueron Uns8
y Sig8
. Podemos ver en la forma de onda que sus valores iniciales son 0, como cabría esperar. ¡Pero a partir de ahí, se comportan de manera diferente! Aparentemente, los tipos con y sin signo marcaron la diferencia al agregar dos señales de diferentes longitudes.
Esto se debe a algo conocido como extensión de signo . Sumar números positivos o negativos almacenados en vectores de igual longitud es la misma operación en lógica digital. Esto se debe a cómo funciona el complemento a dos. Si los vectores son de diferentes longitudes, habrá que alargar el vector más corto.
El número binario de 4 bits sin signo "1000" es 8 decimal, mientras que el número de 4 bits con signo "1000" es -8 decimal. El “1” en el extremo izquierdo del número con signo indica que se trata de un número negativo. Por lo tanto, el compilador extiende el signo de las dos señales de 4 bits de manera diferente.
Esta es una visualización de cómo la extensión de signo crea los diferentes valores para el Uns8
y Sig8
señales:
Para llevar
- Las señales de tipo con y sin signo son vectores que se pueden utilizar en operaciones aritméticas
- Las señales de tipo firmado y sin firmar se desbordarán en silencio
- La extensión de firma puede crear resultados diferentes para tipos firmados y sin firmar
Ir al siguiente tutorial »
VHDL
- Firmado vs. Sin firmar 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 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 instalar un simulador y editor VHDL gratis
- Microcontrolador PIC18:qué es y cómo usarlo
- ¿Qué es un designador de referencia y cómo lo usamos en ensamblaje?