Forum: FPGA, VHDL & Co. Log10 auf FPGA


von Alex (Gast)


Lesenswert?

Hallo!
Ich muss für ein Uni Labor einen 10er log auf den FPGA bringen. Ich 
arbeite mit Xilinx ISE und einem Spartan 3A Starter Kit!
Ich habe mir schon den Cordic Algorithmus angeschaut und auch schon 
überrissen wie ich im CoreGen ein passendes Modul instanziere.
Ich bin jedoch ein wenig Ratlos wenn es um die Constraints der 
Eingangsvektoren des Cordic Blocks geht: die Eingänge werden im Fixkomma 
format x.xxxxxxxx(wieviele bit auch immer nach dem Komma) benötigt. Muss 
ich nun meine 8 Bit Eingangszahl sooft nach rechts shiften das ich sie 
in dem format hab? dann von 2^n den natürlichen logarithmus in eine 
tabelle schreiben und nachdem ich von meiner zahl 0<zahl<2 den ln 
berechnet habe, diesen mit dem passenden ln(2^n) addieren? Oder gibt es 
eine einfachere Möglichkeit die ich gerade nicht bedenke?
Den natürlichen Log muss ich dann am schluss eben noch zum 10er Log 
umformen.

Vielen Dank für eure Hilfe und eure Tipps!


LG Alex

Hier der Link zur Doku des Moduls:
http://www.xilinx.com/support/documentation/ip_documentation/cordic_ds249.pdf

von Tippgeber (Gast)


Lesenswert?

Du musst sie so schieben, dass sie alle passen und dabei wissen, wo du 
aufgefüllt hast. Das ist quasi ein Faktor, der hinten "mehr" rauskommt. 
Den muss man wieder "abziehen" - in diesem Fall wohl tatsächlich 
abziehen, weil ein Shift im Logarithmischen ein Minus ist. Dann einfach 
den log(10,2) draufmultiplizieren. Oder war es ln(10)/ln(2) - bin nicht 
mehr so sicher.

von Alex (Gast)


Lesenswert?

also ist das schon die "richtige" Art es zu machen? Hab leider kein 
einziges richtig ausdokumentiertes Projekt oder Beispiel gefunden, immer 
nur mit der erklärung dass es mit dem Cordic geht....

Es muss + sein, weil (ich schreibs mal fürs 10er system auf): Log(1500) 
= log (1.5 *10^3)= log(1.5)+log(10^3)=log(1.5)+3

Ich soll 8bit einlesen und 8 bit ausgeben, ich darf mir selber aussuchen 
welche Zahlen das sein dürfen (natürliche, ganze, fixkomma). ich will 
bei als eingang 0-255 machen und als ausgang xx.xxxxxx fixkomma. weil 
mehr als 2,40...kann dann ehh nicht rauskommen!

LG und danke!

von Duke Scarring (Gast)


Lesenswert?

Alex schrieb:
> Ich soll 8bit einlesen und 8 bit ausgeben, ich darf mir selber aussuchen
> welche Zahlen das sein dürfen (natürliche, ganze, fixkomma). ich will
> bei als eingang 0-255 machen und als ausgang xx.xxxxxx fixkomma. weil
> mehr als 2,40...kann dann ehh nicht rauskommen!
Bei 2^8 Eingangswerten würde ich eine Tabelle nehmen, ehe ich mich mit 
dem Coregen-Format rumplage.

Duke

von Alex (Gast)


Lesenswert?

Wie gesagt, ist für eine Uni Übung und die 8bit kommen eher daher das 
das DevBoard nur 4 DIP Switches und 4 Taster hat...Und Cordic ist 
vorgegeben!

LG

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


Angehängte Dateien:

Lesenswert?

Duke Scarring schrieb:
> Bei 2^8 Eingangswerten würde ich eine Tabelle nehmen
Und die kann man dann auch leicht den Synthesizer berechnen lassen.

Alex schrieb:
> als ausgang xx.xxxxxx fixkomma.
Damit verschenkst du von deinen 8 Bits aber gut 40% des maximalen 
Wertebereichs und damit 40% der Genauigkeit.

Ich würde am Ausgang 0..255 herauskommen lassen und das bei Bedarf im 
Verlauf der späteren Rechnung dann per Multiplikation zurechtskalieren. 
Damit hätte ich in der eigentlichen log10 Berechnung die maximale 
Genauigkeit und Dynamik. Und sehr wahrscheinlich muss das Ergebnis 
sowieso irgendwo skaliert oder umgerechnet werden...

Hier mal mein Ansatz und im Anhang die Waveform der Testbench (die gibt 
nur die Werte 0..255 vor):
1
library IEEE;
2
  use IEEE.std_logic_1164.all;
3
  use IEEE.numeric_std.all;
4
  USE ieee.math_real.log10;
5
6
Entity LOG is
7
  Port ( CLK  : in  std_logic;
8
         Din  : in  std_logic_vector (7 downto 0);
9
         Dout : out std_logic_vector (7 downto 0)
10
        );
11
end LOG;
12
13
Architecture RTL of LOG is
14
15
  type Rom256x8 is array (0 to 255) of unsigned (7 downto 0); 
16
  signal LOG_Rom : Rom256x8;
17
  signal RomAddr  : integer range 0 to 255;
18
19
begin
20
21
   -- Tabelle berechnen beginnend mit log(1)
22
   table: for i in 0 to 255 generate
23
     LOG_Rom(i) <= to_unsigned( integer( log10(real(i)+1.0)/log10(256.0)*255.0 ),8);
24
   end generate;
25
26
   -- BROM      
27
   process begin
28
     wait until rising_edge(CLK);
29
     RomAddr <= to_integer(unsigned(Din));    -- getaktete Adresse --> BROM
30
   end process;
31
   Dout <= std_logic_vector(LOG_Rom(RomAddr));
32
33
end RTL;

Alex schrieb:
> Und Cordic ist vorgegeben!
Also eine schöne, aber realitätferne Übung... ;-)

: Bearbeitet durch Moderator
von Markus F. (Gast)


Lesenswert?

Für so wenige Werte ist ein Logarithmus ja eher witzlos.

Ließe sich das nicht irgendwie mathematisch zerlegen und zwei kleine 
Tabellen mit Ergebnissen der Teiler aus der Vorgabezahl nutzen, um Platz 
zu sparen?

wenn ... log (a*b) = log (a) + log(b) ->

könnt man doch die Zweierpotenzen aus der Vorgabe rausziehen und später 
wieder "drafaufaddieren", da der Log (2) trivial ist. Bliebe nur die 
Umrechnung auf log(10).

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.