Forum: FPGA, VHDL & Co. Kombinatorische Signale über mehrere Entities routen nicht möglich?


von Steffen Hausinger (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe mir folgendes Programm geschrieben: In Entity 1 werden in einem 
Prozess die Signale A_OE und A_CE und-verknüpft. Das Ergebnis 
A_Request wird an einen Prozess in Entity 2 geleitet. Dort wird es 
ausgewertet und, je nach Ergebnis, der Vektor X_Routing zu "00" oder 
"11" gesetzt und zurück an Entity 1 gesendet.

Dort findet nun in einem dritten Prozess die Auswertung statt: Ändert 
sich der Vektor von "00" auf "11" oder umgekehrt, soll im späteren 
Design eine Reaktion erfolgen. Für's Debugging befülle ich damit aber 
ersteinmal nur meine Testvektoren.

Hier meine Beschreibung:
1
-- ####################################################
2
-- ##################### Entity 1 #####################
3
-- ####################################################
4
5
  -- Kombinatorischer Prozess
6
  -- Nimmt das Eingangssignal A_OE und A_CE und verknüpft es.
7
  Check_Request : process(A_OE, A_CE)
8
  begin
9
    A_Request <= '0';                    -- Pauschal keine Anforderung annehmen
10
    if A_OE = '0' and A_CE = '0' then    -- Liegt doch eine Anforderung vor, ...
11
      A_Request <= '1';                  -- ...dies signalisieren und Routing anfordern
12
    end if;                              --
13
    
14
  end process;
15
16
17
  
18
  -- Getakteter Prozess
19
  -- Nimmt das Zielsignal und wertet es aus.
20
  debug : process(CLK_16MHz)
21
    variable Last_State : STD_LOGIC_VECTOR(1 downto 0);
22
  begin
23
    if rising_edge(CLK_16MHz) then
24
      
25
      TestVec(0) <= '0';
26
      TestVec(1) <= '0';
27
      TestVec(2) <= '0';
28
      
29
      if X_Routing = "00" then          -- Wird aktuell Routing "00" angefordert, ...
30
        TestVec(0) <= '1';              -- ...Kanal 0 setzen
31
      end if;
32
      if Last_State = "00" then         -- Wurde bei der letzten Flanke Routing "00" angefordert, ...
33
        TestVec(1) <= '1';              -- ...Kanal 1 setzen
34
      end if;
35
      if X_Routing /= Last_State then   -- Wurde das Routing geändert, ...
36
        TestVec(2) <= '1';              -- ...Kanal 2 setzen
37
      end if;
38
      
39
      Last_State := X_Routing;          -- Aktuelles Routing für nächste Flanke merken
40
      
41
    end if;
42
  end process;

und
1
-- ####################################################
2
-- ##################### Entity 2 #####################
3
-- ####################################################
4
5
  -- Kombinatorischer Prozess
6
  -- Wertet das Signal aus.
7
  Review_Request : process(A_Request)
8
  begin
9
    if A_Request = '1' then
10
      X_Routing <= "00";
11
    else
12
      X_Routing <= "11";
13
    end if;
14
  end process;


Nur leider funktioniert das Design so nicht. Offenbar hat er Probleme, 
über die Grenzen einer Entity hinweg ein kombinatorische Signal zu 
leiten. Das Bild im Anhang habe ich mit einem Logikanalysator 
aufgenommen. Obwohl der Vektor an den rot markierten Stellen 
zweifelsohne von "11" auf "00" wechselt, wird dies nicht erkannt. Die 
Abtastfrequenz ist natürlich lang genug (ca. 3x T_Signal)

Warum ist das so? Kann man das über die Entity-Grenzen hinweg kein 
kombinatorisches Signal senden? Wenn nein, warum nicht? Sporadisch 
funktioniert es ja. Aber warum denn nicht permanent?!

Grüße
Steffen

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Steffen Hausinger schrieb:
> Kann man das über die Entity-Grenzen hinweg kein
> kombinatorisches Signal senden?
Doch, das geht problemlos.

> Warum ist das so?
Sind die beiden Signale A_OE und A_CE asynchron zum FPGA-Takt?
(es sieht so aus, aber leider ist genau der nicht mit im Screenshot)
Dann wundert mich das nicht, du hast ganz einfach ein asynchrones 
externes (und dazu noch kombinatorisch verknüpftes) Signal nicht 
einsynchronisiert. Und dann wird u.U. der Vergleicher (if X_Routing /= 
Last_State then) nicht mehr rechtzeitig fertig. Blöderweise bekommen die 
beiden FFs bei der Zuweisung (Last_State := X_Routing) den neuen Zustand 
aber offenbar schon mit... :-/
Fazit: du solltest aus diesem Kombinatorikpfad einen Takt komplett 
heraushalten, oder aber die Signale standesgemäß einsynchronisieren.
Zum Hintergrund das hier:
http://www.lothar-miller.de/s9y/archives/64-State-Machine-mit-asynchronem-Eingang.html
Dieses Beispiel passt hier wie die Faust aufs Auge, denn du hast 
eigentlich eine Statemachine (Last_State), die nicht richtig reagiert...

von Steffen Hausinger (Gast)


Lesenswert?

Lothar Miller schrieb:
> Sind die beiden Signale A_OE und A_CE asynchron zum FPGA-Takt?

Ja, das sind sie. Ich war mir über die Problematik gar nicht bewusst: 
Bisher ging ich davon aus, dass die Synchronisation eben in meinem 
ersten getakteten Prozess stattfindet. Nur eben nicht über die 
Eingangssignale A_OE und A_CE, sondern über X_Routing. Das 
kombinatorische Signale X_Routing bleibt aber konstant, so dachte ich.

Was muss ich jetzt machen? A_OE und A_CE über einen getakteten 
Prozess einsynchronisieren und zu A_OE_sync und A_CE_sync wandeln? 
Es gibt in FPGAs doch diese speziellen(?) "Ausgangs-FF" für synchrone 
Ausgangssignale. Gibt es die auch für Eingänge? Wenn ja, wie muss ich es 
beschreiben, damit sie verwendet werden? Es geht um einen Spartan 3E.

Grüße
Steffen

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Steffen Hausinger schrieb:
> Bisher ging ich davon aus, dass die Synchronisation eben in meinem
> ersten getakteten Prozess stattfindet.
Da hast du dir selber Sand in die Augen gestreut. Für den Synthesizer 
gibt es das Signal "X_Routing" eigentlich gar nicht. Der optimiert sich 
da aus seiner internen Wahrheitstabelle selber was zusammen.

> Es gibt in FPGAs doch diese speziellen(?) "Ausgangs-FF" für synchrone
> Ausgangssignale. Gibt es die auch für Eingänge?
Nein.
Aber das ist gar nicht dein Problem...

> Was muss ich jetzt machen?
Du mußt
1. die Beschreibung so ändern, dass die Signale eingetaktet werden:
1
  -- Getakteter Prozess
2
  -- Nimmt das Zielsignal und wertet es aus.
3
  debug : process(CLK_16MHz)
4
    variable Very_Last_State : STD_LOGIC_VECTOR(1 downto 0);
5
    variable Last_State : STD_LOGIC_VECTOR(1 downto 0);
6
  begin
7
    if rising_edge(CLK_16MHz) then
8
      
9
      TestVec(0) <= '0';
10
      TestVec(1) <= '0';
11
      TestVec(2) <= '0';
12
      
13
      if X_Routing = "00" then          -- Wird aktuell Routing "00" angefordert, ...
14
        TestVec(0) <= '1';              -- ...Kanal 0 setzen
15
      end if;
16
      if Last_State = "00" then         -- Wurde bei der letzten Flanke Routing "00" angefordert, ...
17
        TestVec(1) <= '1';              -- ...Kanal 1 setzen
18
      end if;
19
      if Very_Last_State /= Last_State then   -- Wurde das Routing geändert, ...
20
        TestVec(2) <= '1';              -- ...Kanal 2 setzen
21
      end if;
22
      
23
      Last_State := X_Routing;          -- Aktuelles Routing für nächste Flanke merken
24
      Very_Last_State := Last_State;
25
      
26
    end if;
27
  end process;

2. und dann bewerten, ob damit dein Design überhaupt klarkommt.
Denn mit dem Eintakten bekommst du automatisch Latency. Dein TestVec(2) 
kommt jetzt einen Takt später.

BTW: Ein Output Enable OE Signal dient idR. zur Umschaltung einer 
Busrichtung (Lesen). Das sollte daher direkt auf die Tristatetreiber des 
FPGAs gelegt werden. Sonst könntest du dir durch die erwähnte Latency 
einen Buskonflikt einhandeln...  :-o

von Duke Scarring (Gast)


Lesenswert?

Steffen Hausinger schrieb:
> Sporadisch
> funktioniert es ja. Aber warum denn nicht permanent?!

Solche Aussagen kommen sehr häufig, wenn asynchrone Sachen nicht richtig 
behandelt werden :-) (BTDT)

