mikrocontroller.net

Forum: FPGA, VHDL & Co. 16Bit breites Wort in eine LUT speichern und ausgeben


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 möchte in VHDL gerne eine Tabelle anlegen welche ich mit einem 4MHz 
Signal abtaste und ausgebe.

Meine Idee ist ein 3x 16Bit breite Worte abzuspeichern.

Wort 1 (Z1): 1110101011001100

Wort 2 (Z2): 1100110010101111

Wort 3 (Z3): 1010101010101010

Also wie einen Tabelle anlegen. Gesteuert wird die Wortauswahl durch ein 
250Khz schnelles Datensignal. Durch Flankenerkennung des Datensignals 
wird dann Z1, Z2 ausgegeben. Das Datensignal hat an jeder 10ten Stelle 
eine logische null stehen. Wenn diese kommt wird das Datenwort Z3 
ausgegeben.

Nun stellen sich mir ein paar fragen.

1.) Wenn ich die Worte im BRAM Speicher bekomme ich dann eine 
Verzögerung weil die Daten erst bei der nächsten steigenden Flanke 
zurückgegeben werden? Ich gebe ja die Daten dann mit dem 4MHz Takt aus 
mithilfe eines Schieberegisters und MUX. Ziel ist ja ein Ausgangssignal 
zu bekommen in dem die Worte kontinuierlich  aneinandergereiht 
ausgegeben werden.

Muss ich die Worte in den BRAM speichern oder gibt es andere 
Möglichkeiten?

2.) Das einzige ist was ich als Problem ansehe ist wenn mein Datensignal 
4x hintereinander eine 0 kommt. Wie kann ich da auf eine Flanke prüfen? 
Weil 0000 hat keine Flanken.

Beste Grüße

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

Bewertung
0 lesenswert
nicht lesenswert
Sawyer M. schrieb:
> 2.) Das einzige ist was ich als Problem ansehe ist wenn mein Datensignal
> 4x hintereinander eine 0 kommt. Wie kann ich da auf eine Flanke prüfen?
> Weil 0000 hat keine Flanken.
Richtig: es geht nicht. Und was ist dann das Problem? Wenn das nicht 
sein darf, dann darf in deinem Datensignal eben nicht so oft eine 0 
kommen...

> Meine Idee ist ein 3x 16Bit breite Worte abzuspeichern.
> Wort 1 (Z1): 1110101011001100
> Wort 2 (Z2): 1100110010101111
> Wort 3 (Z3): 1010101010101010
Sind das statische Werte oder sollen die zur Laufzeit geändert werden?

> Also wie einen Tabelle anlegen. Gesteuert wird die Wortauswahl durch ein
> 250Khz schnelles Datensignal. Durch Flankenerkennung des Datensignals
> wird dann Z1, Z2 ausgegeben. Das Datensignal hat an jeder 10ten Stelle
> eine logische null stehen. Wenn diese kommt wird das Datenwort Z3
> ausgegeben.
Ich kann nicht erkennen, wie du diese Ausgabe synchronisieren willst. So 
auf dem Papier kannst du die zehn Stellen ja einfach abzählen, aber wie 
machst du das in der Praxis? Mit welchem Mechnismus kannst du dort die 
10 Bits verfolgen und mitzählen?

> 1.) Wenn ich die Worte im BRAM Speicher bekomme ich dann eine
> Verzögerung weil die Daten erst bei der nächsten steigenden Flanke
> zurückgegeben werden?
Der 1 Takt Latency ist doch nicht schlimm, weil du es ja weißt, dass er 
da ist. Und: welche Flanke denn überhaupt?

> Muss ich die Worte in den BRAM speichern oder gibt es andere
> Möglichkeiten?
Du kannst Distributed RAM nehmen. Oder du kannst die paar Bits direkt in 
Flipflops speichern und über Kombinatorik ausgeben.

> Ziel ist ja ein Ausgangssignal zu bekommen in dem die Worte
> kontinuierlich  aneinandergereiht ausgegeben werden.
Womit wird diese Datenübertragung synchronisiert? Allein über die Zeit 
wie bei einer seriellen Schnittstelle?

> Durch Flankenerkennung des Datensignals wird dann Z1, Z2 ausgegeben.
Arbeitest du eigentlich am selben Problem wie Fabian im 
Beitrag "Select auf fallende und steigende Flanke"?

Ich würd dir empfehlen, hier mal das eigentliche Problem zu schildern 
(woher kommen welche Signale mit welchen Frequenzen, was soll damit 
gemacht und wie darafu regiert werden?) und nicht nach Lösungen für 
Detaiprobleme zu fragen, die nur deshalb entstehen, weil der 
grundlegende Ansatz umständlich ist...

