mikrocontroller.net

Forum: FPGA, VHDL & Co. Sinn der Operatoren sra und sla?


Autor: Thomas I. (delphinis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
was ist eigentlich der Sinn von sra und sla? Klar, was es macht steht im 
Buch, aber der Sinn? Und was heisst hier "Arithmetisch"?

bei sll und srl verstehe ich den Sinn (pro shift wird mal 2 resp. durch 
2 geteilt)
Bloss: wieso sagt man dem "logisches" shift? das ist doch 
arithmetisch???

Autor: Kai S. (zigzeg)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Unterschied ergibt sich fuer den Rechtsshift von negativen Zahlen. 
-8 arithmetisch geschiftet gibt -4, logisch geshifted geht das 
Vorzeichen verloren und man bekommt eine positive Zahl, je nach Breite 
des Registers.
Z.b. fuer 8 bit: -8 = 0xf8, geshifted 0x7C = 124.

Autor: Thomas I. (delphinis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Kay,
das hab ich erst auch gedacht, aber ich hab das mal mit -77 ausprobiert:
10110011 sra 2 = 11101100 und das ist 20 und nicht 19!?
Es müsste doch abgerundet werden und nicht aufgerundet?

Und wofür ist denn sla??? das gibt bei signed ja überhaupt keinen Sinn.

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

Bewertung
0 lesenswert
nicht lesenswert
Thomas Iseli schrieb:
> das hab ich erst auch gedacht, aber ich hab das mal mit -77 ausprobiert:
> 10110011 sra 2 = 11101100 und das ist 20 und nicht 19!?
> Es müsste doch abgerundet werden und nicht aufgerundet?
Das Problem taucht immer wieder auf. Auch die Herren Softies haben damit 
zu kämpfen, dass ein arithmetischer Shift einer negativen Zahl eben 
keine richtige Division durch 2 ist.
Beitrag "Re: Dividieren durch Schiften"
Beitrag "Optimiert der Compiler Division durch 2^n wirklich?"

> Und wofür ist denn sla??? das gibt bei signed ja überhaupt keinen Sinn.
Das ist genau das selbe wie sll, egal ob unsigned oder signed. Der 
Befehl ist einfach aus Orthogonalitätsgründen vorhanden. Z.B. auch bei 
uCs:
Beitrag "Was ist der unterschied zwischen ASL und LSL"

Autor: Lattice User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei CPUs gibt es zwischen ASL und LSL durchaus Unterschiede.

z.b. 68000  Nach LSL ist das Overflowbit im Statusregister immer 0, nach 
ASL wird es gesetzt wenn sich das MSB, d.h. das Vorzeichen ändert.

Autor: Thomas I. (delphinis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na ja,
wenn ich diese zum Teil lange diskutierten Beiträge lese, ist für mich 
klar, dass ich diesen Befehl wohl nur zum optimieren benutzen werde, 
ansonsten ist sra nur unnütz und vor allem verwirrend, wenn er eh nicht 
immer zum richtigen Resultat führt! Solchen Code zu unterhalten, vor 
allem wenn es später u.U. jemand anderes tun müsste, ist immer sehr 
Fehlerbehaftet. Für mich ist das alles andere als "Arithmetisch". Und 
dass man einen sinnlosen Befehl wie asl nur Vollständikeitshalber 
kreiert, ist für mich sowiso unverständlich. Hauptsache man ist 
verwirrt?
Deshalb werde ich mich wohl an die Operatoren / und * halten, auch wenn 
sie vielleicht ein bisschen mehr ressourcen benötigen....

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Thomas I. schrieb:
> Deshalb werde ich mich wohl an die Operatoren / und * halten, auch wenn
> sie vielleicht ein bisschen mehr ressourcen benötigen....
Ja, da ist der Fall. Der / braucht einiges, der shift ist ja "nur" eine 
Umverdrahtung mit Vorzeichenerweiterung...

Hier mal eine VHDL-Beschreibung zum Test:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity DivVsShift is
    port ( slv       : in  std_logic_vector (7 downto 0);

           uns_shift : out std_logic_vector (7 downto 0);
           uns_div   : out std_logic_vector (7 downto 0);
           sig_shift : out std_logic_vector (7 downto 0);
           sig_div   : out std_logic_vector (7 downto 0)
       );
end DivVsShift;

architecture Behavioral of DivVsShift is
begin
    
    uns_div   <= std_logic_vector( unsigned(slv) / 8);
    uns_shift <= std_logic_vector( shift_right( unsigned(slv), 3));

    sig_div   <= std_logic_vector(   signed(slv) / 8);
    sig_shift <= std_logic_vector( shift_right(   signed(slv), 3));

end Behavioral;

Und die Testbench:
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
use std.textio.all;

ENTITY tb_DivVsShift_vhd IS
END tb_DivVsShift_vhd;

ARCHITECTURE behavior OF tb_DivVsShift_vhd IS 
  COMPONENT DivVsShift
  PORT(
    slv : IN std_logic_vector(7 downto 0);          
    uns_shift : OUT std_logic_vector(7 downto 0);
    uns_div : OUT std_logic_vector(7 downto 0);
    sig_shift : OUT std_logic_vector(7 downto 0);
    sig_div : OUT std_logic_vector(7 downto 0)
    );
  END COMPONENT;

  SIGNAL slv :  std_logic_vector(7 downto 0) := (others=>'0');

  SIGNAL uns_shift :  std_logic_vector(7 downto 0);
  SIGNAL uns_div :  std_logic_vector(7 downto 0);
  SIGNAL sig_shift :  std_logic_vector(7 downto 0);
  SIGNAL sig_div :  std_logic_vector(7 downto 0);

BEGIN
  uut: DivVsShift PORT MAP(
    slv => slv,
    uns_shift => uns_shift,
    uns_div => uns_div,
    sig_shift => sig_shift,
    sig_div => sig_div
  );

  tb : process
  variable l : line;
  begin

    for i in -128 to 127 loop
    
      slv <= std_logic_vector( to_signed(i, 8));
      wait for 6 ns; -- approx. the real time, for synthesis report
      
      write(l, "i: "         & integer'image( i) & ht);
      write(l, "uns_shift: " & integer'image( to_integer( unsigned(uns_shift))) & ht);
      write(l, "uns_div: "   & integer'image( to_integer( unsigned(uns_div)))   & ht);
      write(l, "sig_shift: " & integer'image( to_integer( signed(sig_shift)))   & ht);
      write(l, "sig_div: "   & integer'image( to_integer( signed(sig_div)))     & ht);
      writeline(output, l);
    
    end loop;

    wait; -- will wait forever
  end process;
END;


Und der Output:
                
i: -128  uns_shift: 16  uns_div: 16  sig_shift: -16  sig_div: -16  
i: -127  uns_shift: 16  uns_div: 16  sig_shift: -16  sig_div: -15  
i: -126  uns_shift: 16  uns_div: 16  sig_shift: -16  sig_div: -15  
:
:
i: -121  uns_shift: 16  uns_div: 16  sig_shift: -16  sig_div: -15  
i: -120  uns_shift: 17  uns_div: 17  sig_shift: -15  sig_div: -15  
i: -119  uns_shift: 17  uns_div: 17  sig_shift: -15  sig_div: -14  
:
:
i: -113  uns_shift: 17  uns_div: 17  sig_shift: -15  sig_div: -14  
i: -112  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -14  
i: -111  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -13  
i: -110  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -13  
i: -109  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -13  
i: -108  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -13  
i: -107  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -13  
:
:
i: -28  uns_shift: 28  uns_div: 28  sig_shift: -4  sig_div: -3  
i: -27  uns_shift: 28  uns_div: 28  sig_shift: -4  sig_div: -3  
i: -26  uns_shift: 28  uns_div: 28  sig_shift: -4  sig_div: -3  
i: -25  uns_shift: 28  uns_div: 28  sig_shift: -4  sig_div: -3  
i: -24  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -3  
i: -23  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
i: -22  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
i: -21  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
i: -20  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
i: -19  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
i: -18  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
i: -17  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
i: -16  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -2  
i: -15  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
i: -14  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
i: -13  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
i: -12  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
i: -11  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
i: -10  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
i: -9  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
i: -8  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: -1  
i: -7  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
i: -6  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
i: -5  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
i: -4  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
i: -3  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
i: -2  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
i: -1  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
i: 0  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
i: 1  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
i: 2  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
i: 3  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
i: 4  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
i: 5  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
i: 6  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
i: 7  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
i: 8  uns_shift: 1  uns_div: 1  sig_shift: 1  sig_div: 1  
i: 9  uns_shift: 1  uns_div: 1  sig_shift: 1  sig_div: 1  
:
:
i: 123  uns_shift: 15  uns_div: 15  sig_shift: 15  sig_div: 15  
i: 124  uns_shift: 15  uns_div: 15  sig_shift: 15  sig_div: 15  
i: 125  uns_shift: 15  uns_div: 15  sig_shift: 15  sig_div: 15  
i: 126  uns_shift: 15  uns_div: 15  sig_shift: 15  sig_div: 15  
i: 127  uns_shift: 15  uns_div: 15  sig_shift: 15  sig_div: 15  

Wer lieber Bilder anguckt: siehe Anhang...

Und in der Implementierung sehen uns_shift und uns_div genau gleich aus. 
sig_shift sieht ähnlich aus wie diese beiden, nur wird das Bit 4 
(=Vorzeichen) auf die führenden 3 Bits ausgedehnt.
Aber sig_div sieht komplett anders aus: da ist einiges mehr an 
Kombinatorik nötig (2 Addierer...).

Demnach sieht hier der Ressourcenverbrauch so aus:
der sig_div braucht 4 Slices, der sig_shift 0.

Autor: Morin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> ansonsten ist sra nur unnütz und vor allem verwirrend, wenn er eh nicht
> immer zum richtigen Resultat führt!

Klar, deshalb wird SRA auch in moderne CPUs immer noch eingebaut... ;)

DIV liefert übrigens auch das falsche Ergebnis. Das korrekte Ergebnis 
wäre ja auch keine Ganzzahl. Dazu mal das Beispiel (-79 / 4) = -19,75

10110001 sra 2 = 11101100 = -20
10110001 div 2 = 11101101 = -19

Wie man leicht sieht liegt "sra 2" näher am korrekten Ergebnis als "div 
2", der Rundungsfehler ist also kleiner. Zählt man die Fälle, wie oft 
welches Verfahren "näher" rundet, geht das im Großen und Ganzen 
unentschieden aus.

Wenn einem das "Runden nach minus Unendlich" egal ist oder sogar gelegen 
kommt, nimmt man halt SRA. Braucht man "Runden zur 0", nimmt man DIV.

-----

Was mich allerdings wirklich interessieren würde: Wenn SRL "logisch" und 
SRA "arithmetisch" ist, warum brauche ich dann zum Teilen einer 
vorzeichenlosen Ganzzahl SRL? Hat doch viel mit Zahlen und wenig mit 
binärer Logik zu tun.

Die Frage bezieht sich auf die Benennung der Befehle, nicht auf die 
Funktionsweise ;)

Autor: Ütze (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
logische Schiebeoperationen schieben immer den Initialisierungswert des 
Basistyps nach, arithmetische füllen Vorzeichen richtig auf

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas I. schrieb:
> dass man einen sinnlosen Befehl wie asl nur Vollständikeitshalber
> kreiert, ist für mich sowiso unverständlich. Hauptsache man ist
> verwirrt?

Ist dir schon mal der Gedanke gekommen, daß man Shift-Befehle zum 
Shiften eines Registers benutzen könnte?

MfG Klaus

Autor: Thomas I. (delphinis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Klaus:
> Ist dir schon mal der Gedanke gekommen, daß man Shift-Befehle zum
> Shiften eines Registers benutzen könnte?

Ja klar,
nur erstens wirst du da wohl eher sll und srl nehmen und zweitens was 
hat asl dann mit "arithmetik" zu tun?(sra = aritmetical shift left)
Das war denn auch meine Frage.

@ Morin:
div liefert meiner Meinung nach das richtige Ergebnis (rundet immer nach 
0 ab). Aber das ist wohl Ansichtssache, was Abrunden heisst: nach 0 oder 
nach minus?


Na ja, auf jeden fall bin ich geholfen ;-)
Vielen Dank für eure Beiträge.

Autor: Morin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> div liefert meiner Meinung nach das richtige Ergebnis (rundet immer nach
> 0 ab). Aber das ist wohl Ansichtssache, was Abrunden heisst: nach 0 oder
> nach minus?

Zum einen das, aber vor allem ist die Frage warum abrunden das 
"richtige" Ergebnis liefert und nicht z.B. "echt runden", was ja im 
Schnitt einen kleineren Rundunsfehler verursacht. DIV ist nunmal 
definiert als Division mit Abrunden, aber das ist halt nur so weil es so 
definiert wurde. Es gibt erst mal keinen Grund, warum SRA das genauso 
machen soll.

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

Bewertung
0 lesenswert
nicht lesenswert
Morin schrieb:
> aber das ist halt nur so weil es so definiert wurde.
> Es gibt erst mal keinen Grund, warum SRA das genauso machen soll.
Das schon, aber urigerweise ist jeder überrascht, wenn er hinter dieses 
"Geheimnis" kommt. Weil es ja im positiven Bereich so gut funktioniert 
hat... ;-)

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.