Forum: FPGA, VHDL & Co. VHDL zwei CLK´s mit LFSR und 1:2 Teiler


von Sawyer M. (sawyer_ma)


Lesenswert?

Hallo alle zusammen,

ich habe eine Frage. Ich muss aus einem 100MHz Takt aus gründen der 
Didaktik einen 2 MHz und 1MHz Takt erzeugen.

Somit habe ich verschiedene Möglichkeiten. Ich kann einen Zähler im 
herkömmlichen sinne aufbauen oder einen LFSR.

Die Vorteile beim LSFR überwiegen gegen über eines herkömmlichen Zählers 
aufgrund der Laufzeit und des kleinen Hardwareverbrauchs. Da ich bei der 
ganzen Sache auch etwas lernen möchte und die bestimmte Zählfolge bei 
einer Taktteilung nicht wichtig ist, habe ich mich für den LSFR 
entschieden.

Bitte korrigiert mich, wenn ich falsch liege!

Neues Ziel neue Probleme. Somit weiß ich nicht so richtig, wie ich den 
2MHz Takt berechne aus einem Eingangstakt von 100MHz?
Die 2MHz würde ich dann mit einem Frequenzteiler auf 1MHz teilen.

Ist das ein guter Plan?

Als Beispiel habe ich diesen Code im Internet gefunden. Diesen würde ich 
dann für meine Wünsche abändern.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity pulse_per_second is
    Port ( clk : in  STD_LOGIC;
           pps : out  STD_LOGIC);
end pulse_per_second;

architecture Behavioral of pulse_per_second is
   signal lfsr : std_logic_vector(24 downto 0) := (others => '1');
begin
p: process(clk)
   begin
      if rising_edge(clk) then
         if lfsr  = "1111111111111111111111111" then
            lfsr <= "0111110111010111001000000";
            pps  <= '1';
         else
            lfsr <= (lfsr(0) xor lfsr(3)) & lfsr(lfsr'high downto 1);
            pps  <= '0';
         end if;
      end if;
   end process;
end Behavioral;

Beste Grüße

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


Lesenswert?

Sawyer M. schrieb:
> Die Vorteile beim LSFR überwiegen gegen über eines herkömmlichen Zählers
> aufgrund der Laufzeit und des kleinen Hardwareverbrauchs.
Wer sagt das?
Es geht schon so los: ein 8 Bit LFSR kann 255 unterschiedliche Zustände 
annehmen, ein 8 Bit Binärzähler kann 256 Zustände annehmen.

Die LFSR, die ich kenne, werden übrigens zur Erzeugung von Rauschen 
eingesetzt. Das ist für einen Oszillator eher suboptimal...

Sawyer M. schrieb:
> Ich muss aus einem 100MHz Takt aus gründen der Didaktik einen 2 MHz und
> 1MHz Takt erzeugen.
Dann erzeuge den 2MHz Takt und teile den mit einem weiteren Flipflop auf 
1MHz.
Von 100MHz auf 2 MHz brauche ich 6 Flipflops, für 2MHz nach 1MHz brauche 
ich ein simples Flipflop.
Allemal weniger als die 25 Bits deines Schieberegisters.

Aber eines muss gesagt sein: diese Taktderivate sind keine Takte, die in 
einem FPGA tatsächlich als Takte verwendet werden sollten. Die Raktion 
der Toolchain dürfte in etwa "derived clocks ... skew ... no good design 
practice" lauten...

Sawyer M. schrieb:
> Als Beispiel habe ich diesen Code im Internet gefunden.
Dort isser her: 
http://hamsterworks.co.nz/mediawiki/index.php/LFSR_Divider
Der letzte Satz dort sollte allerdings alle Alarmglocken aufleuchten 
lassen: dieser Code taugt nur als verwirrender Binärteiler und du 
braucht sie richtigen Taps und den richtigen Intialwert, um etwas 
anderes als einen 32MHz Teiler daraus zu machen.

: Bearbeitet durch Moderator
von Achim S. (Gast)


Lesenswert?

Sawyer M. schrieb:
> Die Vorteile beim LSFR überwiegen gegen über eines herkömmlichen Zählers
> aufgrund der Laufzeit und des kleinen Hardwareverbrauchs.

ein 25 Bit LSFR ist also ein "kleinerer Hardwareverbrauch" als ein 5 Bit 
Zähler? (Den bräuchtest du, um per Zähler alle 25 Takte das 
Ausgangssignal einmal zu toggeln.)

Sawyer M. schrieb:
> Ich muss aus einem 100MHz Takt aus gründen der
> Didaktik einen 2 MHz und 1MHz Takt erzeugen.

Deine Ausgangssignale werden zwar mit 2MHz bzw. 1MHz hin und 
herschalten. Aber du solltest dir im Klaren darüber sein, dass das dann 
kein Taktsignal ist in dem Sinn, dass du damit eine Logik im FPGA 
vernünftig takten kannst. Es wird nicht von den Clock-Treibern des FPGAs 
auf dem Clock-Tree verteilt sondern ist ein normales Logiksignal. Wenn 
du es an einem IO ausgibst und mit dem Oszi betrachtest, wird es aber 
wie ein 2MHz-Takt ausschauen.

von Achim S. (Gast)


Lesenswert?

Ups: da war ich mit meiner Antwort wohl zu spät dran.

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


Lesenswert?

Achim S. schrieb:
> Ups: da war ich mit meiner Antwort wohl zu spät dran.
Kann nicht oft genug gesagt werden. Aber es wird trotzdem passieren... 
;-)

