Forum: FPGA, VHDL & Co. Multiplikation auf zwei Takte verteilen


von Frank M. (Gast)


Lesenswert?

Hallo zusammen,

ich bin auf der Suche nach einer Lösung, wie ich eine Multiplikation in 
zwei Takte aufteilen kann, weil mein Timing nicht mehr mitspielt.
1
if rising_edge(clk) then
2
   if START = '1' then
3
      product <= a * b;
4
      DONE <= '1';
5
   else
6
      DONE <= '0';
7
   end if;
8
end if;

So habe ich es aktuell gestaltet und Quartus implementiert auch 
automatisch einen Multiplizierer-Block, aber in einem Takt (75MHz) ist 
das leider nicht mehr umsetzbar, weil a und b zu breit sind.

Wie kann ich vielleicht mit Hilfe eines Zwischenregisters diese 
Multiplikation aufdröseln, ohne dass ich mein START und DONE Signal 
verliere?

Vielen Dank!
Frank

von Iulius (Gast)


Lesenswert?

Leg auf die Multiplikation ein Multicycle contraint und gib verzöger 
dein done noch um einen Takt.

Alternativ halt die Multiplikation aufspalten, aber ohne Kenntnis der 
Wortbreiten und der Technologie ist es schwer zu sagen ob das sinnvoll 
geht.

von franke (Gast)


Lesenswert?

Schau dir doch mal den Multiplizier-Block nochmal genau an (ich 
bevorzuge eh die IP's direkt wegen genauer Kontrolle)

Normalerweise haben die Eingangs-, Ausgangs- und Pipeline-Register um 
den Takt zu erhöhen. Kann mir fast nicht vorstellen dass die 75 MHz 
nicht schaffen sollen...Wie Groß ist den a und b ?

von Frank M. (Gast)


Lesenswert?

Hallo,

Iulius schrieb:
> Alternativ halt die Multiplikation aufspalten
Genau das möchte ich gerne machen. Dachte es gibt da irgendeinen Trick, 
wie man recht schnell den Ausdruck a*b mit einem Zwischenregister in 
zwei Takte aufteilen kann, ohne jetzt contraints oder den Multi-Block 
selber anfassen zu müssen.

franke schrieb:
> Wie Groß ist den a und b ?
Ich Multipliziere einen 32bit Vektor mit einem 23bit Vektor. Als 
Ergebnis bekomme ich dann 55bit.

In einem Takt ist es nicht mehr zu schaffen, weil für die Multiplikation 
ja mehr oder weniger 32 23-bit-Addierer, oder 23 32-bit-Addierer in 
Reihe geschaltet werden müssen. Durch die Gatterlaufzeiten ist es dann 
ab irgendeiner Anzahl von Addierern begrenzt.

Zumindest ist das bisher meine Erklärung für mein Problem, wenn ich mich 
da auf dem Holzweg befinde, sagt es mir bitte.

Vielen Dank!
Frank

von franke (Gast)


Lesenswert?

hmpf ...

hab das gerade deine Werte bei IPExpress (Lattice) eingegeben... bekomme 
8 DSP9x9 Slices als Resourcen genannt, (mit diversen 
Pipelining-Optionen).

Spiel doch mal mit dem Altera-Äquvalent...
Ansonsten ist Pipelining eh dein Freund.

Gruß

von Lattice User (Gast)


Lesenswert?

Wenn du nicht die vorgefertigten Multiplier aus der Software verwenden 
willst:

Als erstes Eingangsregister definieren um die Laufzeit der Kombinatorik 
und Routing vor dem Multipliern abzutrennen:
ar <= a;
br <= b;
product <= ar * br;
Der Synthesizer dürfte sogar schlau genug sein, für ar und br die 
Eingangsregister der DSP Slices (sofern vorhanden) zu verwenden.

Wenn das nicht reicht, die Mathekenntnisse der Grund und Mittelstufe 
wieder ausgraben (oder lernt man da heutzutage nur noch mit dem 
Taschenrechner?)

Die Faktoren in High und Low aufteilen womit sich die Aufgabe so stellt 
(mit 16 bit HW Multiplieren):
1
(ah * 65536 + al) * (bh * 65536 + bl)

Ausmultiplizieren gibt:
1
ah * bh * 4294967296 + ah * bl * 65536 + al * bh * 65536 + al * bl

Also
1
p1 <= ah * bh;
2
p2 <= ah * bl;
3
p3 <= al * ah;
4
p4 <= al * bl;
5
6
product <= p1 * 4294967296 + ( p2 + p3 ) * 65536 + a1 * b2;

Die Multiplication mit 65536 (2^16) und  4294967296 (2^32) ist einfach 
nur richtig verdrahten.

Den Additionsschritt kann man bei Bedarf auch nochmal in mehrere 
Schritte zerlegen mit Speichern der Zwischenergebnissen.

Obiges gilt nur bei unsigned, bei signed wird es ein wenig 
komplizierterm geht aber nach dem gleichen Prinzip.

von P. K. (pek)


Lesenswert?

Generier' Dir doch den Multiplizierer mit dem Megawizzard 
Plugin-Mangager (Untertool von Quartus), da kannst Du wählen, wieviele 
Pieplining-Stufen Du willst und es werden ganz sicher DSP-Slices optimal 
eingesetzt. Den generierten Multiplizierer instantierst Du dann einfach 
in Deinem Design.

von Hmm... (Gast)


Lesenswert?

Oder ein kombinatorischer Multiplizier der getaktet seine Eingangswerte 
erhält und getaktet ausgelesen wird:

1. Takt:
  - Busy Signal setzen
  - Faktoren setzen
2. Takt:
  - nix tun
3. Takt:
  - Busy Signal löschen
  - Produkt in Signal latchen

Kombinatorisch:

 prod(54 downto 0) <= a(31 downto 0) * b(31 downto 0);

von Lattice User (Gast)


Lesenswert?

Lattice User schrieb:
> product <= p1 * 4294967296 + ( p2 + p3 ) * 65536 + a1 * b2;

Ich sehe gerade dass ich da einen Typo habe, richtig ist:
1
product <= p1 * 4294967296 + ( p2 + p3 ) * 65536 + p4;

von Harri (Gast)


Lesenswert?

Lattice User schrieb:
> (ah * 65536 + al) * (bh * 65536 + bl)
So schön Du es erklärt hast, so falsch ist es leider.

Die Multiplikation muss auf die carry chain in Verbingung mit der 
MUL-Breiten angpepasst werden, wenn man das so machen möchte. Teilung in 
der Mitte ist nicht notwedigerweise das Optimum, insbesondere nicht bei 
asymmetrischen MULs wie beim S6 (18x25).


>Multi Cycle
Bringt nicht wirklich was, besser ist es, weitere asnychrone 
Kombinatorik mit hintendran zu hängen, dann ein Doppel- oder 
Dreifachregister anzuhängen und mit register balancing zu arbeiten. Der 
findet dann meistens ein besseres Optimum.

von Lattice User (Gast)


Lesenswert?

Harri schrieb:
> Lattice User schrieb:
>> (ah * 65536 + al) * (bh * 65536 + bl)
> So schön Du es erklärt hast, so falsch ist es leider.
>

Kannst du mir erklären was daran falsch sein soll?
Dass die Trennung bei 16bit nicht das Optimum ist macht es doch nicht 
falsch, oder?

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.