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


von M. (Gast)


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.

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


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?

von M. (Gast)


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ß

von Marcus W. (Gast)


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.

von M. (Gast)


Lesenswert?

Hi,


die Amplitude soll variabel bleiben. Hab mal so es probiert:
1
  EINGANGSREGISTER: process (REGISTER_CLK, REGISTER_RESET)
2
    begin
3
      if REGISTER_RESET = '1' then
4
        SAVE0    <="000000000000";
5
      elsif falling_edge (REGISTER_CLK) then
6
          SAVE0<= REGISTER_EINGANG; 
7
          SAVE1<=SAVE0;
8
          SAVE2<=SAVE1;
9
          SAVE3<=SAVE2;
10
          SAVE4<=SAVE3;
11
          SAVE5<=SAVE4;
12
          SAVE6<=SAVE5;
13
          SAVE7<=SAVE6;
14
      end if;
15
  end process EINGANGSREGISTER;
16
  --------------------------------------------------------  
17
  
18
  
19
  Fall : process (REGISTER_CLK)
20
  begin
21
  if falling_edge (REGISTER_CLK) then
22
    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
23
      Flanke <= '1';
24
    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
25
      Flanke <= '0';
26
    else
27
    end if;
28
  end if;
29
  end process Fall;
30
  
31
  
32
  Tasten :process (REGISTER_CLK)
33
  begin 
34
  if falling_edge (REGISTER_CLK) then
35
    if Flanke = '1' then
36
      REG_AUSGANG <= SAVE7;
37
    end if;
38
  end if;
39
  end process tasten;

end Behavioral;


Was haltet ihr davon?


Gruß

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


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

von Thomas R. (Firma: abaxor engineering) (abaxor)


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

von M. (Gast)


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ß

von Iulius (Gast)


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.

von M. (Gast)


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ß

von Iulius (Gast)


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;

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


Lesenswert?

> die letzten 3 bits abzuschneiden?
dafür gibts downto als Bereichseinschränkung:
1
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... ;-)

von M. (Gast)


Lesenswert?

Hallo,



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



Gruß ;)

von Thomas R. (Firma: abaxor engineering) (abaxor)


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

von Iulius (Gast)


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.

von igor (Gast)


Lesenswert?

Hallo,


irgendwie hab ich noch ein Denkfehler und zwar :
1
VHDL
2
SIGNAL SAVE0,SAVE1,SAVE2,SAVE3,SAVE4,SAVE5,SAVE6,SAVE7: STD_LOGIC_VECTOR (11 downto 0);
3
SIGNAL summe : std_logic_vector (11 downto 0);
4
SIGNAL summe_div_8 : std_logic_vector (11 downto 0);
5
SIGNAL Flanke  : std_logic;
6
7
8
begin
9
  
10
  summe <= (SAVE1 + SAVE2 + SAVE3+ SAVE4+ SAVE5+ SAVE6+ SAVE7);
