Как заставить машину считать при помощи транзисторов?
Продолжение. Часть 1 Часть 2
В предыдущих частях я рассказал о полупроводниковых приборах, диоде и транзисторе, благодаря которым человечество смогло сменить технологический уклад и войти в компьютерную эру.
Однако, описывая устройство транзистора, я так и не коснулся того, каким образом из этого относительно простого устройства можно сделать компьютер. Что же, сейчас я постараюсь объяснить.
Двоичная логика
Думаю, что ни для кого, кто не прогуливал информатику в школе, не будет секретом, что в компьютерах используется двоичная система счисления, и счёт идёт следующим образом: 0, 1, 10, 11, 100, 101, 110, 111, 1000, и т .д. Когда мы имеем дело с простой электрической цепью, нам доступно, по сути, всего два состояния: напряжения в цепи нет, и напряжение в цепи есть, которые можно обозначить за 0 и 1, соответственно. Люди привыкли считать в десятичной системе счисления (наверное, потому, что у большинства из нас по 10 пальцев на руках). Машину тоже можно научить считать в десятичной системе, однако это не очень практично, так как нам понадобится различать 10 различных состояний электрической цепи, что значительно усложнит конструкцию. Но и двух состояний, как показывает практика, достаточно практически для любой вычислительной задачи.
Для тех, кто не читал предыдущие посты в этой серии, я напомню, что транзистор может работать как запорный кран на водопроводной трубе – включая и выключая напряжение на базе, мы можем либо «открывать кран» (пропускать ток через транзистор), либо «запирать» его. Соответственно, если абстрагироваться от технических деталей, то, подав «единицу» на базу, мы получим «единицу» и на выходе.
Логические вентили
Сразу оговорюсь – одну и ту же схему можно построить, используя несколько способов, здесь предложен лишь один из вариантов.
Здесь и далее, условно мы считаем поданное напряжение за 1 (или ИСТИНА), отсутствие напряжение – 0 (ЛОЖЬ).
Сила транзисторов приходит с их числом. Давайте посмотрим на следующую схему:
На данной схеме, если мы подадим на вход (In) 1, электричество потечёт от коллектора на эмиттер (сверху вниз). Так как ток всегда идёт по линии наименьшего сопротивления, на выходе будет 0. Если на входе будет 0, то транзистор предотвратит ток от коллектора на эмиттер, и на выходе (Out) мы получим 1.
Эта схема является логическим инвертором (превращает 0 в 1 или 1 в 0), представляя собой логическую операцию НЕ (NOT). В логических схемах, по стандарту ANSI 91-1984, она обозначается так:
(есть и другие стандарты обозначений, но в подавляющем большинстве случаев, если вы будете дополнительно изучать эту тему, вы будете встречать именно такие символы).
Забегая вперёд, скажу, что для каждой операции существует так называемая «таблица истинности» (truth table), которая показывает, как данная операция изменяет входящий сигнал. Входящие сигналы обычно обозначают буквами латинского алфавита по порядку (A, B и т. д.) Для операции NOT существует всего 1 входящий сигнал А:
А = 0 → 1
А = 1 → 0
Рассмотрим пример посложнее:
Здесь, если вы уже хоть чуточку разбираетесь в том, что уже было сказано, можно увидеть, что на выходе (Out) мы получим 1 только если на входах A и B тоже будут единицы, а в любом другом случае, на выходе будет 0. Мы получили логический вентиль И (AND), который обозначается так:
Вентиль И имеет следующую таблицу истинности:
A = 0, B = 0 → 0
A = 0, B = 1 → 0
A = 1, B = 0 → 0
A = 1, B = 1 → 1
Для полноты комплекта набора базовых логических вентилей, рассмотрим ещё и вентиль ИЛИ (OR):
Данный вентиль позволяет получить 1 на выходе, если хотя бы один из входов (или сразу оба) на вход получают 1.
У вентиля ИЛИ, как легко предположить имеется следующая таблица истинности:
A = 0, B = 0 → 0
A = 0, B = 1 → 1
A = 1, B = 0 → 1
A = 1, B = 1 → 1
Есть и другие вентили, например XOR, NAND, NOR, и т. д. С целью экономии места и времени, я пропущу их описание, остановлюсь подробнее только на одном из них, под названием NAND (НЕ-И). Дело в том, что при помощи вентилей этого типа, мы можем сконструировать вентиль любого другого типа. Это было математически доказано ещё в далёком 1913 году американским логиком Генри Шеффером. Любая комбинация логических вентилей может быть реализована при помощи вентилей типа НЕ-И или НЕ-ИЛИ.
Почему NAND?
На самом деле всё просто. Вентили NAND быстрее. Есть такой термин «логические трудозатраты». Это параметр, который характеризует временную задержку в логических элементах. На практике при построении интегральных схем чаще всего используются вентили типа NAND.
Как можно уяснить уже из названия, NAND (Not AND) или НЕ-И представляет собой вентиль И с инверсией результата. То есть, он всегда на выходе имеет 1, кроме того случая, когда единица подаётся на оба входа одновременно:
A = 0, B = 0 → 1
A = 0, B = 1 → 1
A = 1, B = 0 → 1
A = 1, B = 1 → 0
На этой схеме представлены варианты изготовления вентилей НЕ (NOT), И (AND), ИЛИ (OR) и исключающего ИЛИ (XOR) только при помощи вентилей типа NAND:
Так как же компьютер считает?
Посмотрите на схему, она состоит из вентиля XOR (исключающее ИЛИ) и вентиля AND:
В качестве разминки для ума, попробуйте сами составить таблицу истинности для этой схемы. Если у вас всё получилось, то вы должны прийти к следующей логике:
A = 0, B = 0 → S = 0, C = 0
A = 0, B = 1 → S = 1, C = 0
A = 1, B = 0 → S = 1, C = 0
A = 1, B = 1 → S = 0, C = 1
Или, если хочется поиграться самому, вот ссылка на работающую симуляцию:https://simulator.io/board/mgWFjacWov/1
(Щёлкайте по сигналам - 0 и 1, чтобы зажечь или погасить лампочку).
Ура! Мы научились складывать 1 и 1! И действительно, мы получили устройство, способное сложить значения двух бит (которые подаются на входы A и B) и получить результат на выходе S (Sum – сумма). 0 + 0 = 0, 0 + 1 = 1, 1 + 0 = 1. Что же происходит, когда складывается 1 + 1 – в этом случае вывод S обнуляется, но зато единица подаётся на вывод C (Carry – перенос). Это сигнал о том, что у нас возникло переполнение, и нам необходим следующий разряд для записи числа 2 (или 10 в двоичном представлении).
Описанная схема называется «полусумматором» (half-adder).
Если мы захотим перерисовать эту схему, используя только вентили типа NAND, то получим вот это:
Очевидно, что полусумматор может работать только с одним разрядом. Теперь давайте совместим два полусумматора вместе:
Симуляция: https://simulator.io/board/2Cf3xg9qcE/1
Заметьте, слева у нас появился ещё один ввод (который обозначен Carry-in). Построим для этой схемы таблицу истинности:
Обратите внимание, как, в зависимости от ввода Carry-In меняется результат. Если на этот ввод подавать состояние вывода переполнения/переноса (C-out) с соседнего сумматора, то будет понятно, что, расположив 8 таких сумматоров в цепочку, мы можем заставить компьютер складывать числа ёмкостью до 8 бит (то есть, в пределах от 0 до 255 или от -127 до 128). Ниже представлена цепочка из 4 полных сумматоров, позволяющих складывать числа до 4 бит:
Cовременные компьютеры работают с шинами в 64 бит, а иногда и в 128 бит. Но мы можем масштабировать подобную схему, в принципе, до любой разрядности.
Со сложением определились. А как быть с вычитанием?
Да, в общем-то, ничего сложного, как вы поняли, в вычитании нет. Вот схема вычитателя, состоящая из двух идентичных половинок. Как видно, мы решаем проблему просто добавлением вентилей НЕ:
И таблица истинности для данной схемы:
Чтобы поупражняться самостоятельно, можете взять симуляцию схемы сумматора (https://simulator.io/board/2Cf3xg9qcE/1), и, добавив вентили НЕ (NOT) превратить его в вычитатель.
Расположив сумматоры параллельно, и добавив на один вход вентиль типа НЕ, мы получим схему, способную вычитать одно двоичное число из другого. Но, как вы уже заметили, сумматор и вычитатель, по сути, являются одной и той же схемой, сама операция зависит лишь от инверсии одного из сигналов. И действительно, мы можем построить универсальную логическую машину, позволяющую как складывать, так и вычитать числа при помощи такой схемы (для 4 бит):
Симуляция: https://simulator.io/board/Kx7SAVz4P6/1
Последний вывод Cout на симуляции обозначает переполнение (лампочка красного цвета).
Мы добавили на входы битовых сумматоров вентили исключающего ИЛИ (XOR), которые выдают единицу только в том случае, если на его входы подаются разные сигналы. Когда M = 0, вентили выдадут значение сигналов B0-B3, когда M = 1, они инвертируют входящие сигналы. Таким образом, когда сигнал М = 1, данная схема становится вычитателем, а когда М = 0 – сумматором.
Надеюсь, этот пост дал вам первичное представление о том, как научить машину считать при помощи транзисторов. В следующем посте я расскажу о том, как производят интегральные схемы, на которых располагаются миллиарды транзисторов, и насколько малых размеров вообще возможно сделать транзистор.