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
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.
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.
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
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?
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.
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.
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... ;-)
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
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.NUMERIC_STD.ALL;
4
5
entityzaehleris
6
Port(
7
clk:INSTD_LOGIC;
8
rst:INSTD_LOGIC;
9
clk2:OUTunsigned
10
);
11
12
endzaehler;
13
14
15
architectureBehavioralofzaehleris
16
17
signalcount2:unsigned(5downto0);
18
signalrstsync:unsigned(1downto0);
19
20
begin
21
22
processbegin-- Einsynchronisieren des Resets
23
waituntilrising_edge(clk);
24
rstsync<=rstsync(0)&rst;
25
endprocess;
26
27
process(rstsync,clk)
28
begin
29
ifrstsync=1orcount2="011000"then
30
count2<="000000";
31
elsifrising_edge(clk)then
32
count2<=count2+1;
33
endif;
34
endprocess;
35
36
endBehavioral;
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...
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
ifrising_edge(clk)then
4
ifrstsync=1then
5
count2<="00000";
6
clk2MHz<='0';
7
else
8
ifcount2="11000"then
9
count2<="00000";
10
clk2MHz<=notclk2MHz;
11
else
12
count2<=count2+1;
13
endif;
14
endif;
15
endif;
16
endprocess;
(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.
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
signalcount2:integerrange0to24:=0;
2
3
4
process(clk)
5
begin
6
ifrising_edge(clk)then
7
ifcount2=24then
8
count2<=0;
9
clk2MHz<=notclk2MHz;
10
else
11
count2<=count2+1;
12
endif;
13
endif;
14
endprocess;
Oder gleich so und den 1MHz "Takt" nebenher miterzeugt:
1
signalcount2:integerrange0to24:=0;
2
3
4
processbegin
5
waituntilrising_edge(clk);
6
ifcount2=24then
7
count2<=0;
8
clk2MHz<=notclk2MHz;
9
ifclk2MHzthen
10
clk1MHz<=notclk1MHz;
11
endif;
12
else
13
count2<=count2+1;
14
endif;
15
endprocess;
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.
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
signalcount2:integerrange0to24:=0;
2
>
3
>processbegin
4
>waituntilrising_edge(clk);
5
>ifcount2=24then
6
>count2<=0;
7
>clk2MHz<=notclk2MHz;
8
>ifclk2MHzthen
9
>clk1MHz<=notclk1MHz;
10
>endif;
11
>else
12
>count2<=count2+1;
13
>endif;
14
>endprocess;
Du hast geschieben:
1
ifclk2MHzthen
2
clk1MHz<=notclk1MHz;
3
endif;
Da fehlt doch eine Bedingung oder? Die If weiß doch gar nicht auf was
sie prüfen soll.
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.
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.
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.
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
entityzaehleris
2
Port(
3
clk:INSTD_LOGIC;
4
rst:INSTD_LOGIC;
5
clk_out1:OUTunsigned
6
7
8
);
9
endzaehler;
10
11
architectureBehavioralofzaehleris
12
13
signalclk1MHz:std_logic;
14
signalclk2MHz:std_logic;
15
signalcount2:unsigned(4downto0);
16
signalrstsync:unsigned(1downto0);
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?
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.
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.
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.
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?
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)
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
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.NUMERIC_STD.ALL;
4
5
entitymodulatoris
6
Port(
7
clk:INSTD_LOGIC;
8
rst:INSTD_LOGIC;
9
clk_out1:OUTSTD_LOGIC;
10
clk_out2:OUTSTD_LOGIC
11
);
12
13
endmodulator;
14
15
architectureBehavioralofmodulatoris
16
signalclk1MHz:std_logic;
17
signalclk2MHz:std_logic;
18
signalcount2:unsigned(4downto0);
19
signalrstsync:unsigned(1downto0);
20
-- signal datainsync : unsigned(1 downto 0);
21
22
begin
23
24
process
25
begin-- Einsynchronisieren des Resets
26
waituntilrising_edge(clk);
27
rstsync<=rstsync(0)&rst;
28
-- datainsync <= datainsync(0) & data_in;
29
endprocess;
30
31
process(clk)
32
begin
33
ifrising_edge(clk)then
34
ifrst='1'then
35
count2<="00000";
36
clk1MHz<='0';
37
clk2MHz<='0';
38
else
39
ifcount2="11000"then
40
count2<="00000";
41
clk2MHz<=notclk2MHz;
42
ifclk2MHz='1'then
43
clk1MHz<=notclk1MHz;
44
endif;
45
else
46
count2<=count2+1;
47
endif;
48
endif;
49
endif;
50
endprocess;
51
52
clk_out1<=clk1MHz;
53
clk_out2<=clk2MHz;
54
55
endBehavioral;
Die Testbench:
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
useIEEE.NUMERIC_STD.ALL;
4
5
entitytestbenchis
6
-- Port ( );
7
endtestbench;
8
9
architectureBehavioraloftestbenchis
10
11
COMPONENTmodulatoris
12
Port(
13
clk:INSTD_LOGIC;
14
rst:INSTD_LOGIC;
15
clk_out1:OUTSTD_LOGIC;
16
clk_out2:OUTSTD_LOGIC
17
);
18
19
endCOMPONENT;
20
21
-- signal data_in : STD_LOGIC := '0';
22
signalclk:STD_LOGIC:='0';
23
signalrst:STD_LOGIC:='0';
24
signalclk_out1:STD_LOGIC:='0';
25
signalclk_out2:STD_LOGIC:='0';
26
27
begin
28
aand:modulatorPORTMAP(
29
clk=>clk,
30
rst=>rst,
31
clk_out2=>clk_out2
32
);
33
34
clk<=notclkafter5ns;
35
rst<='1'AFTER0ns,
36
'0'AFTER5ns;
37
38
-- data_in <= not data_in after 2us;
39
40
endBehavioral;
Woher kommt dieser seltsame Fehler. Hatten den jemand schon einmal?
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?
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'AFTER0ns,
2
'0'AFTER50ns;
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...
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'AFTER0ns,
2
>'0'AFTER50ns;
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?
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.
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> );
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.
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.
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
ifrstsync=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?
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";
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...