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?
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
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.
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
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?
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.
> 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.
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
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
@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
> die 32Bit Operanden in ein 32Bit Register zu multiplizieren
So einen Multiplizierer gibt es nicht...
Ich zumindest habe noch keinen in Hardware gesehen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.