Forum: FPGA, VHDL & Co. Signale in anderen Processen zurücksetzen.


von Dirk (Gast)


Lesenswert?

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

von Ede (Gast)


Lesenswert?

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.



von Ede (Gast)


Lesenswert?

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.

von FPGA-Küchle (Gast)


Lesenswert?

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;

  

von Dirk (Gast)


Lesenswert?

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

von Dirk (Gast)


Lesenswert?

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

von Falk (Gast)


Lesenswert?

@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

von Dirk (Gast)


Lesenswert?

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

von Falk (Gast)


Lesenswert?

@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

von cheff (Gast)


Lesenswert?

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.

von Dirk (Gast)


Lesenswert?

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

von Falk (Gast)


Lesenswert?

@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

von Dirk (Gast)


Lesenswert?

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

von Holger H. (holger-h-hennef) Benutzerseite


Lesenswert?

@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.

von Holger H. (holger-h-hennef) Benutzerseite


Lesenswert?

#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
Noch kein Account? Hier anmelden.