Hallo Leute, wir sitzen im Moment vor einem recht schwierigen Problem, zumindest fuer uns, und finden keine rechte Loesung dafuer, vllt. kann hier je jemand helfen. Wir wuerden gerne ein Signal, welches z.B. 1 Sekunde lang ist auf einen Takt der z.b. nur 0.25s lang ist aufsynchronisieren. Beide Takte (1Hz und 4Hz) sind vom gleichen Takt abgeleitet, die Flanken kommen also zur gleichen Zeit. Was ich tun moechte ist ein Signal, welches eine Sekunde lang anliegt auf 0.25s zu verkuerzen. Sowas sollte doch eigentlich kein Problem sein, mir faellt aber dennoch keine Loesung ein, kann mir jemand helfen? Luigi
Um zwischen zwei Taktdomainen dieser Art die Inforamtion auszutauschen benötigst Du ein sogenanntes Universal Node Device. Diese als U.N.D.-Gatter bezeichneten Blöcke sind u.a. bei Reichelt erhältlich. Man legt an die beiden Eingänge die beiden Takte und erhält den gewünschten verkürzten Takt.
luigi schrieb: > Beide Takte (1Hz und 4Hz) sind vom gleichen Takt abgeleitet, die Flanken > kommen also zur gleichen Zeit. Hmmmm. Wenn alle Flanken zur gleichen Zeit kommen, dann ist es der gleiche Takt... > Wir wuerden gerne ein Signal, welches z.B. 1 Sekunde lang ist auf einen > Takt der z.b. nur 0.25s lang ist aufsynchronisieren. Beide Takte (1Hz > und 4Hz) sind vom gleichen Takt abgeleitet, die Flanken kommen also zur > gleichen Zeit. Kannst du da mal ein Bild von malen? Und wenn es nicht allzu geheim ist: WAS wollt ihr denn machen? Nicht: WIE wollt ihr es machen? Das hört sich nämlich schon anders an: > Was ich tun moechte ist ein Signal, welches eine Sekunde lang anliegt > auf 0.25s zu verkuerzen. Das hört sich für mich nach einem Monoflop an...
luigi schrieb: > Beide Takte (1Hz > und 4Hz) sind das wirklich Takte? So langsam? Eventuell ist das Schlagwort "Flankenerkennung" mit dem 4Hz-Takt hilfreich.
es kommen nie alle Flanken zur selben Zeit! Weg mit dem Gedanken - der existiert nur in der Theorie. Stichwort könnte auch "Überabtastung" sein. Man kann das langsame Signal immer in die schnellere einsynchonisieren. Die Frage ist nur, was will man damit machen?
Zeitgeist schrieb: > es kommen nie alle Flanken zur selben Zeit! Weg mit dem Gedanken - der > existiert nur in der Theorie. Da hast Du wohl Recht. Aber wenn dem Synthese-Tool die Taktverhältnisse bekannt sind, kann man eben so tun als ob...
Philip K. schrieb: > Aber wenn dem Synthese-Tool die Taktverhältnisse bekannt sind, kann man > eben so tun als ob... Aber nur, wenn das wirklich Takte in einem Taktnetz sind, und nicht irgendwas Heruntergeteiltes und Gegatetes...
oh, das ging ja wieder mal schnell, danke schon mal fuer die Kommentare, ich denke ich werde es mal etwas genauer erklaeren: Ich moechte einen I2S Interface bauen (in VHDL), der auf der einen Seite die I2S Daten einliest (die Clocks werden dabei von mir erzeugt, durch einen Clockteiler), und auf der anderen Seite die 24 bit fuer links/rechts ausgibt. Das ganze system wird mit ungefaehr 25MHz getaktet sein, der datentakt ist ein 512tel davon. Ich habe jetzt also 2 schieberegister welche ich befuelle (1 fuer links/ 1 fuer rechts), und wenn beide Schieberegister voll sind moechte ich einen Impuls der laenge 40ns senden (genau ein 25MHz Takt), die schieberegister werden aber mit dem 25MHz/512 Takt befuellt, wie macht man soetwas? es ist eigentlich alles fertig, ausser dem signal welches anzeigt dass die daten fertig anliegen. danke luigi
luigi schrieb: > und wenn beide Schieberegister voll sind moechte ich einen Impuls der > laenge 40ns senden (genau ein 25MHz Takt), Nennt sich Clock-Enable und ist gängige Praxis. > die schieberegister werden aber mit dem 25MHz/512 Takt befuellt, wie > macht man soetwas? Man taktet das gesamte System mit 25MHz (frei nach Concn: es kann nur einen geben!). Jede geringere Frequenz wird über Teiler erzeugt, die Clock-Enables (keinesfalls und niemals aber andere Takte!) generieren. > es ist eigentlich alles fertig Dann häng doch einfach mal die VHDL(oder Verilog oder sonstwas)-Datei hier an.
so, also im Anhang findet Ihr die Dateien. im i2s_in ab Zeile 100 habe ich das Problem, dass ich die beiden Prozesse nicht synchronisiert bekomme. Ich vermute im Moment mal dass es daran liegt, dass ich die beiden Prozesse eben nicht mit unterschiedlichen clocks laufen lassen kann, aber wie geht es denn sonst? falls der Code nicht ausreicht um zu verstehn was ich machen moechte kann ich auch noch eine Zeichnung machen.
Zeile 4: Aua!
1 | if rising_edge(sclk_in) then |
2 | state_reg <= state_reg; |
3 | case state_reg is |
4 | when idle => |
5 | ready <= '0'; |
6 | if falling_edge(lrck_in) then |
7 | state_reg <= write_left; |
8 | elsif rising_edge(lrck_in) then |
9 | state_reg <= write_right; |
hmm, was koennte 'state_reg' wohl fuer ein Bauteil sein, das mit 3 Clocks klarkommt? Schau mal im Datenblatt deines FPGA nach, ob du in einem CLB/LE ein passendes FF findest...
hm, ja jetzt wo du mich darauf hinweist wird mir auch klar dass das nicht geht, aber das ist leider noch nicht mal das problem welches ich meinte. Dabei kommt aber noch eine Frage auf: warum funktioniert dieses Konstrukt in der Simulation mit Questasim? Es handelt sich hier uebrigens um ein ASIC Design und kein FPGA-Projekt, falls das irgendwie wichtig ist.
luigi schrieb: > Es handelt sich hier uebrigens um ein ASIC Design und kein FPGA-Projekt, > falls das irgendwie wichtig ist. Das könnte teuer werden, bei dem Wissensstand... :S
okay, ich hab das ganze jetzt noch mal neu geschrieben, vllt. wird so etwas klarer was ich tun moechte. wie ihr euch sicherlich schon gedacht habt handelt es sich hier um ein uni-projekt, also nichts mit teuer ;)
1 | stage1 : process (clk, nreset) |
2 | begin
|
3 | if nreset='0' then |
4 | q1 <= '0'; |
5 | else
|
6 | if rising_edge(clk) then |
7 | q1 <= sdata_in; |
8 | end if; |
9 | end if; |
10 | end process stage1; |
11 | |
12 | stage2 : process (clk, nreset) |
13 | begin
|
14 | if nreset='0' then |
15 | q2 <= '0'; |
16 | else
|
17 | if rising_edge(clk) then |
18 | q2 <= q1; |
19 | end if; |
20 | end if; |
21 | end process stage2; |
Das ist es, warum VHDL als "geschwätzig verschrien ist. Ich hätte da einfach das hier geschrieben (weil der Reset hier auch in einem ASIC absolut vollkommen unnötig ist!):
1 | q1 <= sdata_in when rising_edge(clk); |
2 | q2 <= q1 when rising_edge(clk); |
Das hier ist übrigens trotz "einsynchronisieren" komplett asynchron, weil q2 auf clk eingetaktet, aber mit sclk weitergegeben wird:
1 | if rising_edge(clk) then |
2 | q2 <= q1; |
3 | :
|
4 | :
|
5 | if rising_edge(sclk) then |
6 | if right_enable = '1' then |
7 | right_reg <= right_reg(23 downto 0) & q2; -- Holla die Waldfee |
Das gibt dann zwischendurch wüstes Rauschen oder Knacken in der Tonübertragung... Mach es mit dem Takt doch einfach so wie der Highlander: Es kann nur einen geben! Und I2S kann mit seinen maximal 6MBit/s locker mit den 25MHz verwaltet werden... Oder du könntest doch einfach den Empfang komplett synchron zum sclk abhandeln, und dann die empfangenen Ton-Daten an die andere Taktdomäne übergeben (so würde ich das machen).
1 | use ieee.numeric_std.all; |
2 | use ieee.std_logic_unsigned.all; |
Oh nein, nicht schon wieder... Siehe den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete"
luigi schrieb: > wie ihr euch sicherlich schon gedacht habt handelt es sich hier um ein > uni-projekt, also nichts mit teuer ;) Doch, für uns Steuerzahler :-) Bringt ja weder dir noch der Uni was, wenn du einen ASIC hast, der nicht das macht, was er soll. luigi schrieb: > Dabei kommt aber noch eine Frage auf: warum funktioniert dieses > Konstrukt in der Simulation mit Questasim? Weil die Syntax korrekt ist. Dein Simulator hat Ahnung von VHDL aber nicht von ASICs. Wenn du ein bisschen Zeit zum Austesten hast, kannst du ja mal eine Post-Map Simulation machen (Also das Ergebnis des Synthesizers und des Technologie-Mappers simulieren). Dann siehst du auch im Simulator, was von deinem Konstrukt übrig geblieben ist.
Lothar Miller schrieb: > Oder du könntest doch einfach den Empfang komplett synchron zum sclk > abhandeln, und dann die empfangenen Ton-Daten an die andere Taktdomäne > übergeben (so würde ich das machen). ja das wollte ich ja genau so machen, nur wie synce ich das dann zu den 25MHz? Als Ausgangsinterface haben wir die 2*24bit Daten für links/rechts spezifiziert und dieses take_data signal, welches halt fuer einen Takt (von clk, also 40ns) auf high geht. in diesem Takt holt das naechste Modul dann die Daten ab und verarbeitet diese. die Anfangsidee war jetzt die Schieberegister mit der SCLK zu feeden und wenn diese voll sind das take_data signal (aber eben nur mit 40ns laenge) zu erzeugen und die schieberegister zu resetten. Von der Sache her scheitert es in meiner Vorstellung der Hardware jetzt vor allem daran dass ich nicht weiß wie ich diesen kurzen impuls aus dem langen SCLK-Impuls erzeuge, und zwar auch noch taktsynchron zur clk.
luigi schrieb: > ja das wollte ich so machen, nur wie synce ich das dann zu den 25MHz? Ist doch einfach, du hast ja pro Wort mindestens 24 Bit des langsamen sclk Zeit zur Übergabe in die schnelle Domain (und damit mindestens 96 Takte deines clk). Ich würde für die Übergabe sogar einfach den WordSelect des I2C Signal einsynchronisieren, dann eine Flankenerkennung draufsetzen und damit dann das abgespeicherte Wort nach clk übernehmen. luigi schrieb: > die Anfangsidee war jetzt die Schieberegister mit der SCLK zu feeden und > wenn diese voll sind das take_data signal (aber eben nur mit 40ns > laenge) zu erzeugen und die schieberegister zu resetten. Nimm zwei Schieberegister: eines für Links, das andere für Rechts. Und immer der Kanal, der gerade nicht übertragen wird, wird in die clk Domäne übernommen. Denn dann ändern sich dessen Daten ja gerade nicht...
:
Bearbeitet durch Moderator
2 schieberegister habe ich schon (fuer links und rechts), die Daten muessen aber gleichzeitig zum naechsten modul uebertragen werden, was aber auch kein problem ist da jede Uebertragung 32 sclk-Takte lang ist, aber nur waehrend der ersten 24 Takte liegen auch daten an (sind halt nur 24bit), da hat man danach also genug Zeit die Daten zu uebertragen und die beide schieberegister zu resetten. Ob die Schieberegister voll sind erkenne ich an dem left/right_full signal welches ins 25. bit der Schieberegister geschoben wird. der ablauf ist also folgender: lrck geht low, die flanke erkenne ich und starte mein ganzes system. von da an wird dann das linke schieberegister mit sclk getaktet und bekommt die daten rein bis left_full high ist. ab jetzt wird gewartet bis lrck high geht, dann wird das rechte schieberegister befuellt. dann sind left_full und right_full beide high, es kann also das take_data signal erzeugt werden, und genau hier weiss ich nicht weiter. wie erzeuge ich denn dieses signal so dass es nur 40ns breit wird? nachdem das take_data signal dann high war werden die schieberegister resettet und alles beginnt von vorn, aber dieses take_data signal zu erzeugen, da komme ich einfach nicht drauf wie das sinnvoll gehen soll, das muss doch irgendwie zu machen sein?
luigi schrieb: > 2 schieberegister habe ich schon (fuer links und rechts), die Daten > muessen aber gleichzeitig zum naechsten modul uebertragen werden, was > aber auch kein problem ist da jede Uebertragung 32 sclk-Takte lang ist, > aber nur waehrend der ersten 24 Takte liegen auch daten an (sind halt > nur 24bit), da hat man danach also genug Zeit die Daten zu uebertragen > und die beide schieberegister zu resetten. Ich behaupte: man braucht da kein Schieberegister irgendwann zurücksetzen. Es müssen nur die jeweils bis dahin empfangenen Daten zum richtigen Zeitpunkt richtig weitergegeben werden. luigi schrieb: > der ablauf ist also folgender: lrck geht low, die flanke erkenne ich und > starte mein ganzes system. von da an wird dann das linke schieberegister > mit sclk getaktet und bekommt die daten rein bis left_full high ist. > ab jetzt wird gewartet bis lrck high geht, dann wird das rechte > schieberegister befuellt. > dann sind left_full und right_full beide high, es kann also das > take_data signal erzeugt werden, und genau hier weiss ich nicht weiter. > wie erzeuge ich denn dieses signal so dass es nur 40ns breit wird? > nachdem das take_data signal dann high war werden die schieberegister > resettet und alles beginnt von vorn, aber dieses take_data signal zu > erzeugen, da komme ich einfach nicht drauf wie das sinnvoll gehen soll, > das muss doch irgendwie zu machen sein? Irgendein Großbuchstabe hätte diesen Text besser lesbar gemacht... > lrck Schon das ist falsch: es gibt keinen Rechts-Links-Clock im I2S Protokoll, sondern es gibt nur den Schiebetakt slck. Im Wikipedia-Artikel ist statt lrck der passendere Namen verwendet: ws für Word-Select. Und so ist es auch: die Daten werden mit den sclk eingetaktet, und mit dem ws wird ausgewählt, welches der beiden Schieberegister gerade aktualisiert wird.
:
Bearbeitet durch Moderator
Lothar Miller schrieb: > Oh nein, nicht schon wieder... > Siehe den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete" Du wirst aber auch nicht müde...;-) Ich muss ja gestehen, dass obwohl ich den Beitrag kenne, ich das Teil seit Jahren weiter verwende. Probleme sind mir daraus noch nie entstanden...
luigi schrieb: > Von der Sache her scheitert es in meiner Vorstellung der Hardware jetzt > vor allem daran dass ich nicht weiß wie ich diesen kurzen impuls aus dem > langen SCLK-Impuls erzeuge, und zwar auch noch taktsynchron zur clk. Synchronisierer mit Flankenerkennung, wie hier beschrieben: http://www.doulos.com/knowhow/fpga/synchronisation/
So zum Beispiel:
1 | entity EDGE_DETECT is |
2 | generic( |
3 | -- Number signals to check
|
4 | G_NUM_SIG : integer; |
5 | -- Input not clock synchronous
|
6 | G_ASYNC : boolean := false |
7 | );
|
8 | port( |
9 | CLK : in std_logic; |
10 | -- Input signal
|
11 | I_SIGNALS : in std_logic_vector(G_NUM_SIG-1 downto 0); |
12 | -- Edge detection output
|
13 | O_RISE : out std_logic_vector(G_NUM_SIG-1 downto 0); |
14 | O_fall : out std_logic_vector(G_NUM_SIG-1 downto 0) |
15 | );
|
16 | end entity EDGE_DETECT; |
17 | |
18 | architecture rtl of EDGE_DETECT is |
19 | |
20 | signal S_CHECK_D0 : std_logic_vector(G_NUM_SIG-1 downto 0); |
21 | signal S_CHECK_D1 : std_logic_vector(G_NUM_SIG-1 downto 0); |
22 | |
23 | begin
|
24 | |
25 | -- Asynchronous case
|
26 | GEN_ASYNC : if (G_ASYNC) generate |
27 | |
28 | B_ASYNC : block is |
29 | signal S_I_SIGNALS : std_logic_vector(G_NUM_SIG-1 downto 0); |
30 | begin -- block B_ASYNC |
31 | -- Purpose: Input register pipe
|
32 | P_REG : process (CLK) |
33 | begin -- process P_REG |
34 | if (rising_edge(CLK)) then |
35 | S_I_SIGNALS <= I_SIGNALS; |
36 | S_CHECK_D0 <= S_I_SIGNALS; |
37 | S_CHECK_D1 <= S_CHECK_D0; |
38 | end if; |
39 | end process P_REG; |
40 | end block B_ASYNC; |
41 | |
42 | end generate GEN_ASYNC; |
43 | |
44 | -- Synchronous case
|
45 | GEN_SYNC : if (not G_ASYNC) generate |
46 | |
47 | -- Purpose: Input register
|
48 | P_REG : process (CLK) |
49 | begin -- process P_REG |
50 | if (rising_edge(CLK)) then |
51 | S_CHECK_D1 <= I_SIGNALS; |
52 | end if; |
53 | end process P_REG; |
54 | |
55 | S_CHECK_D0 <= I_SIGNALS; |
56 | |
57 | end generate GEN_SYNC; |
58 | |
59 | -- Combinational process
|
60 | -- Purpose: Edge detection
|
61 | P_DETECT : process (S_CHECK_D0, S_CHECK_D1) |
62 | begin -- process P_DETECT |
63 | for i in 0 to G_NUM_SIG-1 loop |
64 | O_RISE(i) <= S_CHECK_D0(i) and not S_CHECK_D1(i); |
65 | O_FALL(i) <= not S_CHECK_D0(i) and S_CHECK_D1(i); |
66 | end loop; -- i |
67 | end process P_DETECT; |
68 | |
69 | end architecture rtl; |
pks schrieb: > Du wirst aber auch nicht müde...;-) Frag nicht... > Ich muss ja gestehen, dass obwohl ich den Beitrag kenne, ich das Teil > seit Jahren weiter verwende. Probleme sind mir daraus noch nie > entstanden... Klar geht das gut, solange du nicht zusätzlich auch die numeric_std mit einbindest. Das ist der Kasus Knaxus... ;-) Christoph Z. schrieb: > Synchronisierer mit Flankenerkennung Das ist hier nicht das Problem... @luigi: Ich habe da mal was geschrieben und behaupte, das läuft (ich habe es aber noch nicht ausprobiert oder simulaiert). Du kannst es auf jeden Fall als Gedankenskizze nehmen. Man könnte noch ein paar FF sparen, wenn man die unnötige Registrierung des garantiert stabilen Wortes herausnimmt. pks schrieb: > So zum Beispiel: ... Ja, das wird luigi jetzt entweder a) weiterbringen oder b) ihm wenigstens das Fürchten lehren... ;-) Ich mache das Einsynchronisieren und die folgende Flankenerkennung so: http://www.lothar-miller.de/s9y/categories/18-Flankenerkennung Ich denke, da kapiert man recht schnell worum es geht. Und wie man das dann generisch beschreiben kann, das kann jeder für sich alleine herausfinden.
:
Bearbeitet durch Moderator
Lothar Miller schrieb: > Christoph Z. schrieb: >> Synchronisierer mit Flankenerkennung > Das ist hier nicht das Problem... War auch mehr für die Vollständigkeit. Damit Luigi trotzdem weiss, wie man ein Flag synchronisiert, damit es in der Zieldomäne nur eine Taktperiode kurz ist. Wir sind hier ja alle gleicher Meinung, dass sein Problem gar nicht vorhanden ist, wenn die vorgeschlagenen Lösungen realisiert werden.
Lothar Miller schrieb: > pks schrieb: >> So zum Beispiel: ... > Ja, das wird luigi jetzt entweder a) weiterbringen oder b) ihm > wenigstens das Fürchten lehren... ;-) Was soll denn das jetzt heißen? :-)
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.