www.mikrocontroller.net

Forum: FPGA, VHDL & Co. counter vhdl


Autor: inga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hall zusammen
es geht um ein nec signal
ich habe ein signal (SIG) 32 BIT (31 downto 0), der so gebaut ist
BIT =1 ist :wenn der impuls 560 us und die pausenzeit ist 1,7ms
bit =0 ist:wenn der impuls 560 us und der pausen zeit 560 us
1 und 0 UNTERSCHEIDEN SICH VON DER PAUSENZEIT

DER OSZILATORFREQUENZ VON MEINEM BOARD IST 30 MHZ

ICH HABE SO GEMACHT ABER KLAPPT NICHT

..
...
necsr <= necsr(1 downto 0) & nec when rising_edge(clk);
bits <= bits (31 downto 0)& necsig when rising_edge(nec)

if (necsr(2 downto 1)= "01") then -- start bit fuer zâhler

cnt <= 0; -- bei jeder steigende flanke zähler auf null gesetzt

 ELSE
 cnt <= cnt + 1 ;--hochzählen

if cnt > 37500 then -- wenn der zähler 0 bit länge(freq)  überschreitet

 necsig <= '1';
else

if cnt <37500 then -- wenn zâhler kleiner als 0 bit länge

 necsig <= '0';

das problem ich will dass necsig zeigt ein 1 von bitanfang bis zu 
bitende
und nicht erst wenn cnt > 37500 oder das geht nicht ?
oder ich habe denkfehler bitte um hilfe
ich hoffe meine frage ist klar

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine einfache Lösung, falls ich alles richtig verstanden habe :

Du wertest zu dem zeitpunkt an dem feststeht ob eine '0' oder '1' ankam 
für einen takt lang aus.

Da du intern eh mit 30mhz arbeiten willst bringt es dir ja eh nichts 
wenn du zigtausend takte lang weist was da kam, du musst es ja nur 
einmal wissen.

D.h. an der Stelle wo du den Zähler zurücksetzt würdest du die 
Auswertung vornehmen anhand des aktuellen necsig.

bsp:

process (clk)
begin

 necsr <= necsr(1 downto 0) & nec when rising_edge(clk);

 if (necsr(2 downto 1)= "01") then -- start bit fuer zâhler
  cnt <= 0; -- bei jeder steigende flanke zähler auf null gesetzt
  bits <= bits (31 downto 0)& necsig ;
 ELSE
  cnt <= cnt + 1 ;--hochzählen
 end if;

 if cnt > 37500 then -- wenn der zähler 0 bit länge(freq)  überschreitet
  necsig <= '1';
 else
  necsig <= '0';
 end if;

end process;


allerdings wie gesagt, nur soweit ich das verstanden habe.

was das rising_edge(nec) dort soll weiß ich z.b. nicht, das macht meiner 
Meinung nach überhaupt keinen Sinn.

Ansonsten ist dein Code auch nur sehr zusammengekleckst.


Aber probiers erstmal wie ich das beschrieben habe und wenn das noch 
nicht klappt -> bitte den gesamten code in [/vhdl] + [vhdl] posten oder 
als .vhd anhängen.

Autor: Iulius (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Muss mich echt mal anmelden...wenn dann natürlich mit clk im process :
process (clk)
begin
 if rising_edge(clk) then
 
  necsr <= necsr(1 downto 0) & nec;

  if (necsr(2 downto 1)= "01") then -- start bit fuer zâhler
   cnt <= 0; -- bei jeder steigende flanke zähler auf null gesetzt
   bits <= bits (31 downto 0)& necsig ;
  ELSE
   cnt <= cnt + 1 ;--hochzählen
  end if;

  if cnt > 37500 then -- wenn der zähler 0 bit länge(freq)  überschreitet
   necsig <= '1';
  else
   necsig <= '0';
  end if;

 end if;
end process;

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

Bewertung
0 lesenswert
nicht lesenswert
> allerdings wie gesagt, nur soweit ich das verstanden habe.
Das NEC Signal ist realtiv simpel, es fehlt hier noch, dass der 9ms Puls 
am Anfang zur Synchronisation verwendet wird. Schön erklärt ist das 
dort: http://www.sbprojects.com/knowledge/ir/nec.htm

Ich habe das mit dem NEC-Signal auf meiner todo-Liste und werde es die 
Tage mal durchkneten. Allerdings zeigt der NEC-Modus auf meiner 
Universal-FB ein etwas anderes zetiliches Verhalten...  ;-)

Autor: Iulius C. (iulius)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das sieht ja wirklich simpel aus. Danke für den Link.

