Forum: FPGA, VHDL & Co. Spannungsspitzen in VHDL eliminieren


von Rainer (Gast)


Lesenswert?

Hallo, ich habe folgendes Problem:

Es ist ein Datensignal(3,125MHz ) von ASCII-Zeichen kommt von einem 
FPGA-Board per LVDS über eine Leitung auf ein 2.Board. Es wird per EMV 
einstrahlung ein "Burst", d.h. Sapannungsspitzen draufgegeben um Tests 
durchzuführen. Es sind als am empfangenen Signal auf dem Digitalen Frame 
überschinger, bzw. Spannungsspitzen vorhanden.

Wie kann ich diese Störspitzen, die den Bits überlagert sind, in VHDL 
elimineren, damit ich wieder ein möglichst reines Signal bekomme? Gibt 
es dafür eine Logik???

von Kest (Gast)


Lesenswert?

? Verstehe nicht ganz, was das ganze mit VHDL zu tun hat.

Erstens, LVDS ist robuster als man denkt.
Zweitens, gibt es nicht um sonst Protokolle, die z.B. mit Frames/CRC32 
arbeiten. Du muss Deinen Datenstrom absichern und falls es zum Fehler 
kommt, noch mal schicken oder so.

Grüße,
Kest

von Nephilim (Gast)


Lesenswert?

man könnte das signal vielleicht auch überabtasten und dann digital 
filtern um entweilige spikes zu unterdrücken.

von Rainer (Gast)


Lesenswert?

mir geht es nicht um protokolle hin, oder her.

Ganz simpel:

Ich erhalte meinetwegen irgendein beliebiges Signal, das gelegentlich in 
der Bitmitte z.B. Störspitzen hat. Diese möchte ich einfach eliminieren, 
um dann mit einem Saueberen Signal auf dem FPGA weiterzuarbeiten. Das 
ganz in VHDL implementiert.

von Erik W. (exor)


Lesenswert?

einfach nen spannungsbereich festlegen, der für dich als logische 1 bzw. 
0 gilt alles andere wird ignoriert.

von Rainer (Gast)


Lesenswert?

wie lege ich einen Spannungsbereich fest?
Es dürfen einfach keine Sörungen innerhalb eines Bits, auch wenn sie 
kurzzeitig auf 0 gehen, das Bit verfälschen, d.h. wenn einmal eine 1 
vorhanden ist, soll sie mindestens eine ganze Bitdauer konst. auf 1 
bleiben. bei 0 ebenfalls

von Nephilim (Gast)


Lesenswert?

das was du suchst klingt echt nach der überabtastung und filterung die 
ich schon erwähnt hatte.

das prinzip ist dabei ja so, dass du dein digitales signal mehrfach 
abtastest, also mit einer mehrfach höheren takt als die frequenz des 
nutzsignals hat und dann über eine gewisse zeit den mittelwert bildest. 
liegt dieser über einer werteschweller ist es logisch '1', liegt er 
darunter wird es eine logische '0'. dadurch bekommst du zwar ein 
signaldelay, aber filterst etweilige spitzen innerhlab des signals raus.

von Rainer (Gast)


Lesenswert?

wie würde s konkret aussehen? Kann es mir funktioal gut vorstellen, aber 
implementiert nicht so ganz...

von Erik W. (exor)


Lesenswert?

wie holst du denn dein signal von der leitung? wird das per adc 
umgewandelt? hängt da ein transceiver dazwischen, der da übernimmt? wie 
sieht das umfeld aus?

von Rainer (Gast)


Lesenswert?

ist ein lvds signal, das vom FPGA wiedeer seriell gewandelt wird.

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


Lesenswert?

Lass den Bitstrom durch ein Schieberegister, und nur wenn das ganze 
Register z.B. "000000" oder "111111" ist, dann schaltest du deinen 
internen Pegel um. Siehe dazu in 
http://www.lothar-miller.de/s9y/archives/18-Flinke-Flankenerkennung.html 
die letzten paar Zeilen.

von Thorsten S. (thosch)


Lesenswert?

