mikrocontroller.net

Forum: FPGA, VHDL & Co. VHDL: Multiplexer mit generischer Anzahl zu muxender Busse?


Autor: Stefan Wimmer (wswbln)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leute,

ich muss (mal wieder) einige interne Datenquellen (der Busabreite 
"Width") eines FPGAs auf einen externen Bus multiplexen. Um das Ganze 
nicht immer wieder neu schreiben zu müssen, bastelte ich mir schon vor 
langer Zeit diesen kleinen Generator, bei dem ich die Anzahl der Buse 
doch einfach über ein Generic parametrieren konnte. Das funzte auch ganz 
prima mit T-Bufs, solange ich auf der Xilinx-Schiene war:
--***************************************
-- Generate the Bus-Mux 
BMux:
for i in 0 to (NumOfIORegisters-1) generate
  StatusBus <= StatusBits(Width*i+width-1 downto Width*i) when ChipSelect(i) = '1' else (others => 'Z');
end generate;      

Nun muss ich andere FPGAs nehmen und die haben keine internen 
Tristate-Buffer. Wie baue ich einen generischen Multiplexer?

Also nochmal kurz:
- Ich habe eine Anzahl (NumOfIORegisters) von Bussen mit jeweils einem 
zugehörigen (highaktiven) ChipSelect.
- Von den ChipSelects kann auf Grund der Generierung immer nur einer 
aktiv sein.
- Ich brauche einen Muxer OHNE TBufs, der den jeweils aktiven Bus auf 
den Ausgangsbus routet
- Die Anzahl der vorhandenen Busse soll via Generic bei der 
Instantiierung festgelegt werden können.

Vielleicht ist es ganz einfach, aber irgendwie stehe ich gerade auf'm 
Schlauch....

Any Hints?

Autor: Martin Kohler (mkohler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe schon diverse ältere Designs mit TBUF probehalber in Spartan3E 
implementiert. Das geht problemlos, weil TBUFs automatisch in Logik 
umgewandelt werden können.
Da spare ich mir den Aufwand, das ganze explizit als MUX zu schreiben.

Autor: Stefan Wimmer (wswbln)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fein Martin, so habe ich es - wie schon geschrieben - bei den 
"X-Bausteinen" auch gemacht. Bloss hilft mir das nun nicht wirklich 
weiter, wo ich keine "X-Bausteine" einsetzen kann. Hast Du 'nen Tipp?

Autor: Falk (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Interne Tristates sind nicht das Mittel der Wahl. Ein generischer MUX 
ist besser, weil technologieunabhängig. Ausserdem haben alle neueren 
FPGAs keine internen Tristates mehr.
Was du willst ist eine Art Registerblock, der auf einem externen uC Bus 
lesbar ist? Das macht man zweistufig.

1.) MUX für Register
2.) IO Mux mit Tristates

Siehe Anhang

@ Martin Kohler

> Da spare ich mir den Aufwand, das ganze explizit als MUX zu schreiben.

Wo ist da der "Aufwand"?

MfG
Falk



Autor: Martin Kohler (mkohler)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Falk: Der Aufwand ist darin, ältere "Blackbox-Designs" auf einem 
Spartan2 auf neuere Spartan3E zu portieren.

@Stefan: Auch die Xilinx-Schiene hat ab Spartan3E keine Tristates mehr 
drin, darum schrieb ich ja auch, dass ebendiese in Logik umgewandelt 
werden und vom Tool in Logik (MUX) umgesetzt werden.

Autor: FPGA-User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Falk,

Dein Bsp. ist nicht zu Ende gedacht. Der Datenbus muss natürlich mit 
geändert werden und darf nicht fix 8 bit breit sein.
Außerdem könnte ich die Anzahl der Register jetzt auf 32 hochsetzen, nur 
der MUX unten in der case-Anweisung ändert sich nicht mit. Wenn ich bei 
meiner Simulation dann nur die ersten 16 Register schreibe und lese 
bekomme ich das nichtmal mit.
Weiterhin ist die Sensitivity-Liste des letzten Prozesses nicht 
vollständig.

Und beim Register Schreiben könnte es passieren, dass garnicht genug 
Register da sind (unter der Annahme, dass ich an einer Stelle was 
ändere)
-> schlechtes Beispiel

Autor: Falk (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
@ FPGA-User

> Dein Bsp. ist nicht zu Ende gedacht. Der Datenbus muss natürlich mit
> geändert werden und darf nicht fix 8 bit breit sein.

Lapsus. Asche auf mein Haupt. ;-)

> Außerdem könnte ich die Anzahl der Register jetzt auf 32 hochsetzen, nur
> der MUX unten in der case-Anweisung ändert sich nicht mit. Wenn ich bei
> meiner Simulation dann nur die ersten 16 Register schreibe und lese
> bekomme ich das nichtmal mit.
> Weiterhin ist die Sensitivity-Liste des letzten Prozesses nicht
> vollständig.