Mir war bei der Fragestellung oben gar nicht bewusst das es sich um ein 
Standardprotokoll handelt.


Hmm, den Startpulse kann man sicher auch ignorieren wenns in einen 
kleinen CPLD rein soll..macht den Zähler immerhin um 10 FFs kleiner.

Werd mich morgen auch mal daran versuchen. Immer eine gute Übung :)

Autor: inga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke zusammen
das ist richtig der start signal  mit 9ms wollte ich gar nich daran 
denken,weil ich keine vorstellung habe wie ich das mache
an miller :wie komme ich zu deiner todo liste  miller?

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

Bewertung
0 lesenswert
nicht lesenswert
> wie komme ich zu deiner todo liste  miller?
Keine Chance....
Die ist in meinem Kopf  ;-)

@ Iulius
Das mit dem Sync ist nicht unwichtig, sonst kannst du einen Start nur 
raten. Vor allem solltest du einen sättigenden Zähler für die Bitzeit 
verwenden. Denn die Zeit für eine '1' kann auch mal wesentlich länger 
sein: ich messe an der FB hier bis zu 25 ms!!

Autor: Iulius C. (iulius)
Datum:
Angehängte Dateien:
  • nec.7z (1,55 KB, 95 Downloads)

Bewertung
0 lesenswert
nicht lesenswert
Das einzige Problem das ich sehe, ist wenn ich das Gerät zum Empfangen 
während einer laufenden Übertragung einschalte.

Auf den anderen Seite gefällt mir das so oder so nicht.

Habe jetzt einen Transceiver entworfen der ~160 LE verbraucht.

Davon entfallen 60 auf den Empfänger(ohne Sync) und 100 auf den 
Sender(ziemlich genau nach Protokoll).

Irgentwie wohl doch nix für den CPLD wobei ich mich ehrlich gesagt frage 
wo die ganze Logik herkommt... klar Schieberegister+Zähler frisst schon 
einiges, aber trotzdem.


Habs mal angehangen, aber naja, gefällt mir wie gesagt nicht besonders. 
Zu groß und zu frickelig für meinen Geschmack.

Autor: inga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Denn die Zeit für eine '1' kann auch mal wesentlich länger
>
> sein: ich messe an der FB hier bis zu 25 ms!!

AN MILLER ,ICH BIN GESPANNT WIE DU DAS MACHST

Autor: inga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Iulius C. schrieb:
> Habs mal angehangen, aber naja, gefällt mir wie gesagt nicht besonders.
>
> Zu groß und zu frickelig für meinen Geschmack.

MILLER SAGT IST SEHR  EINFACH

ICH HABE SCHON SEIN RC5-empfänger gesehen er hat das super gemacht und 
nur in ein paar zeilen

aber bei rc5 die bits sind gleich fuer mich ist viel einfacher als 
nec-emp

na ja nicht aufgeben ,programmieren braucht geduld und erfahrung
ich hoffe ein ergebnis von Miller

Autor: berndl (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

wenn du Lothars Link oben (uebrigens danke dafuer, kann ich gut 
gebrauchen!) folgst, dann wirst du relativ einfach rausfinden, wie man 
das loesen kann...

Gruss,
- berndl

Autor: inga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
rc5 ist TOTAL ANDERES ALS NEC
link von miller ist direkt neben seinen namen
DARAUF DRÜCKEN

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier wie versprochen meine Lösungsansätze  ;-)
Variante 1, Bits werden mit der steigenden Flanke vom NEC-Signal 
eingelesen und nach Ablauf eines Timeouts (Pause zwischen 2 
Übertragunspaketen) übernommen.
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity NEC_Decoder is
    Port ( clk : in  STD_LOGIC;
           NEC : in  STD_LOGIC;
           RXdata : out  STD_LOGIC_VECTOR (15 downto 0));
end NEC_Decoder;

