web-dev-qa-db-fra.com

décaler un vecteur de std_logic_n de n bits à droite ou à gauche

J'ai un vecteur signal tmp : std_logic_vector(15 downto 0)

Je dois le déplacer à gauche ou à droite de n bit. Comment puis-je réaliser cette opération? Je pensais à l'opération de concaténation mais je ne savais pas comment l'utiliser.

18
Mazzy

Utilisez la bibliothèque ieee.numeric_std et le type de vecteur approprié pour les nombres sur lesquels vous travaillez (unsigned ou signed).

Ensuite, les opérateurs sont sla/sra pour les décalages arithmétiques (c'est-à-dire remplir avec le bit de signe sur les décalages à droite et lsb sur les décalages à gauche) et sll/srl pour les décalages logiques (c'est-à-dire remplir avec des «0»).

Vous transmettez un paramètre à l'opérateur pour définir le nombre de bits à déplacer:

A <= B srl 2; -- logical shift right 2 bits

</ s>

Mettre à jour:

Je n'ai aucune idée de ce que j'ai écrit ci-dessus (merci à Val de l'avoir signalé!)

Bien sûr, la manière correcte de décaler les types signed et unsigned consiste à utiliser les fonctions shift_left et shift_right définies dans ieee.numeric_std.

Les opérateurs de décalage et de rotation sll, ror etc sont des vecteurs de boolean, bit ou std_ulogic et peuvent avoir comportement inattendu intéressant en ce que les décalages arithmétiques dupliquent le bit final même si la gauche.

Et beaucoup plus d'histoire peut être trouvée ici:

http://jdebp.eu./FGA/bit-shifts-in-vhdl.html

Cependant, la réponse à la question initiale est toujours

sig <= tmp sll number_of_bits;
23
Martin Thompson

Vous pouvez y parvenir de deux manières. Fonctions de concaténation et de déplacement/rotation.

  • La concaténation est la manière "manuelle" de faire les choses. Vous spécifiez la partie du signal d'origine que vous souhaitez "conserver", puis concaténez les données à une extrémité ou à une autre. Par exemple: tmp <= tmp (14 de 0 à 0) & '0';

  • Fonctions de décalage (logiques, arithmétiques): Il s'agit de fonctions génériques qui vous permettent de déplacer ou de faire pivoter un vecteur de plusieurs façons. Les fonctions sont les suivantes: sll (décalage à gauche logique), srl (décalage à droite logique). Un décalage logique insère des zéros. Les décalages arithmétiques (sra/sla) insèrent le bit le plus à gauche ou le plus à droite, mais fonctionnent de la même manière que le décalage logique. Notez que pour toutes ces opérations, vous spécifiez ce que vous souhaitez décaler (tmp) et combien de fois vous souhaitez effectuer le décalage (n bits)

  • Fonctions de rotation: rol (rotation à gauche), ror (rotation à droite). La rotation fait justement cela, le MSB se retrouve dans le LSB et tout se décale vers la gauche (rol) ou inversement.

Voici une référence pratique j'ai trouvé (voir la première page).

13
Josh

Personnellement, je pense que la concaténation est la meilleure solution. La mise en œuvre générique serait

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;

Les deux implémenteront comme registres à décalage. Si vous avez besoin de plus de registres à décalage que vous êtes prêt à dépenser des ressources (par exemple en divisant 1 000 nombres par 4), vous pouvez envisager d’utiliser un BRAM pour stocker les valeurs et un registre à décalage unique contenant des "indices" qui décalage correct de tous les nombres. 

6
Paul Seeb

Je pas suggère d'utiliser sll ou srl avec std_logic_vector. 

Lors de la simulation, sll m'a donné la valeur 'U' pour ces bits, où je m'attendais à 0. 

Utilisez les fonctions shift_left(), shift_right().

Par exemple:

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))));

3

Cela se fait généralement manuellement en choisissant les bits appropriés dans le vecteur, puis en ajoutant des 0.

Par exemple, pour décaler un vecteur de 8 bits

variable tmp : std_logic_vector(15 downto 0)
...
tmp := x"00" & tmp(15 downto 8);

Espérons que cette réponse simple est utile à quelqu'un

2
iyop45
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

Tout d’abord, vous devez convertir le std_logic_vector avec la fonction to_bitvector() .__ car l’instruction sll fonctionne avec les bits logiques 1 et 0.

0
Pablito