mikrocontroller.net

Forum: FPGA, VHDL & Co. VHDL-Tristatebuffer will nicht


Autor: Sebastian H. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich versuche gerade einen Tristatebuffer in VHDL zu implementieren aber
irgendwas stimmt da nicht. In CFG_DATA müssten doch nach dem Einschalten
der Spannung nur Nullen stehen. Das ist aber nicht der Fall da ich bei
meinem Aufbau zwei Bit von CFG_DATA auf LEDs ausgebe und die leuchten
(also muß da wohl eine 1 drin stehen).
Ich bin mir sicher ihr seht den Fehler sofort und könnt mir sagen woran
es liegt!

Danke & Gruß,
Sebastian H.

Autor: Sven Johannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin...

Bist du sicher, dass dein FPGA (welcher?) Tri-Buffer hat?

Ansonsten ziemlich unangenehm zu lesen, aber wenn mit dem ganzen
asynchronen Gehühner nichts Unerwartetes passiert, sollte tatsächlich
eine '0' an CFG_Data anstehen.

--
 SJ

Autor: Sebastian H. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

ich verwende einen XC9572 und der hat doch laut DB Tri-Buffer.
Das asynchrone Gehühner gefällt mir auch nicht, hab aber noch nie
einen
Tri-Buffer verwendet und weiß nicht so wirklich wie ich das WR und RD
Signal gleichzeitig vernünftig handhaben soll.

Constraints Editor (Ports) stehen manche als TRI OUTPUT und manche als
BIDIR drin. ??? (siehe Anhang)

Wäre schon wenn du mir ein paar Tipps geben könntest wie man das
sinnvoll umsetzen kann.

Autor: Sven Johannes (svenj)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin...

Ein 9572 ist, nebenbei gesagt, ein CPLD, kein FPGA. Macht aber nichts,
nur die Benutzung dürfte sich ändern.

Dem Bus <D> werden da verschiedene Funktionen angedacht. Einige sind
Bidirektional, also Ein-/Ausgänge, andere sind die gewünschten Tristate
Buffer. Schon reichlich herb das in einem Bus zu mischen...

Auf alle Fälle müssen alle Pin das gleiche IO Interface eingestellt
bekommen und um den Z State zu benutzen wirst du auch noch ein enable
Signal bedienen müssen. Finde ich jetzt so gar nicht in deinem Code.
Nebenbei: Bist du sicher das es einen InOut-Tristate Buffer gibt?

--
 SJ

Autor: Tobias O. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich weiss leider nicht wieso du soviel Code brauchst um einen Tristate
Buffer in VHDL zu beschreiben.

Bei mir sieht das so aus

IN_DATA    <= INOUT_DATA;
INOUT_DATA <= OUTDATA when WRITE_ENABLE = '1' else (others 'Z');

oder wenn WRITE_ENABLE ein Vector ist, dann vervielfache ich halt einen
einzelnen Buffer mittels Generate Anweisung.
Hinter dem Buffer sind dann halt die IO-Register platziert.
Hoffe das hilft dir weiter.

