Forum: FPGA, VHDL & Co. VHDL - UP / DOWN 3-Bit Zählerproblem


von Witch (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe ein Problem oder ggf. ein Verständigungsproblem mit VHDL und 
ich hoffe das mir hier geholfen werden kann.

Ich benötige für ein Projekt im Studium einen 3-Bit Up/Down Zähler.

Dazu habe ich eine ein Counter "entworfen" welcher 3 Eingänge (clk, 
btn_up, btn_down) hat. Dazu verwende ich folgenden Source Code.
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.std_logic_arith.all;
4
use ieee.std_logic_unsigned.all;
5
use ieee.numeric_std.all;
6
7
entity Counter is generic( MIN_COUNT:natural:=0; MAX_COUNT:natural:=7 );
8
  port
9
  ( 
10
    clk    : in std_logic;
11
    toAdd   : in std_logic;
12
    toDelete: in std_logic;
13
    count   : out std_logic_vector(2 downto 0)
14
  );
15
end entity;
16
17
architecture rtl of Counter is begin
18
  process(clk, toAdd, toDelete)  
19
  variable cnt : integer range MIN_COUNT to MAX_COUNT;
20
  begin
21
    if(clk'event and clk = '1')then
22
      if(toAdd = '1' and toDelete = '0') then
23
        cnt:= cnt + 1;
24
      end if;
25
    
26
      if(toDelete = '1' and toAdd = '0')then
27
        cnt:= cnt - 1;
28
      end if;
29
    end if;
30
  count <= conv_std_logic_vector(cnt,3);
31
  end process;
32
end rtl;

Wie man sieht soll der Wert des Zählers bei „btn_up“  1 und bei 
„btn_down“ -1 hinzuzählen.

Diese Objekt habe ich als Block Symbol entworfen und benutze es in 
meiner Schematicfile. In meiner TestBench werden das „clk“ und „btn_up“ 
Signal aller 10 ns gewechselt. Der „clk“ wird bevor er in den Zähler 
geht durch einen Frequenzteiler durch 4 geteilt.

Nun Zählt mein Zähler aber komischer weise nicht bis "111" sondern nur 
bis "011" also das 3 Bit wird nicht gewechselt sodass es zu folgender 
Waveform (siehe Anhang) beim Simulieren kommt.

Kann mir jemand sagen was ich falsch mache und warum mein Zählerstand 
nie >= 3 wird? Über Hilfe und ggf. eine Erklärung wäre ich sehr dankbar.
MfG

Witch

von ich (Gast)


Lesenswert?

Hi.
Kann es sein dass "natural" vorzeichenbehaftet interpretiert wird?

von ich (Gast)


Lesenswert?

>Kann es sein dass "natural" vorzeichenbehaftet interpretiert wird?

natural = integer >= 0

von ich (Gast)


Lesenswert?

Wäre interesannt was passiert wenn du mal das Abwärtszählen simulierst

von Randomize ... (Gast)


Angehängte Dateien:

Lesenswert?

bei mir geht es richtig (abwärts). ISE 10.1

von Mathi (Gast)


Lesenswert?

Witch schrieb:

> use ieee.std_logic_arith.all;
> use ieee.std_logic_unsigned.all;
> use ieee.numeric_std.all;

Das macht keinen Sinn! Entweder man verwendet numeric_std oder 
std_logic_unsigned + std_logic_arith.
Nur sollte man std_logic_arith und std_logic_unsigned für neue Designs 
nicht mehr verwenden!!!

von Matthias G. (mgottke)


Lesenswert?

Das Problem liegt mit unter an der Verwendung einer Variablen als 
Zähler:
1
Eine Variable in VHDL ist kein "physisch vorhandenes" Signal, sondern nur ein Konstrukt, um die Programmierarbeit zu vereinfachen.
Nach Abarbeitung des Prozesses ist die Variable demnach nicht mehr 
präsent. Sie wird aber durch die verschiedenen Conmpiler und Simulatoren 
unter Umständen verschieden interpretiert. Das ganze sollte 
funktionieren, wenn Du die Variable am Anfang des Processes mit dem Wert 
count initialisierst.
Zum rechnen aber bitte nicht mehr die std_logic_arith und die 
std_logic_unsigned verwenden. Dafür gibt es die numeric_std.
1
use ieee.numeric_std.all;
2
   ...
3
   if(clk'event and clk = '1')then
4
      cnt := to_integer(unsigned(count));
5
      if(toAdd = '1' and toDelete = '0') then
6
   ...
Besser ist es aber gleich als Zähler ein Signal vom Typ unsigned zu 
wählen und kein Variable zu verwenden.

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


Lesenswert?

Zudem ist die Sensitivliste des Prozesses (wie üblich) überdefiniert:
1
  process(clk, toAdd, toDelete)
Weil der Prozess nur auf clk sensitiv ist (also nur bei einer Änderung 
von clk neu berechnet werden muß), reicht hier:
1
  process(clk)

Zudem hat die Variable cnt keinen Initialwert. Es ist also 
undefiniert, wo der Zähler zu zählen beginnt...  :-o

EDIT:
1
      cnt := to_integer(unsigned(count));
Das geht nicht, weil count ein OUT-Port ist.

Am besten also so:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
:
5
architecture rtl of Counter is 
6
  signal cnt : integer range MIN_COUNT to MAX_COUNT;
7
begin
8
  process(clk)  begin
9
    if(clk'event and clk = '1')then
10
      if(toAdd = '1' and toDelete = '0' and cnt<MAX_COUNT) then
11
        cnt <= cnt + 1;
12
      end if;
13
    
14
      if(toDelete = '1' and toAdd = '0' and cnt>MIN_COUNT)then
15
        cnt <= cnt - 1;
16
      end if;
17
    end if;
18
  end process;
19
20
  count <= std_logic_vector(to_unsigned(cnt,3));
21
end rtl;

von Matthias G. (mgottke)


Lesenswert?

Lothar Miller schrieb:
> EDIT:      cnt := to_integer(unsigned(count));
> Das geht nicht, weil count ein OUT-Port ist.

Oh, ja stimmt. Aber vom Ansatz her schon richtig. Wenn schon Variable, 
dann aber initialisieren.

von Witch (Gast)


Lesenswert?

Erstmal Danke für die Hinweise.

Ich hab jetzt den Source von Lothar übernommen.
Allerdings zählt mein Zähler dann gar nicht...
Lasse ich den Vergleich auf MIN_COUNT und MAX_COUNT weg zählt mein 
Zähler weiterhin nur von 0 - 2 (001, 010, 011, 000...).

Langsam gehen mir die Ideen aus...

Habt ihr noch irgendwelche Ideen die mir weiterhelfen können?

von Witch (Gast)


Angehängte Dateien:

Lesenswert?

Sorry für den Doppelpost...

Ich hab eben mal eben nur das BlockSymbolfile "simuliert" in dem ich mit 
Modelsim die Werte "geforced" habe. Es scheint als ob der Zähler einzeln 
das tut was er soll, nämlich zählen und zwar von 0 - 7. Ich hoffte zwar 
das er umläuft also wieder bei 0 anfängt aber naja...

Allerdings zählt er nicht wenn ich auf MIN_COUNT und MAX_COUNT prüfe.

Da ich jetzt annehme das es an meiner SchematicFile liegt, übersende ich 
Euch mal den Aufbau meiner Schaltung, sowie meine TestBench und hoffe 
das mir jemand helfen kann.

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


Angehängte Dateien:

Lesenswert?

> Allerdings zählt mein Zähler dann gar nicht...
Was tut er denn?
Das könnte evtl. am nicht initialisierten cnt liegen...
Obwohl das bei mir auch ohne Initialisierung (wie oben gepostet) geht.

Mit genau diesem Code hier kommt bei mir (genau wie erwartet) die 
Waveform wie im Anhang raus:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity Counter is generic( MIN_COUNT:natural:=0; MAX_COUNT:natural:=7 );
6
  port
7
  ( 
8
    clk     : in std_logic;
9
    toAdd   : in std_logic;
10
    toDelete: in std_logic;
11
    count   : out std_logic_vector(2 downto 0)
12
  );
13
end entity;
14
15
architecture rtl of Counter is 
16
  signal cnt : integer range MIN_COUNT to MAX_COUNT := 0;
17
begin
18
  process(clk)  begin
19
    if(clk'event and clk = '1')then
20
      if(toAdd = '1' and toDelete = '0' and cnt<MAX_COUNT) then
21
        cnt <= cnt + 1;
22
      end if;
23
    
24
      if(toDelete = '1' and toAdd = '0' and cnt>MIN_COUNT)then
25
        cnt <= cnt - 1;
26
      end if;
27
    end if;
28
  end process;
29
30
  count <= std_logic_vector(to_unsigned(cnt,3));
31
end rtl;

> Langsam gehen mir die Ideen aus...
Setzt du irgendwann einfach den Zähler zurück?
Zeig doch mal deine Testbench... :-/

EDIT:
> Ich hoffte zwar das er umläuft also wieder bei 0 anfängt aber naja...
Allein die Hoffnung trägt uns weiter, oder wie?
Dein Integer wird nicht umlaufen, sondern einen Simulationsfehler 
bringen. Denn 7+1 = 8 und damit größer als der angegebene Wertebereich.

Solche "automatisch" überlaufende Zähler werden mit dem Datentyp 
unsigned gemacht.

von Witch (Gast)


Lesenswert?

Also die Testbench die ich verwende hatte ich in meinem vorhergehenden 
Post angehängt. Es ist die "TestBench.vht". Ich hab sie nur umbenannt. 
Also nicht von dem Unterschied zwischen Namen der Datei und dem 
VHT-Source verwirren lassen.

Und zurücksetzen tue ich meines Wissens nach den Zähler nicht. Die 
Schaltung in die er eingegliedert ist habe ich ebenfalls in meinem 
vorhergehenden Post angehängt.

von dr.schmock (Gast)


Lesenswert?

Wird MAX_COUNT vielleicht bei der Instanziierung auf einen Wert kleiner 
7 gesetzt? Es ist ja schließlich ein Generic.
Das ist zwar fast schon zu naheliegend, aber manchmal sind's ja die 
"einfachen" sachen...

von Witch (Gast)


Lesenswert?

Also ich hab jetzt Schritt für schritt (lang lebe der Step-Mode) den 
Zähler mit Modelsim getestet.

Und wie Lothar schon sagte, er läuft tadellos.
Nachdem ich noch einen Vergleich gesetzt hab ob MAX_COUNT bzw MIN_COUNT 
erreicht wurde Funktioniert auch der "Umlauf".

Aber sobald ich das Bauteil "Counter" in meiner angegebenen Schaltung 
mit dem Frequenzteiler "einbaue" und diese dann mit der Testbench teste, 
zählt er wieder nur Unfug zusammen...

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.