von ~Mercedes~ (Gast)


Lesenswert?

Ein echter Hase meinte:

> Kann ein 8 Bit LFSR 255 unterschiedliche Zustände annehmen, ein 8 Bit
> Binärzähler kann 256 Zustände annehmen...

Absoltut geil. Eine Falle,gerade,wenn man mit nem Schieberegister
RAM ansteuern will.
Bin selbst mal dran hängengeblieben. ;-O

@Lothar, wo lernt man soetwas, außerhalb von Trial - Error?

mfg

von Sawyer M. (sawyer_ma)


Lesenswert?

Achim S. schrieb:
> ein 25 Bit LSFR ist also ein "kleinerer Hardwareverbrauch" als ein 5 Bit
> Zähler? (Den bräuchtest du, um per Zähler alle 25 Takte das
> Ausgangssignal einmal zu toggeln.)

Ok ich gebe euch recht da war ich absolut nicht ausreichend informiert. 
Aber deine Antwort verwirrt mich.

Verstehe ich das alles richtig:

Bei 100MHz ist T = 10ns. Das bedeutet um eine 2MHz Takt zu generieren 
brauche ich einen Zähler der 100MHz/2MHz = 50 => 50*10ns = 500ns => f = 
1/T = 2MHz.

Also da mein zukünftiger Zähler auf rising_edge reagiert und diese alle 
10ns bei meinem Clock kommt, brauche ich eine Zähler der auf 25 Zählt. 
Somit reichen 5 Bit.

Alles soweit korrekt?

-----------------------------------------------------------------------

architecture Behavioral of zaehler is

    signal count_2Mhz   : std_logic_vector (4 downto 0);

begin
        process(rst, clk_in)
           begin
               if  rst = '1' or count_2Mhz = "11000" then
                   count_2Mhz <= "00000";
               elsif rising_edge(clk_in)) then
                    count_2Mhz<= count_2Mhz+'1';
               end if;
           end process;
end Behavioral;

-----------------------------------------------------------------------

Die 2MHz teile ich dann mit einem Frequenzteiler mit D-Flip Flops. Dafür 
muss ich ja nicht extra noch einen Zähler bauen.

Ist das dann alles richtig und ein eleganter Weg? Bekomme ich Probleme 
mit Laufzeiten?

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


Lesenswert?

Sawyer M. schrieb:
> Somit reichen 5 Bit.
> Alles soweit korrekt?
Nein. Du hast da irgend einen Dreher rein bekommen,
denn die Rechnung zur Abschätzen der Flipflops ist voll simpel:
100MHz/2MHz = 50 --> 5 Bit reichen nicht, weil die nur 32 Schritte 
abbilden können.

Natürlich ist es so, dass du für ein symmetrisches 2MHz-Signal mit 5 Bit 
von 0..24 zählst und dann das eigentliche sechste(!) 2MHz Flipflop 
toggelst.
In der Summe hast du aber wieder 6 Bits für den gesamten Teiler von 100 
nach 2MHz.

> Die 2MHz teile ich dann mit einem Frequenzteiler mit D-Flip Flops. Dafür
> muss ich ja nicht extra noch einen Zähler bauen.
Das ist ein Zähler. Halt einfach nur mit 1 Bit Breite.

> Ist das dann alles richtig und ein eleganter Weg? Bekomme ich Probleme
> mit Laufzeiten?
Ja, böse Probleme sogar! Abhängig z.B. von der Versorgungsspannung oder 
der Temperatur oder sonstwas....
Denn dieser Code mit dem asynchronen kombinatorischen Reset ist das 
Schlimmste und Unreproduzierbarste, was einem in der Praxis passieren 
kann (das ist nicht übertrieben und es ist bestimmt kein Witz)!
Das Stichwort dazu: Glitches beim Zählen.

: Bearbeitet durch Moderator
Beitrag #5393457 wurde vom Autor gelöscht.
von Sawyer M. (sawyer_ma)


Lesenswert?

Lothar M. schrieb:

>> Ist das dann alles richtig und ein eleganter Weg? Bekomme ich Probleme
>> mit Laufzeiten?
> Ja, böse Probleme sogar! Abhängig z.B. von der Versorgungsspannung oder
> der Temperatur oder sonstwas....
> Denn dieser Code mit dem asynchronen kombinatorischen Reset ist das
> Schlimmste und Unreproduzierbarste, was einem in der Praxis passieren
> kann (das ist nicht übertrieben und es ist bestimmt kein Witz)!
> Das Stichwort dazu: Glitches beim Zählen.

Ok, jetzt bin ich völlig verwirrt. Oben wurde mir doch geraten meinen 
100MHz Takt mit einem synchronen Zähler auf 2MHz zu teilen und 
anschließend diesen mit einem weiteren auf 1MHz. Aber dadurch fange ich 
mir nun böse Fehler ein?

Nun stelle ich mir die Frage wie kann ich 100MHz auf 2MHZ und 1MHz 
teilen ohne Glitches usw. einzufangen?

Vielen Dank für deine Geduld mit mir.

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


Lesenswert?

