www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Teiler durch 1,953125


Autor: Georg Bunter (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe einen uralt Frequenzzähler mit Nixieröhren. Dem möchte ich 
gerne einen Vorteiler durch 1000 verpassen. Der Vorteiler würde aus zwei 
Teilen bestehen.
Erstens wird durch 512 geteilt.
Dann durch 1,953125.
Das macht zusammen 1000.

Ich habe da einen Schaltplan mit TTL-IC's, möchte das aber lieber in 
einem CPLD XC9572 machen.
Wie kann ich das in VHDL programmieren?

Autor: Helmut Lenzen (helmi1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Georg Bunter schrieb:
> Erstens wird durch 512 geteilt.
> Dann durch 1,953125.
> Das macht zusammen 1000.

Du must dir einen Teiler durch 1000 aufbauen. Durch 1,953125 teilen geht 
nicht.

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

Bewertung
0 lesenswert
nicht lesenswert
Georg Bunter schrieb:
> Der Vorteiler würde aus zwei Teilen bestehen.
> Erstens wird durch 512 geteilt.
> Dann durch 1,953125. Das macht zusammen 1000.
Warum teilst du nicht gleich durch 1000?
Denn das geht ja wohl viel einfacher, als durch einskommairgendwas... 
:-o

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

Bewertung
0 lesenswert
nicht lesenswert
Georg Bunter schrieb:
> Wie kann ich das in VHDL programmieren?
Ein "Dreizeiler":
:
use ieee.numeric_std.all;
:
  port ( clkin : in std_logic;
         clkout : out std_logic );
:
signal co: std_logic := '0';
signal count : integer range 0 to 499 := 0;
:
:
process begin
   wait until rising_edge(clkin);
   if count<499 then 
      count <= count+1;
   else 
      count <= 0;
      co    <= not co;
   end if;
end process;

clkout <= co;
:

Autor: Georg Bunter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Warum teilst du nicht gleich durch 1000?
> Denn das geht ja wohl viel einfacher, als durch einskommairgendwas...

Mein Vorteiler der durch 512 teilt, kann das auch bei GHz-Frequenzen.
Das CPLD hat 15ns...

Autor: Georg Bunter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Helmut Lenzen schrieb:
> Du must dir einen Teiler durch 1000 aufbauen. Durch 1,953125 teilen geht
> nicht.

Doch, müsste schon irgendwie gehen:
Da ist ein Zähler der bis 125 zählt.
Da gibt es einen Ausgang wo die Eingangsimpulse durchkommen oder nicht.
Inerhalb dieses Zählerzyklus von 125 Impulsen müssten 64 Impuls 
durchkommen und 61 nicht.
Das ist dann 125/64 = 1,953125

Wahrscheinlich macht diese oben gepostete Schaltung genau das, ich 
kapier's nur irgendwie gerade nicht...

Ich könnte die jetzt natürlich einfach nachbauen, ohne die zu verstehen.
Ich möchte das aber lieber in VHDL machen, das ich mal was lerne  ;-)

Autor: Christoph Kessler (db1uq) (christoph_kessler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also es geht um einen "binary rate multiplier", so heißt der 
Impuls-Verschluck-Zähler üblicherweise. Such mal nach dem Datenblatt zum 
Standard-TTL-IC 7497, der macht n/64 Stufen.

Insgesamt soll die Schaltung ergeben: f_aus=f_in/(512*1000/512), die 
1000/512 sind dabei die genannten 1,953125.

1000/512 kann man noch kürzen, = 125/64 (oder 5^3/2^6). Der 
Impuls-Verschlucker muß also 64 von 125 Impulsen durchlassen, den Rest 
ausblenden.

Der 74HC390 enthält zwei Fünfer-Teiler und zwei Zweier-Teiler, mit zwei 
Stück geht das schon irgendwie, ich hätte nur Bedenken, dass kurze 
Glitches entstehen, wenn man die Verknüpfungen über weitere Gatter 
macht.

Autor: Sebastian Hepp (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Schaltung mit 74HC soll 13GHz und mehr schaffen? Sind die Bausteine 
wirklich so schnell? Und denke an HF-gerechtes Layout. ;)

Autor: Charly B. (charly)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian Hepp schrieb:
> Die Schaltung mit 74HC soll 13GHz und mehr schaffen? Sind die Bausteine
> wirklich so schnell? Und denke an HF-gerechtes Layout. ;)

Georg (TO) schreibt doch:
>Mein Vorteiler der durch 512 teilt, kann das auch bei GHz-Frequenzen.
>Das CPLD hat 15ns...

ALSO NOCHMAL 13Ghz / 512 = 25.39 Mhz
ist doch ganz einfach, mann muss halt nur ALLES lesen, wenn mann
dazu keine Lust hat soll mann auch keine vermutungen oder aehnliches
in die Welt setzen, gell?

Autor: Harald Flügel (hfl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie wärs denn damit: Du schreibst dir Modelle der verwendeten 
TTL-Bausteine, verbindest diese nach Schaltplan, schreibst dir eine 
Testbench dazu und schaust Dir das mal in der Simulation an. Dann 
versteht man vielleicht, was die Schaltung tut, und kann das entweder 
direkt verwenden oder ein neues Modell schreiben, das das Gleiche tut.

Grüße,
Harald

Autor: Harald Flügel (hfl)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag: Habe das Vorgeschlagene mal eben in Verilog runtergetippt und 
simuliert. Siehda, meine Testbench meldet nach 1000 Clocks:

# rising edges of input clock: 1000
# rising edges of output clock: 512
# ratio: 1.953125

Der geteilte Takt sieht aber echt nach Zahnlücke aus! Da fehlen manchmal 
ganze 3 Takte. Und ob das Ganze in Realität funktioniert, müsste man 
noch prüfen.

Grüße,
Harald

Autor: Harald Flügel (hfl)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und noch ein Nachtrag: Mit synchronem Design hat das alles natürlich 
nichts zu tun! In der Schaltung gibt es viele einzelne Clocks und dafür 
sind FPGA eigentlich nicht gemacht. Wenn dir längere Zahnlücken nichts 
ausmachen, dann bietet sich an, einen 125-er Zähler von 0 bis incl. 124 
zu machen, und das "64er"-Bit invertiert als Freigabe für das 
Durchreichen des Clocks zu nehmen. Dann kommen 64 von 125 Takten durch, 
was einen Teiler von 1,953125 ergibt.

Grüße,
Harald

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

Bewertung
0 lesenswert
nicht lesenswert
Harald Flügel schrieb:
> Wenn dir längere Zahnlücken nichts
> ausmachen, dann bietet sich an, einen 125-er Zähler von 0 bis incl. 124
> zu machen, und das "64er"-Bit invertiert als Freigabe für das
> Durchreichen des Clocks zu nehmen. Dann kommen 64 von 125 Takten durch,
> was einen Teiler von 1,953125 ergibt.
Das mit den "Pulspaketen" lässt sich locker mal so "nebenher" 
beschreiben:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Divider is
    Port ( cin : in  STD_LOGIC;
           cout : out  STD_LOGIC);
end Divider;

architecture Behavioral of Divider is
signal cnt : integer range 0 to 124 := 0;
signal enable : std_logic;
begin

   process begin
      wait until falling_edge(cin);
      if cnt<124 then cnt <= cnt+1;
      else            cnt <= 0;
      end if;
      if cnt<64 then  enable <= '1';
      else            enable <= '0';
      end if;
   end process;
 
   cout <= cin when enable='1' else '0';

end Behavioral;
Und braucht gerade mal
Device Used   XC9536XL-5-PC44  
Macrocells    Pterms         Registers     Pins         Function Block Inputs 
9/36  (25%)   16/180  (9%)   8/36  (23%)   2/34  (6%)   15/108  (14%) 

Diese Testbench
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

USE ieee.math_real.ALL;
 
use std.textio.all;
use ieee.std_logic_textio.all;
 
ENTITY tb_divider IS
END tb_divider;
 
ARCHITECTURE behavior OF tb_divider IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
 
    COMPONENT Divider
    PORT(
         cin : IN  std_logic;
         cout : OUT  std_logic
        );
    END COMPONENT;
    

   --Inputs
   signal cin : std_logic := '0';

   --Outputs
   signal cout : std_logic;
   
   signal count_cout : real := 0.0;
   signal count_cin  : real  := 0.0;
 
BEGIN
 
  -- Instantiate the Unit Under Test (UUT)
   uut: Divider PORT MAP (
          cin => cin,
          cout => cout
        );

   cin <= not cin after 10ns;
   
   count_cout <= count_cout+1.0 when rising_edge(cout);
   count_cin  <= count_cin+1.0  when rising_edge(cin);
   
   process 
   variable l : line;
   variable r : real;
   begin
      wait for 1 ms;
      write(l, string'("teilerverhaeltnis: "));
      r := count_cin/count_cout;
      write(l, real'image(r));
      writeline(output, l);
   end process;
END;
zeigt dann an, dass das Ganze prinzipiell geklappt hat:
teilerverhaeltnis: 1.953125e+00

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

Bewertung
0 lesenswert
nicht lesenswert
Aber auch die elegantere Lösung macht sich nicht ohne:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Divider is
    Port ( cin : in  STD_LOGIC;
           cout : out  STD_LOGIC);
end Divider;

architecture Behavioral of Divider is
signal cnt : unsigned (6 downto 0) := (others=>'0');
signal enable : std_logic := '0';
begin

   process begin
      wait until falling_edge(cin);
      if cnt<124 then cnt <= cnt+1;
      else            cnt <= (others=>'0');
      end if;
      enable <= cnt(0) after 7 ns;
      if cnt=0 or cnt=60 then enable <= '1' after 7 ns;
      end if;
   end process;
 
   cout <= cin after 7 ns when enable='1' else '0' after 7 ns;

end Behavioral;
Ich habe hier mal für die Simulation noch ein paar Zeiten eingeführt, um 
zu sehen, wie sich das Ganze in etwa verhält.

Lediglich 2 PT für den zweiten Vergleicher werden zusätzlich benötigt:
Device Used   XC9536XL-5-PC44  
Macrocells    Pterms         Registers     Pins         Function Block Inputs 
9/36  (25%)   18/180  (10%)  8/36  (23%)   2/34  (6%)   15/108  (14%) 

Autor: Georg Bunter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Aber auch die elegantere Lösung macht sich nicht ohne:

Ah ja, du gibst bei cnt=0 und bei cnt=60 jeweils noch einen Impuls dazu.
Dann gibt es auf 125 Eingangsimpuls 62 + 2 = 64 Impulse.
Hübsch.

Ich habe mal den Schaltplan, den ich ganz oben gepostete habe 
entdröselt:
Da ist ein Zähler (1/2 74HC390), der zählt von 0...4
Das Nor-Gatter lässt nur bei Zählerstand 0, 1, 2, 3 die Eingangsimpuls 
durch.
Bei Zählerstand 4 kommen die Eingangsimpulse nicht durch.
Es werden also 4 von 5 Impulsen durchgelassen.
Also ist es ein Teiler durch 1,25
Werden drei solche Teiler hintereinandergeschaltet haben wir einen 
Teilerfaktor von 1,953125  QED

Was bedeutet
after 7 ns;
?

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

Bewertung
0 lesenswert
nicht lesenswert
> after 7 ns;
Ist eine Verzögerte Zuweisung des Signals. Dann sieht man in der 
Simulation besser, was auf was folgt...

Autor: df1as (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Belasse doch das Teilerverhältnis bei 512, oder gehe noch auf 1:1024, 
und passe im gleichen Verhältnis die Torzeit des Zählers an (verlängern 
auf das 1,024-fache) - dann stimmt die Anzeige (bis auf den Faktor 1000) 
wieder. Oder mache das umschaltbar, damit der Zähler ohne Vorteiler auch 
noch verwendbar bleibt.

Autor: df1as (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Außerdem könnte man einen m:n-Teiler wie folgt dahinschreiben:
  -- 64/125
  if Div >= 125-64 then
    Div    <= Div - to_unsigned (125-64, 8);
    ClkOut <= '1';
  else
    Div    <= Div + to_unsigned (    64, 8);
    ClkOut <= '0';
  end if;

Autor: Helmut S. (helmuts)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alle Vorschläge die bisher gebracht wurden sind doch für die Katz.
Offenbar liest keiner was der Fragesteller wirklich machen will.
Eine sinnvolle Lösung sieht so aus:

13GHz/8 Teiler

Dann /125

/5 /5 /5

Alle 4 ICs gibts hier: http://www.hittite.com/

Das wird natürlich nicht gerade billig.


Viel preiswerter wäre es die Zeitbasis von 1s Torzeit auf eine passende 
Zeit anzupassen damit ein Vorteiler durch 1024 passt.

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

Bewertung
0 lesenswert
nicht lesenswert
Helmut S. schrieb:
> Offenbar liest keiner was der Fragesteller wirklich machen will.
Er will eine sehr hohe Taktfrequenz mit seinem langsamen Frequenzzähler 
messen. Und er kann blitzschnell durch 512 teilen. Und um nicht rechnen 
zu müssen oder um den Faktor 1.024 daneben zu liegen, will er die letzte 
Teilerstufe durch einen gebrochenen Teiler bewerkstelligen...

df1as schrieb:
> Außerdem könnte man einen m:n-Teiler wie folgt dahinschreiben:
Ich möchte aber behaupten, dass ein Teilerverhältnis kleiner 2 so nicht 
geht. Denn diese Geschichte kann ja nur durch den Ursprungstakt 
weitergeschaltet werden, und daher bestenfalls mit jedem Takt 1 mal 
umschalten...

Autor: Helmut S. (helmuts)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Und um nicht rechnen
> zu müssen oder um den Faktor 1.024 daneben zu leigen, will er die letzte
> Teilerstufe durch einen gebrochenen Teiler bewerkstelligen...

Den Zahn hätte man dem Fragesteller gleich ziehen müssen.
Dieser Lösungsweg ist für seine Anwendung einfach nicht möglich.

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

Bewertung
0 lesenswert
nicht lesenswert
Helmut S. schrieb:
> Dieser Lösungsweg ist für seine Anwendung einfach nicht möglich.
Da wäre ich mir nicht so sicher. Denn wenn der Frequenzzähler während 
der Gate-Zeit einfach nur Pulse zählt, und mit der doppelten 
Taktfrequenz noch klarkommt, dannn wird das durchaus gehen...

Autor: Helmut S. (helmuts)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Am einfachsten wäre es den Teiler /1000 in der Zeitbasis auf einen 
Teiler /1024 umzuschalten. Dann klappt es auch mit dem 13GHz Teiler 
/1024.
Das wäre sicher die einfachste und preiswerteste Lösung.

Natürlich könnte man einen umschaltbaren Zeitbasisteiler auch in ein
CPLD oder FPGA packen.

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

Bewertung
0 lesenswert
nicht lesenswert
>> Außerdem könnte man einen m:n-Teiler wie folgt dahinschreiben:
> Ich möchte aber behaupten, dass ein Teilerverhältnis kleiner 2 so nicht
> geht. Denn diese Geschichte kann ja nur durch den Ursprungstakt
> weitergeschaltet werden, und daher bestenfalls mit jedem Takt 1 mal
> umschalten...
So ist es.

Aber wenn man wie gehabt aus dem Zähler nur das Clock-Enable gewinnt, 
dann geht es:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Divider is
    Port ( cin : in  STD_LOGIC;
           cout : out  STD_LOGIC);
end Divider;

architecture Behavioral of Divider is
signal cnt : unsigned (7 downto 0) := (others=>'0');
signal enable : std_logic := '1';
begin

   process begin
      wait until falling_edge(cin);
      if cnt > 125-64 then
         cnt  <= cnt - to_unsigned (125-64, 8);
         enable <= '1';
      else
         cnt  <= cnt + to_unsigned (    64, 8);
         enable <= '0';
      end if;
   end process;

   cout <= cin after 7 ns when enable='1' else '0' after 7 ns;
 
end Behavioral;
Mir gefällt hier besonders, dass keine solche "Dreierpakete" mehr 
auftauchen. Und vor allem: die ist wunderbar skalierbar. Allerdings hat 
diese elegante Lösung einen etwas höheren Ressourcenverbrauch:
Device Used   XC9536XL-5-PC44  
Macrocells    Pterms         Registers     Pins         Function Block Inputs 
10/36  (28%)  36/180  (20%)  9/36  (25%)   2/34  (6%)   17/108  (16%) 

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Helmut S. schrieb:
>> Offenbar liest keiner was der Fragesteller wirklich machen will.
> Er will eine sehr hohe Taktfrequenz mit seinem langsamen Frequenzzähler
> messen. Und er kann blitzschnell durch 512 teilen. Und um nicht rechnen
> zu müssen oder um den Faktor 1.024 daneben zu liegen, will er die letzte
> Teilerstufe durch einen gebrochenen Teiler bewerkstelligen...

Könnte man nicht die Gate-Zeit des Zählers so ändern (ohne die 
Nixieröhren dabei rauszuoperieren), daß 1024 als Teilerfaktor passen?

MfG Klaus

Autor: Georg Bunter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar Miller schrieb:
> Mir gefällt hier besonders, dass keine solche "Dreierpakete" mehr
> auftauchen. Und vor allem: die ist wunderbar skalierbar.

Ganz vielen lieben Dank.
Gefällt mir auch sehr.
Werde es am Wochenende umsetzen.
Was bedeutet
to_unsigned (125-64, 8);
?

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

Bewertung
0 lesenswert
nicht lesenswert
Beitrag #2109124:
> Was bedeutet
> to_unsigned (125-64, 8);
to_unsigned it eine Funktion aus der numeric_std, die einen Integer in 
einen unsigned Vektor mit einer gewünschten Breite (hier 8) umwandelt.
Siehe dort: http://www.lothar-miller.de/s9y/archives/14-Numeric_Std.html

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.