Примерное оглавление всей книги тут.
Возможно, в вашем браузере с первого раза не будут правильно отображаться формулы. Если так, попробуйте перезагрузит страницу — на моем компьютере этот фокус работает

Пара слов о том, что мы будем изучать.


На фотографии ниже представлена электронная схема в том масштабе, на котором мы привыкли их видеть невооруженным взглядом. Множество всяких квадратных и не очень блочков с торчащими из них проволочными ножками (пинами), сеть проводящих металлических дорожек, к которым своими ножками припаяны блочки, покрывающая плату затейливым узором. Современные цифровые схемы на кристалле концептуально представляют из себя примерно тоже самое, однако их строение не получится разглядеть без микроскопа.


Какая-то плата. Источник фото ukrmarket.net

В общих словах работу цифровой схемы можно описать так: дорожки соединяют выходные пины одних блочков с входными пинами других. С некоторой периодичностью по дорожкам распространяются электрические импульсы от выходных пинов, где они, собственно, и зарождаются, к входным. Обычно каждый такой импульс кодирует одно из двух значений: логические ноль или логическую единицу. Значение импульсов, которые за текущий такт породит блочок на своих выходных пинах, зависят от конструкции блочка и того, какими были значения импульсов, пришедших на его входные пины за все предыдущие время.

Конечно, чтобы уметь проектировать микросхему и потом быть в состоянии рассуждать о ее работе, нам потребуется какая-то более-менее точная теория. Созданием такой теории мы сейчас и займемся. Если кто-то из читателей переживает, что он не знает или забыл, где у транзистора база, а где эмиттер, я спешу его успокоить – эти знания нам даже не понадобятся. Рассуждения в книге будут относиться к концептуально более простому и высокому уровню: уровню логических блоков.

Базовые концепции.


Формально объектом нашего изучения будут всякого рода логические схемы. Теорию логических схем мы построим на 5 основных понятиях:

  1. понятии логического блока (регистра и функциональных блоков вроде “и”, “или” “не”…);
  2. порта данных;
  3. понятии проводника данных (шины);
  4. понятии внутреннего состояния блока или схемы;
  5. и понятии дискретного времени.

Логические блоки будут олицетворять функциональные устройства, расположенные на плате (или кристалле), порты данных – металлические ножки этих устройств, шинам будут соответствовать металлические проводящие дорожки. С понятием внутреннего состояния мы познакомимся позже. Дискретное время – должно быть привычной концепцией, если читатель знаком с программированием.

Изложение теории формальных логических схем для большей понятности разбито на два этапа. На первом этапе мы изучим ту ее ограниченную часть, в которой «строительными кирпичиками» логических схем могут выступать только блоки строго ограниченного набора типов. Язык этой теории во многом аналогичен ассемблеру и другим языкам программирования, в которых любые программы строятся из заведомо ограниченного числа команд. Рассмотрев несколько примеров логических схем, построенных на языке ограниченной теории, мы увидим, что подобно ассемблерным программам такой подход страдает проблемой избыточного дублирования. Типичной будет ситуация, когда некоторые участки схемы многократно в ней повторяются. Впоследствии мы преодолеем проблему дублирования, добавив в нашу теорию возможность определять в ней новые составные блоки, что по духу аналогично переходу от ассемблера к процедурным языкам программирования.

Аксиомы для общих понятий.


Время.


Самая обычная идея о дискретных шагах времени, которые мы буден называть тактами.

Время и все вместе с ним меняется скачками. Все интересующие нас свойства формального времени содержатся в следующей аксиоме:

T) Множество моментов времени может быть отождествлено с натуральным рядом {0, 1, 2, 3, … }.

Поскольку множество натуральных чисел естественным образом упорядочено, мы будем предполагать что этому же порядку подчинено и множество моментов времени, позволяя себе, например, говорить о следующем и предыдущем моментах времени. В качестве синонима для термина “момент времени” мы также будем употреблять слово “такт”.

Порты.


Порт – это формализация понятия групп проволочных ножек, объединенных неким общим функциональным предназначением (тематических групп пинов устройства). На схеме порты обозначены в виде полукругов. Закрашенные полукруги – это порты выхода, пустые полукруги – порты входа. (рис 1)

рис 1 Схема логического «следует».

Мы будем делить порты на внешние и внутренние.

Внутренние принадлежат логическим блокам, находящимся внутри схемы, то есть тем блокам, из которых эта схема составлена. При графическом способе описания полукруги, обозначающие внутренние порты, все находятся на границах блоков.

Внешние порты, отождествляют собой порты выхода и входа тех устройств, которые остались за пределами рассмотрения схемы, но могут обмениваться с ней данными (Как, например, по отношению к материнской плате компьютера внешними можно считать клавиатуру, монитор и принтер). Внешние порты не принадлежат ни одному блоку внутри схемы и являются атрибутами схемы “в целом”. При графическом способе описания полукруги, обозначающие внешние порты, изображаются примыкающими к прямоугольной рамке, очерченной вокруг схемы.

Следующие 7 аксиом задают формальные свойства, которыми должен обладать всякий порт:

P1) Свойство иметь размерность(количество бит) и тип(входной/выходной,
внешний/внутренний — всего 4 возможных комбинации).


P2) Свойство каждому внутреннему порту принадлежать единственному логическому блоку
внутри схемы, а каждому внешнему порту не принадлежать ни одному из них.


P3) Свойство, обязывающие каждый входной порт быть присоединенным в точности к одной шине, а каждый выходной порт – не более чем к одной шине.

P4) Свойство, обязующее порт принимать какое-то определенное значение на каждом такте. Значениями порта размерности n должны быть двоичные слова длины n.

P5) В любой из тактов значение всякого входного порта равно значению в присоединенной
к нему шине.


P6) В каждый из тактов значение всякого внешнего выходного порта должно быть задано
вешними условиями.


P7) Значение каждого внутреннего выходного порта на каждом такте полностью определяется типом логического блока, которому принадлежит порт, и тем, каковы на этом такте внутреннее состояние блока и значения его входных портов.

Нам потребуется именовать порты. Внешним портам мы будем давать отдельные «собственные» имена. Что касается внутренних портов, то наш способ их называния будет похож на способ обращения к полю конкретного объекта какого-нибудь класса, принятый в объектно-ориентированных языках программирования. Каждый блок внутри схемы будет относится к какому-то определенному типу (скажем “OR”) и вместе с тем иметь «собственное» имя (скажем $or\_0$). Чтобы назвать конкретный порт, мы будем указывать собственное имя блока, а затем через точку то универсальное имя, которое этот порт имеет во всех блоках данного типа (например, $or\_0.arg1$ ).

При графическом способе описания имя внутреннего порта мы будем помещать внутри блока рядом с обозначающим этот порт полукружком. Когда это необходимо, сразу за именем в квадратных скобках мы будем указывать размерность порта.

Пусть $Pname$ – имя конкретного порта, значение этого порта на временном шаге $k$ мы будем обозначать как $Pname(k)$, в свою очередь $i$-тый бит того же значения — как $Pname[i](k)$, или просто $Pname[i]$, если из контекста понятно, о каком именно шаге идет речь.

Внутренние состояние блока и схемы.


Читатель, знакомый с понятием конечного автомата, в аксиоме P7) легко угадает требование всякому логическому блоку представлять из себя конечный автомат. Если же понятие конечного автомата для вас ново, не переживайте: идея внутреннего состояния логического блока станет для вас тривиальной, как только мы дойдем до описания работы элементарных блоков.

Описание формальных свойств внутреннего состояния содержаться в следующих двух аксиомах:

S1) Множество внутренних состояний S всякого логического блока включает в себя только конечное число элементов.