Lothar Miller schrieb:
> Lass den Bitstrom durch ein Schieberegister, und nur wenn das ganze
> Register z.B. "000000" oder "111111" ist, dann schaltest du deinen
> internen Pegel um.
Das funktioniert aber nur gut für relativ langsame Signale (wie zur 
Entprellung eines Kontaktes) oder bei starker Überabtastung und selten 
auftretenden Störsignalen.

Das Problem dabei ist, daß regelmäßig (während eines Bursts) 
eingestreute kurze Störpulse das Tastverhältnis des Datensignals nach 
dem Filter verschieben bzw. sogar das Umschalten auf den richtigen Pegel 
verhindern können.
Wenn z.B. alle 6 (über-)Abtastpunkte ein falsches Bit käme, würde der 
Ausgang Deiner Filterschaltung nie umschalten.

Ich sehe zwei praktikable Lösungsmöglichkeiten:
Wenn die Störimpulse stets nur 1 Abtastpunkt lang sind und mindestens 2 
Abtastpunkte dazwischen korrekt sind, würde ein Medianfilter mit einer 
3-Punkt Apertur wirken.

Deine Schieberegister-Filterschaltung läßt sich erheblich verbessern, 
wenn man sie um einen Prioritätsdecoder erweitert, d.h. man decodiert 
die Bits aus dem Schieberegister so aus, daß z.B. mindestens 4 von den 6 
Bits auf 1 stehen müssen, um den Ausgang auf 1 umzuschalten und ebenso 
mindestens 4 Bits 0 sein müssen um den Ausgang zurück auf 0 zu schalten.

Damit wird die Störsicherheit erheblich erhöht, da jeweils bis zu zwei 
falsche Bits an beliebiger Position im Schieberegister die Funktion 
nicht beeinträchtigen können.

Gruß,
Thorsten

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


Lesenswert?

> Wenn die Störimpulse stets nur 1 Abtastpunkt lang sind und mindestens 2
> Abtastpunkte dazwischen korrekt sind
Dann würde ich dem Signal keinen Zoll über den Weg trauen, denn wer sagt 
denn, das nicht mal 2 Störimpulse nacheinander kommen?

> Deine Schieberegister-Filterschaltung läßt sich erheblich verbessern,
> wenn man sie um einen Prioritätsdecoder erweitert
Richtig, das könnte man. So arbeiten ja auch die Empfänger in der 
seriellen Schnitte von uC: 2 Bit von 3 bestimmen den endgültigen Wert.

> Das funktioniert aber nur gut für relativ langsame Signale (wie zur
> Entprellung eines Kontaktes) oder bei starker Überabtastung und selten
> auftretenden Störsignalen.
Die ursprüngliche Aufgabe:
>>> Es ist ein Datensignal(3,125MHz ) von ASCII-Zeichen kommt von einem
>>> FPGA-Board per LVDS über eine Leitung auf ein 2.Board.
Wenn ich mit 60 MHz überabtaste, ist mein 6-Bit-Schieberegister ganz gut 
im Rennen. Am besten wäre, die Daten so zu codieren, dass korrupte Daten 
erkannt werden und die Übertragung wiederholt werden kann.

von Rainer (Gast)


Lesenswert?

> wenn man sie um einen Prioritätsdecoder erweitert, d.h. man decodiert
> die Bits aus dem Schieberegister so aus, daß z.B. mindestens 4 von den 6
> Bits auf 1 stehen müssen, um den Ausgang auf 1 umzuschalten und ebenso
> mindestens 4 Bits 0 sein müssen um den Ausgang zurück auf 0 zu schalten.

Wie lautet die High oder Low- Abfrage von 4 von 6 bits bei solch einem 
std_logic_vector?

sr <= sr(5 downto 0) & Data_in;

von Iulius (Gast)


Lesenswert?

das einfachste wäre wohl das über eine For-Schleife zu beschreiben (kann 
man auch in eine function packen) und hoffen das der Synthesizer da was 
sinvolles draus macht.

Oder man beschreibt die paar Fälle explizit...


