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:
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?
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.
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?
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
@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.
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
@ 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
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?
> 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
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:
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...
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 ?