MUX mit bidirektionalem Pin

OP #1141661
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
Gast #1141785
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
Gast #1141802
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
Moderator (Firma: Titel) Persönliche Seite #1141973
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  :-/
Gast #1142119
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
Moderator (Firma: Titel) Persönliche Seite #1142185
Lesenswert?

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

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

1
-- praeventiv alles auf Z setzen
2
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 :-/
Gast #1142278
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
Gast #1142318
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren