Forum: FPGA, VHDL & Co. Rechnen mit unsigned vs. signed und einer division


You were forwarded to this site from EmbDev.net. Back to EmbDev.net
von M. K. (marc1234)


Lesenswert?

Hallo,
irgendwie steh ich auf dem Schlauch. Ich kriege von einem bipolaren AD 
zwei 12 Bit Werte, welche ich mir als zweierkomplement oder als straight 
binary (0 bis 4095) ausgeben kann. Diese liegen mir dann als 
std_logic_vector vor, welche ich dann entsprechend in signed oder 
unsigned casten kann oder muss ich noch was beachten?

zweierkomplement wäre ja signed und straight binary unsigned oder?

Mach ich das am besten mit den Werten als Zweierkomplement oder mit dem 
straight binary?

Später muss ich das Ergebnis dividieren, so das der Quotient  immer 
zwischen -1 und 1 liegt. Dafür wollt ich den IP-Core von Lothar Miller 
verwenden.

http://www.lothar-miller.de/s9y/archives/29-Division-in-VHDL.html

oder hat da jemand eine andere Idee, weil mein Quotient ja nicht größer 
als 1 wird?!

Danke für eure hilfe :-)

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


Lesenswert?

Marc K. schrieb:
> Mach ich das am besten mit den Werten als Zweierkomplement
Eher ja. Denn sonst hast du nur positive Werte und musst selber noch den 
Offset abziehen...

> Später muss ich das Ergebnis dividieren, so das der Quotient  immer
> zwischen -1 und 1 liegt.
Wie willst du denn diesen Zahlenbereich darstellen?

> oder hat da jemand eine andere Idee, weil mein Quotient ja nicht größer
> als 1 wird?!
Denk dir einfach das Komma vor das MSB.
Dann hast du eine Zahl von -1...+0.999, und das ganz ohne Rechnen...
:-o

von M. K. (marc1234)


Lesenswert?

ok vielen dank. Ich werde es mit dem Zweierkomplement machen :-)

Lothar Miller schrieb:
> Wie willst du denn diesen Zahlenbereich darstellen?

Das hab ich mich auch gefragt. Ich weiß noch nicht so recht wie ich das 
realisieren soll.


Lothar Miller schrieb:
> Denk dir einfach das Komma vor das MSB.
>
> Dann hast du eine Zahl von -1...+0.999, und das ganz ohne Rechnen...
>
> :-o

Ich muss die Divison aber durchführen, der Divisor ändert sich immer so 
das halt keine größere Zahl als 1 rauskommt. Mich interessiert 
eigentlich nur das vorzeichen und paar Nachkommastellen.

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


Lesenswert?

Marc K. schrieb:
> Ich muss die Divison aber durchführen,
Warum?

> keine größere Zahl als 1 rauskommt.
Nach wie vor die Frage: wie willst du mit Integerzahlen eine Zahl 
kleiner 1 darstellen?
Weiterhin meine Antwort: denk dir einfach ein "Null Komma" vor die 12 
Bit. Dann hat das führende Bit (links) die Wertigkeit 1/2, das nächste 
1/4, dann 1/8, 1/16, usw. Je weiter du nach rechts kommst, umso weniger 
ist ein Bit wert. Genau so, wie du es von gewöhnlichen Integerzahlen 
gewöhnt bist.

So wird das bei Signalprozessoren, die mit Festkommazahlen rechnen, auch 
gern gemacht. Und dafür gibt es massenweise Literatur.

von M. K. (marc1234)


Lesenswert?

Lothar Miller schrieb:
> Marc K. schrieb:
>
>> Ich muss die Divison aber durchführen,
>
> Warum?

Da sich mein Dividend und Divisor unabhängig ändert. Ich jedoch weiß das 
nur der bereich (-1 bis 1) rauskommen kann. Sonst ist ein fehler im AD 
Wert. Ich weiß auch das dies mit Integer nicht möglich ist...

ich werd mich erstmal einlesen und vermutlich löst sich das Problem. ich 
dachte nur vielleicht gehts auch ganz einfach :-)