Duke

von Rene B. (themason) Benutzerseite


Lesenswert?

@Lothar

Würde es sich denn nicht anbieten einfach A_CE und A_OE 
einzusynchronisieren. Der Rest der komb. Logik ist dann ja auch 
synchron.

Also einfach ein :

signal a_oe_s : std_logic;
signal a_ce_s : std_logic;

process (clk, res)
begin
  if rising_edge(clk) then
    if res = '1' then
      a_oe_s <= '0';
      a_ce_s <= '0';
    else
      a_oe_s <= a_oe;
      a_ce_s <= a_ce;
    end if;
  end if;
end process;

Evtl. noch mit einem weiteren Einsynch-FF pro Leitung.
Müsste doch auch funktionieren oder nicht ?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Rene Böllhoff schrieb:
> Müsste doch auch funktionieren oder nicht ?
Ja, das wird es auch tun.
Allerdings würde ich den Reset hier rauslassen, damit nicht unnötig 
Routingressourcen verbraucht werden. Und wehe, wenn dieser scheinbar 
synchrone Reset hier wieder an einen asynchronen Resettasterpin 
angeschlossen ist... ;-)

von Steffen Hausinger (Gast)


Lesenswert?

Nein, Reset habe ich völlig aus meiner Schaltung verbannt. Obwohl ich 
eine zeitlang nicht wusste, wie ich dann der Schaltung mitteilen soll, 
ab wann der DCM einen sauberen Takt liefert. Ich habe es schließlich mit 
der Einstellung "wait until lock goes high" (oder so ähnlich) gelöst.


Ich werde mich dann auch dafür entscheiden, A_OE und A_CE zu 
synchronisieren. Dann komme ich auch in anderen Prozessen gar nicht erst 
auf die Idee, die unsynchronisierten Varianten zu nehmen.


Lothar Miller schrieb:
> BTW: Ein Output Enable OE Signal dient idR. zur Umschaltung einer
> Busrichtung (Lesen). Das sollte daher direkt auf die Tristatetreiber des
> FPGAs gelegt werden. Sonst könntest du dir durch die erwähnte Latency
> einen Buskonflikt einhandeln...  :-o

Ich habe das zwar in einer StateMachine gelöst, weil auch noch weitere 
(externe) Treiber umgeschaltet werden müssen, aber das interessiert mich 
jetzt doch: wie lege ich das Signal direkt auf den Tristatetreiber des 
IOB? Macht die Synthese das automatisch, wenn ich etwas schreibe wie
1
if A_OE = '0' then
2
    Data_out <= (others=>'Z');
3
end if;

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Steffen Hausinger schrieb:
> Macht die Synthese das automatisch, wenn ich etwas schreibe wie...
Ja. Aber du mußt hier sinnvollerweise noch ein wenig weiter vorn 
anfangen:
Bereits in der Top-Level-Entity muß dieser Bus, der ja ein 
bidirektionaler Datenbus vom und zum uC ist, als inout deklariert 
werden.

Und dann geht das so (mal von einem low-aktiven OE-Signal ausgegangen):
1
process (A_OE, FPGADataOut) begin
2
  if A_OE = '1' then  
3
    Datenbus_uC <= (others=>'Z');
4
  else 
5
    Datenbus_uC <= FPGADataOut;
6
  end if;
7
end process;
8
9
FPGADataIn <= Datenbus_uC;

Ich selber schreibe das lieber concurrent (ohne Prozess):
1
Datenbus_uC <= FPGADataOut when A_OE = '0' else (others=>'Z');
2
FPGADataIn <= Datenbus_uC;

von Rene B. (themason) Benutzerseite


Lesenswert?

>Und wehe, wenn dieser scheinbar synchrone Reset hier wieder an einen
>asynchronen Resettasterpin angeschlossen ist... ;-)

Mist. Ich sollte mich nicht immer angesprochen fühlen bei sowas. Ja ja. 
Ich änder meine 500 Prozesse ja schon ab um den Reset ebenfalls synchron 
zu machen :-)))

