mikrocontroller.net

Forum: FPGA, VHDL & Co. Freuquenzteiler in Xilinx


Autor: Jonas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo Leute...

Hab jetzt die Aufgabe, einen Frequenzteiler in VHDL zu Programmieren.

Mein Eingangssignal kommt vom Altium Live Design Evaluation Board 
(Spartan 3) und nennt sich CLK_BRD.

Kann mir jemand helfen?
Bräuchte einen 50MHz Takt, den kann ich ja direkt vom Board übernehmen, 
da dieser ja nen Quarz mit 50MHz hat.
Dann brauch ich noch einen takt mit 500kHz und einen mit 50Hz.
Wäre für Lösungen sehr sehr dankbar, da ich selber leider noch keinen 
wirklichen Plan hab, wie ich das ganze angehen soll.

Danke!!!
Jonas

Autor: Jonas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
achja, ich brauch die takte dann als Ausgangsports, da wir ne 
gruppenarbeit haben, und andere damit weiterarbeiten....

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> da ich selber leider noch keinen wirklichen Plan hab,
> wie ich das ganze angehen soll.

Wie wäre es z.B mit googlen : Frequenzteiler und VHDL ?

Autor: Jonas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab ich schon, wurde dann aber in ein uraltes forum (2005) 
weitergeleitet, und da kam ich auch nicht weiter.....leider....

Autor: Niklas Gürtler (erlkoenig)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist eine Standardaufgabe. Du brauchst einen Zähler bzw. Timer; der 
zählt bei jedem 50MHz-Takt um eins rauf, und immer, wenn er bei 50 
angekommen ist, schaltest du den 500kHz-Ausgang auf high, und wenn er 
bei 100 ankommt schaltest du ihn wieder auf low, und resettest den 
Zähler auf 0. Für 50 Hz machst du das gleiche, nur mit 500 und 1000.

Autor: Jonas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, das hört sich plausibel an...danke schonmal.....ich halt euch auf 
dem laufenden, wenn es probleme gibt! :)

Autor: Jonas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LIBRARY ieee;
USE ieee.std_logic_1164.all;
ENTITY takt IS

  PORT
  (
    CLK      : IN   std_logic;
    takt50    : OUT  std_logic;
    takt500    : OUT  std_logic;
    takt50M    : OUT  std_logic
    );
END takt;


ARCHITECTURE takt_maker OF takt IS

signal clckzw: integer;
signal clckzw1: integer;
signal gen500: std_logic;
signal gen50: std_logic;


Begin

-------------------500kHz-------------------------- 

process (CLK)
  
  begin
  if(CLK'event and CLK = '1')
  then
    clckzw <= clckzw + 1;
  elsif(clckzw = 50)
  then
    clckzw <= 0;
    gen500 <= not gen500;
  end if;
  takt500 <= gen500;
 end process; 

is jetzt für 500kHz, da ich von nem 50MHz takt ausgeh.....klappt auch 
ganz gut....danke für die tips

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

Bewertung
0 lesenswert
nicht lesenswert
Das sieht recht eigenartig aus...
Ich formatier das mal schöner:
process (CLK) begin
  if(CLK'event and CLK = '1') then  -- wenn ein Takt kommt dann zählen 
    clckzw <= clckzw + 1;
  elsif(clckzw = 50)  then   -- sonst auswerten???? --> seltsame Schreibweise...
    clckzw <= 0;
    gen500 <= not gen500;
  end if;
  takt500 <= gen500; -- das ist hier ganz schlecht: gen500 müsste eigentlich in der Sens-List stehen
end process; 
Diese Schreibweise ist gelinde gesagt, unüblich.


Schöner, weil gängiger, ist das so:
signal clckzw: integer range 0 to 49;
:
process (CLK) begin
  if rising_edge(CLK) then  -- wenn ein Takt kommt dann zählen 
    if (clckzw < 49) then   -- 0..49 = 50 Takte
       clckzw <= clckzw + 1;
    else
       clckzw <= 0;
       gen500 <= not gen500;
    end if;
  end if;
end process; 

takt500 <= gen500;  -- concurrent Zuweisung
Gib bei integer einen Range an, sonst werden immmer gleich 32 Bits 
dafür angelegt.

Autor: unpartei'scher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>achja, ich brauch die takte dann als Ausgangsports, da wir ne
>gruppenarbeit haben, und andere damit weiterarbeiten....

was wollen andere denn dranhängen?
üblicherweise würde man einen Puls ('1' mit Dauer 20 ns @50MHz)
erzeugen, egal ob man 1ms oder 1sec irgendwo braucht.

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

Bewertung
0 lesenswert
nicht lesenswert
> üblicherweise würde man einen Puls ('1' mit Dauer 20 ns @50MHz)
Das ist das, was man gemeinhin als Clock-Enable bezeichnet...   :-/

Autor: Daniel -------- (root)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Tags waren falsch gesetzt .. siehe nächsten korrigierten Beitrag

Autor: Daniel -------- (root)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich brauche öfters Pulse als Takte(nennt man das wirktlich Takte?).
Dafür habe ich in meinen Designs folgendes für schnell und gut befunden.
signal cnt: integer range 0 to 100e6 := 0;
signal sec_pulse: std_logic;
--
cnt <= cnt + 1 when rising_edge(clk100MHz);
sec_pulse <= '1' when cnt = 0 else '0';

in etwas umständlicheren Form mit expliziter Trennung
signal cnt, cnt_next: integer range 0 to 100e6 := 0;
signal sec_pulse: std_logic;
--
process
begin
    wait until rising_edge(clk100MHz);
    cnt <= cnt_next + 1;
end process;

cnt_next <= cnt + 1;

sec_pulse <= '1' when cnt = 0 else '0';

Dafür ist die explizite Form leicht erweiterbar, wenn
etwas mehr Funktionalität gefragt ist. Man muss nur eine
Zeile anpassen. zB
cnt_next <= preload_value when modus = load else
    cnt + 1 when modus = upcount else
    cnt - 1 when modus = downcount else
    cnt;

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

Bewertung
0 lesenswert
nicht lesenswert
signal cnt: integer range 0 to 100e6 := 0;
:
cnt <= cnt + 1 when rising_edge(clk100MHz);
sec_pulse <= '1' when cnt = 0 else '0';
Das das geht wundert mich ein wenig.
Hier wird bei erreichen von 100000000 ein impliziter Reset auf 0 
angenommen, der aber weder von der Simulation noch von der Hardware 
unterstützt wird (mal davon abgesehen, dass der Zähler um 1 zu weit 
zählen würde: von 0 bis 100000000 sind es 100000001 Takte).

Die Simulation bringt eine Bereichsverletzung:
# ** Fatal: (vsim-3421) Value 100000001 for cnt is out of range 0 to 100000000.

Die Synthese macht einen 27Bit-Zähler, und der geht bis 134217727, erst 
dann läuft er über (siehe Screenshot)  :-o

Ich beschreibe das dann eher so:
process begin
    wait until rising_edge(clk100MHz);
    sec_pulse <= '0';
    if (cnt<100000000-1) then -- 0 bis 99999999
       cnt <= cnt + 1;
    else
       cnt <= 0;
       sec_pulse <= '1'     
    end if;
end process;

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

Bewertung
0 lesenswert
nicht lesenswert
So geht es:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity CounterImplizit is
    Port ( clk : in  STD_LOGIC;
           sec : out  STD_LOGIC);
end CounterImplizit;

architecture Behavioral of CounterImplizit is
signal cnt: integer range 0 to 100e6 := 0;
begin

  cnt <=  0       when cnt=100e6 else
          cnt + 1 when rising_edge(clk);

  sec <= '1' when cnt = 0 else '0';

end Behavioral;
Allerdings ist die Beschreibung etwas unüblich und mir gefällt der 
asynchrone Reset nicht so richtig...   :-/

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

Bewertung
0 lesenswert
nicht lesenswert
... denn die Auswertung des Vergleichs  cnt=100e6  braucht doch einiges 
an Logik (Screenshot), und wehe, da kommt mal ein kleiner Glitch 
zusammen.
Dann wird der Zähler einfach vor Erreichen des Endwerts zurückgesetzt.


Fazit: Finger weg von solchen asynchronen Beschreibungen.


Kommt jetzt einer auf die Idee, den Vergleich auch noch zu takten:
  cnt <=  0       when cnt=100e3-1 and rising_edge(clk)else
          cnt + 1 when rising_edge(clk);
Dann klopft ihm der Synthesizer auf die Finger und bemängelt eine
bad asynchronous descritpion.

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

Bewertung
0 lesenswert
nicht lesenswert
Zum schönen Abschluss die synchrone Beschreibung:
  process begin
     wait until rising_edge(clk);
     if cnt=100e6-1 then cnt <= 0;
     else                cnt <= cnt + 1;
     end if;
  end process;

  sec <= '1' when cnt = 0 else '0';
Und der klitzekleine Unterschied im Screenshot:
der Zähler wird synchron zurückgesetzt
(die Reset-Leitung geht auf ein R statt auf ein CLR)

Autor: Daniel (root) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe leider nicht nachgeschaut was aus meiner Kurzform nach
der Synthese wird. Dafür mache ich noch zu wenig mit den FPGA's
:)

Auf den Fehler in der Simulation bin ich aber auch irgendwann mal
gekommen. Das war glaube ich sogar bei der längeren Form wie
ich sie oben geschrieben habe.

Eigentlich müsste die Übergangslogik für cnt_next sauber heissen
cnt_next <= 0 when cnt = 100e6 else
    cnt + 1;
sec_pulse <= '1' when cnt=100e6 else '0';

Dann sollte auch cnt_next nie 100e6+1 werden.

Ich schaue mir deine RTL jpgs genauer etwas später an.
Bin jetzt etwas beschäftigt dafür.

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

Bewertung
0 lesenswert
nicht lesenswert
Diese getrennte Schreibweise (cnt und cnt_next, das ist fast schon der 
Zwei-Prozess-SM Stil) ist überflüssig und führt nur zu unüberschaubaren 
Zähl- und Rücksetzbedingungen.
Mach den gesamten Zähler in einem (1) getakteten Prozess, dann sind 
alle Zählbedingungen sofort einsichtig und Querverbindungen 
ausgeschlossen.

Um dein eigenes Beispiel zu nehmen:
signal cnt: integer range 0 to 100e6-1 := 0;
signal sec_pulse: std_logic;
--
process
begin
    wait until rising_edge(clk100MHz);
    if     modus = load      then cnt <= preload_value;
    elsif  modus = upcount   then cnt <= cnt + 1;
    elsif  modus = downcount then cnt <= cnt - 1;
    elsif  cnt = 100e6-1     then cnt <= 0; 
    else                          cnt <= cnt + 1;
end process;

sec_pulse <= '1' when cnt = 0 else '0';

Autor: Jonas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hallo lothar, danke für deinen Tip,
hat alles so geklappt, wie ich das brauchte....

das mit dem (CLK'event and CLK = '1') kam bei uns so in der 
Digitaltechnik vorlesung dran, deswegen hab ich das so verwendet.

wir bauen gerade eine Smart Cockpitsteuerung zusammen, deswegen muss ich 
die Frequenz als Port nehmen und an andere weiterleiten, die die 
Frequenz brauchen....

Jonas

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.