Forum: FPGA, VHDL & Co. 4 Bit Vergleicher


von Matze1992 (Gast)


Lesenswert?

Halle Leute,

ich habe ein kurze Frage. Ich bin noch recht neu in der VHDL Welt und 
soll einen 4 Bit Vergleicher entwerfen. Aus Internetauszügen bin ich auf 
folgenden Quelltext gestoßen.

sum := 0;
for i in 3 downto 0 loop
if A(i) = '0' then
sum := sum * 2;
else
sum := sum * 2 + 1;
end if;
end loop;

Das ganze funktioniert auch in der Simulation. Aber ich glaube es bringt 
mir nichts, den Quelltext einfach so in mein Programm zu übernehmen, 
wenn ich den Vorgang nicht verstehe.

Kann mir daher irgendjemand erklären, was genau in welche Zeile 
eigentlich passieren soll?

A ist mein Eingang mit 4 Bits. Ich verstehe das Programm so: Ich 
schreibe zuerst in meine Variable sum die Zahl null. Da die Variable 16 
bit groß ist, habe ich 16 mal die null. Dann öffne ich eine Schleife mit 
der Variblen i. Danach frage ich ab: Ist der Eingang A null? Ist dieser 
null (also alle 4 Eingang-Bits auf low) so nimmt er die null aus der 
Summe und multipliziert diese mit 2. Also bleibt in der Variablen sum 
eine null stehen. Aber dieser Zustand ändert sich ja eigentlich nicht. 
Also warum multipliziere ich mit 2??? Sobald sich die Eingangsbits 
ändern, gehe ich ja automatisch in den else-Zweig, da mein A ja nicht 
mehr null ist. Ich hoffe jemand sieht mein Problem und kann mir helfen.

Viele Grüße
Matze1992

von Fabio W. (modellbauer)


Lesenswert?

Hmm, ich bin auch VHDL-Neuling, aber ich versuche mal zu antworten:

Also ich habe schon ein Problem, weil ich garkeine Vergleicher sehe. Wo 
soll denn hier verglichen werden?

Das Programm macht doch nicht anderes als die Bits von oben nach unten 
durch zu gehen, und wenn es eine Null ist das Ergebnis um eins nach 
links shiften, und sonst das Ergebnis um eins nach links shiften und 
inkrementieren. Das bedeutet letztendlich nichts anderes, als dass in 
sum ein Kopie von A steht.

Vielleicht erklärst du noch einmal genau, was denn in der Simulation 
schon funktioniert, dann kann man vielleicht weiter helfen.

von Shee2e (Gast)


Lesenswert?

Hi,
das ding Vergleicht doch nichts, bin auch nur neuling in VHDL aber
es geht auf jeden fall etwas anderes.
Meine Lösung wäre ein XOR mit vergleich mit Null
MfG
Shee2e

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


Lesenswert?

Matze1992 schrieb:
> Ich verstehe das Programm so:
Das ist dein Problem. Das was du da hast, ist kein Programm, sondern 
eine Hardwarebeschreibung. Du musst diese prozedurale "C-Denkweise" 
vergessen, in dieser Beschreibung passiert nichts "zuerst" und "dann", 
sondern es wird alles gleichzeitig geschehen.

> Sobald sich die Eingangsbits ändern, gehe ich ja automatisch in den
> else-Zweig, da mein A ja nicht mehr null ist.
Weil dieser "Code" paralell da steht, ist die Hardware mit allen 
Vergleichern immer da, und du gehst immer und jederzeit bei jeder 
Änderung von A diese "Schleife" komplett durch.

> was genau in welche Zeile eigentlich passieren soll?
Da wäre es super, wenn du die VHDL Tags [ vhdl ] und [ /vhdl ] ohne die 
Leerzeichen um deinen Sourcecode setzen würdest, dann bekommst du 
nämlich Syntax-Highlighting geschenkt...

