www.mikrocontroller.net

Forum: FPGA, VHDL & Co. MUX mit bidirektionalem Pin


Autor: Manuel F. (ombre5733)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo an alle!

Ich bin Neuling was VHDL-Programmierung betrifft und bräuchte bitte
einen Rat eurerseits.
Ich möchte gerne einen 2:8 Multiplexer erstellen bei dem die Richtung
eines Pins umschaltbar ist. Der Eingang SEL legt fest, wie die Pins
A und B auf Y gelegt werden. Wenn DIR auf 1 liegt, soll B ein Eingang
sein (Signalfluss B -> Y) und sonst ein Ausgang (Signal also vom
jeweiligen Y-Pin zurück nach B).
Kann man das mit einem temporären Signal erledigen? Was mir vorschwebt
ist in etwa folgendes:

entity MYMUX is
  port (
    SEL : in STD_LOGIC_VECTOR(2 downto 0);
    DIR : in STD_LOGIC;  -- Richtung der Uebertragung B <-> Y
    A : in STD_LOGIC;
    B : inout STD_LOGIC;
    Y : inout STD_LOGIC_VECTOR(8 downto 0));
end MYMUX;

architecture BEHAVORIAL of MYMUX is
  signal B_TEMP : STD_LOGIC;
begin
  MUX_PROCESS : process(SEL, READ, A, B, Y)
  begin
    -- kann man das so loesen? --
    if DIR = '1'
      -- DIR = 1: B -> Y
      B <= 'Z';
      B_TEMP <= B;
    else
      -- DIR = 0: Y -> B
      B_TEMP <= 'Z';
      B <= B_TEMP;
    end if;
    -- kann man das so loesen? --

    -- 2:8 Multiplexer
    case SEL is
      when "000" => Y <= (0 => A, 1 => B_TEMP, others => 'Z');
      when "001" => Y <= (1 => A, 3 => B_TEMP, others => 'Z');
      when "010" => Y <= (5 => A, 6 => B_TEMP, others => 'Z');
      ...
      when others => Y <= (others => 'Z');
    end case;
  end process MUX_PROCESS;
end

Bin für alle Anregungen dankbar!

Beste Grüße,
Manuel

Autor: Der Besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ohne jetzt die richtige Funktionalität Deines Multiplexers genau zu 
beachten
sehe ich bei Deiner Beschreibung ein kleines Problem:
B_TEMP sollte ín Deinem Code eine Variable sein, wenn B oder Y im selben 
Simulationszyklus darauf zugreifen wollen. Irgendwie erscheint mir dein 
Multiplezer etwas kompliziert gedacht. Überlege, ob die 
Bidirektionalität wirklich notwendig ist. Meist handelt man sich damit 
mehr Probleme ein, als man auf den ersten Blick sieht.

Der Besucher

Autor: Der Besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nachtrag:
auch fehlt irgendwie die Zuweisung von Y nach B in deinem Code.
Und das READ Signal in den Sensitivity Liste benötigst Du in Deinem
Beispiel auch nicht.

Aber ausprobieren und Fragen sind schonmal der beste Weg zum Erfolg!

Der Besucher

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Und das READ Signal in den Sensitivity Liste benötigst Du in Deinem
> Beispiel auch nicht.
Richtig, zuviel vom Falschen drin:
unvollständige Sensitivity-Liste
  MUX_PROCESS : process(SEL, READ, A, B, Y)
  begin
    if DIR = '1'
    :
    :
DIR fehlt --> Simulation falsch  :(

Autor: Der Besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo, stimmt.
Sicherlich wurde READ irgendwann in DIR umbenannt. Nur sollte der 
Compiler eigentlich meckern, da er READ nun nicht kennt. Vielleicht eine 
VHDL-Trockenübung ohne Simulation?

Der Besucher

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nochmal angeschaut:
> B_TEMP sollte ín Deinem Code eine Variable sein, wenn B oder Y im selben
> Simulationszyklus darauf zugreifen wollen.
Nein, eine Variable muß das nicht sein, aber B_TEMP sollte in die 
Sensitivity-List, denn wenn sich B_TEMP ändert, kann sich auch der 
Ausgang ändern.  ;-)