Sawyer M. schrieb:
> meinen 100MHz Takt mit einem synchronen Zähler auf 2MHz zu teilen
Ein synchroner Zähler hat niemals einen asynchronen Reset. Also ist das, 
was du da geschrieben hast kein richtiger synchroner Zähler.

Mach einfach wie der Rest der Welt das Zurücksetzen des Zählers auch in 
dem getakteten Teil des Prozesses und du bist dicht am Ziel.

Und dann nimmst du noch einen integer als Zähler, dann kann  man die 
Funktion und den Zahlbereich auf Anhieb sehen...

~Mercedes~ schrieb:
> @Lothar, wo lernt man soetwas
Keine Ahnung, es bleibt irgendwie hängen... ;-)

: Bearbeitet durch Moderator
von Sawyer M. (sawyer_ma)


Lesenswert?

Sodelle ich habe mal ein wenig auf deiner Homepage herumgestöbert. Ich 
hoffe jetzt passt es. Unsicher war ich mir nur sehr bei der Zuweisung 
von count2 auf clk2. Wenn ich

clk2 <= count2;

geschrieben habe gab es Fehler.
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity zaehler is
6
    Port(
7
          clk    :   IN  STD_LOGIC;
8
          rst    :   IN  STD_LOGIC;
9
          clk2   :   OUT unsigned
10
     );
11
         
12
end zaehler;
13
14
15
architecture Behavioral of zaehler is
16
17
    signal count2    : unsigned (5 downto 0);
18
    signal rstsync   : unsigned(1 downto 0);
19
    
20
begin    
21
22
    process begin                   -- Einsynchronisieren des Resets
23
        wait until rising_edge(clk);
24
            rstsync <= rstsync(0) & rst;
25
        end process;   
26
27
     process(rstsync, clk)
28
        begin 
29
        if  rstsync = 1 or count2 = "011000" then
30
            count2 <= "000000";
31
        elsif rising_edge(clk) then
32
            count2 <= count2 + 1;
33
        end if;
34
     end process;   
35
                                                       
36
end Behavioral;

Beste Grüße

Fazit: Irgendwo hat sich doch ein Fehler eingeschlichen. Ich bekomme es 
einfach nicht Simuliert. Ich vermute die Zuweisung auf einen Port Fehlt 
„clk2“. Synthetisieren läuft durch jedoch bei Implementation gibts ein 
fail. :/

Gute Nacht, morgen gehts weiter...

: Bearbeitet durch User
von Achim S. (Gast)


Lesenswert?

Guten Morgen...

Sawyer M. schrieb:
> Irgendwo hat sich doch ein Fehler eingeschlichen.

Die Abfrage auf count2 = "011000" erfolgt nicht taktsynchron, darin 
liegt der Fehler. Der Vergleich zwischen Count2 und der Konstanten 
"011000" wird kombinatorisch durchgeführt und das Ergebnis auf den 
asynch Reset gegeben. Count2 ändert sich also asynchron, getrieben von 
einer asynchronen Kombinatorik. Einige Bits von Count2 können schon den 
"Überlauf" auf 0 machen, und damit nehmen sie den anderen Bits von 
Count2 die Grundlage, um ebenfalls auf 0 überzugehen.

Versuchs mal mit:
1
     process(clk)
2
     begin 
3
        if  rising_edge(clk) then
4
           if rstsync = 1 then
5
              count2 <= "00000";
6
              clk2MHz <= '0';           
7
           else
8
              if count2 = "11000" then
9
                 count2 <= "00000";
10
                 clk2MHz <= not clk2MHz ;
11
              else
12
                 count2 <= count2 + 1;
13
              end if;  
14
           end if;
15
        end if;
16
     end process;

(Die unnötige oberste Stelle von count2 habe ich entfernt um 
Hardwareressourcen zu sparen ;-)

Sawyer M. schrieb:
> Ich vermute die Zuweisung auf einen Port Fehlt
> „clk2“. Synthetisieren läuft durch jedoch bei Implementation gibts ein
> fail. :/

Ja, hat offensichtlich gefehlt, du hast nirgends etwas auf clk2 
zugewiesen. Für die Synthese kein Problem (deine Logik macht einfach gar 
nichts), beim Implementieren fehlt dann eine Quelle für clk2.

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


Lesenswert?

Sawyer M. schrieb:
> clk2   :   OUT unsigned
Der sollte da nicht so gänzlich unconstrained dastehen. Gib eine 
Vektorbreite an...

Achim S. schrieb:
> Versuchs mal mit: ...
Oder besser gleich ohne den unnötigen Reset und so, dass es ein 
Normalsterblicher auch gleich lesen kann:
1
     signal count2 : integer range 0 to 24 := 0;
2
3
4
     process(clk)
5
     begin 
6
        if  rising_edge(clk) then
7
           if count2 = 24 then
8
             count2 <= 0;
9
             clk2MHz <= not clk2MHz ;
10
           else
11
             count2 <= count2 + 1;
12
           end if;
13
        end if;
14
     end process;

Oder gleich so und den 1MHz "Takt" nebenher miterzeugt:
1
     signal count2 : integer range 0 to 24 := 0;
2
3
4
     process begin 
5
        wait until rising_edge(clk);
6
        if count2 = 24 then
7
           count2 <= 0;
8
           clk2MHz <= not clk2MHz ;
9
           if clk2MHz then
10
              clk1MHz <= not clk1MHz;
11
           end if;
12
        else
