Forum: FPGA, VHDL & Co. counter vhdl


von inga (Gast)


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

von Iulius (Gast)


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:
1
process (clk)
2
begin
3
4
 necsr <= necsr(1 downto 0) & nec when rising_edge(clk);
5
6
 if (necsr(2 downto 1)= "01") then -- start bit fuer zâhler
7
  cnt <= 0; -- bei jeder steigende flanke zähler auf null gesetzt
8
  bits <= bits (31 downto 0)& necsig ;
9
 ELSE
10
  cnt <= cnt + 1 ;--hochzählen
11
 end if;
12
13
 if cnt > 37500 then -- wenn der zähler 0 bit länge(freq)  überschreitet
14
  necsig <= '1';
15
 else
16
  necsig <= '0';
17
 end if;
18
19
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.

von Iulius (Gast)


Lesenswert?

Muss mich echt mal anmelden...wenn dann natürlich mit clk im process :
1
process (clk)
2
begin
3
 if rising_edge(clk) then
4
 
5
  necsr <= necsr(1 downto 0) & nec;
6
7
  if (necsr(2 downto 1)= "01") then -- start bit fuer zâhler
8
   cnt <= 0; -- bei jeder steigende flanke zähler auf null gesetzt
9
   bits <= bits (31 downto 0)& necsig ;
10
  ELSE
11
   cnt <= cnt + 1 ;--hochzählen
12
  end if;
13
14
  if cnt > 37500 then -- wenn der zähler 0 bit länge(freq)  überschreitet
15
   necsig <= '1';
16
  else
17
   necsig <= '0';
18
  end if;
19
20
 end if;
21
end process;

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


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

von Iulius C. (iulius)


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

von inga (Gast)


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?

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


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

von Iulius C. (iulius)


Angehängte Dateien:

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.

von inga (Gast)


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

von inga (Gast)


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

von berndl (Gast)


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

von inga (Gast)


Lesenswert?

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

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


Angehängte Dateien:

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.
1
library IEEE;
2
use IEEE.std_logic_1164.all;
3
use IEEE.numeric_std.all;
4
5
entity NEC_Decoder is
6
    Port ( clk : in  STD_LOGIC;
7
           NEC : in  STD_LOGIC;
8
           RXdata : out  STD_LOGIC_VECTOR (15 downto 0));
9
end NEC_Decoder;
10
11
architecture Behavioral of NEC_Decoder is
12
signal   necsr   : std_logic_vector (2 downto 0) := "000";
13
constant oscclk  : integer := 50000000; -- 50MHz z.B. FPGA
14
constant timeout : integer := (oscclk/(1000000/20000))-1;    -- Timeout: 20 ms, nach Timeout werden Daten übernommen.
15
constant one     : integer := (oscclk/(1000000/1685))-1;     -- (2,25+1,12)/2 = 1685 us
16
signal   cnt     : integer range 0 to timeout := 0;
17
signal   bits    : std_logic_vector (15 downto 0) := (others=>'0'); 
18
signal   nextbit : std_logic := '0';
19
begin
20
  -- hart aber herzlich:
21
  -- NEC-Signal einlesen, bis Pause (Timeout) länger als 20 ms
22
  process begin
23
     wait until rising_edge(clk);
24
     necsr <= necsr(necsr'left-1 downto 0) & NEC; 
25
     if (cnt<timeout) then
26
        cnt <= cnt+1;
27
     else  -- Timeout --> Daten übernehmen
28
        RXdata <= bits;
29
     end if;
30
     if (necsr="001") then    -- steigende Flanke
31
        bits <= bits(bits'left-1 downto 0) & nextbit;
32
        cnt  <= 0;
33
     end if;
34
  end process;
35
  nextbit <= '1' when (cnt >= one) else '0';
36
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...  :-/

von inga (Gast)


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?

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


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:
1
  if (necsr(2 downto 1)= "01") then -- start bit fuer zâhler
2
   cnt <= 0; -- bei jeder steigende flanke zähler auf null gesetzt
3
   bits <= bits (31 downto 0)& necsig ;
4
  ELSE
5
   if (cnt<67567) then  cnt <= cnt+1;  end if;
6
  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.

von khalid (Gast)


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;

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.