mikrocontroller.net

Forum: FPGA, VHDL & Co. Uhr Beschreiben


Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

nach dem ich mich jetzt ein wenig mit der Entwicklungsumgebung vertraut 
gemacht habe, möchte ich neben dem VHDL lernen an sich, auch nebenbei 
ein kleines Projekt anfangen. Für den Anfang hätte ich da an eine Uhr 
gedacht.
Leider bin ich noch nicht so mit der Herangehensweise der FPGA 
Entwicklung vertraut.
Ich habe mir das jetzt grob so überlegt. Mir stehen 4 7-Segment anzeigen 
zur Verfügung. Davon würde ich je zwei zusammenfassen, und diese zwei 
wiederum in ein Modul "Anzeige" packen. Dieses Modul bietet 2 Eingänge 
an (5 und 6 Bit breit).
Die Uhr als solche würde ich dann wieder in ein extra Modul packen und 
dort dann die anfallenden "Berechnungen" durchführen. Und damit die 
Anzeige ansteuern.
Die Sekunden würde ich binär über LEDs ausgeben.
Was haltet ihr von dem Ansatz, oder habt ihr noch bessere Vorschläge?

Viele Grüße

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

Bewertung
0 lesenswert
nicht lesenswert
Florentin S. schrieb:
> habt ihr noch bessere Vorschläge?
Zähl jede Stelle einzeln...

> Mir stehen 4 7-Segment anzeigen zur Verfügung.
Also Stunder 10er, Stunden 1er sowie Minuten 10er und 1er.
Also würde ich einfach die Minuten 1er hochzählen bis zum Überlauf, dann 
die Minuten 10er usw.
Dann hast du nicht die (recht aufwendige) Trennung in 10er und 1er 
Stellen extra zu machen...

> Und damit die Anzeige ansteuern.
Ist die Anzeige gemultiplext?

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die vier 7-Segment Anzeigen sind gemultiplext. Deswegen war es ja meine 
Idee, die Anzeigenansteuerung, und die eigentliche Uhr zu separieren.

Also würdest du vorschlagen, die Ansteuerung der Anzeigen, und die Uhr 
quasi in eine Architektur zu packen, und dort immer nur die Stellen bis 
zum Überlauf zählen?

Autor: Flo S. (tuxianer)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So ich habe mich gerade mal an die Ansteuerung der gemultiplexten 
7-Segment Anzeige gemacht, und vermutlich alles falsch gemacht, was man 
als Anfänger nur falsch machen kann :-).
Der Code ist im Anhang.

Autor: D. I. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Schonmal garnicht so schlecht.

Man sollte nur nicht mehr die alten Libs verwenden.

Hier ein Vorschlag von mir

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
D. I. schrieb:
> Man sollte nur nicht mehr die alten Libs verwenden.

Ok. Da ist wohl mein Buch nicht mehr ganz auf dem neusten Stand. Was 
wären denn hier die aktuellen?

D. I. schrieb:
> Hier ein Vorschlag von mir

Danke. Aber da sind leider noch zu viele Sachen dabei, die ich noch 
nicht kenne. Da muss ich mich erst einmal weiter mit der Theorie 
beschäftigen.

Noch eine Allgemeine Frage, bezogen auf den Code von mir. Ich habe ja 
jetzt für jede Anzeige ein Eingangssignal inpx. Nun würde ich gerne noch 
ein Modul "Zeitgeber" o.ä. anlegen, der die Stellen durch zählt, und 
dann den Zeitgeber und die Anzeige beispielsweise im Modul "Uhr" 
instanziieren.

Dazu ein paar Fragen. Muss ich für jedes entity samt architecture eine 
eigene Datei anlegen?
Dem "Zeitgeber" würde ich erst einmal 4 Ausgangsports geben. Diese 
möchte ich zum testen erst einmal mit konstanten Werten belegen. Das 
hatte auch geklappt. Nur irgendwie gab es ein Problem mit der Modul 
"Uhr", in dem ich die beiden Sachen  instanziiert und verbunden habe.
Könnte mir eventuell jemand dafür eine Grobstruktur geben? Ich werde es 
jetzt auch noch einmal probieren, und dann den Code hier posten.

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

Bewertung
0 lesenswert
nicht lesenswert
Florentin S. schrieb:
> Ok. Da ist wohl mein Buch nicht mehr ganz auf dem neusten Stand.
Ja, das ist schade, was da so alles an Literatur herumgrukt.
Und auch was an manchen Hochschulen so gelehrt wird...