13
           count2 <= count2 + 1;
14
        end if;
15
     end process;

Sawyer M. schrieb:
> Unsicher war ich mir nur sehr bei der Zuweisung von count2 auf clk2.
> Wenn ich
> clk2 <= count2;
> geschrieben habe gab es Fehler.
Brauchst du den Zählerstand tatsächlich ausserhalb dieses Moduls? Im 
Simulator kannst du mit einem Klick auch die internen Signale eines 
Moduls ansehen. Die müssen nicht alle zum Toplevel "hochgereicht" 
werden.

: Bearbeitet durch Moderator
Beitrag #5393971 wurde vom Autor gelöscht.
von Sawyer M. (sawyer_ma)


Angehängte Dateien:

Lesenswert?

Ich habe versucht diese Stelle zu verstehen und in meinen Code zu
übersetzen. Leider ist es mir nicht vollständig gelungen. Er wirft immer
noch Fehler. Ein steiniger Weg zu meinen 2MHz und 1MHz. :D

Lothar M. schrieb:
>
1
signal count2 : integer range 0 to 24 := 0;
2
> 
3
>      process begin
4
>         wait until rising_edge(clk);
5
>         if count2 = 24 then
6
>            count2 <= 0;
7
>            clk2MHz <= not clk2MHz ;
8
>            if clk2MHz then
9
>               clk1MHz <= not clk1MHz;
10
>            end if;
11
>         else
12
>            count2 <= count2 + 1;
13
>         end if;
14
>      end process;


Du hast geschieben:
1
if clk2MHz then
2
clk1MHz <= not clk1MHz;
3
end if;

Da fehlt doch eine Bedingung oder? Die If weiß doch gar nicht auf was
sie prüfen soll.

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


Lesenswert?

Sawyer M. schrieb:
> Er wirft immer noch Fehler.
Und zwar welchen?

> Da fehlt doch eine Bedingung oder?
> Die If weiß doch gar nicht auf was sie prüfen soll.
Kleiner "Fehler" zum Mitdenken...  ;-)
Schreib noch ='1' dazu und gib dem clk2MHz und dem clk2MHz auch einen 
Initwert.

: Bearbeitet durch Moderator
von Sawyer M. (sawyer_ma)


Angehängte Dateien:

Lesenswert?

Lothar M. schrieb:
> Sawyer M. schrieb:
>> Er wirft immer noch Fehler.
> Und zwar welchen?
>
>> Da fehlt doch eine Bedingung oder?
>> Die If weiß doch gar nicht auf was sie prüfen soll.
> Kleiner "Fehler" zum Mitdenken...  ;-)
> Schreib noch ='1' dazu und gib dem clk2MHz und dem clk2MHz auch einen
> Initwert.

Ok super dann habe ich das richtig erkannt. Das werde ich dann gleich 
umsetzen wenn der 2MHz läuft. :)

Die Fehler die ausgegeben werden sind für mich seltsam. Wie zum Beispiel

Warnung: [Synth 8-3331] design modulator has unconnected port clk

Die Errors sind im Bild zu erkennen.

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


Lesenswert?

Sawyer M. schrieb:
> Warnung: [Synth 8-3331] design modulator has unconnected port clk
Da wird letztendlich einfach alles wegoptimiert, weil du nichts 
verwendest, also keinen Ausgang hast, der etwas bewirken würde (das 
steht schon in der ersten Meldung "empty top module" und später bei 
"removed all").
Denn so wie es derzeit da steht, merkst du ausserhalb des FPGAs keinen 
Unterschied, ob das Design so implementiert wurde, wie du willst, oder 
ob da einfach gar nichts drin ist.

Kurz&knackig: du musst den clk1MHz und den clk2MHz auf OUT Ports legen.

: Bearbeitet durch Moderator
von Sawyer M. (sawyer_ma)


Lesenswert?

Lothar M. schrieb:
> Sawyer M. schrieb:
>> Warnung: [Synth 8-3331] design modulator has unconnected port clk
> Da wird letztendlich einfach alles wegoptimiert, weil du nichts
> verwendest, also keinen Ausgang hast, der etwas bewirken würde (das
> steht schon in der ersten Meldung "empty top module" und später bei
> "removed all").
> Denn so wie es derzeit da steht, merkst du ausserhalb des FPGAs keinen
> Unterschied, ob das Design so implementiert wurde, wie du willst, oder
> ob da einfach gar nichts drin ist.
>
> Kurz&knackig: du musst den clk1MHz und den clk2MHz auf OUT Ports legen.

Das Problem welches ich da habe ist:
1
entity zaehler is
2
    Port(
3
          clk         :   IN  STD_LOGIC;
4
          rst         :   IN  STD_LOGIC;
5
          clk_out1    :   OUT  unsigned
6
          
7
          
8
     );
9
end zaehler;       
10
11
architecture Behavioral of zaehler is
12
13
    signal clk1MHz    : std_logic;
14
    signal clk2MHz    : std_logic;
15
    signal count2     : unsigned (4 downto 0);
16
    signal rstsync    : unsigned(1 downto 0);
17
18
....
19
...
20
21
clk_out1 <= count2;
(Vollständiger Code weiter oben)


Fehlermeldung: [Synth 8-318] illegal unconstrained array declaration 
'clk_out1'

