Hallo, erstmal sorry für den dürftigen Threadnamen, nur mir viel nix besseres dazu ein. Ich habe folgendes Problem, ich muss eine PLL mit 24 Bit initialisieren und dazu CLK, DATA und STROBE entsprechend ansteuern, also immer DATA anlegen, t_setup warten, CLK hochziehen, t_hold warten, CLK runter und wieder von vorne, anschließend nach der letzten CLK noch STROBE für eine entsprechende Zeit hochziehen um die Daten zu übernehmen. Ich war schon wieder dabei eine FSM dafür zu bauen als ich mir überlegt habe ob es nicht auch einfacher (ohne Unmengen an Text zu schreiben) geht. Dann hatte ich die Idee das Ganze mit einem getakteten Prozess (Statements hintereinander mit wait until rising_edge; leider auch viel Geschreibsel) oder einen Counter (wo ich auf das Setzen bestimmter Bitmuster reagiere) zu machen. Darum meine Frage, wie würdet Ihr das machen, oder eventuell noch ne Idee die ich übersehen hab und einfacher ist?
Tim T. schrieb: > Dann hatte ich die Idee das Ganze mit einem getakteten Prozess > (Statements hintereinander mit wait until rising_edge; leider auch viel > Geschreibsel) Mehrere wait until rising_edge in einem Prozess wird dein Sythesizer nicht unterstützen. Tim T. schrieb: > oder einen Counter (wo ich auf das Setzen bestimmter > Bitmuster reagiere) zu machen. Das ist auch eine FSM, nur mit Zählerwerten als Zustandsnamen. Tim T. schrieb: > wie würdet Ihr das machen FSM. Wieviel "Geschreibsel" das ist, hängt davon ab, was deine FSM macht bzw. wie geschickt du es implementierst.
VHDL hotline schrieb im Beitrag #6138587: > Mehrere wait until rising_edge in einem Prozess wird dein Sythesizer > nicht unterstützen. Kommt auf den Synthesizer und die Aufgabe an. Im Prinzip ging das mit ISE schon vor 10 Jahren: http://www.lothar-miller.de/s9y/archives/47-wait-im-Prozess.html Tim T. schrieb: > oder einen Counter (wo ich auf das Setzen bestimmter Bitmuster reagiere) > zu machen. Dein "Counter (wo du auf das Setzen bestimmter Bitmuster wartest)" ist im Prinzip auch nur eine längere Schreibweise für "FSM". Also kannst du es auch gleich mit einer FSM machen, die die nötigen Zustände und Pegelwechsel so abhandelt, dass es auch nach einem halben Jahr noch jeder versteht. Sieh dir mal die SPI-Schnitte als Grundlage an: http://www.lothar-miller.de/s9y/categories/45-SPI-Master Das Modell dort so abgespeckt, dass nur dein "Modus" abgehandelt wird, und du bist fertig.
Lothar M. schrieb: > VHDL hotline schrieb im Beitrag #6138587: >> Mehrere wait until rising_edge in einem Prozess wird dein Sythesizer >> nicht unterstützen. > Kommt auf den Synthesizer und die Aufgabe an. Im Prinzip ging das mit > ISE schon vor 10 Jahren: > http://www.lothar-miller.de/s9y/archives/47-wait-im-Prozess.html Stimmt, die Seite hab ich irgendwann schon mal gesehen^^ > Tim T. schrieb: >> oder einen Counter (wo ich auf das Setzen bestimmter Bitmuster reagiere) >> zu machen. > Dein "Counter (wo du auf das Setzen bestimmter Bitmuster wartest)" ist > im Prinzip auch nur eine längere Schreibweise für "FSM". Also kannst du Das es alles irgendeine Art FSM ist, ist mir schon klar, dachte nur als Counter wäre es weniger zu Texten. > es auch gleich mit einer FSM machen, die die nötigen Zustände und > Pegelwechsel so abhandelt, dass es auch nach einem halben Jahr noch > jeder versteht. Glaube dass ist das Killerargument, ich hab oft schon am nächsten Morgen Probleme mit sowas... > Sieh dir mal die SPI-Schnitte als Grundlage an: > http://www.lothar-miller.de/s9y/categories/45-SPI-Master > Das Modell dort so abgespeckt, dass nur dein "Modus" abgehandelt wird, > und du bist fertig. Habs jetzt erstmal so gelöst, muss mir nur noch was für den Reset überlegen:
1 | InitPLL : process(clk_100mhz) |
2 | begin
|
3 | if (rising_edge(clk_100mhz)) then |
4 | |
5 | case state is |
6 | when start => idt_sclk <= '0'; |
7 | idt_data <= '0'; |
8 | idt_strobe <= '0'; |
9 | i <= 23; |
10 | state <= setup; |
11 | |
12 | when setup => idt_sclk <= '0'; |
13 | idt_data <= idt_config(i); |
14 | state <= hold; |
15 | |
16 | when hold => idt_sclk <= '1'; |
17 | if (i = 0) then |
18 | state <= strobe1; |
19 | else
|
20 | i <= i - 1; |
21 | state <= setup; |
22 | end if; |
23 | |
24 | when strobe1 => idt_sclk <= '0'; |
25 | idt_data <= '0'; |
26 | idt_strobe <= '1'; |
27 | state <= strobe2; |
28 | |
29 | when strobe2 => state <= strobe3; |
30 | |
31 | when strobe3 => state <= strobe4; |
32 | |
33 | when strobe4 => state <= done; |
34 | |
35 | when done => idt_strobe <= '0'; |
36 | state <= done; |
37 | |
38 | end case; |
39 | |
40 | end if; |
41 | end process; |
Tim T. schrieb: > CLK, DATA und STROBE entsprechend ansteuern, > also immer DATA anlegen, t_setup warten, CLK hochziehen, t_hold warten, > CLK runter und wieder von vorne, anschließend nach der letzten CLK noch > STROBE für eine entsprechende Zeit hochziehen um die Daten zu > übernehmen. Das kling für mich sehr nach einem einfachen Schieberegister mit zusätzlichem Latch wie das SN74HC595. Ich hänge hier mal Code ran der 8 Bits überträgt und dann einen Puls für das Latch ausgibt. Das kannst du sehr wahrscheinlich einfach anpassen.
Gustl B. schrieb: > Tim T. schrieb: >> CLK, DATA und STROBE entsprechend ansteuern, >> also immer DATA anlegen, t_setup warten, CLK hochziehen, t_hold warten, >> CLK runter und wieder von vorne, anschließend nach der letzten CLK noch >> STROBE für eine entsprechende Zeit hochziehen um die Daten zu >> übernehmen. > > Das kling für mich sehr nach einem einfachen Schieberegister mit > zusätzlichem Latch wie das SN74HC595. Jop, dürften 3 Schieberegister hintereinander mit Latch sein. > Ich hänge hier mal Code ran der 8 Bits überträgt und dann einen Puls für > das Latch ausgibt. Das kannst du sehr wahrscheinlich einfach anpassen. Genau sowas ging mir als Counter Variante durch den Kopf, aber stimmt schon die Lesbarkeit leidet da etwas...
:
Bearbeitet durch User
VHDL hotline schrieb im Beitrag #6138587: > Tim T. schrieb: >> wie würdet Ihr das machen > > FSM. Wieviel "Geschreibsel" das ist, hängt davon ab, was deine FSM macht > bzw. wie geschickt du es implementierst. Einen Editor benutzen, der einem beim Schreiben von VHDL unterstützt, damit das meiste von diesem "Geschreibsel" der Editor einfügt und nicht von dir getippt werden muss. Mein persönlicher Favorit ist immer noch der VHDL Modus von Emacs, aber es gibt noch andere Editoren, die einem anständig unterstützen können (Die Editoren die mit den EDA Tools mitkommen sind alle schlecht, wohl weil kein Entwickler bei diesen Firmen diese nutzen würden).
Tim T. schrieb: > Habs jetzt erstmal so gelöst, muss mir nur noch was für den Reset > überlegen: Wow, das war jetzt ja echt viel Geschreibsel... ;-) . Falls du einen Xilinx-FPGA verwendest und die FSM nur einmal beim FPGA-Start laufen soll, kannst du den Resetzustand der FSM gleich in die Signaldeklaration schreiben, also
1 | signal state : t_state := start; |
Deine strobe-Zustände am Ende kannst du sinnvollerweise auch mit einem Zähler zusammenfassen, wie vorher beim hold.
VHDL hotline schrieb im Beitrag #6138733: > Tim T. schrieb: >> Habs jetzt erstmal so gelöst, muss mir nur noch was für den Reset >> überlegen: > > Wow, das war jetzt ja echt viel Geschreibsel... ;-) . Ging mir allgemein darum wie man das am besten angeht, zugegeben hier wars diesmal nicht so schwer wobei ich mir immernoch was für einen sinnvollen Reset überlegen muss. > > Falls du einen Xilinx-FPGA verwendest und die FSM nur einmal beim > FPGA-Start laufen soll, kannst du den Resetzustand der FSM gleich in die > Signaldeklaration schreiben, also > >
1 | > signal state : t_state := start; |
2 | >
|
Ist bekannt und auch so im Source, aber ganz so einfach ist es hierbei nicht, wollte schon zwischendurch einen Reset auslösen können. > > Deine strobe-Zustände am Ende kannst du sinnvollerweise auch mit einem > Zähler zusammenfassen, wie vorher beim hold. Da es nur 4 Clocks waren, fand ich es so einfacher, aber sonst ja.
Was soll der Reset denn überhaupt machen? Ich könnte mir vorstellen, dass der Reset einen definierten Defaultwert ausgibt und in die PLL schreibt. Aber dazu braucht man doch keinen Reset in dieser Komponente sondern übergibt ihr einfach den auszugebenden Defaultwert. Ich sehe da keinen Grund für einen Reset.
Tim T. schrieb: > wobei ich mir immernoch was für einen > sinnvollen Reset überlegen muss. Tim T. schrieb:
1 | > when done => idt_strobe <= '0'; |
2 | > state <= done; |
3 | if (reset = 1) then |
4 | state <= start; |
5 | end if; |
Vielleicht so? Wobei Gustl B. ja schon geschrieben hat, dass die Resetfunktion nicht so richtig klar ist.
VHDL hotline schrieb im Beitrag #6138766: > Tim T. schrieb: >> wobei ich mir immernoch was für einen >> sinnvollen Reset überlegen muss. > > Tim T. schrieb: > >
1 | >> when done => idt_strobe <= '0'; |
2 | >> state <= done; |
3 | > if (reset = 1) then |
4 | > state <= start; |
5 | > end if; |
6 | >
|
> > Vielleicht so? Wobei Gustl B. ja schon geschrieben hat, dass die > Resetfunktion nicht so richtig klar ist. Wenn ich mich darauf beschränke das der Reset nur ausgelöst werden darf wenn die Initialisierung druch ist, dann ja, einsynchronisiert ist der Reset eh, aber was mache ich wenn es einen Grund für einen Reset gibt bevor das Ding fertig initialisiert ist? Das Zweite ist, wie reagiert die PLL darauf wenn während der Initialiserung einfach nochmal von vorne angefangen wird, leider schweigt sich das Datenblatt dazu aus, ich gehe aber einfach mal von einem 24 Bit Schieberegister aus, wo die Bits des ersten Teilinitialisierung einfach hinten Rausfallen und dann die neuen Daten gelatcht werden. Ein gezieltes Reset über einen dedizierten Pin ist leider nicht möglich, der entsprechende Pin der PLL ist nicht zum FPGA geführt.
Tim T. schrieb: > wollte schon zwischendurch einen Reset auslösen können. Was soll der Reset bewirken? Woher kommt der Reset? Was passiert sonst noch bei dem Reset? Kannst du statt eines Resets nicht einfach das FPGA neu laden? Tim T. schrieb: > leider schweigt sich das Datenblatt dazu aus Leider wissen wir nicht, welches Datenblatt du meinst. Ausser, dass es wahrscheinlich eine PLL von IDT ist...
:
Bearbeitet durch Moderator
Lothar M. schrieb: > Tim T. schrieb: >> wollte schon zwischendurch einen Reset auslösen können. > Was soll der Reset bewirken? Woher kommt der Reset? Was passiert sonst > noch bei dem Reset? Kannst du statt eines Resets nicht einfach das FPGA > neu laden? Hauptgrund (eigentlich der Einzige) für einen Reset könnte ein Fehler auf einer der Versorgungsspannungen sein, die werden kontinuierlich getestet und melden das dem FPGA, der daraufhin eine entsprechende Behandlung ausführt. Im Zweifelsfall wird auch der FPGA neu geladen, ja aber nicht unbedingt bei allen Fehlern, nur wenn die FPGA Versorgung betroffen ist, aber dann ist es eh egal.
Lothar M. schrieb: > Tim T. schrieb: >> leider schweigt sich das Datenblatt dazu aus > Leider wissen wir nicht, welches Datenblatt du meinst. Ausser, dass es > wahrscheinlich eine PLL von IDT ist... ICS307M-02LF von IDT https://www.idt.com/document/dst/307-02-datasheet OK, in dem Datenblatt steht auch der entscheidende Satz: "The ICS307 can be reprogrammed at any time during operation."
:
Bearbeitet durch User
Über #PDTS könntest du den Chip selbst doch auch resetten wenn ich das richtig sehe?!
Gustl B. schrieb: > Über #PDTS könntest du den Chip selbst doch auch resetten wenn ich das > richtig sehe?! Das ist eine Gute Frage, egal wie oft ich den 2. Satz über den Powerdown auch lese, ich komme einfach nicht dahinter was er eigentlich sagen will... Satz 1: "When the PDTS pin is pulled low, the chip will enter the power-down mode, where the output clocks are tri-stated and the rest of the chip is powered down." Satz 2: "The chip can be programmed during power-down mode, however, if the chip is programmed during operation and enters power-down mode, the registers will return to their settings and not reset when exiting power-down mode (PDTS pin is pulled high)." Wobei ich mittlerweile eine Tendenz dazu hab, das der Chip nach dem Powerdown wieder die vorherigen Werte annimmt und nicht resettet wird, aber sicher bin ich mir da nicht. Aber unabhängig davon ist der PDTS auch nicht am FPGA, also eigentlich auch egal.
:
Bearbeitet durch User
Du hast Recht, das ist wirklich kein Reset. Also bleibt dir nur als "Reset" die Defaultwerte hineinzuschreiben.
Tim T. schrieb: > ich gehe aber einfach mal von einem 24 Bit Schieberegister aus, wo die > Bits des ersten Teilinitialisierung einfach hinten Rausfallen und dann > die neuen Daten gelatcht werden. Es werden die zuletzt eingeschobenen 24 Bit gelatcht. Die "Note" im "Programming Example" zeigt das dann auch an:
1 | As show in Figure 2, after these 24 bits are clocked into the ICS307-02, taking STROBE high will send this data to the internal latch and the CLK output will lock within 10 ms. |
2 | |
3 | Note: If STROBE is in the high state and SCLK is pulsed, DATA is clocked directly to the internal latch... |
Es gibt ein SCLK-taktgesteuertes Schieberegister und ein pegelabhängiges STROBE-Latch. Im Schieberegister werden einfach die Daten durchgeschoben. Wenn STROBE während des Schiebens aktiv ist, ist das Latch transparent und jedes Bit bringt neue Überraschungen.
Lothar M. schrieb: > Tim T. schrieb: >> ich gehe aber einfach mal von einem 24 Bit Schieberegister aus, wo die >> Bits des ersten Teilinitialisierung einfach hinten Rausfallen und dann >> die neuen Daten gelatcht werden. > Es werden die zuletzt eingeschobenen 24 Bit gelatcht. Die "Note" im > "Programming Example" zeigt das dann auch an: >
1 | > As show in Figure 2, after these 24 bits are clocked into the ICS307-02, |
2 | > taking STROBE high will send this data to the internal latch and the CLK |
3 | > output will lock within 10 ms. |
4 | > |
5 | > Note: If STROBE is in the high state and SCLK is pulsed, DATA is clocked |
6 | > directly to the internal latch... |
7 | > |
> Es gibt ein SCLK-taktgesteuertes Schieberegister und ein pegelabhängiges > STROBE-Latch. Im Schieberegister werden einfach die Daten > durchgeschoben. Wenn STROBE während des Schiebens aktiv ist, ist das > Latch transparent und jedes Bit bringt neue Überraschungen. Ja, den Teil hatte ich auch gesehen (und das Bild vom Block Diagram), daher auch die Idee das einfach immer die letzten 24 Bit vor dem Strobe übernommen werden könnten. Manchmal gehen die Amerikaner mir mit ihrer unpräzisen Ausdrucksweise schon auf den Wecker... Hätten ja auch einfach schreiben können das die letzten 24 in den Chip getakteten Bits beim Strobe übernommen werden, evtl. mit dem Hinweis das wenn weniger als 24 Bits in den Chip getaktet wurden die fehlenden Bitstellen im Schieberegister mit undefiniertem Müll gefüllt sind. Also werde ich jetzt in jeden State wohl einfach ne Reset Abfrage machen und dann jeweils zum Start State verzweigen, wobei das natürlich wieder genau die Art vom stupidem rumtexten ist, die ich gerne vermeiden würde. Oder hat jemand dazu noch ne elegantere Idee?
Tim T. schrieb: > Also werde ich jetzt in jeden State wohl einfach ne Reset Abfrage machen Ich würde das Verhalten von Signalen in Prozessen vorteilhaft anwenden und es basierend auf deinem Code einfach so machen:
1 | InitPLL : process(clk_100mhz) |
2 | begin
|
3 | if (rising_edge(clk_100mhz)) then |
4 | |
5 | case state is |
6 | :
|
7 | :
|
8 | end case; |
9 | |
10 | if reset = '1' then -- letzte Zuweisung "gewinnt" |
11 | state <= start; |
12 | end if; |
13 | |
14 | end if; |
15 | end process; |
:
Bearbeitet durch Moderator
Oh man, klar wieder total das Brett vorm Kopf gehabt. Danke Dir Und im übrigen auch den Anderen hier im Thread, insbesondere auch die Lösung mit dem Zähler von Gustl B. werde ich mir bei Gelegenheit mal genauer anschauen.
:
Bearbeitet durch User
Die Idee mit dem Zähler ist Folgende: Der Zähler(n-1 downto 0) ist n Bits lang. Und zählt nach oben. Jetzt werden die obersten Zähler(n-1 downto n-X) Bits als Adresse für das auszugebende Bit, und das Bit Zählers(n-X-1) als "Takt" verwendet. Die Bits Zähler(n-X-2 downto 0) sind dann noch übrig und dienen als Taktteiler. Dann kann man den Zähler schön bequem mit Systemtakt betreiben und bekommt trotzdem einen deutlich niedrigeren Takt für das Schieberegister. Beispiel: Du willst 24 Bits ausgeben. Das sind also schon 5 Bits für die Adresse. Dann das eine Bit für den Takt. Und dann haben wir jetzt als Beispiel 100 MHz Systemtakt und wollen aber nur maximal 8 MHz Takt für das Schieberegister. Das bedeutet wir teilen die 100 durch 8, bekommen 12,5 und nehmen die nächste Zweierpotenz, 16, das sind 4 Bits. Das 4. Bit vom LSB aus ist also der neue Takt (das sind dann 6,25 MHz) und die 3 niederwertigsten Bits sind die Taktteiler. Der Zähler muss insgesamt mindestens 5+4=9 Bits lang sein. Es bietet sich an einen Alias für die Adresse zu verwenden und intern ein Register das bei einem Startsignal den Inhalt überreicht bekommt. Da der Zähler bei mir nach oben zählt, aber das MSB zuerst ausgegeben werden soll, habe ich intern das TX_Reg als ein 0 to 23 beschrieben. Zusätzlich gibt es noch ein Ready als Ausgang der sagt wann fertiggeschoben ist. Das gibt es jetzt hier als Anhang, es wird nach 200 ns für einen Takt lang Start auf '1' gesetzt und die Daten x"ABCDEF" übergeben. Danach wird herausgeschoben und am Ende einmal das Latch gepulst. Damit man auch beobachten kann was passiert gibt es mehrere Bausteine: 1. Die Komponente die die Daten bekommt mit dem Startsignal und die dann herausschiebt. Ich habe sie SR_24Bit genannt. 2. Den IC Baustein, also das Schieberegister in das hineingeschoben wird, das ist quasi dein PLL Baustein, hier SR_24Bit_IC genannt. 3. Die SR_24Bit_bench, das ist die Testbench die die Komponente im FPGA mit dem IC verbindet und der Komponente einmal die 24 Datenbits überreicht. Die ZIP Datei enthält das schön als Xilinx Vivado Projekt.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.