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.
1 | : |
2 | Number of Slices: 834 out of 20480 4% |
3 | Number of Slice Flip Flops: 305 out of 40960 0% |
4 | Number of 4 input LUTs: 1596 out of 40960 3% |
5 | : |
Da ist aber offenbar noch einiges mehr im Spiel... Hier meine Erkenntnisse:
1 | library IEEE; |
2 | use IEEE.STD_LOGIC_1164.ALL; |
3 | use IEEE.NUMERIC_STD.ALL; |
4 | |
5 | entity SignalVsVariable is |
6 | Port ( z1 : in STD_LOGIC_VECTOR (7 downto 0); |
7 | z2 : in STD_LOGIC_VECTOR (7 downto 0); |
8 | z3 : in STD_LOGIC_VECTOR (7 downto 0); |
9 | res : out STD_LOGIC_VECTOR (7 downto 0); |
10 | s : in STD_LOGIC_VECTOR (1 downto 0)); |
11 | end SignalVsVariable; |
12 | |
13 | architecture Behavioral of SignalVsVariable is |
14 | signal zahl1 : integer range -128 to 127; |
15 | signal zahl2 : integer range -128 to 127; |
16 | signal zahl3 : integer range -128 to 127; |
17 | signal result : integer range -128 to 127; |
18 | signal i : integer range 1 to 3; |
19 | begin
|
20 | zahl1 <= to_integer(signed(z1)); |
21 | zahl2 <= to_integer(signed(z2)); |
22 | zahl3 <= to_integer(signed(z3)); |
23 | i <= to_integer(unsigned(s)); |
24 | |
25 | -- 21 Slices, 37 Luts, Maximum combinational path delay: 15.656ns
|
26 | process (zahl1,zahl2,zahl3,i) |
27 | variable tmp : integer range -256 to 255; |
28 | begin
|
29 | case i is |
30 | when 1 => tmp := (zahl1 + zahl2); |
31 | when 2 => tmp := (zahl1 + zahl3); |
32 | when others => tmp := (zahl2 + zahl3); -- Defaultzuweisung |
33 | end case; |
34 | result <= tmp/2; |
35 | end process; |
36 | |
37 | -- 57 Slices, 103 Luts, Maximum combinational path delay: 16.236ns
|
38 | process (zahl1,zahl2,zahl3,i) |
39 | begin
|
40 | case i is |
41 | when 1 => result <= ((zahl1 + zahl2) / 2); |
42 | when 2 => result <= ((zahl1 + zahl3) / 2); |
43 | when others => result <= ((zahl2 + zahl3) / 2); -- Defaultzuweisung |
44 | end case; |
45 | end process; |
46 | |
47 | -- 62 Slices, 107 Luts
|
48 | process (zahl1,zahl2,zahl3,i) |
49 | begin
|
50 | result <= ((zahl2 + zahl3) / 2); -- Defaultzuweisung |
51 | if i = 1 then result <= ((zahl1 + zahl2) / 2); end if; |
52 | if i = 2 then result <= ((zahl1 + zahl3) / 2); end if; |
53 | end process; |
54 | |
55 | -- 62 Slices, 107 Luts
|
56 | process (zahl1,zahl2,zahl3,i) |
57 | begin
|
58 | if i = 1 then result <= ((zahl1 + zahl2) / 2); |
59 | elsif i = 2 then result <= ((zahl1 + zahl3) / 2); |
60 | else result <= ((zahl2 + zahl3) / 2); |
61 | end if; |
62 | end process; |
63 | |
64 | -- 46 Slices, 81 Luts, Maximum combinational path delay: 16.187ns
|
65 | process (zahl1,zahl2,zahl3,i) |
66 | begin
|
67 | result <= 0; -- Defaultzuweisung gegen Latches |
68 | if i = 1 then result <= ((zahl1 + zahl2) / 2); end if; |
69 | if i = 2 then result <= ((zahl1 + zahl3) / 2); end if; |
70 | if i = 3 then result <= ((zahl2 + zahl3) / 2); end if; |
71 | end process; |
72 | |
73 | -- 46 Slices, 81 Luts, Latches!!!!
|
74 | process (zahl1,zahl2,zahl3,i) |
75 | begin
|
76 | if i = 1 then result <= ((zahl1 + zahl2) / 2); end if; |
77 | if i = 2 then result <= ((zahl1 + zahl3) / 2); end if; |
78 | if i = 3 then result <= ((zahl2 + zahl3) / 2); end if; |
79 | end process; |
80 | |
81 | -- ohne Defaultzuweisung: 27 Slices, 47 Luts, Maximum combinational path delay: 18.129ns
|
82 | -- mit Defaultzuweisung: 19 Slices, 33 Luts, Maximum combinational path delay: 13.144ns
|
83 | process (zahl1,zahl2,zahl3,i) |
84 | variable tmp : integer range -256 to 255; |
85 | begin
|
86 | tmp := 0; -- Defaultzuweisung |
87 | if i = 1 then tmp := (zahl1 + zahl2); end if; |
88 | if i = 2 then tmp := (zahl1 + zahl3); end if; |
89 | if i = 3 then tmp := (zahl2 + zahl3); end if; |
90 | result <= tmp/2; |
91 | end process; |
92 | |
93 | res <= std_logic_vector(to_signed(result,8)); |
94 | |
95 | end Behavioral; |
Bitte selber bewerten ;-)
@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;
Das kommt dabei raus:
1 | -- 21 Slices, 37 Luts, Maximum combinational path delay: 15.656ns
|
2 | process (zahl1,zahl2,zahl3,i) |
3 | variable tmp : integer range -256 to 255; |
4 | begin
|
5 | tmp := (zahl2 + zahl3); -- Defaultzuweisung |
6 | if i = 1 then tmp := (zahl1 + zahl2); end if; |
7 | if i = 2 then tmp := (zahl1 + zahl3); end if; |
8 | result <= tmp/2; |
9 | end process; |
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.
Danke. Das war auch schon irgendwie meine Vermutung. Schön, dass das Werkzeug das automatisch erkennt. Der Besucher
@ Lothar: Könntest du bitte noch mal prüfen, ob dieser Code (mit Shift anstelle Division) noch weniger verbraucht:
1 | process (zahl1,zahl2,zahl3,i) |
2 | variable tmp : integer range -256 to 255; |
3 | begin
|
4 | tmp := 0; -- Defaultzuweisung |
5 | if i = 1 then tmp := (zahl1 + zahl2); end if; |
6 | if i = 2 then tmp := (zahl1 + zahl3); end if; |
7 | if i = 3 then tmp := (zahl2 + zahl3); end if; |
8 | result <= shift_right(tmp,1); |
9 | end process; |
Danke!
Klar, was dabei herauskommt:
1 | shift_right can not have such operands in this context. |
Ok, also etwas hin- und herkonvertiert:
1 | result <= to_integer(shift_right(to_signed(tmp,9),1)); |
Und dann das Ergebnis -- 17 Slices, 30 Luts, Maximum combinational path delay: 12.988ns Aber bei negativen Zahlen ist / nicht das selbe wie shift_right Beitrag "Re: right_shift und "/" liefern unterschiedliche Ergbnisse"
wie seht es mit der Taktrate aus? Du warst bei 68MHz, das ist mir viel zu langsam.
@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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.