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


von Thomas I. (delphinis)


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???

von Kai S. (zigzeg)


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.

von Thomas I. (delphinis)


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.

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


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"

von Lattice User (Gast)


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.

von Thomas I. (delphinis)


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....

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


Angehängte Dateien:

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:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity DivVsShift is
6
    port ( slv       : in  std_logic_vector (7 downto 0);
7
8
           uns_shift : out std_logic_vector (7 downto 0);
9
           uns_div   : out std_logic_vector (7 downto 0);
10
           sig_shift : out std_logic_vector (7 downto 0);
11
           sig_div   : out std_logic_vector (7 downto 0)
12
       );
13
end DivVsShift;
14
15
architecture Behavioral of DivVsShift is
16
begin
17
    
18
    uns_div   <= std_logic_vector( unsigned(slv) / 8);
19
    uns_shift <= std_logic_vector( shift_right( unsigned(slv), 3));
20
21
    sig_div   <= std_logic_vector(   signed(slv) / 8);
22
    sig_shift <= std_logic_vector( shift_right(   signed(slv), 3));
23
24
end Behavioral;

Und die Testbench:
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
USE ieee.numeric_std.ALL;
4
use std.textio.all;
5
6
ENTITY tb_DivVsShift_vhd IS
7
END tb_DivVsShift_vhd;
8
9
ARCHITECTURE behavior OF tb_DivVsShift_vhd IS 
10
  COMPONENT DivVsShift
11
  PORT(
12
    slv : IN std_logic_vector(7 downto 0);          
13
    uns_shift : OUT std_logic_vector(7 downto 0);
14
    uns_div : OUT std_logic_vector(7 downto 0);
15
    sig_shift : OUT std_logic_vector(7 downto 0);
16
    sig_div : OUT std_logic_vector(7 downto 0)
17
    );
18
  END COMPONENT;
19
20
  SIGNAL slv :  std_logic_vector(7 downto 0) := (others=>'0');
21
22
  SIGNAL uns_shift :  std_logic_vector(7 downto 0);
23
  SIGNAL uns_div :  std_logic_vector(7 downto 0);
24
  SIGNAL sig_shift :  std_logic_vector(7 downto 0);
25
  SIGNAL sig_div :  std_logic_vector(7 downto 0);
26
27
BEGIN
28
  uut: DivVsShift PORT MAP(
29
    slv => slv,
30
    uns_shift => uns_shift,
31
    uns_div => uns_div,
32
    sig_shift => sig_shift,
33
    sig_div => sig_div
34
  );
35
36
  tb : process
37
  variable l : line;
38
  begin
39
40
    for i in -128 to 127 loop
41
    
42
      slv <= std_logic_vector( to_signed(i, 8));
43
      wait for 6 ns; -- approx. the real time, for synthesis report
44
      
45
      write(l, "i: "         & integer'image( i) & ht);
46
      write(l, "uns_shift: " & integer'image( to_integer( unsigned(uns_shift))) & ht);
47
      write(l, "uns_div: "   & integer'image( to_integer( unsigned(uns_div)))   & ht);
48
      write(l, "sig_shift: " & integer'image( to_integer( signed(sig_shift)))   & ht);
49
      write(l, "sig_div: "   & integer'image( to_integer( signed(sig_div)))     & ht);
50
      writeline(output, l);
51
    
52
    end loop;
53
54
    wait; -- will wait forever
55
  end process;
56
END;


Und der Output:
1
                
2
i: -128  uns_shift: 16  uns_div: 16  sig_shift: -16  sig_div: -16  
3
i: -127  uns_shift: 16  uns_div: 16  sig_shift: -16  sig_div: -15  
4
i: -126  uns_shift: 16  uns_div: 16  sig_shift: -16  sig_div: -15  
5
:
6
:
7
i: -121  uns_shift: 16  uns_div: 16  sig_shift: -16  sig_div: -15  
8
i: -120  uns_shift: 17  uns_div: 17  sig_shift: -15  sig_div: -15  
9
i: -119  uns_shift: 17  uns_div: 17  sig_shift: -15  sig_div: -14  
10
:
11
:
12
i: -113  uns_shift: 17  uns_div: 17  sig_shift: -15  sig_div: -14  
13
i: -112  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -14  
14
i: -111  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -13  
15
i: -110  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -13  
16
i: -109  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -13  
17
i: -108  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -13  
18
i: -107  uns_shift: 18  uns_div: 18  sig_shift: -14  sig_div: -13  
19
:
20
:
21
i: -28  uns_shift: 28  uns_div: 28  sig_shift: -4  sig_div: -3  
22
i: -27  uns_shift: 28  uns_div: 28  sig_shift: -4  sig_div: -3  
23
i: -26  uns_shift: 28  uns_div: 28  sig_shift: -4  sig_div: -3  
24
i: -25  uns_shift: 28  uns_div: 28  sig_shift: -4  sig_div: -3  
25
i: -24  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -3  
26
i: -23  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
27
i: -22  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
28
i: -21  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
29
i: -20  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
30
i: -19  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
31
i: -18  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
32
i: -17  uns_shift: 29  uns_div: 29  sig_shift: -3  sig_div: -2  
33
i: -16  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -2  
34
i: -15  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
35
i: -14  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
36
i: -13  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
37
i: -12  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
38
i: -11  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
39
i: -10  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
40
i: -9  uns_shift: 30  uns_div: 30  sig_shift: -2  sig_div: -1  
41
i: -8  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: -1  
42
i: -7  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
43
i: -6  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
44
i: -5  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
45
i: -4  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
46
i: -3  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
47
i: -2  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
48
i: -1  uns_shift: 31  uns_div: 31  sig_shift: -1  sig_div: 0  
49
i: 0  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
50
i: 1  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
51
i: 2  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
52
i: 3  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
53
i: 4  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
54
i: 5  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
55
i: 6  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
56
i: 7  uns_shift: 0  uns_div: 0  sig_shift: 0  sig_div: 0  
57
i: 8  uns_shift: 1  uns_div: 1  sig_shift: 1  sig_div: 1  
58
i: 9  uns_shift: 1  uns_div: 1  sig_shift: 1  sig_div: 1  
59
:
60
:
61
i: 123  uns_shift: 15  uns_div: 15  sig_shift: 15  sig_div: 15  
62
i: 124  uns_shift: 15  uns_div: 15  sig_shift: 15  sig_div: 15  
63
i: 125  uns_shift: 15  uns_div: 15  sig_shift: 15  sig_div: 15  
64
i: 126  uns_shift: 15  uns_div: 15  sig_shift: 15  sig_div: 15  
65
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.

von Morin (Gast)


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 ;)

von Ütze (Gast)


Lesenswert?

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

von Klaus (Gast)


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

von Thomas I. (delphinis)


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.

von Morin (Gast)


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.

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


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... ;-)

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.