auch möglich : man addiert schon auf während die einzelnen Bits 
reinkommen in 2 verschiedene Zähler und prüft am Ende nur ob einer der 
Zähler > 3 ist.



Ist halt nur fraglich ob das ausreicht...solange Fehler nur 
kurzzeitig(1-2 Takte) auftreten mag das ok sein, aber wenn nicht versagt 
das ja völlig und du wirst es nie rausfinden.

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


Lesenswert?

> Wie lautet die High oder Low- Abfrage von 4 von 6 bits bei solch einem
> std_logic_vector?
Etwa so:
1
  signal mehrheit : std_logic;
2
:
3
  process (clk) 
4
    variable einsen : integer;
5
  begin
6
    if rising_edge(clk) then
7
      sr <= sr(5 downto 0) & Data_in;
8
      einsen := 0;
9
      for i in 0 to 5 loop
10
        if sr(i) ='1' then einsen := einsen+1;
11
      end loop;
12
      if einsen >= 4 then mehrheit <= '1';
13
      if einsen <  2 then mehrheit <= '0';
14
    end if;
15
  end process;

> Oder man beschreibt die paar Fälle explizit...
Naja, das sind doch schon einige Fälle:
Für eine gültige 0:
000000
000001
000010
000100
001000
010000
100000
000011
000101
001001
010001
100001
000110
001010
...
110000

und dann das Ganze noch für die 1, das wäre mir zu viel Tipperei ;-)

von Erik W. (exor)


Lesenswert?

da kann man doch bestimmt was mit logischen gleichungen machen...stell 
doch einfach ma ne wertetabelle auf und vereinfache die 1en und 0en zu 
ner konjunktiven normalform...da sparst du dir dann auf jedenfall die 
for-schleife

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


Lesenswert?

>> da sparst du dir dann auf jedenfall die for-schleife
Die Synthese macht aus der for-Schleife die Kombinatorik.
Ich lasse sowas immer vom Synthesizer machen, das kann er und dafür ist 
er da. Nur mal angenommen, ich möchte da mal 9 Bits draus machen. Dann 
müsstest du manuell wieder alles durchkneten, ich ändere die 
Grenzwerte und bin fertig.

Nimm mal diese Beschreibung:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Mehrheit is
6
    Port ( din : in  std_logic_vector (6 downto 0);
7
           dout : out  STD_LOGIC);
8
end Mehrheit;
9
10
architecture Behavioral of Mehrheit is
11
begin
12
  process (din)
13
    variable einsen : integer;
14
  begin
15
    einsen := 0;
16
    for i in din'range loop
17
      if din(i) ='1' then einsen := einsen+1; end if;
18
    end loop;
19
    if einsen >= 4 then 
20
       dout <= '1';
21
    else    
22
       dout <= '0'; 
23
    end if;
24
  end process;
25
end Behavioral;

Ich glaube kaum, dass du das von Hand wesentlich besser hinbekommst:
1
# Adders/Subtractors                                   : 6
2
 1-bit adder carry out                                 : 1
3
 2-bit adder                                           : 1
4
 2-bit adder carry out                                 : 1
5
 3-bit adder                                           : 3
6
# Comparators                                          : 1
7
 3-bit comparator greatequal                           : 1
und daraus insgesamt (Spartan3): Number of Slices 3

von Erik W. (exor)


Lesenswert?

also wenn ich das ma für 3 abtastwerte durchspiele, dann sieht das so 
aus

x2  x1  x0    y
 0   0   0    0
 0   0   1    0
 0   1   0    0
 0   1   1    1
 1   0   0    0
 1   0   1    1
 1   1   0    1
 1   1   1    1

y = x2 | x1x0

und dann sieht der code etwa so aus :
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Mehrheit is
6
    Port ( din : in  std_logic_vector (2 downto 0);
7
           dout : out  STD_LOGIC);
8
end Mehrheit;
9
10
architecture Behavioral of Mehrheit is
11
begin
12
  process (din)
13
  begin
14
15
     dout <= din(2) OR (din(1) AND din(0));
16
17
  end process;
18
end Behavioral;

hab jetz keinen synthesizer da, aber ich glaub das läuft auf einen slice 
(also eine LUT) hinaus.
für größere vektoren is das natürlich etwas handarbeit.

von Iulius (Gast)


Angehängte Dateien:

Lesenswert?

Mich würde bei der For schleife stören das damit eine 3-level logik 
aufgebaut wird, siehe png.
Insbesondere aber das es miserabel skaliert. Bei einem 10 Bit 
schieberegister komme ich schon auf 17 Logicelements und 6(!) Level 
Logik.

Da ist eben das Problem, das der Synthesizer wirklich einen Addierer 
daraus baut und nicht etwa nur Komperatoren als würde man es händisch 
hinschreiben.
(quartus übrigens auch, keine Macke von ISE)


mit der Zählervariante braucht man etwa gleich viel Ressourcen (da man 
auf das Schieberegister verzichten kann), 2 Level 4LUT Logik und es 
skaliert deutlich besser.

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity Mehrheit is
6
    Port ( clk : in std_logic;
7
           din : in  std_logic_vector (6 downto 0);
8
           dout : out  STD_LOGIC);
9
end Mehrheit;
10
11
architecture Behavioral of Mehrheit is
12
  
13
  signal ones : unsigned(2 downto 0) := (others => '0');
14
  signal zeros : unsigned(2 downto 0) := (others => '0');
15
  signal dout_buffer : std_logic;
16
17
begin
18
  
19
  process (din)
20
  begin
21
  if rising_edge(clk) then
22
    if din(0)='1' then
23
      ones <= ones +1;
24
    else
25
      zeros <= zeros +1;
26
    end if;
27
    
28
    if ones+zeros=7 then
29
      if ones>3 then
30
        dout_buffer <= '1';
31
      else
32
        dout_buffer <= '0';
33
      end if;
34
      ones<=(others => '0');
35
      zeros<=(others => '0');
36
    end if;
37
    
38
    end if;
39
  end process;
40
  
41
  dout <= dout_buffer;
42
  
43
end Behavioral;


Naja, letztendlich ist es bei 7 Samples wohl noch egal was man nimmt.

von Erik W. (exor)


Lesenswert?

sorry oben is noch nen fehler drin muss natürlich heißen:

y = x2/x1x0 | x2x1/x0 | x1x0

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


Lesenswert?

@ Erik
>> aber ich glaub das läuft auf einen slice (also eine LUT) hinaus.
Ich habe mein Beispiel mit der Schleife mal kurz auf 3 Bit umgestellt 
(Zeitaufwand ca. 30 Sekunden) und erhalte einen Ressourcenbedarf von 1 
LUT.

Genausoviel kommt heraus, wenn ich deinen Code synthetisiere ;-)

@ Iulius
Durch das Rücksetzen der Zähler stellst du dich zeitweise "blind". Der 
Ansatz mit dem "Mitzählen" gefällt mir ganz gut, ich würde das aber 
etwas vereinfachen:
1
entity Mehrheit1 is
2
    Port ( din  : in   std_logic;
3
           clk  : in   std_logic;
4
           dout : out  std_logic);
5
end Mehrheit1;
6
7
architecture Behavioral of Mehrheit1 is
8
  signal ones : integer range 0 to 7 := 0;
9
begin
10
  process (clk)
11
  begin
12
    if rising_edge(clk) then
13
      if din='1' then
14
        if(ones<7) then ones <= ones+1;  end if;
15
      else
16
        if(ones>0) then ones <= ones-1;  end if;
17
      end if;
18
      if    ones>3 then dout <= '1';
19
      else              dout <= '0';
20
      end if;
21
    end if;
22
  end process;
23
end Behavioral;
Verbraucht 5 LUTs und läuft mit 300 MHz  ;-)

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


Angehängte Dateien:

Lesenswert?

Besser wäre es übrigens, zu sagen
"Eine 1 am Ausgang ist es erst, wenn mindestens 5 von 7 Werten '1' sind.
Und eine 0 kommt am Ausgang, wenn mindestens 5 von 7 Werten '0' sind".

Das gibt ein Schmitttrigger-Verhalten, und das Signal kann nicht 
"zappeln", wenn mal so die Mitte erreicht ist:
1
architecture Behavioral of Mehrheit1 is
2
  signal ones : integer range 0 to 7 := 0;
3
  constant schmitttrigger : boolean := true;
4
begin
5
  process (clk)
6
  begin
7
    if rising_edge(clk) then
8
      if din='1' then
9
        if(ones<7) then ones <= ones+1;  end if;
10
      else
11
        if(ones>0) then ones <= ones-1;  end if;
12
      end if;
13
      if (schmitttrigger=true) then
14
-- obere und untere Schwelle, Schitt-Trigger-Verhalten
15
         if    ones>4 then dout <= '1';
16
         elsif ones<3 then dout <= '0';
17
         end if;
18
      else
19
-- Nur 1 Schwelle
20
         if    ones>3 then dout <= '1';
21
         else              dout <= '0';
22
         end if;
23
      end if;
24
    end if;
25
  end process;
26
end Behavioral;

von Iulius (Gast)


Lesenswert?

Sehr schön, bin gar nicht drauf gekommen das man das soweit noch 
vereinfachen kann.

Die Lösung gefällt mir so auch deutlich besser. Stabiler, schneller, 
kleiner und skaliert hervorragend.


Immer wieder lustig wie man sich doch mit einer erst so trivial 
erscheinenden Aufgabe beschäftigen kann und sich immer neue (und auch 
bessere) Lösungen ergeben.

Und dabei geht es ja nichtmal um Kleinigkeiten, im Vergleich zur ersten 
Version mit Schieberegister sind das ja gerade mal noch <40% 
Ressourcenverbrauch.

von Matthias G. (mgottke)


Lesenswert?

Störungen mit Burst: Da bin ich mit den Filtern sehr skeptisch, ob die 
an so einer Stelle wirken. Dazu muss man aber erst einmal verstehen was 
Bursts sind, wie diese wirken um dann die Folgen abschätzen zu können.

Bursts kommen auf Datenleitungen lediglich durch kapazitive 
Einkopplungen parallel liegender Leitungen zu Stande. In der Regel sind 
das induktive Verbraucher die geschaltet werden. Z.B. Wechselrichter. Um 
das im Labor nachzubilden werden kapazitive Koppelzangen verwendet. 
Typisch ist hier eine Koppelkapazität von 100pF. Die Störungen die 
dadurch auf einer Datenleitung zustande kommt ist somit in 1. Linie eine 
Gleichtaktstörung. Daher treten die Störungen sowohl auf den 
Datenleitungen, hier dem LVDS-Signal, so wie eventuell mitgeführten 
Masse, bzw. Spannungsführenden Leitungen im Gleichtakt auf.

Wenn es nun zu Störungen durch Bursts kommt, dann liegt das nicht daran, 
dass die Spannungsdifferenzen des LVDS-Signals fehlerhafte Zustände 
einnimmt, sondern in der Regel zwischen Sender und Empfänger keine 
galvanische Trennung vorhanden ist. So fließen während eines Störpeak 
auf den Versorgungsleitungen (meist auf GND) Ausgleichsströme. Die Folge 
ist, dass das Potential am Empfänger in einen unerlaubten Bereich 
abdriftet. Vermutlich über die Substratdioden geerdet, bzw. bei 
Verwendung von Transildioden über diese, die Störungen abgeleitet 
werden.

Was in so einem Fall dann der Receiver tut und wie lange da die 
Erholungszeiten sind ist meist undefiniert.

Es sollte also als 1. mal die Übertragungsstrecke IO gebracht werden. 
Galvanische Trennung ist da das Zauberwort Nr. 1. Dann können nämlich 
keine Ausgleichsströme mehr fließen und die Ursache der Störung ist 
beseitigt.

Als zweites kann dann noch ein digitaler Filter für eine zusätzliche 
Stabilität sorgen.