S2) Внутреннее состояние, в котором окажется логический блок в следующий момент времени, однозначно определяется типом блока, тем, в каком состоянии этот блок находится в данный момент, и тем, какие в данный момент значения принимают его входные порты.

Шины.


Говоря по секрету, понятие шины для создаваемой нами теории совсем не обязательное – можно, и в некоторых случаях даже удобнее, обойтись без него. Содержание всех аксиом абстрактной шины, которые вы найдете ниже, призвано отразить одну очень простую идею: каждому входному порту должен быть назначен в точности один выходной порт той же размерности. На каждом такте входной порт копирует в себя значение из назначенного ему выходного порта.

Несмотря на то, что шина – не обязательное и даже слегка загромождающее теорию понятие, мы это понятие все-таки в нее добавим. Причин для этого две:

Первая – это то, что в нашем мире абстрактному понятию шины соответствуют реальные провода, кабели, группы проводящих дорожек на печатной плате или полупроводниковом кристалле. Вторая причина кроется в исключительном удобстве графического изображения того, какой именно выходной порт какому входному назначен. Тонкая (возможно разветвленная) линия, обозначающая шину, соединяет выходной порт со всеми теми входными портами, которым он назначен.

Места разветвления шин по традиции обозначаются жирной точкой. Если точки в месте пересечения линий нет, то, как правило, эти линии относятся к двум разным шинам.

Определение абстрактной шины мы подчиним 5-ти аксиомам:

B1) Каждая шина обладает определенной размерностью (числом бит), размерность шины и
размерность любого порта, с которым соединена эта шина, должны быть одинаковыми.


B2) Среди портов, с которыми соединена шина должен найтись в точности один выходной порт.

B3) Среди портов, с которыми соединена шина должен найтись по крайней мере один входной порт.

B4) На каждом такте определено значение в шине, представляющее из себя некоторое двоичное слово, длина этого слова совпадает с размерностью шины.

B5) В любой из тактов значение в шине равно значению того единственного выходного порта, с которым эта шина соединена.

Концы шин, сообщения и сигналы.


О том единственном выходном порте, к которому присоединена шина, мы будем иногда говорить, что он является ее «началом» или, что он «стоит в ее начале». Обо всех соединенных с шиной входных портах мы будем говорить, как о «концах» этой шины. Из аксиом B2 и B3 следует, что у каждой шины есть по крайней мере один «конец» и в точности одно «начало».

Поскольку на каждом такте значение шины совпадает со значением порта, стоящего в ее начале и, следовательно, ему же оказываются равны значения всех портов, расположенных на ее концах, то неформально мы можем сказать, что это общее для всех значение – есть сообщение или сигнал, распространяющийся на данном такте от начала шины к ее концам. В этом же смысле мы будем употреблять выражение, что некоторое сообщение или сигнал «поступил» из шины на некоторый входной (поэтому расположенный на ее конце) порт, с которым соединена эта шина. Следует заметить, что понятие «распространяющегося сообщения» не входит в набор основных понятий нашей теории: читателю следует воспринимать его просто как удобную форму речи.

Пример: на рисунке 1 запечатлено, как сообщение “1” распространяется от порта … к портам … и ….

Определение элементарных блоков.


Элементарные логические блоки – последний тип примитивных “кирпичиков”, из которых будут строится логические схемы, а в последствие и более сложные логические блоки. В рамках нашей теории элементарные блоки не имеют «внутренней структуры», однако имеют строго задекларированное поведение. Все принадлежащие элементарным блокам порты, как входные, так и выходные, являются внутренними.

Все многообразие типов элементарных блоков удобно разделить на 5 групп:
  1. Блоки константных функций: «0» и «1».
  2. Блоки логических функций: «AND», «OR», «NOT» «+».
  3. Прямой и обратный однобитный двухходовый мультиплексоры.
  4. Блоки прямого отображения:
    • блок прямой и обратной конкатенации,
    • блок фиксированной перестановки (в том числе блок инверсии).
  5. Однобитные регистры: базовый регистр, регистры сочетающие функции запрета записи и/или сброса.

Теперь по порядку о каждом группе.

Блоки-константы.


E1) Блоки «0» и «1» реализуют одноименные константные функции. Блоки этих типов не имеют портов входа и каждый имеет по одному однобитному порту выхода. Со сменой тактов значения их портов выхода остаются всегда неизменными: односимвольным словом “0” для блока «0» и односимвольным словом “1” для блока «1».

Блоки элементарных логических функций.


E2) Блоки типов «AND» и «OR» (рис 2) реализуют одноименные логические функции. Экземпляры этих типов имеют каждый по два однобитных порта входа, именуемые как $arg1$ и $arg2$, и по одному однобитному порту выхода $r$.

Если интерпретировать однобитное слово “0”, как логическую «ложь», а однобитное слово “1” – как логическую «истина», то правило задающее значение выходных портов можно записать так:

Для блоков, принадлежащих типу «AND»: (для всякого $k$) $r(k) = arg1(k)\ AND \ arg2(k)$.

Для блоков, принадлежащих типу «OR»: (для всякого $k$): $r(k) = arg1(k)\ \ OR \ \ arg2(k)$.

Аналогично блоки, принадлежащие типу «NOT» имеют только один порт входа arg и один порт выхода r. Значения порта выхода устанавливаются правилом $r(k) = NOT \ arg(k)$.

Блоки типа «+» реализуют сложение двух однобитных чисел, поступивших на их входные порты arg1 и arg2. Значение однобитного выходного порта r устанавливается равным младшему биту этой суммы, а старший бит “передается” в выходной порт c:

$r(k) = arg1(k) + arg2(k)\ (mod 2)$;
$c(k) = arg1(k) \ \ AND \ \ arg2(k)$;


рис 2 Блоки «и», «или», «не», и «+»

Мультиплексоры.


E3) Двухходовые мультиплексоры выполняют важную роль: с их помощью можно управлять направлением, в котором далее будет распространяться сообщение или сигнал.

Прямой однобитный двухходовый мультиплексор F_MUX (рис 3a) через значение его входного порта $comm$ позволяет выбрать, будет ли значение на его «выходе» $out$ копией сообщения, пришедшего на входной порт $in1$, или же копией сообщения, пришедшего на входной порт $in2$. Вот точное описание его поведения:

Если $comm(k) = “0”$, то
$out(k) = in1(k)$;
иначе
$out(k) = in2(k)$;

Обратный однобитный двухходовый мультиплексор действует в некотором смысле наоборот (рис 3b). Подавая подходящий управляющий сигнал на вход $comm$, вы тем самым можете выбрать, у какого из двух его выходных портов $out1$ или $out2$ значение на текущем такте станет копией сигнала, пришедшего на вход $in$, а у какого это значение окажется словом “0”. Точное правило для обратного мультиплексора выглядит так:

Если $comm(k) = “0”$, то
$out1(k) = in(k)$ и
$out2(k) = “0”$;
иначе
$out1(k) = “0”$ и
$out2(k) = in(k)$.

(рис 3а и 3b прямого и обратного мультиплексоров)

Блоки прямого отображения.


Блоки прямого отображения осуществляют безусловное копирование некоторых разрядов портов входа в некоторые разряды портов выхода. Такие зависимости между сигналами на входах и выходах замечательны тем, что с технической точки зрения их реализация не требуют вообще никаких физических устройств.