Florentin S. schrieb:
> Dazu ein paar Fragen. Muss ich für jedes entity samt architecture eine
> eigene Datei anlegen?
Nein, du kannst das alles
(jeweils ab library IEEE; use IEEE.STD_LOGIC_1164.ALL; ...)
in eine einzige Datei packen. Aber idR. ist es sinnvoller, genau das 
nicht zu tun. Denn die Dateien werden doch sowieso von der IDE 
verwaltet...

BTW:
    AN0,AN1,AN2,AN3: inout std_logic;
Es ist nur Faulheit ein inout oder einen buffer zu verwenden, 
damit sich das Signal zurücklesen lässt. Aber (!) inout und buffer 
haben eigentlich eine gänzlich andere Funktion!!! Du wirst damit früher 
oder später auf die Nase fallen...

Besser wäre es, ein internes Signal zu definieren, und an den Ports nur 
in und out zu verwenden!

Hier mal dein Code überarbeitet:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity twoseven is
  port(
    CLOCK: in std_logic;
    AN0,AN1,AN2,AN3: out std_logic;
    inp0,inp1,inp2,inp3: in std_logic_vector(3 downto 0);
    LED: out std_logic_vector(6 downto 0));
end twoseven;

architecture Anzeige of twoseven is
signal stelle : integer range 0 to 3;
signal counter : integer range 0 to 50000; --- anpassen
signal code: std_logic_vector(3 downto 0);
begin
  Multiplex: process(CLOCK)
  begin
    if rising_edge(CLOCK) then
      if(counter < 500000) then
        counter<=counter+1;
      else
        counter<=0;
        if (stelle<3) then
           stelle <= stelle+1;
        else
           stelle <= 0;
        end if;
      end if;
    end if;
  end process;
  
  Stellenauswahl: process(code)
  begin
    AN0<='1'; -- erst mal alle deaktivieren
    AN1<='1';
    AN2<='1';
    AN3<='1';
    case Stelle is
      when 0 => AN0<='0';
                code<=inp0;
      when 1 => AN1<='0';
                code<=inp1;
      when 2 => AN2<='0';
                code<=inp2;
      when 3 => AN3<='0';
                code<=inp3;
    end case;
  end process;

  Anzeigen: process(code)
  begin
    case code is
      when "0000" => LED <="1000000"; --0
      when "0001" => LED <="1111001"; --1
      when "0010" => LED <="0100100"; --2
      when "0011" => LED <="0110000"; --3
      when "0100" => LED <="0011001"; --4
      when "0101" => LED <="0010010"; --5
      when "0110" => LED <="0000010"; --6
      when "0111" => LED <="1111000"; --7
      when "1000" => LED <="0000000"; --8
      when "1001" => LED <="0010000"; --9
      when others => LED <="0000110"; -- Error
    end case;
  end process;
    
end Anzeige;

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Hier mal dein Code überarbeitet:

Danke ich arbeite den gerade mal durch. Nur eine kurze Frage schon mal:
  Stellenauswahl: process(code)

Wieso ist hier code in der sensitivity list? Müsste da nicht Stelle und 
die inpx rein?

Autor: D. I. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Florentin S. schrieb:
> Lothar Miller schrieb:
>> Hier mal dein Code überarbeitet:
>
> Danke ich arbeite den gerade mal durch. Nur eine kurze Frage schon mal:
>
>
  Stellenauswahl: process(code)
>
> Wieso ist hier code in der sensitivity list? Müsste da nicht Stelle und
> die inpx rein?

ja

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

Bewertung
0 lesenswert
nicht lesenswert
Florentin S. schrieb:
> Müsste da nicht Stelle und die inpx rein?
Ja. Sch3155 Copy&Paste... ;-)

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So jetzt scheitert es an der vernetzung der Module und deren 
Organisation im ISE.

Also ich habe jetzt eine Anzeige.vhd. Die kennt ihr ja schon. Dann eine 
Zeitgeber.vhd. Ausschnitt:
entity timer is
  Port(
    CLOCK: in std_logic;
    out0,out1,out2,out3: out std_logic_vector(3 downto 0)
    );
end timer;

architecture Zeitgeber of timer is
begin
  Refresh: process (CLOCK)
  begin
    out0<="0000";
    out1<="0001";
    out2<="0010";
    out3<="0011";
  end process;

end Zeitgeber;

Dann die Uhr.vhd:
entity struktur is
  port(
    CLOCK: in std_logic
  );
end struktur;

architecture Uhr of struktur is

component timer
  Port(
    CLOCK: in std_logic;
    out0,out1,out2,out3: out std_logic_vector(3 downto 0)
  );
end component;

component twoseven
  port(
    CLOCK: in std_logic;
    AN0,AN1,AN2,AN3: out std_logic;
    inp0,inp1,inp2,inp3: in std_logic_vector(3 downto 0);
    LED: out std_logic_vector(6 downto 0));
