www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Pin als In oder Out konfigurieren, abhängig von einzelnem B


Autor: Tobias Plüss (hubertus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich bin am Experimentieren mit VHDL. Nun wollte ich einen simplen 
Peripheriebaustein machen, der ein paar paralelle I/Os hat und einen 
Datenbus, um ihn mit einem MC zu verbinden.
Dazu habe ich Mehrere Register definiert: einmal ein Datenregister pro 
Port, und dann noch ein Richtungsregister. Die einzelnen Register sind 
über einen Adressbus- und Datenbus auswähl-, beschreib- und lesbar.
Das ganze funktioniert mehr oder weniger: Schreibt man in das 
Datenregister, erscheinen die Daten auch am gewünschten Port. Umgekehrt 
kann man natürlich den geschriebenen Wert zurücklesen. Nun möchte ich 
aber noch das Richtungsregister mit einbeziehen: Steht an irgend einer 
Stelle des 8 Bit breiten Registers eine 1, ist das entsprechende Bit des 
zugehörigen Ausgangsports immer auf Z, unabhängig davon, was im 
Datenregister steht.

Beispiel:

Datenregoster =       11110000
Richtungsregister =   00000000 (ganzer Port ist Ausgang)
Signale an den Pins = 11110000 (Signale werden 1:1 ausgegeben)

Datenregiser =        11110000
Richtungsregister =   11100000 (erste 3 Bit Eingang, rest Ausgang)
Signale an den Pins = ZZZ10000

Nun ist die Frage, wie man das macht. Ich könnte natürlich jedes 
einzelne Bit der entsprechenden Signale abfragen und "von Hand" den Pin 
auf Z oder 1 oder 0 setzen. Wie könnte man es einfacher lösen?

Noch genialer wäre es, wenn jeder Pin ein Open Drain wäre, und einfach 
per internen Pullup nach VCCIO gezogen würde (Altera Cyclone II FPGAs 
haben ja zuschaltbare Pullups). Wie könnte man die Pins als Open Drain 
konfigurieren? Und wie schaltet man die "weak pullup resistors" ein?
Ich verwende Quartus II 7.2. Der Code soll später in einem Cyclone II 
EP2C8 laufen (wenn mein Board mal fertig ist, was noch etwas dauert. Bis 
dann begnüge ich mich mit dem Simulator...)

Ideen?

Grüsse
     Tobias

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Tobias Plüss (hubertus)

>kann man natürlich den geschriebenen Wert zurücklesen. Nun möchte ich
>aber noch das Richtungsregister mit einbeziehen: Steht an irgend einer
>Stelle des 8 Bit breiten Registers eine 1, ist das entsprechende Bit des
>zugehörigen Ausgangsports immer auf Z, unabhängig davon, was im
>Datenregister steht.

>Nun ist die Frage, wie man das macht. Ich könnte natürlich jedes
>einzelne Bit der entsprechenden Signale abfragen und "von Hand" den Pin
>auf Z oder 1 oder 0 setzen. Wie könnte man es einfacher lösen?

Mit einer Schleife.


-- Datenumschaltung per Registerbits, Push Pull Ausgang

l_label: for i in 0 to 7 generate
  my_port(i) <= my_data(0) when my_ddr(i)='1' else 'Z';
end generate;

-- Datenausgang ohne Richtungssteuerung, Open Drain Ausgang
-- wie PCF8574

l_label: for i in 0 to 7 generate
  my_port(i) <= '0' when my_data(i)='0' else 'Z';
end generate;


>Noch genialer wäre es, wenn jeder Pin ein Open Drain wäre, und einfach

Warum? Open Drain liefert kaum Strom bei HIGH. Kann man aber machen.

>konfigurieren? Und wie schaltet man die "weak pullup resistors" ein?

Kann man in den Tools zuweisen. Kenn mich bei Altera nicht so aus.

MFG
Falk

Autor: Tobias Plüss (hubertus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Falk,
danke. Warum ich Open Drain verwenden wollte: Das wäre insofern ideal, 
weil man dann nämlich folgendes tun kann: Wenn man bei einem Port 
abwechslungsweise Daten ausgeben und wieder einlesen will muss man 
normalerweise immer die Richtung vorher umschalten. So aber könnte man 
einfach die Port-Daten auf 11111111 setzen. Der Ausgang wäre dann 
hochohmig und würde auf VCCIO gezogen und von dem Gerät, das an den Pins 
angeschlossen ist dann auf GND oder wieder VCCIO. So hätte man dan 
IO-Ports ähnlich wie beim 8051, wo man ja auch 11111111 auf den Port 
schreibt, um ihn als Eingang zu konfigurieren.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Tobias Plüss (hubertus)

>IO-Ports ähnlich wie beim 8051, wo man ja auch 11111111 auf den Port
>schreibt, um ihn als Eingang zu konfigurieren.

Igitt, wer will denn sowas? Das ist ein Relikt aus längst vergangener 
Zeit. Nimm Push Pull Ausgänge.

MFG
Falk

Autor: Tobias Plüss (hubertus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Push Pull Ausgänge? Schon gehört, weiss aber nicht genau was es ist.

Autor: Karl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Push-Pull ist sozusagen das "normale", mit einem Transistor gegen Vdd 
und einem gegen Masse.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Tobias Plüss (hubertus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Info.
Hey Falk, das weisst du sicher auch:
Ich möchte in einem D-FF ein bestimmtes Bit speichern, und zwar wenn 2 
Signale auf Low sind. Das Bit soll sowohl übernommen werden, wenn an CS 
low liegt und an WR eine fallende Flanke auftritt, als auch wenn WR auf 
low ist und an CS eine fallende Flanke anliegt. Also immer auf die 
jeweils spätere fallende Flanke. Natürlich könnte ich sowas machen:

signal s : std_logic;
s <= cs or wr;

process(s)
begin
   if falling_edge(s) then
       ...
   end if;
end process;


dann habe ich aber einen "gated clock", was man ja nicht tun soll. Gibts 
eine Möglichkeit, das Problem zu umgehen? so gehts nicht:

if falling_edge(cs) or falling_edge(wr) then ...

Autor: Andreas Schwarz (andreas) (Admin) Benutzerseite Flattr this
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Tobias Plüss (hubertus)

>Ich möchte in einem D-FF ein bestimmtes Bit speichern, und zwar wenn 2
>Signale auf Low sind. Das Bit soll sowohl übernommen werden, wenn an CS
>low liegt und an WR eine fallende Flanke auftritt, als auch wenn WR auf
>low ist und an CS eine fallende Flanke anliegt. Also immer auf die
>jeweils spätere fallende Flanke. Natürlich könnte ich sowas machen:

Das geht so nicht. Du musst dich schon entscheiden, welches Signal als 
Takt/Strobe verwendet werden soll.
process(wr)
begin
   if falling_edge(wr) then
      if cs='0' and sig1='0' and sig2='0' then
         my_sig <= '1';
      end if;
   end if;
end process;


>dann habe ich aber einen "gated clock", was man ja nicht tun soll. Gibts
>eine Möglichkeit, das Problem zu umgehen? so gehts nicht:

Was soll das denn werden? Ich bin sicher, dass man nicht auf zwei 
Flanken reagieren muss.

MFG
Falk

Autor: Jan M. (mueschel)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sowohl WR als auch CS scheinen keine "richtigen" Clock-Signale zu sein. 
Deswegen solltest du besser ein FF mit der normalen Clock betreiben und 
dir aus beiden Signalen ein Clockenable generieren:
if rising_edge(CLK) then
  if (WR = 0 and last_WR=1) or (CS = 0 and last_CS = 1) then
...

last_WR / last_CS ist dann jeweils das um einen Takt verzögerte Signal 
WR / CS (einfach durch ein FF geleitet).

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Jan M. (mueschel)

>Sowohl WR als auch CS scheinen keine "richtigen" Clock-Signale zu sein.

Sind es auch nicht, es sind Strobesignale.

>Deswegen solltest du besser ein FF mit der normalen Clock betreiben und
>dir aus beiden Signalen ein Clockenable generieren:

Kann man machen, kann aber bisweilen kniffelig und aufwändig werden.
Normalerweise reicht es, WR ODER CS als Takt für Scheiboperationen zu 
verwenden. Damit kann man jeden uC anschliessen.

MFG
Falk

Autor: Tobias Plüss (hubertus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk:
> Was soll das denn werden? Ich bin sicher, dass man nicht auf zwei
> Flanken reagieren muss.

Eigentlich muss man ja auch nicht auf 2 Flanken reagieren. Aber in 
Datenblättern von Flash oder RAM-Bausteinen beispielsweise steht oft 
"Data is latched on the falling edge of WE or CE, whichever happens 
first" und solche Sachen. Genau solches Timingverhalten möchte ich auch 
für meinen eigenen Peripheriebaustein haben.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Tobias Plüss (hubertus)

>"Data is latched on the falling edge of WE or CE, whichever happens
>first" und solche Sachen. Genau solches Timingverhalten möchte ich auch
>für meinen eigenen Peripheriebaustein haben.

Vergiss es. Sowas ist nicht sinnvoll und in CPLDs/FPGAs nur schwer 
umsetzbar. Das ist nur eine Erbe der alten asynchronen uC Busse. 
Entscheide dich für ein Signal.

MFG
Falk

Autor: Tobias Plüss (hubertus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Okay. Im Artikel "VHDL Flankenerkennung" stand allerdings, dass man 
falling_edge() und rising_edge() nur für Clock-Signale benutzen 
darf/soll. Funktioniert es denn überhaupt, wenn ich ein "gewöhnliches" 
Signal als Clock benutze? Oder muss ich das tatsächlich irgendwie 
umbauen, dass ich mit Clock Enables arbeite?

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Tobias Plüss (hubertus)

>darf/soll. Funktioniert es denn überhaupt, wenn ich ein "gewöhnliches"
>Signal als Clock benutze?

Ja.

> Oder muss ich das tatsächlich irgendwie
> umbauen, dass ich mit Clock Enables arbeite?

Nein.

MFg
Falk

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.