Im übrigen Störungen durch Burst sind Störungen die in einer engen Folge 
ununterbrochen auftreten können. So ein Frequenzumrichter stört so lange 
der angeschlossene Motor läuft. Von daher sollte man sein Hardwaredesign 
tunlichst so auslegen, dass es unter den geforderten Einsatzbedingungen 
im Normalfall ohne Digitalfilter an so einer Stelle stabil läuft.

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


Lesenswert?

> Im übrigen Störungen durch Burst sind Störungen die in einer engen Folge
> ununterbrochen auftreten können.
Meine Worte im Beitrag "Re: Spannungsspitzen in VHDL eliminieren"
Aber ich habe das jetzt mal als kleine Spielerei angesehen...
Und es ist doch schön, was man dabei so herausfindet  ;-)

von Martin L. (Gast)


Lesenswert?

Hallo,

das ist so ne Frickellösung, dass einem ganz anders wird. Wenn es 
wirklich eine Verbindung auf einer PCB ist, dann tunke Deinen Layouter 
in den Burggraben und lass jemanden der von EMV schon mal was gehört hat 
das Layout neu machen. Wie man aber ein LDVS so schlecht verlegen kann, 
dass es genug Leistung einfängt ist mir ein Rätsel. Vielleicht liegt das 
Problem aber auch an fehlenden oder ungeeigneten Abblockkondensatoren 
bzw. fehlender GND-Plane. (Siehe Groundbounce und kurzzeitigem 
Spannungseinbruch der Versorgungsspannung)

Je nach Länge der Leitung kann es aber auch eine Reflektion auf der 
Leitung sein. Dann helfen Terminierungswiderstände (bei manchen Chips 
kann man sowas auf dem Chip zuschalten) und/oder auch weniger 
Treiberleistung am Sender. Bei einem so langsamen Signal sollte man das 
als erstes ausprobieren.

Und wenn die Verbindung über einen Kanal läuft der nicht beeinflussbar 
ist dann sollte man ein Protokoll mit Fehlerschutz bzw. 
Fehlervorwärtskorrektur verwenden.

Viele Grüße,
 Martin L.

von Jochen (Gast)


Lesenswert?

wird der oben angegebene Process icht getaktet???

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Mehrheit is
    Port ( din : in  std_logic_vector (6 downto 0);
           dout : out  STD_LOGIC);
end Mehrheit;

architecture Behavioral of Mehrheit is
begin
  process (din)
    variable einsen : integer;
  begin
    einsen := 0;
    for i in din'range loop
      if din(i) ='1' then einsen := einsen+1; end if;
    end loop;
    if einsen >= 4 then
       dout <= '1';
    else
       dout <= '0';
    end if;
  end process;
end Behavioral;

von Iulius (Gast)


Lesenswert?

Nein, wozu auch ?

Das ist nur Kombinatorik(mit recht langer Durchlaufzeit).
Die Auswertung kann danach sofort mit DOUT vorgenommen werden.

Empfehlenswert ist aber eher die letzte Variante von Lothar.

von Jochen (Gast)


Lesenswert?

Hallo,
ich möchte in folegndem Code von Lothar gerne eine Änderung durchführen 
und zwar, dass das Ergebnis, der Anzahl der "1" in dem Vektor, erst zum 
Schluss oder am Ende ausgegeben werden.
D.h ich taste z.B. in meinem Fall ein Bit das 320ns lang ist, mit 50Mhz 
ab so es passen in dieses Bit genau 16 Takte vom 50Mhz Takt mit jeweils 
20ns. Am Ende des des abgetasteten Bits will ich dann sagen, so, hier 
gab es insgesammt  z.B. 11pos abgetastete Bits, als war das eben eine 
"1", danach wird das selbe mit dem nächsten Bit gemacht, während das 
vorhergehende dann auf dem Wert bleibt.

Somit habe ich dann eine Verschiebung des Eingangs zum Ausgangssignla 
vom 320 ns, aber das spielt bei mir keine Rolle.