end component;
Signal con0,con1,con2,con3: std_logic_vector(3 downto 0);
begin
  Geber : timer
  port map(CLOCK,con0,con1,con2,con3);
  Anzeiger : twoseven
  port map(CLOCK=>CLOCK,inp0=>con0,inp1=>con1,inp2=>con2,inp3=>con3);
end Uhr;

Und eine Constraints.ucf (war bisher der Anzeige zugeordnet):
NET "AN0"  LOC = "D14"  ;
NET "AN1"  LOC = "G14"  ;
NET "AN2"  LOC = "F14"  ;
NET "AN3"  LOC = "E13"  ;
NET "CLOCK"  LOC = "T9"  ;
NET "LED<0>"  LOC = "E14"  ;
NET "LED<1>"  LOC = "G13"  ;
NET "LED<2>"  LOC = "N15"  ;
NET "LED<3>"  LOC = "P15"  ;
NET "LED<4>"  LOC = "R16"  ;
NET "LED<5>"  LOC = "F13"  ;
NET "LED<6>"  LOC = "N16"  ;

Wie organisiere ich diese jetzt am besten? Anscheinend ist eine *.ucf 
immer nur einem Modul zugeordnet. Die Definitionen hier sind ja bis auf 
den CLOCK alle für die Anzeige gedacht. Aber wo bringe ich dann den 
Clock unter?

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

Bewertung
0 lesenswert
nicht lesenswert
Florentin S. schrieb:
> Anscheinend ist eine *.ucf immer nur einem Modul zugeordnet.
Machs dir am Anfang einfach und verwende nur 1 ucf-Datei. Diese word dem 
"obersten" Modul zugeorndet, das alle Anschlüsse zur Aussenwelt hat.

Dieser Top-Level dürfte die UHR sein, denn dort geht ja der Takt rein. 
Also müssen dort auch die LEDs rausgehen:
entity struktur is
  port(
    CLOCK: in std_logic;
    AN0,AN1,AN2,AN3: out std_logic;
    LED: out std_logic_vector(6 downto 0))
  );
end struktur;
:
Und diesem Modul wird die UCF-Datei zugeordnet, denn genau dort hast du 
ja die Portnamen wie auch in der UCF-Datei...

Und auf einmal kannst du die bisher unverdrahteten Ports deines Anzeige 
auch noch verdrahten:
  Anzeiger : twoseven
  port map(CLOCK=>CLOCK,inp0=>con0,inp1=>con1,inp2=>con2,inp3=>con3,
           AN0=>AN0,AN1=>AN1,AN2...,LED=>LED);

BTW:
  Geber : timer
  port map(CLOCK,con0,con1,con2,con3);
Mach das besser wie in der anderen Port-Liste nicht nach Position, 
sondern mit expliziten Namen (wie im Anzeiger:twoseven auch).

Autor: Flo S. (tuxianer)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ok danke. Das habe ich jetzt mal gemacht, und jetzt meckert die IDE zu
mindestens nicht mehr herum. Allerdings wird jetzt auf der Anzeige
irgendwas ausgegeben, was sich ändert, wenn ich die Buttons auf dem
Board betätige.
Folglich scheint es irgendwo noch ein Problem zu geben, und die
Anschlüsse "hängen scheinbar in der Luft".
Hast du eine Idee, woran das liegen kann? Funktioniert der Zeitgeber so,
wie ich mir das gedacht habe? Eigentlich müssten da ja konstante Werte
auf den Ports liegen.
Die aktuelle Uhr.vhd ist im Anhang.

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok. Jetzt scheint alles zu funktionieren. Anscheinend war irgendetwas in 
der IDE faul. Nach einem Project Clean funktioniert alles wie gewollt.

Jetzt würde mich noch interessieren, wie man einen möglichst genauen 1Hz 
Takt erzeugt. Hat dafür jemand Tipps? Nimmt man dafür auch einfach einen 
Zähler, und zählt diesen bis 50*10^6 hoch (Mein Board arbeitet mit 50 
MHz), oder gibt es da elegantere Varianten?

Autor: Flo S. (tuxianer)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier die aktuelle Zeitgeber.vhd. Es werden die Sekunden und die Minuten 
auf der Anzeige ausgegeben(besser zum testen :-)).
Als nächstes werde ich versuchen die Sekunden binär über ein paar LEDs 
ausgeben zu lassen, und im Takt dazu den Trennpunkt der Anzeige blinken 
zu lassen.
Als nächstes geht es dann an die Benutzereingabe, damit man die Uhr auch 
stellen kann.

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

