mikrocontroller.net

Forum: FPGA, VHDL & Co. Uhr mit zwei unterschiedlichen Takten


Autor: Phillip (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Abend Allerseits.

Ich bin VHDL Anfänger. Wir müssen dazu im Studium eine Uhr mit 
bestimmten Eigenschaften erstellen, müssen uns aber die ganze 
Programmiersprache aber mehr oder weniger selbst erarbeiten. Daher seht 
es mir nach, wenn ich jetzt hier schwerwiegende Fehler gemacht habe.

Zur Aufgabe. Es soll eine Uhr erstellt werden mit "Set-Funktion", bei 
der man Minuten und Stunden einzeln einstellt. Wenn man diese nutzt, 
sollen Minuten bzw. Stunden mit 2Hz hochgezählt werden. Ansonsten soll 
die Uhr mit 1Hz laufen. Das Zählwerk soll von einem eigenen 
Taktgeneratorblock mit den zwei Takten "versorgt" werden. Es sollen 
später noch weitere Funktionen wie Alarm dazu kommen. Sekunden, Minuten 
und Stunden sollen BCD-codiert an einen Multiplexer für die Ausgabe 
weitergegeben werden.

Ich stehe nun vor dem Problem, dass ich nicht weiß, wie ich die Ausgabe 
realisieren soll. Folgendes habe ich mir dazu überlegt am Beispiel der 
Minuten überlegt:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

entity tim_mins is
   port
   (  clk1s,clk500ms,set_time,set_mins,reset    :in std_logic;
    tim_mins1  :out std_logic_vector(3 downto 0);
    tim_mins10  :out std_logic_vector(2 downto 0));
end entity;
architecture rtl of tim_mins is
    shared variable mins1:integer range 0 to 10;
    shared variable mins10:integer range 0 to 6;
    shared variable mins1_set:integer range 0 to 10;
    shared variable mins10_set:integer range 0 to 6;
    shared variable abfrage:bit;
begin
    uhr_stellen: process(clk500ms,set_time,set_mins,reset)
      begin
        if reset='0' then
          mins1_set:=0;
          mins10_set:=0;
        elsif rising_edge(clk500ms) then
          if set_time='0' then
            mins1_set:=mins1;
            mins10_set:=mins10;
          elsif (set_mins = '1') then

            mins1_set:=mins1_set+1;
            if mins1_set=10 then
              mins1_set:=0;
              mins10_set:=mins10_set+1;
              if (mins10_set=6) then
                mins10_set:=0;
              end if;
            end if;
          end if;
        end if;

    end process;

    uhr_zaehlt: process(clk1s,set_time,set_mins,reset)
    variable cnt:integer range 0 to 60;
      begin

        if reset='0' then
          mins1:=0;
          mins10:=0;
          abfrage:='0';
        elsif rising_edge(clk1s) then
          if set_time='1' then
            abfrage:='1';
            mins1:=mins1_set;
            mins10:=mins10_set;
          else
            if abfrage='1' then
              abfrage:='0';
              mins1:=mins1_set;
              mins10:=mins10_set;
            end if;
            cnt:=cnt+1;
            if cnt=60 then
              cnt:=0;
              mins1:=mins1+1;
              if mins1=10 then
                mins1:=0;
                mins10:=mins10+1;
                if (mins10=6) then
                  mins10:=0;
                end if;
              end if;
            end if;
          end if;
        end if;
    end process;
    ausgabe_set:process(clk500ms)
      begin
        if rising_edge(clk500ms) then
          if (abfrage='0') then
            tim_mins1<=conv_std_logic_vector(mins1,4);
            tim_mins10<=conv_std_logic_vector(mins10,3);
          else
            tim_mins1<=conv_std_logic_vector(mins1_set,4);
            tim_mins10<=conv_std_logic_vector(mins10_set,3);
          end if;
        end if;
    end process;
end rtl;

Problem ist nun, dass ich nicht von beiden Prozessen Signale an den 
Ausgang geben kann. Dazu hab ich mir den Ausgabeprozess geschrieben.

Das klappt allerdings nur solange, wie "set_time" bei steigender 1Hz 
Flanke auf 0 zurück geht. Wenn das nicht der Fall ist, wird der beim 
Setzen der Zeit eingestellte Wert nicht korrekt übernommen.

Ist das halbwegs verständlich? Sofern jemand Lust und Zeit hat, würde 
ich ihm das Ganze auch per E-Mail zusenden. Ich möchte allerdings 
keinesfalls eine Komplettlösung, denn mich interessiert das sehr und ich 
möchte es auch lernen. Ein Denkanstoß oder Vorschlag zu einem anderen 
Lösungsansatz würde ich auch sehr gerne nehmen.

Grüße und Danke
Phillip

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

Bewertung
0 lesenswert
nicht lesenswert
Das sieht man in letzter Zeit immer mehr:
    shared variable mins1:integer range 0 to 10;
    shared variable mins10:integer range 0 to 6;
    shared variable mins1_set:integer range 0 to 10;
    shared variable mins10_set:integer range 0 to 6;
    shared variable abfrage:bit;
Allerdings würde ich zu diesem Designstil "Mist" sagen  :-/
Man hat dabei die "Softwaredenkweise", die so überhaupt nicht auf 
Hardware passt. Geh mal in die Bücherei und sieh nach, ob das Buch 
"VHDL-Synthese" von Reichardt/Schwarz im Angebot ist.

      :
        elsif rising_edge(clk1s) then
      :
        if rising_edge(clk500ms) then
      :
[vhdl]
Für Allgemein und für Anfänger speziell gilt:
*Im ganzen Design nur 1 Takt*
Der Rest wird über Clock-Enable gemacht.


[vhdl]
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
Sieh dir die genormte numeric_std an:
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Phillip (Gast)

>sollen Minuten bzw. Stunden mit 2Hz hochgezählt werden. Ansonsten soll
>die Uhr mit 1Hz laufen. Das Zählwerk soll von einem eigenen
>Taktgeneratorblock mit den zwei Takten "versorgt" werden. Es sollen
>später noch weitere Funktionen wie Alarm dazu kommen. Sekunden, Minuten
>und Stunden sollen BCD-codiert an einen Multiplexer für die Ausgabe
>weitergegeben werden.

Siehe Taktung FPGA/CPLD

Und hör bitte mit diesen shared variables auf, die braucht kein Mensch.

Deine Beschreibung ist recht akademisch. OK, du bist neu in VHDL. Aber 
wirklich gut ist das alles nicht.

>Problem ist nun, dass ich nicht von beiden Prozessen Signale an den
>Ausgang geben kann. Dazu hab ich mir den Ausgabeprozess geschrieben.

Dafür hat der liebe Gott den Multiplexer erfunden.

>Das klappt allerdings nur solange, wie "set_time" bei steigender 1Hz
>Flanke auf 0 zurück geht. Wenn das nicht der Fall ist, wird der beim
>Setzen der Zeit eingestellte Wert nicht korrekt übernommen.

Das ist alles reichlich verworren. Du brauchst eine saubere State 
Machine. Der Rest ist dann klar und fast schon zu einfach.

Deine State Machine hat nur EINEN Takt. Und zwar den schnellsten im 
System, hier unglaubliche 2 Hz :-0
Steuereingänge sind deine Taster. Muss man bei 2 Hz nicht mal entprellen 
;-)
Über die Auswertung deiner Taster erfolgt das hochzählen der Zeit in 
deinen Variablen. Diese werden dann einfach ausgegeben, ggf. vorher in 
7-Segment dekodiert. Fettig.

