Forum: FPGA, VHDL & Co. Multiplikation


von inGoogleITrust (Gast)


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?

von D. I. (Gast)


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

von inGoogleITrust (Gast)


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.

von Hagen R. (hagen)


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

von inGoogleITrust (Gast)


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?

von D. I. (Gast)


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.
1
variable op1, op2 : std_logic_vector(31 downto 0);
2
variable oplen1, oplen2 : integer range 0 to 31 := 0;
3
...
4
for i in 0 to 31 loop
5
    if (op1(i) = '1') then
6
        oplen1 := i+1;
7
    end if;
8
    if (op2(i) = '1') then
9
        oplen2 := i+1;
10
    end if;
11
end loop;
12
13
if (oplen1 + oplen2 > 32) then
14
    error <= '1';
15
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.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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.
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity M32x32 is
6
    Port ( a : in  STD_LOGIC_VECTOR (31 downto 0);
7
           b : in  STD_LOGIC_VECTOR (31 downto 0);
8
           x : out  STD_LOGIC_VECTOR (31 downto 0));
9
end M32x32;
10
11
architecture Behavioral of M32x32 is
12
signal op1 : signed(31 downto 0);
13
signal op2 : signed(31 downto 0);
14
signal tmp : signed(63 downto 0);
15
begin
16
  op1 <= signed(a);
17
  op2 <= signed(b);
18
  tmp <= op1 * op2;
19
  x   <= std_logic_vector(tmp(63 downto 32)); -- nur die MSB weiterverwenden
20
end Behavioral;
Der Hintergrund: Betrachte deine Zahl einfach als Festkommazahl im 
Bereich zwischen -1 und +1.

von Hagen (Gast)


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

von Hagen (Gast)


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

von Hagen (Gast)


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

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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

von inGoogleITrust (Gast)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.