Bewertung
0 lesenswert
nicht lesenswert
Florentin S. schrieb:
> Nimmt man dafür auch einfach einen Zähler, und zählt diesen
> bis 50*10^6 hoch (Mein Board arbeitet mit 50 MHz),
Jain...
Korrekt wäre: man zählt 50000000 Takte. Das sind von 0...49999999
:
signal counter : integer range 0 to 50000000-1;
:
      if (counter<50000000-1) then
        counter<=counter+1;
      else
        counter<=0;
   :
Übrigens ein immer wieder gern gemachter Fehler....   ;-)

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Übrigens ein immer wieder gern gemachter Fehler....   ;-)

Oh ja ich vergaß. Die Informatiker fangen ja bei 0 an mit zählen :-).

Beim einbauen des blinkenden Punktes sind mir gleich noch ein paar 
Sachen aufgefallen.
Wenn man die Schnittelle im entity verändert muss man diese ja auch in 
allen Architekturen ändern, in denen das entity über ein component 
eingebunden ist. Das ist ja nicht gerade wartungsfreundlich. Gibt es da 
einen Trick, oder muss man das einfach hinnehmen?
Des Weiteren hat mein Geber als Output nur einen Punkt. In das Interface 
der Anzeige habe ich jedoch alle 4 Punkte eingebaut, da man die Anzeige 
so ja auch für evtl. andere Projekte nutzen kann. Wie handhabt man am 
elegantesten die nicht genutzten Ports(also die am Eingang der Anzeige). 
Im Moment habe ich in der Anzeigen Schnittstelle, und auch beim 
einbinden via component, die Ports mit einem Standard Wert belegt. Beim 
Port Map habe ich diese Ports auf open gelegt. Trotzdem zeigt die IDE 
noch Warnungen an. Also kann das scheinbar noch nciht ganz optimal sein.

Autor: D. I. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Florentin S. schrieb:
> Wenn man die Schnittelle im entity verändert muss man diese ja auch in
> allen Architekturen ändern, in denen das entity über ein component
> eingebunden ist. Das ist ja nicht gerade wartungsfreundlich. Gibt es da
> einen Trick, oder muss man das einfach hinnehmen?

Sigasi VHDL Eclipse Plugin, dann geht das über Refactoring.

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

Bewertung
0 lesenswert
nicht lesenswert
Florentin S. schrieb:
> Wenn man die Schnittelle im entity verändert muss man diese ja auch in
> allen Architekturen ändern, in denen das entity über ein component
> eingebunden ist. Das ist ja nicht gerade wartungsfreundlich.
Abgesehen von irgendwelchen Managementsystemen ist das wie in einem 
C-Programm: wenn du dort z.B. eine Funktionsdeklaration änderst, mußt du 
auch an jeder betroffenen Stelle nachbessern.

> Beim Port Map habe ich diese Ports auf open gelegt. Trotzdem zeigt
> die IDE noch Warnungen an.
Sind das tatsächlich Warnungen oder nur Infos?
In welchem Prozessschritt?

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Florentin S. schrieb:
> Beim
> Port Map habe ich diese Ports auf open gelegt. Trotzdem zeigt die IDE
> noch Warnungen an. Also kann das scheinbar noch nciht ganz optimal sein.

Doch, das passt schon. Irgendwann wird man von ISE bzw. XST so mit 
Warnungen zugemüllt, so das die nicht mehr richtig hilfreich sind :-(
Leider hilft da der Message Filter auch nur bedingt.

Ich guck immer nach, ob folgende Warnungen auftauchen:
WARNING:Xst:737 --> unwanted Latches
WARNING:Xst:653 --> nicht zugewiesene (aber verwendete) Signale

Duke

Autor: Flo S. (tuxianer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es sind Warnungen:
Xst:752[...]Unconnected input port 'p0i' of component 'twoseven' is tied to default value

Ich werde mich jetzt als nächstes an die Benutzerschnittstelle, sprich 
tasten zum Zeit stellen machen. Die Taster müssen ja vermutlich noch 
entprellt werden. Was ist denn dafür die effektivste Methode?

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Florentin S. schrieb:
> Die Taster müssen ja vermutlich noch
> entprellt werden. Was ist denn dafür die effektivste Methode?

Alle x Millisekunden den Wert einlesen (x = 10...100) und nach dem 
Muster "001" suchen.

Duke

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

Bewertung
0 lesenswert
nicht lesenswert
Florentin S. schrieb:
>> Die Taster müssen ja vermutlich noch
>> entprellt werden. Was ist denn dafür die effektivste Methode?
> Alle x Millisekunden den Wert einlesen (x = 10...100) und nach dem
> Muster "001" suchen.
So etwa:
http://www.lothar-miller.de/s9y/categories/5-Entprellung

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.