Autor: FPGAküchle (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Das Problem ist wohl das im Multiplexer einem SIGNAL 'Z' zugewiesen
wird. Da will der interne Tristates draus machen. Das geht zwar bei
Spartan2/2E, die haben interne tristates (TBUF) aber das willst du
nicht. Du willst nur einen Tristateport (also extern 'Z'). Also am
besten Z nur OUT oder INOUT PORTS der Top-Level zuweisen. Ansonsten
habe ich den Code etwas ent-"krautet".

Autor: FPGAküchle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm besser wäre wohl, statt:

[vhdl]
READ_BUS : IN_DATA <= D;

  SET_CFG_REG : PROCESS(WR)
  BEGIN
    IF WR = '1' AND WR'event THEN
      IF OUT_EN /= '1' THEN
        CFG_DATA <= IN_DATA;
      END IF;
    END IF;
  END PROCESS SET_CFG_REG;
[\vhdl]

besser:
Hm besser wäre wohl, statt:

[vhdl]
  SET_CFG_REG : PROCESS(WR)
  BEGIN
    IF WR = '1' AND WR'event THEN
      IF OUT_EN /= '1' THEN
        CFG_DATA <= D;
      END IF;
    END IF;
  END PROCESS SET_CFG_REG;
[\vhdl]

Autor: Sebastian H. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@ Sven

Hab nie behauptet, daß der 9572 ein CPLD ist, oder?
Das enable Signal sollte durch das OUT_EN realisiert werden. Mit dem
Tristate Buffer bin ich mir eigentlich ziemlich sicher, ob er InOut ist
aber nicht so.

---

Hab die Sache jetzt mal umgeschreiben. Hab aber jetzt ein anderes
Problem, der 9572 ist zu klein (91 statt 72). Kann mir irgendwie nicht
ganz vorstellen das ein Zähler (bis 44) und der Rest (siehe Anhang)
nicht in den 9572 passt. Kann man die Schieberegister nicht anders an
den Tristate Buffer anschliessen?

Gruß,
Sebastian

Autor: FPGAküchle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach doch aus den write enables ein shiftregister, spart counter und
decoder.

Autor: Tobias O. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schick mal zu deinem VHDL auch die Entity mit damit man mal die ISE
anwerfen kann um sich das ganze als RTL anzuschauen.

Autor: Sebastian H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Code (funktioniert soweit und passt rein) und die Tipps!
Werd alles nochmal überarbeiten. Ich muß jetzt erstmal eine Verdrahtung
auf der Platine checken, ob da alles stimmt.

Gruß,
Sebastian

Autor: FPGAküchle (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder mit richtigen counter:
signal RD_CNT : STD_LOGIC_VECTOR(2 downto 0) := (others => '0');

WRITE_ENABLE: process(RD, RESET)
begin
  if RESET = '1' then
    RD_CNT := (others => '0');
  elsif RD = '0' and RD'event then
             if rd_cnt = "011" then
                rd_cnt <= "000";
             ELSE 
                 RD_CNT <= RD_CNT +1;
             END IF;
  end if;
end process WRITE_ENABLE;

      WRITE_4_ENABLE <= '1' WHEN RD_CNT = "011" ELSE '0';
      WRITE_3_ENABLE <= '1' WHEN RD_CNT = "010" ELSE '0';
      WRITE_2_ENABLE <= '1' WHEN RD_CNT = "001" ELSE '0';
      WRITE_1_ENABLE <= '1' WHEN RD_CNT = "000" ELSE '0';


Allerdings sind die enables jetzt ungebuffert, aber spart FF und ein
CPLD ist schnell genug. Dann kannst Du noch ein paar Optimierungen
anschalten. Du optimierst doch auf AREA?

Autor: Sebastian H. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Wollte mich schon eher melden, bin aber mal wieder nicht auf die Seite
gekommen. (Error 505)

Hab jetzt das Konfigurationsregister rausgeworfen. Mußte die
Lesezugriffe auf drei begrenzen da die FF sonst nicht ausgereicht
hätten. Der Counter erhöht sich jetzt bei der steigenden Flanke.
Dadurch wollte ich sicherstellen das die ENABLE Signale nicht während
des Lesezugriffs umschalten.

Im Constraints Editor (Ports) stehen jetzt alle Ds als TRISTATE drin.

An den Optimierungen hab ich nichts verstellt. Sind alle auf Default.

Das komplette Projekt (von CPLD1) hängt im Anhang. Ich hoffe doch, dass
euch .rar keine Probleme macht.
Die Signale IN_1 und IN_2 kommen von einem zweiten CPLD.

Bekomme jetzt aber eine Warnung:

WARNING:Cpld:158 - We have detected that a large number of internal
signals may be switching at the same time. To avoid potential
simultaneous switching/ground bounce issues, please contact Xilinx
customer support for more information.

Gruß,
Sebastian

Autor: FPGAküchle (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
-Optimieren auf wenig FF: Hab mal (wieder) screenshots von Einstellungen

 beigefügt, die vielleicht noch 10-20 % FF sparen.

-Warning: soll heissen an den Flanken der Outputs können heftige
Unter/Überschwinger sein und man sollte die Betriebsspannung richtig
gebuffert haben (mind. 10/100 nf an jedem Vcc/GND Pärchen. Beim FPGA
würde ich sagen unkritisch, CPLD habe ich mit der warning noch nicht
praktisch ausprobiert.

Mal Scope dranhängen, ich hätte aber auch beim CPLD erstmal keine
bedenken.

Autor: FPGAküchle (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hm, ich habe den counter in einen extra Process geschoben, so wie der
beschrieben wahl (an vier stellen inkrement) wird der XST wohl kein
countermakro sondern wüste Logik (gross) einfügen.

Problem könnten auch die drei Signale mit 'event sein, heisst drei
taktnetzwerke. Die XC95xxx sind wohl für 1 oder 2 Taktnetzwerke (?)
optimiert.

Statt 'event besser rising_edge() oder falling_edge(), macht (fast)
dasselbe, ist die selbe Hardware aber übersichtlicher.

Anbei der überarbeitete Code (evtl. inkl. Tipp- & Dengfehler).

Autor: Sebastian H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke!

Hat fast alles gepasst. Die rising_edge() oder falling_edge()
Funktionen sind nur mit den BIT-Typ nicht zufrieden gewesen.

Es macht den Anschein als wäre die(oder doch das/der) RTL-Schematic
jetzt übersichtlicher.

Irgendwas stimmt halt mit den Tristate-Buffer noch nicht. Sobald ich
die acht Datenleitungen an den Controller hänge steigt der aus.
Abblockkondensatoren verwende wo es nur geht. Die Versorgung ist auch
gut gepuffert. Außerdem haben Controller und die CPLDs nur eine
gemeinsame Masse. ???

Ich werd jetzt zum Test mal einen 74541 dazwischen hängen. Die Freigabe
werd ich mit den ENABLE Signalenerzeugen.

Gruß,
Sebastian H.

Autor: Sebastian H. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab den Fehler gefunden. Der Controller betätigt das RD Signal auch wenn
er auf interne Adressen zugreift. Und dann muß der Treiber aber
hochohmig bleiben, sonst dreht der Controller durch. Hab also noch nen
nen CS Signal dazugenommen. Jetzt funktioniert es soweit. Mal sehen wie
sich jetzt der Rest der Schaltung verhält. ;)

Hast du vielleicht noch eine Idee wie man den GTS-Pin nutzen kann. Hab
in der ISE nichts gefunden. (typisch Anfänger ;))
  WR_EN <= '1' WHEN (RD = '0' AND CS = '0') ELSE '0'; 

  WR_1_EN <= '1' WHEN (RD_CNT = "00" AND WR_EN = '1') ELSE
'0';
  WR_2_EN <= '1' WHEN (RD_CNT = "01" AND WR_EN = '1') ELSE
'0';
  WR_3_EN <= '1' WHEN (RD_CNT = "10" AND WR_EN = '1') ELSE
'0';

Gruß und Danke,
Sebastian H.

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Funktioniert das überhaupt?
WR_1_EN <= '1' when (RD_CNT = "00" and RD = '0') else '0'; 
WR_2_EN <= '1' when (RD_CNT = "01" and RD = '0') else '0';
WR_3_EN <= '1' when (RD_CNT = "10" and RD = '0') else '0';


D <=                 X_DATA(7 downto 0)  when WR_1_EN = '1' else (others =>
'Z');
D <=                 Y_DATA(7 downto 0)  when WR_2_EN = '1' else (others =>
'Z');
D <= X_DATA(11 downto 8) & Y_DATA(11 downto 8) when WR_3_EN = '1'
else (others => 'Z');

Du willst anscheinend 3 verschiedene Signal auf den gleichen Datenbus D
legen.
Die korrekte Hardware (-Beschreibung) dazu ist zuerst ein Multiplexer,
der zwischen den Signalen auswählt, und dann der Tri-State Block
selbst.
-- Zuerst der Multiplexer 
with RD_CNT select
    OutputData <=
        X_DATA(7 downto 0) when "00",
        Y_DATA(7 downto 0) when "01",
        D <= X_DATA(11 downto 8) & Y_DATA(11 downto 8) when "10",
        "--------" when others;

-- Dann der Tri-State Buffer
D <= OutputData when WR_EN = '1' else (others => 'Z');

Wenn in diesem Fall das WR_EN Signal direkt von einem GTS Pin kommt,
dann sollte das GTS verwendet werden.
Grüße
Klaus

Autor: Klaus Falser (kfalser)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag :
-- Dann der Tri-State Buffer
D <= OutputData when RD = '0' else (others => 'Z'); 

müßte funktionieren, wenn Du das RD Sigal auf einen GTS Pin legst.

Klaus

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.