Serwis Edukacyjny w I-LO w Tarnowie Materiały dla uczniów liceum |
Wyjście Spis treści Wstecz Dalej Autor artykułu: mgr Jerzy Wałaszek |
©2024 mgr Jerzy Wałaszek |
SPIS TREŚCI |
Podrozdziały |
Licznik rewersyjny (ang. reverse counter) jest licznikiem zliczającym wstecz. Można go zbudować jako asynchroniczny (ang. ripple reverse counter) lub synchroniczny (synchronous reverse counter). Samo zliczanie wstecz jest dosyć proste do uzyskania - wystarczy pobierać sygnał z komplementarnych wyjść Q przerzutników T w liczniku asynchronicznym. Zanegowane stany wyjść pracują właśnie jako licznik rewersyjny.
Przyjrzyjmy się poniższej tabelce:
Wyjścia normalne | Wyjścia zanegowane | ||||||||
Stan | QD | QC | QB | QA | QD | QC | QB | QA | Stan |
0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 15 |
1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 14 |
2 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 13 |
3 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 12 |
4 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 11 |
5 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 10 |
6 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 9 |
7 | 0 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 8 |
8 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 7 |
9 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 6 |
10 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 5 |
11 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 4 |
12 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 3 |
13 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 2 |
14 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 | 1 |
15 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 |
Początkowy stan 0 uzyskamy wykorzystując wejście PRE (PRESET - ustwianie Q na 1) zamiast CLR (CLEAR - ustawianie Q na 0 ) ( patrz tabelka).
Rozważania te sugerują następujący układ pracy asynchronicznego licznika rewersyjnego:
Synchroniczny licznik rewersyjny można oprzeć na tej samej zasadzie lub zaprojektować go od podstaw wyznaczając funkcje przełączające T dla przerzutników J-K. Zastosujemy tę drugą metodę.
Kolejne stany licznika | Funkcje przełączające | |||||||
Stan | QD | QC | QB | QA | TD | TC | TB | TA |
0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
15 | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |
14 | 1 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
13 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 1 |
12 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 |
11 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 1 |
10 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
9 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
8 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 |
7 | 0 | 1 | 1 | 1 | 0 | 0 | 0 | 1 |
6 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 |
5 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 |
4 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 1 |
3 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 1 |
2 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 1 |
1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 |
Na podstawie tabelki pożądanych stanów licznika wyznaczamy sygnały przełączające TX dla poszczególnych przerzutników. Sygnał TX ma wartość zero, gdy przerzutnik X nie musi być przełączony przy przejściu do kolejnego stanu licznika i 1, gdy przerzutnik należy przełączyć w stan przeciwny.
Wartości poszczególnych funkcji przełączających można wyprowadzić po krótkiej analizie tabelki lub wykorzystując tablice Karnaugha. Ja wybrałem ten pierwszy sposób:
Zwróć uwagę, iż poszczególne sygnały przełączające tworzą regularny ciąg (porównaj go z ciągiem funkcji przełączających dla licznika synchronicznego zliczającego w przód).
Na podstawie tych funkcji tworzymy sieć logiczną licznika:
Funkcje przełączające TX sterują wejściami J i K poszczególnych przerzutników wchodzących w skład sieci logicznej licznika.
Napiszemy teraz prosty program w języku C++, który symuluje pracę licznika. Wykorzystamy funkcję przerzutnika J-K z poprzedniego rozdziału:
int JK(int J, int K, int Q) { if((J == K) && J) return 1 - Q; if(J) return 1; if(K) return 0; return Q; } |
Rozpoczynamy od ponumerowania elementów logicznych:
Definiujemy sieć połączeń:
YB5 = AND(NOT(QA),NOT(QB))
YB6 = AND(NOT(QA),NOT(QB),NOT(QC))
QB = JK(NOT(QA),NOT(QA))
QA = JK(1,1)
QC = JK(YB5,YB5)
QD = JK(YB6,YB6)
Stan przerzutników J-K będzie pamiętany w zmiennych QA, QB, QC i QD. Na początku symulacji zmienne te zostaną wyzerowane, następnie będzie wykonana 18 razy pętla symulacyjna, każdy obieg symuluje jeden impuls zegarowy. Na wyjściu powinniśmy otrzymać wyniki zgodne z poniższą tabelką:
Kolejne stany licznika | ||||
Stan | QD | QC | QB | QA |
0 | 0 | 0 | 0 | 0 |
15 | 1 | 1 | 1 | 1 |
14 | 1 | 1 | 1 | 0 |
13 | 1 | 1 | 0 | 1 |
12 | 1 | 1 | 0 | 0 |
11 | 1 | 0 | 1 | 1 |
10 | 1 | 0 | 1 | 0 |
9 | 1 | 0 | 0 | 1 |
8 | 1 | 0 | 0 | 0 |
7 | 0 | 1 | 1 | 1 |
6 | 0 | 1 | 1 | 0 |
5 | 0 | 1 | 0 | 1 |
4 | 0 | 1 | 0 | 0 |
3 | 0 | 0 | 1 | 1 |
2 | 0 | 0 | 1 | 0 |
1 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 |
15 | 1 | 1 | 1 | 1 |
C++// Symulacja rewersyjnego licznika synchronicznego // (C)2020 mgr Jerzy Wałaszek // I LO w Tarnowie #include <iostream> #include <iomanip> using namespace std; // Funkcje bramek int AND(int a, int b, int c = 1) { return (a & b & c); } int NOT(int a) { return a ^ 1; } // Funkcja przerzutnika JK int JK(int J, int K, int Q) { if((J == K) && J) return 1 - Q; if(J) return 1; if(K) return 0; return Q; } int main( ) { // Stany przerzutników int QA,QB,QC,QD; // Stany wyjściowe bramek int YB5,YB6; int i; // Zerujemy stany przerzutników QA = QB = QC = QD = 0; cout << " STAN | QD QC QB QA" << endl; for(i = 0; i < 18; i++) { // Wyniki // Obliczamy wartość w liczniku int v = QD * 8 + QC * 4 + QB * 2 + QA; cout << setw(4) << v << " | " << QD << " " << QC << " " << QB << " " << QA << endl; // Symulujemy sieć YB5 = AND(NOT(QA),NOT(QB)); YB6 = AND(NOT(QA),NOT(QB),NOT(QC)); QB = JK(NOT(QA),NOT(QA),QB); QA = JK(1,1,QA); QC = JK(YB5,YB5,QC); QD = JK(YB6,YB6,QD); } cout << endl; return 0; } |
Wynik: |
STAN | QD QC QB QA 0 | 0 0 0 0 15 | 1 1 1 1 14 | 1 1 1 0 13 | 1 1 0 1 12 | 1 1 0 0 11 | 1 0 1 1 10 | 1 0 1 0 9 | 1 0 0 1 8 | 1 0 0 0 7 | 0 1 1 1 6 | 0 1 1 0 5 | 0 1 0 1 4 | 0 1 0 0 3 | 0 0 1 1 2 | 0 0 1 0 1 | 0 0 0 1 0 | 0 0 0 0 15 | 1 1 1 1 |
Poniżej przedstawiamy symulację interaktywną takiej sieci. Stany wyjściowe licznika zmieniają się synchronicznie z opadającym zboczem sygnału zegarowego.
Symulator |
Wykorzystując opisaną metodę projektowania liczników synchronicznych przez określanie funkcji przełączających TX można konstruować dowolne układy sekwencyjne, tzn. takie, które w takt kolejnych impulsów zegarowych generują dowolne kody binarne. Aby to udowodnić, zaprojektujemy licznik zliczający w dół i w górę modulo 10 (jest to tzw. rewersyjny synchroniczny licznik BCD). Do sterowania kierunkiem zliczania będzie wymagany dodatkowy sygnał P. Umówmy się, iż dla P = 1 licznik zlicza w górę od 0 do 9, czyli jest normalnym licznikiem synchronicznym modulo 10, a dla P = 0 licznik staje się licznikiem rewersyjnym, zliczającym w dół od 9 do 0. Ułóżmy tabelkę stanów licznika wraz z sygnałami przełączającymi TX dla przerzutników:
|
|
Na podstawie tej tabelki wyznaczamy funkcje przełączające TX wykorzystując mapy Karnaugha.
Z tym sygnałem nie ma problemów, gdyż z prostej analizy tabelki wynika, iż:
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Podsumujmy:
Przystępujemy do budowy sieci logicznej licznika.
Napiszemy teraz program symulacji tego licznika w języku C++. Zaczynamy od numeracji elementów sieci logicznej:
Definiujemy połączenia:
W symulacji najpierw wyzerujemy wszystkie wyjścia QA, QB, QC i QD. Następnie ustawimy P na 1 i uruchomimy symulację sieci 12 razy. Wyzerujemy P i ponownie uruchomimy symulację 13 razy. Na wyjściu powinniśmy otrzymać następujące stany sygnałów:
STAN | P | QD | QC | QB | QA |
0 | 1 | 0 | 0 | 0 | 0 |
1 | 1 | 0 | 0 | 0 | 1 |
2 | 1 | 0 | 0 | 1 | 0 |
3 | 1 | 0 | 0 | 1 | 1 |
4 | 1 | 0 | 1 | 0 | 0 |
5 | 1 | 0 | 1 | 0 | 1 |
6 | 1 | 0 | 1 | 1 | 0 |
7 | 1 | 0 | 1 | 1 | 1 |
8 | 1 | 1 | 0 | 0 | 0 |
9 | 1 | 1 | 0 | 0 | 1 |
0 | 1 | 0 | 0 | 0 | 0 |
1 | 1 | 0 | 0 | 0 | 1 |
2 | 1 | 0 | 0 | 1 | 0 |
1 | 0 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 |
9 | 0 | 1 | 0 | 0 | 1 |
8 | 0 | 1 | 0 | 0 | 0 |
7 | 0 | 0 | 1 | 1 | 1 |
6 | 0 | 0 | 1 | 1 | 0 |
5 | 0 | 0 | 1 | 0 | 1 |
4 | 0 | 0 | 1 | 0 | 0 |
3 | 0 | 0 | 0 | 1 | 1 |
2 | 0 | 0 | 0 | 1 | 0 |
1 | 0 | 0 | 0 | 0 | 1 |
0 | 0 | 0 | 0 | 0 | 0 |
C++// Symulacja licznika modulo 10 zliczającego w górę i w dół // (C)2020 mgr Jerzy Wałaszek // I LO w Tarnowie #include <iostream> #include <iomanip> using namespace std; // Funkcje bramek int NAND(int a, int b, int c = 1) { return (a & b & c) ^ 1; } int NOT(int a) { return a ^ 1; } // Funkcja przerzutnika JK int JK(int J, int K, int Q) { if((J == K) && J) return 1 - Q; if(J) return 1; if(K) return 0; return Q; } int main( ) { // Stany przerzutników int QA,QB,QC,QD; // Stany wyjściowe bramek int YB5,YB6,YB7,YB8,YB9,YB10,YB11,YB12,YB13,YB14,YB15; int YB16,YB17,YB18,YB19,YB20; int i, P; // Zerujemy stany przerzutników QA = QB = QC = QD = 0; cout << " STAN | P QD QC QB QA" << endl; for(i = 0; i < 25; i++) { P = (i < 12); // Wyniki // Obliczamy wartość w liczniku int v = QD * 8 + QC * 4 + QB * 2 + QA; cout << setw(4) << v << " | " << P << " " << QD << " " << QC << " " << QB << " " << QA << endl; // Symulujemy sieć YB5 = NOT(P); YB6 = NAND(QB,QC); YB7 = NAND(QA,QB,P); YB8 = NAND(QC,NOT(QB)); YB9 = NAND(P,NOT(QD),QA); YB10 = NAND(NOT(QB),NOT(QC),NOT(QD)); YB11 = NAND(NOT(QD),YB6); YB12 = NAND(NOT(QD),YB10); YB13 = NAND(NOT(QD),YB8); YB14 = NAND(NOT(QA),YB5,YB10); YB15 = NAND(QA,P,YB11); YB16 = NAND(NOT(QA),YB5,YB12); YB17 = NAND(NOT(QA),YB5,YB13); YB18 = NAND(YB9,YB14); YB19 = NAND(YB15,YB16); YB20 = NAND(YB7,YB17); QA = JK(1,1,QA); QB = JK(YB18,YB18,QB); QC = JK(YB20,YB20,QC); QD = JK(YB19,YB19,QD); } cout << endl; return 0; } |
Wynik: |
STAN | P QD QC QB QA 0 | 1 0 0 0 0 1 | 1 0 0 0 1 2 | 1 0 0 1 0 3 | 1 0 0 1 1 4 | 1 0 1 0 0 5 | 1 0 1 0 1 6 | 1 0 1 1 0 7 | 1 0 1 1 1 8 | 1 1 0 0 0 9 | 1 1 0 0 1 0 | 1 0 0 0 0 1 | 1 0 0 0 1 2 | 0 0 0 1 0 1 | 0 0 0 0 1 0 | 0 0 0 0 0 9 | 0 1 0 0 1 8 | 0 1 0 0 0 7 | 0 0 1 1 1 6 | 0 0 1 1 0 5 | 0 0 1 0 1 4 | 0 0 1 0 0 3 | 0 0 0 1 1 2 | 0 0 0 1 0 1 | 0 0 0 0 1 0 | 0 0 0 0 0 |
Liczniki synchroniczne są produkowane w postaci gotowych układów cyfrowych. Poniżej przedstawiamy najpopularniejsze synchroniczne liczniki rewersyjne dwójkowe i binarne wchodzące w skład serii SN74.
SN74190 -
synchroniczny licznik rewersyjny BCD
SN74191
- synchroniczny licznik rewersyjny binarny
Układy scalone SN74190 i SN74191 są synchronicznymi licznikami rewersyjnymi pracującymi w kodach binarnym 8421 (SN74191) i BCD (SN74190). Liczniki posiadają wejścia programujące A,B,C i D, które można wykorzystywać do do ustalania wstępnego stanu liczników. Dane z tych wejść są asynchronicznie przepisywane do przerzutników J-K przy ustawieniu wejścia LOAD w stan 0.
Przerzutniki J-K tworzące licznik zmieniają swój stan przy przejściu sygnału zegarowego ze stanu niskiego w wysoki - zwróć uwagę na oznaczenie wejścia taktującego. Licznik zlicza impulsy zegarowe przy stanie niskim wejścia CTEN. Gdy wejście to przyjmie stan wysoki, zliczanie jest zablokowane. Kierunek zliczania określa stan wejścia D/U (ang. Down/Up). Przy stanie wysokim licznik zlicza w dół, a przy stanie niskim w górę.
Wyjścia RCO (ang. Ripple Carry Output - wyjście przeniesienia kaskadowego) oraz MAX/MIN umożliwiają podłączenie kolejnych scalonych liczników SN74190/1. Wyjście RCO generuje ujemny impuls o czasie trwania porównywalnym z ujemnym impulsem zegarowym przy powstaniu przeniesienia (zliczanie w górę) lub pożyczki (zliczanie w dół). Wyjście RCO łączy się z wejściem CTEN następnego licznika przy równoległym taktowaniu liczników sygnałem zegarowym lub z wejściem CLK następnego licznika. Wyjście MAX/MIN generuje dodatni impuls o czasie trwania równym pełnemu okresowi sygnału zegarowego przy zaistnieniu warunku przepełnienia lub niedopełnienia licznika. Wyjście to używane jest przez układy generacji równoległych przeniesień. Odpowiednie informacje na ten temat znajdziesz w materiałach producentów.
SN74192 -
synchroniczny licznik rewersyjny BCD
SN74193
- synchroniczny licznik rewersyjny binarny
Dwa kolejne układy SN74192 i SN74193 są również synchronicznymi licznikami rewersyjnymi BCD (SN74192) i binarnymi (SN74193). Od powyżej opisanych synchronicznych liczników rewersyjnych różnią się one sygnałami wejściowymi i wyjściowymi.
Licznik posiada asynchroniczne wejście CLR (ang. clear - czyść). Podanie stanu wysokiego na to wejście powoduje wyzerowanie wszystkich przerzutników.
Zamiast pojedynczego wejścia zegarowego, licznik posiada dwa wejścia UP (ang. w górę) i DOWN (ang. w dół). Impulsy zegarowe podawane na te wejścia odpowiednio powodują zliczanie w górę lub w dół. Nieużywane wejście zegarowe powinno być w stanie wysokim.
Dwa wyjścia CO (ang. Carry Output - wyjście przeniesienia) i BO (ang. Borrow Output - wyjście pożyczki) pozwalają w prosty sposób łączyć ze sobą kolejne dekady liczników. Wyjście CO łączymy z wejściem UP kolejnego licznika a wyjście BO z wejściem DOWN. Więcej informacji na temat tych układów znajdziesz w materiałach producentów.
Zespół Przedmiotowy Chemii-Fizyki-Informatyki w I Liceum Ogólnokształcącym im. Kazimierza Brodzińskiego w Tarnowie ul. Piłsudskiego 4 ©2024 mgr Jerzy Wałaszek |
Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone
pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email:
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.