vhdl - srr - Desplace un std_logic_vector de n bit a derecha o izquierda
vhdl rol example (6)
Esto normalmente se hace manualmente eligiendo los bits apropiados del vector y luego agregando 0s.
Por ejemplo, para desplazar un vector de 8 bits.
variable tmp : std_logic_vector(15 downto 0)
...
tmp := x"00" & tmp(15 downto 8);
Esperemos que esta simple respuesta sea útil para alguien.
Tengo una signal tmp : std_logic_vector(15 downto 0)
vectorial signal tmp : std_logic_vector(15 downto 0)
Tengo que cambiarlo a izquierda o derecha de n bit. ¿Cómo puedo realizar esta operación? Pensé en la operación de concatenación pero no sabía cómo usarla.
Hay dos maneras en que puede lograr esto. Concatenación, y funciones de cambio / rotación.
La concatenación es la forma "manual" de hacer las cosas. Usted especifica qué parte de la señal original desea "mantener" y luego concatenar datos en uno u otro extremo. Por ejemplo: tmp <= tmp (14 downto 0) & ''0'';
Funciones de cambio (lógicas, aritméticas): son funciones genéricas que le permiten cambiar o rotar un vector de muchas maneras. Las funciones son: sll (shift left logic), srl (shift right logic). Un cambio lógico inserta ceros. Los cambios aritméticos (sra / sla) insertan el bit más a la izquierda o más a la derecha, pero funcionan de la misma manera que el cambio lógico. Tenga en cuenta que para todas estas operaciones, especifique qué desea cambiar (tmp) y cuántas veces desea realizar el cambio ( n bits)
Funciones de rotación: rol (girar a la izquierda), ror (girar a la derecha). La rotación hace precisamente eso, el MSB termina en el LSB y todo se desplaza a la izquierda (rol) o al revés para ror.
Aquí hay una referencia útil que encontré (vea la primera página).
No sugeriría usar sll
o srl
con std_logic_vector.
Durante la simulación, sll
me dio un valor de ''U'' para esos bits, donde esperaba 0.
Usa las shift_left()
, shift_right()
.
Por ejemplo:
OP1 : in std_logic_vector(7 downto 0); signal accum: std_logic_vector(7 downto 0);
accum <= std_logic_vector(shift_left(unsigned(accum), to_integer(unsigned(OP1)))); accum <= std_logic_vector(shift_right(unsigned(accum), to_integer(unsigned(OP1))));
Personalmente, creo que la concatenación es la mejor solución. La implementación genérica sería
entity shifter is
generic (
REGSIZE : integer := 8);
port(
clk : in str_logic;
Data_in : in std_logic;
Data_out : out std_logic(REGSIZE-1 downto 0);
end shifter ;
architecture bhv of shifter is
signal shift_reg : std_logic_vector(REGSIZE-1 downto 0) := (others<=''0'');
begin
process (clk) begin
if rising_edge(clk) then
shift_reg <= shift_reg(REGSIZE-2 downto 0) & Data_in;
end if;
end process;
end bhv;
Data_out <= shift_reg;
Ambos se implementarán como registros de desplazamiento. Si necesita más registros de turnos de los que está dispuesto a gastar recursos (por ejemplo, dividir 1000 números por 4), podría considerar usar un BRAM para almacenar los valores y un solo registro de turnos para contener "índices" que resulten en el Cambio correcto de todos los números.
Use la biblioteca ieee.numeric_std
y el tipo de vector apropiado para los números en los que está trabajando ( unsigned
o con signed
).
Luego, los operadores son sla
/ sra
para los cambios aritméticos (es decir, rellenar con el bit de signo en los desplazamientos a la derecha y lsb en los desplazamientos a la izquierda) y sll
/ srl
para los cambios lógicos (es decir, rellenar con ''0'').
Pasa un parámetro al operador para definir el número de bits a desplazar:
A <= B srl 2; -- logical shift right 2 bits
Actualizar:
No tengo idea de lo que estaba escribiendo arriba (¡gracias a Val por señalarlo!)
Por supuesto, la forma correcta de cambiar los tipos con unsigned
y unsigned
es con las funciones shift_left
y shift_right
definidas en ieee.numeric_std
.
Los operadores shift y sll
, ror
, etc. son para vectores de boolean
, bit
o std_ulogic
, y pueden tener un comportamiento interesante inesperado en el sentido de que los cambios aritméticos duplican el bit final incluso cuando se desplaza a la izquierda.
Y mucha más historia se puede encontrar aquí:
http://jdebp.eu./FGA/bit-shifts-in-vhdl.html
Sin embargo, la respuesta a la pregunta original es todavía
sig <= tmp sll number_of_bits;
add_Pbl <= to_stdlogicvector(to_bitvector(dato_cu(25 downto 2)) sll 1);
add_Pbl is a std_logic_vector of 24 bit
dato_cu is a std_logic_vector of 32 bit
Primero, necesita convertir el std_logic_vector
con la función to_bitvector()
porque la sentencia sll funciona con la lógica 1 y 0 bits.