vielen dank für die antwort :-)

von Dipl.-Ing. (TH) (Gast)


Lesenswert?

Du hast doch für beide einen Skalierungsfaktor drin. Z.B. wird die 1 
immer als 32768 dargstellt. Das betrifft dann Zähler und Nenner. 
Rauskommen "tut" dann bei einer Division (egal ob mit core oder manuell) 
immer einen Bitfolge, die du nur zu interpretieren brauchst. Also: Bit 
einsammeln und für jeden shift nach links, den Du zusätzlich machst, 
musst du hinterher einen "weginterpretieren".

Bei einem core kannst Du so teilen, dass vorne die 1 rauskommt und dann 
sofort den Rest weiterverarbeiten, indem du nochmal teilst. Oder, Du 
multiplizierst = schiebst den Zähler so weit nach links, dass Du genug 
Stellen rausbekommst.

Beispiel:

Zählerwert = Z, Nennerwert = N, mit -N < Z < +N;

Digitale Darstellung:

ZD = 32768 x Z =  -32768*Z < ZD < 32767*Z

Wenn Z aus z.B: einem ADC stammt und selber schon 15 Bit hat, hast du 
eben rund 30Bit+Signum. Dann könntest Du reduzieren.

Gehen wir also davon aus, dass wir 31 Bit im Zähler haben und 31 im 
Nenner.

Du rechnest dann einfach  ZD & "00000000" / ND und heraus kommt eine 
Zahl mit 8 Stellen vor dem Komma. Den Rest, den der Core auswirft, 
kannst Du dann verwerfen. Der teil der Schaltung wird dann auch nicht 
synthetisiert. Habe das bei Altera exzessiv durchgecheckt.

von M. K. (marc1234)


Lesenswert?

ok danke. Ich bin gerade noch am umstrukturieren,  aber hab ich das 
jetzt richtig verstanden. Ich erweitere die Zähler und Nenner so

  Divisor <=  "000000000000" & std_logic_vector(Nenner);
   Dividend <= std_logic_vector(Zaehler) & "000000000000";

von Spartanist (Gast)


Lesenswert?

Marc K. schrieb:
> Divisor <=  "000000000000" & std_logic_vector(Nenner);

Den Divisor würde ich gar nicht erweitert. Bläht nur den Divider auf, 
der dann wieder reduziert wird, wenn die Synthese die vielen Nullen 
sieht.

von M. K. (marc1234)


Lesenswert?

ich nutzte ein FPGA von Microsemi und ich habe dort bezüglich der 
division nachgefragt. Diese meinten man kann es einfach mit "/" 
implementieren. Wie es aussieht funktioniert es auch :-/

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


Lesenswert?

Marc K. schrieb:
> Diese meinten man kann es einfach mit "/" implementieren.
> Wie es aussieht funktioniert es auch :-/
Kann Altera auch.
Aber sieh mal nach, wie es mit dem Ressourcenverbrauch aussieht.
Was kostet dich eine 32/16 Division, die in 1 Takt fertig ist?

von M. K. (marc1234)


Lesenswert?

Lothar Miller schrieb:
> Marc K. schrieb:
>> Diese meinten man kann es einfach mit "/" implementieren.
>> Wie es aussieht funktioniert es auch :-/
> Kann Altera auch.
> Aber sieh mal nach, wie es mit dem Ressourcenverbrauch aussieht.
> Was kostet dich eine 32/16 Division, die in 1 Takt fertig ist?

Das sagt die synthese bei folgendem code:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Div is
6
  port (
7
    div_out : OUT std_logic_vector (5 downto 0);
8
    clk  : IN std_logic;
9
    zahl_32 : IN std_logic_vector(5 downto 0);
10
    zahl_16 : IN std_logic_vector(5 downto 0)
11
   );