Чтобы понять, чем такие блоки физически являются, представьте, что перед вами находится множество проводков или проводящих дорожек, которые пересекают некую условную черту справа налево. Вообще говоря, справа и слева от условной черты эти множество проводков может быть по-разному разбито на группы (шины) и внутри этих групп иметь свою собственную нумерацию (двоичные разряды в значениях этих шин). Суть блока любого прямого отображения состоит в том, чтобы установить соответствие между этими двумя способами разбиения и нумерации. Блоки прямого отображения – вообще говоря не необходимый элемент нашей теории, ведь, по существу, с передаваемым по проводам сигналом они ничего не делают. Без них можно было и обойтись, но с ними теория и графическое представление схем выглядят намного опрятнее. В качестве элементарных удобно взять следующие:

E4) Блок прямой конкатенации (рис 4a). Этот тип блоков является параметрическим, параметрами для него служат количество и разрядности входных портов $in1, in2, … in\_q$. Блок прямой конкатенации $*(n_1,n_2,…,n_q)$ объединяет $q$ шин размерностей $n_1,n_2,…,n_q$ в одну шину размерности $n_1+n_2+⋯+n_q$, сохраняя общий порядок нумерации битов. Это означает, что если $u_1$ – значение $n_1$-битного пота $in1$, $u_2$ — значение $n_2$-битного пота $in2$, … $u_q$ — значение $n_q$-битного пота $in\_q$, то значением $(n_1+n_2+⋯+n_q)$ -битного порта $out$ будет слов $w$, являющееся конкатенацией слов $u_1,u_2,…u_q$ (например, если $q=2, n_1=3, n_2=4, u="001”, v=”0011”$, то $w=”0010011”$). Более формально блок прямой конкатенации с параметрами $(n_1,n_2,…,n_q)$ можно описать так:

$out[0](k) = in1[0](k)$;
*
*
*
$out[n_1 - 1](k) = in1[n_1 - 1](k)$;
$out[n_1+0](k) = in2[0](k)$;
*
*
*
$out[n_1+n_2-1](k) = in2[n_1-1](k)$;
*
*
*
$out[n_1+n_2+⋯+n_q-1](k) = inq[n_q-1](k)$;

рис 4 Блоки прямой и обратной конкатенации

E5) Действия блоков обратной конкатенации прямо противоположно действиям блоков прямой конкатенации (рис 4b). Этот тип блоков тоже параметрический. Блок обратной конкатенации $* ̅(n_1,n_2,…,n_q)$ разделяет шину размерности $n_1+n_2+⋯+n_q$ на $q$ шин размерностей $n_1,n_2,…,n_q$ соответственно, сохраняя при этом общий порядок битов. Формальное определение его поведения таково:

$out1[0](k) = in[0](k)$;
*
*
*
$out1[n_1 - 1](k) = in[n_1 - 1](k)$;
$out2[0](k) = in[n_1+0](k)$;
*
*
*
$out2[n_2-1](k) = in[n_1+n_2-1](k)$;
*
*
*
$outq[n_q-1](k) = in[n_1+n_2+⋯+n_q-1](k)$;

E6) Пусть $n$ – какое-то натуральное число, $p: \{0,1,…,n-1\} ->\{0,1,…,n-1\}$ – произвольная перестановка n-элементного множества. Каждой такой перестановке мы сопоставим блок $π(p)$ с одним $n$-битным портом входа и одни $n$-битным портом выхода. Действия блока $π(p)$ будут заключается в том, чтобы подействовать перестановкой p на номера разрядов входного сигнала:

$out[p(0)](k) = in[0](k)$;
$out[p(1)](k) = in[1](k)$;
*
*
*
$out[p(n-1)](k) = in[n-1](k)$;

E7) В частности, если $p$ – это инверсия n-элементного множества ( $p(i) = n-i-1$ ), то блок $π(p)$ мы будем обозначать как INV($n$) и именовать блоком инверсии.

Класс функциональных блоков.


Должно быть читатель обратил внимание, что все перечисленные выше элементарные блоки обладали сходной чертой: значения их выходных портов на момент любого такта выражались как функции от значений их входных портов, принимаемыми ими на том же самом такте. Логические блоки, отвечающие этому свойству, мы будем называть функциональными.

Можно считать, что функциональные блоки вообще не имеют внутреннего состояния, или же, что они обладают единственным состоянием, в котором все время и пребывают. Следующее семейство блоков радикально нарушает эту традицию.

Регистры.


Значение выходного порта регистра зависит от значений на его входах не на прямую, а опосредованно, через значение его внутреннего состояния s. Значения состояния однобитного регистра являются двоичные слова “0” или “1”. Значение выходного порта регистра на текущем такте всегда совпадает со значением его внутреннего состояния. В свою очередь значения, которые принимают порты входа регистра на текущем такте, полностью определяют то, каким окажется состояние этого регистра в следующий такт времени. На практике при включении устройства, то есть в нулевой такт времени, внутреннее состояние регистра самопроизвольно может стать равным “0” или “1”. В нашей теории мы будем считать, что установка состояний регистров в нулевой момент происходит случайно.

E8) Простой однобитный регистр имеет один однобитный порт входа $in$ и один однобитный порт выхода $out$. Значение внутреннего состояния простого регистра в следующий такт времени всегда является копией того значения, которое его порта входа принял на текущем такте. Более формально описание поведения простого регистра выглядит так:

$s(0) = random$;
$s(k+1) = in(k)$;
$out(k)=s(k)$;

E9) Однобитный регистр с опциональной записью имеет два однобитных входных порта $enable$ и $in$ и единственный однобитный порт выхода $out$. Отличие этого типа регистров от предыдущего состоит в том, что значение внутреннего состояния у этого типа регистров меняется только при условии, что на их порт $enable$ подана «единица»:

$s(0) = random$;

если $enable(k)=1$, то
$s(k+1) = in(k)$,
иначе
$s(k+1) = s(k)$;

$out(k)=s(k)$;

E10) Однобитный регистр со сбросом имеет два однобитных входных порта $reset$ и $in$ и единственный однобитный порт выхода $out$. Работает также, как и простой регистр с тем лишь отличием, что его состояние на следующем такте обязательно становится равным “0”, если на текущем значение порта $reset$ есть “1”:

$s(0) = random$;

