www.mikrocontroller.net

Forum: FPGA, VHDL & Co. Flanke vom Signal erkennen


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,


ich habe eine Frage: Ich habe ein 12bit Eingangssignal vom AD Wandler. 
Wie mache ich am besten den VHDL code um die fallende Flanke vom Signal 
zu erkennen?


Ich dachte an zwischenstellen wo ich quasi ein Vergleich erstelle und wo 
ein max. wert erreicht wird und wenn er unterschritten wird fängt die 
fallende flanke an?


Hat da jemand ein besseren vorschlag?


Gruß


M.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wie mache ich am besten den VHDL code um die fallende Flanke vom Signal
> zu erkennen?
Du machst die erste Ableitung des Signals. Wenn diese eine bestimmte 
negative Schwelle überschreitet hast du eine fallende Flanke.

Also: vorherigen Wert speichern, eine bestimmte Zeit abwarten, dann den 
vorigen Wert vom aktuellen abziehen. Wenn das Ergebnis negativ ist und 
eine bestimmte Größe überschreitet, dann hast du die fallende Flanke.

Nicht ganz uninteressant sind natürlich auch Daten wie:
wie steil ist deine fallende Flanke?
welche Frequenz hat dein Signal?
ist es ein Signalgemisch?
wie definierst du eine fallende Flanke bei einem analogen Signal?

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

danke für den Tipp. Ich werde ein Impuls mit der breite von ca. 20 ms 
draufgeben. Der AD wandler tastet mit 20 Mhz ab.


Ich probier mal dein tipp in meine Logik reinzubekommen.




DANKE DANKE


Gruß

Autor: Marcus W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich werde ein Impuls mit der breite von ca. 20 ms
> draufgeben. Der AD wandler tastet mit 20 Mhz ab.

Da reicht doch evtl. ein einfacher Schmitt-Trigger.
Ich gehe mal davon aus, dass du High- und Low-Pegel des Impulses kennst. 
Dann könntest du dir zwei Grenzwerte definieren, die ein internes Signal 
entweder setzen oder löschen.

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,


die Amplitude soll variabel bleiben. Hab mal so es probiert:
  EINGANGSREGISTER: process (REGISTER_CLK, REGISTER_RESET)
    begin
      if REGISTER_RESET = '1' then
        SAVE0    <="000000000000";
      elsif falling_edge (REGISTER_CLK) then
          SAVE0<= REGISTER_EINGANG; 
          SAVE1<=SAVE0;
          SAVE2<=SAVE1;
          SAVE3<=SAVE2;
          SAVE4<=SAVE3;
          SAVE5<=SAVE4;
          SAVE6<=SAVE5;
          SAVE7<=SAVE6;
      end if;
  end process EINGANGSREGISTER;
  --------------------------------------------------------  
  
  
  Fall : process (REGISTER_CLK)
  begin
  if falling_edge (REGISTER_CLK) then
    if ((SAVE1 - SAVE0)>0 ) or  ((SAVE2 - SAVE1)>0) or ((SAVE3 - SAVE2)>0) or  ((SAVE4 - SAVE3))>0 or  ((SAVE5 - SAVE4)>0)  or ((SAVE6 - SAVE5)>0) or ((SAVE7 - SAVE6)>0) then
      Flanke <= '1';
    elsif ((SAVE1 - SAVE0)<0 ) or  ((SAVE2 - SAVE1)<0) or ((SAVE3 - SAVE2)<0) or  ((SAVE4 - SAVE3))<0 or  ((SAVE5 - SAVE4)<0)  or ((SAVE6 - SAVE5)<0) or ((SAVE7 - SAVE6)<0)   then
      Flanke <= '0';
    else
    end if;
  end if;
  end process Fall;
  
  
  Tasten :process (REGISTER_CLK)
  begin 
  if falling_edge (REGISTER_CLK) then
    if Flanke = '1' then
      REG_AUSGANG <= SAVE7;
    end if;
  end if;
  end process tasten;


end Behavioral;


Was haltet ihr davon?


Gruß

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Was haltet ihr davon?
Was sagt die Simulation?

Welche Frequenz hat der REGISTER_CLK? 20MHz, also 50ns?
Das wäre arg schnell verglichen mit einem
>>> Impuls mit der breite von ca. 20 ms
Immerhin sind da 6 Zehenerpotenzen dazwischen...  :-o

Autor: Thomas Reinemann (Firma: abaxor engineering) (abaxor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. schrieb:

Hallo,

wenn du mitten in einer fallenden Flanke bist, ist üblicherweise x(n - 
1) < x(n). Aber darauf kannst du dich nicht verlassen. Schon die 
AD-Wandler-Kennlinie muss nicht monoton sein, abgesehen vom Rauschen. 
Daher kann es passieren, dass x(n - 1) > x(n) in einer fallenden Flanke 
vorkommt.

Dann liefert einer deiner Vergleiche hier

>     if ((SAVE1 - SAVE0)>0 ) or  ((SAVE2 - SAVE1)>0) or ((SAVE3 -
> SAVE2)>0) or  ((SAVE4 - SAVE3))>0 or  ((SAVE5 - SAVE4)>0)  or ((SAVE6 -
> SAVE5)>0) or ((SAVE7 - SAVE6)>0) then

größer 0, damit erhälst du eine steigende Flanke. Das Ergebnis läuft 
dann durch deine Register und erzeugt dir für sieben Takte eine 
steigende Flanke.

Dies Problem hast du bei einer hohen Sampling-Frequenz, deine 20 MHz.
Falls du das nicht ändern kannst, ist es am einfachsten, du 
programmierst einen Schmitt-Trigger. Eine andere Möglichkeit beseht 
darin, einen Tiefpass (arithmetischer Mittelwert) zu verwenden oder eine 
Flanke muss mehr als 128 Takte aktiv sein, erst dann schaltest du um.

Oder reduziere die Samplingfrequenz.

Tom

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,


das mit dem (arithmetischer Mittelwert) hab ich mir auch schon überlegt, 
nur weiß ich nicht wie ich am besten das machen soll... die 7 
Zwischensspeicherungen addieren und duch 7 teilen?? Aber das mit dem 
Teilen ist so ein ding mit dem std_logic_vectoren..... gibt es was 
fertiges im coregeneartor zu finden? Oder wie programmier ich am besten 
den Teifpass oder Schmitt- Trigger?



Gruß

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keine Ahnung ob die mittelwerte wirklich zielführend sind, aber am 
einfachsten wäre es in dem Fall einfach 8 werte zu addieren und dann die 
hinteren 3 bits abzuschneiden, was einer division durch 8 entspricht.

Eine division durch 7 dafür zu verbauen wäre völlig mit Kanonen auf 
Spatzen geschossen.

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

da ich noch in paar dingen noch sehr als Anfäger bin, wie würd ich denn 
das machen die letzten 3 bits abzuschneiden?

Bzw. ich versteh es nicht ganz mit der division...?

Vielleicht ein zahlenbeispiel? :)

