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


von Stefan W. (wswbln)


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:
1
--***************************************
2
-- Generate the Bus-Mux 
3
BMux:
4
for i in 0 to (NumOfIORegisters-1) generate
5
  StatusBus <= StatusBits(Width*i+width-1 downto Width*i) when ChipSelect(i) = '1' else (others => 'Z');
6
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?

von Martin K. (mkohler)


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.

von Stefan W. (wswbln)


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?

von Falk (Gast)


Angehängte Dateien:

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



von Martin K. (mkohler)


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.

von FPGA-User (Gast)


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

von Falk (Gast)


Angehängte Dateien:

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


von FPGA-User (Gast)


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?

von T.M. (Gast)


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
1
read_bus <= my_reg(adr_int);
für den MUX?

von Falk (Gast)


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

von Stefan W. (wswbln)


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:
1
StatusBus <= StatusBits(7 downto 0) when ChipSelect(0) = '1' else (others => 'Z'); -- i=0
2
StatusBus <= StatusBits(15 downto 8) when ChipSelect(1) = '1' else (others => 'Z'); -- i=1
3
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...

von FPGA-User (Gast)


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 ?

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.