Sprzętowy dekoder protokołu RC5
Transkrypt
Sprzętowy dekoder protokołu RC5
Sprzętowy dekoder RC5 1 Sprzętowy dekoder protokołu RC5 Współcześnie, w większości przypadków, dekodowanie sygnałów zdalnego sterowania realizowane jest w sposób programowy z wykorzystaniem mikrokontrolerów. Alternatywnie, do dekodowania poszczególnych protokołów zdalnego sterowania można zastosować rozwiązania całkowicie sprzętowe. Dzięki zastosowaniu współcześnie bardzo dynamicznie rozwijających się układów programowalnych i komputerowych narzędzi syntezy logicznej jest to zadanie stosunkowo nieskomplikowane (w porównaniu z klasycznymi metodami projektowania i realizacji układów cyfrowych z wykorzystaniem „katalogowych” układów scalonych) i tanie w realizacji. W niniejszym opracowaniu przedstawiono sprzętowy dekoder protokołu RC5, z interfejsem równoległym oraz szeregowym interfejsem kompatybilnym z SPI, opisany w języku Verilog i zrealizowany z wykorzystaniem układów CPLD firmy Xilinx. Dekodowanie protokołu RC5 W protokole RC5 do kodowania przesyłanych bitów stosowany jest kod Manchester. Czas trwania bitu jest stały i wynosi 1.778ms. Bit o wartości logicznej 1 kodowany jest jako zmiana poziomu sygnału z niskiego na wysoki (zbocze narastające) w połowie czasu trwania bitu. Bit o wartości logicznej 0 kodowany jest jako zmiana poziomu sygnału z wysokiego na niski (zbocze opadające) również w połowie czasu trwania bitu. Inaczej można też powiedzieć, że jedynka logiczna kodowana jest jako kolejno: przerwa o czasie trwania równym połowie czasu trwania bitu, czyli 889µs i impulsu o identycznym czasie trwania. Podobnie zero logiczne kodowane jest jako kolejno: impuls o długości 889µs (połowa czasu trwania bitu) oraz przerwa o takim samym czasie trwania. 1 1 1 0 0 1 0 1 1 0 0 1 1 0 S1 S2 T A4 A3 A2 A1 A0 C5 C4 C3 C2 C1 C0 Rys. 2. Ramka danych protokołu RC5. Na rys. 2 przedstawiono przykładową ramkę danych protokołu RC5. Pierwsze dwa przesyłane bity S1 i S2 to bity startowe, których wartość logiczna zawsze równa jest 1. Kolejnym, trzecim przesyłanym bitem jest bit T informujący o przytrzymaniu klawisza w pilocie zdalnego sterowania. Bit ten zmienia swoją wartość na przeciwną, za każdym razem, kiedy naciskany jest klawisz w pilocie (wysyłane jest polecenie). W przypadku, kiedy klawisz w pilocie przytrzymany zostanie dłużej, kolejno wysyłane są identyczne ramki danych w odpowiednich odstępach czasowych – bit T nie jest wówczas cyklicznie negowany i ma cały czas stałą wartość. Kolejne przesyłane bity A4...A0 to bity adresu urządzenia RC5. Ostatnie 6 bitów ramki danych C0...C5 stanowią bity kodu polecenia. Ponieważ protokół RC5 wykorzystuje kodowanie Manchester, dlatego też do jego dekodowania można zastosować metody identyczne jak dla tego kodu. Dekodowanie kodu Manchester realizowane jest bądź z użyciem układów czasowych, bądź automatu synchronicznego. Na rys. 3 przestawiono ideę dekodowania protokołu RC5 z wykorzystaniem układu czasowego. Układ różniczkujący wytwarza impulsy przy każdej zmianie sygnału wejściowego. Impulsy te wyzwalają monowibrator (generator monostabilny), który generuje impulsy o szerokości równej 3/4 czasu trwania bitu w protokole RC5 (ok. 1.3ms). Jeżeli następny impuls wyzwalający (następne zbocze) pojawi się wówczas, gdy monowibrator nie zakończył jeszcze generowania impulsu, to powtórne wyzwolenie mo- Sprzętowy dekoder RC5 2 nowibratora nie nastąpi. Zanegowane impulsy monowibratora stanowią sygnał zegarowy taktujący przerzutnik D, na którego wyjściu Q występują wartości zdekodowanych bitów. D układ różniczkujący A B SET Q C monowibrator CLR Q wy zegar 1 0 1 1 0 0 A B C 3/4T wy T Rys. 3. Ilustracja idei dekodowania protokołu RC5 z wykorzystaniem układu czasowego sp START, 1 S0 S1 sg, 1 lg, 1 lp, 0 sg S2 S3 sp, 0 Rys. 4. Graf automatu dekodowania protokołu RC5 Na rys. 4 przedstawiono graf automatu (inaczej graf przejść i wyjść dla modelu automatu Mealy’ego), wykorzystywanego do dekodowania protokołu RC5. Etykiety opisujące łuki oznaczają odpowiednio rodzaj zdarzenia, oraz po przecinku wartość logiczną zdekodowanego bitu. Zdarzenia opisane są następującymi symbolami: sp – krótki impuls, sg – krótka przerwa, lp – długi impuls, lg – długa przerwa. Zdarzenia te sklasyfikowane są w sposób podany w tabeli (czas podany w mikrosekundach). zdarzenie sp sg lp lg ideał 889 889 1778 1778 min 444 444 1334 1334 max 1333 1333 2222 2222 Automat rozpoczyna swoje działanie od stanu S0, przy czym wejście do tego stanu powodowane jest pojawieniem się zbocza narastającego dekodowanego sygnału i jednocześnie oznacza, że odebrany został pierwszy bit o wartości logicznej 1. Następnie dekodowanych jest pozostałych 13 bitów (odebranie kolejno 14 bitów stanowi warunek zatrzymania automatu). Każde inne występujące zdarzenie, nie opisane grafem z rys. 4, traktowane jest jako błąd, powodujący przerwanie działania automatu Sprzętowy dekoder RC5 3 Sprzętowy dekoder RC5 wykorzystujący układ czasowy Na rys. 5 przedstawiony został bardziej szczegółowy schemat implementacji dekodera protokołu RC5 wykorzystującego układ czasowy. 1MHz REJESTR PRZESUWNY LICZNIK 11bit A0..A4 C0..C5 T S0 INTERFEJS SPI DET 0 IN DETEKTOR 1/0 0/1 LICZNIK 3bit STEROWANIE SCK CS RDY Rys. 5. Schemat blokowy dekodera RC5 z wykorzystaniem układu czasowego Dekoder składa się tutaj z: • detektora zboczy wykrywającego zmiany poziomu sygnału z 1 na 0 oraz z 0 na 1, • 3 – bitowego licznika zliczającego ilość pojawiających się zboczy sygnału wejściowego w momencie gdy odmierzany jest czas przez licznik 11 – bitowy, • 11 – bitowego licznika z wpisem równoległym liczącego wstecz, służącego do odmierzania czasu 3/4T (T – czas trwania bitu w protokole RC5), • detektora (komparatora) wykrywającego stan osiągnięcia przez licznik wartości 0, • 14 – bitowego rejestru przesuwnego zapamiętującego w odpowiednich chwilach czasu (wyznaczonych przez układ sterowania i licznik 11 – bitowy) stan wejścia dekodera (wyjścia odbiornika podczerwieni), • układu sterowania. Opcjonalnie dekoder może być wyposażony w interfejs kompatybilny z SPI, służący do szeregowej wymiany danych np. z mikrokontrolerem. Układ sterowanie realizuje następujące funkcje: • Na podstawie informacji z detektora zboczy steruje pracą licznika 11 – bitowego: w momencie wystąpienia zbocza do tego licznika ładowana jest wartość stałej czasowej odpowiadająca 3/4T. Jeżeli pojawi się kolejne zbocze sygnału wejściowego w momencie, gdy licznik nie zakończy jeszcze odmierzania czasu 3/4T od momentu wystąpienia poprzedniego zbocza (licznik nie osiągnie jeszcze stanu 0), wówczas powtórne załadowanie stałej czasowej do licznika nie nastąpi. • Sprawdza ilość występujących zboczy sygnału wejściowego (za pośrednictwem licznika 3 – bitowego), w czasie gdy licznik 11 – bitowy odmierza czas 3/4T. Wystąpienie w tym czasie więcej niż jednego zbocza sygnału wejściowego układ sterowania interpretuje jako błąd (dekodowany protokół nie jest protokołem RC5) i wznawia proces dekodowania od początku (zerowana jest zawartość rejestru przesuwnego). • Na podstawie informacji z detektora osiągnięcia przez licznik 11 – bitowy wartości 0, kieruje pracą rejestru przesuwnego wyznaczając moment próbkowania stanu sygnału wejściowego. • Jeżeli od momentu ostatniego zakończenia odmierzania czasu 3/4T upłynął czas dłuższy niż 3/4T układ sterowania interpretuje taką sytuację jako błąd (normalnie w protokole RC5 następne zbocze powinno pojawić się po czasie 1/4T) i proces dekodowania rozpoczynany jest od początku. W celu wyznaczenia momentu przekroczenia czasu oczekiwania na zbocze układ sterujący odpowiednio steruje pracą licznika 11 – bitowego: licznik automatycznie ładowany jest wartością stałej czasowej 3/4T, w momencie gdy osiągnie stan 0 (czyli, gdy ukończy odmierzanie poprzedniej wartości 3/4T). Sprzętowy dekoder RC5 • 4 Określa moment zakończenia dekodowania ramki protokołu RC5 ustawiając na pewien czas (3/4T) wyjście RDY. Aby określić moment zakończenia dekodowania (odebranie wszystkich 14 – stu bitów) układ sterowania analizuje stan najstarszego bitu (najbardziej znaczącego) wyjścia w rejestrze przesuwnym. Jeżeli bit ten ma wartość 1, wówczas oznacza to zakończenie procesu dekodowania. W celu implementacji sprzętowej tak zdefiniowanego dekodera RC5, z zastosowaniem narzędzi EDA i języków HDL najlepiej posłużyć się opisem mieszanym: strukturalno – behawioralnym. Strukturę dekodera określa sposób połączenia poszczególnych bloków funkcjonalnych, podczas gdy działanie tych bloków można opisać behawioralnie. Podstawową jednostką projektową w języku Verilog jest tzw. moduł. Może więc on zawierać opis behawioralny działania poszczególnych bloków z rys. 5. Jednak w przedstawionym na listingu 1 kodzie specyfikującym działanie dekodera RC5 wygodniej było zintegrować bloki: detektora zboczy, licznika 3 – bitowego, detektora osiągnięcia przez licznik 11 – bitowy stanu zerowego, rejestru przesuwnego oraz układu sterowania – w module głównym dekodera. Osobny moduł zawiera jedynie definicję działania bloku licznika 11 bitowego. W przedstawionym kodzie, celem zmniejszenia niezbędnych do implementacji zasobów sprzętowych układu programowalnego, zredukowano do 2 liczbę bitów licznika zliczającego ilość pojawiających się zboczy sygnału wejściowego w czasie gdy odmierzany jest czas 3/4T (co jednak wiąże się ze zmniejszeniem skuteczności wykrywania opisanych sytuacji, ale w praktyce okazało się zupełnie wystarczające). Listing 1. Dekoder kodu RC5 opisany w języku Verilog, wykorzystujący układ czasowy. module rc5decoder(clk,in,rdy,rc5code); // deklaracja portów we/wy input clk,in; output rdy; output [13:0] rc5code; //deklaracja zmiennych reg [13:0] rc5code; reg rc5ready,in1,load,start,to,onair; reg [13:0] rc5temp; wire [10:0] qcntr; reg [1:0] ecnt; cntr c1(.clk(clk),.load(load),.d(11'd1333),.q(qcntr)); //konkretyzacja (utworzenie instancji) modułu licznika //(licznik zdefiniowany jest w oddzielnym module) //poniżej opis behawioralny działania dekodera always @(posedge clk) begin in1<=in; //zapamiętanie stanu wejścia w poprzednim takcie zegara if((in1&~in)||(~in1&in)) begin // jeżeli zbocze 0/1 lub 1/0 sygnału wejściowego // (realizacja detektora zboczy) if(~start) begin // jeżeli nie rozpoczęto jeszcze dekodowania // ustaw odpowiednie wartości początkowe start=1'b1; onair=0; rc5temp=14'd1; ecnt=0; end else ecnt=ecnt+1; //inkrementuj wartość licznika błędu if(~onair) begin // jeżeli wystąpiło zbocze na wejściu // i nie trwa odmierzania czasu 3/4T load=1'b1; //załaduj licznik stałą 3/4T onair=1'b1; Sprzętowy dekoder RC5 5 end to=0; end else load=0; if(ecnt==2'b11) begin // jeżeli zbyt dużo zboczy – rozpocznij dekodowanie od początku start=0; to=0; end if(qcntr==11'd0) begin //licznik osiągnął stan 0 onair=0; ecnt=0; if(~to) begin to=1'b1; //jeżeli to=1, licznik odmierza czas oczekiwania na następne zbocze if(start) rc5temp={rc5temp[12:0],in}; //realizacja rejestru przesuwnego end else begin // jeżeli przekroczono czas oczekiwania na zbocze start=0; to=0; rc5ready=0; end end if(rc5temp[13]==1'b1) begin // jeżeli odebrano już 14 bitów – koniec dekodowania rc5code=rc5temp; rc5ready=1; start=0; end end assign rdy=rc5ready; endmodule // definicja działania licznika 11-bitowego module cntr(clk,load,d,q); input clk,load; input [10:0] d; output [10:0] q; reg [10:0] tmp; always @(posedge clk) begin if(load) tmp=d; else if(tmp==11'd0) tmp=d; else tmp=tmp-1; // jeżeli licznik osiągnął 0 – ładuj automatycznie stałą // czasową d, w przeciwnym przypadku dekrementuj zawartość licznika end assign q=tmp; endmodule Tak zdefiniowany wirtualny komponent dekodera RC5 może być postrzegany jako pewna „czarna skrzynka” z następującymi sygnałami wejściowymi i wyjściowymi: • clk – zegarowy sygnał taktujący (musi być 1MHz), • in – wejście dekodera, które powinno być połączone z wyjściem odbiornika podczerwieni (aktywny poziom niski – nie trzeba więc negować sygnału z odbiornika), Sprzętowy dekoder RC5 • • 6 rdy – wyjście informujące o pomyślnym zakończeniu dekodowania protokołu (na tym wyjściu pojawia się impuls o czasie trwania ok. 3ms) rc5code – 14-sto bitowe wyjście danych zdekodowanych (stan poszczególnych bitów w odebranej ramce danych protokołu RC5) Sprzętowy dekoder RC5 wykorzystujący automat sekwencyjny W przypadku implementacji sprzętowej dekodera z wykorzystaniem automatu sekwencyjnego odpowiedni schemat blokowy układu dekodera może wyglądać tak jak pokazano na rys. 6. AUTOMAT SEKWENCYJNY REJESTR PRZESUWNY A0..A4 C0..C5 T S0 SP SG LP LG INTERFEJS SPI TO SCK CS KOMPARATORY STEROWANIE 1MHz IN DETEKTOR 1/0 0/1 RDY LICZNIK RST Rys. 6. Schemat blokowy dekodera RC5 z wykorzystaniem automatu sekwencyjnego Dekodera składa się tutaj z: detektora zboczy (1/0 lub 0/1) zerującego licznik (wystąpienie zbocza sygnału wejściowego powoduje wyzerowanie licznika), • licznika 11 – bitowego odmierzającego czas z rozdzielczością 1us (przy taktowaniu 1MHz), • zespołu komparatorów, który określa wystąpienie odpowiednich zdarzeń dla automatu sekwencyjnego (krótki impuls – SP, długi impuls – LP, krótka przerwa – SG, długa przerwa – LG, przekroczenie czasu oczekiwania na zbocze – TO), • automatu sekwencyjnego, działającego według grafu z rys. 3.16, będącego zasadniczą częścią dekodera, • rejestru przesuwnego, zapamiętującego kolejne odebrane bity ramki protokołu RC5, wyznaczone przez automat sekwencyjny, • prostego układu sterująco – nadzorującego, odpowiedzialnego m. in. za wyznaczania końca transmisji ramki danych RC5. Kod źródłowy implementacji dekodera z wykorzystaniem automatu sekwencyjnego przedstawiono na listingu 2. • Listing 2. Dekoder RC5 opisany w języku Verilog, wykorzystujący automat sekwencyjny module rc5decoder_II(clk,in,rdy,rc5code); input clk,in; output rdy; output [13:0] rc5code; wire short_pulse,long_pulse,short_gap,long_gap; reg[3:0] state; wire time_out; reg [13:0] rc5temp; reg rc5ready; reg [13:0] rc5code; timer t1(.clk(clk),.in(~in), .lp(long_pulse),.sp(short_pulse), .lg(long_gap),.sg(short_gap),.to(time_out)); Sprzętowy dekoder RC5 //Konkretyzacja modułu timera (licznik wraz z komparatorami) //Poniżej realizacja automatu always@(posedge clk) begin if(time_out) begin // jeżeli przekroczono czas oczekiwania na zbocze // automat wraca do stanu początkowego state=4'd0; rc5ready=0; end else begin case(state) 4'd0: begin rc5temp=0; if(~in) state=4'd1; else state=4'd0; // jeżeli zmiana poziomu wejścia na niski – // przejdź do stanu 1, w przeciwnym przypadku pozostań w 0 end 4'd1: begin rc5temp={rc5temp[12:0],1'b1}; //wpisanie jedynki do rejestru przesuwnego //(pierwszy bit startu ramki RC5) state=4'd2; //przejdź do stanu 2 czyli S0 end 4'd2: begin //stan S0 automatu (rys. 3.16) if(short_pulse&&long_pulse) state=4'd0; //jeżeli inne zdarzenie niż krótki impuls lub długi impuls //wróć do stanu 0 else if(short_pulse&&!long_pulse) state=4'd3; //S1 //jeżeli krótki impuls przejdź do stanu 3 (S1) else if(long_pulse&&!short_pulse) state=4'd4; // jeżeli długi impuls przejdź do stanu pośredniego 4 else state=4'd2; // w przeciwnym przypadku pozostań w bieżącym stanie 2 end 4'd3: begin //stan S1 if(short_gap&&long_gap) state=4'd0; //jeżeli zdarzenie inne niż spodziewane – następny stan 0 else if(short_gap&&!long_gap) state=4'd5; //jeżeli krótka przerwa wróć do stanu S0 else state=4'd3; end 4'd4: begin // odebrano bit o wartości 0 rc5temp={rc5temp[12:0],1'b0}; //wpisanie 0 do rejstru przesuwnego state=4'd6; //przejdź do stanu S2 end 4'd5: begin 7 Sprzętowy dekoder RC5 // odebrano bit o wartości 1 rc5temp={rc5temp[12:0],1'b1}; wpisanie 1 do rejestru przesuwnego state=4'd2; //przejdź do stanu S0 end 4'd6: begin //stan S2 if(short_gap&&long_gap) state=4'd0; //jeżeli zdarzenie inne niż spodziewane – następny stan 0 else if(long_gap&&!short_gap) state=4'd5; //jeżeli długa przerwa przejdź do stanu pośredniego 5 else if(short_gap&&!long_gap) state=4'd7; //jeżeli krótka przerwa przejdź do stanu S3 else state=4'd6; end 4'd7: begin //stan S3 if(short_pulse&&long_pulse) state=4'd0; //jeżeli zdarzenie inne niż spodziewane – następny stan 0 else if(short_pulse&&!long_pulse) state=4'd4; //jeżeli krótki impuls idź do stanu pośredniego 4 else state=4'd7; end endcase if(rc5temp[13]==1'b1) begin //jeżeli bit MSB rejstru przesuwnego zapalony – //dekodowanie zakończone rc5code=rc5temp; //zapamiętaj odebrane bity w rejestrze zatrzaskowym rc5ready=1; state=4'd0; //ustaw flage zakończenia dekodowania i przejdź do stanu 0 end end end assign rdy=rc5ready; //przepisanie flagi zakończenia dekodowania do portu wyjściowego endmodule //Poniżej kod modułu timera module timer(clk,sp,lp,sg,lg,in,to); input clk,in; output sp,lp,sg,lg,to; reg sp1,lp1,sg1,lg1,rst,in1,to; wire [11:0] time1; wire [4:0] tm; cntr c1(.clk(clk),.q(time1),.rst(rst)); //konkretyzacja modułu licznika assign tm={time1[11],time1[10],time1[9],time1[8]}; //zmienna tm zawiera 4 najbardziej znaczące bity licznika assign assign assign assign sp=sp1; lp=lp1; sg=sg1; lg=lg1; //poniżej opis behawioralny działania układu licznik - komparatory always @(posedge clk) begin 8 Sprzętowy dekoder RC5 if(time1>12'd2300) to=1; else to=0; //jeżeli oczekiwanie na zbocze dłużej niż 2.3ms – ustaw flagę to in1<=in; //przypisanie nie blokujące //(zapamiętanie stanu wejścia w poprzednim takcie zegara) if(in1&~in) //zbocze opadające na wejściu begin rst=1; //wyzeruj licznik (w następnym takcie) if(tm>4'd2&&tm<4'd5) //krótki impuls begin sp1=1; lp1=0; sg1=0; lg1=0; end else if(tm>4'd4&&tm<4'd8) //długi impuls begin sp1=0; lp1=1; sg1=0; lg1=0; end else begin //jeżeli impuls spoza przedziału - błąd sp1=1; lp1=1; sg1=0; lg1=0; end end else if(~in1&in) //zbocze narastające na wejściu begin rst=1; //zeruj licznik if(tm>4'd2&&tm<4'd5) //krótka przerwa begin sg1=1; lg1=0; sp1=0; lp1=0; end else if(tm>4'd4&&tm<4'd8) //długa przerwa begin sg1=0; lg1=1; sp1=0; lp1=0; end else begin //jeżeli przerwa spoza przedziału – błąd sg1=1; lg1=1; sp1=0; lp1=0; end end else rst=0; end endmodule //Poniżej kod licznika module cntr(clk,rst,q); input clk,rst; output [11:0] q; reg [11:0] tmp; always @(posedge clk) begin if (rst) tmp=0; //synchroniczne zerowanie else tmp=tmp+1; //inkrementacja licznika end assign q=tmp; endmodule 9 Sprzętowy dekoder RC5 10 Tak zaimplementowany, według kodu z listingu 2, wirtualny komponent dekodera RC5, z punktu widzenia sygnałów wejścia – wyjścia zachowuje się identycznie jak opisany już poprzednio dekoder. Wymaga jednak nieco więcej zasobów sprzętowych danego układu programowalnego (dla przykładu: w przypadku implementacji z zastosowaniem układu Xilinx XC9572XL i narzędzi XST zawartych w pakiecie Xilinx ISE 5.2i, dekoder ten zajmuje 63 makrokomórki, podczas gdy poprzednia wersja – 57, w obu przypadkach dla strategii silnej optymalizacji powierzchni). Szeregowy interfejs SPI Budując sprzętowy dekoder RC5 z wykorzystaniem układów PLD, można wyposażyć go w szeregowy interfejs kompatybilny z SPI. Interfejs ten może być przydatny w przypadku współpracy dekodera z mikrokontrolerem (odciążając mikroprocesor z realizacji zadania dekodowania protokołu RC5) lub innymi urządzeniami peryferyjnymi. Szeregowy interfejs SPI (Serial Peripheral Interface) do transmisji danych wykorzystuje trzy linie: CS – wybór danego urządzenia SPI (aktywny poziom niski), SCK – sygnał zegarowy, S0 – wyjście danych. Za pośrednictwem interfejsu SPI dane przesyłane są w sposób synchroniczny. W pewnym uproszczeniu działanie interfejsu można opisać następująco. Transmisję danych inicjuje układ nadrzędny ustawiając linię CS układu podrzędnego w stan niski. Układ podrzędny ustawia wówczas linię wyjściową S0 w stan odpowiadający pierwszemu transmitowanemu bitowi (bit najbardziej znaczący przesyłany jest jako pierwszy). Stan linii S0 może być próbkowany przez układ nadrzędny podczas opadającego zbocza sygnału zegarowego SCK. Układ podrzędny może zmieniać stan linii wyjściowej tylko wówczas, gdy sygnał SCK generowany przez układ nadrzędny znajduje się w stanie niskim. Wygenerowanie impulsu na linii SCK przez układ nadrzędny powoduje pojawienie się na linii S0 kolejnego transmitowanego bitu, itd. Na listingu 3 przedstawiono kod w języku Verilog opisujący działanie interfejsu szeregowego SPI dla układu sprzętowego dekodera RC5. Listing 3. Wirtualny komponent realizujący interfejs SPI dla układu podrzędnego module spi_core(clk,data,cs,sck,s0); input clk,cs,sck; input [13:0] data; output s0; reg [15:0] sreg; reg f1,f2; always @(posedge clk) begin if(~cs) begin //jeżeli linia CS znajduje się w stanie niskim if(~f1) begin f1=1; f2=0; sreg=data; end //równoległy wpis do rejestru przesuwnego sreg //wartości danych wejściowych – podczas opadającego //zbocza sygnału CS if(~sck&&f2) begin sreg={sreg[12:0],sreg[13]}; f2=0; //zeruj flagę f2 //rejestr przesuwny sreg przesuwany jest podczas gdy //SCK zmieni swój stan na niski end if (sck&&~f2) f2=1; //jeżeli SCK zmienił poziom na wysoki – ustaw flagę f2 end else f1=0; // jeśli CS=1, zeruj flagę f1 end end assign s0=sreg[13]; Sprzętowy dekoder RC5 11 //SO to najstarszy bit rejestru przesuwnego endmodule Przedstawiona na listingu 3 implementacja interfejsu szeregowego wykorzystuje rejestr przesuwny z wpisem równoległym. Jak wykazały doświadczenia tego typu realizacja interfejsu zajmuje relatywnie dużo zasobów sprzętowych układu programowalnego (co jest istotne w przypadku implementacji na tanich układach programowalnych klasy CPLD, wyposażonych w dość ograniczone zasoby logiczne). Można jednak zastosować nieco prostszą konstrukcję interfejsu, tak jak zilustrowano to na rys. 7. Zamiast rejestru przesuwnego można wykorzystać licznik sprzężony z multiplekserem. Wystąpienie zbocza opadającego na linii CS spowoduje wyzerowanie licznika. Wyjścia licznika połączone są z wejściami wyboru multipleksera. Pojawienie się impulsów na wejściu zegarowym licznika spowoduje zwiększanie wartości licznika i odpowiadające tej wartości połączenie wyjścia multipleksera z jednym z wejść danych multipleksera. Efekt końcowy będzie identyczny jak z użyciem rejestru przesuwnego. MUX DANE SO SEL E LICZNIK SCK RST DETEKTOR 1/0 CS Rys. 7. Inna realizacja interfejsu SPI Na listingu 4 przedstawiono kod w języku Verilog opisujący alternatywną realizację interfejsu SPI. Listing 4. Alternatywna implementacja interfejsu SPI module spi_core(data,clk,cs,sck,s0); input cs,clk,sck; input [13:0] data; output s0; wire [3:0] qcntr; cntr4 c1(.sck(sck),.clk(clk),.q(qcntr),.cs(cs)); mux m1(.data(data),.sel(qcntr),.out(s0)); //definicja sposobu połączenia licznika i multipleksera //(konkretyzacja modułów licznika i multipleksera) endmodule //definicja modułu licznika module cntr4(cs,clk,sck,q); input sck,clk,cs; output [3:0] q; reg [3:0] q; reg clrcnt,f; wire rst; always @(posedge clk) begin if(~cs&&f) begin f=0; clrcnt=1; Sprzętowy dekoder RC5 12 end else clrcnt=0; //sygnał zerowanie clrcnt dla licznika ustawiany //w momencie wystąpienia zbocza opadającego na CS if(cs&&~f) f=1; end assign rst=~clrcnt; //zmiana polaryzacji always @(negedge sck or negedge rst) begin if(~rst) q=4'd0; //asynchroniczne zerowanie licznika else q=q+1; //inkrementacja licznika end endmodule //opis behawioralny modułu multipleksera module mux(data,sel,out); input [13:0] data; input [3:0] sel; output out; reg out; always @(sel or data) begin case (sel) 4'd0: out=data[13]; 4'd1: out=data[12]; 4'd2: out=data[11]; 4'd3: out=data[10]; 4'd4: out=data[9]; 4'd5: out=data[8]; 4'd6: out=data[7]; 4'd7: out=data[6]; 4'd8: out=data[5]; 4'd9: out=data[4]; 4'd10: out=data[3]; 4'd11: out=data[2]; 4'd12: out=data[1]; 4'd13: out=data[0]; 4'd14: out=0; 4'd15: out=0; endcase end endmodule CS SCK SO S1 S2 T A4 A3 A2 A1 A0 C5 C4 C3 C2 C1 C0 S1 S2 Rys. 8. Ilustracja działania interfejsu SPI Na rys. 8 przedstawiono ilustrację sposobu działania interfejsu SPI zrealizowanego według opisu z listingu 3. Ilość bitów interfejsu dostosowana jest do długości ramki protokołu RC5 i wynosi 14 bitów. Dlatego też w przypadku, gdy na linii SCK interfejsu wystąpi więcej niż 14 impulsów, wówczas dane pojawiają się na wyjściu „od początku” (czyli po najmniej znaczącym bicie kodu polecenia RC5 pojawia się pierwszy bit startu, itd.). Sprzętowy dekoder RC5 13 Działanie interfejsu SPI z listingu 4 jest analogiczne, przy czym po 14 bitach ramki danych RC5, w przypadku dalszego taktowania linii SCK, pojawiając się dwa bity, których wartość zawsze jest równa 0 i dopiero wówczas kolejne bity ramki RC5 transmitowana jest od początku. Dane z interfejsu SPI mogą być odczytywane w dowolnej chwili z szybkością wyznaczoną przez układ nadrzędny (mikrokontroler). Jednak w przypadku interfejsu z listingu 3 maksymalna częstotliwość impulsów na wejściu SCK musi być mniejsza niż częstotliwość taktowania na wejściu zegarowym (clk) interfejsu. W przypadku implementacji interfejsu według listingu 4, częstotliwość impulsów na linii SCK może być znacznie większa niż częstotliwość taktowania na wejściu clk (licznik, będący głównym elementem interfejsu, taktowany jest bezpośrednio impulsami z linii SCK, podczas gdy pomocniczy sygnał taktujący clk wykorzystywany jest tylko do wykrywania opadającego zbocza sygnału na linii CS). Listing 5. Funkcja odczytu danych z interfejsu SPI, napisana w języku C dla mikrokontrolera unsigned int spi_rx(void) { char j, b; unsigned int w; w=0; CS=0; SCK=0; for (j=0;j<14;j++) { SCK=1; w<<=1; b=SO; w|=b; SCK=0; } CS=1; return w; } Na listingu 5 przedstawiono dodatkowo kod źródłowy funkcji w języku C, napisanej dla mikrokontrolera, dzięki której można odczytać dane z przedstawionego powyżej interfejsu SPI. Funkcja zwraca pełne 14 bitów ramki danych RC5. Przykładowa aplikacja Wykorzystując opisane powyżej wirtualne komponenty dekoderów RC5 oraz interfejsu SPI można zbudować rzeczywisty, sprzętowy dekoder protokołu RC5. Na rys. 9 przedstawiono przykładowy schemat ideowy takiego układu, a na rys. 10 widok płytki drukowanej. U2 LM317L JP1 3 Vcc 3.3V Vin Vout C1 100n 2 JTAG JP2 C2 100n R1 240 Vcc 5 4 3 2 1 Adj 2 1 1 39 40 41 42 43 44 1 2 R3 820 4 U3 VCC 3 OUT GND 3 JP3 GEN 2MHz 2 R4 120 U4 OUT 1 2 C3 3 220n 18 19 20 21 22 23 I/O/MC1-17 I/O/MC2-17 I/O/MC4-2 I/O/MC4-5 I/O/MC4-8 I/O/MC4-9 I/O/MC4-11 I/O/MC4-14 I/O/MC3-2 I/O/MC3-5 I/O/MC3-8 I/O/MC3-9 I/O/MC3-11 I/O/MC3-14 14 16 28 27 25 17 4 GND VS 5 4 3 2 1 JP5 U1 I/O/MC2-2 I/O/MC2-5 I/O/MC2-6 I/O/MC2-8 I/O/GSR/MC2-9 I/O/GTS2/MC2-11 I/O/GTS1/MC2-14 I/O/MC2-15 I/O/MC3-15 I/O/MC3-17 I/O/MC4-17 I/O/MC4-15 GND GND GND RDY CS SCK SO GND I/O/MC1-2 I/O/MC1-5 I/O/MC1-6 I/O/MC1-8 I/O/GCK1/MC1-9 I/O/GCK2/MC1-11 I/O/GCK3/MC1-14 I/O/MC1-15 VCCIO VCCINT VCCINT D1 LED TDO TMS TDI TCK 390 26 35 15 24 10 9 11 R2 29 30 31 32 33 34 36 37 1 2 3 4 5 6 7 C0 C1 C2 C3 C4 C5 T JP4 38 5 6 7 8 12 13 XC9572XL-VQ44 TSOP1736 Rys. 9. Schemat ideowy układu sprzętowego dekodera RC5 10 8 6 4 2 9 7 5 3 1 A4 A3 A2 A1 A0 Sprzętowy dekoder RC5 14 Rys. 10. Widok płytki drukowanej dekodera Jako układ programowalny wybrano tutaj Xilinx CPLD z rodziny XC9500XL typu XC9572XL w obudowie VQFP44. Układ zasilany jest napięciem 3.3V, ale od strony wejść akceptuje napięcia o standardzie TTL. Jako stabilizator 3.3V zastosowano typowy stabilizator uniwersalny typu LM317 z odpowiednio dobranymi wartościami rezystorów określającymi wartość napięcia wyjściowego. W układzie wytwarzania przebiegu taktującego pracuje typowy, cztero końcówkowy (w metalowej obudowie) zintegrowany generator zegara o częstotliwości 2MHz (można zastosować generator o innej częstotliwości, ale wówczas należy odpowiednio zaprogramować dzielniki częstotliwości dla układu dekodera RC5, który musi być taktowany z częstotliwością 1MHz). Do przetwarzania sygnałów podczerwieni, nadawanych przez pilota zdalnego sterowania, wykorzystano zintegrowany odbiornik podczerwieni firmy Vishay (TSOP1736). Na listingu 6 przedstawiono kod źródłowy w języku Verilog modułu implementującego dekoder RC5 i interfejs SPI. Listing 6. Kompletny sprzętowy dekoder RC5 z interfejsem SPI module top(clock,in,cs,sck,s0,rdy,ld,C,A,T); //definicja portów we - wy input clock,in,cs,sck; output ld,s0,rdy,T; output [4:0] A; // adres RC5 output [5:0] C; // kod polecenia wire clk; reg rc5ready; wire [13:0] rc5code; clock_divider cd1(.clock(clock),.clk(clk)); //konkretyzacja modułu dzielnika częstotliwości //sygnał clk ma teraz częstotliwość 1MHz rc5decoder dec(.clk(clk),.in(in),.rdy(rdy),.rc5code(rc5code)); //konkretyzacja opisanego wcześniej modułu dekodera assign ld=rdy; //dioda LED połączona z sygnałem rdy assign C={rc5code[5],rc5code[4],rc5code[3],rc5code[2], rc5code[1],rc5code[0]}; //przypisanie do odpowiednich wyjść kodu polecenia RC5 assign A={rc5code[10],rc5code[9],rc5code[8],rc5code[7],rc5code[6]}; //przypisanie adresu urządzenia RC5 assign T=rc5code[11]; //bit informujący o przytrzymaniu klawisza w pilocie spi_core spi1(.clk(clk),.cs(cs),.sck(sck),.s0(s0),.data(rc5code)); //konkretyzacja modułu interfejsu SPI endmodule //moduł dzielnika częstotliwości module clock_divider(clock,clk); input clock; output clk; reg q; always @(posedge clock) Sprzętowy dekoder RC5 15 begin q=~q; end assign clk=q; endmodule Po zaimportowaniu do środowiska EDA dla układów programowalnych kodów źródłowych z listingu 5 – modułu nadrzędnego w hierarchicznej strukturze projektu – oraz jednego z modułów dekodera RC5 (których kody źródłowe zamieszczono na listingach 1 i 2) i modułu interfejsu SPI (listing A.3 lub A.4), i jeszcze przypisując portom wejścia / wyjścia modułu nadrzędnego odpowiednie numery końcówek układu PLD – kompletny projekt można poddać kompilacji. Jako środowisko EDA wykorzystano tutaj pakiet Xilinx ISE w wersji 5.2i. W wyniku procesu kompilacji (implementacji) otrzymuje się plik w standardowym, dla układów CPLD, formacie JEDEC, który służy do zaprogramowania nieulotnej pamięci konfiguracji w danym układzie PLD. Zastosowany układ PLD posiada możliwość programowania w systemie – ISP (In-System Programming), poprzez intefejs JTAG, którego odpowiednie linie wyprowadzono na złącze JP2 płytki drukowanej. W celu zaprogramowania układu można wykorzystać uniwersalny programator ISP opisany w Elektronice Praktycznej 1/2004 lub też prosty programator, którego schemat można znaleźć w dokumentacji firmy Xilinx (programator ten był opisany również w Elektronice Praktycznej 4/2001). Po zaprogramowaniu układu PLD sprzętowy dekoder RC5 jest gotowy do pracy. Poprawne odebranie przez dekoder ramki danych protokołu RC5 sygnalizowane jest krótkim mignięciem diody LED. Jednocześnie na wyjściu RDY (złącze JP3) pojawia się w tym momencie stan wysoki. Na złączu JP5 występują kolejne bity (C0..C5) kodu polecenia RC5 oraz bit T (informujący o przytrzymaniu klawisza w pilocie), a na złączu JP4 dostępne są bity adresu urządzenia (A0..A4). Zdekodowane bity ramki danych RC5 można również odebrać poprzez wbudowany interfejs SPI (linie CS, SCK, SO złącza JP3). Sprzętowy dekoder RC5 można również tak skonfigurować, by odbierał tylko ramkę danych z określonym adresem urządzenia RC5 (podobnie jak robił to wycofany już z produkcji układ SAA3049 firmy Philips). W tym celu wystarczy nieco zmienić kod w module nadrzędnym – tak jak pokazano to na listingu 7. Listing 7. Kod sprzętowego dekodera RC5 akceptującego określony adres urządzenia RC5 module top(clock,in,cs,sck,s0,rdy,ld,C,A,T); input clock,in,cs,sck; output ld,s0,rdy,T; input [4:0] A; output [5:0] C; wire [4:0] rc5addr; reg [5:0] C; wire clk; reg T,ready; wire rdy; wire [13:0] rc5code; clock_divider cd1(.clock(clock),.clk(clk)); rc5decoder dec(.clk(clk),.in(in),.rdy(rdy),.rc5code(rc5code)); spi_core spi1(.clk(clk),.cs(cs),.sck(sck),.s0(s0),.data(rc5code)); assign rc5addr={rc5code[10],rc5code[9], rc5code[8],rc5code[7],rc5code[6]}; //wydzielenie adresu urządzenia always @(posedge clk) begin if(rdy) begin if(rc5addr==A) begin //jeżeli zgadza się adres RC5 z adresem ustawionym //na liniach zewnętrznych układu PLD C={rc5code[5],rc5code[4],rc5code[3],rc5code[2], Sprzętowy dekoder RC5 16 rc5code[1],rc5code[0]}; T=rc5code[11]; ready=1; end end else ready=0; end assign ld=ready; endmodule W tym przypadku adres urządzenia RC5 odebrany z ramki danych porównywany jest z adresem odczytanym z zewnętrznych końcówek układu dekodera (stan linii A0...A4 złącza JP3). Jeżeli oba adresy są zgodne, wówczas ustawiane jest wyjście RDY (złącze JP3) i na krótką chwilę zapala się dioda LED. Na wyjściach C0...C5 oraz T dostępne są wówczas odpowiednie dane. Dane odczytane za pomocą interfejsu SPI dostępne są niezależnie od tego czy oba adres urządzeń RC5 są zgodne, czy też nie. Na kolejnych rysunkach przedstawiono przebiegi czasowe w wybranych punktach sprzętowego dekodera RC5 otrzymane przy pomocy analizatora stanów logicznych. Na rys. 11 pokazano przebiegi czasowe dla układu dekodera opisanego kodem z listingu 1. Pierwszy kanał analizatora ilustruje stan sygnału wejściowego dekodera (wyjście zintegrowanego odbiornika podczerwieni) w momencie nadawania ramki danych RC5 z kodem polecenia równym 01h oraz adresem urządzenia 16h. Drugi kanał przedstawia zachowanie sygnału onair (listing 1 – sygnał wyprowadzono na zewnętrzne końcówki układu PLD). Sygnał ten odpowiada sygnałowi z wyjścia monowibratora z rys. 3. Jego opadające zbocze wyznacza moment próbkowania sygnału wejściowego przez rejestr przesuwny (czyli stan dekodowanego bitu). Trzeci kanał analizatora ilustruje przebieg sygnału na wejściu rdy. Poziom wysoki na tym wyjściu oznacza pomyślne zakończenie dekodowania ramki danych RC5. Rys. 11. Przebiegi czasowe w układzie dekodera RC5 zaimplementowanego według kodu z listingu 1 Rys. 12. Przebiegi czasowe w układzie dekodera RC5 zaimplementowanego według kodu z listingu 2 Rys. 12 przedstawia przebiegi czasowe w układzie sprzętowego dekodera RC5 wykorzystującego ideę automatu sekwencyjnego (kod z listingu 2). Kanały pierwszy i ostatni analizatora stanów logicznych ilustrują zachowanie sygnałów wejściowego in oraz wyjściowego rdy. Na pozostałych kanałach widoczne są przebiegi sygnałów określające rodzaj zdarzenia dla automatu sekwencyjnego wykorzystywanego do dekodowania protokołu RC5 (sygnały: lg – długa przerwa, sg – krótka przerwa, lp – długi impuls, sp – krótki impuls). Zbigniew Hajduk http://zh.prz-rzeszow.pl Sprzętowy dekoder RC5 17 UWAGA Przedstawione powyżej wirtualne komponenty sprzętowego dekodera RC5 przeznaczone są bezpośrednio do syntezy. W przypadku symulacji wyniki symulacji funkcjonalnej mogą nie odpowiadać rezultatom symulacji czasowej (po syntezie). Literatura 1. Łuba T., Rawski M, Tomaszewicz P., Zbierzchowski B., Synteza układów cyfrowych, WKŁ, Warszawa 2003. 2. Pasierbiński J., Zbysiński P., Układy programowalne w praktyce, WKŁ, Warszawa 2002. 3. Synopsys Inc., FPGA Compiler II / FPGA Express Verilog HDL Reference Manual, 1999. 4. Xilinx Inc., Xilinx Synthesis Technology (XST) User Guide, 2002. 5. Zbysiński P., UnISProg – uniwersalny programator ISP, Elektronika Praktyczna, Nr 1, str. 21 – 25, styczeń 2004. 6. Zwoliński M., Projektowanie układów cyfrowych z wykorzystaniem języka VHDL, WKŁ, Warszawa 2002.