12
End Div;
13
14
architecture BEHAV of div is
15
16
signal ergebnis : unsigned (5 downto 0);
17
18
begin 
19
process (clk)
20
begin
21
if (rising_edge(clk)) then
22
ergebnis <=  unsigned(zahl_32) / unsigned(zahl_16);
23
end if;
24
end process;
25
26
div_out <= std_logic_vector(ergebnis);
27
28
end BEHAV;

Compile report:
===============

    CORE                       Used:    151  Total:  38400   (0.39%)
    IO (W/ clocks)             Used:     19  Total:    147   (12.93%)
    Differential IO            Used:      0  Total:     65   (0.00%)
    GLOBAL (Chip+Quadrant)     Used:      1  Total:     18   (5.56%)
    PLL                        Used:      0  Total:      2   (0.00%)
    RAM/FIFO                   Used:      0  Total:     60   (0.00%)
    Low Static ICC             Used:      0  Total:      1   (0.00%)
    FlashROM                   Used:      0  Total:      1   (0.00%)
    User JTAG                  Used:      0  Total:      1   (0.00%)

Wolltest du das wissen?

von Duke Scarring (Gast)


Lesenswert?

Marc K. schrieb:
> CORE                       Used:    151  Total:  38400   (0.39%)
Das sind vermutlich die Logic Cells.

Interessant wäre noch die Taktfrequenz. Dazu müsste man vorher und 
hinterher noch ein Register dranpappen.

Duke

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


Lesenswert?

Marc K. schrieb:
> Wolltest du das wissen?
Jein...
Einen Divider für 6 Bit kann ich in ein BRAM packen...

Ich wollte das eigentlich für 32/16 Bits wissen:
1
    :
2
    zahl_32 : IN std_logic_vector(31 downto 0);
3
    zahl_16 : IN std_logic_vector(16 downto 0)
4
    :
Und auch: Wie schnell kannst du dieses Design takten?

von M. K. (marc1234)


Lesenswert?

Lothar Miller schrieb:
> Marc K. schrieb:
>> Wolltest du das wissen?
> Jein...
> Einen Divider für 6 Bit kann ich in ein BRAM packen...
>
> Ich wollte das eigentlich für 32/16 Bits wissen:
>
1
>     :
2
>     zahl_32 : IN std_logic_vector(31 downto 0);
3
>     zahl_16 : IN std_logic_vector(16 downto 0)
4
>     :
5
>


 CORE                       Used:   1799  Total:  38400   (4.68%)
    IO (W/ clocks)             Used:     81  Total:    147   (55.10%)
    Differential IO            Used:      0  Total:     65   (0.00%)

von M. K. (marc1234)


Lesenswert?

Lothar Miller schrieb:
> Marc K. schrieb:
>> Wolltest du das wissen?
> Jein...
> Einen Divider für 6 Bit kann ich in ein BRAM packen...
>
> Ich wollte das eigentlich für 32/16 Bits wissen:
>>     :
>     zahl_32 : IN std_logic_vector(31 downto 0);
>     zahl_16 : IN std_logic_vector(16 downto 0)
>     :
>



 CORE                       Used:   1799  Total:  38400   (4.68%)
    IO (W/ clocks)             Used:     81  Total:    147   (55.10%)
    Differential IO            Used:      0  Total:     65   (0.00%)






> Und auch: Wie schnell kannst du dieses Design takten?

Wo seh ich das?

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


Lesenswert?

Marc K. schrieb:
>   zahl_32 : IN std_logic_vector(5 downto 0);
>   zahl_16 : IN std_logic_vector(5 downto 0)
>     CORE                    Used:    151  Total:  38400   (0.39%)

Marc K. schrieb:
>     zahl_32 : IN std_logic_vector(31 downto 0);
>     zahl_16 : IN std_logic_vector(15 downto 0)
>  CORE                       Used:   1799  Total:  38400   (4.68%)
Da wird tatsächlich ein kombinatorischer Divider gebaut.

>> Und auch: Wie schnell kannst du dieses Design takten?
> Wo seh ich das?
Das ist eine wichtige Zahl, die solltest du mit einem Blick erkennen 
können. Such mal im Synthese- oder Implementation-Report nach MHz.

von M. K. (marc1234)


Lesenswert?

>>> Und auch: Wie schnell kannst du dieses Design takten?
>> Wo seh ich das?
> Das ist eine wichtige Zahl, die solltest du mit einem Blick erkennen
> können. Such mal im Synthese- oder Implementation-Report nach MHz.




Alles was ich mit MHz im Report gefunden habe.
1
Clock Summary
2
**************
3
4
Start      Requested     Requested     Clock      Clock          
5
Clock      Frequency     Period        Type       Group          
6
-----------------------------------------------------------------
7
System     1.0 MHz       1000.000      system     system_clkgroup
8
=================================================================
9
10
11
12
13
Performance Summary 
14
*******************
15
16
17
Worst slack in design: NA
18
19
                   Requested     Estimated     Requested     Estimated               Clock        Clock              
20
Starting Clock     Frequency     Frequency     Period        Period        Slack     Type         Group              
21
---------------------------------------------------------------------------------------------------------------------
22
top|clk            100.0 MHz     NA            10.000        NA            NA        inferred     Inferred_clkgroup_0
23
=====================================================================================================================
24
25
26
##### START OF TIMING REPORT #####[
27
# Timing Report written on Thu Sep 06 16:08:47 2012
28
#
29
30
31
32
Requested Frequency:    100.0 MHz
33
Wire load mode:         top
34
Paths requested:        5
35
Constraint File(s):    
36
@N: MT320 |Timing report estimates place and route data. Please look at the place and route timing report for final timing.
37
38
@N: MT322 |Clock constraints cover only FF-to-FF paths associated with the clock.

von Spartanist (Gast)


Lesenswert?

Lothar Miller schrieb:
> Da wird tatsächlich ein kombinatorischer Divider gebaut.
Klaro und wenn man dem genug FF-stages hinten dran packt, kann die 
Synthese ihn per register retiming auch auf das jeweils benötigte Tempo 
bringen.

von T. M. (xgcfx)


Lesenswert?

Bei Actel FPGAs würde ich da nicht zuviel erwarten bezüglich 
Taktfrequenz. Deren Architecktur ist nicht auf solche Rechenschaltungen 
optimiert. Ich kann es hier ja auch mal fix bauen und nachprüfen, haben 
die Toolchain auch am Start.

von T. M. (xgcfx)


Lesenswert?

Also Synplify Pro 9.0.2A2 kann diese Division nicht synthetisieren. Er 
möchte gern nur durch 2^n teilen.

von M. K. (marc1234)


Lesenswert?

T. M. schrieb:
> Also Synplify Pro 9.0.2A2 kann diese Division nicht synthetisieren. Er
> möchte gern nur durch 2^n teilen.

Ich nutzte Synplify Pro AE F-2012.03MSP1. Da gehts.

von Lattice User (Gast)


Lesenswert?

M. K. schrieb:
> Ich nutzte Synplify Pro AE F-2012.03MSP1. Da gehts.

Mit Synplify Pro F-2012.03L geht es auch.

Resourcen auf ECP3-35
1
Design Summary
2
   Number of registers:    96
3
      PFU registers:    16
4
      PIO registers:    80
5
   Number of SLICEs:          1187 out of 16632 (7%)
6
      SLICEs(logic/ROM):      1187 out of 13428 (9%)
7
      SLICEs(logic/ROM/RAM):     0 out of  3204 (0%)
8
          As RAM:            0 out of  3204 (0%)
9
          As Logic/ROM:      0 out of  3204 (0%)
10
   Number of logic LUT4s:     709
11
   Number of distributed RAM:   0 (0 LUT4s)
12
   Number of ripple logic:    641 (1282 LUT4s)
13
   Number of shift registers:   0
14
   Total number of LUT4s:     1991

Geschwindigkeit (Speedgrade 9)
1
----------------------------------------------------------------------------
2
Preference                              |   Constraint|       Actual|Levels
3
----------------------------------------------------------------------------
4
                                        |             |             |
5
FREQUENCY NET "clk_c" 50.000000 MHz ;   |   50.000 MHz|   15.296 MHz|  94 *
6
                                        |             |             |
7
----------------------------------------------------------------------------



Ich habe noch Eingangsregister hinzugefügt, ohne hatte er mit dem 
Constraint nix am Hut.

von Lattice User (Gast)


Lesenswert?

Das ganze nochmal für einen MachXO2 (LCMXO2-4000HE Speedgrade 6)

Spannend ist der Unterschied zwischen der neuen Lattice Synthese Engine 
(LSE) und Synplify Pro

LSE:
1
Design Summary
2
   Number of registers:    80
3
      PFU registers:    0
4
      PIO registers:    80
5
   Number of SLICEs:           362 out of  2160 (17%)
6
      SLICEs(logic/ROM):       362 out of   540 (67%)
7
      SLICEs(logic/ROM/RAM):     0 out of  1620 (0%)
8
          As RAM:            0 out of  1620 (0%)
9
          As Logic/ROM:      0 out of  1620 (0%)
10
   Number of logic LUT4s:      69
11
   Number of distributed RAM:   0 (0 LUT4s)
12
   Number of ripple logic:    297 (594 LUT4s)
13
   Number of shift registers:   0
14
   Total number of LUT4s:     663
15
16
17
18
----------------------------------------------------------------------------
19
Preference                              |   Constraint|       Actual|Levels
20
----------------------------------------------------------------------------
21
                                        |             |             |
22
FREQUENCY NET "clk_c" 50.000000 MHz ;   |   50.000 MHz|    9.568 MHz| 284 *
23
                                        |             |             |
24
----------------------------------------------------------------------------


Synplify Pro:
1
Design Summary
2
   Number of registers:    93
3
      PFU registers:    13
4
      PIO registers:    80
5
   Number of SLICEs:          1199 out of  2160 (56%)
6
      SLICEs(logic/ROM):       540 out of   540 (100%)
7
      SLICEs(logic/ROM/RAM):   659 out of  1620 (41%)
8
          As RAM:            0 out of  1620 (0%)
9
          As Logic/ROM:    659 out of  1620 (41%)
10
   Number of logic LUT4s:     617
11
   Number of distributed RAM:   0 (0 LUT4s)
12
   Number of ripple logic:    641 (1282 LUT4s)
13
   Number of shift registers:   0
14
   Total number of LUT4s:     1899
15
16
----------------------------------------------------------------------------
17
Preference                              |   Constraint|       Actual|Levels
18
----------------------------------------------------------------------------
19
                                        |             |             |
20
FREQUENCY NET "clk_c" 50.000000 MHz ;   |   50.000 MHz|    7.048 MHz|  97 *
21
                                        |             |             |
22
----------------------------------------------------------------------------

Mit dem LSE werden viel weniger Resourcen gebraucht, es ist obendrein 
noch schneller obwohl der kritische Pfad über fast 3 mal so viele 
Logikebenen geht.

von Spartanist (Gast)


Lesenswert?

Du solltest am Eingang UND Ausgang mindestens 2, besser 3 Register 
haben, damit er

a) in die IO-FFs kommt
b) bequem zu jeder Resource kommt.

Damit ist sicher gestellt, dass das ausgerechnete Tempo wirklich das 
Maximum ist, dass die Architektur in einer günstigen Umgebung kann.


Habe beispielhaft einen Divider mit 160 Stellen gemacht:

signed(Zaehler(79 downto 0) & Leerbits(79 downto 0)) / signed (Nenner(79 
downto 0));

Er braucht nach 6 min Synthese >33.000 slices im Spartan3 und kommt auf 
etwas über 1MHz :-)

Nach Optimierung durch Trans & MAP (insgesamt 49 min) braucht er 154.000 
slices und schafft knapp 3 MHz

Da waren die alten DX33-Copros schon schneller :-)

Gibt es eigentlich CoProzessor-Chips als fertige ASICs?
Sowas liesse sich doch an einen FPGA anschliessen, die könnten dann 
DIV/LOG/SQR berechnen.

