www.mikrocontroller.net

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


Autor: Witch (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity Counter is generic( MIN_COUNT:natural:=0; MAX_COUNT:natural:=7 );
  port
  ( 
    clk    : in std_logic;
    toAdd   : in std_logic;
    toDelete: in std_logic;
    count   : out std_logic_vector(2 downto 0)
  );
end entity;

architecture rtl of Counter is begin
  process(clk, toAdd, toDelete)  
  variable cnt : integer range MIN_COUNT to MAX_COUNT;
  begin
    if(clk'event and clk = '1')then
      if(toAdd = '1' and toDelete = '0') then
        cnt:= cnt + 1;
      end if;
    
      if(toDelete = '1' and toAdd = '0')then
        cnt:= cnt - 1;
      end if;
    end if;
  count <= conv_std_logic_vector(cnt,3);
  end process;
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

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi.
Kann es sein dass "natural" vorzeichenbehaftet interpretiert wird?

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Kann es sein dass "natural" vorzeichenbehaftet interpretiert wird?

natural = integer >= 0

Autor: ich (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wäre interesannt was passiert wenn du mal das Abwärtszählen simulierst

Autor: Randomize ... (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
bei mir geht es richtig (abwärts). ISE 10.1

Autor: Mathi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!!!

Autor: Matthias G. (mgottke)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem liegt mit unter an der Verwendung einer Variablen als 
Zähler:
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.
use ieee.numeric_std.all;
   ...
   if(clk'event and clk = '1')then
      cnt := to_integer(unsigned(count));
      if(toAdd = '1' and toDelete = '0') then
   ...
Besser ist es aber gleich als Zähler ein Signal vom Typ unsigned zu 
wählen und kein Variable zu verwenden.

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

Bewertung
0 lesenswert
nicht lesenswert
Zudem ist die Sensitivliste des Prozesses (wie üblich) überdefiniert:
  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:
  process(clk)  

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

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

Am besten also so:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
:
architecture rtl of Counter is 
  signal cnt : integer range MIN_COUNT to MAX_COUNT;
begin
  process(clk)  begin
    if(clk'event and clk = '1')then
      if(toAdd = '1' and toDelete = '0' and cnt<MAX_COUNT) then
        cnt <= cnt + 1;
      end if;
    
      if(toDelete = '1' and toAdd = '0' and cnt>MIN_COUNT)then
        cnt <= cnt - 1;
      end if;
    end if;
  end process;

  count <= std_logic_vector(to_unsigned(cnt,3));
end rtl;

Autor: Matthias G. (mgottke)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Witch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Witch (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

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

Bewertung
0 lesenswert
nicht 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:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity Counter is generic( MIN_COUNT:natural:=0; MAX_COUNT:natural:=7 );
  port
  ( 
    clk     : in std_logic;
    toAdd   : in std_logic;
    toDelete: in std_logic;
    count   : out std_logic_vector(2 downto 0)
  );
end entity;

architecture rtl of Counter is 
  signal cnt : integer range MIN_COUNT to MAX_COUNT := 0;
begin
  process(clk)  begin
    if(clk'event and clk = '1')then
      if(toAdd = '1' and toDelete = '0' and cnt<MAX_COUNT) then
        cnt <= cnt + 1;
      end if;
    
      if(toDelete = '1' and toAdd = '0' and cnt>MIN_COUNT)then
        cnt <= cnt - 1;
      end if;
    end if;
  end process;

  count <= std_logic_vector(to_unsigned(cnt,3));
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.

Autor: Witch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: dr.schmock (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Witch (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

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.