Klar ich versuche einen Vektor auf eine Variable abzubilden. Also ich 
vermute das ist der Fehler. Aber egal wie ich es versuche (std_logic, 
unsigned usw.) nichts funktioniert. Warum, wo, wie kann ich das 
verstehen und lernen?

: Bearbeitet durch User
von Achim S. (Gast)


Lesenswert?

Sawyer M. schrieb:
> Fehlermeldung: [Synth 8-318] illegal unconstrained array declaration
> 'clk_out1'

Die Fehlermeldung gibt ja schon einen guten Hinweis: clk_out1 ist vom 
Typ unsigned und damit ein Array-Typ. Du hast nicht angegeben, wie groß 
dieses Array sein soll (bei count2 hast du dagegen korrekt Arraygrenzen 
vorgegeben).

Aber warum willst du überhaupt den Count2 über clk_out1 als Ausgabewert 
verwenden? Eigentlich geht es dir doch darum, die Signale clk1MHz und 
clk2MHz als Ausgabewerte zu erzeugen.

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


Lesenswert?

Achim S. schrieb:
> Aber warum willst du überhaupt den Count2 über clk_out1 als Ausgabewert
> verwenden?
Hatte ich mich im Beitrag "Re: VHDL zwei CLK´s mit LFSR und 1:2 Teiler" 
auch schon gefragt...

Das ergibt für mich eher Sinn:
1
entity zaehler is
2
    Port(
3
      clk         :   IN  STD_LOGIC;
4
      rst         :   IN  STD_LOGIC;
5
      clk_out1    :   OUT  STD_LOGIC;
6
      clk_out2    :   OUT  STD_LOGIC;
7
     );
8
end zaehler;       
9
10
architecture Behavioral of zaehler is
11
    signal clk1MHz    : std_logic;
12
    signal clk2MHz    : std_logic;
13
:
14
:
15
    clk_out1 <= clk1MHz;
16
    clk_out2 <= clk2MHz;

von Josef G. (bome) Benutzerseite


Lesenswert?

Achim S. schrieb:
> Deine Ausgangssignale werden zwar mit 2MHz bzw. 1MHz hin und
> herschalten. Aber du solltest dir im Klaren darüber sein, dass das dann
> kein Taktsignal ist in dem Sinn, dass du damit eine Logik im FPGA
> vernünftig takten kannst. Es wird nicht von den Clock-Treibern des FPGAs
> auf dem Clock-Tree verteilt sondern ist ein normales Logiksignal.

Bei Spartan3, CycloneII/III/IV geht das aufschalten auf Clockleitungen
durchaus, siehe mein Projekt. Man muss nur im Clock-Report nachschauen,
ob die Synthese das von sich aus macht. Andernfalls kann man es durch
Instantierung eines Clockbuffers erzwingen.

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


Lesenswert?

Trotzdem wird die Toolchain irgendwas zum Thema "skew" ausgeben...

Beitrag #5394538 wurde vom Autor gelöscht.
von Achim S. (Gast)


Lesenswert?

Sawyer M. schrieb im Beitrag #5394538:
> Aber nichtsdestotrotz habe ich einen kleinen Fehler. Ich habe einen
> Versatz zwischen Clock und meinen Zähler Clocks von 100ps. Wenn das
> schon in der Simulation zum Vorschein kommt, will ich nicht wissen was
> in der Realität passiert. Ist das der böse Glitch?

Ne, das ist kein Glitch sondern das beschreibt einfach die Tatsache, 
dass von der Taktflanke am Eingang des Flipflops clk1MHZ_reg bis zum 
Umschalten von dessen Ausgang eine gewisse Zeit vergeht. Je nachdem, 
welche Art der Simulation du betreibst (Verhaltenssimu oder Timingsimu) 
wird dir ein Wert für diese Umschaltzeit angezeigt.

von Sawyer M. (sawyer_ma)


Lesenswert?

Josef G. schrieb:
> Achim S. schrieb:
>> Deine Ausgangssignale werden zwar mit 2MHz bzw. 1MHz hin und
>> herschalten. Aber du solltest dir im Klaren darüber sein, dass das dann
>> kein Taktsignal ist in dem Sinn, dass du damit eine Logik im FPGA
>> vernünftig takten kannst. Es wird nicht von den Clock-Treibern des FPGAs
>> auf dem Clock-Tree verteilt sondern ist ein normales Logiksignal.
>
> Bei Spartan3, CycloneII/III/IV geht das aufschalten auf Clockleitungen
> durchaus, siehe mein Projekt. Man muss nur im Clock-Report nachschauen,
> ob die Synthese das von sich aus macht. Andernfalls kann man es durch
> Instantierung eines Clockbuffers erzwingen.


Kann man mir das ein wenig genauer erklären? Also ich habe mein 2MHz und 
1MHz „Clock“ erzeugt. Aber Ihr meint das es kein richtiger Clock ist.

Habe ich das richtig verstanden?

Mit dem Thema Clock Tree bin ich nicht vertraut habe aber dieses 
Dokument gefunden.

https://www.xilinx.com/support/documentation/user_guides/ug472_7Series_Clocking.pdf

Jetzt nochmal die Frage an euch. Wenn ich aus einem 100MHz Clock einen 1 
und 2 MHz Clock generieren möchte darf ich das nicht mit Zählern machen? 
Wenn ja, wie macht man es dann? Gibt es kein Tool in Vivado wo ich sagen 
kann ich will diesen und diesen Clock?

