Hi
Arbeite gerade an einen Design in dem ich abhängig von einen Counterwert
2 verschiedene Werte zusammenaddieren muss und diese dann durch 2
Rechnen muss. Eigentlich wäre dafür ja eine shift operation perfekt
allerdings ist der Wert ein signed. Daher mache ich eine normale
division durch 2. Nun ist meine Frage ob es besser ist das ich die zwei
werte zuerst zusammenzähle und in eine Variable schreibe die ich nacher
dividiere oder kann ich für jeden fall einen mittels if abfrage
unterscheiden und in jeden zweig eine Division machen? Was ist vorallem
in Bezug auf synthese besser?
Fall 1:
if i = 1 then
result <= ((zahl1 + zahl2) / 2)
if i = 2 then
result <= ((zahl1 + zahl3) / 2)
if i = 2 then
result <= ((zahl2 + zahl3) / 2)
end if
oder
Fall 2:
if i = 1 then
tmp := ((zahl1 + zahl2) / 2)
if i = 2 then
tmp := ((zahl1 + zahl3) / 2)
if i = 2 then
tmp := ((zahl2 + zahl3) / 2)
end if
result <= (tmp / 2)
Vielleicht weiß jemand von euch welcher der beiden Fälle besser für die
HW.
MFG Gast
Simulier und synthetisier es doch einfach mal und guck was hinterher
rauskommt.
DAS könnte jedenfalls interessant werden ;) :
if *i = 2* then
tmp := ((zahl1 + zahl3) / 2)
if *i = 2* then
tmp := ((zahl2 + zahl3) / 2)
Das die if abfrage zweimal 2 abfragt ist natürlich ein tippfehler. Kommt
durch copy and paste. Gibt es sonst eine Möglichkeit die Division in
VHDL zu machen oder ist das eh der Standard weg um einen signed typ zu
dividieren?
Hi
Was ich vorher vergessen habe die Zahlen Zahl1, Zahl2 und Zahl3 sind
std_logic_vector die mit Hilfe von signed fürs rechnen umgewandelt
werden. Das Ergebnis ist wieder ein std_logic_vector. tmp ist eine
Variable die ebenfalls std_logic_vector ist. Kann ich davon ausgehen das
beide Varianten das Ergebnis innerhalb eines Taktzyklus haben oder kann
es da auch unterschiede geben. Suche eigentlich die Variante die am
wenigsten Logic braucht.
DANKE
Hatte noch einen Fehler in Fall 2
Fall 2:
if i = 1 then
tmp := (zahl1 + zahl2)
if i = 2 then
tmp := (zahl1 + zahl3)
if i = 3 then
tmp := (zahl2 + zahl3)
end if
result <= (tmp / 2)
MFG Gast
hmmm...
tmp := (zahl1 + zahl2)
Pass auf, dass tmp breit genug ist, sonst bekommst du schnell einen
Überlauf bei größeren Summanden.
Das beste Syntheseergebnis bekommst du meist nur durch testen raus.
Kannst gerne posten, was die Synthese dir als Resultat ausgibt und dann
kann man ans optimieren denken. Jedes Synthesewerkzeug hat seine
"Eigenheiten".
Probieren geht über studieren.
Der Besucher
Wenn es sich um signed-Division handelt und du möchtest das
syntethisieren, dann nimm lieber dann shifte lieber (arithmetisch
natürlich - dann ist das kein Problem).
Siehe mein Posting von letzter Wochen:
Beitrag "right_shift und "/" liefern unterschiedliche Ergbnisse"
Synthesiere doch einfach mal beide Varianten (also Shift und Division)
und stell deine Syntheseergebnisse hier rein. Würde mich mal
interessieren...
Hi
Habe das ganze nun mal getestet und folgende ergebnisse bekommen
Fall 1(division in jeden Zweig)
Minimum period: 14.499ns (Maximum Frequency: 68.970MHz)
Number of Slices: 834 out of 20480 4%
Number of Slice Flip Flops: 305 out of 40960 0%
Number of 4 input LUTs: 1596 out of 40960 3%
Number of IOs: 175
Number of bonded IOBs: 132 out of 333 39%
Number of GCLKs: 1 out of 8 12%
Fall 2(einmalige Division am Ende)
Minimum period: 16.059ns (Maximum Frequency: 62.272MHz)
Number of Slices: 820 out of 20480 4%
Number of Slice Flip Flops: 343 out of 40960 0%
Number of 4 input LUTs: 1576 out of 40960 3%
Number of IOs: 175
Number of bonded IOBs: 132 out of 333 39%
Number of GCLKs: 2 out of 8 25%
Fall 3 (shiften um 1 nach rechts und oberstes Bit setzen damit negative
Werte richtig sind und kleinstes Bit setzen damit richtig abgerundet
wird ei negativen Werten)
Minimum period: 14.534ns (Maximum Frequency: 68.802MHz)
Number of Slices: 871 out of 20480 4%
Number of Slice Flip Flops: 341 out of 40960 0%
Number of 4 input LUTs: 1673 out of 40960 4%
Number of IOs: 175
Number of bonded IOBs: 132 out of 333 39%
Number of GCLKs: 2 out of 8 25%
Welches würdet ihr nun als beste Variante bezeichnen. Eigentlich doch
die Variante mit der Division in jeden Zweig oder?
MFG Gast
Ich wuerde die if statements noch durch ein switch/case ersetzen. Die if
statements verursachen je nach Synthese einen Priority-Tree vor den
Arithmetik-Einheiten, den Du nicht(?) brauchst. switch/case erzeugt
einen Balanced-Tree und erlaubt einfacheres Ressource-Sharing von
Addierern und Dividierern.
@Lothar
Was sagt deine Synthese zu folgendem?
Hier ist der Fall i=0 und i=3 zusammengefasst.
Aber i ist auch nur im Bereich von 1 bis 3 definiert. Merkt das
Sythesewerkzeug, das i=0 don't care ist?
Der Besucher
process (zahl1,zahl2,zahl3,i)
variable tmp : integer range -256 to 255;
begin
tmp := (zahl2 + zahl3); -- Defaultzuweisung
if i = 1 then tmp := (zahl1 + zahl2); end if;
if i = 2 then tmp := (zahl1 + zahl3); end if;
result <= tmp/2;
end process;
-- 21 Slices, 37 Luts, Maximum combinational path delay: 15.656ns
2
process(zahl1,zahl2,zahl3,i)
3
variabletmp:integerrange-256to255;
4
begin
5
tmp:=(zahl2+zahl3);-- Defaultzuweisung
6
ifi=1thentmp:=(zahl1+zahl2);endif;
7
ifi=2thentmp:=(zahl1+zahl3);endif;
8
result<=tmp/2;
9
endprocess;
Insgesamt scheint mir das Beispiel ziemlich vertrakt, u.a. auch wegen
des Index, der erst bei 1 losgeht...
Und dann natürlich wegen der Latches, die es im Original-Post Fall 1
gibt.
Und was ist hiervon zu halten? Hier werden die Eingänge gemultiplext.
Ausserdem wird ausserdem ausgenutzt, dass a+b=b+a ist.
process (zahl1,zahl2,zahl3,i)
variable summand1 : integer range -128 to 127;
variable summand2 : integer range -128 to 127;
begin
summand1 := zahl2; -- Defaultzuweisung
summand2 := zahl3; -- Defaultzuweisung
if i = 1 then summand2 := zahl1; end if;
if i = 2 then summand1 := zahl1; end if;
result <= (summand1 + summand2)/2;
end process;
-- 22 Slices, 38 Luts, Maximum combinational path delay: 15.509ns
Das läuft dann auch vom Schematic her in die gleiche Richtung wie der
vorher gepostete Fall. Denn auch dort werden die Eingänge auf den
Addierer gemultiplext.
@dose
benötigst du wirklich jeden Takt ein Rechenergebnis?
Wenn nicht, ist es auch möglich eine Multicycle-Rechenoperation
durchzuführen. Man muss den entsprechenden Pfad nur der Synthese
mitteilen und der Rechenoperation soviele Takte zugestehen, wie sie
benötigt. Alles ohne zusätzliche Register.
Und wenn jeden Takt ein Ergebnis benötigt wird, kann man immer noch
mehrere Multicycle-Rechenwerke parallel aufbauen, die zeitversetzt
arbeiten.
Der Besucher
Ich habe mal mit Korrelationsalgorithmen zu tun gehabt, da wuchsen die
Daten sehr schnell an.
Sicher geht mit Piplineed architktur eine ganze Menge es zu
effektivieren.