2017-04-23 8 views
0

J'utilise VHDL pour décrire un multiplicateur 32 bits, pour un système à implémenter sur un FPGA Xilinx, j'ai trouvé sur le web que la règle de base est que si vous avoir des entrées de taille N bits, la sortie doit avoir (2 * N) bits de taille. Je l'utilise pour un système de feedback, est-il possible de disposer d'un multiplicateur avec une sortie de la même taille que ses entrées?multiplicateur VHDL dont la sortie a le même côté de ses entrées

Je jure une fois que j'ai trouvé une application fpga, quel code vhdl a des additionneurs et des blocs multiplicateurs câblés avec des signaux de même taille. La personne qui a écrit le code m'a dit qu'il suffit de mettre le résultat du produit sur un signal 64 bits et que la sortie doit obtenir les 32 bits les plus significatifs du résultat (ce qui n'était pas forcément sur les 32 bits les plus significatifs) du signal 64 bits).

Au moment où je construis un système (fonctionne apparemment) en utilisant le code suivant:

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all; 

entity Multiplier32Bits is 
    port(
     CLK: in std_logic; 
     A,B: in std_logic_vector(31 downto 0); 
     R: out std_logic_vector(31 downto 0) 
    ); 
end Multiplier32Bits; 

architecture Behavioral of Multiplier32Bits is 
signal next_state: std_logic_vector(63 downto 0); 
signal state: std_logic_vector(31 downto 0); 

begin 

    Sequential: process(CLK,state,next_state) 
    begin 
     if CLK'event and CLK = '1' then 
      state <= next_state(61 downto 30); 
     else 
      state <= state; 
     end if; 
    end process Sequential; 

    --Combinational part 
     next_state <= std_logic_vector(signed(A)*signed(B)); 

    --Output assigment 
    R <= state; 

end Behavioral; 

Je pensais qu'il travaillait depuis au moment où j'avais le bloc simulé avec simulateur Active-HDL FPGA, mais savoir que je simule tout le système 32 bits en utilisant iSim de Xilinx ISE Design Suite. J'ai trouvé que ma sortie a une grande différence avec le produit réel des entrées A et B, que je ne sais pas si c'est juste la précision lâche de sauter 32 bits ou mon code est tout simplement mauvais.

+0

ok, où est la question? – Staszek

+0

Et fournissez les numéros que vous avez utilisés pour la simulation. – Staszek

+0

Vous souhaitez probablement utiliser le post-décalage pour aligner le résultat. Et vous utilisez une entrée à virgule fixe signée. – JHBonarius

Répondre

0

Votre code a quelques problèmes:

  1. next_state et state n'appartiennent pas dans la liste de sensibilité
  2. L'écriture CLK'event and CLK = '1' devrait être remplacé par rising_edge(CLK)
  3. state <= state; n'a aucun effet et provoque des outils tels que ISE pour mal interpréter le motif. Retirez-le.
  4. Le fait de placer des espaces autour des opérateurs ne fait pas de mal, mais améliore la lisibilité.
  5. Pourquoi attendez-vous le résultat d'un * b dans les bits 30 à 61 au lieu de 0 à 31?
  6. state et next_state ne représentent pas les états d'une machine d'état. C'est juste un registre.

Code amélioré:

architecture Behavioral of Multiplier32Bits is 
    signal next_state: std_logic_vector(63 downto 0); 
    signal state: std_logic_vector(31 downto 0); 
begin 
    Sequential: process(CLK) 
    begin 
    if rising_edge(CLK) then 
     state <= next_state(31 downto 0); 
    end if; 
    end process Sequential; 

    --Combinational part 
    next_state <= std_logic_vector(signed(A) * signed(B)); 

    --Output assigment 
    R <= state; 
end architecture Behavioral; 
+0

'state' n'appartient pas non plus à la liste de sensibilité. Et 'rising_edge (CALL)' -> 'rising_edge (CLK)' ... Bien que ce ne soit pas vraiment nécessaire. Il va synthétiser la façon dont il est maintenant. – JHBonarius

+0

N'est-il pas préférable d'avoir rising_edge (CLK), car il vérifie si c'est vraiment un front montant, et par exemple ne pas passer de haute impédance à '1'? – Staszek

0

Je suis totalement d'accord avec tout ce qui Paebbels écrire. Mais je vais vous expliquer cela sur le nombre de bits dans le résultat. donc je vais l'expliquer par des exemples dans la base 10.

9 * 9 = 81 (two 1 digit numbers gives maximum of 2 digits) 
99 * 99 = 9801 (two 2 digit numbers gives maximum of 4 digits) 
999 * 999 = 998001 (two 3 digit numbers gives maximum of 6 digits) 
9999 * 9999 = 99980001 (4 digits -> 8 digits) 

Et ainsi de suite ... Il est tout à fait la même chose pour binaire. C'est pourquoi la sortie est (2 * N) bits de taille d'entrée.

Mais si vos chiffres sont plus petits, résultat alors s'inscrira dans un même nombre de chiffres, en tant que facteurs:

3 * 3 = 9 
10 * 9 = 90 
100 * 99 = 990 

Et ainsi de suite. Donc, si vos chiffres sont assez petits, le résultat sera de 32 bits. Bien sûr, comme Paebbels déjà écrit, le résultat sera dans la partie la moins significative du signal. Et comme J.H.Bonarius l'a déjà souligné, si votre entrée n'est pas composée d'entiers, mais de nombres à virgule fixe, alors vous devrez faire un post-shift.Si c'est votre cas, écrivez-le dans le commentaire, et je vais vous expliquer ce qu'il faut faire.

+0

Merci Staszek !!, Oui c'est mon cas, j'utilise à la fois les nombres à virgule fixe et signé, donc le MSBit est utilisé comme bit de signe, 2 bits pour la partie entière (la plage de sortie est comprise entre -1 et 1), et le reste des 32 bits pour la partie fraction. Comme je n'étais pas sûr du post shift, j'ai sélectionné les MSBytes pour la réponse, même si la perte des LSBytes de la partie fraction n'affectera pas la dynamique du système dans lequel le multiplicateur est utilisé. Mais le point de J.H. Bonarius semble aider dans la précision et améliorera donc la dynamique du système. Merci! :) – Tebi

+0

En fait, la plage de sortie est comprise entre -4 et 3. (9);) – Staszek