Datum:
Hallo Zusammen, ich implementiere momentan ein Design auf einem Altera Arria II GX mit PCIe-Anbindung. Vom PICe-Core erhalte ich den Systemtakt von 125 MHz, mit welchem meine Module getaktet sind. Allerding stelle ich jetzt in der Timing-Analyse fest, dass er diesen Takt nicht schafft, maximal 104 MHz wären drin. Untenstehend habe ich den Code zum kritischen Pfad beigefügt: Kritischer Pfad: Signal "par_factor" to Signal ""res_mult
... signal d_in : std_logic_vector(31 downto 0); signal par_factor : std_logic_vector(31 downto 0); signal res_mult : std_logic_vector(31 downto 0); ... case state is when MULT => if trig_in = '1' then -- Multiply with scaling factor res_mult <= mult(d_in, par_factor); end if; ... end case; ... function mult (a, b : signed) return signed is variable temp : signed((a'length * 2) - 1 downto 0); variable ov_check : signed((a'length / 2) downto 0); variable ret : signed(a'range); begin -- Multiply temp := a * b; -- Check for overflow ov_check := temp(temp'left downto temp'left - (a'length / 2)); if (ov_check = 0) or (ov_check = -1) then -- No overflow occured, resize ret := temp(temp'left) & temp(temp'left - (a'length / 2) - 1 downto (a'length / 2)); elsif(ov_check(ov_check'left) = '0') then ret := '0' & ((ret'left - 1) downto 0 => '1'); else ret := '1' & ((ret'left - 1) downto 0 => '0'); end if; return ret; end function; |
Mir ist klar, dass 125 MHz kein Pappenstiel sind, aber kann es sein, dass schon eine 32-Bit-Multiplikation (plus etwas Logik davor und dahinter) den Rahmen des Möglichen sprengt? Oder ist das unwahrscheinlich und ich mache vermutlich Fehler bei der Timing-Analyse? Peter
Datum:
Hallo, du willst eine 32bit x 32bit Multiplikation ein einem Takt schaffen. Der Arria II GX hat 18bit x 18bit Multiplizierer, davon muss Quartus vier parallel schalten und die Produkte noch addieren. Das wird nicht in 8 ns. Du musst die Multiplikation pipelinen. Vielleicht bietet der Megawizzard einen entscprechenden Multiplizierer an. Tom
Datum:
Warum nimmst du nicht einen fertigen Hardware-Multiplier aus dem FPGA, dann kannst du das Timing im Datenblatt nachlesen... Ein alter Spartan 3 schafft hier 139MHz:
entity Multiply32x32 is Port ( a : in STD_LOGIC_VECTOR (31 downto 0); b : in STD_LOGIC_VECTOR (31 downto 0); q : out STD_LOGIC_VECTOR (31 downto 0); clk : in STD_LOGIC); end Multiply32x32; architecture Behavioral of Multiply32x32 is signal la,lb,lq : unsigned (31 downto 0); begin la <= unsigned(a); lb <= unsigned(b); process begin wait until rising_edge(clk); lq <= la*lb; q <= std_logic_vector(lq); end process; end Behavioral; |
Aber ich glaube, nicht die Multiplikation ist hier das Problem, sondern die gleichzeitige Prüfung des Überlaufs. Kannst du die nicht einen Takt später machen?
Datum:
Danke für eure Antworten! Hardware-Multiplizierer habe ich bisher keine instanziiert, da ich Multiplikation nach diesem Schema an mehreren Stellen durchführe, und deshalb in eine Funktion ausgelagert habe. Kann ich denn trotzdem in der Funktion einen Hardware-Multiplizier instanziieren? Wenn ja, hätte dies aber vermutlich den Nachteil, dass die Hardware für jeden Aufruf der Funktion erzeugt werden muss, da ja der Funktionsaufruf prinzipiell mehrfach gleichzeitig stattfinden könnte. Zum Pipelining der Multiplikation und anschließendem Überlauf-Check: Selbige Begründung. In der Funktion kann ich das meines Wissens nach nicht auf mehrere Takte verteilen.
Datum:
Peter Z. schrieb: > Hardware-Multiplizierer habe ich bisher keine instanziiert, Das macht die Toolchain solange möglich von sich aus, wenn du sowas schreibst:
-- Multiply
temp := a * b;
|
Irgendwann gehen dir aber die Mutltiplizierer aus, dann wird haarig... Musst du diese Multiplizierer immer alle gleichzeitig nutzen? Falls nein, dann sollten die sinnvoll gemultiplext werden. Denn Multiplizierer sind wertvoll, weil nur in endlicher Stückzahl auf dem FPGA vorhanden...
Datum:
>> Hardware-Multiplizierer habe ich bisher keine instanziiert, > Das macht die Toolchain solange möglich von sich aus, wenn du sowas > schreibst: Das ist schonmal erfreulich ;-) > Musst du diese Multiplizierer immer alle gleichzeitig nutzen? Jein. Die Funktion wird momentan von mehreren Komponenten aus aufgerufen. Innerhalb jeder Komponente erfolgen aber alle Berechnungen getaktet nacheinander. Somit bräuchte ich einmal pro Komponente den Hardware-Multiplizierer, was vertretbar sein sollte. Nur fällt mir eben keine elegante Beschreibung ein, um diese Multiplikation mit anschließender Begrenzung so gekapselt wie möglich zu beschreiben. Ich habe diese Funktion extra in ein Package ausgelagert, um Redundanzen in Code der einzelnen Komponenten zu minimieren.
Datum:
Peter Z. schrieb: > Mir ist klar, dass 125 MHz kein Pappenstiel sind, aber kann es sein, > dass schon eine 32-Bit-Multiplikation (plus etwas Logik davor und > dahinter) den Rahmen des Möglichen sprengt? Hier die klare Aussage: Ja dass KANN sein: Die im Datenblatt angegebene Maximale Frequenz der Multplier sind zumeist ziemlich ausgelutscht: Der Marketing K(r)ampf zwischen A und X lässt grüssen... Außerdem sind die Multiplier nicht feingranuliert über den Chip verteilt, so dass Routing Delays sowie die Propagation deiner "etwas" Logik schon ganz schön ins Gesamtbudget eingehen. Die wirkliche Performance der Multiplier kann also nur ausgenutzt werden wenn direkt Eingangs- wie ausgangsseitig registert gearbeitet wird (pipelining), je nach verwendeter Architektur kann die Verwendung von Pipelinestufen innerhalb der Hardwaremultiplier nochmals einige hundert Megaherz Gewinn bringen... Gruß Vanilla
Datum:
Peter Z. schrieb: > Wenn ja, hätte dies > aber vermutlich den Nachteil, dass die Hardware für jeden Aufruf der > Funktion erzeugt werden muss, da ja der Funktionsaufruf prinzipiell > mehrfach gleichzeitig stattfinden könnte. In Hardware wird nichts aufgerufen, sondern instanziert. Wenn du die Funktion in drei Prozessen verwendest, wird den Multiplizierer dreimal instanziert. Ob du nun einen Hardware-Multiplizierer verwendest oder nicht, spielt keine Rolle. Tom
Datum:
Peter Z. schrieb: > Ich habe diese Funktion extra in ein Package ausgelagert, > um Redundanzen in Code der einzelnen Komponenten zu minimieren. Bringt wie schon gesagt alles nichts. Wenn da im "Code" dreimal eine Funktion mit a*b "aufgerufen" wird, dann werden im FPGA parallel 3 Multiplizierer eingebaut.
Datum:
Okay, dann wird wohl die eleganteste Beschreibung eine separate "Multiplizier-Komponente" sein, welche die Multiplikation und Überlaufprüfung gepipelined durchführt. Diese wird einmal pro "nutzende" Komponente instanziiert und in den entsprechenden Schritten mit Daten versorgt.
Datum:
Peter Z. schrieb: > Diese wird einmal pro "nutzende" > Komponente instanziiert und in den entsprechenden Schritten mit Daten > versorgt. Wenn sie 3 mal instanziert wird, dann ist sie auch 3 vorhanden. Du darfst sie nur einmal instanzieren !
Datum:
> dass die Hardware für jeden Aufruf der > Funktion erzeugt werden muss Hä ? Die Hardware wird nicht erzeugt. Die ist da und wird entweder benutzt oder nicht. Wenn du in den Syntheseoptionene einstellst, daß er Harwaremultiplizierer benutzen soll dan tut er das auch wenn du irgendwo "*" hinschreibst. Wenn du die Option deaktiviert läßt dann liegen die Hardwaremultiplizierer einfach brach und werden nicht benutzt. Ist doch schade du hast dafür doch bezahlt. Also nutz die Dinger auch !
Datum:
Uwe schrieb: > Die Hardware wird nicht erzeugt. > Die ist da und wird entweder benutzt oder nicht. Wenn alle Multiplizierer verbraucht sind, dann bastelt sich die Synthese einen aus LUTs, und der ist dann durchaus "erzeugt"...
Datum:
> Wenn sie 3 mal instanziert wird, dann ist sie auch 3 vorhanden. > Du darfst sie nur einmal instanzieren ! Das ist mir klar. Ich meinte, dass ein Multiplizierer innerhalb der jeweiligen Komponente erzeugt wird, mit dem dann nacheinander alle Berechnungen ausgeführt werden. Ich probiere das die Tage mal aus, aber dann scheint das die sinnvollste Lösung zu sein.
Datum:
Peter Z. schrieb: > Ich meinte, dass ein Multiplizierer innerhalb der > jeweiligen Komponente erzeugt wird, mit dem dann nacheinander alle > Berechnungen ausgeführt werden. Wenn Du das so haben willst, muß da ein Multiplexer und eine State-Machine drumrum. Duke
Datum:
>> Ich meinte, dass ein Multiplizierer innerhalb der >> jeweiligen Komponente erzeugt wird, mit dem dann nacheinander alle >> Berechnungen ausgeführt werden. > Wenn Du das so haben willst, muß da ein Multiplexer und eine > State-Machine drumrum Jepp, aber das wird schwerlich zu vermeiden sein, wenn ich einen Multiplizierer mehrfach nutze?!
Datum:
Peter Z. schrieb: > Hardware-Multiplizierer habe ich bisher keine instanziiert, da ich > > Multiplikation nach diesem Schema an mehreren Stellen durchführe, und > > deshalb in eine Funktion ausgelagert habe. Das hört sich für mich an, wie eine ausgelagerte Funktion in C die mehrfach benutzt wird.
Datum:
R. K. schrieb: > Das hört sich für mich an, wie eine ausgelagerte Funktion in C die > mehrfach benutzt wird. Ja, nur dass man diese Denkweise aus der Software-Entwicklung bei FPGAs ganz schnell komplett vergessen muss.
Datum:
Peter Z. schrieb: > Hardware-Multiplizierer habe ich bisher keine instanziiert, Bist Du sicher, dass Dir Q keinen reininstanziiert hat? Das tut es nämlich bei DER Beschreibung. Zusammenfassend gesagt: du musst die zusammengebaute MUL nicht händisch realisieren, sondern sie nur hinschreiben und das timing einhalten (lassen). Einmal registriert / pipelined und der Arria müsste das können.
