Décalage de droite arithmétique en VHDL
Question
Je suis la conception opérateur arithmétique de décalage universel. Y at-il une meilleure façon d'y parvenir en plus d'utiliser le multiplexeur 32 bits (décodeur) d'une manière présentée ci-dessous?
ENTITY isra IS
PORT (
clk: in std_logic;
rst: in std_logic;
di: in std_logic_vector (31 downto 0);
sel: in std_logic_vector (31 downto 0);
res: out std_logic_vector (31 downto 0) := (others => '0')
);
END isra;
PROCESS
BEGIN
WAIT UNTIL clk'EVENT AND clk = '1';
IF rst = '1' THEN
res <= (others => '0');
ELSE
CASE sel IS
when X"00000001" => res <= to_stdlogicvector(to_bitvector(a) sra 1);
when X"00000002" => res <= to_stdlogicvector(to_bitvector(a) sra 2);
...
when X"0000001F" => res <= to_stdlogicvector(to_bitvector(a) sra 31);
when others => res <= (others => '0');
END CASE;
END IF;
END PROCESS;
La solution
Utilisez l'indexation?
PROCESS
VARIABLE shift_count : INTEGER RANGE 0 TO 31;
BEGIN
IF rst = '1' THEN
res <= (others => '0');
ELSIF RISING_EDGE(clk) THEN
shift_count := to_integer(sel);
FOR I IN 0 TO 31 LOOP
IF I + shift_count < 32 THEN
res(I) <= din(I + shift_count);
ELSE
res(I) <= din(31); -- for logical shift right, use '0' instead
END IF;
END LOOP;
END IF;
END PROCESS;
Cette version est beaucoup plus facile à paramétrer dans un générique.
Rappelez-vous que VHDL est une description du comportement, il ne précise pas MUX. Le compilateur peut générer des modèles différents selon que vous optimisez la taille, la vitesse, laissez pipelining, etc.
Notez que 5 2: 1 muxes peuvent mettre en œuvre ce dans une zone beaucoup plus petite qu'un seul 32: 1 MUX. Si ce n'est pas le bloc qui limite votre fréquence d'horloge, qui pourrait être préférable.
Notez également que votre entrée est sel
beaucoup trop, il n'a besoin que d'être 5 bits.
Autres conseils
Vous pouvez utiliser la fonction sans boucles SRA ou déclarations de cas:
res <= to_stdlogicvector(to_bitvector(di) sra to_integer(sel));
Notez que vous devez faire un sel non signé, pas std_logic_vector:
sel: in unsigned (31 downto 0);
Si vous ne voulez pas, vous pouvez toujours jeter dans un sel non signé. Vous nous avez aussi besoin numeric_bit:
use ieee.numeric_bit.all;
Eh bien d'un point de vue matériel, de décalage vers la droite dans une seule horloge un nombre variable de positions, chaque bit est une bascule unique avec l'un des 32 valeurs possibles en fonction de la sélection. De ce point de vue, voici comment vous le faites.
Je ferais == 0 sel un cas et en faire un passthrough, cependant. Logiquement, cela a plus de sens que de mettre tout à zéro.