Autor: Sawyer M. (sawyer_ma)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Meine Idee ist ein 3x 16Bit breite Worte abzuspeichern.
>> Wort 1 (Z1): 1110101011001100
>> Wort 2 (Z2): 1100110010101111
>> Wort 3 (Z3): 1010101010101010
> Sind das statische Werte oder sollen die zur Laufzeit geändert werden?

Das sind statische Werte und müssen zur Laufzeit nicht abgeändert 
werden.

>> Also wie einen Tabelle anlegen. Gesteuert wird die Wortauswahl durch ein
>> 250Khz schnelles Datensignal. Durch Flankenerkennung des Datensignals
>> wird dann Z1, Z2 ausgegeben. Das Datensignal hat an jeder 10ten Stelle
>> eine logische null stehen. Wenn diese kommt wird das Datenwort Z3
>> ausgegeben.
> Ich kann nicht erkennen, wie du diese Ausgabe synchronisieren willst. So
> auf dem Papier kannst du die zehn Stellen ja einfach abzählen, aber wie
> machst du das in der Praxis? Mit welchem Mechnismus kannst du dort die
> 10 Bits verfolgen und mitzählen?

Ja das hätte ich über eine Flankenerkennung gemacht vom Datensignal. 
Aber wenn mehrere nullen nacheinander kommen geht dies eben nicht. Ich 
muss mir da nochmals Gedanken machen wie ich das umsetze.

>> Muss ich die Worte in den BRAM speichern oder gibt es andere
>> Möglichkeiten?
> Du kannst Distributed RAM nehmen. Oder du kannst die paar Bits direkt in
> Flipflops speichern und über Kombinatorik ausgeben.

Im Internet werde ich leider nicht richtig fündig, wie man ein paar 
wenige Bits in FlipFlips speichert und per Kombinatorik ausgeben. Ich 
denke mir fehlen die Suchbegriffe.

Hättest du mir ein Beispiel oder eine Seite oder ein Suchbegriff? Ich 
denke In FF speichern ist das beste bei meiner Problematik.

Spannend wäre auch in den DRAM. Das wäre dann wie eine LUT, oder?


>> Ziel ist ja ein Ausgangssignal zu bekommen in dem die Worte
>> kontinuierlich  aneinandergereiht ausgegeben werden.
> Womit wird diese Datenübertragung synchronisiert? Allein über die Zeit
> wie bei einer seriellen Schnittstelle?

Verstehe die Frage nicht genau, Ich habe ja einen Grundtakt von meinem 
FPGA von 100MHz. Das Datensignal synchronisiere ich damit. Verstehe ich 
das gerade falsch?

>> Durch Flankenerkennung des Datensignals wird dann Z1, Z2 ausgegeben.
> Arbeitest du eigentlich am selben Problem wie Fabian im
> Beitrag "Select auf fallende und steigende Flanke"?

Nicht das ich wüsste aber es hört sich ähnlich an.

> Ich würd dir empfehlen, hier mal das eigentliche Problem zu schildern
> (woher kommen welche Signale mit welchen Frequenzen, was soll damit
> gemacht und wie darafu regiert werden?) und nicht nach Lösungen für
> Detaiprobleme zu fragen, die nur deshalb entstehen, weil der
> grundlegende Ansatz umständlich ist...

Das Datensignal kommt von einen AD-Wandler vom FPGA selbst. Deshalb ist 
dieses schon auf den Takt synchron. Dieses Datensignal möchte ich wie 
oben beschrieben digital modulieren.

Die Bits geben ich dann mit dem 4MHz Takt aus.

Also Clocktakt_1 -> Bit 1, Clocktakt_2 -> Bit 2, usw. bis ich alle 
16Bits (zum Beispiel Z1) nacheinander ausgegeben habe auf ein 
Ausgangssignal Out. Direkt anschließend kommt vom Datensignal die 
nächste Flanke an der ich erkenne ob Z1 oder Z2 ausgegeben wird und 
reihe an das Ausgangssignal Out die nächsten 16Bits an. So entsteht mir 
ein kontinuierliches Ausgangssignal Out mit meiner aneinandergereihten 
16Bit Wörtern.


Viele Grüße

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