MFG
Falk

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

Bewertung
0 lesenswert
nicht lesenswert
Leider ist Falk meinem Korrekturversuch zuvorgekommen ;-)
Deshalb hier mit richtigen Tags:
      :
        elsif rising_edge(clk1s) then
      :
        if rising_edge(clk500ms) then
      :
Allgemein und für Anfänger speziell gilt:
Im ganzen Design nur 1 Takt
Der Rest wird über Clock-Enable gemacht.

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
irgendwie kommt mir die aufgabe verdammt bekannt vor!

nachdem ich jetzt davon ausgehe, dass du an der hochschule mit dem 
"roten würfel" studierst: komm doch mal am donnerstag ab 13 uhr in den 
raum R0053 und frag nach den leuten mit den fpgas - da wird dir gerne 
geholfen ;)

Autor: Max (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ach ja: sollte ich mit meiner vermutung recht behalten: das von Lothar 
Miller vorgeschlagene buch ist in großer stückzahl in der bib vorhanden. 
wir haben damals beantragt, dass das aus studiengebühren angeschafft 
wird. es ist sehr zu empfehlen!

Autor: Phillip (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich danke Euch erst mal. Nachdem Buch werde ich erst mal schauen. Der 
schnellste Takt der gesamten Schaltung soll 1000Hz für einen Piepser 
(Weckfunktion) sein. Die drei Takte sollen in einem eigenen Block 
erzeugt werden und dann an die einzelnen Bausteine weiter geleitet 
werden. Der Takt auf dem späteren Board beträgt 25MHz

Verstehe ich es jetzt erst mal richtig, dass ich danach vor die 
Bausteine einen Multiplexer setze und dann entsprechend dem Taster, den 
jeweiligen Takt durchschalte?

Ich werd jetzt erst mal die Links durcharbeiten, nach dem Buch schauen 
und mich dann wieder melden.

Unsere Hochschule hat ein blaues Logo und eine andere Raumnumerierung. 
;)

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

Bewertung
0 lesenswert
nicht lesenswert
> Der Takt auf dem späteren Board beträgt 25MHz
Dann ist das nicht der spätere Takt, sondern der einzige Takt.
Das ist der Takt, auf dem das gesamte Design laufen wird.

Alles andere wird über Clock-Enables gemacht. Es wird also ein 
Clock-Enable für 1sec und 500ms und 500us (--> Piepser) geben. Aber jede 
Taktabfrage wird in etwa so lauten:
signal teilersec : integer range 0 to 24999999; -- 25MHz Takt 
signal onesec : std_logic := '0'; -- Clockenable für Sekunde 
signal teilerhalfsec : integer range 0 to 12499999;  
signal halfsec : std_logic := '0'; -- Clockenable für halbe Sekunde 

  process (clk) begin
    if rising_edge(clk25m) then -- es kann nur einen geben: der Mastertakt
      if teilersec < 24999999 then
         teilersec <= teilersec +1;
         onesec <= '0';
      else
         teilersec <= 0;
         onesec <= '1';
      end if;
    end if;
  end process;

  process (clk) begin
    if rising_edge(clk25m) then -- es kann nur einen geben: der Mastertakt
      if teilerhalfsec < 12499999 then
         teilerhalfsec <= teilerhalfsec +1;
         halfsec <= '0';
      else
         teilersec <= 0;
         halfsec <= '1';
      end if;
    end if;
  end process;
  
  process (clk) begin
    if rising_edge(clk25m) then -- es kann nur einen geben: der Mastertakt
      if (onesec='1') then
         :
      end if;
      if (halfsec='1') then
         :
      end if;
      if (halfmillisec='1') then 
         piepser <= not piepser:
      end if;
    end if;
  end process;

> und dann entsprechend dem Taster, den jeweiligen Takt durchschalte?
Es gibt nur 1 Takt, deshalb gibt es auch keine Taktumschaltung.

Autor: Nephilim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sollte das signal in der sensitivity-list dann nich auch clk25m heissen 
?

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

Bewertung
0 lesenswert
nicht lesenswert
Nephilim schrieb:
> sollte das signal in der sensitivity-list dann nich auch clk25m heissen
Ach Mann, richtig...... :-/

Ich hätte das am liebsten so geschrieben:
  process begin
    wait until rising_edge(clk25m); -- es kann nur einen geben: der Mastertakt
    if teilerhalfsec < 12499999 then
       teilerhalfsec <= teilerhalfsec +1;
       halfsec <= '0';
    else
       teilersec <= 0;
       halfsec <= '1';
    end if;
  end process;
  
  process begin
    wait until rising_edge(clk25m); -- es kann nur einen geben: der Mastertakt
    if (onesec='1') then
       :
    end if;
    :
  end process;
Dann wäre das mit der Sensitivliste nicht passiert ;-)

