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


von Manuel F. (ombre5733)


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

von Der Besucher (Gast)


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

von Der Besucher (Gast)


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

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


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
1
  MUX_PROCESS : process(SEL, READ, A, B, Y)
2
  begin
3
    if DIR = '1'
4
    :
5
    :
DIR fehlt --> Simulation falsch  :(

von Der Besucher (Gast)


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

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


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  :-/

von Manuel (Gast)


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

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


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 :-/

von Manuel (Gast)


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

von Der Besucher (Gast)


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

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


Lesenswert?

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

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

von Maximilian .. (maxpautsch)


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 ;)

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.