если $reset(k)=”1”$, то
$s(k+1) = “0”$,
иначе`
$s(k+1) = in(k)$;

$out(k)=s(k)$;


рис 5 Почти все типы регистров

E11) Однобитный регистр со сбросом и опциональной записью сочетает в себе продвинутые возможности регистров двух предыдущих типов. Такой регистр включает в себя три однобитных порта входа $reset$, $enable$ и $in$ и один однобитный порт выхода $out$. Сброс превалирует над разрешением записи: если на порт reset подана “1”, то состояние на следующем такте будет иметь значение “0” в любом случае.

Формальное описание поведения регистров со сбросом и опциональной записью таково:

$s(0) = random$;

если $reset(k)=”1”$, то
$s(k+1) = “0”$,
иначе
{
если $enable(k)=”1”$, то
$s(k+1) = in(k)$,
иначе
$s(k+1) = s(k)$;
};
$out(k) = s(k)$;

Свойства элементарных схем.


Определение.


Собственно элементарными мы будем называть логические схемы, в состав которых входят блоки исключительно элементарных типов. Поскольку пока мы договорились в нашей теории рассматривать только такие схемы, добавим к ней надлежащую аксиому:

C*) Всякий логический блок должен принадлежать одному из типов, описанных в E1) – E11).

Звездочка означает, что содержание аксиомы изменится, когда мы расширим теорию, определив в ней понятие составного логического блока.

Чтение элементарных схем.


Пусть мы имеем дело со схемой, включающей в себя только элементарные блоки. Предположим, нам известно, какое на каждом такте значение примет каждый ее внешний выходной порт, а также то, в каком внутреннем состоянии в нулевой момент времени будет находится каждый из ее регистров. Возникает естественная задача: найти значения остальных портов схемы и состояния ее регистров в каждый из последующих моментов времени. Ниже изложен метод ее решения.

Метод прямого потока данных.


Попробуем действовать конструктивно и наиболее очевидным образом. Первое, что стоило бы в таком случае сделать, — это попытаться установить, какие значения будут иметь в схеме ее порты и шины на нулевом такте времени.

Описанный далее процесс представляет собой повторяющуюся последовательность шагов. На каждом шаге мы будем выбирать и приписывать значения лишь тем шинам и портам, для которых сложившиеся к тому шагу условия и аксиомные требования будут указывать на единственно возможное для них значение.

Значения портов выхода блоков-констант «0» и «1», если последние присутствуют в схеме, известны всегда (аксиома E1). Значения внешних выходных портов мы знаем по условию (аксиома P6). Также по условию на момент нулевого такта нам известны внутренние состояния всех регистров схемы, поэтому благодаря аксиомам E8-E11 мы без труда можем найти значения, которые на нулевом такте примут их выходные порты.

Определение процедуры:

Внешние выходные порты схемы, выходные порты блоков-констант и выходные порты регистров объявим нулевым фронтом распространения сигнала $F_0$.

С помощью индукции определим $n$-тый фронт распространения сигнала $F_n$.

  1. Пусть все фронты $F_0,… F_{(n-1)}$ уже построены, а значения всем входящим в их состав портам уже приписаны.
  2. В качестве базы для построения $F_n$ возьмем пустое множество.
  3. Каждой шине, имеющей своим началом выходной порт из фронта $F_{(n-1)}$, припишем то же самое значение, что было ранее приписано этому порту (необходимость соответствовать аксиоме B5).
  4. Выделим в схеме каждый логический блок, у которого по крайней мере один его входной порт соединен шиной с выходным портом, находящимся в составе фронта $F_{(n-1)}$, а все остальные входные порты этого блока соединены шинами с какими-либо выходными портами, находящимися в составе любого из уже построенных фронтов $F_0, … , F_{(n-1)}$.

    рис 6, поясняющий это сложное предложение.
  5. Каждому входному порту каждого выделенного блока припишем значение, равное значению того единственного выходного порта, с которым этот входной порт соединен общей шиной (необходимость соответствовать аксиомам B5 и P5). Поскольку согласно пункту 4) упомянутый выходной порт принадлежит одному из фронтов $F_0, … , F_{(n-1)}$, то по индуктивному предположению (пункт 1) ) его значение нам уже известно.
  6. Все входные порты выделенных блоков добавим к множеству $F_n$.
  7. Если выделенный блок имеет тип функционального (не является регистром), то по значениям, приписанным его входным портам, вычислим значения всех его выходных портов (необходимость соответствовать аксиоме P7), после чего их тоже добавим к фронту $F_n$.
  8. Если какой-либо внешний входной порт соединен общей шиной с выходным портом, находящимся в составе фронта $F_{(n-1)}$, то припишем первому из них значение последнего (необходимость соответствовать аксиомам B5 и P5), а затем добавим первый к фронту $F_n$.
  9. На этом $n$-тый фронт распространения сигнала $F_n$ считается построенным.

Конец процедуры.

Стоит обратить внимание на несколько важных моментов, присутствующих в описанном только что алгоритме.

*) Поскольку множества $F_0,… F_n$ конструируются непересекающимися (индукция из пунктов 4, 5 и 9), то за всю процедуру их построения каждому порту и каждой шине схемы значения будут приписаны не более одного раза.

**) Если вдруг очередной фронт $F_n$ по завершению своего строительства оказался пуст (в нем не содержится ни одного порта схемы), то и все последующие фронты $F_m$$m>n$ также будут пусты (непосредственно следует из пунктов 4, 5 и 9). Таким образом на практике построение фронтов стоит продолжать только до тех пор, пока очередной из них не окажется пустым.

Распространение метода на всю временную шкалу.


Предположим теперь, что при некотором n каждый присутствующий в схеме порт окажется включенным в какой-нибудь из построенных фронтов распространения сигнала $F_0,… F_n$.

Такое предположение в том числе означает, что всем портам и шинам схемы в процессе построения фронтов были приписаны некоторые значения. Индукцией по номеру фронта несложно показать (сделайте это), что исходя их начальных условий эти значения были единственными не вступающими в противоречия с аксиомами P5-P7, B4-B5, E1-E11. Поскольку условиями исходной задачи предполагалось, что рассматриваемая схема, взятая с некоторыми значениями на ее портах и шинах в каждый такт, — вместе удовлетворяют всей аксиоматике, то из предыдущего замечания следует, что на нулевом такте метод прямого распространения данных действительно позволил эти значения установить (как единственные, которые могли бы удовлетворить аксиомам теории). Отыщем значения портов и шин схемы на всех последующих тактах.

И так, значения всех портов схемы на нулевом такте мы уже знаем. В том числе мы знаем, какие значения в этот момент времени будут у всех портов входа каждого из ее регистров, следовательно ( аксиомы E8-E11) нам не составит труда установить и то, в какое внутреннее состояние придут все эти регистры в следующий такт времени.

Последнее замечание показывает, что если метод прямого распространения данных достиг успеха на нулевом такте, то создается ситуация, когда его можно вновь применить, но уже на такте под номером “1”. Действительно: состояния, в которых будут находится регистры на первом такте, мы только что вычислили, а значения внешних портов выхода в каждый такт времени известны нам по условию.

Кроме того, индукцией по $k$ легко показать (сделайте это), что $k$-тые фронты распространения сигнала, построенные для нулевого и для первого тактов, будут в точности друг с другом совпадать, то есть состоять из одних и тех же портов схемы. В частности, как и на нулевом такте, построенные для первого такта фронты с нулевого по $n$-тый вместе будут содержать в себе все порты схемы. Следовательно, и на первом такте метод прямого распространения данных сделает известными значения всех шин, портов и то, в каком состоянии окажутся регистры такт спустя.

Прибегнув к математической индукции, мы без труда распространим предыдущие рассуждения на все такты, доказав тем самым следующую простую

Лемма 1: если метод прямого распространения данных позволяет вычислить значения всех потов, шин и следующее состояние регистров на нулевом такте, то его итерациями можно вычислить значения всех портов, шин и следующее состояние регистров на любом из последующих тактов времени.

Примеры.


Вот несколько простых схем, на которых метод прямого распространения данных достигает успеха. Проверьте, что все они работают заявленным образом.

Представленная на рисунке 1 схема, реализует логическую функцию «следует»: на каждом такте значение ее внешнего входного пота glob_r(k) равно истинностному значению выражения glob_arg1(k) -> glob_arg2(k).

На рисунке 7 представлен простой «пульсар». Значение его внутреннего порта glob_out(k) при k=0 (на нулевом такте) случайно. Каждый следующий такт оно меняется на противоположное, чередуя между собой «нули» и «единицы». В качестве упражнения постарайтесь придумать, как построить пульсар, у которого последовательность значений порта glob_out обязательно начиналась бы с «единицы».


рис 7: схема простого «пульсара»

Поведение схемы, изображенной на рисунке 8, в некотором смысле повторят поведение прямого двухходового мультиплексора. Если на k-том такте значение glob_com равно “0”, то в этот такт значение порта glob_out копирует значение порта glob_in1, в противном случает на этом такте значение порта glob_out установится равным значению порта glob_in2. На досуге подумайте, поведение каких элементарных блоков можно проэмулировать с помощью схем, содержащих исключительно отличные от них элементарные блоки.


рис 8: Схема «составного» мультиплексора (с перепутанными входами)

Логические противоречия и вычислительная полнота.


Вычислительная неполнота метода прямого распространения данных.


Во всех ли логических схемах метод прямого распространения данных позволит узнать все неизвестные значения портов и шин? Говоря более детально мы можем переформулировать предыдущий вопрос так:

Должно ли вычисление все новых фронтов распространения сигнала обязательно завершиться тем, что их объединение (как множеств) вместе с очередным фронтом охватит собою в схеме все ее порты?

Вообще говоря, нет!


рис 9. Схема из циклически соединенных блока прямой и обратной конкатенации

Ниже на рисунке 9 изображена схема из двух блоков и трех шин. Она не включает в себя ни регистров, ни блоков-констант, ни внешних портов выхода. Отсюда следует, что множество портов нулевого и всех последующих фронтов распространения сигнала в этой схеме будет пусто и метод прямого распространения данных завершится ни с чем.

Тем не менее существуют такие значения портов и шин для схемы рисунка 9, при которых она вместе с ними удовлетворяют всем аксиомам нашей теории. Все такие значения получаются по следующему рецепту: достаточно для каждого такта как угодно выбрать однобитное значение x1, общее для шины b1 и соединенных с ней портов, затем как угодно выбрать однобитное значение x2, общее для шины b2 и соединенных с ней портов, а в качестве значения x3, общего для шины b3 и соединенных с ней портов, взять конкатенацию x1*x2 (докажите).

Например, все аксиомы будут выполнены, если на любом такте значениями всех портов и шин будут двоичные слова, состоящие только из нулей. (одного или двух в зависимости от их размерностей). С другой стороны, все аксиомы точно так же будут выполнены, если значением всех портов и шин будут двоичные слова, состоящие только из единиц. Этот паталогический пример показывает, что наша теория допускает неоднозначность в выборе значений портов и шин в некоторых схемах. Ни к одной из таких схем сугубо однозначный по своей природе метод прямого распространения данных результативно применен быть не может.
Однако дело тут не только в неоднозначности.

На рисунке 10 изображена схема, значение портов и шин в которой однозначно определены – все они должны быть равны “1”. Тем не менее, несмотря на однозначность, установить значения порта OR.arg2 методом прямого распространения данных тут не выйдет (проверьте).


рис 10 Схема безо всяких двусмысленностей.

Логические противоречия в значениях элементов схемы.


Все введенные нами аксиомы грубо можно разделить на две группы: конструкционную и поведенческую.

Аксиомы конструкционной группы определяют конструкцию логической схемы, то есть то, что представляют из себя ее элементы и как они должны быть друг с другом соединены. Сюда относятся аксиомы P1-P3, B1-B3 и аксиома C*.

Все остальные аксиомы образуют поведенческую и группу. Содержание аксиом поведенческой группы навязывает определенные взаимные ограничения между возможными значениями портов, шин, внутренним состоянием регистров и ходом дискретного времени.

Возникает естественный вопрос:

Предположим, что у нас есть схема, которая полностью удовлетворяет конструкционной группе аксиом. Другими словами, эта схема набрана из «правильных» элементов, соединенных меду собой «правильным» образом. Пусть также для каждого внешнего выходного порта этой схемы заданы его значения в каждый из тактов времени, а для каждого регистра объявлено его состояние на нулевом такте.

Всегда ли существует способ так приписать значения всем остальным портам и шинам схемы, чтобы все вместе они удовлетворяли еще и поведенческой группе аксиом?

Этот длинный вопрос имеет очень короткий ответ: “Нет”. Почти хрестоматийной иллюстраций этому служит «зацикленный на себя» блок “NOT” – по сути, парадокс лжеца в «железе».


рис 11. Парадокс лжеца

Каким бы мы не попробовали объявить значение порта not.r: “нулем”, или “единицей”, – передав это значение на порт not.arg и пересчитав значение для not.r заново, в обоих случаях мы придем к противоречию.

Довольно показательно, что схема “пульсара” на рисунке 7 отличается от только что рассмотренной противоречивой схемы наличием единственного регистра на пути зацикливания сигнала от “NOT” к “NOT”. Грубо говоря, наличие регистра вынуждает значение на выходе “NOT” «влиять» не на самое себя в том же такте, а на свое значение тактом позже. Как мы видим, такое «отложенное» круговое влияние уже не создает противоречий.

Следует отметить, что «не отложенное влияние» значений порта на самое себя проглядывается и во всех «паталогических» примерах с неоднозначным выбором значений, которые мы рассматривали в прошлом параграфе. Все эти факты подталкивают нас к догадке, что «не отложенное влияние» портов самих на себя может оказаться важным явлением внутри нашей теории, и поэтому на нем мы остановимся подробнее.

Функциональное влияние портов друг на друга.


В этом параграфе мы исследуем влияние, которое значения портов могут оказывать друг на друга в пределах времени, ограниченном одним единственным тактом. Как и прежде речь будет идти только о схемах, составленных исключительно из элементарных блоков.
Среди всего списка элементарных блоков только у регистров значения портов выхода в любой из тактов совершенно никак не зависят от значений, которые на том же такте принимают их порты входа. У всех остальных типов элементарных блоков (кроме блоков-констант), которые мы отнесли к функциональным, эта зависимость присутствует, более того она является определяющей, то есть функциональной.

Непосредственное функциональное влияние.


Будем говорить, что порт $p$ оказывает непосредственное функциональное влияние на порт $p’$ (или то же самое порт $p’$ испытывает непосредственное функциональное влияние со стороны порта $p$), если и только если выполнено хотя бы одно из следующих условий:

  1. $p$ является портом входа, а $p’$ — портом выхода одного и того же функционального элементарного блока;
  2. $p$ является каким-либо портом выхода, $p’$ – каким-либо портом входа и оба они соединены общей шиной.

Конечную последовательность портов $p_0,… p_n$, в которой каждый следующий порт испытывает непосредственное функциональное влияние со стороны предыдущего, назовем цепочкой функционального влияния.

Мы будем говорить, что порт $p$ формально влияет на порт $p’$, если и только если из портов схемы можно составить такую цепочку функционального влияния, в которой начальным элементом служит порт $p$, а последним – порт $p’$.

Подсознательно нам хотелось бы думать, что если порт $p$ функционального влияет на порт $p’$, то при некоторых условиях значение, принимаемое портом $p$ на такте $k$, должно как-то влиять на множество тех значений, которые в этот такт способен принять порт $p’$. Однако, как показывает схема на рисунке 12, подобное предположение верно не всегда: формально определенное функциональное влияние еще не означает влияния фактического.


(рисунок 12, где на один из аргументов “OR” подана “1”)

Цепочку функционального влияния, в которой первый и последний элемент совпадают, назовем циклом функционального влияния. Докажем теперь простую, но важную:

Теорема о функциональной ацикличности: если все порты и шины внутри схемы соединены конструкционно правильно (выполнены аксиомы конструкционной группы) и в этой схеме нет ни одного цикла функционального влияния, то:

!) при заданных на каждом такте значениях внутренних выходных портов схемы и известных на момент нулевого такта состояниях ее регистров, метод прямого распространения данных позволяет на каждом такте приписать значения абсолютно всем шинам, портам, а так же найти состояния в которых окажутся ее регистры в следующий такт времени;

!!) схема вместе с приписанными ее портам и шинам значениями удовлетворяет всем аксиомам поведенческой группы.

Доказательство !).

Согласно лемме 1 метод прямого распространения данных будет успешен на всей последовательности тактов тогда и только тогда, когда он оказывается успешен на нулевом такте. Отсюда следует, что нам достаточно доказать утверждение !) леммы 2 только для нулевого такта.

Будем действовать от противного. Предположим, что метод прямого распространения данных не достигает успеха: ни для какого $k$ объединение фронтов $F_0, … , F_k$ не включает в себя всех портов схемы. Пусть также $F_n$ – наибольший по индексу непустой фронт (если таковые у схемы вообще имеются).

Покажем, что существует по крайней мере один выходной порт, который не содержится ни одном фронте $F_0,… F_n$. Поскольку любой такой порт не может быть внешним, ровно как не может принадлежать ни одному регистру или блоку констант (все причисленные входят в $F_0$), то тем самым он должен быть портом выхода одного из функциональных блоков схемы.

Снова предположим обратное. Пусть каждый выходной порт принадлежит некоторому фронту $F_i$.

Если так, то пункт 8) алгоритма построения фронтов гарантирует, что тогда и каждый внешний входной порт будет включен в состав одного из фронтов, а именно в тот фронт $F_i$, которому принадлежит единственный выходной порт, соединенный с ним одной шиной.

Этим доказано, что все внешние входные порты принадлежат объединению фронтов $F_0,… F_n$.

Рассмотрим любой блок внутри схемы, у которого есть по крайней мере один входной порт. Каждый входной порт блока соединен с общей шиной некоторым единственным выходным портом в схеме, который в свою очередь входит в состав некоторого фронта $F_i$. Сопоставим каждому входному порту соответствующее ему $i$. Пусть $m$ – это максимум всех таких $i$ для данного блока, тогда согласно пунктам 4) и 5) алгоритма построения фронтов все входные порты этого блока должны были быть включены в состав фронта $F_m$. Тем самым оказано, что все внутренние входные порты также принадлежат объединению фронтов $F_0,… F_n$.

Найденное противоречие, как раз показывает, что если не все порты вошли в состав фронтов распространения сигнала, то среди них есть по крайней мере один выходной порт функционального блока. Пусть $p_0$ – один из таких портов.

Остается построит внутри схемы какой-нибудь цикл функционального влияния.

Если $p_0$ – выходной порт функционального блока и значение порту $p_0$ не было приписано, значит среди входных портов этого блока есть по крайней мере один такой, которому также не было приписано значение. Пусть $p_1$ – такой входной порт.

Отсутствие приписанного значения у порта $p_1$ в свою очередь означает, что тот единственный выходной порт $p_2$, с который $p_1$ соединен общей шиной, так же не получил приписанного значения и, следовательно, $p_2$ не принадлежит ни одному из фронтов $F_0,… F_n$. В том числе $p_2$ не может быть выходным портом никакого регистра, никакого блока констант, ровно, как и не может оказаться внешним выходным портом схемы (все эти категории входят в $F_0$). Следовательно,$ p_2$, как и $p_0$ (причем это может быть один и тот же порт) – это выходной порт какого-то функционального блока.

Действуя подобно тому, как описано выше, мы сможем построить сколь угодно длинную последовательность портов $p_0, p_1, p_2, …$ в которой:

a) каждый порт с нечетным индексом будет являться входным портом некоторого функционального блока, а стоящий перед ним в последовательности порт с четным индексом – выходным портом того же блока.

b) для каждого порта с нечетным индексом следующий за ним в последовательности порт с четным индексом будет тем единственным выходным портом с которым тот соединен общей шиной.

Поскольку количество портов, в том числе и выходных, в любой схеме предполагается конечным, то при наращивании последовательности $ p_0, p_1, p_2, …$ среди портов с четным индексом обязательно возникнут дубликаты. Пусть i<j – два таких числа, что порт $p_{2i}$– есть то же самый порт, что и $p_{2j}$. В таком случае конечная последовательность портов $π_0, π_1,… π_{(2(j-i))}$, где
$π_0= p_{(2j-0)}$,
$ π_1= p_{(2j-1)}$,
*
*
*
$ π_{(2(j-i))}=p_{2i}$
– будет ни чем иным, как обнаруженным нами циклом функционального влияния.

Полученное только что противоречие полностью доказывает !)

Доказательство !!) :

Двойной индукцией по номеру фронта и номеру такта проверить, что приписанные значения действительно не нарушают поведенческую группу аксиом. Предоставляется читателю в качестве упражнения.

Как мы видим, дополнительное требование, касающееся отсутствия в логической схеме циклов функционального влияния делает многие желательные и утверждения верными а анализ схем крайне удобным. Так почему бы не добавит это требование в качестве еще одной аксиомы в нашу теорию! Эта — будет последней:

A*) Никакая логическая схема не должна содержать циклов функционального влияния.

На этот раз все. В следующей статье надеюсь полностью разобрать теорию составных блоков и сложных схем и перейти уже к интересным практическим примерам и задачам.

Комментарии (17)


  1. Sergey_Kovalenko Автор
    04.05.2022 19:38
    +1

    Ваши отзывы и соображения помогут улучшить конечный вариант книги, особенно если Вы оставите вместе с этим отзывом какую-то информацию о своей категории как читателя, например: "я - студент", или "я - преподаватель этой дисциплины в университете", или "я - инженерный гений", или "да мне просто интересно стало". Можно писать очень плохие и даже самые ужасные отзывы, главное, чтобы развернуто и по делу.


  1. victor_1212
    04.05.2022 21:12
    +1

    > Впоследствии мы преодолеем проблему дублирования, добавив в нашу теорию возможность определять в ней новые составные блоки, что по духу аналогично переходу от ассемблера к процедурным языкам программирования.

    если по духу, возможно лучше макро определения, а не процедуры, таки переиспользование кода процедур имеет динамический характер

    ps

    желаю успеха


    1. Sergey_Kovalenko Автор
      04.05.2022 21:19

      Тут просто аналогия, вам программистам - виднее. Я имел в виду больше сам язык и его выразительную силу. Языки описания аппаратуры именно что описывают: их инструкции не призваны "исполнятся" на каких-либо машинах.


      1. victor_1212
        04.05.2022 21:28

        понимаю конечно, но аналогия не совсем, во всяком случае imho


      1. WASD1
        05.05.2022 13:59
        +1

        Одно из двух открытий в универе для меня было понятие "модульности" (проговоренное в явном виде) - как вообще основа всех сложных систем.

        Поэтому это возможно то место, в котором не стоит гнаться за упрощениями и аналогиями, и описать всё как есть?

        Сугубо ИМХО, конечно.

        ПС
        Да большое спасибо за ваш труд.
        Когда вышло оглавление (предыдущий пост) - я подумал, что оно настолько монументально, что реализации ожидать не стоит. Уже вижу что ошибся.
        Буду рад продолжению.


  1. Sergey_Kovalenko Автор
    05.05.2022 10:32

    Огромная благодарность от меня тем незримым редакторам хабра, которые всякий раз правят и аккуратно верстают мои неряшливые тексты. После ваших усилий статьи становятся куда более удобочитаемыми, чем до!


  1. CBET_TbMbI
    05.05.2022 13:30
    +1

    Я почитал в рамках ликбеза. Общие представления о теме были, но не более того.

    Собственно, текст мне понравился. Читается хорошо, стиль хороший. Но его требуется вычитать с точки зрения читателя. Не всё в нём можно понять опираясь только на него. И есть просто несколько ляпов.

    1. Не помешает во введении конкретное указание, о чём речь – о устройстве микросхем, о устройстве чипов и процессоров, или обо всём сразу.

     «Современные цифровые схемы на кристалле концептуально представляют из себя примерно тоже самое, однако их строение не получится разглядеть без микроскопа»

    Вот после этой фраз не хватает фразы, что далее речь идёт о «схемах на кристалле» (процессорах, чипах, …?). Или о том, что в книге будут рассмотрены принципы одинаково подходящие и к чипам, и к микросхемам.

    2. Блочок – не очень удачный термин. Миниблок, базовый блок, логически блок, просто блок, элемент схемы - не так режет слух. Конечно, если это не общепринятый термин.

    3. 5. и понятии дискретного времени.

    "И" лишнее

    4. всего 4возможных комбинации

    пропущен пробел

    5. P3) Свойство, обязывающие каждый входной порт быть присоединенным в точности к одной шине, а каждый выходной порт – не более чем к одной шине.

    Сложно написано, приходится вчитываться. Может быть так: Входной порт всегда подсоединён к одной и только одной шине, а выходной либо к одной, либо ни к одной?

    6. P6) В каждый из тактов значение всякого внешнего выходного порта должно быть задано вешними условиями.

    Может быть входного, а не выходного? Иначе непонятно, почему выходное значение должно зависеть от внешних условий. Или значение выходного порта зависит от внешних значений на входных портах?

    7. Чтобы назвать конкретный порт, мы будем указывать собственное имя блока, а затем через точку то универсальное имя, которое этот порт имеет во всех блоках данного типа (например, or_0.arg1)

    Непонятно, что такое арг. Имя блока понятно, а далее какое-то универсальное имя, и какой-то этот (какой этот?) порт, суть которых не понять по данному тексту.

     8. Когда это необходимо, сразу за именем в квадратных скобках мы будем указывать размерность порта.

    Размерность – это количество бит, которое он передаёт?

    Пусть Pname – имя конкретного порта, значение этого порта на временном шаге k мы будем обозначать как Pname(k), в свою очередь i-тый бит того же значения — как Pname[i](k), или просто Pname[i], если из контекста понятно, о каком именно шаге идет речь.

    Из этого абзаца уже непонятно, что же в квадратных скобках – количество бит (размерность) или номер бита. Я бы оба абзаца переписал, более чётко, но просто указав что в квадратных скобках ,а что в круглых.

    Если интересно, могу позже продолжить.


    1. Sergey_Kovalenko Автор
      05.05.2022 14:01

      Спасибо, много дельных замечаний, вы дали мне пищу для ума.

      Касательно цитата:
      "Может быть входного, а не выходного? Иначе непонятно, почему выходное значение должно зависеть от внешних условий. Или значение выходного порта зависит от внешних значений на входных портах?"

      6) Я тоже переживал, что будет сбивать с толку. Понимаете, выходные порты - это все те, на которые устройства подают сигнал. Сканер подает сигнал на свои выходные порты, если эти порты присутствуют на материнской плате компьютера, то в моем определении они являются внешними для платы, но выходными портами. Конечно в некотором смысле, это входные порты платы, как единого устройства, однако по своим свойствам, по их роли в правилах конструирования логической схемы и содержании теорем - по свойствам эти порты почти ни чем не отличаются от выходных портов блоков, расположенных внутри схемы. Я думал остановится и уделить внимание этому моменту в тесте, но почему-то так и не сумел найти нужных слов или не посчитал проблему достаточно важной.

      7) Имена полей всех объектов класса устанавливаются в момент определения класса. У каждого экземпляра объекта класса будет то же самое именование его собственных полей, что и у всех других представителей класса. Теперь прямая аналогия: класс объектов-> тип логических блоков, конкретный объект класса -> конкретный блок своего типа, поле объекта -> порт блока. arg1 - это общее (универсальное) название одного из портов в типи блоков логического "ИЛИ", or_2 - какой-то конкретный блок этого типа, or_2 arg1 - конкретный порт.

      Не уверен, что смогу оперативно включить все Ваши замечания в текст (текст с учтёнными замечаниями - это новая статья), но в конечной редакции книги я постараюсь все исправить. Так что, да, я буду благодарен за ту обратную связь, которую Вы даете.


      1. CBET_TbMbI
        05.05.2022 16:46
        +1

        Про входы и выходы спорить не буду. Я не знаю, как принято. Интуитивно мне кажется, что, если есть шина, то один её конец будет входным для одного блока, а другой выходным для другого. Если какой-то внешний блок (схема, или группа блоков, или устройство) подаёт по шине сигнал в рассматриваемый блок (схему), то, то для внешнего блока это будет выходной порт, а для рассматриваемого входной. Но это моя логика. Если это не так, то надо всё же объяснить, ибо это, как я понимаю, базовые термины и принципы.

        Про arg1. Может, я упрощу, но, мне кажется, тут слишком усложнено. Вот суть, которую и надо отразить в книге: or_2 - имя конкретного блока, arg1 - имя порта, который может (не может) быть в разных блока, or_2 arg1 - имя конкретного порта в конкретном блоке. По идее этого будет достаточно для начала. Дополнительно можно (но не обязательно) что-нибудь пояснить про то, что клон arg1 может быть портом в or_3. А может ли быть в and_1.

        И я бы не привязывал это к классам из программирования. Иначе получится, что для чтения книги нужно будет знать программирование на весьма неплохом уровне. Я бы постарался сделать книгу такой, чтобы было достаточно школьных знаний (логику И, ИЛИ человек знает, но ассемблер и классы не полностью или вовсе только слышал).


        1. Sergey_Kovalenko Автор
          05.05.2022 17:07

          Гениально! Я пол часа голову ломал, как вот об этом всем написать, и не додумался - пришлось через аналогию выпутываться. Ваша версия несравненно лучше, она и войдет в конечный вариант текста.

          Про порты - да, вы правы. К тем же самым соображениям я прибегну, когда буду строить понятие составного логического блока. В теории элементарных схем, к сожалению такой подход делает все громоздким и запутанным. Вот и приходится идти отчасти против интуиции и традиций.


        1. Sergey_Kovalenko Автор
          05.05.2022 17:18

          Если бы я избрал "традиционны" вариант, то во всех аксиомах, теоремах, доказательствах теорем вместо "для всякого выходного порта" мне пришлось бы писать "для всякого внутреннего выходного либо внешнего входного", то же самое для нынешней "для всякого входного". Мне показалось меньшим злом избрать тот вариант, который вы собственно и видите в статье.


  1. Sergey_Kovalenko Автор
    05.05.2022 14:00

    не туда


  1. karambaso
    05.05.2022 14:04
    +1

    Заинтересовало желание автора "отрефакторить" проектирование логических схем. По сути автор решил начать почти с нуля и протянуть привычные ему математические подходы до некого практически полезного завершения. Но есть проблема. Она состоит в том, что методов проектирования логических схем создано к настоящему моменту немало, и созданы они чаще всего практиками, или с тесной привязкой к практике. Привязка эта отражается в связности изложения при обучении инженера электронщика. Сначала даётся некая база, основные понятия котрой в дальнейшем используются, в том числе в таких дисциплинах, как проектирование логических схем. То есть подход автора не то что бы совсем отрован от этой базы, но всё же предполагает значительный разрыв между базой и предложенным подходом.

    Дополнительно подход автора несёт на себе явный отпечаток математичности. Это неплохо, но внутри такого подхода заложены неустранимые проблемы. Иначе было бы странным, почему бы за сотню лет никто не сподобился начать использовать математику в проектировании настолько глубоко, как предлагает автор. А не сподобились они по простой причине - аксиоматизация реального мира нереальна для смертных. Затраты стремятся к бесконечности. Практический результат - к нулю. Поэтому автор вынужден ограничиться неким базовым набором аксиом, от которого далее строит своё изложение.

    Но базовый набор аксиом, как известно на примерах из той же математики, хорош для исключительно математических построений, когда соответствие реальности является практически ненужным качеством построения. Но в электронике на первом месте стоит всё же именно соответствие реальности. Как добивается автор такого соответствия? Он намеренно ограничивает сложность построения, вводя ограничения на составляющие предложенной теории. Что из этого получилось, ещё предстоит оценить, но тем не менее уже появились вопросы.

    Было бы интересно узнать мнение автора по проблеме выбора минимального набора аксиом. Почему именно такой набор? Что вы думаете о его минимальности? А о непротиворечивости? Последнее вы, видимо, сами обнаружили при попытке описать схемы с внутренними циклами, и в результате ввели дополнительные ограничений (аксиомы), препятствующие появлению таких циклов. Но правильно ли это с практической точки зрения?

    На практике разного рода ухищрения с зацикливанием приводят к некоторым полезным эффектам (мультивибратор, например), а намеренное исключение таких эффектов ведёт к уменьшению "силы теории" (если выражаться в математических терминах). На практике же это означает меньшую свободу действий проектировщика, худший результат на выходе.

    Собственно, привычные в электронике методы проектирования потому и не берутся доходить до самых основ, ведь это приведёт к наличию ограничений. Предполагается, что лучше иметь возможность делать всё, не накладывая на себя запретов, а моделировать такие вседозволенности по частям, в рамках которых некие ограничения всё же соблюдаются (но часто наборы ограничений сильно отличаются от модуля к модулю).

    Так же, как важная часть математичности, в подходе присутствует возможность почти один-в-один переложить его на любой язык логического программирования (с точностью до обозначений). Не думал ли автор сходить и в эту сторону? Лёгкость моделирования мне представляется важным достоинством подхода.

    Ещё есть моменты "мелкого характера". В вашем определении шина - это просто провод, связь, и более ничего. Зачем тогда слово "шина"? В компьютерах шина является довольно сложным изделием, предполагающим коммутацию поставщиков/потребителей двольно сложным образом. В вашем ограниченном случае этим могут заниматься входящие в вашу теорию мультиплксоры. Но выбор был сделан в пользу простого провода. Почему?

    Термин "фронт распространения" мне кажется неудачным. Вы рассматриваете статическую картину, когда все значения напряжений на всех выходах полностью определены. Фронт же предполагает различные значения на элементах, находящихся до него и после него. Это непривычное использование термина может привести к плохим последствиям.

    Ну и по побозначениям. Например - or_0 - зачем связка в виде "_"? А если без неё? Что тогда ухудшится? Зачем вводить лишнюю сущность?

    Так же я бы сделал преобразование: pname[i](k) -> pname(k)[i]. Потому что сначала идёт такт, а уже потом идёт значение бита на данном такте. У вас же первично значение, а такт появляется позднее.

    Итог: хотя бы отличие от существующих методов всё же стоит пояснить - зачем, почему именно так, чем лучше, чем хуже. Ну и на все остальные впросы ответить, заодно :)


    1. Sergey_Kovalenko Автор
      05.05.2022 15:21
      +1

      Спасибо, я должен вас порадовать, вы почти везде правильно догадались до моих задумок и с большинством ваших посылок я согласен. Результат анализа этих посылок у меня правда отличается, во многом по этому и появилась идея написать книгу.

      Одна из сверх идей, которые прячутся за содержанием: время для обучения и развития навыков у каждого человека конечны. Если бы я потратил так много времени на изучение всего того, что должен знать мало-мальски квалифицированный инженер-электронщик и еще столько же, чтобы эти знания превратить в рабочий навык, то мне некогда было бы изучать математику, практиковаться в исследованиях и я не смог бы изобрести те несколько, как мне кажется, интересных алгоритмов и общих концепций о которых собираюсь рассказать.

      Я готов высказать гипотезу, что в среде людей, которые занимаются проектированием сложной микроэлектроники существует дефицит знаний и навыков в области более абстрактной математики и теории алгоритмов. У меня есть уверенность, что проектирование микросхем, как ремесло и область знания усложнилась в той мере, когда должно произойти очередное "разделение труда". Стиль и содержание книги задумывались мной с той целью, чтобы сблизить людей с абстрактно-математическим и инженерно-прикладным стилем мышления, нащупать очертания возможного языка коммуникации между ними. Это ответ на главные ваши вопросы и догадки.

      Те следующие сомнения, которые вы высказываете наверное могли бы быть применены и к обычному программированию в каких-нибудь 60-тых годах. Поверьте, RAM-модель, на основе которой построены все книги и все обучение современных программистов бесконечно далека от реального устройства процессора, памяти и конкретной реализации вычислений. Однако именно изобретение RAM-модели позволило привлечь к исследования алгоритмов широкий круг ученых, которые без нее и носа бы не сунули в непроходимые закоулки логики существовавших на тот момент машин. Универсальность и доступность их теорий стало основой для лучшей подготовки "специалистов на местах". Все-таки разница между программистом, который знает быструю сортировку и программистом, который выполняет сортировку исключительно пузырьком, разница существенна.

      Набор аксиом непротиворечив, если непротиворечива арифметика (аксиома T), поскольку в таком случае логическая схема не содержащая ни одного блока, шины или порта является его моделью. Теория обладающая моделью не может быть противоречивой.

      Насчет переименования pname[i](k) -> pname(k)[i] - полностью с вами согласен, хотя так как есть моему взгляду нравится больше. Не знаю, что победит, чувство эстетики или здравый смысл. Подожду еще мнений.


      1. karambaso
        05.05.2022 15:57

        У меня есть уверенность, что проектирование микросхем, как ремесло и
        область знания усложнилась в той мере, когда должно произойти очередное
        "разделение труда".

        Разделение нужно для повышения эффективности en mass, но для повышения качества понимания, являющегося основой повышения возможностей по проектированию, разделение вредно. Отсюда цель вашего труда - предложения по массовому обучению (ибо только тогда есть эффект). Если же на самом деле цель - углубление понимания, то не нужно говорить о разделении. Или вообще мысль не донесена (либо мной не понята).

        RAM-модель

        Это модель абстрактной нерпрерывной адресуемой памяти или что-то ещё? Если память, то там давно все сложности работы учитываются. Вспомним хотя бы количество уровней промежуточных кэшей в современном компьютере. Эти знания активно используются при написании эффективных программ.

        Теория обладающая моделью не может быть противоречивой.

        Исключите требование ацикличности и тогда на пустой схеме вы тоже построите модель. Но результат-то противоречивый.


        1. Sergey_Kovalenko Автор
          05.05.2022 16:17

          Насчет непротиворечивости вы не совсем правы. Если некоторая теория непротиворечива, то есть из всех ее аксиом нельзя вывести противоречие, то и из любого подмножества аксиом тоже нельзя вывести противоречия.

          Исключение из списка аксиомы ацикличности просто не позволит доказать, что из соответствия схемы логических блоков конструкционной группе аксиом, следует, что портам, шинам и состояниям блоков на каждом такте можно приписать такие значения, так чтобы все вместе они удовлетворяли всем аксиомам теории.

          Разделение труда как раз и происходит, либо если вы делаете что-то массовое (упрощение ради эффективности), либо что-то очень сложное (ограничение необходимого объема и сложности знаний каждого сотрудника). БАК, ИТЕР, "Джеймс Вэб" не делаются "моноспециалистами".

          RAM-модель - это не совсем про память, скорее, это такая абстрактная вычислительная машина, вроде машины Тьюринга, только каретка куда угодно может за один шаг прыгать и ячейка на ленте может сколь угодно большое натуральное числа содержать.


  1. Sergey_Kovalenko Автор
    05.05.2022 16:14

    снова не туда