architecture Behavioral of NEC_Decoder is
signal   necsr   : std_logic_vector (2 downto 0) := "000";
constant oscclk  : integer := 50000000; -- 50MHz z.B. FPGA
constant timeout : integer := (oscclk/(1000000/20000))-1;    -- Timeout: 20 ms, nach Timeout werden Daten übernommen.
constant one     : integer := (oscclk/(1000000/1685))-1;     -- (2,25+1,12)/2 = 1685 us
signal   cnt     : integer range 0 to timeout := 0;
signal   bits    : std_logic_vector (15 downto 0) := (others=>'0'); 
signal   nextbit : std_logic := '0';
begin
  -- hart aber herzlich:
  -- NEC-Signal einlesen, bis Pause (Timeout) länger als 20 ms
  process begin
     wait until rising_edge(clk);
     necsr <= necsr(necsr'left-1 downto 0) & NEC; 
     if (cnt<timeout) then
        cnt <= cnt+1;
     else  -- Timeout --> Daten übernehmen
        RXdata <= bits;
     end if;
     if (necsr="001") then    -- steigende Flanke
        bits <= bits(bits'left-1 downto 0) & nextbit;
        cnt  <= 0;
     end if;
  end process;
  nextbit <= '1' when (cnt >= one) else '0';
end Behavioral;
Das funktioniert mit meiner Fernbedienung hier, weil die den Repeat-Code 
nicht sendet. Statt dessen wird das komplette Datenpaket nochmal 
übertragen (siehe Screenshot) :-o

Die Variante 2 ist konform zum NEC-Protokoll, weil dort die Repeat-Pulse 
gesondert behandelt werden (siehe Anhang). Allerdings kann ich die 
Funktion nicht detailliert testen, weil wie gesagt meine FB nicht ganz 
das beschriebene NEC-Protokoll sendet...  :-/

Autor: inga (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
danke sehr miller, du hast dein versprechen  gehalten danke nochmal
aber ich werde dein code erst morgen analysieren ,bin müde

mein cnt zählt auch vor der ersten flanke
.
.
.
signal cnt : integer range 0 to 67567 := 0;

bits <= bits (31 downto 0)& NECSIG ;


.
.
.
if rising_edge(clk) then

if (necsr(2 downto 1)= "01") then

  cnt <= 0;

else cnt <= cnt + 1 ;

end if ;END IF;
NORMALERWEISE DER CNT FÄNGT ZU ZÄHLEN ERST NACH DEM TREFFEN MIT EINER 
FLANKE UND NICHT VOR DEM ERSTEN FLANKE VON DER STARTBIT,
WO KEINE FLANKE GIBT
VORAN KANN DAS LIEGEN? HABE ICH WAS FALSCHES üBERSEHEN?

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

Bewertung
0 lesenswert
nicht lesenswert
Was mir da sofort auffällt:
Dein Zähler begrenzt nicht. Der zählt lustig weiter bis 131071 und läuft 
dann über auf 0 und zählt dann dort weiter....

Besser wäre es auf jeden Fall so:
  if (necsr(2 downto 1)= "01") then -- start bit fuer zâhler
   cnt <= 0; -- bei jeder steigende flanke zähler auf null gesetzt
   bits <= bits (31 downto 0)& necsig ;
  ELSE
   if (cnt<67567) then  cnt <= cnt+1;  end if;
  end if;


>>> signal cnt : integer range 0 to 67567 := 0;
Warum reichen dir nicht 65535 als Endwert?
Dann würden für den Zähler 16 Bit reichen.

Autor: khalid (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
dein programm ist 90 prozent wie meins
es gibt ein problem was ich seit tagen lösen will
die steigende flanke von nec signal zeigt den wert von der dem 
nextbit(dein signal) von den vorherigen nec signal ;
der letzen bit wird unbewertet  ,
stattdessen ist der 15-te bei dir ,bei mir auch der start bit
hier ist ein fertigen testbench kannst du noch mal probieren
NEC_PROC :PROCESS
  BEGIN
  NEC <= '0'; --pause
  WAIT FOR 3 MS;
  NEC <= '1';
  WAIT FOR 9 mS;--START BIT
  NEC <= '0';
  WAIT FOR 4500 us;
  NEC <= '1'; -- 1
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 1690 US;
  NEC <= '1'; -- 2
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 1690 US;
  NEC <= '1'; -- 3
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 560 US;
  NEC <= '1'; -- 4
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 560 US;
  NEC <= '1'; -- 5
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 1690 US;
  NEC <= '1'; -- 6
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 1690 US;
  NEC <= '1'; -- 7
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 560 US;
  NEC <= '1'; -- 8
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 1690 US;
  NEC <= '1'; -- 1
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 1690 US;
  NEC <= '1'; -- 2
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 1690 US;
  NEC <= '1'; -- 3
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 560 US;
  NEC <= '1'; -- 4
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 1690 US;
  NEC <= '1'; -- 5
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 560 US;
  NEC <= '1'; -- 6
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 1690 US;
  NEC <= '1'; -- 7
  WAIT FOR 560 us;
  NEC <= '0';
  WAIT FOR 560 US;
  NEC <= '1'; -- 8
  WAIT FOR 560 us;
  NEC <= '0';   --PAUSE ,INKLUSIV PAUSENZEIT VON DEM LETZTENBIT
  WAIT FOR 20 MS;
  END PROCESS;

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
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




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.