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


von Georg Bunter (Gast)


Angehängte Dateien:

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?

von Helmut L. (helmi1)


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.

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


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

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


Lesenswert?

Georg Bunter schrieb:
> Wie kann ich das in VHDL programmieren?
Ein "Dreizeiler":
1
:
2
use ieee.numeric_std.all;
3
:
4
  port ( clkin : in std_logic;
5
         clkout : out std_logic );
6
:
7
signal co: std_logic := '0';
8
signal count : integer range 0 to 499 := 0;
9
:
10
:
11
process begin
12
   wait until rising_edge(clkin);
13
   if count<499 then 
14
      count <= count+1;
15
   else 
16
      count <= 0;
17
      co    <= not co;
18
   end if;
19
end process;
20
21
clkout <= co;
22
:

von Georg Bunter (Gast)


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...

von Georg Bunter (Gast)


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  ;-)

von Christoph db1uq K. (christoph_kessler)


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.

von Sebastian Hepp (Gast)


Lesenswert?

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

von Charly B. (charly)


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?

von Harald F. (hfl)


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

von Harald F. (hfl)


Angehängte Dateien:

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

von Harald F. (hfl)


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

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


Angehängte Dateien:

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:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Divider is
6
    Port ( cin : in  STD_LOGIC;
7
           cout : out  STD_LOGIC);
8
end Divider;
9
10
architecture Behavioral of Divider is
11
signal cnt : integer range 0 to 124 := 0;
12
signal enable : std_logic;
13
begin
14
15
   process begin
16
      wait until falling_edge(cin);
17
      if cnt<124 then cnt <= cnt+1;
18
      else            cnt <= 0;
19
      end if;
20
      if cnt<64 then  enable <= '1';
21
      else            enable <= '0';
22
      end if;
23
   end process;
24
 
25
   cout <= cin when enable='1' else '0';
26
27
end Behavioral;
Und braucht gerade mal
1
Device Used   XC9536XL-5-PC44  
2
Macrocells    Pterms         Registers     Pins         Function Block Inputs 
3
9/36  (25%)   16/180  (9%)   8/36  (23%)   2/34  (6%)   15/108  (14%)

Diese Testbench
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.ALL;
3
USE ieee.numeric_std.ALL;
4
5
USE ieee.math_real.ALL;
6
 
7
use std.textio.all;
8
use ieee.std_logic_textio.all;
9
 
10
ENTITY tb_divider IS
11
END tb_divider;
12
 
13
ARCHITECTURE behavior OF tb_divider IS 
14
 
15
    -- Component Declaration for the Unit Under Test (UUT)
16
 
17
    COMPONENT Divider
18
    PORT(
19
         cin : IN  std_logic;
20
         cout : OUT  std_logic
21
        );
22
    END COMPONENT;
23
    
24
25
   --Inputs
26
   signal cin : std_logic := '0';
27
28
   --Outputs
29
   signal cout : std_logic;
30
   
31
   signal count_cout : real := 0.0;
32
   signal count_cin  : real  := 0.0;
33
 
34
BEGIN
35
 
36
  -- Instantiate the Unit Under Test (UUT)
37
   uut: Divider PORT MAP (
38
          cin => cin,
39
          cout => cout
40
        );
41
42
   cin <= not cin after 10ns;
43
   
44
   count_cout <= count_cout+1.0 when rising_edge(cout);
45
   count_cin  <= count_cin+1.0  when rising_edge(cin);
46
   
47
   process 
48
   variable l : line;
49
   variable r : real;
50
   begin
51
      wait for 1 ms;
52
      write(l, string'("teilerverhaeltnis: "));
53
      r := count_cin/count_cout;
54
      write(l, real'image(r));
55
      writeline(output, l);
56
   end process;
57
END;
zeigt dann an, dass das Ganze prinzipiell geklappt hat:
1
teilerverhaeltnis: 1.953125e+00

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


Angehängte Dateien:

Lesenswert?

Aber auch die elegantere Lösung macht sich nicht ohne:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Divider is
6
    Port ( cin : in  STD_LOGIC;
7
           cout : out  STD_LOGIC);
8
end Divider;
9
10
architecture Behavioral of Divider is
11
signal cnt : unsigned (6 downto 0) := (others=>'0');
12
signal enable : std_logic := '0';
13
begin
14
15
   process begin
16
      wait until falling_edge(cin);
17
      if cnt<124 then cnt <= cnt+1;
18
      else            cnt <= (others=>'0');
19
      end if;
20
      enable <= cnt(0) after 7 ns;
21
      if cnt=0 or cnt=60 then enable <= '1' after 7 ns;
22
      end if;
23
   end process;
24
 
25
   cout <= cin after 7 ns when enable='1' else '0' after 7 ns;
26
27
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:
1
Device Used   XC9536XL-5-PC44  
2
Macrocells    Pterms         Registers     Pins         Function Block Inputs 
3
9/36  (25%)   18/180  (10%)  8/36  (23%)   2/34  (6%)   15/108  (14%)

von Georg Bunter (Gast)


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
1
after 7 ns;
?

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


Lesenswert?

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

von df1as (Gast)


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.

von df1as (Gast)


Lesenswert?

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

von Helmut S. (helmuts)


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.

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


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...

von Helmut S. (helmuts)


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.

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


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...

von Helmut S. (helmuts)


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.

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


Angehängte Dateien:

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:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Divider is
6
    Port ( cin : in  STD_LOGIC;
7
           cout : out  STD_LOGIC);
8
end Divider;
9
10
architecture Behavioral of Divider is
11
signal cnt : unsigned (7 downto 0) := (others=>'0');
12
signal enable : std_logic := '1';
13
begin
14
15
   process begin
16
      wait until falling_edge(cin);
17
      if cnt > 125-64 then
18
         cnt  <= cnt - to_unsigned (125-64, 8);
19
         enable <= '1';
20
      else
21
         cnt  <= cnt + to_unsigned (    64, 8);
22
         enable <= '0';
23
      end if;
24
   end process;
25
26
   cout <= cin after 7 ns when enable='1' else '0' after 7 ns;
27
 
28
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:
1
Device Used   XC9536XL-5-PC44  
2
Macrocells    Pterms         Registers     Pins         Function Block Inputs 
3
10/36  (28%)  36/180  (20%)  9/36  (25%)   2/34  (6%)   17/108  (16%)

von Klaus (Gast)


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

von Georg Bunter (Gast)


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
1
to_unsigned (125-64, 8);
?

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


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

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.