Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz       Dalej  

obrazek

Autor artykułu: mgr Jerzy Wałaszek
Konsultacje: Wojciech Grodowski, mgr inż. Janusz Wałaszek

©2023 mgr Jerzy Wałaszek
I LO w Tarnowie

obrazek

Elementy

Układy kombinacyjne

SPIS TREŚCI
Podrozdziały

Co to jest układ kombinacyjny

Układ kombinacyjny (ang. combinational logic) jest siecią logiczną zbudowaną z bramek cyfrowych, która realizuje pewną funkcję logiczną. Stan wyjść tej sieci zależy tylko od stanu jej wejść:

obrazek

Układy kombinacyjne projektuje się za pomocą metod, które opisaliśmy w poprzednim rozdziale – szczególnie polecana jest tutaj metoda Karnaugha. W rozdziale omówimy podstawowe układy kombinacyjne, z którymi możesz się spotkać w technice cyfrowej. Wiele z nich produkowane jest w postaci gotowych do zastosowania układów scalonych.

Na początek:  podrozdziału   strony 

Bramka programowana

Jako pierwszy układ kombinacyjny omówimy tzw. bramkę programowaną. Jest to sieć logiczna, której funkcję wybieramy za pomocą sygnałów sterujących.

Bramka będzie posiadała dwa wejścia danych A, B, dwa wejścia programujące funkcję F1, F0 oraz jedno wyjście Y:

obrazek

W zależności od stanów na wejściach F1 i F0 bramka realizuje następujące funkcje logiczne:

F1 F0 Y
0 0 A AND B
0 1 A OR B
1 0 A NAND B
1 1 A NOR B

Układamy tabelkę stanów:

F1 F0 A B Y
0 0 0 0 0
0 0 0 1 0
0 0 1 0 0
0 0 1 1 1
0 1 0 0 0
0 1 0 1 1
0 1 1 0 1
0 1 1 1 1
1 0 0 0 1
1 0 0 1 1
1 0 1 0 1
1 0 1 1 0
1 1 0 0 1
1 1 0 1 0
1 1 1 0 0
1 1 1 1 0

Układamy mapę Karnaugha:

obrazek

Na podstawie mapy wyprowadzamy funkcję:

Funkcję upraszczamy:

Na podstawie funkcji tworzymy sieć logiczną:

obrazek

Testujemy się za pomocą programu w języku C:

obrazek
Bramka Typ Wejścia
b1 NOT F1
b2 NOT F0
b3 NOT A
b4 NOT B
b5 OR A,B
b6 AND A,B
b7 AND b5,F0
b8 OR b7,b6
b9 AND b8,b1
b10 OR b4,b3
b11 AND b4,b3
b12 AND b10,b2
b13 OR b12,b11
b14 AND b13,F1
b15 (Y) OR b9,b14
/*
** SYMULACJA SIECI LOGICZNEJ
** (C)2018 mgr Jerzy Wałaszek
*/

#include <stdio.h>
#include <stdlib.h>

int main()
{
    // Sygnały wejściowe sieci
    int F1,F0,A,B;
    // Sygnał wyjściowy sieci
    int Y;
    // Bramki
    int b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,
        b11,b12,b13,b14,b15;

    printf("Symulacja bramki programowanej\n");
    printf("------------------------------\n");
    printf("\n\n");
    printf("F1 F0  A  B  Y\n");
    printf("--------------\n");

    // Tworzymy środowisko pracy sieci
    for(F1 = 0; F1 < 2; F1++)          // Sygnał F1 0,1
        for(F0 = 0; F0 < 2; F0++)      // Sygnał F0 0,1
            for(A = 0; A < 2; A++)     // Sygnał A 0,1
                for(B = 0; B < 2; B++) // Sygnał B 0,1
                {
                    // Wyświetlamy sygnały wejściowe
                    printf(" %d  %d  %d  %d  ",F1,F0,A,B);

                    // Wyznaczamy wartości na wyjściach bramek sieci

                    b1  = !F1;
                    b2  = !F0;
                    b3  = !A;
                    b4  = !B;
                    b5  = A|B;
                    b6  = A&B;
                    b7  = b5&F0;
                    b8  = b7|b6;
                    b9  = b8&b1;
                    b10 = b4|b3;
                    b11 = b4&b3;
                    b12 = b10&b2;
                    b13 = b12|b11;
                    b14 = b13&F1;
                    Y = b15 = b9|b14;

                    // Wyświetlamy sygnał wyjściowy

                    printf("%d\n",Y);
                }
    printf("\n--- KONIEC SYMULACJI ---\n\n");
    return 0;
}

Tego typu układy znajdują się w mikrokontrolerach. Dzięki nim mikrokontroler potrafi wykonywać różne operacje nad danymi. Jeśli cię to zainteresowało, przeczytaj opis układu SN74181.

