Forum: FPGA, VHDL & Co. Demux Optimierung möglich?


von Martin (Gast)


Lesenswert?

Ich habe intern zwei 128-bit Register. Das Host interface ist 8-bit 
breit. Um nun die beiden register schreiben zu können, habe ich folgende 
Demux-Struktur (das ganze 2x):
1
    if ctrl_busy = '0' then
2
        if wr_en_data = '1' then
3
          case byte_sel(3 downto 0) is
4
            when "0000" => data(7   downto 0)   <= wdata;
5
            when "0001" => data(15  downto 8)   <= wdata;
6
            when "0010" => data(23  downto 16)  <= wdata;
7
            when "0011" => data(31  downto 24)  <= wdata;
8
            when "0100" => data(39  downto 32)  <= wdata;
9
            when "0101" => data(47  downto 40)  <= wdata;
10
            when "0110" => data(55  downto 48)  <= wdata;
11
            when "0111" => data(63  downto 56)  <= wdata;
12
            when "1000" => data(71  downto 64)  <= wdata;
13
            when "1001" => data(79  downto 72)  <= wdata;
14
            when "1010" => data(87  downto 80)  <= wdata;
15
            when "1011" => data(95  downto 88)  <= wdata;
16
            when "1100" => data(103 downto 96)  <= wdata;
17
            when "1101" => data(111 downto 104) <= wdata;
18
            when "1110" => data(119 downto 112) <= wdata;
19
            when others => data(127 downto 120) <= wdata;
20
          end case;
21
        end if;
22
        ....
23
    end if;

Ist es irgendwie möglich, eine solches Verhalten einfacher zu 
beschreiben, bzw. die Struktur zu optimieren?

lg Martin

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


Lesenswert?

Martin schrieb:
> Ist es irgendwie möglich, eine solches Verhalten einfacher zu
> beschreiben,
Ja. Siehe 
http://www.lothar-miller.de/s9y/archives/65-Vektormanipulation.html

> die Struktur zu optimieren?
Du könntest dein 128-Bit Wort in kleinere Happen unterteilen (Bytesel 
z.B. nur 2 Bit breit), dann ist nicht vor jedem einzelen Bit ein großer 
16:1 Multiplexer, sondern nur ein 4:1 Mux. Allerdings musst du dann 
natürlich einen paralellen 4:1 Pfad aufbauen, denn letztlich hast du ja 
die 16:1 Zuweisung.
Ob das was bringt zeigt dir dann der RTL-Schaltplan oder die erreichbare 
Taktfrequenz/Durchlaufzeit...

: Bearbeitet durch Moderator
von greg (Gast)


Lesenswert?

Klar, was ist hiermit? Aus dem Stehgreif, hoffe es passt.
1
  variable idx : integer := to_integer(unsigned(byte_sel(3 downto 0)));
2
begin
3
  ...
4
  data(8*(idx + 1) downto 8*idx) <= wdata;

von greg (Gast)


Lesenswert?

Muss natürlich
1
data(8*(idx + 1)-1 downto 8*idx) <= wdata;
[
heißen.

von greg (Gast)


Lesenswert?

Und die Zuweisung an idx natürlich im Körper des Prozesses. Ich krieg 
gerade nix hin. Wie auch immer: Xilinx-Tools generieren mir mit dieser 
"high-level"-Beschreibung brauchbare Hardware.

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


Lesenswert?

OT, aber trotzdem nötig:
> Stehgreif
Es ist ein Stegreif, der nichts mit "stehen" oder "greifen" zu tun 
hat...
http://de.wikipedia.org/wiki/Stegreif

von Binärbär (Gast)


Lesenswert?

Martin schrieb:
> Ist es irgendwie möglich, eine solches Verhalten einfacher zu
> beschreiben, bzw. die Struktur zu optimieren?

Einen Binärbaum kann man daraus machen. Bringt bei manchen Tools 
besseres Timing :-)

von J. S. (engineer) Benutzerseite


Lesenswert?

Binärbär schrieb:
> Einen Binärbaum kann man daraus machen. Bringt bei manchen Tools
> besseres Timing :-)

Bei dem oben dargestellten Multiplexer handelt es sich ja um exklusive 
(nicht "alternative") Zuweisungen, von daher wird da eigentlich nichts 
anderes gebraucht, als eine Handvoll enables für die Teilzuweisungen des 
Vektors, also jeweils ein Komparator. Was anders wäre es bei einem MUX 
der folgenden Art, dass immer dasselbe Register aus einer von n Optionen 
gespeist wird.

Beides sollte wohl jedes Synthesewerkzeug plattdrücken können. Obwohl, 
man weiss ja nie :-)

von Sigi (Gast)


Lesenswert?

Die Exklusivität spielt bei solchen Zuweisungen keine Rolle,
bei obigen Beispiel ergibt sie sich nur aus der Definition.

Für die Implementierung braucht man je 8Bit-DATA-Slice ein
ENABLE-Signal, das per LUT4 erzeugt werden kann. Dann wird
per DATA-Slice-FF ein LUT4 mit den Signalen ENABLE, WRITE
und WDATA(*) zur Ansteuerung verwendet. Macht also
144 (=16+128) LUT4s und 128 FFs.

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


Lesenswert?

Sigi schrieb:
> und 128 FFs
Wofür braucht ein Mux ein Flipflop?

Jürgen Schuhmacher schrieb:
> Was anders wäre es bei einem MUX der folgenden Art, dass immer dasselbe
> Register aus einer von n Optionen gespeist wird.
So ist es aber doch auch: ein Ausgang bekommt das Signal eines von 16 
Eingängen. Das Ganze dann 8 mal parallel. Denn es gibt keine 
"Vektoroperationen" im FPGA. Es wird jeder einzelne der 128 Eingänge per 
Handschlag zum Ausgang durchgereicht. Man braucht also 8 Stück 16:1 Mux, 
die zudem noch mit Steuersignalen zu kämpfen haben (hoffent sind das 
keine Latches...)

von Sigi (Gast)


Lesenswert?

Lothar Miller schrieb:
>So ist es aber doch auch: ein Ausgang bekommt das Signal eines von 16
>Eingängen. ..
Sicher?
Einem 8Bit-Slice wird unter einer bestimmten Bedingung byte_sel="xyzw"
WDATA zugewiesen. Trifft diese Bedigung nicht zu, muss etwas anderes
zugewiesen werden, was aber oben im Code nicht erwähnt wird. Irgendwo
wird also ein Latch-Vector oder FF-Vector hängen, daher meine 128 FFs
(ist aber nur eine Vermutung, es sei denn es werden noch 128 Signale
ins FPGA eingeleitet?).
Also kann man sagen, obige Schaltung ist je data-Signal ein 2erMUX.

von J. S. (engineer) Benutzerseite


Lesenswert?

Möglich, dass wir uns misverstehen, ich wollte nur darauf hinweisen, 
dass bei der hiesigen Schaltung (DEMUX) wenig Raum für mangelnde 
Optimierung besteht und das anfordernde eher der MUX wäre, wobei auch 
der einfach plattgeklopft werden können muss.

Lothar Miller schrieb:
> So ist es aber doch auch: ein Ausgang bekommt das Signal eines von 16
> Eingängen.
Bei einem MUX ja, bei dem DEMUX oben bekommt jeder Ausgang nur ein 
einziges Datensignal.

> Denn es gibt keine "Vektoroperationen" im FPGA.
Gemeint war der "vector" data(128 downto 0) und die Operation, die auf 
ihn wirkt.

> Es wird jeder einzelne der 128 Eingänge per
> Handschlag zum Ausgang durchgereicht.
So ist es.

> Man braucht also 8 Stück 16:1 Mux
Ich sehe hier nur 128 FFs (im getakteten Fall) mit 128 enables von denen 
jeweils 8 zusammen einen Komparatorausgang benutzen - einen von 16 
Decodern. Muxen tun die nichts und die 128 FFs fallen bei geschickter 
Verdrahtung weiteren Optimierungen zum Opfer. Oder waren wir hier wieder 
beim Mux-Fall?

Wenn der Prozess ungetaktet ist und so sieht es ja aus, würde ich 
ohnehin nicht versuchen, diese Schaltung partiell optimieren zu wollen, 
denn die Funktionalität kann auch noch mit folgender Kombinatorik 
zusammengefaltet werden, bevor es in den nächsten Speicher geht.

Ich habe zu dem Thema immer mal wieder Versuche gemacht und gefunden, 
dass es bei aktuellen Tools sogar Wurscht ist, ob man If THEN nutzt oder 
CASE WHEN. Solange es keinen echten Vorrang gibt, purzelt alles zusammen 
und die Schaltung (als Modul formuliert) hat immer denselben 
Grössenbedarf.

Änderungen gibt es nur in der Gesamtbetrachtung bei Hinzunahme weiterer 
Schaltungsteile, also z.B. bei der Frage, wie denn die enables und 
Steuersignale gebildet werden und wie deren Kombinatorik vorher 
aussieht. Wenn da FFs drinstecken und sie an anderer Stelle zu ganz 
bestimmten Zeiten im Design verwendet werden, kann die Synthese weniger 
umbalancieren, als wenn man alles mit Kombinatorik macht und nur davor 
und dahinter FFs hat - das timing und die Verteilung offenbleibt.

Dann wirken sich die globalen constraints area / speed am Stärksten aus, 
weil die Synthese dann erstmal die gemeinsamen Signale bilden und 
registrieren kann, um sie dann mehrfach zu verwenden und dies so, dass 
es timing-getrieben optimal passt. Im anderen Falle (area) werden die 
Urspünge der enables mit Teilen des Decoders zusammengefasst und in die 
LUTs abgebildet. Wie das dann aussieht und welche Terme gebildet werden, 
hängt stark von der Decodergrösse ab und den LUT-Breiten im FPGA ab.

Ob man da per Hand bessere Ergebnisse erzielt, als die Synthesetools, 
ist äusserst fraglich. Unterschiede gibt es freilich, wenn man sie nur 
mal die Ergebnisse von XST und/oder Synplify ansieht.

: Bearbeitet durch User
von Sigi (Gast)


Lesenswert?

Jürgen Schuhmacher schrieb:
>Ob man da per Hand bessere Ergebnisse erzielt, als die Synthesetools,
>ist äusserst fraglich. Unterschiede gibt es freilich, wenn man sie nur
>mal die Ergebnisse von XST und/oder Synplify ansieht.
Also "von Hand" würde ich bei einer LUT4-Architektur 2 LUT4s
je DATA-Bit hintereinanderschalten, bei einer LUT6-Architektur
reicht ein LUT6 je Bit vollkommen aus (ich nehme einfach mal an,
DATA ist als 128-FF-Vector implementiert). Damit kann man in beiden
Fällen das max. Mögliche in Bezug auf Performance und Platz erzielen.
XST/Quartus/Diamond wird das höchstwahrcheinlich nicht erreichen.

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.