Forum: FPGA, VHDL & Co. overflow für ADD und SUB


von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

Ich baue gerade an einer ALU herum.

Die library ieee.numeric_std.all unterstützt die Operationen + und -.

Nur wie kann ich das Overflowbit noch herausfischen?

Wer hat da eine Idee?

von Georg A. (Gast)


Lesenswert?

Welches Overflowbit willst du? Der Überlauf ist für vorzeichenbehaftete 
Zahlen anders zu erkennen, als für vorzeichenlose (der Addition selbst 
ist das ja egal).

von user (Gast)


Lesenswert?

du machst deinen additionsvektor um ein bit größer, und schaust dann das 
bit an

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

user schrieb:
> du machst deinen additionsvektor um ein bit größer, und schaust dann das
> bit an
Addition ist mir schon klar.

und bei der Subtraktion? Wo steckt da das bit?

Subtraktion in eine Addtion überführen?
Zweikomplement bilden (Minuend negieren ein bit addieren und dann beide 
Zahlen addieren)

Das ist nicht toll, weil es zwei Addition werden und damit die 
Subtraktion länger als die Addition dauert.

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

Georg A. schrieb:
> Welches Overflowbit willst du? Der Überlauf ist für vorzeichenbehaftete
> Zahlen anders zu erkennen, als für vorzeichenlose (der Addition selbst
> ist das ja egal).

Das ist eine gute Frage. Ich bin mir selber nicht im Klaren was ich für 
ein Overflow benötige.

Ich will einen Mips Softcore bauen. Da gibt es zwei Befehlen ADD und 
ADDU. Bei einem wird das Overflowbit nicht ausgewertet. Es ist jedoch 
die gleiche Additionsoperation. Die Addtionen sind bei signed und 
unsigned gleich, nur das Overflow bit unterscheidet sich. Nur wie wird 
es bei der Mips gemacht?

Ich wollte es mir nicht aus Halb- und Volladdieren haerausfiltern.

von D. I. (Gast)


Lesenswert?

René D. schrieb:
> Das ist nicht toll, weil es zwei Addition werden und damit die
> Subtraktion länger als die Addition dauert.

not, bei nem RCA zum beispiel nicht

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

>
> not, bei nem RCA zum beispiel nicht

RCA ??

von D. I. (Gast)


Lesenswert?

René D. schrieb:
>>
>> not, bei nem RCA zum beispiel nicht
>
> RCA ??

ripple carry addierer, den kann man ganz leicht zu nem subtrahierer 
umbauen:

man XORed den carry_in eingang vom ersten glied mit dem 2. operanden:

Setzt man nun carry_in vom ersten glied auf 1 hat man einen subtrahierer 
ansonsten einen addierer (2er komplement, da negiert und +1)

von Georg A. (Gast)


Lesenswert?

> Nur wie wird es bei der Mips gemacht?

Meine MIPSeleien sind schon länger her, aber wenn es da noch ein 
Carry-Flag gibt, ist es klar: Carry=unsigned, Overflow=signed.

von René D. (Firma: www.dossmatik.de) (dose)


Lesenswert?

Georg A. schrieb:
>> Nur wie wird es bei der Mips gemacht?
>
> Meine MIPSeleien sind schon länger her, aber wenn es da noch ein
> Carry-Flag gibt, ist es klar: Carry=unsigned, Overflow=signed.

Es gibt kein Flags bei der Mips. Es wird ein interrupt ausgelöst. Wobei 
ich das Wort trap nicht ganz deuten kann.


Format: ADDI rt, rs, immediate MIPS I
Purpose: To add a constant to a 32-bit integer. If overflow occurs, then 
trap.
Description: rt ¬ rs + immediate

Exceptions:
Integer Overflow

von Florian K. (kromerf)


Lesenswert?

hallo,
ich habe das selbe problem. folgende befehle sollen realisiert werden:

ALUfunc  Output
0000     C = 0
0001     C = A+B
0010     C = A-B
0011     C = B-A
0100     C = A
0101     C = B
0110     C = A+1
0111     C = B+1
1000     C = A AND B
1001     C = A OR B
1010     C = A XOR B
1011     C = B-1
1100     C = NOT A
1101     C = NOT B
1110     C = (NOT A)+1
1111     C = (NOT B)+1

wir haben alle zahlen zu unsigned konvertiert, ein bit vorrangestellt 
und es dann auch mit diesem !!!schema!!! versucht:

A, B     : in  std_logic_vector(15 downto 0);
C        : out std_logic_vector(15 downto 0);
ALUFunc  : in  std_logic_vector(3 downto 0);

variable result_temp : std_logic_vector(16 downto 0);

-- z.B. Overflow bei B-A
elsif ALUFunc = "0011" then
    result_temp := std_logic_vector(unsigned('0' & B) + unsigned('0' & 
not A) + 1);
    result <= result_temp(15 downto 0);
     cout <= result_temp(16);

     if (A(15)='1' and B(15)='0' and unsigned(result_temp(15 downto 0)) 
> 32767) or (A(15)='0' and B(15)='1' and unsigned(result_temp(15 downto 
0)) < 32768) then
      ov <= '1';
    else
      ov <= '0';
    end if;

