¿Cómo desplazar a la izquierda / derecha un valor STD_LOGIC_VECTOR dentro de una instrucción WHEN?

4

Estoy intentando crear una ALU parametrizable que maneja datos firmados de N-Bit. Sin embargo, los métodos que conozco de desplazamiento a la izquierda / derecha tampoco funcionarán porque los valores se definen como STD_LOGIC_VECTOR:

--Declaration
A, B, X : in  STD_LOGIC_VECTOR(N downto 0);
--Usage
OUTPUT <= (A sra X) WHEN OPERATION = "0000" ELSE

O porque está dentro de una instrucción WHEN:

OUTPUT <= (A <= X(N) & X(N downto 1)) WHEN OPERATION = "1001" ELSE
--This causes Type of OUTPUT is incompatible with type of <= error

Para reiterar, necesito desplazar A / X bits de izquierda / derecha. ¿Podría alguien apuntarme en la dirección correcta?

Código completo:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use work.DigEng.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity core is
    Generic (
           N : INTEGER);
    Port ( CLK : in  STD_LOGIC;
           A, B, X : in  STD_LOGIC_VECTOR(N downto 0);
              OPERATION : in STD_LOGIC_VECTOR(3 downto 0); --Allows us up to 16 operations
              FLAGS : in STD_LOGIC_VECTOR(7 downto 0);
           ALU_OUTPUT : out  STD_LOGIC_VECTOR(N downto 0));
end core;

architecture Behavioral of core is
    signal TEMP_OUTPUT : STD_LOGIC_VECTOR(N downto 0);
begin
    TEMP_OUTPUT <= (A) WHEN OPERATION = "0000" ELSE
                --Bit-wise Logic
                 (A AND B) WHEN OPERATION = "0001" ELSE
                 (A OR B) WHEN OPERATION = "0010" ELSE
                 (A XOR B) WHEN OPERATION = "0011" ELSE
                 (NOT A) WHEN OPERATION = "0100" ELSE
                --Arithmetic
                 STD_LOGIC_VECTOR(SIGNED(A) + 1) WHEN OPERATION = "0101" ELSE
                 STD_LOGIC_VECTOR(SIGNED(A) - 1) WHEN OPERATION = "0110" ELSE
                 STD_LOGIC_VECTOR(SIGNED(A) + SIGNED(B)) WHEN OPERATION = "0111" ELSE
                 STD_LOGIC_VECTOR(SIGNED(A) - SIGNED(B)) WHEN OPERATION = "1000" ELSE
                --Shift
                 --(A <= X(N) & X(N downto 1)) WHEN OPERATION = "1001" ELSE
                 "1111";

end Behavioral;
    
pregunta SRG3006

1 respuesta

2

Hay un par de maneras de ir con esto. Si desea usar sra , entonces necesita usar los tipos correctos. El operando de la izquierda debe ser un BIT_VECTOR y el de la derecha debe ser un entero. Su salida es un BIT_VECTOR . De modo que puede definir sus entradas y salidas como BIT_VECTOR en lugar de STD_LOGIC_VECTOR y luego usar una conversión para obtener solo su X en un entero. Pienso que los lanzamientos apropiados serían algo así (pero tendrá que revisarme nuevamente ya que no tengo un compilador VHDL en esta máquina):

--Declaration
A, B, X : in  BIT_VECTOR(N downto 0);
--Usage
OUTPUT <= (A sra to_integer(unsigned(to_stdlogicvector(X)) WHEN OPERATION = "1001" ELSE

O, si es posible, defina A como BIT_VECTOR y X como STD_LOGIC_VECTOR para dejar de lado la conversión adicional.

Alternativamente, podría seguir usando STD_LOGIC_VECTOR para sus entradas y salidas. Pero luego necesitaría convertir ambos operandos a los tipos apropiados y luego emitir la salida:

--Declaration
A, B, X : in  STD_LOGIC_VECTOR(N downto 0);
--Usage
OUTPUT <= to_stdlogicvector(to_bitvector(A) sra to_integer(unsigned(X)) WHEN OPERATION = "1001" ELSE

Todos estos deberían estar disponibles en ieee.numeric_std.ALL y IEEE.STD_LOGIC_1164 .

La diferencia entre BIT_VECTOR y STD_LOGIC_VECTOR es que BIT_VECTOR solo tiene dos valores: 0 y 1 . Mientras que STD_LOGIC_VECTOR tiene nueve: U , X , 0 , 1 , Z , W , L , H y - . Donde:

U = no inicializado
X = desconocido: una línea de múltiples fuentes se maneja '0' y '1' simultáneamente (*)
0 = logic 0
1 = logic 1
Z = alta impedancia (tri estado)
W = débil desconocido
L = débil "0"
H = débil "1"
- = no importa

En general, es mejor usar STD_LOGIC_VECTOR ya que es más flexible y un mejor modelo de señales del mundo real.

Mirando tu código para la concatenación, no estoy completamente seguro de lo que estás tratando de hacer. Parece que está intentando asignar el MSB de X concatenado con el MSB hasta el LSB + 1 de X a A y luego asignarlo a TEMP_OUTPUT . Creo que es la asignación doble <= la que está causando el error.

Lo que desea para un desplazamiento aritmético a la derecha es establecer los bits más a la derecha, menos el número de turnos de los bits más significativos de la salida a la mayoría de los bits a la izquierda, menos el número de turnos de los bits menos significativos de la entrada. Luego, configure todo el número de desplazamiento de los bits más significativos de la salida en el bit más significativo de la entrada.

La primera parte es un poco complicada, pero la segunda parte se puede lograr fácilmente con la palabra clave others .

--|right most - shift # * MSB of output|   |left most - shift # * LSB of input| |MSBs of output|  
((N - to_integer(unsigned(X))) downto 0 => A(N downto to_integer(unsigned(X))), others => A(N)) WHEN OPERATION = "1001" ELSE

El problema básico que está teniendo es uno de conversiones de tipo. Por lo tanto, deberá pensar qué señal debe ser de qué tipo y qué tipos de operandos las funciones que está utilizando requieren y emiten en consecuencia.

    
respondido por el embedded.kyle

Lea otras preguntas en las etiquetas