Forum: FPGA, VHDL & Co. Umsetzung LowPass Filter C in vhdl


von Thomas S. (tstoll)


Lesenswert?

Hallo -
ich habe hier einen C-Code eines LowPass Filters, und wüßte gerne wie 
man so einen Code in VHDL umsetzt.. Clock Frequency = 32kHz
Wäre um jeden Hinweis dankbar.
Grüße

unsigned long LPF2(unsigned char voltf, char smpl)
//====================================================================== 
===
{
static unsigned long ACC0=0, ACC1=0, ACC2=0, OUT=0;

    ACC0+=voltf;

    if (smpl) {
      ACC1+=(ACC0*16-OUT);

      ACC2+=(ACC1/32);
      OUT = ACC2/16;

      ACC2-=OUT;
      OUT = ACC2/16;
      ACC0=0;
    }
    return(OUT);
}

von Wolfang L. (Gast)


Lesenswert?

Sieht irgendwie nach einem HP zweiter Ordnung aus. Im Prinzip kannst du 
das in VHDL genau so hinschreiben, da keine divider benötigt werden.

von Thomas S. (tstoll)


Lesenswert?

Hallo Wolfgang -

hier habe ich mal angefangen, weiss aber nicht wie ich die C-Funktion 
umsetzen soll. Jeglicher input willkommen.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity lp2 is
port(
clk     : in std_logic;
smpl     : in std_logic;
voltf    : in integer;
output  : out integer :=0)
end lp2;

architecture t1 of lp2 is

begin

  process(clk) is
    variable ACC0 : integer_vector(0 to 5) := (others => 0);
    variable ACC1 : integer_vector(0 to 5) := (others => 0);
    variable ACC2 : integer_vector(0 to 5) := (others => 0);
  begin -- process
    if rising_edge(clk) then -- rising clock edge
     if smpl = '1' then
      ??
      ??
      ??
     else
      output <= output;
     end if;
    end if;
  end process;

end t1;

von Duke Scarring (Gast)


Lesenswert?

Thomas Stoll schrieb:
> use IEEE.STD_LOGIC_ARITH.ALL;
> use IEEE.STD_LOGIC_UNSIGNED.ALL;
NEIN, nicht für neue Designs. Besser:
1
use ieee.numeric_std.all;
Für nähere Informationen bitte die Forumssuche benutzen.
1
  signal ACC0 : integer := 0;
2
  signal ACC2 : integer := 0;
3
  signal temp : integer := 0;
4
5
  process(clk) is
6
  begin -- process
7
    if rising_edge(clk) then -- rising clock edge
8
9
    ACC0 = ACC0 + voltf;
10
11
      if smpl = '1' then
12
        ACC1 <= ACC1 + (ACC0 * 16 - temp);
13
        ACC2 <= ACC2 + (ACC1 / 32);
14
        ACC2 <= ACC2 - (ACC2 / 16);
15
        temp <= ACC2 / 16;
16
        ACC0 <= 0;
17
      end if;
18
19
    OUT <= temp;
20
21
    end if;
22
  end process;
Ob das tut mußt Du mal schauen (simulieren), Dein Quellcode läßt sich 
so, wie er ist nicht direkt in Hardware umsetzen.

BTW: Welchen Simulator verwendest Du?

Duke

von Thomas S. (tstoll)


Lesenswert?

Danke, werde ich mal ausprobieren.
Ich verwende ISE.
Grüße,
Tom

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


Lesenswert?