Na początek:  podrozdziału   strony 

Kodery

Kodery (ang. coders) lub transkodery (ang. transcoders) są układami kombinacyjnymi, które przekształcają jeden kod binarny w inny kod binarny.

Kod NBC

Kodów binarnych jest bardzo dużo. Podstawowym jest naturalny kod binarny, NBC (ang. Natural Binary Code). Koduje on za pomocą bitów wartości liczbowe. Realizuje się to przypisując bitom wagi będące kolejnymi potęgami liczby 2. Dlatego często oznacza się ten kod symbolem 8421 (8 = 23, 4 = 22, 2 = 21 i 1 = 20). Wygląda to następująco:

Mamy 4 bity, które ponumerujemy od prawej do lewej kolejno: b3, b2, b1, b0. Numerki bitów będziemy nazywali pozycjami. Bitom na kolejnych pozycjach przypiszemy wagi, które będą równe liczbie 2 podniesionej do potęgi o wykładniku równym numerowi pozycji:
Wagi 23=8 22=4 21=2 20=1
Bity b3 b2 b1 b0
Pozycje 3 2 1 0

Bity mogą znajdować się w dwóch stanach: 0 lub 1. Wartość kodowanej liczby obliczamy jako sumę wag pozycji pomnożonych przez wartość bitów, które znajdują się na tych pozycjach:

Na przykład, mamy bity kolejno: 0111.

Zatem kod 0111 reprezentuje w naszym systemie dziesiętnym liczbę 7.

Ponieważ kod NBC pojawia się bardzo często, warto nauczyć się na pamięć wartości kodów 4-bitowych NBC lub zapamiętać sposób obliczania wartości tych kodów:

b3 b2 b1 b0 SUMA W
23=8 22=4 21=2 20=1    
0 0 0 0 0 0
0 0 0 1 1 1
0 0 1 0 2 2
0 0 1 1 2 + 1 3
0 1 0 0 4 4
0 1 0 1 4 + 1 5
0 1 1 0 4 + 2 6
0 1 1 1 4 + 2 + 1 7
1 0 0 0 8 8
1 0 0 1 8 + 1 9
1 0 1 0 8 + 2 10
1 0 1 1 8 + 2 + 1 11
1 1 0 0 8 + 4 12
1 1 0 1 8 + 4 + 1 13
1 1 1 0 8 + 4 + 2 14
1 1 1 1 8 + 4 + 1 15

Zwróć uwagę na budowę kodu NBC w tabelce. Jest to schemat rekurencyjny, który łatwo da się zapamiętać.

Jeśli kod NBC jest jednobitowy, to otrzymujemy tylko dwa słowa kodowe:

b0 SUMA W
20=1    
0 0 0
1 1 1

Jeśli dodamy kolejny bit, to dopisujemy go ze stanem 0 do wszystkich słów kodowych poprzedniego kodu i dopisujemy go ze stanem 1 do wszystkich słów kodowych poprzedniego kodu:

b1 b0 SUMA W
21=2 20=1    
0 0 0 0
0 1 1 1
1 0 2 2
1 1 2 + 1 3

Dla kolejnego bitu postępujemy podobnie:

b2 b1 b0 SUMA W
22=4 21=2 20=1    
0 0 0 0 0
0 0 1 1 1
0 1 0 2 2
0 1 1 2 + 1 3
1 0 0 4 4
1 0 1 4 + 1 5
1 1 0 4 + 2 6
1 1 1 4 + 2 + 1 7

Kod NBC można rozszerzyć na dowolną liczbę bitów. Zapamiętaj jedynie, że wagi kolejnych pozycji są kolejnymi potęgami liczby 2 (wykładnik potęgi jest równy numerowi pozycji):

Wagi 24=16 23=8 22=4 21=2 20=1
Bity b4 b3 b2 b1 b0
Pozycje 4 3 2 1 0
Wagi 25=32 24=16 23=8 22=4 21=2 20=1
Bity b5 b4 b3 b2 b1 b0
Pozycje 5 4 3 2 1 0
Wagi 27=128 26=64 25=32 24=16 23=8 22=4 21=2 20=1
Bity b7 b6 b5 b4 b3 b2 b1 b0
Pozycje 7 6 5 4 3 2 1 0

Przy obliczaniu wartości sumujemy tylko wagi pozycji, dla których bit ma wartość 1.

Na przykład kod 11110111 reprezentuje liczbę:

128 64 32 16 8 4 2 1    
1 1 1 1 0 1 1 1 = 128 + 64 + 32 + 16 + 4 + 2 + 1 = 247

Kod BCD

