mikrocontroller.net

Forum: FPGA, VHDL & Co. Multiplikation


Autor: inGoogleITrust (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo,
ich möchte zwei operanden miteinander multiplizieren. habe die operanden 
so angelegt:

variable op_one : signed((OPERAND_WIDTH - 1) downto 0);
variable op_two : signed((OPERAND_WIDTH - 1) downto 0);
variable tmp    : signed((2 * OPERAND_WIDTH - 1) downto 0);
variable result : signed((OPERAND_WIDTH - 1) downto 0);

so ich hab jetzt geschrieben:

tmp := op_one * op_two;

kein problem. funktioniert auch soweit. so ich möchte jetzt wissen, ob 
bei der multiplikation ein overflow aufgetreten ist, also das ergebnis 
eine 32 bit zahl sprengt. deswegen habe ich mir gedacht ich vergleich 
das ergebnis einfach mit den grenzen:

if tmp < (2**(OPERAND_WIDTH - 1) - 1) and tmp > -(2**(OPERAND_WIDTH - 
1)) then

so und da sagt mir jetzt model sim:
Integer exponentiation has overflowed; result is -2147483648.

warum?

Autor: D. I. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja Modelsim meckert das an wenn was größeres als int rauskommt. Wie man 
das umgeht weiß ich leider auch nicht :(
Wenn der Zieloperand entsprechend breit gewählt ist kann er ja nicht 
überlaufen, aber du kannst ja testen ob z.b. das oberste Bit gesetzt ist

Autor: inGoogleITrust (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja was ich nicht verstehe. wenn du für OPERAND_WIDTH 32 annimmst, kommt 
doch da nicht -2147483648 raus wie ModelSim sagt, sondern das richtige. 
habe das auch ausprobiert indem ich das negative weg lasse, und nur den 
positiven teil lasse. da kam die selbe fehlermeldung. was soll das? bzw. 
heißt das ich kann diese warning unbesorgt ignorieren.

Autor: Hagen Re (hagen)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du schreibst eine Entity in der zB. zwei 16 Bit Zahlen multipliziert 
werden und deklarierst natürlich das Ausgangsregister als 32 Bit 
Variable. Damit kann deine Multilikation niemals überlaufen. Deklarierst 
du aber dein Ausgangsregister kürzer als 32 Bit dann ist das in meinen 
Augen ein Designfehler. Um zu testen ob zwei 16 Bit Register nicht mehr 
zb. in ein 20 Bit Register reinpassen kannst du schon vor der 
Multiplikation das abprüfen. Rechne Ln2(Op1) + Ln2(Op2) und wenn das 
größer 20 ist dann weist du das diese Operanden ausmultipliziert mehr 
als 20 Bits benötigen. Um Ln2(Op1) zu berechnen errechnest du den 
Index+1 des höchstwertigsten Bits im Operand.

Wenn also in den zwei 16 Bit Operanden nur 10 Bit Zahlen drinnen stehen 
dann ist deren Resulat bei einer Multiöplikation nur maximal 20 Bit 
groß.

Da in deinem Design aber schon von Anfang an die max. Größe der beiden 
Operanden feststeht kannst du also schon zur Designzeit die nötige Größe 
des Resultates ausrechnen und ausreichend groß festlegen. Alles andere 
macht ja keinen Sinn. Ergo, es kann bzw. sollte kein Überlauf entstehen.

Gruß Hagen

Autor: inGoogleITrust (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja meine operanden sind 32 bit. aber ich kann nur 32 bit ergebnisse 
gebrauchen. sollte das ergebnis da nicht rein passen, setzt ich eine 
error leitung high, und der fall ist für mich erledigt. d.h. dazu muss 
ich aber wissen ob das ergebnis auch eine 32 bit zahl ist. deswegen 
wollte ich so die überprüfung machen.
nur ich versteh eben die model sim warning nicht. wenn ich nämlich nicht 
den term hinschreiben, sondern selbst die grenzen für 32 bit integer 
ausrechne und die hinschreibe, dann mekert es nicht. also was stört das 
tool?

Autor: D. I. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
inGoogleITrust schrieb:
> ja meine operanden sind 32 bit. aber ich kann nur 32 bit ergebnisse
> gebrauchen. sollte das ergebnis da nicht rein passen, setzt ich eine
> error leitung high, und der fall ist für mich erledigt. d.h. dazu muss
> ich aber wissen ob das ergebnis auch eine 32 bit zahl ist. deswegen
> wollte ich so die überprüfung machen.
> nur ich versteh eben die model sim warning nicht. wenn ich nämlich nicht
> den term hinschreiben, sondern selbst die grenzen für 32 bit integer
> ausrechne und die hinschreibe, dann mekert es nicht. also was stört das
> tool?

Was das tool in dem Fall stört weiß ich wie gesagt nicht. Aber wenn das 
dein Ziel ist, solltest du den Weg ld(op1) + ld(op2) <= 32 gehen.
variable op1, op2 : std_logic_vector(31 downto 0);
variable oplen1, oplen2 : integer range 0 to 31 := 0;
...
for i in 0 to 31 loop
    if (op1(i) = '1') then
        oplen1 := i+1;
    end if;
    if (op2(i) = '1') then
        oplen2 := i+1;
    end if;
end loop;

if (oplen1 + oplen2 > 32) then
    error <= '1';
end if;

Der Algorithmiker in mir sagt, dass das aber auch in logarithmischer 
Zeit ginge (ich probiere das später mal aus was raus kommt):

Wiederhole bis Vektorlänge = 1:

- Teile den Vektor in 2 Hälften
- Wenn linke Hälfte != 0, setze neuerVektor = linke Hälfte, andernfalls 
neuerVektor = rechte Hälfte
- Vektor = neuerVektor

Sich dabei immer den aktuellen Indexbereich merken und am Ende + 1.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ja meine operanden sind 32 bit.
> aber ich kann nur 32 bit ergebnisse gebrauchen.
Dann mach eine Operation 32Bit x 32Bit und verwende vom 64Bit-Ergebnis 
nur die oberen 32 Bits. Denn nur dort kann auch was Wichtiges 
drinstehen.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity M32x32 is
    Port ( a : in  STD_LOGIC_VECTOR (31 downto 0);
           b : in  STD_LOGIC_VECTOR (31 downto 0);
           x : out  STD_LOGIC_VECTOR (31 downto 0));
end M32x32;

architecture Behavioral of M32x32 is
signal op1 : signed(31 downto 0);
signal op2 : signed(31 downto 0);
signal tmp : signed(63 downto 0);
begin
  op1 <= signed(a);
  op2 <= signed(b);
  tmp <= op1 * op2;
  x   <= std_logic_vector(tmp(63 downto 32)); -- nur die MSB weiterverwenden
end Behavioral;
Der Hintergrund: Betrachte deine Zahl einfach als Festkommazahl im 
Bereich zwischen -1 und +1.

Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Würde ich so nicht machen. Ich denke Resourcenschonender ist es wirklich 
die 32Bit Operanden in ein 32Bit Register zu multiplizieren wenn die 
vorherige Prüfung Ln2(Op1) + Ln2(Op2) <= 32 ergibt. Beides läuft in 
paralell ab und du führst ein Overflow Signal mit raus und akzeptierst 
das Resultat nur dann als gültig wenn Overflow FALSE ist. Vorteil wäre 
es dann das die Multiplikation und die Overfow Prüfung unabhängig 
voneinander laufen, was wieder den max. machbaren Taktraten zugute 
kommt.


Gruß Hagen

Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dh. mathematisch ausgedrückt -> R = (A * B) mod 2^32 mit R,A,B jeweils 
32 Bit unsigned. Overflow = Ln2(A) + Ln2(B) > 32 mit Overflow = Boolean.

Bezieht sich aber erstmal alles nur auf vorzeichenlose Ganzzahlen !

Gruß Hagen

Autor: Hagen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Lothar:

er ist nicht an einer echten 32x32 Mul interessiert, also nicht R = A*B 
div 2^32 sondern an R = A*B mod 2^32. Schätze sein Design verarbeitet 
32Bit Operanden und Resultate per Default und i.A. stehen da drinnen 
keine vollen 32Bit Zahlen und wenn möchte er nur erkennen ob ein 
Überlauf auftrat.

Er könnte auch eine echte 32x32=64'er MUL implementieren, nur die 
untersten 32Bit landen im Resultat und Overflow ist gleich oberste 32Bit 
<> 0.

Gruß Hagen

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> die 32Bit Operanden in ein 32Bit Register zu multiplizieren
So einen Multiplizierer gibt es nicht...
Ich zumindest habe noch keinen in Hardware gesehen.

Autor: inGoogleITrust (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also ich habe es jetzt so gelöst. multipliziere die beiden zahlen in ein 
64 bit register. danach schau ich mir die obersten 32 bit an, wenn die 
ungleich null sind, muss ein überlauf passiert sein, und ich setzte 
meiner error leitung high. fertig. glaub das ist das einfachste.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.