Autor: Phillip (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso, ich glaube ich verstehe es langsam, was überall mit dem einen 
Takt geschrieben wird.

Ich erzeuge sozusagen einen Frequenzteiler vom Systemtakt auf die 
gewünschten Frequenzen. In die Uhr/den Block geht dann nach wie vor der 
Systemtakt rein, die Aktion wird aber nur durch das high der "onesec" 
oder "halfsec" entsprechend dem Status von "set_time",sowie "set_min"/ 
"set_hr"freigeschaltet oder nicht?

Ich werde meinen Code heute Nachmittag anpassen.

Das Ganze soll auch erst mal nur am PC simuliert werden. Dabei wäre es 
doch nicht sinnvoll (bezüglich der Dauer der Simulierung) den 
Frequenzteile von 25MHz auf 1Hz herunter zu takten, sondern erst mal als 
Systemfrequenz die 1kHz zu nehmen?

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Das Ganze soll auch erst mal nur am PC simuliert werden. Dabei wäre es
> doch nicht sinnvoll (bezüglich der Dauer der Simulierung) den
> Frequenzteile von 25MHz auf 1Hz herunter zu takten, sondern erst mal als
> Systemfrequenz die 1kHz zu nehmen?
Bei der Größe deines Designs und den heutigen PCs kannst Du locker mit 
25MHz simulieren.

Duke

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

Bewertung
0 lesenswert
nicht lesenswert
> die Aktion wird aber nur durch das high der "onesec" oder "halfsec"
> entsprechend dem Status von "set_time",sowie "set_min"/"set_hr"
> freigeschaltet oder nicht?
Richtig, wobei du darauf achten mußt, dass jedes der Clock-Enable 
Signale nur 1 Takt lang aktiv sein darf. denn wenn das Clock-Enable 
onesec 2 Takte aktiv ist, dann wird gleich um 2 Sekunden hochgezählt.
Für externe Eingänge ist daher eine Flankenerkennung nötig, die wiederum 
dieses für 1 Takt aktive Clock-Enable Signal erzeugt:
http://www.lothar-miller.de/s9y/categories/18-Flan...

Autor: Peee. Teee. (da-phil)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So ich hab mich mal angemeldet. Das Buch musste ich mir leider bestellen 
und ich mich somit gedulden. In der Bibo sind nur sehr wenige Exemplare 
vorhanden und die sind alle vergriffen.

Zur Flankenerkennung. Es soll so realisiert werden, dass die 
Minuten/Stunden hochlaufen, solange man den Schalter hält. Da benötigt 
man doch eigentlich keine Flankenauswertung oder?

Autor: Duke Scarring (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Phillip T.:

>Zur Flankenerkennung. Es soll so realisiert werden, dass die
>Minuten/Stunden hochlaufen, solange man den Schalter hält. Da benötigt
>man doch eigentlich keine Flankenauswertung oder?

Was denkst Du, wie schnell der Zähler bei 25MHz hochzählen kann :-)

Wenn Du Deinen Taster/Schalter mit einem enable von - sagen wir - 1 Hz 
aktivierst, dann bedient sich das Ganze wahrscheinlich etwas komisch. Du 
weißt ja nicht, wann das enable kommt. Es kann quasi sofort kommen oder 
nach fast einer Sekunde.

Schicker ist es die steigende Flanke (edge) zu nehmen und damit 
gleichzeitig einen Zähler zu starten, der dann nach einer Sekunde (oder 
500 ms) einen erneuten Zählimpuls (tick) ausgibt.

Ungefähr so:
Taster ________--------------------------------------____________
edge   ________-_________________________________________________
tick   ____________________-___________-___________-_____________

Duke

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wobei dann der Taktgeneratorblock nicht mehr schön akademisch nur den 
Takt generiert, sondern noch auf Flanken reagieren muss...
Bedienbarkeit ist bei solchen Aufgaben doch meist zweitrangig :)

Autor: Peee. Teee. (da-phil)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also die Simulation fiel erst mal positiv aus. Heute habe ich die 
Portzuweisung begonnen und es erstmals getestet. Zählen und Stellen 
funktioniert. Unser Dozent war sehr überrascht über meinen Fortschritt. 
Da ich eh bis Januar noch Zeit habe, kann ich das ja dann noch 
probieren.

Das Buch ist wirklich gut. Danke für die Tipps.

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Dozent ist überrascht das jemand einen Zähler schreiben kann der mit 
einem enable Signal hochzählt ? (überspitzt ausgedrückt)

Was machen die anderen Studenten denn ?

Bei uns wurden da irgentwie höhere Erwartungen gestellt und ehrlich 
gesagt bin ich auch froh drum.

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist alles eine Frage der Schwerpunktsetzung der Uni...

In Sachen VHDL und FPGA Design habe ich an der Uni auch nicht viel mehr 
gemacht. Andere Sachen dagegen waren wesentlich ausführlicher und 
anspruchsvoller.

Autor: Peee. Teee. (da-phil)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich enthalte mich jetzt weiteren Ausführungen. Man weiß nie wer alles 
mitliest. ;)

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.