mikrocontroller.net

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


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Sawyer M. (sawyer_ma)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Achim S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Achim S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ups: da war ich mit meiner Antwort wohl zu spät dran.

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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... 
;-)

Autor: ~Mercedes~ (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Sawyer M. (sawyer_ma)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.
Autor: Sawyer M. (sawyer_ma)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Sawyer M. (sawyer_ma)
Datum:

Bewertung
0 lesenswert
nicht 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.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity zaehler is
    Port(
          clk    :   IN  STD_LOGIC;
          rst    :   IN  STD_LOGIC;
          clk2   :   OUT unsigned
     );
         
end zaehler;


architecture Behavioral of zaehler is

    signal count2    : unsigned (5 downto 0);
    signal rstsync   : unsigned(1 downto 0);
    
begin    

    process begin                   -- Einsynchronisieren des Resets
        wait until rising_edge(clk);
            rstsync <= rstsync(0) & rst;
        end process;   

     process(rstsync, clk)
        begin 
        if  rstsync = 1 or count2 = "011000" then
            count2 <= "000000";
        elsif rising_edge(clk) then
            count2 <= count2 + 1;
        end if;
     end process;   
                                                       
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
Autor: Achim S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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:
     process(clk)
     begin 
        if  rising_edge(clk) then
           if rstsync = 1 then
              count2 <= "00000";
              clk2MHz <= '0';           
           else
              if count2 = "11000" then
                 count2 <= "00000";
                 clk2MHz <= not clk2MHz ;
              else
                 count2 <= count2 + 1;
              end if;  
           end if;
        end if;
     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
Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
     signal count2 : integer range 0 to 24 := 0;


     process(clk)
     begin 
        if  rising_edge(clk) then
           if count2 = 24 then
             count2 <= 0;
             clk2MHz <= not clk2MHz ;
           else
             count2 <= count2 + 1;
           end if;
        end if;
     end process; 
     

Oder gleich so und den 1MHz "Takt" nebenher miterzeugt:
     signal count2 : integer range 0 to 24 := 0;


     process begin 
        wait until rising_edge(clk);
        if count2 = 24 then
           count2 <= 0;
           clk2MHz <= not clk2MHz ;
           if clk2MHz then
              clk1MHz <= not clk1MHz;
           end if;
        else
           count2 <= count2 + 1;
        end if;
     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.
Autor: Sawyer M. (sawyer_ma)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
>
signal count2 : integer range 0 to 24 := 0;
> 
>      process begin
>         wait until rising_edge(clk);
>         if count2 = 24 then
>            count2 <= 0;
>            clk2MHz <= not clk2MHz ;
>            if clk2MHz then
>               clk1MHz <= not clk1MHz;
>            end if;
>         else
>            count2 <= count2 + 1;
>         end if;
>      end process; 


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

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

: Bearbeitet durch User
Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Sawyer M. (sawyer_ma)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Sawyer M. (sawyer_ma)
Datum:

Bewertung
0 lesenswert
nicht 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:
entity zaehler is
    Port(
          clk         :   IN  STD_LOGIC;
          rst         :   IN  STD_LOGIC;
          clk_out1    :   OUT  unsigned
          
          
     );
end zaehler;       

architecture Behavioral of zaehler is

    signal clk1MHz    : std_logic;
    signal clk2MHz    : std_logic;
    signal count2     : unsigned (4 downto 0);
    signal rstsync    : unsigned(1 downto 0);

....
...

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
Autor: Achim S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
entity zaehler is
    Port(
      clk         :   IN  STD_LOGIC;
      rst         :   IN  STD_LOGIC;
      clk_out1    :   OUT  STD_LOGIC;
      clk_out2    :   OUT  STD_LOGIC;
     );
end zaehler;       

architecture Behavioral of zaehler is
    signal clk1MHz    : std_logic;
    signal clk2MHz    : std_logic;
:
:
    clk_out1 <= clk1MHz;
    clk_out2 <= clk2MHz;

Autor: Josef G. (bome) Benutzerseite
Datum:

Bewertung
-1 lesenswert
nicht 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.

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Trotzdem wird die Toolchain irgendwas zum Thema "skew" ausgeben...

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

Bewertung
0 lesenswert
nicht 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.

Autor: Sawyer M. (sawyer_ma)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Achim S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Sawyer M. (sawyer_ma)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity modulator is
    Port(
          clk         :   IN  STD_LOGIC;
          rst         :   IN  STD_LOGIC;
          clk_out1    :   OUT STD_LOGIC;
          clk_out2    :   OUT STD_LOGIC
        );

end modulator;

architecture Behavioral of modulator is
    signal clk1MHz    : std_logic;
    signal clk2MHz    : std_logic;
    signal count2     : unsigned (4 downto 0);
    signal rstsync    : unsigned(1 downto 0);
--    signal datainsync : unsigned(1 downto 0);

begin

    process
    begin                   -- Einsynchronisieren des Resets
        wait until rising_edge(clk);
            rstsync <= rstsync(0) & rst;
--            datainsync <= datainsync(0) & data_in;
        end process;

     process(clk)
     begin
        if  rising_edge(clk) then
           if rst = '1' then
              count2 <= "00000";
              clk1MHz <= '0';
              clk2MHz <= '0';
           else
              if count2 = "11000" then
                 count2 <= "00000";
                 clk2MHz <= not clk2MHz;
                  if clk2MHz = '1' then
                     clk1MHz <= not clk1MHz;
                  end if;
              else
                 count2 <= count2 + 1;
              end if;
           end if;
        end if;
     end process;
     
    clk_out1 <= clk1MHz;
    clk_out2 <= clk2MHz;

end Behavioral;

Die Testbench:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity testbench is
--  Port ( );
end testbench;

architecture Behavioral of testbench is

COMPONENT modulator is
    Port( 
        clk         :   IN  STD_LOGIC;
        rst         :   IN  STD_LOGIC;
        clk_out1    :   OUT STD_LOGIC;
        clk_out2    :   OUT STD_LOGIC
        ); 
        
end COMPONENT;

--    signal data_in      :   STD_LOGIC := '0';
    signal clk          :   STD_LOGIC := '0';
    signal rst          :   STD_LOGIC := '0';
    signal clk_out1     :   STD_LOGIC := '0';
    signal clk_out2     :   STD_LOGIC := '0';
  
begin
    aand : modulator PORT MAP(
         clk      =>  clk,
         rst      =>  rst,
         clk_out2 =>  clk_out2
         );

    clk     <=  not clk after 5 ns;
    rst     <=  '1' AFTER 0ns, 
                '0' AFTER 5ns;
                
--    data_in <= not data_in after 2us;

end Behavioral;

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

: Bearbeitet durch User
Autor: Sawyer M. (sawyer_ma)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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?

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
 rst     <=  '1' AFTER 0ns,
             '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
Autor: Sawyer M. (sawyer_ma)
Datum:

Bewertung
0 lesenswert
nicht 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:
>
>  rst     <=  '1' AFTER 0ns,
>              '0' AFTER 50ns;
> 


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?

Autor: Josef G. (bome) Benutzerseite
Datum:

Bewertung
-1 lesenswert
nicht 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.

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Da D. (dieter)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Gustl B. (-gb-)
Datum:

Bewertung
-1 lesenswert
nicht 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.

Autor: Sawyer M. (sawyer_ma)
Datum:

Bewertung
0 lesenswert
nicht 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
 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?

process
    begin                   -- Einsynchronisieren des Resets
        wait until rising_edge(clk);
            rstsync <= rstsync(0) & rst;
            datainsync <= datainsync(0) & data_in;
        end process;

     process(clk)
     begin
        if  rising_edge(clk) then
           if rstsync = 1 then
              count2 <= "00000";
              clk1MHz <= '0';
              clk2MHz <= '0';
           else
              if count2 = "11000" then
                 count2 <= "00000";
                 clk2MHz <= not clk2MHz;
                  if clk2MHz = '1' then
                     clk1MHz <= not clk1MHz;
                  end if;
              else
                 count2 <= count2 + 1;
              end if;
           end if;
        end if;
     end process;

Beste Grüße

: Bearbeitet durch User
Autor: Achim S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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";

Autor: M. W. (elektrowagi78) Benutzerseite
Datum:

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

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht 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

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.