Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz       Dalej  

Autor artykułu: mgr Jerzy Wałaszek

©2020 mgr Jerzy Wałaszek
I LO w Tarnowie

Bity w elektronice

Licznik rewersyjny

SPIS TREŚCI
Podrozdziały

Opis

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:

Na początek:  podrozdziału   strony 

Synchroniczny licznik rewersyjny

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
Na początek:  podrozdziału   strony 

Licznik modulo 10 zliczający w górę i w dół

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:

P = 1
Kolejne stany licznika Funkcje przełączające
Stan QD QC QB QA TD TC TB TA
0 0 0 0 0 0 0 0 1
1 0 0 0 1 0 0 1 1
2 0 0 1 0 0 0 0 1
3 0 0 1 1 0 1 1 1
4 0 1 0 0 0 0 0 1
5 0 1 0 1 0 0 1 1
6 0 1 1 0 0 0 0 1
7 0 1 1 1 1 1 1 1
8 1 0 0 0 0 0 0 1
9 1 0 0 1 1 0 0 1
0 0 0 0 0  
P = 0
Kolejne stany licznika Funkcje przełączające
Stan QD QC QB QA TD TC TB TA
0 0 0 0 0 1 0 0 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
0 0 0 0 0  

Na podstawie tej tabelki wyznaczamy funkcje przełączające TX wykorzystując mapy Karnaugha.

Sygnał TA

Z tym sygnałem nie ma problemów, gdyż z prostej analizy tabelki wynika, iż:

Sygnał TB

Obszar TB1
obrazek 00 01 11 10
000 0 0 0 1
001 1 0 0 1
011 X X X X
010 1 0 X X
110 0 0 X X
111 X X X X
101 0 1 1 0
100 0 1 1 0
Obszar TB2
obrazek 00 01 11 10
000 0 0 0 1
001 1 0 0 1
011 X X X X
010 1 0 X X
110 0 0 X X
111 X X X X
101 0 1 1 0
100 0 1 1 0
Obszar TB3
obrazek 00 01 11 10
000 0 0 0 1
001 1 0 0 1
011 X X X X
010 1 0 X X
110 0 0 X X
111 X X X X
101 0 1 1 0
100 0 1 1 0
Obszar TB4
obrazek 00 01 11 10
000 0 0 0 1
001 1 0 0 1
011 X X X X
010 1 0 X X
110 0 0 X X
111 X X X X
101 0 1 1 0
100 0 1 1 0
         

Sygnał TC

Obszar TC1
obrazek 00 01 11 10
000 0 0 0 0
001 1 0 0 0
011 X X X X
010 1 0 X X
110 0 0 X X
111 X X X X
101 0 0 1 0
100 0 0 1 0
Obszar TC1
obrazek 00 01 11 10
000 0 0 0 0
001 1 0 0 0
011 X X X X
010 1 0 X X
110 0 0 X X
111 X X X X
101 0 0 1 0
100 0 0 1 0
Obszar TC1
obrazek 00 01 11 10
000 0 0 0 0
001 1 0 0 0
011 X X X X
010 1 0 X X
110 0 0 X X
111 X X X X
101 0 0 1 0
100 0 0 1 0
         

Sygnał TD

Obszar TD1
obrazek 00 01 11 10
000 1 0 0 0
001 0 0 0 0
011 X X X X
010 1 0 X X
110 0 1 X X
111 X X X X
101 0 0 1 0
100 0 0 0 0
Obszar TD2
obrazek 00 01 11 10
000 1 0 0 0
001 0 0 0 0
011 X X X X
010 1 0 X X
110 0 1 X X
111 X X X X
101 0 0 1 0
100 0 0 0 0
Obszar TD3
obrazek 00 01 11 10
000 1 0 0 0
001 0 0 0 0
011 X X X X
010 1 0 X X
110 0 1 X X
111 X X X X
101 0 0 1 0
100 0 0 0 0
Obszar TD4
obrazek 00 01 11 10
000 1 0 0 0
001 0 0 0 0
011 X X X X
010 1 0 X X
110 0 1 X X
111 X X X X
101 0 0 1 0
100 0 0 0 0
         

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:

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)
QB = JK(YB18,YB18)
QC = JK(YB20,YB20)
QD = JK(YB19,YB19)

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
obrazek

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
obrazek

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.

Na początek:  podrozdziału   strony 

Zespół Przedmiotowy
Chemii-Fizyki-Informatyki

w I Liceum Ogólnokształcącym
im. Kazimierza Brodzińskiego
w Tarnowie
ul. Piłsudskiego 4
©2020 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: i-lo@eduinf.waw.pl

Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.
Informacje dodatkowe.