-- z.B. Carry bei Addition B+1
elsif ALUFunc = "0111" then
    result_temp := std_logic_vector(unsigned('0' & B) + 1);
    result <= result_temp(15 downto 0);
    cout <= result_temp(16);

    if (A(15)='0' and unsigned(result_temp(15 downto 0)) > 32767) or 
(A(15)='1' and unsigned(result_temp(15 downto 0)) < 32768) then
      ov <= '1';
    else
      ov <= '0';
    end if;

leider stimmt irgendetwas noch nicht...

von Georg A. (Gast)


Lesenswert?

> leider stimmt irgendetwas noch nicht...

Und wir sollen jetzt nicht nur die Ursache sondern auch noch das 
"Irgendwas" suchen?

BTW: Der Overflowcheck ist aber auf jeden Fall falsch, die Eingangswerte 
haben da nichts zu suchen.

von Florian K. (kromerf)


Lesenswert?

nachdem ich ein bisschen auf wikipedia (zweierkomplement, unterpunkt 
vorzeichenerweiterung) und in dem wirklich guten buch "how computers do 
math" von maxfield und brown (verlag wiley) geschmöckert habe bin ich zu 
folgenden folgerungen (in "pseudocode") gekommen:

0) bei subtraktion 2er-komplement des jeweils zweiten operanden bilden, 
bei den 2er-komplement-operationen sowieso, bei den NOT-operationen das 
1er-komplement bilden
1) 16 bit vektoren von A und B als signed verwenden
2) 1 vorzeichenbit an A und B anhängen (natürlich vorne), das heißt: 
msb-bit des 16 bit vektors des jeweiligen vektors kopieren (NICHT immer 
0en anhängen!!!)
3) die beiden 17 bit vektoren ganz normal addieren
4) JETZT wirds spannend:
ACHTUNG fürs verständnis: das ergebnis wird später auf 16 bit breite 
beschnitten und hat dann trotzdem noch bzw. wieder ein "zweites" 
vorzeichenbit!!!!

4)a) falls 17. und 16. bit des ergebnisses gleich sind (beide 0 oder 1)
4)a)i) ...beide 0 dann positives ergebnis im erlaubten bereich (ov = 0, 
cout = 0)
4)a)ii) ... beide 1 dann negatives ergebnis im erlaubten bereich (ov = 
0, cout = 0)

4)b) falls 17.bit = 0 und 16.bit = 1 dann positives ergebnis außerhalb 
des erlaubten bereichs (dann ist das 16.bit das carry flag, sonst würde 
es ja eine negative zahl andeuten) (ov = 0, cout = 1)

4)c) falls 17.bit = 1 und 16.bit = 0 dann negatives ergebnis außerhalb 
des erlaubten bereichs (dann ist das 17.bit das overflow flag, sonst 
würde das positive 16.bit ja eine positive zahl andeuten) (ov = 1, cout 
= 0)

was haltet ihr davon?

in dem oben genannten buch ist die rede von flags, die bei 
hintereinander durchgeführten operationen irgendwie "propagieren". dann 
ist ja auch ein carry_in und overflow_in notwendig, oder? wie wird das 
realisiert?

von Georg A. (Gast)


Lesenswert?

Bei 4b meinst du wohl auch ov=1, wenn ov das Overflow-Flag der gesamten 
Operation sein soll. Und für den Check von 4b/c gibt es passenderweise 
eine boolsche Operation...

> wie wird das realisiert?

Overflow_in gibts nicht, Carry_in schon. Macht halt +1. Damit reduziert 
sich das SUB auf A + NOT B mit invertiertem Carry_in.

von (prx) A. K. (prx)


Lesenswert?

Florian Kromer schrieb:

> 0) bei subtraktion 2er-komplement des jeweils zweiten operanden bilden,

Kann man zwar machen, ist aber unnötig aufwendig. Das +1 der Bildung des 
Zweierkomplements lässt sich mit dem eingehenden Carry der Addition 
kombinieren.

Eine Zweierkomplement-Subtraktion ist daher technisch die Addition des 
Einer(!)komplements, allerdings mit invertiertem Carry (rein wie raus). 
Bei manchen Architekturen funktioniert das Carry auch exakt so (z.B. 
6502), bei anderen wird das eigens invertiert.

von Florian K. (kromerf)


Lesenswert?

danke fürs feedback.

von Andre (Gast)


Lesenswert?

@Florian
Wo bleibt denn bei deinem Befehlssatz das A-1?

von Florian K. (kromerf)


Lesenswert?

@ Andre:
Auf "C=A-1" habe ich verzichtet, weil ich diese Funktion nicht unbedingt 
brauche und ansonsten die ALUfunc-Breite von 4 Bit (max. 16 Befehle) auf 
5 Bit (max.32 Befehle) hätte erweitern müssen. Die Funktion "C=B-1" ist 
wichtiger, da sie für Dekrementierungen von Zeigern bei indirekter 
Adressierung benutzt wird. Am A-Eingang liegt der Akkumulator, am 
B-Eingang die Register über Multiplexer.

von Andreas U. (Gast)


Lesenswert?

Gibt es von dies ALU etwas zu sehen?

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.