von Uwe (Gast)


Lesenswert?

> Gibt es eigentlich CoProzessor-Chips als fertige ASICs?
Nimm nen Fließkomma DSP z.B. C6000 mit PCIe Interface und verbinde den 
mit nem V6 oder V7. Oder über Serdes.

von Uwe (Gast)


Lesenswert?

> Gibt es eigentlich CoProzessor-Chips als fertige ASICs?
Klar nennt sich FPU 80387 für x86 und MC68882.
http://en.wikipedia.org/wiki/X87
http://de.wikipedia.org/wiki/Motorola_68881

von Spartanist (Gast)


Lesenswert?

Uwe schrieb:
>> Gibt es eigentlich CoProzessor-Chips als fertige ASICs?
>
> Klar nennt sich FPU 80387 für x86 und MC68882.

War schon klar, dass SO ein link kommt :-)

Uwe schrieb:
> Nimm nen Fließkomma DSP z.B. C6000
> SERDES
Ist wieder mit Flaschenhals. Ein ASIC könnte mit jedem Takt ein Datum 
berechnen.

von Sven P. (Gast)


Lesenswert?

Spartanist schrieb:
> Ist wieder mit Flaschenhals. Ein ASIC könnte mit jedem Takt ein Datum
> berechnen.
Das kannst du mit einem Kern im FPGA auch, und noch dazu vergleichsweise 
ressourcenschonend.

Tradeoff ist dann halt die Latenz. Zwar jeden Tankt ein Datum, aber 
nicht sofort am Ausgang.

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


Lesenswert?

Spartanist schrieb:
> Lothar Miller schrieb:
>> Da wird tatsächlich ein kombinatorischer Divider gebaut.
> Klaro und wenn man dem genug FF-stages hinten dran packt, kann die
> Synthese ihn per register retiming auch auf das jeweils benötigte Tempo
> bringen.
Das ist aber immer langsamer als ein nicht aufgeteilter Pfad und dazu 
ein Multicycle Constraint, weil ja für jedes FF noch die Setup-Zeit 
dazukommt...

von Michael (Gast)


Lesenswert?

Lothar Miller schrieb:
> Das ist aber immer langsamer als ein nicht aufgeteilter Pfad und dazu
> ein Multicycle Constraint,
Nun, dieses gilt ja generell: Sobald Speicher hinzutreten, wird der 
Zeitpfad länger, aber oft benötigt man die pipelinefähige Schaltung, um 
bei jedem  Takt Daten einspeisen zu können.

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


Lesenswert?

Es ist aber nicht so, dass eine mit "register retiming" beschleunigte 
Logik automatisch pipelinefähig wäre...

von Michael (Gast)


Lesenswert?

Doch, natürlich - unser Beispiel schon.. Oben die Kombinatorik hat 0,x 
Takte und benutzt damit einen Takt. Einen, der langsam genug ist. Eine 
beschleunigte Architektur braucht dann mehr Takte, nämlich die, die man 
künstlich angehängt hat und wird Dank balancing schneller.

Sie ist dann immer noch pipelinefähig.

Du hast natürlich dann Recht, wenn eine nicht gepipelinte Architektur 
mit FFs nachversorgt wird.

von berndl (Gast)


Lesenswert?

Michael schrieb:
> Sie ist dann immer noch pipelinefähig.

Da wage ich mal vorsichtig zu widersprechen...

Wenn du eine <10MHz Logik durch Zugabe von Registern und anpassen der 
Constraints auf ~100MHz hochzwiebelst ist das mitnichten pipelined. 
Pipelined wuerde bedeuten, dass du jeden 100MHz Takt neue Daten in die 
Stufe reinfuetterst und dass nach ~10 Zyklen dann das jeweilige Ergebnis 
rausfaellt.

Wenn du das ganze pipelined machen willst musst du schon eine adequate 
FSM schreiben die in jeder pipeline-Stufe eben auch die Daten 
entsprechend auf die naechste Stufe verteilt. Das ist dann aber 
Design/Handarbeit

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.