Wie könnte ich das ändern? i kann ich ja nicht nach 6 abfragen, oder? 
Oder welche Möglichkit gäbe es, so etwas zu machen?



library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity Mehrheit is
    Port ( din : in  std_logic_vector (6 downto 0);
           dout : out  STD_LOGIC);
end Mehrheit;

architecture Behavioral of Mehrheit is
begin
  process (din)
    variable einsen : integer;
  begin
    einsen := 0;
    for i in din'range loop
      if din(i) ='1' then einsen := einsen+1; end if;
    end loop;
    if einsen >= 4 then
       dout <= '1';
    else
       dout <= '0';
    end if;
  end process;
end Behavioral;

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


Lesenswert?

> Empfehlenswert ist aber eher die letzte Variante von Lothar.
ACK. Die ist am schönsten ;-)

@  Jochen
Vergiss die Variante mit der for-Schleife.
Du meinst nur dass du sie verstehst. Es wird dabei nicht zu 
irgendeinem Zeitpunkt etwas berechnet, sondern immer, andauerd, 
jederzeit, parallel.

>  Am Ende des des abgetasteten Bits will ich dann sagen,
Wie erkenne ich, wo das Bit anfängt und aufhört? Einen Flankenwechsel im 
Datenstrom kann ich nicht hernehmen, den da sind ja Störungen drauf. Ein 
paralleles Sync-Signal kann ich nicht verwenden, denn das könnte ja auch 
gestört sein...  :-o

von Jochen (Gast)


Lesenswert?

die Störungen werden erst zugeschaltet, d.h. am Anfang könnte ich schon 
einen Zähler starten mit einer exakten Flanke.

Meine Idee war diese:

Eine steigende Flanke erkennen, also Zählerbeginn von 1-16. der 
Zählerstand von 16 sagt, dann, dass hier ein Bit zu ende sein könnte, 
wenn vorher(in den letzten 16 Takten) überwiegend Nullen vorhanden warn.

Ich möchte das auf jeden Fall mal ausprobieren, nur fehlt mir der Ansatz 
zum Imlementieren wie ich die High/Low bits zähle und gleichzeitig bei 
Zählschritt 16 abfrage wie der Stand war und denn dann ausgebe.

von Iulius (Gast)


Lesenswert?

Meine Methode hatte das praktisch mit eingebaut.

Allerdings bezweifle ich das du damit die Synchonität lange behälst... 
da brauchts schon irgentwas im Datenstrom auf das du synchronisieren 
kannst.

von Jochen (Gast)


Lesenswert?

> Meine Methode hatte das praktisch mit eingebaut.

welche von den vielen Methoden meinst du jetzt?
Erst mal den ersten schritt, synchronisation später!

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


Lesenswert?

Jochen schrieb:
> am Anfang könnte ich schon einen Zähler starten mit einer exakten Flanke.
Allein die Hoffnung trägt uns weiter...?
Das hilft dir nicht weit, denn dein Takt ist asynchron zum Sendetakt. 
Es wird nicht lange dauern, bis du außer Tritt bist. Und wenn dann eine 
gestörte Flanke kommt, setzt du darauf auf...

> Erst mal den ersten schritt, synchronisation später!
Richtig: du mußt erst mal versuchen, ein brauchbares Signal zu erzeugen. 
Das ginge m.E. am ehesten damit: 
Beitrag "Re: Spannungsspitzen in VHDL eliminieren". Erst danach 
kannst du eine Flankenauswertung und daraus eine Synchronisation machen.

von Jochen (Gast)


Lesenswert?

> Beitrag "Spannungsspitzen in VHDL eliminieren". Erst danach
> kannst du eine Flankenauswertung und daraus eine Synchronisation machen.

Das Signal ist Sauber, jetzt liegt es nur noch an der Synchronisation. 
Hätte jemand eine Idee wie man das Sysnchronisieren kann?

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


Lesenswert?

> Hätte jemand eine Idee wie man das Sysnchronisieren kann?
So ähnlich wie ich beim RC5-Decoder: 
http://www.lothar-miller.de/s9y/archives/63-RC-5-Empfaenger.html

