Forum: FPGA, VHDL & Co. Frequenzteiler


von Marktschreier (Gast)


Lesenswert?

Hallo,
ich möchte eine Frequenz durch 125 teilen.
Wie kann ich das in VHDL programmieren?
Könnte mir jemand die verschiedenen Möglichkeiten aufzeigen?

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


Lesenswert?

Marktschreier schrieb:
> Wie kann ich das in VHDL programmieren?
So etwa:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Clockdivider is
6
    Generic ( divider  : integer := 125);
7
    Port ( ci : in  STD_LOGIC;
8
           co : out  STD_LOGIC);
9
end Clockdivider;
10
11
architecture Behavioral of Clockdivider is
12
signal clkdiv : integer range 0 to divider-1 := 0;
13
begin
14
   process begin
15
      wait until rising_edge(ci);
16
      -- erst mal ein Zähler mit 125 Schritten
17
      if (clkdiv < divider-1) then   clkdiv < clkdiv + 1;
18
      else                           clkdiv <= 0;
19
      end if;
20
      -- und dann so
21
      if (clkdiv < divider/2) then   co <= '1';
22
      else                           co <= '0';
23
      end if;
24
   end process;
25
   -- oder so
26
   co <= '1' when clkdiv < divider/2 else '0';
27
end Behavioral;

Aber so ein Takt sollte nicht innerhalb eines FPGAs weiterverwendet 
werden. Dort arbetiet man idR. besser mit Clock-Enables. Etwa so:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Clockdivider is
6
    Generic ( divider  : integer := 125);
7
    Port ( ci : in  STD_LOGIC;
8
           :
9
           :
10
           );
11
end Clockdivider;
12
13
architecture Behavioral of Clockdivider is
14
signal clkdiv : integer range 0 to divider-1 := 0;
15
signal ce: std_logic := '0';
16
begin
17
   process begin
18
      wait until rising_edge(ci);
19
      -- erst mal ein Zähler mit 125 Schritten
20
      if (clkdiv < divider-1) then   
21
         clkdiv < clkdiv + 1;
22
         ce <= '0';
23
      else
24
         clkdiv <= 0;
25
         ce <= '1';
26
      end if;
27
   end process;
28
29
   process begin
30
      wait until rising_edge(ci);
31
      if (ce='1') then
32
        :
33
        : -- mach was alle 125 Takte   
34
        :
35
      end if;
36
   end process;
37
38
end Behavioral;

Sieh dir da mal das Lauflicht an:
http://www.lothar-miller.de/s9y/archives/61-Lauflicht.html

von Marktschreier (Gast)


Lesenswert?

Lieber Lothar,

hab ganz vielen herzlichen Dank für deinen tollen VHDL-Code!

Der Hintergrund, warum ich so einen Code haben wollte war übrigens 
folgendes:

1. Um davon zu lernen... Besten Dank :-)
2. Ich möchte einen alten Frequenzzähler mit einem Vorteiler/Prescaler 
versehen. Einem schnellen Teiler durch 8 würde ich dann einen Teiler 
durch 125 nachschalten um insgesamt auf einen Teilerfaktor von 1000 zu 
kommen.

Darf ich den Thread hier durch eine Zusatzfrage erweitern?:
Wenn mein Prescaler durch 512 teilt, und ich insgesamt einen 
Teilerfaktor von 1000 haben möchte, wie kann man das realisieren?

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


Lesenswert?

Marktschreier schrieb:
> Wenn mein Prescaler durch 512 teilt, und ich insgesamt einen
> Teilerfaktor von 1000 haben möchte, wie kann man das realisieren?
Nur sehr schlecht, denn ohne den Eingangstakt zu haben, ist dann im 
heruntergeteilten Takt zuviel Information verloren...

von Mathias J. (mjpdx)


Lesenswert?

Weitere Möglichkeit:
Sequentielle Anweisung:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity Divider_module is

port(

clk: IN std_logic ;
divclk: OUT std_logic;
);

end Divider_module;


architecture Bev of Divider_module is

signal  sig_clk    : std_logic_vector (6 downto 0);

begin
process (clk)
begin

if (clk 'event and clk = '1') then
   sig_clk <= sig_clk + 1 ;

   if(sig_clk = "1111101") ; -- =125
     divclk <= '1'  ;
     sig_clk <=  "0000000" ;

     else
      divclk <= '0' ;

   end if
end if
end process ;
end Bev;


Vielleicht etwas leichter verständlich.
Über die Qualität kann ich keine Aussage machen, da Anfänger;-
Getestet habe ich die Anweisung noch nicht, sollte aber laufen!

> Wenn mein Prescaler durch 512 teilt, und ich insgesamt einen
> Teilerfaktor von 1000 haben möchte, wie kann man das realisieren?

Auf 1024 zu kommen wäre leicht: /2
Aber auf 1000:  /1.953... Mir fällt auf die schnelle nichts ein!

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


Lesenswert?

Mathias Jt schrieb:
> signal  sig_clk    : std_logic_vector (6 downto 0);
> :
>    sig_clk <= sig_clk + 1 ;
Was mir dazu einfällt: mit Vektoren rechnet man nicht.
Stattdessen gibt es die Datentypen signed, unsigned und integer.
Und dazu dann die numeric_std.all verwenden

von Duke Scarring (Gast)


Lesenswert?

Mathias Jt schrieb:
> Aber auf 1000:  /1.953... Mir fällt auf die schnelle nichts ein!

Da hilft ein fractional counter. Problematisch könnte der Jitter in 
diesem Fall werden. Wofür brauchst Du denn den Takt?

Duke

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.