von Achim S. (Gast)


Lesenswert?

Sawyer M. schrieb:
> Jetzt nochmal die Frage an euch. Wenn ich aus einem 100MHz Clock einen 1
> und 2 MHz Clock generieren möchte darf ich das nicht mit Zählern machen?
> Wenn ja, wie macht man es dann? Gibt es kein Tool in Vivado wo ich sagen
> kann ich will diesen und diesen Clock?

Eine häufig verwendete Methode ist es, alle Flip-Flops im Design mit dem 
identischen CLK zu versorgen (bei dir mit dem 100MHz Clock). Und für die 
Flip-Flops, die nur in jedem 50ten oder jedem 100ten Takt wirklich 
umschalten sollen erzeugt man mit dem Zähler ein Clock-Enable, dass nur 
in jedem 50ten (oder 100ten) Takt von Clk100MHz genau einen Taktzyklus 
lang aktiv ist.

Ansonsten bieten FPGAs auch dedizierte Hardwareblöcke, um Taktsignale zu 
"bearbeiten" (also z.B. die Frequenz zu ändern, oder die Phase zu 
schieben, oder ...) Je nach FPGA-Familie sind die etwas unterschiedlich 
aufgebaut (und heißen etwas unterschiedlich). In deinem Userguide 
findest du die Beschreibung in Kapitel 3 (MMCM und PLL)

von Sawyer M. (sawyer_ma)


Angehängte Dateien:

Lesenswert?

Ich hatte gehofft ich habe nun alle Fehler hinter mir gelassen jedoch 
ist es leider nicht so. Ich glaube ich nehme jedes Fettnäpfchen mit was 
man nur so mitnehmen kann als Anfänger.

Mein Code von der Main:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity modulator is
6
    Port(
7
          clk         :   IN  STD_LOGIC;
8
          rst         :   IN  STD_LOGIC;
9
          clk_out1    :   OUT STD_LOGIC;
10
          clk_out2    :   OUT STD_LOGIC
11
        );
12
13
end modulator;
14
15
architecture Behavioral of modulator is
16
    signal clk1MHz    : std_logic;
17
    signal clk2MHz    : std_logic;
18
    signal count2     : unsigned (4 downto 0);
19
    signal rstsync    : unsigned(1 downto 0);
20
--    signal datainsync : unsigned(1 downto 0);
21
22
begin
23
24
    process
25
    begin                   -- Einsynchronisieren des Resets
26
        wait until rising_edge(clk);
27
            rstsync <= rstsync(0) & rst;
28
--            datainsync <= datainsync(0) & data_in;
29
        end process;
30
31
     process(clk)
32
     begin
33
        if  rising_edge(clk) then
34
           if rst = '1' then
35
              count2 <= "00000";
36
              clk1MHz <= '0';
37
              clk2MHz <= '0';
38
           else
39
              if count2 = "11000" then
40
                 count2 <= "00000";
41
                 clk2MHz <= not clk2MHz;
42
                  if clk2MHz = '1' then
43
                     clk1MHz <= not clk1MHz;
44
                  end if;
45
              else
46
                 count2 <= count2 + 1;
47
              end if;
48
           end if;
49
        end if;
50
     end process;
51
     
52
    clk_out1 <= clk1MHz;
53
    clk_out2 <= clk2MHz;
54
55
end Behavioral;

Die Testbench:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity testbench is
6
--  Port ( );
7
end testbench;
8
9
architecture Behavioral of testbench is
10
11
COMPONENT modulator is
12
    Port( 
13
        clk         :   IN  STD_LOGIC;
14
        rst         :   IN  STD_LOGIC;
15
        clk_out1    :   OUT STD_LOGIC;
16
        clk_out2    :   OUT STD_LOGIC
17
        ); 
18
        
19
end COMPONENT;
20
21
--    signal data_in      :   STD_LOGIC := '0';
22
    signal clk          :   STD_LOGIC := '0';
23
    signal rst          :   STD_LOGIC := '0';
24
    signal clk_out1     :   STD_LOGIC := '0';
25
    signal clk_out2     :   STD_LOGIC := '0';
26
  
27
begin
28
    aand : modulator PORT MAP(
29
         clk      =>  clk,
30
         rst      =>  rst,
31
         clk_out2 =>  clk_out2
32
         );
33
34
    clk     <=  not clk after 5 ns;
35
    rst     <=  '1' AFTER 0ns, 
36
                '0' AFTER 5ns;
37
                
38
--    data_in <= not data_in after 2us;
39
40
end Behavioral;

Woher kommt dieser seltsame Fehler. Hatten den jemand schon einmal?

: Bearbeitet durch User
von Sawyer M. (sawyer_ma)


Angehängte Dateien:

Lesenswert?

Zur Ergänzung. Die Fehlermeldung ist weg. Das hatte intern etwas mit 
meinem RAM zu tun vom PC, da bei mir alles über eine virtuelle Maschine 
läuft. Das hat sich geklärt. Und funktioniert nun wieder perfekt.

Aber was sich nicht geklärt hat ist, warum mein Zähler nicht zählt. Ich 
habe nun mal Breakpoints gesetzt und Schritt für Schritt geschaut was 
passiert. Der Programmcode läuft alles korrekt ab aber der Vector von 
count2 wird nicht befüllt. Deshalb bleibt die Kurve bis in die Ewigkeit 
undefiniert. Was mache ich falsch. Das passt doch eigentlich soweit, 
oder?

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