von Jochen (Gast)


Lesenswert?

Was genau muss in unserem Fall synchronisiert werden? Der Bitanfang mit 
dem Abtasttakt???

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


Lesenswert?

> Der Bitanfang mit dem Abtasttakt???
Dein Ziel ist, richtige Daten aus einem seriellen Datenstrom einzulesen.
Deshalb solltest du in der Bitmitte abtasten (gern auch mehrfach).
Um zu wissen, wo die Bitmitte ist, mußt du wissen, wo der Bitanfang und 
das Bitende ist.

Das ist bei manchestercodierten (oder ähnlichen) Signalen einfach, weil 
bei jedem bit ein Pegelwechsel erfolgt. Jedes bitt bringt praktisch 
seinen Anfang selber mit. Dadurch können große Baudratentoleranzen 
ausgeglichen werden. Wenn du z.B. "nur" eine RS232 Übertragung hast, 
dann kannst du nur auf das Startbit synchronisieren und mußt dann darauf 
vertrauen, dass der Unterschied zwischen Sende- und Empfangsfrequenz 
kleiner als 3% ist. CAN (und andere) macht einen Mittelweg und überträgt 
nach längerer Zeit ohne Pegelwechsel ein Stuffbit, damit der Empfänger 
wieder aufsynchronisieren kann.

von Jochen (Gast)


Lesenswert?

ich habe bemerkt, dass wenn ich selbst ein ungestörtes Signal nehme und 
es durch die oben erwähnte Elimination-der-Spannungsspitzen-Schaltung 
laufen lasse, es hinten nach einer gewissen Zeit zyklisch ein 
verfälschtes Ausgangssignal bekomme. Da dürfte es doch keine Probleme 
geben, oder? Es scheint als läuft es mit der Zeit irgendwie weg und 
fängt sich dann wieder, und das ohne störung.

Kann es sen, dass ich dort schon die Sync-probleme habe?

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


Lesenswert?

> Kann es sen, dass ich dort schon die Sync-probleme habe?
Ja. So ist das.

von Jochen (Gast)


Lesenswert?

Aus Deinem implementierten RC5-Empfänger verstehe ich nicht wie Du auf 
die Bitmitte von 1778 kommst?

Mein Bit ist 320ns lang, und verwende 50MHz boardtakt.

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


Lesenswert?

1
constant bittime : integer := 1778;     -- us
Die Bitmitte ist gleich der Bitzeit (bei RC5 = 1,777ms), wenn ich das 
erste Bit in der Mitte erwische.

von Jochen (Gast)


Lesenswert?

welche änderungen müsste ich für eine Bitlänge von 320ns machen einfach 
auf 160 umstellen? Oder gäbes im Core noch etwas zu beachten, ich takte 
mit 50MHz

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


Lesenswert?

> welche änderungen müsste ich für eine Bitlänge von 320ns machen
> einfach auf 160 umstellen?
Nein, der aus der Bitzeit und der angegebenen Taktfrequenz wird der Rest 
berechnet:
1
constant oscclk  : integer := 50000000; -- 50MHz FPGA-Takt
2
constant bittime : integer := 320;      -- ein Bit dauert 320 us

> Oder gäbes im Core noch etwas zu beachten,
Zu beachten ist, welches Protkoll du für die Übertragung verwendest. 
Wenn die Daten nicht manchestercodiert sind, kannst du einiges mehr 
umkrempeln. Denn es können ja z.B. 10 Bits = 10*320us hintereinander '0' 
kommen...

von Jochen (Gast)


Lesenswert?

das sind ja us ich benötige aber ns.

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


Lesenswert?

> das sind ja us ich benötige aber ns.
Ja, stimmt.
Dann muß der Teiler auch angepasst werden:
1
constant clkdiv  : integer := (oscclk/(1000/bittime))-1;

Wenn es aber sowieso um Zählerstände im Bereich um 320ns/20ns = 16 geht, 
würde ich die Werte von Hand ausrechnen und eintragen.

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.