Gruß

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
z.b. so :

counter <= counter +1;
if counter <7 then
 summe <= summe + summand;
else
 counter <= (others => 0)
 summe <= "000" & summe(summe'length downto 3);
end if;

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> die letzten 3 bits abzuschneiden?
dafür gibts downto als Bereichseinschränkung:
summe_div_8 <= summe(summe'left downto 3); -- Bits 2..0 werden nicht verwendet

EDIT:
>> summe(summe'length downto 3);
summe'length  ist 1 zuviel... ;-)

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,



danke danke an euch beide! Werde es morgen mal probieren... meld mich 
noch!



Gruß ;)

Autor: Thomas Reinemann (Firma: abaxor engineering) (abaxor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo M.

Iulius schrieb:
> Eine division durch 7 dafür zu verbauen wäre völlig mit Kanonen auf
> Spatzen geschossen.

Eine Division durch Sieben ist eine Multiplikation mit

1/7 = 0.142857 = (0.142857 * 1024) / 1024 = 146/1024

Also, du addierst deine Eingangswerte, multiplizierst mit 146 und 
schneidest die letzten 10 Bit ab. Das geht auch mit anderen 
Zweierpotenzen.

Ich bezweifle, ob bei deinem Verhältnis (1/400000) von Signalfrequenz zu 
Samplingfrequenz ein Mittelwert über sieben Werte ausreicht. Das wäre 
ein FIR-Filter 6. Ordnung.

Am Besten du verwendest einen Schmitt-Trigger, den kannst du ganz 
einfach mit einer FSM programmieren.

Du kannst auch nur jedes 1024 Sample verwenden, damit hast du deine 
Samplingfrequnez auf rund 20kS/s reduziert.

Tom

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Anstatt einen Zähler zu nehmen der so weit zählt kann man aber auch 
gleich mehrere Takte lang auswerten, das ist zum einen sicherer bzgl 
einzelnen Ausreißern und verbraucht auch nicht viel mehr Ressourcen.

Wo soll denn nun der Vorteil von z.b. 7 Samples ggü 8 sein, so das man 
das auf Biegen und Brechen nutzen will (div, mul, etc) ?
Das erschließt sich mir nicht.


@ Lothar :

ich wusste doch das da ein Haken ist ;)
Verwende lenght praktisch nie, sondern wenn die Länge nicht feststeht 
meist direkt das entsprechende generic.
Das mit left werde ich mir aber merken, klingt gut.

Autor: igor (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,


irgendwie hab ich noch ein Denkfehler und zwar :
VHDL
SIGNAL SAVE0,SAVE1,SAVE2,SAVE3,SAVE4,SAVE5,SAVE6,SAVE7: STD_LOGIC_VECTOR (11 downto 0);
SIGNAL summe : std_logic_vector (11 downto 0);
SIGNAL summe_div_8 : std_logic_vector (11 downto 0);
SIGNAL Flanke  : std_logic;


begin
  
  summe <= (SAVE1 + SAVE2 + SAVE3+ SAVE4+ SAVE5+ SAVE6+ SAVE7);
  summe_div_8 <= summe(summe'length downto 3); -- 

-Code

Es kommt folgender fehler: ""Left bound value <12> of slice is out of 
range [11:0] of array <summe>
Netlist EINGANGS_REGISTER(Behavioral) remains a blackbox, due to errors 
in its contents""

@ Thomas :
> Am Besten du verwendest einen Schmitt-Trigger, den kannst du ganz
einfach mit einer FSM programmieren.

FSM = ? :)




Gruß

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
FSM = finite state machine oder einfacher "Zustandautomat"

ansonsten hatte Lothar schon recht, lenght ist eins zu viel.

summe_div_8 <= summe(summe'length downto 3);

ist also entweder
summe_div_8 <= summe(summe'length-1 downto 3);
oder
summe_div_8 <= summe(summe'left downto 3);


aber eigentlich sagt das der Fehler auch ;)



Scheinbar hast du aber noch ein paar mehr Denkfehler, wenn ich mir das 
ungetaktete Addieren sowie Auswerten von 8 Werten mit Signalen ansehe...

Hast du schonmal etwas einfacheres geschrieben ?
Mit ein paar Leds kann für den anfang super ausprobiern wie man das mit 
den shiftoperationen usw richtig macht.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Siehe Beitrag "Re: Flanke vom Signal erkennen"

EDIT:
Also gut, ich hätte gleich auf Absenden drücken müssen ;-)

Wenn SAVE0 ..7 jeweils 12 Bit breit sind, dann ist die Summe davon 3 Bit 
breiter.
Ergo: Das Signal summe als std_logic_vector(11 downto 0) ist zu kurz.

Du solltest nicht mit std_logic Vektoren rechnen, nimm besser die in der 
numeric_std definierten Datentypen signed und unsigned für solche 
Aufgaben.

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, also danke erstmal an euch alle!!!

Hier mal der Code, ich wollte für den Anfang einfach mal sagen wenn der 
Mittelwert der Zwischenstellen (SAVE0...7) kleiner als "100000000000" 
dann soll am Ausgang ne 1 kommen ansonsten ne null . Aber klappt nicht 
so ganz..
Am AD wandler liegt ein Rechtecksignal an!

Hier mal der Code:


architecture Behavioral of EINGANGS_REGISTER is

SIGNAL SAVE0,SAVE1,SAVE2,SAVE3,SAVE4,SAVE5,SAVE6,SAVE7: STD_LOGIC_VECTOR (11 downto 0);
SIGNAL summe : std_logic_vector (11 downto 0);
SIGNAL summe_div_8 : std_logic_vector (8 downto 0);
SIGNAL Flanke  : std_logic;

begin
  --------------------------------------------------------   
  EINGANGSREGISTER: process (REGISTER_CLK, REGISTER_RESET)
    begin
      if REGISTER_RESET = '1' then
        SAVE0    <="000000000000";
      elsif falling_edge (REGISTER_CLK) then
          SAVE0<= REGISTER_EINGANG; 
          SAVE1<=SAVE0;
          SAVE2<=SAVE1;
          SAVE3<=SAVE2;
          SAVE4<=SAVE3;
          SAVE5<=SAVE4;
          SAVE6<=SAVE5;
          SAVE7<=SAVE6;
          
      end if;
  end process EINGANGSREGISTER;
  --------------------------------------------------------  
  
  SUM: process (REGISTER_CLK)
  begin
    if falling_edge (REGISTER_CLK) then
      summe <= (SAVE0 + SAVE1 + SAVE2 + SAVE3+ SAVE4+ SAVE5+ SAVE6+ SAVE7);
    end if;
  end process SUM;
    
  summe_div_8 <= summe(summe'left downto 3);
  --------------------------------------------------------
  Fall : process (REGISTER_CLK)
  begin
  if falling_edge (REGISTER_CLK) then
    if summe_div_8 < ("100000000000") then -- 
      Flanke <= '0';
    elsif summe_div_8 > ("100000000000") then -- 
      Flanke <= '1';
    end if;
  end if;
  end process Fall;
  ----------------------------------------------------------
  Tasten :process (Flanke)
  begin 
    if Flanke = '1' then  
      REG_AUSGANG <="111111111111";
    elsif Flanke ='0' then
      REG_AUSGANG <="000000000000";
   end if;
  end process tasten;



Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was sagt denn die Simulation?

>     if summe_div_8 < ("100000000000") then --
Sieh dir mal die Warnungen des Synthesizers an.
Deine summe_div_8 ist nur 9 Bits breit, das ist dir klar?

>     if summe_div_8 < ("100000000000") then --
Welche Libs verwendest du denn?

Autor: Thomas Reinemann (Firma: abaxor engineering) (abaxor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
igor schrieb:
> @ Thomas :
>> Am Besten du verwendest einen Schmitt-Trigger, den kannst du ganz
> einfach mit einer FSM programmieren.
>
> FSM = ? :)

Diese Frage habe ich erwartet. Was bist du von Beruf, wie alt.


FSM heißt Finite State Machine auf Deutsch Zustandsmaschine, Endlicher 
Automat

http://de.wikipedia.org/wiki/Finite_State_Machine

Eine FSM beschreibt ein Verhalten, bei dem die Ausgangssignale nicht nur 
von den Eingangssignalen abhängen, sondern auch von einem internen 
Zustand. Jeder Zähler ist eine FSM.

Tom

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

@ Thomas : Bin Student und vom Zustandsautomaten habe ich natürlich 
gehört, kannte es lediglich unter FSM nicht! Es wurde auch behandelt, 
nur nicht so intensiv!


@Lothar Miller ; Jetzt hat es mich total verwirrt... ich möchte doch nur 
einen Mittelwert bilden.

Mal ein Beispiel:

A= 1111, B = 1011, C = 1000-- Mittelwert davon wäre laut der 
Beschreibung von obem mit dem "left downto"


      1111                         -- 15
+     1011                         -- 11
+     1000                         --  8
------------
    100010                         -- 34
 /      3                          --    3
------------------------
summe'left downto ?          -- 11,3 (1011)


Hier verplannt es mich, ich soll die letzten stellen weg schneiden? Es 
müsste ja 1011 rauskommen, wenn ich auch nur eine stelle wegschneide 
dann kommt da nie 1011 raus? Oder hab ich das vollkomen falsch 
verstanden.



Ich habe jetzt mal rumprobiert. und hab mir gedacht  Schwellen zu 
definieren, und zwar ist vom AD wandler max. Spannung bei "111111111111" 
was der 4095 quantisierungsstufe entspricht und min. bei "000000000000",
was der 0 quantisierungsstufe entspricht.


Ich hab einfach gesagt  wenn der Letzte zustand kleiner als 
"100110011001" (60% von Maximum) und die ersten 6 Zustände über der 
"100110011001" dann fängt da meine fallende Flanke an!



Fall : process (REGISTER_CLK)
  begin
  if falling_edge (REGISTER_CLK) then

  if (((SAVE7 and not SAVE6 and not SAVE5 and not SAVE4 and not SAVE3 and not SAVE2 and not SAVE1  < "100110011001")) then
      C <= '1';
    else 
      C<='0';
    end if;
  end if;
  end process Fall;
  ----------------------------------------------------------
  Tasten :process (C)
  begin 
  if falling_edge (REGISTER_CLK) then  
    if C = '1' then  
      REG_AUSGANG <="111111111111"; -- 000000000000
    elsif C ='0' then
      REG_AUSGANG <="000000000000";
    end if;
  end if;
  end process tasten;




Was auch einigermaßen funktioniert. Was haltet ihr davon?

Autor: Nephilim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
naja, das mit dem /3 is genauso ungünstig wie mit /7. am besten halt 
durch eine zweierpotenz teilen wie 2,4,8,16,32 ...
das hat den vorteil das man für die division nur shiften muss.

also 6/2=3
wodurch binär durch abschneiden der letzten stelle 110 -> 11(0) = 3 wird

und das funktioniert natürlich auch bei der 4

also 20/4 = 5
durch abschneiden der letzten beiden stellen sieht es dann so aus
10100 -> 101(00) = 5

ich hoffe, das prinzip ist verständlich dargestellt

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HI,

ok jetzt hab ich es kapiert! :) Danke nochmal für das Beispiel. Jetzt 
habe ich aber dazu eine Frage. Angenommen ich möchte aus 8 Zuständen den 
Mittelwert rechnen und dem dann meinem Ausgang zuweisen, wie mach ich 
das da der Ausgang ja std_logic_vector 11 downto 0 und mein Mittelwert 
ja dann nur noch aus 7 downto 0 besteht. (Teile duch 8 letzten 4 bits 
gehen verloren ). Kann ich da irgendwie die restlichen Bits mit Null 
füllen... oder geht es überhaupt nicht. Weil für mich wäre dies ein 
Filter dann, der mir ausreiser weg rechnet...



Geht das ?



Gruß

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vergiss zum Rechnen mal die std_logic Vektoren... :-/

Nimm die NUMERIC_STD statt der alten STD_LOGIC_ARITH + 
STD_LOGIC_UNSIGNED.
Und dann verwende konsequent die Datentypen unsigned und signed 
sowie zum Rechnen am besten integer.

Statt
  summe : unsigned (11 downto 0);  
  ergebnis : unsigned (7 downto 0);
   :
  ergebnis <= summe(11 downto 4); -- teilen durch 16
und
  summe : unsigned (12 downto 0);  
  ergebnis : unsigned (7 downto 0);
   :  
  ergebnis <= summe(12 downto 5); -- teilen durch 32
kannst du mit Integer einfach so schreiben
  summe : integer range 0 to 2**12-1;  
  ergebnis : unsigned (7 downto 0);
   :  
  ergebnis <= to_unsigned(summe/16,ergebins'length); -- teilen nur durch Zweierpotenzen!!

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein interner Akkumulator wird dann, wie Lother schon mehrfach erwähnt 
hat, breiter sein um auch die Überträge aufzunehmen.

Bsp : akku von 15 bit länge und ausgeben tust du nur die höherwertigen 
12 Bit.
Du verlierst übrigens bei Division durch 8 nur 3 stellen ;)



Ansonsten verabscheide dich bitte endlich von dem Gedanken solche Späße 
:

- "SAVE7 and not SAVE6 and not SAVE5 and not SAVE4 and not SAVE3 and not 
SAVE2 and not SAVE1  < "100110011001"

- summe <= (SAVE0 + SAVE1 + SAVE2 + SAVE3+ SAVE4+ SAVE5+ SAVE6+ SAVE7);

in einem Takt zu berechnen. Sieh dir bitte an wie FPGAs funktionieren 
und du wirst festellen das das was du da baust extrem lange Laufzeiten 
entwickelt.

Bei einem 4er LUT FPGA brauchst du dafür 12 Logikebenen, wenn ich mich 
nicht verzählt habe. Das wird jämmerlich langsam.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> as wird jämmerlich langsam.
Zudem wird dir eine einfachere Mittelwertbildung vollkommen reichen. 
Sowas etwa: http://www.lothar-miller.de/s9y/archives/25-Filter-in-C.html
Das ist zwar C, aber die Idee dürfte klar werden: ein Speicherregister 
(avgsum), in das jeweils 1 neuer Wert dazuaddiert wird, und der 
Mittelwert der alten Werte abgezogen wird.

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder eben die Methode wie von mir oben beschrieben.

In jedem Fall sollte man nicht alle Werte in einem Takt addieren, denn 
man bekommt sie ja schließlich ohnehin zu verschiedenen Zeitpunkten 
rein.


Noch eine simple Möglichkeit mit möglichst wenig Ressourcenverbrauch bei 
halbwegs kurzer Betrachtungsdauer(1 FF pro Takt Glättung + ~1/3 LUT pro 
Eingangsvektorbreite + ~1/3 LUT pro Takt Glättung) :

if value < trigger_schwelle then
 shiftreg <= shiftreg(shiftreg'left-1 downto 0) & '0';
else
 shiftreg <= shiftreg(shiftreg'left-1 downto 0) & '1';
end if;

high<='0';
low <='0';
if shiftreg=(shiftreg'left downto 0 => '1') then
 high<='1';
end if;
if shiftreg=(shiftreg'left downto 0 => '0') then
 low <='1';
end if;


Autor: J. Softwareintegrator (Firma: N.N. Darmstadt) (juergenffm) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Worin besteht denn da die Glättung?

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

puh ich hab mir gestern das zig mal durchgelesen..:) bin ein bischen, ne 
eigentlich total verwirrt. Ok, ich danke euch  herzlich für euere Hilfe, 
ich weiß dies zu schätzen!

Aber kommen wir zum signed, unsigend....Ok ab sofort verwende ich zum 
rechnen nicht mehr std_logic_vectoren sondern nur noch signed und 
unsigend und integer!

Zum Verständis, heißt es das man die Signale als std_logic_vector 
benutzten soll/kann, aber die Hilfssignale in signed und unsigned zum 
rechnen benutzen soll? Und später mit to_.... umkonventiert bzw. 
zuweist?


Zu meinem Beispiel: Ist den das schieberegister wennigstens vom Prinzip 
ok?



entity EINGANGS_REGISTER is
    Port ( REGISTER_EINGANG  : in  STD_LOGIC_vector (11 downto 0);
           REGISTER_RESET    : in  STD_LOGIC;
           REGISTER_CLK     : in  STD_LOGIC;
           REG_AUSGANG       : out  STD_LOGIC_vector (11 downto 0));
end EINGANGS_REGISTER;


architecture Behavioral of EINGANGS_REGISTER is

Signal SAVE0,SAVE1,SAVE2,SAVE3,SAVE4,SAVE5,SAVE6,SAVE7 : STD_LOGIC_vector (11 downto 0));
--Signal sum : signed (11 downto 0);
--Signal sum_div_8 : std_logic_vector (8 downto 0);
begin
  
  Schieben :process (REGISTER_CLK)
  begin
    if falling_edge (REGISTER_CLK) then
      SAVE0 <= REGISTER_EINGANG;
      SAVE1 <= SAVE0;
      SAVE2 <= SAVE1;
      SAVE3 <= SAVE2;
      SAVE4 <= SAVE3;
      SAVE5 <= SAVE4;
      SAVE6 <= SAVE5;
      SAVE7 <= SAVE6;
    end if;
  end process Schieben ; 

Für mich heißt es mit jedem Takt wird das Signal weitergegeben... was 
eigentlich auch gefunzt hatte oder habe ich selbst da ein denkfehler?

Jetzt würd ich als nächten schritt mit jedem Takt ein Mittelwert von 
diesem sieben Zwischenständen am Ausgang ausgeben..... und dazu werde 
ich jetzt mit signed und unsigned rechnen bzw. versuchen.


@ Iulius

>Du verlierst übrigens bei Division durch 8 nur 3 stellen ;)


Wieso drei ich dachte .....2^4 2^3 2^2 2^1 2^0
                           16   8   4  2    1

Ist doch die 4 Stelle ? oder ?




Gruß

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wieso drei ich dachte .....2^4 2^3 2^2 2^1 2^0
>                           16   8   4  2    1
> Ist doch die 4 Stelle ? oder ?
Was ist 13 geteilt durch 1? Oder 12785 geteilt durch 2^0?
Kurz: bei einer Division durch 1 mußt du nicht schieben...   :-o
Also mußt du bei einer Division durch 2 um 1 Stelle schieben,
bei einer Division durch 4 um 2 Stellen,
bei einer Division durch 8 dann um ... wieviele Stellen?

> Für mich heißt es mit jedem Takt wird das Signal weitergegeben... was
> eigentlich auch gefunzt hatte oder habe ich selbst da ein denkfehler?
Nein, das passt, ist aber enorm ineffizient, weil du so viel 
Speicherplatz (= Fliflops) verbrauchst...

Autor: Nephilim (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nicht die stelle ist das entscheidende, sondern die zweierpotenz. guckt 
dir mein beispiel oben mit /2 und /4 nochmal an.

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,


also mit den Stellen habe ich es jetzt verstanden und mit dem
 >Kurz: bei einer Division durch 1 mußt du nicht schieben...   :-o
sag ich nur: Klar, Shame on me! :)

Zu dem Signed und Unsigned... ich hab mir auf der Seite von Lothar 
Miller dieses Diagram von std_logic_vector => signed=>integer=>unsigned 
und dann wieder zu std_logic_vector.


Ich wollte jetzt fürs Üben, nach dem Schieberegister immer den 
Mittelwert von den letzt 2 zustanden ausgeben (SAVE7,SAVE6). Dazu habe 
ich sie in signed und dann in integer und dann wieder zurück gewandelt.



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.std_logic_unsigned.all; 
use IEEE.NUMERIC_STD.ALL;


---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity EINGANGS_REGISTER is
    Port ( REGISTER_EINGANG  : in  STD_LOGIC_vector (11 downto 0);
           REGISTER_RESET    : in  STD_LOGIC;
           REGISTER_CLK     : in  STD_LOGIC;
           REG_AUSGANG       : out  STD_LOGIC_vector (11 downto 0));
end EINGANGS_REGISTER;


architecture Behavioral of EINGANGS_REGISTER is

Signal SAVE0,SAVE1,SAVE2,SAVE3,SAVE4,SAVE5,SAVE6,SAVE7 : STD_LOGIC_vector (11 downto 0);
Signal S0,S1,S2,S3,S4,S5,S6,S7   : signed (11 downto 0);
Signal I6,I7          : integer;
Signal  summe : integer range 0 to 2**12-1;  
Signal  ergebnis : unsigned (11 downto 0);

begin
  
  Schieben :process (REGISTER_CLK)
  begin
    if falling_edge (REGISTER_CLK) then
      SAVE0 <= REGISTER_EINGANG;
      SAVE1 <= SAVE0;
      SAVE2 <= SAVE1;
      SAVE3 <= SAVE2;
      SAVE4 <= SAVE3;
      SAVE5 <= SAVE4;
      SAVE6 <= SAVE5;
      SAVE7 <= SAVE6;
    end if;
  end process Schieben ;
  
  Mittelwert: process (REGISTER_CLK)
  begin 
    S6 <=signed(SAVE6);
    S7 <=signed(SAVE7);
    I6 <=to_integer(S6);
    I7 <=to_integer(S7);
       if falling_edge (REGISTER_CLK) then
    summe <= (I6 + I7);  
       end if;
  ergebnis <= to_unsigned(summe/2,ergebnis'length);          
     end process Mittelwert;
  
  REG_AUSGANG <=std_logic_vector(ergebnis);

end Behavioral; 



Abgesehen davon das man das nicht in einem Takt rechnen soll wegen 
Recourcen verbrauch... was haltet ihr davon? Ist die denkweiße jetzt 
richtig?

Ich habe schon jetzt Angst vor eueren Antworten :)

Gruß

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Sensitivliste des Prozesses ist unvollständig:
  Mittelwert: process (REGISTER_CLK)
  begin 
    S6 <=signed(SAVE6);                                --- SAVE6
    S7 <=signed(SAVE7);                                --- SAVE7
    I6 <=to_integer(S6);                               --- S6
    I7 <=to_integer(S7);                               --- S7
    if falling_edge (REGISTER_CLK) then
      summe <= (I6 + I7); 
    end if;
    ergebnis <= to_unsigned(summe/2,ergebnis'length);  --- summe         
  end process Mittelwert;
Es fehlen alle die Signale, die hinter den --- stehen   :-o
Das wird dir die Simulation sauber zerhageln. Denn bei jeder Änderung 
eines dieser Signale müsste der Prozess neu berechnet werden.

Was du wolltest war wahrscheinlich sowas:
  S6 <= signed(SAVE6);                               
  S7 <= signed(SAVE7);                               
  I6 <= to_integer(S6);                              
  I7 <= to_integer(S7);                              

  Mittelwert: process (REGISTER_CLK)
  begin 
    if falling_edge (REGISTER_CLK) then
      summe <= (I6 + I7); 
    end if;
  end process Mittelwert;

  ergebnis <= to_unsigned(summe/2,ergebnis'length);  
Das könntest du auch abkürzen:
  Mittelwert: process (REGISTER_CLK)
  begin 
    if falling_edge (REGISTER_CLK) then
      summe <= (to_integer(signed(SAVE6)) + to_integer(signed(SAVE7))); 
    end if;
  end process Mittelwert;

  ergebnis <= to_unsigned(summe/2,ergebnis'length);  

Trotzdem: deine Summe ist positiv unsigned (range 0 to 2**12-1). Warum 
sollten dann S1..6 signed sein?

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

DANKE!!


hm... ja stimmt mit dem unsigned, hab mir noch mal die Definiton vom 
Wertebereich angeschaut. So aber jetzt, ist es jetzt eingermaßen ok was 
ich mache?
-> Das ich von std_logic_vector über unsigned auf integer wandle damit 
rechne und dann wieder zurückwandle??


-> Und wie ist es jetzt mit dem Teilen und den bits wegschneiden, 
angenommen ich würde ja mit 4 Teilen also müsste ich die letzten 2 bits 
wegschneiden...

ergebnis <= to_unsigned(summe/4,ergebnis'length downto 2);

ergebnis <= to_unsigned(summe/8,ergebnis'length downto 3);



Da mein Ausgang 12 bit breit ist, und mit dem Wegschneiden ja 2 bzw. 3 
bits fehlen?

Oder da ich ja mit Integerwerten teile, kriege ich auch ein Integerwert 
der diesen dann in ein std_logic_umwandelt und muss somit am ergebnis 
nichts wegschneiden?




Gruß

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Und wie ist es jetzt mit dem Teilen und den bits wegschneiden,
Die Bits schneidest du schon mit /4 bzw. /8 weg.

>>> summe : integer range 0 to 2**12-1;
Die summe sollte natürlich um diese 2 bzw. 3 Bits breiter sein:
 summe : integer range 0 to 2**15-1;

> Das ich von std_logic_vector über unsigned auf integer wandle damit
> rechne und dann wieder zurückwandle??
Das passt. Nur über die Wertebereiche mußt du dir (wie gesagt) Gedanken 
machen. Wenn du das nicht willst, dann schreibst du einfach mal:
  summe : integer;
Dann darf der Synthesizer selber rausfinden, was er braucht. Du hast 
aber in der simulation keine Kontrolle, wenn die Zahl mal überläuft...

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hm... also hier erstmal der überarbeitete Code


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
USE ieee.std_logic_unsigned.all; 
use IEEE.NUMERIC_STD.ALL;


Entity EINGANGS_REGISTER is
    Port ( REGISTER_EINGANG  : in  STD_LOGIC_vector (11 downto 0);
           REGISTER_RESET    : in  STD_LOGIC;
           REGISTER_CLK     : in  STD_LOGIC;
           REG_AUSGANG       : out  STD_LOGIC_vector (11 downto 0));
end EINGANGS_REGISTER;


architecture Behavioral of EINGANGS_REGISTER is

Signal SAVE0,SAVE1,SAVE2 : STD_LOGIC_vector (11 downto 0);
Signal S0,S1,S2   : unsigned (11 downto 0);
Signal I0,I1,I2  : integer;
Signal  summe : integer range 0 to 2**12-1 ;  
Signal  ergebnis : unsigned (11 downto 0);

begin
  
  Schieben :process (REGISTER_CLK)
  begin
    if falling_edge (REGISTER_CLK) then
      SAVE0 <= REGISTER_EINGANG;
      SAVE1 <= SAVE0;
      SAVE2 <= SAVE1;
    end if;
  end process Schieben ;
    --------------------
    S0 <=unsigned(SAVE0);
    S1 <=unsigned(SAVE1);
    S2 <=unsigned(SAVE2);
    --------------------
    I0 <=to_integer(S0);
    I1 <=to_integer(S1);
    I2 <=to_integer(S2);
    --------------------
  Mittelwert: process (REGISTER_CLK)
  begin 
    
      if falling_edge (REGISTER_CLK) then
        summe <= ((I2+I1));  
      end if;
  end process Mittelwert;
  
  ergebnis <= to_unsigned(summe/2,ergebnis'length); -- teilen nur durch Zweierpotenzen!!
  REG_AUSGANG <=std_logic_vector(ergebnis);

end Behavioral; 



Was mich jetzt stuzig macht ist wenn ich das so eingebe dann kommt am 
Ausgang(Oszi) für ein rechtecksignal ein sagen wir mal ein abgestutzes 
rechtecksignal.


Wenn ich aber statt
ergebnis <= to_unsigned(summe/2,ergebnis'length);
..
ergebnis <= to_unsigned(summe,ergebnis'length); 
und dafür oben die
((I2+I1)/2);
 mache kommt dann ein schöner gegläteter Rechteckraus ...


Ich dacht ich hätte es verstanden aber... :(

Ich mein wenn ich das bei dem integerwerten mache und sie addiere und 
dann durch 2 teile bekomme ich ja ein integerwert der dann wieder in ein 
std_logic_vector gewandelt wird => und das mach ja sinn für mich...

aber wenn ich das so mache das ich dann summe/2 oder 4 mache also laut 
der Erklärung so die bits wegschneide... kommt da was komsiches raus... 
hm...

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. schrieb:
> Ich dacht ich hätte es verstanden aber... :(
Das wird das Problem sein:
summe : integer range 0 to 2**12-1;
Du schneidest führende Stellen deiner Summe ab.
Mach daraus:
summe : integer;

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

danke danke für die Tipps die ganze Zeit!

Ich hab jetzt mal den Code abgespeckt und hab auf euere Tipps gehört und 
hab die Zwischenstände reduziert und den Mittelwert über ein counter 
gemacht. Was haltet ihr davon?

@ Über integer range 0 to 2** 12-1 hab ich nochmal nachgedacht, also 
wenn ich durch 8 teile müsen 3 stellen von meinem vector weg.Somit muss 
ich den hilfsvector um diese 3 stellen erweitern so das nur die unteren 
BITS (LSB) weggeschnitten werden und am ende die summe trotzdem 12 
ergibt oder? . wenn ich durch 2 teile => 13-1, druch 4 teile => 14-1 
durch 8 teile =>16-1 ... oder ?


Hier mal der Code

entity EINGANGS_REGISTER is
    Port ( REGISTER_EINGANG  : in  STD_LOGIC_vector (11 downto 0);
           REGISTER_RESET    : in  STD_LOGIC;
           REGISTER_CLK     : in  STD_LOGIC;
           REG_AUSGANG       : out  STD_LOGIC_vector (11 downto 0));
end EINGANGS_REGISTER;

architecture Behavioral of EINGANGS_REGISTER is

Signal SAVE0           : STD_LOGIC_vector (11 downto 0);
Signal S0              : unsigned (11 downto 0);
Signal ergebnis         : unsigned (11 downto 0);
Signal I0            : integer;
Signal summe,summe_max    : integer range  0 to 2**15-1;  
Signal cnt              : integer range  0 to 7 :=0;
begin
  
  Schieben :process (REGISTER_CLK)
  begin
    if falling_edge (REGISTER_CLK) then
      SAVE0 <= REGISTER_EINGANG;
    end if;
  end process Schieben ;
    --------------------
    S0 <=unsigned(SAVE0);
    --------------------
    I0 <=to_integer(S0);
    --------------------
    Mittelwert: process (REGISTER_CLK)
    begin 
      if falling_edge (REGISTER_CLK) then
      if cnt = 3 then
        cnt      <=0;
        summe_max <= summe;
        summe    <=0;
      else
        cnt   <= cnt+1;
        summe <= summe + I0;  
      end if;
    end if;
     end process Mittelwert;
  ergebnis <= to_unsigned(summe_max/4,ergebnis'length); -- teilen nur durch Zweierpotenzen!!
  
  REG_AUSGANG<=std_logic_vector(ergebnis);

end Behavioral; 



Zum eigentlichen Problem der Flankenerkennung, hatte ich ja erwähnt das 
ich das eventuell über schwellen mach wollte. Dies hatte auch geklappt 
aber in dem Bereich der Schwelle ist nicht nur die fallende Flanke, die 
haben will, sondern auch die Steigenede. Somit wurde mir 2 mal ein 
Signal ausgegben, ich will aber das er die steigende ignoriert und nur 
auf die fallende reagiert. Deshalb hatte ich auch mit
not
 gearbeitet  da nur einmal eine Bedingung vorkommen kann in dem die 
fallende Flanke anfängt.
Jetzt wurde mir nahegelegt das damit nicht arbeiten soll... und weiß 
jetzt nicht wie ich die steigende ignorieren soll...

Autor: Marcus W. (blizzi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. schrieb:
> Zum eigentlichen Problem der Flankenerkennung, hatte ich ja erwähnt das
> ich das eventuell über schwellen mach wollte.
Also doch ein Schmitt-Trigger?
process (CLK)
begin
  if falling_edge(CLK) then

    fallende_flanke <= '0';

    if REG_IN > schwelle_oben then
      zustand <= '1';
    end if;
    if REG_IN < schwelle_unten then
      zustand <= '0';
      if zustand = '1' then
        fallende_flanke <= '1';
      end if;
    end if;

  end if;
end process;

Damit bekommst du einen Impuls, wenn die fallende Flanke kam.
Die Grenzen legst du so weit entfernt, dass Rauschen den Schmitt-Trigger 
nicht beeinflusst bzw. schalten lässt.

Autor: Thomas Reinemann (Firma: abaxor engineering) (abaxor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. schrieb:

Durch
   summe    <=0;
in
> if cnt = 3 then
>         cnt      <=0;
>         summe_max <= summe;
>         summe    <=0;
>       else
>         cnt   <= cnt+1;
>         summe <= summe + I0;  
>       end if;


verlierst du jeden 4. Wert. Du musst summe mit I0 initialisieren.
summe    <= I0;

Tom

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, für den  Tipp, hat auch geklappt, wobei ich denke das er mir die 
steigende Flanke erkennt, aber da muss ich noch mit den Grenzen spielen!





Vielen Dank!



Gruß

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zusätzliche Frage:

Wenn ich auf die Flanke aber nur in bestimmten Zeitintervallen reagieren 
will, also ich erkenne vom Signal die Flanke und dann soll er für z.B 
500us nichts machen auch wenn sgignale kommen und dann erst wieder 
erkennen.

Ich hab mir gedacht es über ein Counter zu machen der quasi jedes mal 
hochgezahlt wird wenn eine fallende flanke vorliegt, und dann nur wenn 
der counter einen bestimmten wert hat gibt ich ein Signal am Ausgang. 
Was hlatet ihr von der Idee?



Gruß

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> in bestimmten Zeitintervallen ...
> ... es über ein Counter zu machen ...
Richtig: Zeiten werden in FPGAs mit Zählern gemacht.

Ich würde einen (sättigenden) Zähler nehmen, den bei einer erkannten 
Analogsignalflanke zurücksetzen und dann mit jeder Taktflanke des 
Mastertakts um 1 hochzählen. Wenn der Endwert erreicht ist, dann ist die 
Flankenerkennung wieder scharf. Und mit der nächsten erkannten 
Analogsognalflanke ghet das Spiel von vorne los.


> Wenn ich auf die Flanke aber nur in bestimmten ...
> ... jedes mal hochgezahlt wird wenn eine fallende flanke vorliegt
Du mußt aufpassen, dass du die Flanke nicht mit der Flanke verwechselst. 
Für mich ist eine Flanke die Taktflanke innerhalb des FPGAs. Such mal 
nach einem geeigneten Namen für die Änderung des Analogsignals (z.B. 
Sprung).

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,


so ungefähr hab ich mir das gedacht:

  Trigger: process (REGISTER_CLK)
    begin
      if falling_edge(REGISTER_CLK) then
        if cnt = 5 then
          sprung <= '0';
          if (S0 > "101001100101")  then  -- OBERE SCHWELLE HIER 65% VOM AD BEREICH
          zustand <= '1';
          end if;
          if (S0 < "011001100110")  then  -- UNTERE SCHWELLE HIER 40%  VOM AD BEREICH  
          zustand <= '0';
            if zustand = '1' then
              sprung <= '1';
            end if;
          end if;
        elsif sprung = '1' then
          cnt<=0;
        else
          cnt<=cnt+1;
        end if;
      end if;  
  end process Trigger;




> ...(sättigenden) Zähler nehmen, den bei einer erkannten
>Analogsignalflanke zurücksetzen ...

mit zurücksetzen meintest du schon den counter auf null wieder zu setzen 
und nicht um eins ab zu ziehen.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Machs doch einfacher:
  Trigger: process (REGISTER_CLK)
    begin
      if falling_edge(REGISTER_CLK) then
        if cnt<5 then   -- den Zähler einfach mal laufen lassen
          cnt <= cnt+1;
        end if;
        if cnt = 5 then
          if (S0 > "101001100101")  then  -- OBERE SCHWELLE HIER 65% VOM AD BEREICH
            zustand <= '1';
          end if;
          if (S0 < "011001100110")  then  -- UNTERE SCHWELLE HIER 40%  VOM AD BEREICH  
            if zustand = '1' then -- fallende Analogflanke
              cnt <= 0;           -- Zähler zurücksetzen
            end if;
            zustand <= '0';
          end if;
        end if;
      end if;  
  end process Trigger;

> mit zurücksetzen meintest du schon den counter auf null wieder
> zu setzen und nicht um eins ab zu ziehen.
Es gibt Zurücksetzen (auf 0), Laden (mit einem bestimmten Wert), 
Inkrement (+1) und Dekrement (-1).

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm...

und dem Ausgang weise ich den wert "1111111111111" wenn cnt = 0 oder wie 
z.B
 REG_AUSGANG <="000000000000" when cnt ='1' else "111111111111" ;    
 bzw. "000000000000" da ich ne invertierung am Ausgang hab?

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bzw.

    Trigger: process (REGISTER_CLK)
    begin
      if falling_edge(REGISTER_CLK) then
        if cnt<840 then   
          cnt <= cnt+1;
        end if;
        if cnt = 840 then
          if (S0 > "101001100101")  then  -- OBERE SCHWELLE HIER 65% VOM AD BEREICH
            zustand <= '1';
          end if;
          if (S0 < "011001100110")  then  -- UNTERE SCHWELLE HIER 40%  VOM AD BEREICH  
        if zustand = '1' then       -- FALLENDE ANALOFFLANKE
          cnt <= 0;                 -- ZÄHLER ZURÜCKSETZEN
        end if;
           zustand <= '0';
          end if;
        end if;
      end if;  
  end process Trigger;
 
  Aus:process (REGISTER_CLK) 
  begin
    if falling_edge (REGISTER_CLK) then
      if cnt = 0 then
        REG_AUSGANG <="000000000000";
      elsif cnt  > 0 then
        REG_AUSGANG <="111111111111";
      end if;
    end if;
  end process AUS;  

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ok hier mal der engültige code der auch soweit funktioniert


    Trigger: process (REGISTER_CLK)
    begin
      if falling_edge(REGISTER_CLK) then
        if cnt < 8399 then   
          cnt  <= cnt+1;
        end if;
        if cnt = 8399 then
          if (S0 > "101001100101")  then  -- OBERE SCHWELLE HIER 65% VOM AD BEREICH
            zustand <= '1';
          end if;
          if (S0 < "011001100110")  then  -- UNTERE SCHWELLE HIER 40%  VOM AD BEREICH  
        if zustand = '1' then       -- FALLENDE ANALOFFLANKE
          cnt <= 0;                 
        end if;
           zustand <= '0';
          end if;
        end if;
      end if;  
  end process Trigger;
 
  Aus:process (REGISTER_CLK) 
  begin
    if falling_edge (REGISTER_CLK) then
      if cnt > 0 and cnt < 100 then
        REG_AUSGANG <="000000000000";
      else
        REG_AUSGANG <="111111111111";
      end if;
    end if;
  end process AUS;  



ABER:( Ein kleiner Problem hab ich: Ich möchte nach einer erkannten 
Flanke das Signal für genau 420us nicht anschauen. Also ich hab ein 
clocksignal mit 20 MHZ, also hab ich alle 0,05 us ein Takt, 420/0,05 
sind 8400 werte und deswegen der counter bis 8399. Wenn ich es aber am 
Oszzi messe sind es genau 440us und somit 20us zu viel also 400 
Taktwerte zu viel... wieso? :(

Autor: Marcus W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was genau hast du gemessen?

Dein Code wartet 420us, dannach wartest du auf die nächste fallende 
Flanke am ADC, dannach wartest du wieder 420us usw...

Ich nehme an, du hast an REGISTER_OUT gemessen, da eine Periodendauer 
von 420 us zu messen wäre quasi Zufall, denn dann müsste die ADC Flanke 
jedesmal genau dann kommen, wenn der Trigger gerade wieder scharf 
geworden ist.

Autor: berndl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. schrieb:
>         if cnt < 8399 then
>           cnt  <= cnt+1;
>         end if;
>         if cnt = 8399 then
> ...

Warum so kompliziert? Schmeiss' doch das Signal 'zustand' komplett raus 
und mache anstelle der beiden 'if cnt <' bzw. 'if cnt =' daraus ein 
normales 'if'-'else'-'end if'. Und dann den reset des counters in den 
Zweig wo dein Maximalwert erreicht ist. Macht den Code um 50% kuerzer 
und besser lesbar

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

sorry mein Fehler, ne des passt schon so. Mein denkfehler war, dass er 
innerhalb von den 420us auf nichts reagiern soll. So und nach den 420us 
kamm die nächte flanke erst nach 20us und daher kam ich auf 440us. :)



Danke


Gruß

Autor: Marcus W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
berndl schrieb:
> Schmeiss' doch das Signal 'zustand' komplett raus

Wie unterscheidet man dann zwischen einer fallenden Flanke (vom ADC) und 
einem statischen Low-Pegel?

Autor: berndl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
na, also ich verstehe den Code oben so, dass nach einem vom Counter 
vorgegebenen Warteintervall wenn dann die Schwelle groesser als 
haumichblau ist der Counter von neuem los laeuft. Und das 'if schwelle > 
xxx' kann man ja in den else-Zweig reinschreiben (counter also auf 
Endwert und bleibt da auch).
So wie der Code jetzt ist, werden im selben Prozess FFs generiert, d.h. 
die Abarbeitung der folgenden Zustaende wird immer um einen Clock 
verzoegert. Macht es meiner Meinung nach schwerer lesbar/verstehbar. Da 
sind fuer meinen Geschmack halt ein paar Sachen vermantscht die 
eigentlich nicht zusammen gehoeren...

Autor: Marcus W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
berndl schrieb:
> ich verstehe den Code oben so, dass nach einem vom Counter
> vorgegebenen Warteintervall wenn dann die Schwelle groesser als
> haumichblau ist der Counter von neuem los laeuft.

Nicht ganz:
Nach einer Wartezeit wird auf die nächste fallende Flanke gewartet.
Das Signal "zustand" speichert den Wert eines Schmitt-Triggers.

Wichtig ist denke ich, dass auf die fallende Flanke gewartet wird und 
bei konstantem Pegel nicht getriggert wird.


Den 2. Vorschlag find ich aber auch gut, man kann wirklich ein 
if-then-else draus machen :)

Autor: berndl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, hab' ich jetzt auch bemerkt...

Aber dann wuerde ich den Schmitt-Trigger in einen eingenen Prozess 
verpacken. So ist es m.M. wirklich unuebersichtlich...

Autor: Thomas Reinemann (Firma: abaxor engineering) (abaxor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. schrieb:
> Zusätzliche Frage:
>
> Wenn ich auf die Flanke aber nur in bestimmten Zeitintervallen reagieren
> will, also ich erkenne vom Signal die Flanke und dann soll er für z.B
> 500us nichts machen auch wenn sgignale kommen und dann erst wieder
> erkennen.
>
> Ich hab mir gedacht es über ein Counter zu machen der quasi jedes mal
> hochgezahlt wird wenn eine fallende flanke vorliegt,

Ich würde nicht den Haupttakt nehmen. Für solche Fälle habe ich in 
meinen Designs immer einen 1µs Tick. Also ein Enable-Signal, dass einmal 
pro µs aktiv wird.

> und dann nur wenn
> der counter einen bestimmten wert hat gibt ich ein Signal am Ausgang.
> Was hlatet ihr von der Idee?

Dann musst du hier nur bis 500 zählen und nicht bis 20*500.

Tom

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ja den code muss ich wirklich noch etwas netter umgestalten, da er aber 
funktioniert reicht  mir das mal für Testzwecke.

Was mich aber noch stört ist folgendes. Ich möchte als nächstem Schritt 
wenn eine Fallende Flanke erkannt wurde , als Antwort eine z.B 
E-kunktion fahren. Die E-Funktion habe ich mir im coregenerator als 
12bit breit und auf 1023 stellen mittels .coe file erstellt und als 
componente implementiert.


Zum test hab ich mal die Efunktion direkt ohne was dazwischen auf dem 
Ausgang gegeben um zu schauen obs auch passt.

So dann wollte ich wie oben schon erwähnt als Antwort auf mein Signal 
geben.

Dazu

  Aus:process (REGISTER_CLK) 
  begin
    if falling_edge (REGISTER_CLK) then
      if cnt > 0  and cnt < 1023 then
        REG_AUSGANG <=Efunk;
      else
        REG_AUSGANG <="111111111111";
      end if;
    end if;
  end process AUS;  


 so umgeschrieben. Wenn ich mich auf den cnt beziehe dann habe ich 
festgestellt das ich auch ein Wertebereich von 1023 definieren muss um 
die Efunktion darzustellen. Meine Frage ist, kann das so sein? Ist meine 
process für Ausgabe korrekt.


Zur Efunktion : 12 bit, 1023 tief und lass es mit jedem Takt ausgeben

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wie würde ich vor der fallenden Flanke die maximale Amplitude auch noch 
dazu erkennen, die ich dann mit meiner Antwort mulitpliziere?



Gruß

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
M. schrieb:
> wie würde ich vor der fallenden Flanke die maximale Amplitude auch noch
> dazu erkennen, die ich dann mit meiner Antwort mulitpliziere?
????

Autor: M. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,


ich meine ich gebe ja ein Impuls. Dieser Impuls ist in der Amplitude 
variabel, diese Ampliutde möchte ich auch noch erkennen, also die 
Fallende Flanke vom Impuls, (was ja schon geht) und auch noch die 
maximale Amplitude von diesem Signal bzw. Impuls... irgendwie denk ich 
an das Schieberegister (was ihr nicht so effektiv findet) und irgendwie 
ein Vergleich machen...aber es fällt mir so keine Idee ein.


Und noch mals zum Ausgang, passt es so mit dem cnt als quasi Enable 
signal?


Gruß

Autor: Basti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,


eine Frage hätte ich zur Flankenerkennung und zwar :
    if REG_IN > schwelle_oben then
      zustand <= '1';
    end if;
    if REG_IN < schwelle_unten then
      zustand <= '0';


Wieso wird hier nur die fallende Flanke erkannt und nicht auch noch die 
steigende Flanke? Denn REG_IN > schwelle_oben trifft doch 2 mal zu bei 
einem rechteck-Impuls? genaus so wie REG_IN < schwelle_unten 2 mal 
zutrifft oder wie soll man das verstehen?

Autor: Marcus W. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Basti,

das entscheidende hast du vergessen zu kopieren:
    if REG_IN < schwelle_unten then
      zustand <= '0';
      if zustand = '1' then
        fallende_flanke <= '1';
      end if;
    end if;

Nur wenn die Schwelle zum ersten mal unterschritten wird, wird eine 
Flanke detektiert.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.