1
-- hier fehlt der ganze Prozedur-Kopf...
2
3
sum := 0;                 -- Eine Variable namens sum vermutlich vom Typ integer wird auf 0 gesetzt                 
4
for i in 3 downto 0 loop  -- eine Schleife wird mit einem Indesx i von 0..3 durchlaufen
5
   if A(i) = '0' then     -- Ein Bit eines Verktors mit unbestimmtem Typ wird auf '0' verglichen
6
      sum := sum * 2;     -- falls dieses Bit nicht gesetzt war, wird die Summe verdoppelt
7
   else 
8
      sum := sum * 2 + 1; -- falls es gesetzt war, wird auf die vorige Summe Verdoppelt und eins draufaddiert
9
   end if;               
10
end loop;                 -- das wars

Man könnte das auch so schreiben:
1
sum := 0;                                  
2
for i in 3 downto 0 loop  
3
   sum := sum * 2;
4
   if A(i) = '1' then     
5
      sum := sum + 1;     
6
   end if;               
7
end loop;

Und was macht das Ganze?
Damit wird ein Vektor in eine Integer-Zahl umgerechnet. Man könnte 
diesen Ausschnitt z.B. so oder so ähnlich bei der Funktion to_integer() 
aus der numeric_std finden...
EDIT: such einfach mal dort im letzten Drittel nach to_integer:
http://www.ece.msstate.edu/~reese/EE8993/ieee_standards/numeric_std.vhd
Und tatsächlich ist das da so ähnlich, nur wird nicht die Summe 
geschoben, sondern das, was auf die Summe aufaddiert wird:
1
variable w : INTEGER:= 1;  -- weight factor  --> Gewichtung des aktuellen Bits
2
3
  for i in XARG'reverse_range loop        -- von rechts her jedes Element des Vektors durchlaufen
4
    if XARG (i) = '1' then                -- wenn gesetzt, dann die aktuelle Gewichtung dazuaddieren
5
      RESULT:= RESULT + w;
6
      end if;
7
    if (i /= XARG'left) then w := w + w;  -- und solange nicht das linkeste Element erreicht ist, die Gewichtung verdoppeln
8
      end if;
9
    end loop;


Fabio W. schrieb:
> Das bedeutet letztendlich nichts anderes, als dass in sum ein Kopie von
> A steht.
Nein, denn sum ist ein Integer und A ist ein Vektor. Und das sind zwie 
grundlegend verschiedene Datentypen, auch wenn das jeweilige Bitmuster 
exakt gleich aussehen wird...

Ach übrigens: in diesen Code sind 2 Dinge, die einen Anfänger problemlos 
ins Verderben bringen können: eine Variable und eine Schleife. Such 
einfach mal mit "Variable vs. Signal", da ist das mit der Variable 
ausgeführt...

: Bearbeitet durch Moderator
von Matze1992 (Gast)


Lesenswert?

-- hier fehlt der ganze Prozedur-Kopf...

sum := 0;                 -- Eine Variable namens sum vermutlich vom Typ 
integer wird auf 0 gesetzt

for i in 3 downto 0 loop  -- eine Schleife wird mit einem Indesx i von 
0..3 durchlaufen

   if A(i) = '0' then     -- Ein Bit eines Verktors mit unbestimmtem Typ 
wird auf '0' verglichen

      sum := sum * 2;     -- falls dieses Bit nicht gesetzt war, wird 
die Summe verdoppelt

   else
      sum := sum * 2 + 1; -- falls es gesetzt war, wird auf die vorige 
Summe Verdoppelt und eins draufaddiert

   end if;
end loop;                 -- das wars



Also es ist so, dass das gesamte Programm ein 4 Bit Vergleicher ist. 
Jedoch verstehe ich nur diesen Abschnitt nicht. Deshalb habe ich nur 
diesen Abschnitt euch gezeigt.

Lothar Miller hat mein Problem denke ich so gut wie möglich versucht 
aufzugreifen. Eigentlich brauche ich nichts anderes, wie Kommentare 
hinter jeder Zeile, die mir das geschehen erklärt. Leider verstehe ich 
immer noch nicht ganz, was da passiert.

Hier die Kopfzeile:

vergleicher: process (A, B) is
type int16 is range 0 to 15;
variable a_int: int16;
variable b_int: int16;
variable i: int16;
variable sum: int16;
begin

Ich verstehe einfach nicht, warum ich die Summe mal 2 nehme, wenn doch 
eh null drin steht. und sobald A ungleich Null ist, gehe ich ja in den 
else-Zweig. Damit wird der if-Zweig ja gar nicht mehr verwendet. Also 
warum mal 2, wenn es doch eh immer null ist?

Beispiel: im Vektor A steht die binäre folge von :0110
Wir beginnen mit dem MSB also 0. Er geht in die if-Verzweigung und 
multipliziert die Summe 0 mit 2. Danach geht er auf die nächste Stelle 
also 1. Er geht in die else-Verzweigung und schreibt in die Summe 0*2+1 
also ist die Summe jetzt 1. Danach an die nächste Stelle also wieder 1. 
Else-Verzweigung: Summe= 1*2+1 also 3. Danach die letzte Stelle 0 also 
wieder if-Verzweigung: Summe = 3*2 =6. Jetzt steht in der Summe 6.

Und irgendwie wird mir jetzt gerade klar, was das Programm macht :D
Ich habe verstanden! Ein ganz großes Dankeschön an alle! Ist mir jetzt 
fast ein bisschen peinlich! Ich hoffe ich habe niemandens Zeit 
verschwendet!

Viele Grüße
Matze1992

von user (Gast)


Lesenswert?

und warum so kompliziert

wie wäre es mit (Vergleicht b mit c und das verglichene Ergebnis steht 
dann in a)

a <= '1' when b = c else '0';

von Fabio W. (modellbauer)


Lesenswert?

Lothar Miller schrieb:
> Fabio W. schrieb:
>> Das bedeutet letztendlich nichts anderes, als dass in sum ein Kopie von
>> A steht.
> Nein, denn sum ist ein Integer und A ist ein Vektor. Und das sind zwie
> grundlegend verschiedene Datentypen, auch wenn das jeweilige Bitmuster
> exakt gleich aussehen wird...

Ja, sorry, das ist natürlich leicht falsch zu verstehen. Ich meinte viel 
mehr, dass an der Stelle überhaupt nichts verglichen wird, statt viel 
mehr den INHALT zu 'kopieren'. Natürlich sind die beiden Datentypen 
aber überhaupt nicht gleich.

Matze1992 schrieb:
> type int16 is range 0 to 15;

Matze1992 schrieb:
> Da die Variable 16
> bit groß ist, habe ich 16 mal die null.

Das ist leider falsch. Die Variable ist nicht 16 bit groß, sie kann nur 
16 verschiedene Zustände speichern. Das bedeutet, es sind log(16)bit=4 
bit.

Im Übrigen komme ich jetzt auch dahinter, was der Ausschnitt machen 
soll: to_integer und dann vergleichen...

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


Lesenswert?

Matze1992 schrieb:
> Und irgendwie wird mir jetzt gerade klar,
Na bitte, schrittweises Mitdenken hilft.
> was das Programm macht :D
Irgendwie scheinst du die wichtigste Anmerkung in meinem Post überlesen 
zu haben: Das ist kein Programm sondern eine Hardwarebeschreibung.

user schrieb:
> wie wäre es mit (Vergleicht b mit c und das verglichene Ergebnis steht
> dann in a)
> a <= '1' when b = c else '0';
Der gepostete VHDL-Code ist kein Vergleicher. Es sind nur "irgendwie" 
vier Vergleiche darin. Diese "Vergeleicher" werden in der Hardware aber 
nie aufgebaut. Es wird nur der selbe Vektor mit anderem Datentyp 
dargestellt...

von Matze1992 (Gast)


Lesenswert?

Okay, bevor es noch mehr Missverständnisse zu meinem Post gibt, hier das 
vollständige Programm:

-- Bibliotheken initialisieren:

  library ieee;
  use ieee.std_logic_1164.all;
  use work.all;

-- 
************************************************************************ 
**************

-- Eingaenge und Ausgaenge deklarieren:

entity vergleicher is
  port (
    A, B: in std_logic_vector (3 downto 0);
    GR, EQ, LE: out std_logic
    );
  end entity vergleicher;

-- 
************************************************************************ 
**************

-- Hauptprogramm:

architecture behavior of vergleicher is
  begin

-- Prozess starten:

-- Initialisierung der benötigten Variablen:

    vergleicher: process (A, B) is
    type int16 is range 0 to 15;
    variable a_int: int16;
    variable b_int: int16;
    variable i: int16;
    variable sum: int16;

      begin

-- Umwandlung von Eingang A in Variable a_int

    sum := 0;

    for i in 3 downto 0 loop

      if A(i) = '0' then
        sum := sum * 2;
      else
        sum := sum * 2 + 1;

      end if;

    end loop;

-- Umwandlung von Eingang B in Variable b_int

    a_int := sum;
    sum := 0;

    for i in 3 downto 0 loop

      if B(i) = '0' then
        sum := sum * 2;
      else
        sum := sum * 2 + 1;

      end if;

    end loop;

-- Vergleicher von a_int und b_int

    if a_int > b_int then
      GR <= '1';
      EQ <= '0';
      LE <= '0';
    end if;

    if a_int < b_int then
      GR <= '0';
      EQ <= '0';
      LE <= '1';
    end if;

    if a_int = b_int then
      GR <= '0';
      EQ <= '1';
      LE <= '0';
    end if;

-- 
************************************************************************ 
**************

  end process vergleicher;

-- 
************************************************************************ 
**************

end architecture behavior;

-- 
************************************************************************ 
**************

von Fabio W. (modellbauer)


Lesenswert?

Lothar Miller schrieb:
> Da wäre es super, wenn du die VHDL Tags [ vhdl ] und [ /vhdl ] ohne die
> Leerzeichen um deinen Sourcecode setzen würdest, dann bekommst du
> nämlich Syntax-Highlighting geschenkt...

Außerdem fehlt da meiner Meinung ein:
1
 b_int := sum;

: Bearbeitet durch User
von Hululu (Gast)


Lesenswert?

>hier das vollständige Programm:

Was für ein Programm? Mensch, Meier! Jetzt hat man Dir das schon zweimal 
im selben Thread geschrieben. Das ist kein Programm! Das ist eine 
Hardwarebeschreibung! Auch die extensive Verwendung von Sternchen ändert 
daran nichts.

>-- Bibliotheken initialisieren:

Sowas gibts nicht. Was da folgt, ist eine Deklaration von benutzten 
Bibliotheken. Sogenannte "use clauses".

>VHDL Tags [ vhdl ] und [ /vhdl ] ohne die
>Leerzeichen um deinen Sourcecode setzen würdest, dann bekommst du
>nämlich Syntax-Highlighting geschenkt...

Das ist wohl auch irgendwie an Deinen Gehirnwindungen vorbeigesaust.

>Und was macht das Ganze?
>Damit wird ein Vektor in eine Integer-Zahl umgerechnet. Man könnte
>diesen Ausschnitt z.B. so oder so ähnlich bei der Funktion to_integer()
>aus der numeric_std finden...

Und das wohl auch!

So. Jetzt das ganze nochmal. Aber richtig. Sonst gibts kein Abendbrot 
und Du musst mit Socken ins Bett.

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.