Hast Recht. Scheiss Copy & Paste. :-(

> Und beim Register Schreiben könnte es passieren, dass garnicht genug
> Register da sind (unter der Annahme, dass ich an einer Stelle was
> ändere) -> schlechtes Beispiel

Naja, es ging ja in erster Linie um Tristate Busse mit variabler Breite. 
Eine variable Anzahl Register war erstmal nicht gefordert. Im Anhang 
nochmal die saubere Version, allerdings mit konstanter Registeranzahl.

MFG
Falk


Autor: FPGA-User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Falk,

schon besser, jetzt müssen wir aber noch sicherstellen, dass die Anzahl 
der vorhandenen Register mit dem MUX konform geht (angenommen, dass alle 
Register gelesen werden sollen)
Wenn man ein Register einfügt, wäre der MUX zum Lesen dann automatisch 
angepasst - wie könnte man das realisieren?

Autor: T.M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann sein, dass ich mich irre, aber genügt nicht einfach
signal adr_int      : integer range 0 to 2**(width);
[/vhdl]
für die integer Deklaration und
read_bus <= my_reg(adr_int);
für den MUX?

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Kann sein, dass ich mich irre, aber genügt nicht einfach
> signal adr_int      : integer range 0 to 2**(width);

Fast

signal adr_int      : integer range 0 to 2**(width)-1;

> [/vhdl]
> für die integer Deklaration undread_bus <= my_reg(adr_int);
> für den MUX?

Ja, aber einge VHDL Compiler fressen das nicht, z.B. der von ALtera. Ist 
aber schon ne Weile her.

MfG
Falk

Autor: Stefan Wimmer (wswbln)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falk wrote:

> Naja, es ging ja in erster Linie um Tristate Busse mit variabler Breite.
> Eine variable Anzahl Register war erstmal nicht gefordert.

Oh doch! Genau das ist ja mein Problemchen. Wenn ich eine feste Anzahl 
Busse hätte, wäre das Ganze ja easy. Die Anzahl der Register ist in dem 
Design aber mit dem Generic "NumOfIORegisters" parametriert. Schau' Dir 
bitte nochmal den Generator ganz oben an:
Der Vector "StatusBits" (mit der Breite "Width * NumOfIORegisters") soll 
auf einen Bus der Breite "Width" heruntergebrochen werden und auf 
"NumOfIORegisters" aufeinanderfolgenden Adressen (deren ChipSelects mit 
einem 1-aus-N (N="NumOfIORegisters") Dekoder erzeugt werden) ausgelesen 
werden können.

Vielleicht wird's klarer, wenn ich mal die erzeugten Zeilen für 
NumOfIORegisters=3 und Width=8 hinschreibe:
StatusBus <= StatusBits(7 downto 0) when ChipSelect(0) = '1' else (others => 'Z'); -- i=0
StatusBus <= StatusBits(15 downto 8) when ChipSelect(1) = '1' else (others => 'Z'); -- i=1
StatusBus <= StatusBits(23 downto 16) when ChipSelect(2) = '1' else (others => 'Z'); -- i=2

Die Parametrierung von "Width" ist ja keine Kunst, aber wie generiere 
ich einen Muxer abhängig von der Anzahl der Register 
("NumOfIORegisters")?

Tristaten tue ich den Bus eh' "draussen an den Pins": er ist immer 
Eingang (Ausgangstreiber auf `Z`) ausser bei einem Readzugriff mit 
gültigen Adressen.

@Martin:
Oh, die X-en haben nun auch keine internen TBufs mehr? Dann herrscht ja 
in der Beziehung wieder Gleichstand mit den anderen (hab' seit 3 Jahren 
nichts mehr mit denen gemacht). Aber dort scheinen einem ja die Tools 
unter die Arme zu greifen...

Autor: FPGA-User (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
na nu so schwer isses doch nich, schließlich werden hier ab und zu sogar 
Profis gesucht, mit fettem Jahresgehalt... ;-)

Spaß beiseite, mal angenommen man möchte ein primitives OR-Gatter mit 
einer
variablen Anzahl Eingängen beschreiben.
Dann könnte man auf folgende Idee kommen:

...
constant OR_WIDTH : integer := 5; -- Bsp.
signal or_input : std_logic_vector(OR_WIDTH-1 downto 0);
signal or_y : std_logic; -- das ist der OR-Ausgang
...
process(or_input)
begin
   or_y <= '0'; -- falls wir keine '1' am Eingang haben
   for i in 0 to OR_WIDTH-1 loop
      if or_input(i)='1' then
         or_y <= '1';
      end if;
   end loop;
end process;

So könnte man Kombinatorik parametrisieren.
Reicht das ?

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.