Duke Scarring schrieb:
> BTW: Welchen Simulator verwendest Du?
Thomas Stoll schrieb:
> Ich verwende ISE.
Pech, der ISIM kann noch keine Analogdarstellung...   :-(

Duke Scarring schrieb:
>   signal ACC0 : integer := 0;
>   signal ACC2 : integer := 0;
>   signal temp : integer := 0;
>
>   process(clk) is
>   begin -- process
>     if rising_edge(clk) then -- rising clock edge
>       ACC0 = ACC0 + voltf;
>       if smpl = '1' then
>         ACC1 <= ACC1 + (ACC0 * 16 - temp);
>         ACC2 <= ACC2 + (ACC1 / 32);
>         ACC2 <= ACC2 - (ACC2 / 16);   --- ACC2 ist ein Signal
>                     --> der vorige Wert wird einfach überschrieben...
> :
> :
> Ob das tut mußt Du mal schauen...
Kann leider nicht tun, weil ACCx Signale sind und daher ACC2 einfach 
überschreiben wird.
In diesem speziellen Fall hier würde ich die "globalen" 
Akkumulatorsignale im Prozess auf temporäre Variablen abbilden, mit 
denen rechnen und das Ergebnis am Ende des Prozesses wieder an die 
Signale zuweisen...

von Thomas S. (tstoll)


Lesenswert?

Hallo Lothar -

Schade das mit ISE.. könnte allerdings auch auf modelsim umsteigen..

Und - könntest Du mir das

<<In diesem speziellen Fall hier würde ich die "globalen"
Akkumulatorsignale im Prozess auf temporäre Variablen abbilden, mit
denen rechnen und das Ergebnis am Ende des Prozesses wieder an die
Signale zuweisen...>>

mal als Beispiel anschreiben?

Grüße,
Tom

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


Lesenswert?

Thomas Stoll schrieb:
> Und - könntest Du mir das mal als Beispiel anschreiben?
Naja, sooooo kompliziert ist das nicht:
1
  signal ACC0 : integer := 0;
2
  signal ACC1 : integer := 0;
3
  signal ACC2 : integer := 0;
4
  signal RESULT : integer := 0; -- ein Signal darf nicht OUT heißen, das ist ein Keyword
5
6
  process(clk) is
7
    variable A0  : integer; -- alles nur temporäre Variable
8
    variable A1  : integer;      --> hier wird kein Flipflop instatiiert
9
    variable A2  : integer;
10
    variable RES : integer;
11
  begin -- process
12
    if rising_edge(clk) then -- rising clock edge
13
      A0  := ACC0; -- "globale" Signale auf Variable abbilden
14
      A1  := ACC1;
15
      A2  := ACC2;
16
      RES := RESULT;
17
18
      if (clock_enable_32khz='1') then  -- der FPGA-Takt wird ja wohl höher sein als 32kHz, deshalb wird mit Clock-Enable gearbeitet
19
        A0 = A0 + voltf;
20
21
        if (smpl='1') then
22
          A1  := A1 + (A0*16 - RES);
23
24
          A2  := A2 + (A1/32);
25
          RES := A2/16;
26
27
          A2  := ACC2 - (RES/16);
28
          RES := A2/16;
29
          A0  := 0;
30
        end if;
31
32
      end if;
33
34
      RESULT <= RES; -- Signale updaten
35
      ACC0   <= A0;
36
      ACC1   <= A1;
37
      ACC2   <= A2;
38
    end if;
39
  end process;

von Thomas S. (tstoll)


Lesenswert?

Herzlichen Dank!

Es wird mit 32kHz gearbeitet.. somit gehe ich davon aus, dass ich das 
clk_enable_32kHz weg lassen kann?

Grüße,
Tom

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


Lesenswert?

Thomas Stoll schrieb:
> Es wird mit 32kHz gearbeitet.. somit gehe ich davon aus, dass ich das
> clk_enable_32kHz weg lassen kann?
In dem Fall schon, ja. Aber ... :-/

... die Frequenz scheint mir doch extrem niedrig. Worauf wird das Filter 
implementiert (CPLD/FPGA)? Läuft das ganze Design drumrum auch mit 
32kHz? Wieviele Takte hast du in dem Design?

von Thomas S. (tstoll)


Lesenswert?

Design soll auf FPGA ausprobiert werden. Anschliessend in CMOS 0.35u 
Technologie synthetisiert werden.
Kann man die inputs (integer) irgendwie auf 6 bit begrenzen?

So vielleicht?

integer_vector(5 downto 6)

Tom

von Thomas S. (tstoll)


Lesenswert?

also, habe gerade nochmals nachgelesen

der systemtakt ist 32KHz
der sample takt ist 1kHz für das LPF.

damit bekomme ich zusammen mit den koeffizienten einen butterworth LPF 
mit 7Hz Grenzfrequenz

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


Lesenswert?

Thomas Stoll schrieb:
> Kann man die inputs (integer) irgendwie auf 6 bit begrenzen?
signal vorzeichenlos : integer range 0 to 63;
oder
signal vorzeichenbehaftet : integer range -32 to 31;

von Hocko (Gast)


Lesenswert?

Den 2 stufigen Filter müsse man auch verkettet schreiben können:

Kombinatorisch: (Neubelegung)

Wert1Neu <= Wert1Alt*(1-k1) + Input*k1;
Wert2Neu <= Wert2Alt*(1-k2) + Wert1Neu*k2;


Getaktet: (Fortschreiben der Zeit)

Wert1Alt <= Wert1Neu;
Wert2Alt <= Wert2Neu;

Output <= Wert2Neu;

Wenn man sowas dreistufig baut, kann man aus einem Rechteck locker einen 
Sinus machen. Die k1 müssen dazu in der Höhe absteigen.

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.