Bewertung
0 lesenswert
nicht lesenswert
Sawyer M. schrieb:
> Das sind statische Werte und müssen zur Laufzeit nicht abgeändert
> werden.
Dann definiere einfach einen Vektor und gib den über ein Schieberegister 
oder einen Multiplexer aus:
constant Wort1 : std_logic_vecotr(15 downto 0) := "1110101011001100";
constant Wort1 : std_logic_vecotr(15 downto 0) := "1100110010101111";
constant Wort1 : std_logic_vecotr(15 downto 0) := "1010101010101010";
Und wie der Synthesizer das umsetzt ist dir dabei erst mal völlig 
egal...

> Das Datensignal kommt von einen AD-Wandler vom FPGA selbst.
Ein AD-Wandler im FPGA?
Oder einem Wandler, der an das FPGA angeschlossen ist und ausgelesen 
werden soll?
> Deshalb ist dieses schon auf den Takt synchron.
Dann ist das Einlesen doch simpel, weil die Daten ja mit diesme Takt 
eingelesen werden können. Aber welchen Takt meinst du denn überhaupt? 
Den 100MHz-Takt? Oder einen anderen, der mit den 250kHz synchron ist?

> Direkt anschließend kommt vom Datensignal die nächste Flanke an der ich
> erkenne ob Z1 oder Z2 ausgegeben wird
Wie kannst du an einer Flanke erkennen, welches Signal ausgegeben werden 
soll?

> Verstehe die Frage nicht genau, Ich habe ja einen Grundtakt von meinem
> FPGA von 100MHz. Das Datensignal synchronisiere ich damit. Verstehe ich
> das gerade falsch?
Mir ist nicht klar, was du überhaupt machen willst: welcher Baustein 
(Name, Typ, Bestellnummer) erzeugt das "Datensignal" und was soll 
anschließend damit passieren?

Autor: Achim S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Beschreibung ist wirklich nicht einfach zu verdauen, einige Begriffe 
sind wohl "fragwürdig" verwendet.

Sawyer M. schrieb:
> So entsteht mir
> ein kontinuierliches Ausgangssignal Out mit meiner aneinandergereihten
> 16Bit Wörtern.

Kontinuierlich ist das Gegenstück zu diskret. Du gibst nicht 
kontinuierlich Werte aus sondern wertediskret und wahrscheinlich auch 
zeitdiskret (also die Werte ändern sich immer nur zu bestimmten 
Zeitpunkten, die durch einen Takt gegeben sind (4 MHz).

Ich versuche mal zu raten, was du vielleicht meinen könntest:
- du betreibst einen externen ADC (irgendwas Delta-Sigma-Mäßiges, das 
dir im 250kHz-Takt jeweils ein 1-Bit Signal gibt?)
- je nach dieser Signalfolge willst du jeweils eines deiner beiden Z 
auswählen und dieses über ein Schieberegister ausgeben (mit 4MHz-Takt, 
so dass die vollen 16 Bit mit 250kHz ausgegeben werden).
- am Ende einer Ausgabe schaust du dir wieder den aktuellen Eingabewert 
(ADC-Daten) an und entscheidest, welches Z als nächstes ausgegeben wird.

Ist das so ungefähr richtig interpretiert?

Was ist dann das Kriterium dafür, ob du Z1 oder Z2 ausgibst? Wenn sich 
das Eingangssignal seit dem letzten Einlesen geändert hat (Flanke) 
wählst du Z1, wenn nicht dann Z2? Oder hängt die Auswahl Z1 vs. Z2 von 
der "Richtugn" der Flanke ab? Oder nur vom aktuellen Pegel des 
Dateneingangs?

Falls letzteres zutrifft: vergiss bitte für den Moment das Sitchwort 
Flankendetektion. Wenn der Dateneingang schon synchron zum 250kHz Takt 
vorliegt (d.h. in jeder 16. Periode des 4MHz-Signals ein neuer 
Dateneingang vorliegt), dann zähle einfach immer 16 Perioden deines 
4MHz-Takts ab um das neue Z ins Schieberegister zu schicken. Und zähle 
die 16*10 Perioden des 4 MHz Takts ab bis du Z3 ausgeben musst.

Sawyer M. schrieb:
> Spannend wäre auch in den DRAM. Das wäre dann wie eine LUT, oder?

Das wäre nicht spannend sondern anstrengend. Und nein, das wäre nicht 
wie eine LUT. Mit deinen Gedankengängen bist du einfach auf dem Holzweg.

Versuch erst mal, die gewünschte Funktion so weit zu durchdringen, dass 
du sie verständlich darstellen kannst. Danach kannst du dir Gedanken 
machen, wie die Z am besten gespeichert werden (wahrscheinlich wird sich 
diese Frage dann gar nicht mehr stellen).

Und noch viel später kannst du dich an die spannende Frage machen, wie 
man ein DRAM mit einem FPGA ansteuert und nutzt. Für diese Aufgabe hier 
ist das in keiner Weise sinnvoll oder zielführend, es lenkt dich nur von 
deiner eigentlichen Aufgabenstellung ab und verwirrt die Leser.

Für die aktuelle Aufgabe mach es wie von Lothar vorgeschlagen: schreib 
die drei konstanten Werte einfach in deinen VHDL-Code und überlasse es 
dem Synthesetool, wie diese genau gespeichert werden.

Autor: Sawyer M. (sawyer_ma)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achim S. schrieb:
> Ich versuche mal zu raten, was du vielleicht meinen könntest:
> - du betreibst einen externen ADC (irgendwas Delta-Sigma-Mäßiges, das
> dir im 250kHz-Takt jeweils ein 1-Bit Signal gibt?)
> - je nach dieser Signalfolge willst du jeweils eines deiner beiden Z
> auswählen und dieses über ein Schieberegister ausgeben (mit 4MHz-Takt,
> so dass die vollen 16 Bit mit 250kHz ausgegeben werden).
> - am Ende einer Ausgabe schaust du dir wieder den aktuellen Eingabewert
> (ADC-Daten) an und entscheidest, welches Z als nächstes ausgegeben wird.
>
> Ist das so ungefähr richtig interpretiert?

Ja so kann man es absolut interpretieren.

>
> Was ist dann das Kriterium dafür, ob du Z1 oder Z2 ausgibst? Wenn sich
> das Eingangssignal seit dem letzten Einlesen geändert hat (Flanke)
> wählst du Z1, wenn nicht dann Z2? Oder hängt die Auswahl Z1 vs. Z2 von
> der "Richtugn" der Flanke ab? Oder nur vom aktuellen Pegel des
> Dateneingangs?
> Falls letzteres zutrifft: vergiss bitte für den Moment das Sitchwort
> Flankendetektion. Wenn der Dateneingang schon synchron zum 250kHz Takt
> vorliegt (d.h. in jeder 16. Periode des 4MHz-Signals ein neuer
> Dateneingang vorliegt), dann zähle einfach immer 16 Perioden deines
> 4MHz-Takts ab um das neue Z ins Schieberegister zu schicken. Und zähle
> die 16*10 Perioden des 4 MHz Takts ab bis du Z3 ausgeben musst.

Ja hier liegt glaube ich gerade der Hund begraben. Ich glaube ein 
gravierender Denkfehler hat sich bei mir eingeschlichen. :/

Am Ende meiner ganzen Wortschieberei, will ich ein moduliertes Signal 
erzeugen auf Basis des Datensignals: Datensignal 250KHz, Das Wort 3 ist 
ja 1010101010101010.

Wenn ich nun nach dem neunten Paket mit 4MHz das Wort ausgebe über ein 
Schieberegister, dann war das Ziel das ein 8 Bit breites "Taktsignal 
(ich nenn es nur mal so)" herauskommt. Taktsignal deshalb da ja eine 
4MHz Periode, aus einer 10 (high, low) besteht und die Dauer von 250ns 
hat. Da ja immer nur mit eine fallenden oder steigenden Flanke 
geschalten wird muss ich deshalb erst das high und low abwarten bis das 
nächste Bit herausgeschoben wird. Das bedeutet im Umkehrschluss das aus 
4MHz, 2MHz werden.

Stimmt meine Annahme?? (Bitte nicht erschießen wenn ich falsch liege.)

Ziel ist das Wort 3 als 2MHz "Takt" auszugeben. Dafür brauch ich doch 
4MHz. Problem, ein 4MHz CLK aus 100MHz CLK benötigt einen Zähler mit 
12,5. Somit habe ich nun ein Problem wenn meine Annahme mit den 4MHz 
richtig ist.

Die anderen Wörter sind normalerweise auch 8 Bit breit. Ich habe Sie 
sozusagen (mit einem Schreibfehler wie mir gerade auffällt sollte Wort 1 
(Z1): 1100101011001100) künstlich verbreitert, um am Ende auf ein 8Bit 
breites Signal zu kommen welches 2MHz wie auch 1MHz Anteile hat. Klar 
eine 1100 = 1MHz, 1010 = 2MHz.

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

Bewertung
0 lesenswert
nicht lesenswert
Sawyer M. schrieb:
> Das bedeutet im Umkehrschluss das aus 4MHz, 2MHz werden.
Ja, das ist aber in erster Näherung absolut irrelevant...

> Stimmt meine Annahme??
Beantworte doch bitte einfach erst mal meine Fragen. Du nimmst nämlich 
gerne irgendwas an, das dir irgendwie bekannt vorkommt. Das bringt aber 
nichts. Du fühst dich selber in die Irre.

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

Bewertung
0 lesenswert
nicht lesenswert
Sawyer M. schrieb:
> Stimmt meine Annahme?

Ja, dieses Detail deiner Betrachtung stimmt. Aber es ist leider immer 
noch unklar, nach welchen Kriterien du Z1 oder Z2 auswählst.

Sawyer M. schrieb:
> Problem, ein 4MHz CLK aus 100MHz CLK benötigt einen Zähler mit
> 12,5. Somit habe ich nun ein Problem wenn meine Annahme mit den 4MHz
> richtig ist.

Das ist überhaupt kein Problem, nur dein Lösungsansatz ist falsch. Das 
hatten wir doch schon in deinem Parallelthread:
Beitrag "VHDL zwei CLK´s mit LFSR und 1:2 Teiler"

Wie dort schon erklärt: ein einfacher (und funktionierender) 
Lösungsansatz wäre, alles mit dem 100MHz-Takt laufen zu lassen. Und das, 
was du per geteilten Takt erreichen willst, mit dem Einsatz von 
Clock-Enables zu machen.

Es ist überhaupt kein Problem ein CE4MHz Signal zu erzeugen, dass in 
jeder 25ten Periode des 100MHz Takts für genau einen Taktzyklus auf 1 
ist (und die anderen 24 Takte auf 0). Das nutzt du als Clock-Enable 
Signal für deine FlipFlops und taktest sie weiter mit 100MHz - aber sie 
werden nur in jedem 25ten Takt wirklich umschalten (so als würden sie 
mit 4MHz getaktet)

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

Bewertung
0 lesenswert
nicht lesenswert
Sodelle ich bin am Projekt dran. Jedoch stolpere ich noch ziemlich oft. 
Ich habe nun meinen Zähler aufgebaut und bin gerade an der Logik wie ich 
die drei Zustände schalten kann und könnte. Idee war, die drei Vektoren 
mit den 16Bits mithilfe von einem MUX in ein Schieberegister zu laden.

Zu Testzwecken habe ich deshalb die Variablen F1, F2 und F3 eingeführt. 
ich wollte bevor ich das Schieberegister aufbaue testen ob alles soweit 
funktioniert.

Fazit: Leider nein. Ich habe eine Taktverzögerung. Man kann es auf dem 
Bild deutlich sehen.

Das Problem ist das ich im Code nicht schreiben kann:
if (rising_edge(data_in) and irq10 = '1') then
     F1 <= '1';
elsif (rising_edge(data_in) and irq10 = '0') then
      F2 <= '0';
elsif (rising_edge(data_in) and irq10 = '0') then
      F3 <= '1';
end if;

Dann wäre mein Takt synchron aber es wirft Error's. Auch mein Code von 
dem die Simulation stammt geht nicht.
process(clk)                           
begin
  if  rising_edge(clk) then
      if count10 = "1001" then
           count10 <= "0000";
           clk10 <= not clk10;
           irq10 <= '1';
      else
          count10 <= count10 + 1;
          irq10 <= '0';
      end if;
  end if;
end process;


process(clk, irq10, data_in)
begin
  if  rising_edge(data_in) then

                           
  if (data_in = '1' and irq10 = '1') then
     F1 <= '1';
  elsif (data_in = '1' and irq10 = '0') then
     F2 <= '0';
  elsif (data_in = '0' and irq10 = '0') then
     F3 <= '1';
end if;
                       
end if;
end process;


Wie macht man das? Das liegt diesmal ja nicht am Einsynchronisieren, 
oder?

Beste Grüße

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

Bewertung
0 lesenswert
nicht lesenswert
Sawyer M. schrieb:
> Das liegt diesmal ja nicht am Einsynchronisieren,
> oder?

Nein, es liegt daran, dass du ein völlig falsches Konzept verfolgst. Du 
verwendest datain als Taktsignal. Es ist völlig sinnlos, bei der 
positiven Taktflanke von datain auch noch den Pegel von datain 
abzufragen und damit Unterscheidungen treffen zu wollen.

Sawyer M. schrieb:
> Wie macht man das?

Indem man zwischendurch mal Rückfragen beantwortet und versucht, 
gegebene Ratschläge umzusetzen. Da du offenbar zu beidem keine Lust hast 
verabschiede ich mich hiermit aus diesem Thema.

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.