Aber da mal eben eine Offtopic frage zu dem Thema.
Und zwar du meintest das ein Asynchroner Reset u.u auch Probleme mit dem 
Routen des Designs geben kann. Ich habe bei meinem Audio-Projekt das 
Problem gehabt das ich einen 32x32bit Multiplier in einem Takt verwendet 
habe. Das braucht natürlich sehr viele Interconnects. Da die 32Bit sowie 
die 64Bit Pfade an mehreren stellen benötigt werden und durch Register 
dargestellt werden habe ich auch ein asynchronen Reset. Nun habe ich das 
Problem das der Router stellenweise nicht fertig wird weil er 2-6 
Leitungen nicht immer Routen kann (congestion on net xyz). Kann ein 
Synchroner Reset da vllt auch helfen das Routingproblem zu lösen ? Ich 
bin mir da nicht ganz sicher obwohl ich eher denke das das Design durch 
den 32x32Bit-Multiplizierer einfach zu vollgestopft ist und der Router 
daher nicht fertig wird.
Aber generell würde mich mal interessieren wieviele Ressourcen durch 
einen asynchronen Reset mehr verbraten werden als bei einem synchronen. 
Gibt es da erfahrungen ? Ist das abhängig von der Anzahl der FF's die 
asynchron resettet werden, grob nach dem Motto : pro async FF wird ein 
Slice zusätzlich "verschwendet" ?
Ich gebe dir recht das der asynchrone Reset eigentlich Mist ist, aber 
bei mir hats soweit immer funktioniert. Was nicht heißt das es gut war, 
das weiß ich selbst :)). Aber wieviele Ressourcen weniger würden durch 
einen synchronen Reset benötigt werden ? Ich meine das endet dann ja 
auch irgendwo in Laufzeit und benutzten Slices/Logik die dann für andere 
Dinge wieder frei werden würde/könnte.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Rene Böllhoff schrieb:
> Aber generell würde mich mal interessieren wieviele Ressourcen durch
> einen asynchronen Reset mehr verbraten werden als bei einem synchronen.
Das beginnt schon ziemlich früh im Chip: direkt an den FFs...  :-o
Siehe den Beitrag "Re: Hardware mit VHDL "richtig" beschreiben."

Und sehr überaus lesenswert die beiden Xilinx Whitepaper
WP275 "Get your priorities right"
http://www.xilinx.com/support/documentation/white_papers/wp275.pdf
WP272 "Get Smart About Reset: Think Local, Not Global"
http://www.xilinx.com/support/documentation/white_papers/wp272.pdf

> Da die 32Bit sowie die 64Bit Pfade an mehreren stellen benötigt werden
> und durch Register dargestellt werden habe ich auch ein asynchronen Reset.
Wozu?

von Duke Scarring (Gast)


Lesenswert?

Rene Böllhoff schrieb:
> Aber generell würde mich mal interessieren wieviele Ressourcen durch
> einen asynchronen Reset mehr verbraten werden als bei einem synchronen.
> Gibt es da erfahrungen ?

Ich hatte mal die XST-Option async_to_sync ausprobiert. Bei manchen 
Designs wurden ein paar Slices eingespaart, bei anderen waren es ein 
paar Slices mehr. Das es sich signifikant auf timing/routing ausgewirkt 
hätte, kann ich nicht behaupten.

Aber das kann bei anderen Designs natürlich anders aussehen...

Duke

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Duke Scarring schrieb:
> Das es sich signifikant auf timing/routing ausgewirkt hätte, kann ich
> nicht behaupten.
Das hätte eigentlich ich auch erwartet. In einem "normalen" Design 
mitteln sich die Vorteile heraus. Es geht eher darum, darüber 
nachzudenken, ob überhaupt ein Reset nötig ist...

von Rene B. (themason) Benutzerseite


Lesenswert?

@Lothar

Die betrachtung in welchen Prozessen ich einen Reset brauche oder nicht 
müsste ich auch nochmal für die Designs machen. Ist einfach eine Art 
Mechanismus erstmal einen Reset vorzusehen. Meist "rüste" ich den Reset 
nach wenn ich in der Simulation sehe das Signale undefiniert sind. Das 
ich aber in z.b. einem Multiplizierer mit nachgeschaltetem Register 
meist keinen Reset brauche da beim nächsten Takt ja ohnehin ein gültiges 
Datenwort (gültige Eingangsworte vorausgesetzt) anliegt, es sei denn ich 
hab bei dem Multiplizierer ein Enable, dann könnte (bzw wird) das 
Ausgangswort ja undefiniert sein, solange wie nicht einmal ein Enable 
gekommen ist. (Hoffe ich konnte das nun richtig erklären :-))

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.