Lesenswert?

Sawyer M. schrieb:
> Aber was sich nicht geklärt hat ist, warum mein Zähler nicht zählt.
Und noch viel, viel mehr: warum clk_out2 immer noch "uninitialized" 
ist!!!
Der wurde vermutlich einfach noch nicht zurückgesetzt, weil der Reset 
nicht lang genug anliegt. Und selbes dürfte auch für deinen Zähler 
gelten.

Denn wenn der Reset über 2 Flipflops einsynchronisiert wird, dann muss 
er auch mindestens 2 Takte lang anliegen...

Mein Tipp dazu: denk auch mal drüber nach, was du da geschrieben hast 
und analysiere die Waveform.

Und als Abhilfe schreib da mal besser sowas:
1
 rst     <=  '1' AFTER 0ns,
2
             '0' AFTER 50ns;

Sawyer M. schrieb:
> Deshalb bleibt die Kurve bis in die Ewigkeit undefiniert.
Achtung: 'U' bedeutet NICHT "undefiniert" sondern "uninitialisiert".
'U' ist der Defaultwert eines std_logic, wenn er noch keinen anderen 
Wert zugewiesen bekommen hat!
'X' bedeutet dagegen tatsächlich "undefiniert" oder besser 
"Zugriffskonflikt".

BTW: du solltest natürlich alle Ports deiner Komponente verdrahten...

: Bearbeitet durch Moderator
von Sawyer M. (sawyer_ma)


Lesenswert?

Lothar M. schrieb:
> Sawyer M. schrieb:
>> Aber was sich nicht geklärt hat ist, warum mein Zähler nicht zählt.
> Und noch viel, viel mehr: warum clk_out2 immer noch "uninitialized"
> ist!!!
> Der wurde vermutlich einfach noch nicht zurückgesetzt, weil der Reset
> nicht lang genug anliegt. Und selbes dürfte auch für deinen Zähler
> gelten.
>
> Denn wenn der Reset über 2 Flipflops einsynchronisiert wird, dann muss
> er auch mindestens 2 Takte lang anliegen...
>
> Mein Tipp dazu: denk auch mal drüber nach, was du da geschrieben hast
> und analysiere die Waveform.
>
> Und als Abhilfe schreib da mal besser sowas:
>
1
>  rst     <=  '1' AFTER 0ns,
2
>              '0' AFTER 50ns;
3
>


Das mit dem Reset hat aufgrund der längeren halte Dauer funktioniert 
aber leider nur für CLK_2MHz. CLK_1MHz hat noch andere Problem die ich 
irgendwo finden muss.

Aber klar du hast du vollkommen recht und das habe ich übersehen/ nicht 
darauf geachtet das mit den 2 Takten.


> Sawyer M. schrieb:
>> Deshalb bleibt die Kurve bis in die Ewigkeit undefiniert.
> Achtung: 'U' bedeutet NICHT "undefiniert" sondern "uninitialisiert".
> 'U' ist der Defaultwert eines std_logic, wenn er noch keinen anderen
> Wert zugewiesen bekommen hat!
> 'X' bedeutet dagegen tatsächlich "undefiniert" oder besser
> "Zugriffskonflikt".
>
> BTW: du solltest natürlich alle Ports deiner Komponente verdrahten...

Das mit alle Ports verdrahten verstehe ich aber nicht. Ich habe doch 
alle verwendet? Welche siehst du unverdrahtet? Meinst du in der 
Testbench?

von Josef G. (bome) Benutzerseite


Lesenswert?

Lothar M. schrieb:
> Trotzdem wird die Toolchain irgendwas zum Thema "skew" ausgeben...

Nein, bei mir nicht.

Der erzeugte Takt kommt ja an allen Flipflops gleichzeitig an,
weil er über das Clock-Leitungssystem verteilt wird.

Nur gegenüber der erzeugenden Flanke des Master-Clocks besteht
ein kleiner Zeitversatz, dessen genaue Größe unbekannt ist.
Das muss man halt im Auge behalten bei Übergängen
zwischen den Taktdomainen.

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


Lesenswert?

Sawyer M. schrieb:
> Welche siehst du unverdrahtet?
Den hier:
Sawyer M. schrieb:
> CLK_1MHz hat noch andere Problem die ich irgendwo finden muss.
Such dort:
Sawyer M. schrieb:
> aand : modulator PORT MAP(
>          clk      =>  clk,
>          rst      =>  rst,
>          clk_out2 =>  clk_out2
>          );

: Bearbeitet durch Moderator
von Da D. (dieter)


Lesenswert?

Sawyer M. schrieb:
> Josef G. schrieb irgendwas:
>> ...
>
> Kann man mir das ein wenig genauer erklären?

Klingt jetzt vielleicht gemein, soll dich aber nur vor Schaden bewahren: 
Josef ist auch kein FPGA Experte.

: Bearbeitet durch User
von Gustl B. (-gb-)


Lesenswert?

Aber er hat hier schon Recht. Wenn man den Takt mit einem FF teilt und 
wieder in ein Taktnetzwerk einspeist, dann ist das OK. Man hat einen 
Versatz zwischen dem ursprünglichen Takt und dem neuen Takt, aber wenn 
man das ordentlich behandelt passt das.