Wieso behandelt du diese Signalpfade A und B nicht getrennt?
1)  A ist unidirektinal, also ein ordinärer Multiplexer
2)  B ist bidirektonal und braucht ein wenig Sonderbehandlung...

> when "000" => Y <= (0 => A, 1 => B_TEMP, others => 'Z');
Das geht nicht, denn es wird zwar B_TEMP auf Y(1) zugewiesen, aber nicht 
automatisch auch Y(1) auf B_TEMP.
In deiner Beschreibung fehlt der "Rückwärtsgang" von Y nach B  :-/

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

READ sollte eigentlich DIR heißen, richtig. Ich hab den Code gerade
erst geschrieben und noch gar keine Simulation gemacht.

@Lothar:
Danke fuer die Anregung mit der Aufteilung! Wenn ich es richtig
verstanden habe, meinst du so etwas in der Art:

-- praeventiv alles auf Z setzen
B <= 'Z';
Y <= (others => 'Z');

-- Mux fuer A
case SEL is
  when "000" => Y(0) <= A;
  when "001" => Y(1) <= A;
  when "010" => Y(5) <= A;
  ...
  when others => null;
end case;

if DIR = '1'
  -- Mux B -> Y
  case SEL is
    when "000" => Y(1) <= B;
    when "001" => Y(3) <= B;
    when "010" => Y(6) <= B;
    ...
    when others => null;
  end case;
else
  -- Mux B -> Y
  case SEL is
    when "000" => B <= Y(1);
    when "001" => B <= Y(3);
    when "010" => B <= Y(6);
    ...
    when others => null;
  end case;
end if;

Grüße,
Manuel

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> meinst du so etwas in der Art...
Der Ansatz scheint mir nicht ganz falsch  ;-)

BTW:
Wenn du deine case komplett auscodierst
  when "000" => Y(0) <= A;
  when "001" => Y(1) <= A;
  when "010" => Y(5) <= A;
  ...
  when "111" => Y(3) <= A;
dann ist der
  when others => null;
unnötig, denn er wird nicht synthetisiert.

-- praeventiv alles auf Z setzen
Y <= (others => 'Z');
Der Kommentar leitet etwas in die Irre, denn damit wird nicht 
vorsorglich was gesetzt, sondern durch diese Zeile erhältst du 
Kombinatorik. Ohne diese Zeile bekämst du u.U. Latches :-/

Autor: Manuel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Super! Vielen Dank für die Hilfe. Ich werd heut abend mal probieren,
ob ich es jetzt hinbekomme. Der Code ist jetzt zwar 3x so lang, wie
ursprünglich geplant, aber hauptsache er läuft ;-)

Danke nochmal für den ganzen Input!

/Manuel

Autor: Der Besucher (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn dir der Code zu lang wird kann man den bestimmt auch kürzer 
schreiben.
Nur ist dann fraglich, ob der dann noch auf die schnelle verständlich 
bleibt.
Wenn du den kompletten MUX fertig hast kann man ja mal schauen wo man 
optimieren kann. Ich denke mal, das man z.B. auf die cases verzichten 
kann (aber und nicht durch elsif). Hängt aber von der gewünschten 
Kodierung ab.

Der Besucher

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Der Code ist jetzt zwar 3x so lang...
Langer Code bedeutet nicht unbedingt auch großes Design.

BTW:
> ...dann ist der
  when others => null;
> unnötig, denn er wird nicht synthetisiert.
Ich korrigiere mich, lass den besser drin  ;-)

Autor: Maximilian .. (maxpautsch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich bin auch dafür ihn drin zu lassen, da es eine case-anweisung ist, 
die von einem std_logic_vector abhängig ist.
alles "auszucodieren" dürfte schwer/langweilig werden, wenn man die 
restlichen zustände außer "0" und "1" auch noch berücksichtigt ;)

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.