Drugim popularnym kodem jest kod BCD (ang. Binary Coded Decimal = kod dziesiętny kodowany dwójkowo).

W kodzie BCD kodowane są cyfry dziesiętne liczby za pomocą 4-bitowych słówek w kodzie NBC. Brzmi zawile, lecz sprawa jest bardzo prosta. Zakodujmy w NBC liczbę dziesiętną 628. Każda cyfra dziesiętna potrzebuje 4 bitów, które przedstawiają jej wartość:

6 = 0110
2 = 0010
9 = 1001

I ostatecznie:

629(10) = 011000101001(NBC)

W drugą stronę jest również prosto. Na przykład kod BCD 100001110101 oznacza liczbę:

1000 0111 0101

1000 = 8
0111 = 7
0101 = 5

100001110101(NBC) = 875(10)

4-bitowe kody NBC mają wartości od 0 (0000) do 15 (1111). Kod BCD używa tylko wartości od 0 (0000) do 9 (1001). Pozostałe słówka kodu NBC (1010, 1011, 1100, 1101, 1110 i 1111) nie są używane (ponieważ nie reprezentują żadnej cyfry dziesiętnej).

Kody 1 z n

Są to kody n-bitowe. W słowie kodowym tylko jeden bit może przyjąć wartość 1. Pozostałe bity mają wartość 0. Położenie bitu 1 określa wartość słowa kodowego. Na przykład dla kodu 1 z 10 mamy:

1 z 10
0 1 2 3 4 5 6 7 8 9
1 0 0 0 0 0 0 0 0 0
0 1 0 0 0 0 0 0 0 0
0 0 1 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0
0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 1

Kod Gray'a

Kody Gray'a stosowane są przy pomiarach położenia lub kąta obrotu. Zaletą ich jest to, iż kolejne wyrazy różnią się od siebie tylko jednym bitem. Minimalizuje to ewentualne przekłamania pomiaru. Aby pokazać ci, o co tutaj chodzi, wyobraź sobie, iż masz układ pomiarowy, który zwraca wynik w postaci kodu NBC. Kolejne położenia są kodowane 3 bitami:

000 001 010 011 100 101 110 111
0 1 2 3 4 5 6 7

Jednakże z powodu niedokładności czujnika bity kodu nie zmieniają się jednocześnie, tylko mają pewne "luzy". Położenie przechodzi z 3 (011) na 4 (100). Jeśli zmiana bitów nie będzie jednoczesna, to na wyjściu czujnika chwilowo mogą w zasadzie pojawić się wszystkie pozostałe kody, np. kod 111 (pierwszy bit zmienił się na 1, lecz dwa pozostałe wciąż mają starą wartość). Otrzymamy przekłamanie położenia. Oczywiście można temu zapobiec za pomocą odpowiedniego oprogramowania, niemniej problem pozostaje. Kod Gray'a eliminuje tę niedogodność, sprowadzając ewentualne przekłamanie do 1 bitu, czyli położenia sąsiedniego.

Kodów Gray'a jest wiele. Podam tutaj kod Gray'a odzwierciedlony binarnie, zwany również kodem refleksyjnym.

Bity w kodzie Gray'a nie posiadają wag jak w kodzie NBC. Należy skonstruować słowa kodu. Robimy to rekurencyjnie, poczynając od słówek jednobitowych i dodając kolejne bity, aż otrzymamy kod Gray'a o założonej liczbie bitów.

Kod 1-bitowy Gray'a:

b0 W
0 0
1 1

Aby utworzyć kod o zwiększonej o 1 liczbie bitów, do słówek kodu dopisujemy na początku nowy bit o stanie 1, po czym odwracamy kolejność słówek i dopisujemy do nich bit o stanie 1:

Kod 2-bitowy Gray'a:

b1 b0 W
0 0 0
0 1 1
1 1 2
1 0 3

Dalej postępujemy podobnie:

Kod 3-bitowy Gray'a:

b2 b1 b0 W
0 0 0 0
0 0 1 1
0 1 1 2
0 1 0 3
1 1 0 4
1 1 1 5
1 0 1 6
1 0 0 7

Kod 4-bitowy Gray'a:

b3 b2 b1 b0 W
0 0 0 0 0
0 0 0 1 1
0 0 1 1 2
0 0 1 0 3
0 1 1 0 4
0 1 1 1 5
0 1 0 1 6
0 1 0 0 7
1 1 0 0 8
1 1 0 1 9
1 1 1 1 10
1 1 1 0 11
1 0 1 0 12
1 0 1 1 13
1 0 0 1 14
1 0 0 0 15

Zwróć uwagę na jedną z cech kodu Gray'a: pierwszy wyraz (0,00,000,0000...) i ostatni (1,10,100,1000...) również różnią się jednym bitem. Z tego powodu kod ten jest cykliczny.

Kod wyświetlacza 7-segmentowego

Do wyświetlania cyfr w technice cyfrowej używa się powszechnie wyświetlaczy 7-segmentowych (ang. 7-segment display).

obrazek

Segmenty wyświetlacza są diodami LED lub ciekłymi kryształami. Numeracja segmentów jest następująca:

obrazek  

Wyświetlacze te umożliwiają wyświetlanie cyfr 0...9 oraz kilku liter alfabetu:

obrazek

Kod wyświetlacza dla cyfr jest następujący (1 oznacza zapalony segment, 0 oznacza zgaszony segment):

Segmenty Cyfra
a b c d e f g
1 1 1 1 1 1 0 0
0 1 1 0 0 0 0 1
1 1 0 1 1 0 1 2
1 1 1 1 0 0 1 3
0 1 1 0 0 1 1 4
1 0 1 1 0 1 1 5
1 0 1 1 1 1 1 6
1 1 1 0 0 1 0 7
1 1 1 1 1 1 1 8
1 1 1 1 0 1 1 9

Transkoder kodu 421 na kod 1 z 8

W ramach ćwiczeń przedstawimy teraz sposób projektowania dwóch transkoderów.

Transkoder posiada 3 wejścia D4, D2, D1 oraz 8 wyjść 0, 1, 2, 3, 4, 5, 6, 7 i 8. Na wejścia podajemy 3-bitowy kod NBC. Na wyjściach otrzymujemy 8-bitowy kod 1 z 8.

obrazek  
Wejścia Wyjścia
D4 D2 D1 0 1 2 3 4 5 6 7
0 0 0 1 0 0 0 0 0 0 0
0 0 1 0 1 0 0 0 0 0 0
0 1 0 0 0 1 0 0 0 0 0
0 1 1 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 1 0 0 0
1 0 1 0 0 0 0 0 1 0 0
1 1 0 0 0 0 0 0 0 1 0
1 1 1 0 0 0 0 0 0 0 1

Tą sieć rozwiążemy metodą algebraiczną. Wyznaczamy funkcje logiczne poszczególnych wyjść:

Budujemy sieć logiczną:

obrazek

Symulacja sieci w języku C:

obrazek
Bramka Typ Wejścia
b1 NOT D4
b2 NOT D2
b3 NOT D1
b4 (0) AND3 b1,b2,b3
b5 (1) AND3 b1,b2,D1
b6 (2)

AND3

b1,D2,b3
b7 (3) AND3 b1,D2,D1
b8 (4) AND3 D4,b2,b3
b9 (5) AND3 D4,b2,D1
b10 (6) AND3 D4,D2,b3
b11 (7) AND3 D4,D2,D1
/*
** SYMULACJA SIECI LOGICZNEJ
** (C)2018 mgr Jerzy Wałaszek
*/

#include <stdio.h>
#include <stdlib.h>

int main()
{
    // Sygnały wejściowe sieci
    int D1,D2,D4;
    // Sygnały wyjściowe sieci
    int O0,O1,O2,O3,O4,O5,O6,O7;
    // Bramki
    int b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11;

    printf("Symulacja transkodera 421 na 1 z 8\n");
    printf("----------------------------------\n");
    printf("\n\n");
    printf("D4 D2 D1  0 1 2 3 4 5 6 7\n");
    printf("-------------------------\n");

    // Tworzymy środowisko pracy sieci
    for(D4 = 0; D4 < 2; D4++)         // sygnał D4 0,1
        for(D2 = 0; D2 < 2; D2++)     // sygnał D2 0,1
            for(D1 = 0; D1 < 2; D1++) // sygnał D1 0,1
            {
                // Wyświetlamy sygnały wejściowe D4, D2 i D1
                printf(" %d  %d  %d  ",D4,D2,D1);

                // Wyznaczamy wartości na wyjściach bramek sieci

                b1 = !D4;
                b2 = !D2;
                b3 = !D1;
                O0 = b4  = b1&b2&b3;
                O1 = b5  = b1&b2&D1;
                O2 = b6  = b1&D2&b3;
                O3 = b7  = b1&D2&D1;
                O4 = b8  = D4&b2&b3;
                O5 = b9  = D4&b2&D1;
                O6 = b10 = D4&D2&b3;
                O7 = b11 = D4&D2&D1;

                // Wyświetlamy sygnały wyjściowe

                printf("%d %d %d %d %d %d %d %d\n",O0,O1,O2,O3,O4,O5,O6,O7);
            }
    printf("\n--- KONIEC SYMULACJI ---\n\n");
    return 0;
}

Transkoder BCD na kod wskaźnika 7-segmentowego

Transkoder posiada 4 wejścia danych D8, D4, D2, D1 oraz 7 wyjść a,b,c,d,e,f,g. Na wejście podajemy cyfrę dziesiętną w kodzie BCD, na wyjściu otrzymujemy kod sterujący świeceniem segmentów we wskaźniku.

obrazek obrazek
Cyfra Wejścia Wyjścia
D8 D4 D2 D1 a b c d e f g
0 0 0 0 0 1 1 1 1 1 1 0
1 0 0 0 1 0 1 1 0 0 0 0
2 0 0 1 0 1 1 0 1 1 0 1
3 0 0 1 1 1 1 1 1 0 0 1
4 0 1 0 0 0 1 1 0 0 1 1
5 0 1 0 1 1 0 1 1 0 1 1
6 0 1 1 0 1 0 1 1 1 1 1
7 0 1 1 1 1 1 1 0 0 1 0
8 1 0 0 0 1 1 1 1 1 1 1
9 1 0 0 1 1 1 1 1 0 1 1
  1 0 1 0 X X X X X X X
  1 0 1 1 X X X X X X X
  1 1 0 0 X X X X X X X
  1 1 0 1 X X X X X X X
  1 1 1 0 X X X X X X X
  1 1 1 1 X X X X X X X

Zadanie rozwiążemy za pomocą map Karnaugha, wyznaczając funkcje logiczne dla każdego sygnału wyjściowego.

a:
obrazek
b:
obrazek
c:
obrazek
d:
obrazek
e:
obrazek
f:
obrazek
  g:
obrazek
obrazek
 

Tworzymy sieć logiczną:

obrazek

Testujemy sieć za pomocą programu w języku C:

obrazek
Bramka Typ Wejścia
b1 NOT D8
b2 NOT D4
b3 NOT D2
b4 NOT D1
b5 AND b1,b2,b4
b6 AND D4,D1
b7(a) OR b5,D2,D8,b6
b8 AND b3,b4
b9 AND D2,D1
b10(b) OR b8,b2,b9
b11(c) OR b3,D1,D4
b12 OR b4,D2
b13 AND D2,b4
b14 AND D4,b3,D1
b15 AND b12,b2
b16(d) OR b15,b13,b14,D8
b17 AND b2,b4
b18(e) OR b13,b17
b19(f) OR b8,D4,D8
b20 AND b2,D2
b21 AND D4,b3
b22(g) OR b20,b13,b21,D8
/*
** SYMULACJA SIECI LOGICZNEJ
** (C)2018 mgr Jerzy Wałaszek
*/

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int main()
{
    // Sygnały wejściowe sieci
    int D1,D2,D4,D8;
    // Sygnały wyjściowe sieci
    int a,b,c,d,e,f,g;
    // Bramki
    int b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,
        b11,b12,b13,b14,b15,b16,b17,b18,
        b19,b20,b21,b22;

    setlocale(LC_ALL,"");

    printf("Symulacja transkodera BCD na kod wskaźnika 7-segmentowego\n");
    printf("---------------------------------------------------------\n");
    printf("\n\n");
    printf("D8 D4 D2 D1  a b c d e f g\n");
    printf("--------------------------\n");

    // Tworzymy środowisko pracy sieci
    for(D8 = 0; D8 < 2; D8++)             // Sygnał D8 0,1
        for(D4 = 0; D4 < 2; D4++)         // Sygnał D4 0,1
            for(D2 = 0; D2 < 2; D2++)     // Sygnał D2 0,1
                for(D1 = 0; D1 < 2; D1++) // Sygnał D1 0,1
                {
                    // Wyświetlamy sygnały wejściowe D7, D4, D2 i D1
                    printf(" %d  %d  %d  %d  ",D8,D4,D2,D1);

                    // Wyznaczamy wartości na wyjściach bramek sieci

                    b1  = !D8;
                    b2  = !D4;
                    b3  = !D2;
                    b4  = !D1;
                    b5  = b1&b2&b4;
                    b6  = D4&D1;
                    a   = b7 = b5|D2|D8|b6;
                    b8  = b3&b4;
                    b9  = D2&D1;
                    b   = b10 = b8|b2|b9;
                    c   = b11 = b3|D1|D4;
                    b12 = b4|D2;
                    b13 = D2&b4;
                    b14 = D4&b3&D1;
                    b15 = b12&b2;
                    d   = b16 = b15|b13|b14|D8;
                    b17 = b2&b4;
                    e   = b18 = b13|b17;
                    f   = b19 = b8|D4|D8;
                    b20 = b2&D2;
                    b21 = D4&b3;
                    g   = b22 = b20|b13|b21|D8;

                    // Wyświetlamy sygnały wyjściowe

                    printf("%d %d %d %d %d %d %d\n",a,b,c,d,e,f,g);
                }
    printf("\n--- KONIEC SYMULACJI ---\n\n");
    return 0;
}

Tego typu transkodery są produkowane w postaci pojedynczych układów scalonych:

Na początek:  podrozdziału   strony 

Multipleksery

Multiplekser (ang. multiplexer, mux) jest układem posiadającym n wejść danych D, m wejść wybierających A oraz jedno wyjście Y:

obrazek

Działanie układu jest bardzo proste:

Na wejścia wybierające A podajemy adres dwójkowy jednego z wejść D. Wtedy na wyjściu Y pojawia się stan wybranego wejścia.

Dla przykładu zaprojektujmy multiplekser dwuwejściowy:

obrazek  
S A B Y
0 0 X 0
0 1 X 1
1 X 0 0
1 X 1 1

Jeśli na wejściu wybierającym S panuje stan niski 0, to na wyjściu Y mamy stan wejścia A. Jeśli zmienimy stan wejścia wybierającego S na wysoki 1, to na wyjściu Y pojawi się stan wejścia B.

Układamy mapę Karnaugha dla wyjścia Y:

obrazek

Funkcja logiczna:

Sieć logiczna:

obrazek

Jako ćwiczenie sprawdź działanie tej sieci programem w języku C.

Multipleksery są produkowane w postaci gotowych układów scalonych:

Multipleksery stosuje się często do odczytu stanu wielu linii wejścia, np. z klawiatury. Pozwalają one zaoszczędzić wiele portów mikrokontrolera. Np. układ SN74150 jest multiplekserem 16 kanałowym:

obrazek

Do wejść E podłączasz sygnały, które chcesz odczytywać, następnie na wejściach A...D (D zawiera najstarszy bit adresu) umieszczasz adres wejścia E i stan wejścia odczytujesz z wyjścia W, tutaj będzie zanegowany. Wejście G należy połączyć z masą, aby układ był uaktywniony. W sumie potrzebujesz tylko 5 portów do sterowania tym układem, a bez niego potrzebowałbyś 16 portów. Widzisz zysk?

Na początek:  podrozdziału   strony 

Demultipleksery

Demultiplekser jest układem o odwrotnej funkcji do multipleksera. Posiada jedno wejście danych D, m wejść wybierających A oraz n wyjść Y:

obrazek

Zasada działania jest następująca:

Na wejściach wybierających A umieszczamy dwójkową liczbę określającą jedno z wyjść Y. Wtedy na wybranym wyjściu pojawia się stan z wejścia D. Na pozostałych wyjściach Y panuje stan nieaktywny.

Zaprojektujmy 2-kanałowy demultiplekser:

obrazek  
S D Y1 Y0
0 0 0 0
0 1 0 1
1 0 0 0
1 1 1 0

Jeśli na wejściu wybierającym S panuje stan niski 0, to na wyjściu Y0 jest stan wejścia D. Jeśli S przyjmuje stan wysoki 1, to na wyjściu Y1 pojawi się stan wejścia D. Na wyjściu niewybranym panuje stan nieaktywny 0.

Tworzymy mapy Karnaugha dla obu wyjść:

Y0:
obrazek
  Y1:
obrazek
 

Sieć logiczna:

obrazek

Sprawdź działanie tej sieci za pomocą programu w języku C.

Przemysł elektroniczny produkuje scalone demultipleksery w różnych konfiguracjach, np.:

Na początek:  podrozdziału   strony 

Komparatory

Komparator jest układem, który porównuje ze sobą dwa słowa binarne. Porównanie może ograniczać się jedynie do stwierdzenia, iż oba słowa są takie same lub różne. Istnieją również komparatory, które traktują porównywane słowa jako liczby. W takim przypadku generowana jest dodatkowo informacja o  tym, która z tych liczb jest większa, a która mniejsza:

obrazek

Działanie jest następujące:

Na wejściach A i B umieszczamy n-bitowe liczby dwójkowe.

Na wyjściu A < B otrzymujemy stan 1, jeśli liczba A jest mniejsza od liczby B. W przeciwnym razie na wyjściu tym jest stan 0.

Na wyjściu A = B otrzymujemy stan 1, jeśli liczba A jest równa liczbie B. W przeciwnym razie na wyjściu tym jest stan 0.

Na wyjściu A > B otrzymujemy stan 1, jeśli liczba A jest większa od liczby B. W przeciwnym razie na wyjściu tym jest stan 0.

Dla przykładu zaprojektujmy komparator 2-bitowy:

obrazek  
A1 A0 B1 B0 A<B A=B A>B
0 0 0 0 0 1 0
0 0 0 1 1 0 0
0 0 1 0 1 0 0
0 0 1 1 1 0 0
0 1 0 0 0 0 1
0 1 0 1 0 1 0
0 1 1 0 1 0 0
0 1 1 1 1 0 0
1 0 0 0 0 0 1
1 0 0 1 0 0 1
1 0 1 0 0 1 0
1 0 1 1 1 0 0
1 1 0 0 0 0 1
1 1 0 1 0 0 1
1 1 1 0 0 0 1
1 1 1 1 0 1 0

Układamy mapy Karnaugha dla poszczególnych wyjść komparatora:

A<B
obrazek
A=B
obrazek
A>B
obrazek

Sieć logiczna komparatora:

obrazek

Test sieci za pomocą programu w języku C:

obrazek
Bramka Typ Wejścia
b1 NOT A1
b2 NOT A0
b3 NOT B1
b4 NOT B0
b5 OR b1,B1
b6 AND b1,B1
b7 AND b5,b2,B0
b8 (A<B) OR b7,b6
b9 AND b2,b4
b10 AND A0,B0
b11 AND b1,b3
b12 AND A1,B1
b13 OR b9,b10
b14 OR b11,b12
b15 (A=B) AND b13,b14
b16 OR b3,A1
b17 AND A1,b3
b18 AND b16,A0,b4
b19 (A>B) OR b18,b17
/*
** SYMULACJA SIECI LOGICZNEJ
** (C)2018 mgr Jerzy Wałaszek
*/

#include <stdio.h>
#include <stdlib.h>

int main()
{
    // Sygnały wejściowe sieci
    int A1,A0,B1,B0;
    // Sygnał wyjściowy sieci
    int ALB,AEB,AGB;
    // Bramki
    int b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,
        b11,b12,b13,b14,b15,b16,b17,b18,b19;

    printf("Symulacja komparatora 2-bitowego\n");
    printf("--------------------------------\n");
    printf("\n\n");
    printf("A1 A0 B1 B0 A<B A=B A>B\n");
    printf("-----------------------\n");

    // Tworzymy środowisko pracy sieci
    for(A1 = 0; A1 < 2; A1++)             // Sygnał A1 0,1
        for(A0 = 0; A0 < 2; A0++)         // Sygnał A0 0,1
            for(B1 = 0; B1 < 2; B1++)     // Sygnał B1 0,1
                for(B0 = 0; B0 < 2; B0++) // Sygnał B0 0,1
                {
                    // Wyświetlamy sygnały wejściowe
                    printf(" %d  %d  %d  %d  ",A1,A0,B1,B0);

                    // Wyznaczamy wartości na wyjściach bramek sieci

                    b1 = !A1;
                    b2 = !A0;
                    b3 = !B1;
                    b4 = !B0;
                    b5 = b1|B1;
                    b6 = b1&B1;
                    b7 = b5&b2&B0;
                    ALB = b8 = b7|b6;
                    b9 = b2&b4;
                    b10 = A0&B0;
                    b11 = b1&b3;
                    b12 = A1&B1;
                    b13 = b9|b10;
                    b14 = b11|b12;
                    AEB = b15 = b13&b14;
                    b16 = b3|A1;
                    b17 = A1&b3;
                    b18 = b16&A0&b4;
                    AGB = b19 = b18|b17;

                    // Wyświetlamy sygnały wyjściowe

                    printf("%d   %d   %d\n",ALB,AEB,AGB);
                }
    printf("\n--- KONIEC SYMULACJI ---\n\n");
    return 0;
}

Produkowany jest układ  SN7485, który zawiera komparator 4-bitowy:

obrazek

Oprócz wejść A i B komparator posiada również wejścia wyników porównania z poprzedniej kaskady. Umożliwia to tworzenie komparatorów liczb binarnych o większej niż 4 ilości bitów:

obrazek

obrazek

Na początek:  podrozdziału   strony 

Sumatory

Sumator (ang. adder) jest układem arytmetycznym, który wykonuje operację dodawania dwójkowego. Tabliczka dodawania w systemie dwójkowym jest bardzo prosta:
0 + 0 =  0
0 + 1 =  1
1 + 0 =  1
1 + 1 = 10

Zasady dodawania są identyczne jak w naszym systemie dziesiętnym. Dla przykładu dodajmy dwie liczby dwójkowe 1101 i 1011. Zapisujemy je słupku i ostatnią podkreślamy:

  1 1 0 1
+ 1 0 1 1
         

Dodawanie rozpoczynamy od ostatnich cyfr obu liczb i posuwamy się w lewą stronę, dodając do siebie kolejne cyfry. Jeśli wynik jest dwucyfrowy (1 + 1 = 10), to pod kreską zapisujemy ostatnią cyfrę, a pierwszą cyfrę zapisujemy ponad kolejną cyfra pierwszej liczby. Jest to tzw. przeniesienie (ang. carry), które musi zostać dodane do wyniku sumowania cyfr następnej kolumny.

Sumujemy ostatnie dwie cyfry: 1 + 1 = 0 i 1 przeniesienia

      1  
  1 1 0 1
+ 1 0 1 1
        0

Sumujemy kolejne cyfry: 0 + 1 = 1 + przeniesienie = 0 i 1 przeniesienia

    1 1  
  1 1 0 1
+ 1 0 1 1
      0 0

Sumujemy kolejne cyfry: 1 + 0 = 1 + przeniesienie = 0 i 1 przeniesienia

  1 1 1  
  1 1 0 1
+ 1 0 1 1
    0 0 0

Sumujemy kolejne cyfry: 1 + 1 = 0 i 1 przeniesienia + przeniesienie = 1 i 1 przeniesienia

1 1 1 1  
  1 1 0 1
+ 1 0 1 1
  1 0 0 0

Cyfry obu liczb skończyły się, ale pozostało nam przeniesienie równe 1. Przepisujemy je do wyniku (możemy potraktować tę kolumnę tak, jakby obie liczby miały tu cyfry zero):

  1 1 1 1  
  0 1 1 0 1
+ 0 1 0 1 1
  1 1 0 0 0

Dostajemy wynik: 1101 + 1011 = 11000. Sprawdźmy, czy wynik jest poprawny:

1101 = 8 + 4 + 1 = 13
1011 = 8 + 2 + 1 = 11
11000 = 16 + 8 = 24

Nie może być inaczej – wynik dodawania nie zależy od systemu liczbowego, w którym wykonujemy dodawanie, lecz od wartości dodawanych liczb.

Dla przykładu zaprojektujemy sumator jednobitowy:

obrazek  
Ci A B Y Co
0 0 0 0 0
0 0 1 1 0
0 1 0 1 0
0 1 1 0 1
1 0 0 1 0
1 0 1 0 1
1 1 0 0 1
1 1 1 1 1

Ci jest przeniesieniem z poprzedniej kaskady sumującej. Pozwala to łączyć sumatory w szereg i wykonywać sumowanie dla liczb wielobitowych.

A i B to sumowane bity.
Y jest wynikiem sumowania.
Co jest wyjściem przeniesienia.

Układamy mapy Karnaugha dla Y i Co:

Y
obrazek
Co
obrazek

Budujemy sieć:

obrazek

Testujemy sieć za pomocą programu w języku C:

obrazek
Bramka Typ Wejścia
b1 NOT Ci
b2 NOT A
b3 NOT B
b4 AND b2,B
b5 AND A,b3
b6 OR b4,b5
b7 AND b6,b1
b8 AND b2,b3
b9 AND A,B
b10 OR b8,b9
b11 AND b10,Ci
b12 (Y) OR b7,b11
b13 OR B,A
b14 AND b13,Ci
b15 (Co) OR b9,b14
/*
** SYMULACJA SIECI LOGICZNEJ
** (C)2018 mgr Jerzy Wałaszek
*/

#include <stdio.h>
#include <stdlib.h>

int main()
{
    // Sygnały wejściowe sieci
    int A,B,Ci;
    // Sygnały wyjściowe sieci
    int Co,Y;
    // Bramki
    int b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,
        b11,b12,b13,b14,b15;

    printf("Symulacja sumatora 1-bitowego\n");
    printf("-----------------------------\n");
    printf("\n\n");
    printf("Ci A B Y Co\n");
    printf("-----------------------\n");

    // Tworzymy środowisko pracy sieci
    for(Ci = 0; Ci < 2; Ci++)          // Sygnał Ci 0,1
        for(A = 0; A < 2; A++)         // Sygnał A 0,1
            for(B = 0; B < 2; B++)     // Sygnał B 0,1
            {
                // Wyświetlamy sygnały wejściowe
                printf(" %d %d %d ",Ci,A,B);

                // Wyznaczamy wartości na wyjściach bramek sieci

                b1 = !Ci;
                b2 = !A;
                b3 = !B;
                b4 = b2&B;
                b5 = A&b3;
                b6 = b4|b5;
                b7 = b6&b1;
                b8 = b2&b3;
                b9 = A&B;
                b10 = b8|b9;
                b11 = b10&Ci;
                Y = b12 = b7|b11;
                b13 = B|A;
                b14 = b13&Ci;
                Co = b15 = b9|b14;

                // Wyświetlamy sygnały wyjściowe

                printf("%d %d\n",Y,Co);
            }
    printf("\n--- KONIEC SYMULACJI ---\n\n");
    return 0;
}

W handlu można spotkać następujące sumatory scalone:

Więcej na ten temat znajdziesz w osobnym artykule "Bit w zastosowaniach".

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
©2023 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.