Log10 auf FPGA

Gast #4516422
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
Gast #4516483
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.
Gast #4516520
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!
Gast #4516790
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
Moderator (Firma: Titel) Persönliche Seite #4517115
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... ;-)
Angehängte Dateien:
Gast #4517594
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).

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren