2010-11-13 49 views
0

Je conçois l'opérateur arithmétique de décalage universel. Existe-t-il un meilleur moyen d'y parvenir en plus d'utiliser le multiplexeur 32 bits (décodeur) d'une manière présentée ci-dessous?arithmétique de décalage universel à droite en VHDL

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; 
+1

démultiplexeur? Il n'y a pas de démultiplexage ici. –

+0

vous avez raison, j'ai changé la description. Merci pour cela. – name

Répondre

1

Utiliser 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 en générique. Rappelez-vous que VHDl est une description comportementale, elle ne spécifie pas de multiplexage. Le compilateur peut générer différentes conceptions selon que vous optimisez la taille, la vitesse, le pipelining, etc.

Notez que 5 Muxes 2: 1 peuvent l'implémenter dans une zone beaucoup plus petite qu'un seul mux 32: 1. Si ce n'est pas le bloc qui limite votre fréquence d'horloge, cela pourrait être préférable.

Notez également que votre entrée sel est trop large, elle ne doit être que 5 bits.

+0

Merci pour la réponse. Je suis d'accord que c'est une approche plus générique qui le rend meilleur. Le problème est que sel dans mon cas doit être large de 32 bits et je crois que "shift_count: = to_integer (sel)" ne fonctionnera pas dans ce cas. Comme vous l'avez dit, la partie délicate de cette conception consiste à utiliser des décodeurs intelligents - il n'est pas judicieux de faire 32: 1. Pensez-vous que coller avec votre design et utiliser sel (5 downto 0) est une bonne idée? Une autre chose est si c'est bon pour une raison de performance d'avoir un asynchrone en premier? THX. – name

+1

Ceci est pour un FPGA, non? Les éléments logiques d'un FPGA ont des entrées de réinitialisation asynchrones dédiées à chaque bascule D, donc cela ne coûtera rien en termes de performance ou d'utilisation de LE (il peut rapporter plus de * portes * utilisées, mais ces portes ne peuvent pas être utilisées toute autre fonction). Avoir un bus 'sel' plus large ne devrait rien faire, car le test' I + shift_count <32' gérera automatiquement toute valeur de 'shift_count' correctement. –

+0

"IF I + shift_count <32 THEN" c'est intelligent! – name

1

bien d'un point de vue matériel, de décalage à 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. Donc, de ce point de vue, c'est comme ça que vous le faites.

Je ferais sel == 0 un cas et en ferais un passthrough, cependant. Logiquement, cela a plus de sens que de tout mettre en zéros.

+0

Salut, merci de le signaler. Les autres dans l'instruction case fournissent que le signal res est écrit dans chaque branche. Cela aide à l'outil de synthèse pour éviter de créer les verrous. – name

4

Vous pouvez utiliser la fonction SRA sans boucles ou des déclarations de cas:

res <= to_stdlogicvector(to_bitvector(di) sra to_integer(sel)); 

Notez que vous devez faire sel non signé, pas std_logic_vector:

sel: in unsigned (31 downto 0); 

Si vous n » Je veux ça, vous pouvez toujours lancer sel dans un non signé. Vous avez également besoin de nous numeric_bit:

use ieee.numeric_bit.all;