Ich habe ein mittelschweres VHDL Problem für das ich keine Lösung finde. Ich benötige ein Signal C das durch die steigende Flanke eines anderen Signales A auf 1 gesetzt wird.Zurückgesetzt werden soll das Signal durch die steigende oder fallende Flanke eines weiteren Signals B. Nun kann es aber passieren die steigende Flanke des ersten Signals A genau mit der 0/1 bzw 1/0 Flanke des zweiten Signales B zusammentrifft. In diesem Fall soll das erste Signal A bevorzugt behandelt werden. Für den ersten Teil 0/1 Signal A habe ich schon etwas. process (a,b) variable flanke :std_logic; begin if rising_edge(A) then C<='1'; -- Das funktioniert if((flanke='0' and B ='1') or (flanke='1' and B='0')) then C<='0'; end if; flanke:=B; end process; Grüße Dirk
Hallo Dirk! Probier mal aus, ob es vielleicht über ne FSM lösbar ist. Taste deine Signale A und B mit dem Systemtakt ab und speicher dir den Wert der Eingänge des vorangegangenen Taktes in einem separaten Register (a_old, b_old). So kannst du in jedem Zustand eine Flankenauswertung der Signale durchführen und dann entsprechend reagieren.. State 1: wenn a_old = '0' and a = '1' (steigende Flanke), dann C setzten und in nächsten Zustand springen State 2: wenn (b_old = '0 and b = '1') or ( b_old = '1' and b = '0') , dann C wieder zurücksetzen und in State 1 springen.
oder eventuell über ne if-Anweisung: if (a_old and...... c <= '1'; elsif (b_old and .... c <= '0'; dann sollte der Flankenwechsel auf a priorisiert werden. Egal wie du das löst, ich denke, der Schlüssel liegt darin, dass du deine Signale mit nem höheren Systemtakt abtastest und dann diese abgetasteten Werte weiter verarbeitest. Dann hast du auch ein synchrones Design, das ordentlich synthetisiert und constrained werden kann.
Hallo Dirk, icg schätze dein VHDL code soll synthetisierbar sein. Dann zeigt Ede in die richtige Richtung. Das was Du mit "die steigende Flanke" bezeichnet, meint wechselndes Signal. Du versuchst es mit rising_edge, das ist aber in der Synthese für taktsignale reserviert. Und bei FlipFlops ist immer nur ein Takkteingang aktiv. Zwei gleichzeitig wechselnde Taktsignale an einem FF gibt es nicht und wenn doch dann ist es ein Designfehler. Also deine beiden signale behandelst du in einem Process der mit dem Systemtakt läuft, also
1 | process(clk_i) |
2 | begin
|
3 | if rising_edge(clk_i) then |
4 | B_verzoegert_q <= B_i; --speichern für Signalwechselerkennung |
5 | A_verzoegert_q <= a_i; |
6 | --Setzen ist höher prior als Löschen
|
7 | if A_verzoegert_q = '0' and a_i = '1' then |
8 | c_q <= '1'; --A wechselt von 0 auf 1 |
9 | elsif (B_verzoegert_q /= B_i) --beliebiger wechsel |
10 | c_q <= '0'; |
11 | end if; |
12 | end if; |
13 | end process; |
Super !Ihr habt mir sehr geholfen.Der Code soll auch synthetisierbar sein. Das ganze soll Zugriffe auf einen Adressbus multiplexen. Wenn der 0/1 Flankenwechsel Signal A stattfindet sind ROM adressen gültig, Bei Zustandsänderungen von Signal B sind es die RAM adressen. Der Problemfall ist wenn während des 0/1 Flankenwechsels auch eine Zustandsänderung von Signal B eintritt.Dann muß erst die ROM Adresse anliegen,zwei Taktzyklen später die RAM Adresse. Grüße Dirk
Die Umschaltung sollte aber im gleichen Augenblick wie der Flankenwechsel erfolgen.Ich habe dazu mal die if abfrage rising_clk entfernt. Im Simulator sieht es gut aus, nur auf dem Board funktioniert es nicht. process(rom_e) variable out1:std_logic; begin --if rising_edge(clk) then B_verzoegert_q <= rom_e(0); --speichern für Signalwechselerkennung A_verzoegert_q <= rom_e(1); --Setzen ist höher prior als Löschen if (A_verzoegert_q = '0') and (rom_e(1) = '1') then out1 := '1'; --A wechselt von 0 auf 1 elsif (B_verzoegert_q /= rom_e(0)) and (out1='1') then out1 := '0'; elsif (B_verzoegert_q /= rom_e(0)) and (out1='0') then out1:= '1'; else out1:='0'; end if; rf<=out1; --end if; end process; Dirk
@Dirk >Im Simulator sieht es gut aus, nur auf dem Board funktioniert es nicht. Das kommt des öfteren vor. > B_verzoegert_q <= rom_e(0); --speichern für Signalwechselerkennung > A_verzoegert_q <= rom_e(1); Schon mal gut, aber unvollstämdig, weil >--Setzen ist höher prior als Löschen > if (A_verzoegert_q = '0') and (rom_e(1) = '1') then out1 := '1'; --A >wechselt von 0 auf 1 Hier knallts. Du darfst niemals nicht in einer State Machine auf nichtsynchrone Signale reagieren. Das gibt sehr böse schwer zu findende Fehler. Du musst auf jeden Fall dein Signal rom_e erstmal synchronisieren (abtasten) und nur auf dieses synchronisierte Signal darfst du zugreifen. Bei höheren Taktraten (50 MHz++) sollte man sogar zwei FlipFlops zu Synchronisation verwenden. Stichworte Metastabilität und Race Condition. rom_e_int <= rom_e; B_verzoegert_q <= rom_e_int(0); --speichern für Signalwechselerkennung A_verzoegert_q <= rom_e_int(1); if (A_verzoegert_q = '0') and (rom_e_int(1) = '1') then out1 := '1'; MfG Falk
Ok. Das verstehe ich, ist wie bei der "normalen" Programmierung. Dort soll man Ports auch erst in einer variablen speichern, der Zustand des Ports kann sich ja jederzeit ändern. Um die beiden Adressbusse umzuschalten habe ich ram_a(13 downto 0)<= '1'&ad(12 downto 0) when rf ='1' else '0'&rab(12 downto 0); als nebenläufige Logik geschrieben. Muß rf zwischengespeichert werden bevor ich es außerhalb des processes benutze ? Darf ich Ports direkt in einem port map benutzen port( ram_io ram_io : inout std_logic_vector(7 downto 0); ) port map( . . RDB => ram_io, -- RAM IB => ram_io, -- Eprom ) Grüße Dirk
@Dirk >Ok. Das verstehe ich, ist wie bei der "normalen" Programmierung. Du meinst mit Assembler/C/Whatever? >Dort soll man Ports auch erst in einer variablen speichern, der Zustand >des Ports kann sich ja jederzeit ändern. Naja, wenn ich Ports in C abfrage, kann ich das schon direkt machen, die Darunterliegende Hardware liefer der Software schon die richtigen Daten. >Um die beiden Adressbusse umzuschalten habe ich >ram_a(13 downto 0)<= '1'&ad(12 downto 0) > when rf ='1' > else '0'&rab(12 downto 0); >als nebenläufige Logik geschrieben. Muß rf zwischengespeichert werden >bevor ich es außerhalb des processes benutze ? Nein. >Darf ich Ports direkt in einem port map benutzen Nein, bei Ausgängen brauchst du eine MUX. MfG Falk
Die Problembeschreibung scheint mir schon verdächtig: Was ist das denn für ein DEsign, wo zwei Takte gleichzeitig kommen können? Meines Erachtens sind das beides einzutaktenden Signale, deren logische Schaltfunktionalität rein über Kombinatorik gelöst werden kann und muss, so wie man es auch hardwaremaessig diskret aufbauen würde. Dann reicht ein flipflop.
In dem Design teilen sich CPU und ein Videogenerator das RAM.Zusätzlich hängt noch ein Eprom am Bus.Während die CPU Adressen für das Eprom auf den Bus legt kann ein Zähler das Ram adressieren. Das ganze wäre ja halb so wild, nur hat mein FPGA zu wenig Block RAM um einen der Speicher dort abzulegen.Außerdem, bedingt durch nur einen externen Speicherbaustein, sind RAM und Eprom auf einem Chip. Und der Gipfel ist, das ich mit VHDL erst vor kurzem angefangen habe. Grüße Dirk
@Dirk >In dem Design teilen sich CPU und ein Videogenerator das RAM.Zusätzlich Naja, aber die sollten doch schon irgendwie halbwegs synchron laufen. Und ich meine WIRKLICH synchron, mit einem Takt. >Und der Gipfel ist, das ich mit VHDL erst vor kurzem angefangen habe. VHDL ist das Eine, der wesentlich wichtigere Punkt ist das Konzept. Das klingt mir im Moment etwas wild gestrickt. MfG Falk
Das Design ist ja vorgegeben.Es ist mein beliebtes "Space Invaders". Das läuft schön synchron.Das ist ja auch nicht von mir. Wie das Zusamenspiel von CPU,RAM, ROM und Video funktioniert läßt sich ganz wunderbar in Modelsim erkennen. Meine Grundidee war ein neues Signal zu erzeugen das mir anzeigt wann RAM und wann ROM Zugriffe statttfinden.Dazu "beobachte" ich von bestimmten Signalen die Flankenwechsel und reagiere darauf.Natürlich völlig asynchron.Sobald ich den Takt benutze kommen meine Signale verzögert. Ich denke Du hast Recht, jetzt sieht mein erzeugtes Signal in Modelsim zwar schön synchon aus, aber in der echten Hardware kommen die Signale trotzdem verzögert, zwar nicht einen ganzen Takt, aber wahrscheinlich ausreichend um das Timing durcheinander zu werfen. Das Ergebnis auf dem Monitor betrachtet ist im Augenblick so bescheiden wie wie nie zuvor.Ich hatte schon mal ein flackerndes Titelbild. ;) Das Projekt ist aber sehr lehrreich,Dank aller die sich daran beteiligen und mir mit Tips zu Seite stehen. Aber es ist erst zu Ende wenn die Außerirdischen besiegt sind. Grüße Dirk
@Dirk Stichwort Flip-Flop Handling von Chef. Möglicherweise ist es für dich hilfreich, das du dich in so einen z.B 8 Kanal IRQ Baustein eindenkst. Oder dir das Core Design von so einem Teil besorgst. Mich erinnert die Core-Problematik an einen IRQ Baustein. Mit programmable prioritäts Level Stages. 8 Channel IRQ CHIP Intel 8020 80XX PC MotherBoard ??? Bei dem Intel chip konnte man in der IRq Routine nochmals die Prio steuern und so den Folgelauf für andere Kanäle beeinflussen, umd vorausbestimmen. Damit war es möglich so etwas zu managen. Oder bei 8051 derivaten.???? Oder ist das kein guter Tip ???? Gruss Holger.
#Title 'IRQ Controller Program'; #Engineer 'Morgan Taylor'; "Inputs INPUT CLOCK, RMOTDET, LMOTDET, CMOTDET, /EDGE, TIC; "Outputs OUTPUT IRQ, IRQCLOCK; D_FLOP OUTPUT IRQTEMP CLOCKED_BY CLOCK; D_FLOP OUTPUT Rmotdetdd, LMotDetdd, CMotDetdd, Edgedd, IRQStatedd[3] CLOCKED_BY CLOCK; VIRTUAL NODE IRQ1, IRQ2, IRQ3, IRQ4; "Equations IRQTEMP=IRQ1 + IRQ2 + IRQ3 + IRQ4; IRQCLOCK=TIC; "State Machines STATE_MACHINE RMOTDETSM STATE_BITS Rmotdetdd; STATE A [0b]: IRQ1=RMOTDET; IF (RMOTDET) THEN GOTO B; ELSE GOTO A; END IF; STATE B [1b]: IRQ1=/RMOTDET; IF (/RMOTDET) THEN GOTO A; ELSE GOTO B; END IF; End RMOTDETSM; STATE_MACHINE LMOTDETSM STATE_BITS LMOTDETDD; STATE A [0b]: IRQ2=LMOTDET; IF (LMOTDET) THEN GOTO B; ELSE GOTO A; END IF; STATE B [1b]: IRQ2=/LMOTDET; IF (/LMOTDET) THEN GOTO A; ELSE GOTO B; END IF; End LMOTDETSM; STATE_MACHINE CMOTDETSM STATE_BITS CMOTDETDD; STATE A [0b]: IRQ3=CMOTDET; IF (CMOTDET) THEN GOTO B; ELSE GOTO A; END IF; STATE B [1b]: IRQ3=/CMOTDET; IF (/CMOTDET) THEN GOTO A; ELSE GOTO B; end if; End CMOTDETSM; STATE_MACHINE EDGESM STATE_BITS EDGEDD; STATE A [0b]: IRQ4=EDGE; IF (EDGE) THEN GOTO B; ELSE GOTO A; END IF; STATE B [1b]: IRQ4=/EDGE; IF (/EDGE) THEN GOTO A; ELSE GOTO B; END IF; End EDGESM; STATE_MACHINE IRQSTATE STATE_BITS IRQStatedd; STATE A [000b]: IRQ=0; IF (IRQTEMP) THEN GOTO B; ELSE GOTO A; END IF; STATE B [001b]: IRQ=1; GOTO C; STATE C [010b]: IRQ=1; GOTO D; STATE D [011b]: IRQ=1; GOTO E; STATE E [100b]: IRQ=1; GOTO F; STATE F [101b]: IRQ=1; GOTO G; STATE G [110b]: IRQ=1; GOTO H; STATE H [111b]: IRQ=1; GOTO A; END IRQSTATE;
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.