von Sawyer M. (sawyer_ma)


Lesenswert?

Der Taktversatz kommt durch die Laufzeit zusammen oder?

Ich habe ja versucht mein Reset auf den 100MHz einzusynchronisieren. So 
wie Lothar Miller das auf seiner Seite beschreibt.

http://www.lothar-miller.de/s9y/archives/41-Einsynchronisieren-von-asynchronen-Signalen.html

Jedoch wird dann in meiner Simulation nichts mehr ausgegeben. Woher 
kommt dieses Problem? Wenn ich anstatt rstsync in der Zeile
1
 if rstsync = 1
 mit rst vertausche geht es. Aber das ist ja nicht das Ziel da ich ja 
dann keinen einsynchronisierten Reset mehr habe. Des weiteren habe ich 
datainsync welcher auch synchronisiert werden müsste. Datainsync wird 
seriell eingespeist aber da habe ich das gleiche Problem.

Habe ich Lothar Miller falsch verstanden?

1
process
2
    begin                   -- Einsynchronisieren des Resets
3
        wait until rising_edge(clk);
4
            rstsync <= rstsync(0) & rst;
5
            datainsync <= datainsync(0) & data_in;
6
        end process;
7
8
     process(clk)
9
     begin
10
        if  rising_edge(clk) then
11
           if rstsync = 1 then
12
              count2 <= "00000";
13
              clk1MHz <= '0';
14
              clk2MHz <= '0';
15
           else
16
              if count2 = "11000" then
17
                 count2 <= "00000";
18
                 clk2MHz <= not clk2MHz;
19
                  if clk2MHz = '1' then
20
                     clk1MHz <= not clk1MHz;
21
                  end if;
22
              else
23
                 count2 <= count2 + 1;
24
              end if;
25
           end if;
26
        end if;
27
     end process;

Beste Grüße

: Bearbeitet durch User
von Achim S. (Gast)


Lesenswert?

Sawyer M. schrieb:
> Jedoch wird dann in meiner Simulation nichts mehr ausgegeben.

Es wird "nichts mehr ausgegeben"? Das glaube ich nicht. Was ich dir 
vielleicht schon glaube ist, dass deine Signale nie resettet werden und 
deshalb in der Simu immer nur etwas wie undefined oder uninitialized 
rauskommt.

Liest dir noch mal richtig durch, was die Idee beim Einsynchronisieren 
ist. MIt Lothars Code wird das externe Signal (das sich zu beliebigen 
Zeiten relativ zur Taktflanke ändern kann) in ein Schieberegister 
geschoben. Und die höheren Bits des Schieberegisters bekommen ihren 
Eingang von niederwertigen Bits des Schieberegisters - die sich nicht zu 
beliebigen Zeitpunkten sondern immer nur bei den Taktflanken ändern 
können.

Die höherwertigen Bits des Schieberegisters stellen also das 
einsynchronisierte Signal dar. Das wird in Lothars Code ausgewertet mit
 if (insr(1) = '1') then   -- Synchronisierten Eingang verwenden
Er testet also das höherwertige Bit des Schieberegisters.

In deinem Code steht dagegen:
         if rstsync = 1 then
Das heißt, du vergleichst das gesamte Schieberegister (vom Typ 
unsigned(1 downto 0) mit dem Integerwert 1. Kriegst du da keine Warnung, 
dass der Vergleich von unterschiedlichen Typen nie erfüllt sein kann 
(d.h. dass deine Signale nie resettet werden)?

Also: entweder
 if rstync(1)='1' then
oder ganz auf den Reset verzichten, und die Signale stattdessen passen 
initialisieren. (hat Lothar auch oben schon mal erwähnt)

    signal clk1MHz    : std_logic:='0';
    signal clk2MHz    : std_logic:='0';
    signal count2     : unsigned (4 downto 0):="00000";

von Michael W. (Gast)


Lesenswert?

Irgendwie riecht die Aufgabe und TE nach dem hier:
Beitrag "Select auf fallende und steigende Flanke"

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


Lesenswert?

Sawyer M. schrieb:
> rstsync <= rstsync(0) & rst;
:
>            if rstsync = 1 then
Das kann so aber nicht funktionieren. Ich würde vorschlagen, du beendest 
di Salamitaktik und postest den gesamten Code ab dem ersten use bis zum 
letzten Strichpunkt (am besten als angehängte *.vhdl Datei). Und dazu 
auch die Testbench. Und dann beschreibst du, was der Code deiner Meinung 
nach machen soll und was er stattdessen tut.

> Wenn ich anstatt rstsync in der Zeile  if rstsync = 1  mit rst
> vertausche geht es.
Richtig. Denk mal drüber nach. Welchen Datentyp hat rstsync? Und welcher 
Datentyp ist die Zahl 1? Welche Warnung wirft der Synthesizer ab? Und 
warum gibt das keinen Fehler? Welche Arithmetikbibliotheken hast du da 
eingebunden?

> if count2 = "11000" then
Wie gesagt: nimm Integer zum Zählen. Dann kann man das sofort menschlich 
lesen ohne im Binärsystem herumhampeln zu müssen.

> Habe ich Lothar Miller falsch verstanden?
Nein. Das Problem ist grundlegender: du "programmierst" und "probierst" 
da herum, statt einmal über die Meldungen nachzudenken...

: Bearbeitet durch Moderator
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.