11
  summe_div_8 <= summe(summe'length downto 3); -- 
12
13
-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ß

von Iulius (Gast)


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.

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


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.

von M. (Gast)


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:

1
architecture Behavioral of EINGANGS_REGISTER is
2
3
SIGNAL SAVE0,SAVE1,SAVE2,SAVE3,SAVE4,SAVE5,SAVE6,SAVE7: STD_LOGIC_VECTOR (11 downto 0);
4
SIGNAL summe : std_logic_vector (11 downto 0);
5
SIGNAL summe_div_8 : std_logic_vector (8 downto 0);
6
SIGNAL Flanke  : std_logic;
7
8
begin
9
  --------------------------------------------------------   
10
  EINGANGSREGISTER: process (REGISTER_CLK, REGISTER_RESET)
11
    begin
12
      if REGISTER_RESET = '1' then
13
        SAVE0    <="000000000000";
14
      elsif falling_edge (REGISTER_CLK) then
15
          SAVE0<= REGISTER_EINGANG; 
16
          SAVE1<=SAVE0;
17
          SAVE2<=SAVE1;
18
          SAVE3<=SAVE2;
19
          SAVE4<=SAVE3;
20
          SAVE5<=SAVE4;
21
          SAVE6<=SAVE5;
22
          SAVE7<=SAVE6;
23
          
24
      end if;
25
  end process EINGANGSREGISTER;
26
  --------------------------------------------------------  
27
  
28
  SUM: process (REGISTER_CLK)
29
  begin
30
    if falling_edge (REGISTER_CLK) then
31
      summe <= (SAVE0 + SAVE1 + SAVE2 + SAVE3+ SAVE4+ SAVE5+ SAVE6+ SAVE7);
32
    end if;
33
  end process SUM;
34
    
35
  summe_div_8 <= summe(summe'left downto 3);
36
  --------------------------------------------------------
37
  Fall : process (REGISTER_CLK)
38
  begin
39
  if falling_edge (REGISTER_CLK) then
40
    if summe_div_8 < ("100000000000") then -- 
41
      Flanke <= '0';
42
    elsif summe_div_8 > ("100000000000") then -- 
43
      Flanke <= '1';
44
    end if;
45
  end if;
46
  end process Fall;
47
  ----------------------------------------------------------
48
  Tasten :process (Flanke)
49
  begin 
50
    if Flanke = '1' then  
51
      REG_AUSGANG <="111111111111";
52
    elsif Flanke ='0' then
53
      REG_AUSGANG <="000000000000";
54
   end if;
55
  end process tasten;

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


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?

von Thomas R. (Firma: abaxor engineering) (abaxor)


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

von M. (Gast)


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!


1
Fall : process (REGISTER_CLK)
2
  begin
3
  if falling_edge (REGISTER_CLK) then
4
5
  if (((SAVE7 and not SAVE6 and not SAVE5 and not SAVE4 and not SAVE3 and not SAVE2 and not SAVE1  < "100110011001")) then
6
      C <= '1';
7
    else 
8
      C<='0';
9
    end if;
10
  end if;
11
  end process Fall;
12
  ----------------------------------------------------------
13
  Tasten :process (C)
14
  begin 
15
  if falling_edge (REGISTER_CLK) then  
16
    if C = '1' then  
17
      REG_AUSGANG <="111111111111"; -- 000000000000
18
    elsif C ='0' then
19
      REG_AUSGANG <="000000000000";
20
    end if;
21
  end if;
22
  end process tasten;


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

von Nephilim (Gast)


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

von M. (Gast)


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ß

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


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

von Iulius (Gast)


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.

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


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.

von Iulius (Gast)


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) :
1
if value < trigger_schwelle then
2
 shiftreg <= shiftreg(shiftreg'left-1 downto 0) & '0';
3
else
4
 shiftreg <= shiftreg(shiftreg'left-1 downto 0) & '1';
5
end if;
6
7
high<='0';
8
low <='0';
9
if shiftreg=(shiftreg'left downto 0 => '1') then
10
 high<='1';
11
end if;
12
if shiftreg=(shiftreg'left downto 0 => '0') then
13
 low <='1';
14
end if;

von J. S. (Gast)


Lesenswert?

Worin besteht denn da die Glättung?

von M. (Gast)


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?

1
entity EINGANGS_REGISTER is
2
    Port ( REGISTER_EINGANG  : in  STD_LOGIC_vector (11 downto 0);
3
           REGISTER_RESET    : in  STD_LOGIC;
4
           REGISTER_CLK     : in  STD_LOGIC;
5
           REG_AUSGANG       : out  STD_LOGIC_vector (11 downto 0));
6
end EINGANGS_REGISTER;
7
8
9
architecture Behavioral of EINGANGS_REGISTER is
10
11
Signal SAVE0,SAVE1,SAVE2,SAVE3,SAVE4,SAVE5,SAVE6,SAVE7 : STD_LOGIC_vector (11 downto 0));
12
--Signal sum : signed (11 downto 0);
13
--Signal sum_div_8 : std_logic_vector (8 downto 0);
14
begin
15
  
16
  Schieben :process (REGISTER_CLK)
17
  begin
18
    if falling_edge (REGISTER_CLK) then
19
      SAVE0 <= REGISTER_EINGANG;
20
      SAVE1 <= SAVE0;
21
      SAVE2 <= SAVE1;
22
      SAVE3 <= SAVE2;
23
      SAVE4 <= SAVE3;
24
      SAVE5 <= SAVE4;
25
      SAVE6 <= SAVE5;
26
      SAVE7 <= SAVE6;
27
    end if;
28
  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ß

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


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...

von Nephilim (Gast)


Lesenswert?

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

von M. (Gast)


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.


1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
USE ieee.std_logic_unsigned.all; 
4
use IEEE.NUMERIC_STD.ALL;
5
6
7
---- Uncomment the following library declaration if instantiating
8
---- any Xilinx primitives in this code.
9
--library UNISIM;
10
--use UNISIM.VComponents.all;
11
12
entity EINGANGS_REGISTER is
13
    Port ( REGISTER_EINGANG  : in  STD_LOGIC_vector (11 downto 0);
14
           REGISTER_RESET    : in  STD_LOGIC;
15
           REGISTER_CLK     : in  STD_LOGIC;
16
           REG_AUSGANG       : out  STD_LOGIC_vector (11 downto 0));
17
end EINGANGS_REGISTER;
18
19
20
architecture Behavioral of EINGANGS_REGISTER is
21
22
Signal SAVE0,SAVE1,SAVE2,SAVE3,SAVE4,SAVE5,SAVE6,SAVE7 : STD_LOGIC_vector (11 downto 0);
23
Signal S0,S1,S2,S3,S4,S5,S6,S7   : signed (11 downto 0);
24
Signal I6,I7          : integer;
25
Signal  summe : integer range 0 to 2**12-1;  
26
Signal  ergebnis : unsigned (11 downto 0);
27
28
begin
29
  
30
  Schieben :process (REGISTER_CLK)
31
  begin
32
    if falling_edge (REGISTER_CLK) then
33
      SAVE0 <= REGISTER_EINGANG;
34
      SAVE1 <= SAVE0;
35
      SAVE2 <= SAVE1;
36
      SAVE3 <= SAVE2;
37
      SAVE4 <= SAVE3;
38
      SAVE5 <= SAVE4;
39
      SAVE6 <= SAVE5;
40
      SAVE7 <= SAVE6;
41
    end if;
42
  end process Schieben ;
43
  
44
  Mittelwert: process (REGISTER_CLK)
45
  begin 
46
    S6 <=signed(SAVE6);
47
    S7 <=signed(SAVE7);
48
    I6 <=to_integer(S6);
49
    I7 <=to_integer(S7);
50
       if falling_edge (REGISTER_CLK) then
51
    summe <= (I6 + I7);  
52
       end if;
53
  ergebnis <= to_unsigned(summe/2,ergebnis'length);          
54
     end process Mittelwert;
55
  
56
  REG_AUSGANG <=std_logic_vector(ergebnis);
57
58
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ß

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


Lesenswert?

Die Sensitivliste des Prozesses ist unvollständig:
1
  Mittelwert: process (REGISTER_CLK)
2
  begin 
3
    S6 <=signed(SAVE6);                                --- SAVE6
4
    S7 <=signed(SAVE7);                                --- SAVE7
5
    I6 <=to_integer(S6);                               --- S6
6
    I7 <=to_integer(S7);                               --- S7
7
    if falling_edge (REGISTER_CLK) then
8
      summe <= (I6 + I7); 
9
    end if;
10
    ergebnis <= to_unsigned(summe/2,ergebnis'length);  --- summe         
11
  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:
1
  S6 <= signed(SAVE6);                               
2
  S7 <= signed(SAVE7);                               
3
  I6 <= to_integer(S6);                              
4
  I7 <= to_integer(S7);                              
5
6
  Mittelwert: process (REGISTER_CLK)
7
  begin 
8
    if falling_edge (REGISTER_CLK) then
9
      summe <= (I6 + I7); 
10
    end if;
11
  end process Mittelwert;
12
13
  ergebnis <= to_unsigned(summe/2,ergebnis'length);
Das könntest du auch abkürzen:
1
  Mittelwert: process (REGISTER_CLK)
2
  begin 
3
    if falling_edge (REGISTER_CLK) then
4
      summe <= (to_integer(signed(SAVE6)) + to_integer(signed(SAVE7))); 
5
    end if;
6
  end process Mittelwert;
7
8
  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?

von M. (Gast)


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...

1
ergebnis <= to_unsigned(summe/4,ergebnis'length downto 2);
2
3
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ß

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


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...

von M. (Gast)


Lesenswert?

Hallo,

hm... also hier erstmal der überarbeitete Code
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
USE ieee.std_logic_unsigned.all; 
4
use IEEE.NUMERIC_STD.ALL;
5
6
7
Entity EINGANGS_REGISTER is
8
    Port ( REGISTER_EINGANG  : in  STD_LOGIC_vector (11 downto 0);
9
           REGISTER_RESET    : in  STD_LOGIC;
10
           REGISTER_CLK     : in  STD_LOGIC;
11
           REG_AUSGANG       : out  STD_LOGIC_vector (11 downto 0));
12
end EINGANGS_REGISTER;
13
14
15
architecture Behavioral of EINGANGS_REGISTER is
16
17
Signal SAVE0,SAVE1,SAVE2 : STD_LOGIC_vector (11 downto 0);
18
Signal S0,S1,S2   : unsigned (11 downto 0);
19
Signal I0,I1,I2  : integer;
20
Signal  summe : integer range 0 to 2**12-1 ;  
21
Signal  ergebnis : unsigned (11 downto 0);
22
23
begin
24
  
25
  Schieben :process (REGISTER_CLK)
26
  begin
27
    if falling_edge (REGISTER_CLK) then
28
      SAVE0 <= REGISTER_EINGANG;
29
      SAVE1 <= SAVE0;
30
      SAVE2 <= SAVE1;
31
    end if;
32
  end process Schieben ;
33
    --------------------
34
    S0 <=unsigned(SAVE0);
35
    S1 <=unsigned(SAVE1);
36
    S2 <=unsigned(SAVE2);
37
    --------------------
38
    I0 <=to_integer(S0);
39
    I1 <=to_integer(S1);
40
    I2 <=to_integer(S2);
41
    --------------------
42
  Mittelwert: process (REGISTER_CLK)
43
  begin 
44
    
45
      if falling_edge (REGISTER_CLK) then
46
        summe <= ((I2+I1));  
47
      end if;
48
  end process Mittelwert;
49
  
50
  ergebnis <= to_unsigned(summe/2,ergebnis'length); -- teilen nur durch Zweierpotenzen!!
51
  REG_AUSGANG <=std_logic_vector(ergebnis);
52
53
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
1
ergebnis <= to_unsigned(summe/2,ergebnis'length);
2
..
3
ergebnis <= to_unsigned(summe,ergebnis'length);
und dafür oben die
1
((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...

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


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;

von M. (Gast)


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
1
entity EINGANGS_REGISTER is
2
    Port ( REGISTER_EINGANG  : in  STD_LOGIC_vector (11 downto 0);
3
           REGISTER_RESET    : in  STD_LOGIC;
4
           REGISTER_CLK     : in  STD_LOGIC;
5
           REG_AUSGANG       : out  STD_LOGIC_vector (11 downto 0));
6
end EINGANGS_REGISTER;
7
8
architecture Behavioral of EINGANGS_REGISTER is
9
10
Signal SAVE0           : STD_LOGIC_vector (11 downto 0);
11
Signal S0              : unsigned (11 downto 0);
12
Signal ergebnis         : unsigned (11 downto 0);
13
Signal I0            : integer;
14
Signal summe,summe_max    : integer range  0 to 2**15-1;  
15
Signal cnt              : integer range  0 to 7 :=0;
16
begin
17
  
18
  Schieben :process (REGISTER_CLK)
19
  begin
20
    if falling_edge (REGISTER_CLK) then
21
      SAVE0 <= REGISTER_EINGANG;
22
    end if;
23
  end process Schieben ;
24
    --------------------
25
    S0 <=unsigned(SAVE0);
26
    --------------------
27
    I0 <=to_integer(S0);
28
    --------------------
29
    Mittelwert: process (REGISTER_CLK)
30
    begin 
31
      if falling_edge (REGISTER_CLK) then
32
      if cnt = 3 then
33
        cnt      <=0;
34
        summe_max <= summe;
35
        summe    <=0;
36
      else
37
        cnt   <= cnt+1;
38
        summe <= summe + I0;  
39
      end if;
40
    end if;
41
     end process Mittelwert;
42
  ergebnis <= to_unsigned(summe_max/4,ergebnis'length); -- teilen nur durch Zweierpotenzen!!
43
  
44
  REG_AUSGANG<=std_logic_vector(ergebnis);
45
46
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
1
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...

von Marcus W. (blizzi)


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?
1
process (CLK)
2
begin
3
  if falling_edge(CLK) then
4
5
    fallende_flanke <= '0';
6
7
    if REG_IN > schwelle_oben then
8
      zustand <= '1';
9
    end if;
10
    if REG_IN < schwelle_unten then
11
      zustand <= '0';
12
      if zustand = '1' then
13
        fallende_flanke <= '1';
14
      end if;
15
    end if;
16
17
  end if;
18
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.

von Thomas R. (Firma: abaxor engineering) (abaxor)


Lesenswert?

M. schrieb:

Durch
   summe    <=0;
in
1
> if cnt = 3 then
2
>         cnt      <=0;
3
>         summe_max <= summe;
4
>         summe    <=0;
5
>       else
6
>         cnt   <= cnt+1;
7
>         summe <= summe + I0;  
8
>       end if;

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

Tom

von M. (Gast)


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ß

von M. (Gast)


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ß

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


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).

von M. (Gast)


Lesenswert?

Hi,


so ungefähr hab ich mir das gedacht:
1
  Trigger: process (REGISTER_CLK)
2
    begin
3
      if falling_edge(REGISTER_CLK) then
4
        if cnt = 5 then
5
          sprung <= '0';
6
          if (S0 > "101001100101")  then  -- OBERE SCHWELLE HIER 65% VOM AD BEREICH
7
          zustand <= '1';
8
          end if;
9
          if (S0 < "011001100110")  then  -- UNTERE SCHWELLE HIER 40%  VOM AD BEREICH  
10
          zustand <= '0';
11
            if zustand = '1' then
12
              sprung <= '1';
13
            end if;
14
          end if;
15
        elsif sprung = '1' then
16
          cnt<=0;
17
        else
18
          cnt<=cnt+1;
19
        end if;
20
      end if;  
21
  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.

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


Lesenswert?

Machs doch einfacher:
1
  Trigger: process (REGISTER_CLK)
2
    begin
3
      if falling_edge(REGISTER_CLK) then
4
        if cnt<5 then   -- den Zähler einfach mal laufen lassen
5
          cnt <= cnt+1;
6
        end if;
7
        if cnt = 5 then
8
          if (S0 > "101001100101")  then  -- OBERE SCHWELLE HIER 65% VOM AD BEREICH
9
            zustand <= '1';
10
          end if;
11
          if (S0 < "011001100110")  then  -- UNTERE SCHWELLE HIER 40%  VOM AD BEREICH  
12
            if zustand = '1' then -- fallende Analogflanke
13
              cnt <= 0;           -- Zähler zurücksetzen
14
            end if;
15
            zustand <= '0';
16
          end if;
17
        end if;
18
      end if;  
19
  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).

von M. (Gast)


Lesenswert?

Hm...

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

von M. (Gast)


Lesenswert?

Bzw.
1
    Trigger: process (REGISTER_CLK)
2
    begin
3
      if falling_edge(REGISTER_CLK) then
4
        if cnt<840 then   
5
          cnt <= cnt+1;
6
        end if;
7
        if cnt = 840 then
8
          if (S0 > "101001100101")  then  -- OBERE SCHWELLE HIER 65% VOM AD BEREICH
9
            zustand <= '1';
10
          end if;
11
          if (S0 < "011001100110")  then  -- UNTERE SCHWELLE HIER 40%  VOM AD BEREICH  
12
        if zustand = '1' then       -- FALLENDE ANALOFFLANKE
13
          cnt <= 0;                 -- ZÄHLER ZURÜCKSETZEN
14
        end if;
15
           zustand <= '0';
16
          end if;
17
        end if;
18
      end if;  
19
  end process Trigger;
20
 
21
  Aus:process (REGISTER_CLK) 
22
  begin
23
    if falling_edge (REGISTER_CLK) then
24
      if cnt = 0 then
25
        REG_AUSGANG <="000000000000";
26
      elsif cnt  > 0 then
27
        REG_AUSGANG <="111111111111";
28
      end if;
29
    end if;
30
  end process AUS;

von M. (Gast)


Lesenswert?

Hallo,

ok hier mal der engültige code der auch soweit funktioniert
1
    Trigger: process (REGISTER_CLK)
2
    begin
3
      if falling_edge(REGISTER_CLK) then
4
        if cnt < 8399 then   
5
          cnt  <= cnt+1;
6
        end if;
7
        if cnt = 8399 then
8
          if (S0 > "101001100101")  then  -- OBERE SCHWELLE HIER 65% VOM AD BEREICH
9
            zustand <= '1';
10
          end if;
11
          if (S0 < "011001100110")  then  -- UNTERE SCHWELLE HIER 40%  VOM AD BEREICH  
12
        if zustand = '1' then       -- FALLENDE ANALOFFLANKE
13
          cnt <= 0;                 
14
        end if;
15
           zustand <= '0';
16
          end if;
17
        end if;
18
      end if;  
19
  end process Trigger;
20
 
21
  Aus:process (REGISTER_CLK) 
22
  begin
23
    if falling_edge (REGISTER_CLK) then
24
      if cnt > 0 and cnt < 100 then
25
        REG_AUSGANG <="000000000000";
26
      else
27
        REG_AUSGANG <="111111111111";
28
      end if;
29
    end if;
30
  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? :(

von Marcus W. (Gast)


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.

von berndl (Gast)


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

von M. (Gast)


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ß

von Marcus W. (Gast)


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?

von berndl (Gast)


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...

von Marcus W. (Gast)


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 :)

von berndl (Gast)


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...

von Thomas R. (Firma: abaxor engineering) (abaxor)


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

von M. (Gast)


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
1
  Aus:process (REGISTER_CLK) 
2
  begin
3
    if falling_edge (REGISTER_CLK) then
4
      if cnt > 0  and cnt < 1023 then
5
        REG_AUSGANG <=Efunk;
6
      else
7
        REG_AUSGANG <="111111111111";
8
      end if;
9
    end if;
10
  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

von M. (Gast)


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ß

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


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?
????

von M. (Gast)


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ß

von Basti (Gast)


Lesenswert?

Hallo,


eine Frage hätte ich zur Flankenerkennung und zwar :
1
    if REG_IN > schwelle_oben then
2
      zustand <= '1';
3
    end if;
4
    if REG_IN < schwelle_unten then
5
      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?

von Marcus W. (Gast)


Lesenswert?

Hallo Basti,

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

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

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.