Forum: FPGA, VHDL & Co. Freuquenzteiler in Xilinx


von Jonas (Gast)


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

von Jonas (Gast)


Lesenswert?

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

von Klaus F. (kfalser)


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 ?

von Jonas (Gast)


Lesenswert?

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

von Niklas G. (erlkoenig) Benutzerseite


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.

von Jonas (Gast)


Lesenswert?

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

von Jonas (Gast)


Lesenswert?

1
LIBRARY ieee;
2
USE ieee.std_logic_1164.all;
3
ENTITY takt IS
4
5
  PORT
6
  (
7
    CLK      : IN   std_logic;
8
    takt50    : OUT  std_logic;
9
    takt500    : OUT  std_logic;
10
    takt50M    : OUT  std_logic
11
    );
12
END takt;
13
14
15
ARCHITECTURE takt_maker OF takt IS
16
17
signal clckzw: integer;
18
signal clckzw1: integer;
19
signal gen500: std_logic;
20
signal gen50: std_logic;
21
22
23
Begin
24
25
-------------------500kHz-------------------------- 
26
27
process (CLK)
28
  
29
  begin
30
  if(CLK'event and CLK = '1')
31
  then
32
    clckzw <= clckzw + 1;
33
  elsif(clckzw = 50)
34
  then
35
    clckzw <= 0;
36
    gen500 <= not gen500;
37
  end if;
38
  takt500 <= gen500;
39
 end process;

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

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


Lesenswert?

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


Schöner, weil gängiger, ist das so:
1
signal clckzw: integer range 0 to 49;
2
:
3
process (CLK) begin
4
  if rising_edge(CLK) then  -- wenn ein Takt kommt dann zählen 
5
    if (clckzw < 49) then   -- 0..49 = 50 Takte
6
       clckzw <= clckzw + 1;
7
    else
8
       clckzw <= 0;
9
       gen500 <= not gen500;
10
    end if;
11
  end if;
12
end process; 
13
14
takt500 <= gen500;  -- concurrent Zuweisung
Gib bei integer einen Range an, sonst werden immmer gleich 32 Bits 
dafür angelegt.

von unpartei'scher (Gast)


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.

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


Lesenswert?

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

von Daniel -. (root)


Lesenswert?

Die Tags waren falsch gesetzt .. siehe nächsten korrigierten Beitrag

von Daniel -. (root)


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.
1
signal cnt: integer range 0 to 100e6 := 0;
2
signal sec_pulse: std_logic;
3
--
4
cnt <= cnt + 1 when rising_edge(clk100MHz);
5
sec_pulse <= '1' when cnt = 0 else '0';

in etwas umständlicheren Form mit expliziter Trennung
1
signal cnt, cnt_next: integer range 0 to 100e6 := 0;
2
signal sec_pulse: std_logic;
3
--
4
process
5
begin
6
    wait until rising_edge(clk100MHz);
7
    cnt <= cnt_next + 1;
8
end process;
9
10
cnt_next <= cnt + 1;
11
12
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
1
cnt_next <= preload_value when modus = load else
2
    cnt + 1 when modus = upcount else
3
    cnt - 1 when modus = downcount else
4
    cnt;

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


Angehängte Dateien:

Lesenswert?

1
signal cnt: integer range 0 to 100e6 := 0;
2
:
3
cnt <= cnt + 1 when rising_edge(clk100MHz);
4
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:
1
# ** 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:
1
process begin
2
    wait until rising_edge(clk100MHz);
3
    sec_pulse <= '0';
4
    if (cnt<100000000-1) then -- 0 bis 99999999
5
       cnt <= cnt + 1;
6
    else
7
       cnt <= 0;
8
       sec_pulse <= '1'     
9
    end if;
10
end process;

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


Angehängte Dateien:

Lesenswert?

So geht es:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity CounterImplizit is
6
    Port ( clk : in  STD_LOGIC;
7
           sec : out  STD_LOGIC);
8
end CounterImplizit;
9
10
architecture Behavioral of CounterImplizit is
11
signal cnt: integer range 0 to 100e6 := 0;
12
begin
13
14
  cnt <=  0       when cnt=100e6 else
15
          cnt + 1 when rising_edge(clk);
16
17
  sec <= '1' when cnt = 0 else '0';
18
19
end Behavioral;
Allerdings ist die Beschreibung etwas unüblich und mir gefällt der 
asynchrone Reset nicht so richtig...   :-/

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


Angehängte Dateien:

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:
1
  cnt <=  0       when cnt=100e3-1 and rising_edge(clk)else
2
          cnt + 1 when rising_edge(clk);
Dann klopft ihm der Synthesizer auf die Finger und bemängelt eine
bad asynchronous descritpion.

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


Angehängte Dateien:

Lesenswert?

Zum schönen Abschluss die synchrone Beschreibung:
1
  process begin
2
     wait until rising_edge(clk);
3
     if cnt=100e6-1 then cnt <= 0;
4
     else                cnt <= cnt + 1;
5
     end if;
6
  end process;
7
8
  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)

von Daniel (root) (Gast)


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
1
cnt_next <= 0 when cnt = 100e6 else
2
    cnt + 1;
3
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.

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


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:
1
signal cnt: integer range 0 to 100e6-1 := 0;
2
signal sec_pulse: std_logic;
3
--
4
process
5
begin
6
    wait until rising_edge(clk100MHz);
7
    if     modus = load      then cnt <= preload_value;
8
    elsif  modus = upcount   then cnt <= cnt + 1;
9
    elsif  modus = downcount then cnt <= cnt - 1;
10
    elsif  cnt = 100e6-1     then cnt <= 0; 
11
    else                          cnt <= cnt + 1;
12
end process;
13
14
sec_pulse <= '1' when cnt = 0 else '0';

von Jonas (Gast)


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

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.