This commit is contained in:
dboyarov
2026-09-24 18:31:50 +03:00
parent 787d33d7ea
commit 6d53a2451e
24 changed files with 8106 additions and 25 deletions

View File

@@ -1,23 +1,507 @@
= Цель работы
#import "../config/utils.typ": *
[Цель работы]
#par(first-line-indent: 0pt)[#fill-in[Жёлтым маркером отмечены места, которые заполняются по результатам работы на стенде (измерения, осциллограммы, снимки DSView), а также номер группы и ФИО преподавателя]]
= Предварительный расчёт
// =====================================================================
= 1 Цель работы
[Предварительный расчёт]
Ознакомиться с базовыми логическими элементами, реализующими логические операции НЕ, И-НЕ, ИЛИ-НЕ, и их особенностями на примере микросхем серии 74HC: научиться по таблице истинности строить и минимизировать логическую функцию, реализовывать её в базисах 2И-НЕ и 2ИЛИ-НЕ, моделировать схему в Micro-Cap, измерять задержку распространения сигнала и наблюдать ложные срабатывания (состязания сигналов).
= Экспериментальный расчёт
// =====================================================================
= 2 Краткие теоретические сведения
[Экспериментальный расчёт]
Логический элемент – схема, выходной сигнал которой (0 или 1) определяется логической функцией от входных сигналов. В работе используются микросхемы серии 74HC (КМОП): 74HC04 – шесть инверторов (НЕ), 74HC00 – четыре элемента 2И-НЕ, 74HC02 – четыре элемента 2ИЛИ-НЕ, 74HC14 – шесть инверторов с триггером Шмитта.
= Обработка результатов машинного эксперимента
#figure(
table(columns: (2cm, 2cm, 3cm, 3.5cm, 3.5cm), align: center,
..hdr[A][B][НЕ A][A И-НЕ B][A ИЛИ-НЕ B],
[0], [0], [1], [1], [1],
[0], [1], [1], [1], [0],
[1], [0], [0], [1], [0],
[1], [1], [0], [0], [0]),
caption: [Базовые логические элементы]) <tab:basic>
[Обработка результатов]
Элементы И-НЕ и ИЛИ-НЕ называют универсальными: из элементов одного такого типа можно построить любую логическую функцию. Инвертор получают, соединив оба входа элемента вместе: И-НЕ(A, A) = ИЛИ-НЕ(A, A) = $overline(A)$.
= Вывод
Для перевода выражения в базис И-НЕ или ИЛИ-НЕ используют правила де Моргана:
$ overline(A dot B) = overline(A) + overline(B), quad quad overline(A + B) = overline(A) dot overline(B). $
[Вывод]
Минимизация функции выполняется с помощью карты Карно – таблицы, в которой соседние клетки отличаются значением только одной переменной (строки и столбцы нумеруются кодом Грея 00, 01, 11, 10). Соседние единицы (или нули) объединяются в прямоугольные группы по 2, 4, 8 клеток; переменные, которые внутри группы меняются, из соответствующего слагаемого исчезают. Клетки, значение которых по условию не задано («безразличные», обозначены «–»), можно доопределять нулём или единицей так, как удобнее для укрупнения групп.
= Ответы на вопросы для самопроверки
Задержка распространения $t_"pd"$ – время между изменением входного сигнала и соответствующим изменением выходного (измеряется по уровню 50 %). Для 74HC она зависит от напряжения питания: чем оно ниже, тем медленнее переключается элемент. При последовательном включении $N$ элементов задержки складываются.
[Ответы на вопросы]
Ложное срабатывание (риск сбоя, «глитч») – короткий импульс на выходе комбинационной схемы, которого не должно быть по таблице истинности. Он возникает, когда при смене входного набора сигналы приходят на входы элемента разными путями с разной задержкой (состязания, гонки сигналов), или когда входные сигналы сами меняются не одновременно. Триггер Шмитта – элемент с гистерезисом: у него разные пороги переключения при нарастании ($V_(T+)$) и спаде ($V_(T-)$) входного напряжения, поэтому короткие «недоросшие» импульсы и шум на медленных фронтах он не пропускает.
// =====================================================================
= 3 Модель индивидуального варианта
== 3.1 Формирование индивидуального варианта
Студент: Бояров Данила. Первые четыре буквы имени: Д, А, Н, И – им соответствует значение $Y = 1$. Первые четыре буквы фамилии: Б, О, Я, Р – им соответствует $Y = 0$.
Номер буквы берётся по алфавиту, номер строки таблицы – как остаток от деления номера буквы на 16. Нумерация выполнена так же, как в примере методички (Пётр Иванов: П = 1, Е = 6, Т = 4, Р = 2, И = 10, В = 3, А = 1, Н = 15). Этот пример получается только при нумерации по полному алфавиту из 33 букв (А = 1, …, Е = 6, Ё = 7, Ж = 8, …, И = 10, …, Я = 33), а указание «удалить букву ё» относится к самим имени и фамилии (Пётр → Петр). Строки таблицы нумеруются с единицы: номер 1 – строка 0000, номер 2 – строка 0001, …, номер 16 (остаток 0) – строка 1111. При совпадении номеров (коллизии) занимается следующая свободная строка. Сначала расставляются буквы имени, затем фамилии.
#figure(
table(columns: (1.6cm, 2.4cm, 2.8cm, 2.6cm, 4.4cm, 1.2cm), align: center + horizon,
..hdr[Буква][Номер в алфавите][Остаток от деления на 16][Строка по номеру][Занятая строка (X4X3X2X1)][Y],
[Д], [5], [5], [5], [5 (0100)], [1],
[А], [1], [1], [1], [1 (0000)], [1],
[Н], [15], [15], [15], [15 (1110)], [1],
[И], [10], [10], [10], [10 (1001)], [1],
[Б], [2], [2], [2], [2 (0001)], [0],
[О], [16], [0], [16], [16 (1111)], [0],
[Я], [33], [1], [1 – занята], [1, 2 заняты → 3 (0010)], [0],
[Р], [18], [2], [2 – занята], [2, 3 заняты → 4 (0011)], [0]),
caption: [Определение строк таблицы истинности]) <tab:letters>
== 3.2 Таблица истинности
#figure(
table(columns: (1.2cm, 1.5cm, 1.5cm, 1.5cm, 1.5cm, 1.5cm, 1.8cm), align: center,
..hdr[№][X4][X3][X2][X1][Y][Буква],
[1], [0], [0], [0], [0], table.cell(fill: one)[1], [А],
[2], [0], [0], [0], [1], table.cell(fill: zero)[0], [Б],
[3], [0], [0], [1], [0], table.cell(fill: zero)[0], [Я],
[4], [0], [0], [1], [1], table.cell(fill: zero)[0], [Р],
[5], [0], [1], [0], [0], table.cell(fill: one)[1], [Д],
[6], [0], [1], [0], [1], [–], [],
[7], [0], [1], [1], [0], [–], [],
[8], [0], [1], [1], [1], [–], [],
[9], [1], [0], [0], [0], [–], [],
[10], [1], [0], [0], [1], table.cell(fill: one)[1], [И],
[11], [1], [0], [1], [0], [–], [],
[12], [1], [0], [1], [1], [–], [],
[13], [1], [1], [0], [0], [–], [],
[14], [1], [1], [0], [1], [–], [],
[15], [1], [1], [1], [0], table.cell(fill: one)[1], [Н],
[16], [1], [1], [1], [1], table.cell(fill: zero)[0], [О],
),
caption: [Таблица истинности индивидуального варианта («–» – значение не задано)]) <tab:truth>
X4 – старший разряд, X1 – младший, т. е. набор X4X3X2X1 – это двоичная запись числа (номер строки минус 1).
== 3.3 Логическое выражение (СДНФ)
Функция равна единице на четырёх наборах: 0000, 0100, 1001, 1110. Для каждого такого набора записывается произведение всех переменных, причём переменная, равная в наборе нулю, берётся с инверсией. Сумма этих произведений – совершенная дизъюнктивная нормальная форма (СДНФ):
$ Y = overline(X_4) thin overline(X_3) thin overline(X_2) thin overline(X_1) + overline(X_4) X_3 overline(X_2) thin overline(X_1) + X_4 overline(X_3) thin overline(X_2) X_1 + X_4 X_3 X_2 overline(X_1). $
== 3.4 Минимизация по единицам (карта Карно)
Строки карты – X2X1, столбцы – X4X3, порядок в коде Грея (00, 01, 11, 10), поэтому любые две соседние клетки, в том числе крайние (карта «сворачивается» в тор), отличаются одной переменной. Замечание: в примере методички строки и столбцы записаны в порядке 00, 01, 10, 11 – группы там объединены правильно по смыслу, но визуально соседние клетки не всегда являются логически соседними, поэтому здесь использован стандартный порядок кода Грея.
#figure(
table(columns: (3.4cm, 2.4cm, 2.4cm, 2.4cm, 2.4cm), align: center,
..hdr[X2X1 \\ X4X3][00][01][11][10],
[00], table.cell(fill: one)[1], table.cell(fill: one)[1], [–], [–],
[01], table.cell(fill: zero)[0], [–], [–], table.cell(fill: one)[1],
[11], table.cell(fill: zero)[0], [–], table.cell(fill: zero)[0], [–],
[10], table.cell(fill: zero)[0], [–], table.cell(fill: one)[1], [–],
),
caption: [Карта Карно исходной функции]) <tab:kmap0>
Безразличные клетки доопределяются единицами там, где это позволяет укрупнить группы, при этом ни одна группа не должна захватить заданный нуль (клетки 0001, 0010, 0011, 1111). Получаются три группы по 4 клетки:
#figure(
table(columns: (3.4cm, 2.4cm, 2.4cm, 2.4cm, 2.4cm), align: center,
..hdr[X2X1 \\ X4X3][00][01][11][10],
[00], table.cell(fill: one)[1], table.cell(fill: one)[1], table.cell(fill: one)[1\*], table.cell(fill: one)[1\*],
[01], [0], [0\*], table.cell(fill: one)[1\*], table.cell(fill: one)[1],
[11], [0], [0\*], [0], [0\*],
[10], [0], [0\*], table.cell(fill: one)[1], table.cell(fill: one)[1\*],
),
caption: [Карта Карно после доопределения (оптимизация по единицам; добавленные единицы отмечены «1\*»)]) <tab:kmap1>
#figure(
table(columns: (1.8cm, 5.2cm, 4.4cm, 3.6cm), align: center + horizon,
..hdr[Группа][Клетки (X4X3X2X1)][Что не меняется][Слагаемое],
[1], [0000, 0100, 1100, 1000], [X2 = 0, X1 = 0], [$overline(X_2) thin overline(X_1)$],
[2], [1000, 1001, 1100, 1101], [X4 = 1, X2 = 0], [$X_4 overline(X_2)$],
[3], [1000, 1010, 1100, 1110], [X4 = 1, X1 = 0], [$X_4 overline(X_1)$]),
caption: [Группы единиц]) <tab:groups1>
Группа 1 покрывает единицы 0000 и 0100, группа 2 – единицу 1001, группа 3 – единицу 1110. Минимальная дизъюнктивная нормальная форма (МДНФ):
$ Y = overline(X_2) thin overline(X_1) + X_4 overline(X_2) + X_4 overline(X_1). $
Переменная X3 из функции исчезла: при выбранном доопределении выход от X3 не зависит. Меньше трёх слагаемых получить нельзя: единицы 1001 и 1110 отличаются тремя разрядами, и единственная группа, содержащая обе клетки ($X_4 = 1$, 8 клеток), захватывает заданный нуль 1111.
== 3.5 Минимизация по нулям
Аналогично объединяются нули; безразличные клетки доопределяются так же (иначе функции по единицам и по нулям не совпадали бы). Каждая группа нулей даёт сомножитель-сумму, в которой переменная, равная в группе единице, берётся с инверсией:
#figure(
table(columns: (3.4cm, 2.4cm, 2.4cm, 2.4cm, 2.4cm), align: center,
..hdr[X2X1 \\ X4X3][00][01][11][10],
[00], [1], [1], [1\*], [1\*],
[01], table.cell(fill: zero)[0], table.cell(fill: zero)[0\*], [1\*], [1],
[11], table.cell(fill: zero)[0], table.cell(fill: zero)[0\*], table.cell(fill: zero)[0], table.cell(fill: zero)[0\*],
[10], table.cell(fill: zero)[0], table.cell(fill: zero)[0\*], [1], [1\*],
),
caption: [Карта Карно, оптимизация по нулям (добавленные нули отмечены «0\*»)]) <tab:kmap2>
#figure(
table(columns: (1.8cm, 5.2cm, 4.4cm, 3.6cm), align: center + horizon,
..hdr[Группа][Клетки (X4X3X2X1)][Что не меняется][Сомножитель],
[1], [0001, 0011, 0101, 0111], [X4 = 0, X1 = 1], [$(X_4 + overline(X_1))$],
[2], [0010, 0011, 0110, 0111], [X4 = 0, X2 = 1], [$(X_4 + overline(X_2))$],
[3], [0011, 0111, 1011, 1111], [X2 = 1, X1 = 1], [$(overline(X_2) + overline(X_1))$]),
caption: [Группы нулей]) <tab:groups0>
$ Y = (X_4 + overline(X_1)) (X_4 + overline(X_2)) (overline(X_2) + overline(X_1)). $
Проверка: раскрыв скобки, получаем то же выражение, что и в п. 3.4. Функция является функцией «большинства» (мажоритарной) от трёх сигналов $X_4$, $overline(X_1)$, $overline(X_2)$: $Y = 1$, когда хотя бы два из них равны единице.
== 3.6 Перевод в базисы 2И-НЕ и 2ИЛИ-НЕ
Доступны только двухвходовые элементы И-НЕ (74HC00) и ИЛИ-НЕ (74HC02); обычные И и ИЛИ недоступны, инверторы делаются из тех же элементов с объединёнными входами. Ниже для краткости используется функциональная запись: И-НЕ(a, b) = $overline(a dot b)$, ИЛИ-НЕ(a, b) = $overline(a + b)$.
+ МДНФ в базисе 2И-НЕ (двойная инверсия и правило де Моргана):
$ Y = overline(overline(overline(X_2) thin overline(X_1)) dot overline(X_4 overline(X_2)) dot overline(X_4 overline(X_1))) = "И-НЕ"_3 ("И-НЕ"(overline(X_2), overline(X_1)), "И-НЕ"(X_4, overline(X_2)), "И-НЕ"(X_4, overline(X_1))). $
Трёхвходовое И-НЕ из двухвходовых требует ещё трёх элементов, итого: 2 инвертора + 3 + 3 = 8 элементов.
+ МДНФ в базисе 2ИЛИ-НЕ: каждое произведение превращается в ИЛИ-НЕ от инверсий ($X_4 overline(X_2)$ = ИЛИ-НЕ($overline(X_4)$, $X_2$) и т. д.), затем нужна сумма трёх слагаемых – итого 8 элементов.
+ МКНФ в базисе 2ИЛИ-НЕ: $Y$ = ИЛИ-НЕ#sub[3]\(ИЛИ-НЕ($X_4$, $overline(X_1)$), ИЛИ-НЕ($X_4$, $overline(X_2)$), ИЛИ-НЕ($overline(X_2)$, $overline(X_1)$)) – 8 элементов.
+ МКНФ в базисе 2И-НЕ: сомножители $X_4 + overline(X_1)$ = И-НЕ($overline(X_4)$, $X_1$) и т. д., затем И трёх сомножителей – 8 элементов.
Число элементов можно уменьшить, если вынести общий множитель за скобки (скобочная форма):
$ Y = X_4 (overline(X_1) + overline(X_2)) + overline(X_1) thin overline(X_2) = X_4 overline(X_1 X_2) + overline(X_1) thin overline(X_2), $
$ Y = (X_4 + overline(X_1) thin overline(X_2)) (overline(X_1) + overline(X_2)). $
Отсюда по правилам де Моргана:
$ Y = "И-НЕ"("И-НЕ"(X_4, "И-НЕ"(X_1, X_2)), "И-НЕ"(overline(X_1), overline(X_2))), quad overline(X_i) = "И-НЕ"(X_i, X_i); $
$ Y = "ИЛИ-НЕ"("ИЛИ-НЕ"(X_4, "ИЛИ-НЕ"(X_1, X_2)), "ИЛИ-НЕ"(overline(X_1), overline(X_2))), quad overline(X_i) = "ИЛИ-НЕ"(X_i, X_i). $
Проверка второй формулы: ИЛИ-НЕ($X_1$, $X_2$) = $overline(X_1) thin overline(X_2)$; ИЛИ-НЕ($X_4$, $overline(X_1) thin overline(X_2)$) = $overline(X_4 + overline(X_1) thin overline(X_2))$; ИЛИ-НЕ($overline(X_1)$, $overline(X_2)$) = $X_1 X_2 = overline(overline(X_1) + overline(X_2))$; внешнее ИЛИ-НЕ двух инверсий даёт произведение $(X_4 + overline(X_1) thin overline(X_2))(overline(X_1) + overline(X_2)) = Y$.
#figure(
table(columns: (4.2cm, 3.4cm, 3.4cm, 2.4cm, 2.6cm), align: center + horizon,
..hdr[Вариант][Базис][Число 2-входовых элементов][Число микросхем][Ступеней в пути],
[МДНФ, «в лоб»], [2И-НЕ], [8], [2], [4],
[МДНФ, «в лоб»], [2ИЛИ-НЕ], [8], [2], [5],
[МКНФ, «в лоб»], [2ИЛИ-НЕ], [8], [2], [4],
[МКНФ, «в лоб»], [2И-НЕ], [8], [2], [5],
[Скобочная форма], [2И-НЕ (7400)], table.cell(fill: one)[6], [2], [3],
[Скобочная форма], [2ИЛИ-НЕ (7402)], table.cell(fill: one)[6], [2], [3]),
caption: [Сравнение вариантов реализации]) <tab:variants>
Наименьшее число действий – 6 элементов – дают скобочные формы, причём в обоих базисах одинаково. То, что меньше шести двухвходовых элементов не бывает, дополнительно проверено полным перебором всех схем из 1…5 элементов И-НЕ (и отдельно ИЛИ-НЕ) на компьютере: ни одна не реализует функцию. Обе схемы имеют одинаковую структуру (@fig:nand-sch и @fig:nor-sch), поэтому промоделированы обе; на стенде можно собрать любую, основной выбрана схема на 2И-НЕ.
#figure(
table(columns: (2.3cm,) + (1.4cm,) * 8, align: center,
..hdr[X4X3X2X1][0000][0001][0010][0011][0100][0101][0110][0111],
[*Y*], [1], [0], [0], [0], [1], [0], [0], [0],
..hdr[X4X3X2X1][1000][1001][1010][1011][1100][1101][1110][1111],
[*Y*], [1], [1], [1], [0], [1], [1], [1], [0],
),
caption: [Полная таблица реализованной функции (с учётом доопределения)]) <tab:full>
== 3.7 Моделирование в Micro-Cap 12
=== 3.7.1 Генератор входных сигналов
На схему помещается генератор Stim4 (Component → Digital Primitives → Stimulus Generators → Stim4). Его выходы подключены так: Out3 → X4 (старший разряд), Out2 → X3, Out1 → X2, Out0 → X1. Атрибут COMMAND = SixteenCount, FORMAT = 1111 (двоичные значения), а на странице Text схемы записана команда из методички:
```
.define SixteenCount
+0ns 0000
+label=start
+100ns Incr By 0001
+200ns goto start Until GE 1111
```
Генератор перебирает наборы 0000 → 1111, каждый держится 100 нс; после 1,5 мкс остаётся 1111. Анализ Transient: Maximum Run Time = 2u, графики d(X4), d(X3), d(X2), d(X1), d(OUT). Number of Points = 4001 (шаг вывода 0,5 нс) – увеличено по сравнению с методичкой, чтобы по числовому выводу точно измерить задержки; на вид графиков это не влияет.
=== 3.7.2 Исходная функция (СДНФ) на цифровых примитивах
Схема собрана из примитивов Inverter, And4, Or4 (модель задержки D0\_GATE – идеальные элементы без задержки): четыре инвертора формируют $overline(X_4)$, $overline(X_3)$, $overline(X_2)$, $overline(X_1)$, четыре элемента 4И реализуют четыре произведения СДНФ, элемент 4ИЛИ их складывает.
#figure(image("../img/sdnf-sch.png", width: 14.5cm), caption: [Схема исходной функции (СДНФ) в Micro-Cap]) <fig:sdnf-sch>
#figure(image("../img/sdnf-tr.png", width: 100%), caption: [Временные диаграммы схемы СДНФ (шаг набора 100 нс)]) <fig:sdnf-tr>
Выход OUT равен единице на интервалах 0–100 нс (набор 0000), 400–500 нс (0100), 900–1000 нс (1001), 1400–1500 нс (1110) и нулю на всех остальных. Это в точности совпадает с таблицей истинности (@tab:truth): все заданные единицы и нули на месте, индивидуальный вариант построен верно. Задержек нет, так как примитивы с моделью D0\_GATE идеальные.
=== 3.7.3 Минимальная функция на элементах 7400 (2И-НЕ)
Схема собрана из моделей реальных микросхем (Component → Digital Library → 74xx00 → 00 → 7400). В Micro-Cap каждый символ 7400 – это один элемент 2И-НЕ из четырёх, имеющихся в корпусе. Элементы X1, X2 – инверторы (входы объединены), X3 = И-НЕ($X_1$, $X_2$) = A, X4 = И-НЕ($overline(X_1)$, $overline(X_2)$) = C, X5 = И-НЕ($X_4$, A) = B, X6 = И-НЕ(C, B) = OUT. Для наглядности на диаграмму выведены и промежуточные сигналы.
#figure(image("../img/nand-sch.png", width: 14.5cm), caption: [Схема минимальной функции в базисе 2И-НЕ (7400)]) <fig:nand-sch>
#figure(image("../img/nand-tr.png", width: 100%), caption: [Временные диаграммы схемы на 7400]) <fig:nand-tr>
=== 3.7.4 Минимальная функция на элементах 7402 (2ИЛИ-НЕ)
Та же структура, но все элементы – 2ИЛИ-НЕ (Digital Library → 74xx00 → 02 → 7402).
#figure(image("../img/nor-sch.png", width: 14.5cm), caption: [Схема минимальной функции в базисе 2ИЛИ-НЕ (7402)]) <fig:nor-sch>
#figure(image("../img/nor-tr.png", width: 100%), caption: [Временные диаграммы схемы на 7402]) <fig:nor-tr>
=== 3.7.5 Анализ результатов моделирования
Значения выхода схем на 7400 и 7402 проверены по числовому выводу Micro-Cap (файл .TNO) в конце каждого 100-наносекундного интервала: на всех 16 наборах они совпадают с полной таблицей реализованной функции (@tab:full), в том числе на всех восьми заданных клетках варианта. Значит, минимизация выполнена верно.
#figure(
table(columns: (5.4cm, 3.6cm, 3.6cm, 3.4cm), align: center + horizon,
..hdr[Схема][Задержка 1 → 0 на выходе, нс][Задержка 0 → 1 на выходе, нс][Ложные срабатывания],
[СДНФ, примитивы D0\_GATE], [0], [0], [нет],
[7400 (2И-НЕ), 3 ступени], [25], [29], [нет],
[7402 (2ИЛИ-НЕ), 3 ступени], [28], [32], [нет]),
caption: [Задержки, полученные при моделировании (по числовому выводу)]) <tab:model-delay>
Задержка схемы на реальных элементах составляет 25–32 нс – это сумма задержек трёх последовательных элементов (около 7–11 нс на элемент у модели ТТЛ-микросхемы 7400). Переход 0 → 1 на выходе дольше, чем 1 → 0, так как у ТТЛ-элементов время включения $t_"PLH"$ больше времени выключения $t_"PHL"$. Выходной сигнал оказывается сдвинутым вправо относительно входных наборов (сравните @fig:sdnf-tr и @fig:nand-tr).
В отличие от примера методички, ложных срабатываний в модели нет. Причина – в устройстве схемы: при смене набора выход может «дёрнуться» только если на входы одного элемента приходят два меняющихся сигнала с разной задержкой. Такие места в схеме есть:
- переход 0001 → 0010 (X1 падает, X2 растёт, $Y = 0 → 0$): на элемент C приходят $overline(X_1)$ (растёт) и $overline(X_2)$ (падает). Если бы $overline(X_1)$ вырос раньше, чем упадёт $overline(X_2)$, на короткое время оба были бы равны 1, $C = 0$, и на выходе появился бы ложный импульс «1». У модели 7400 спад ($t_"PHL" approx 7$ нс) быстрее нарастания ($t_"PLH" approx 11$ нс), поэтому $overline(X_2)$ успевает упасть первым и импульса нет;
- переход 1001 → 1010 ($Y = 1 → 1$): элемент A = И-НЕ($X_1$, $X_2$) получает сразу два меняющихся входа; генератор Stim4 меняет их строго одновременно, поэтому провала нет.
У реальных микросхем 74HC времена $t_"PLH"$ и $t_"PHL"$ почти одинаковы, а входные сигналы от микроконтроллера меняются не одновременно, поэтому на стенде в этих местах ложные срабатывания вполне возможны (см. раздел 7).
// =====================================================================
= 4 Экспериментальная часть: измеренные задержки
Измерения выполняются на лабораторном стенде: на вход цепочки инверторов 74HC04 подаётся меандр 20 кГц с микроконтроллера ESP32-C3 (программа – Приложение А), осциллограф Hantek DSO2D10 подключается каналом CH1 ко входу цепочки, каналом CH2 – к выходу. Задержка измеряется между уровнями 50 % фронтов (курсорами по времени или автоматическим измерением Delay CH1→CH2). Подробный порядок действий – в Приложении Б.
Справочные значения для 74HC04 (Texas Instruments, $C_L = 50$ пФ, 25 °C): $t_"pd"$ тип. = 45 нс при 2 В, 9 нс при 4,5 В, 8 нс при 6 В; максимум 19 нс при 4,5 В. Для 3,3 В в справочнике нет строки – по интерполяции типовое значение порядка 12–15 нс. На плате нагрузка меньше 50 пФ (вход следующего элемента + щуп), поэтому реальные задержки могут быть меньше справочных.
#figure(
table(columns: (2.6cm, 2.2cm, 3.8cm, 3.6cm, 3.6cm), align: center + horizon,
..hdr[Число инверторов][Питание, В][Ожидаемая задержка (оценка), нс][Измеренная задержка, нс][Задержка на один инвертор, нс],
[2], [3,3], [24 … 30], [#fill-in[]], [#fill-in[]],
[2], [5,0], [16 … 18], [#fill-in[]], [#fill-in[]],
[6], [3,3], [72 … 90], [#fill-in[]], [#fill-in[]],
[6], [5,0], [48 … 54], [#fill-in[]], [#fill-in[]]),
caption: [Задержка распространения цепочки инверторов 74HC04]) <tab:delays>
Задержка на один инвертор = измеренная задержка / число инверторов. Ожидается, что: 1) задержка цепочки из 6 инверторов примерно втрое больше, чем из 2; 2) при 3,3 В задержка заметно (в 1,4–1,7 раза) больше, чем при 5 В.
*Важное замечание для измерений при 5 В.* Микроконтроллер выдаёт сигнал 3,3 В, а при питании 74HC от 5 В гарантированный порог «единицы» на входе $V_"IH"$ = 3,5 В. Обычно элемент всё равно переключается (реальный порог около $V_"CC"$/2 ≈ 2,5 В), но задержка первого инвертора при этом может немного отличаться – это стоит отметить при обсуждении результатов.
// =====================================================================
= 5 Осциллограммы сигналов
На каждой осциллограмме должны быть видны вход (CH1) и выход (CH2) цепочки и измеренное значение задержки. Удобно растянуть по времени один фронт (развёртка 10–20 нс/дел.). Снимок экрана осциллографа сохраняется на флешку (кнопка Save/Print) или фотографируется.
#figure(placeholder[осциллограмму: 2 инвертора, 3,3 В], caption: [Вход и выход цепочки из 2 инверторов, питание 3,3 В])
#figure(placeholder[осциллограмму: 2 инвертора, 5 В], caption: [Вход и выход цепочки из 2 инверторов, питание 5 В])
#figure(placeholder[осциллограмму: 6 инверторов, 3,3 В], caption: [Вход и выход цепочки из 6 инверторов, питание 3,3 В])
#figure(placeholder[осциллограмму: 6 инверторов, 5 В], caption: [Вход и выход цепочки из 6 инверторов, питание 5 В])
// =====================================================================
= 6 Временные диаграммы, измеренные через DSView
На плате собирается схема минимальной функции на элементах 2И-НЕ (@fig:nand-sch). Выводы микроконтроллера подключаются к входам: GPIO6 → X1, GPIO7 → X2, GPIO8 → X3 (в схеме не используется, но записывается анализатором), GPIO10 → X4. Логический анализатор DSLogic: каналы 0–3 → X1…X4, канал 4 → выход Y, земля анализатора – на GND платы. Программа перебирает наборы 0000…1111, каждый длится 100 мкс (10 кГц). В DSView частота выборки – не ниже 100 МГц, чтобы были видны короткие (десятки наносекунд) ложные импульсы.
#figure(
table(columns: (5.4cm, 2.0cm, 4.4cm, 3.6cm), align: center + horizon,
..hdr[Элемент схемы][Функция][Входы][Выход],
[X1 (1-й элемент 1-й микросхемы)], [$overline(X_1)$], [X1, X1 (выв. 1, 2)], [$overline(X_1)$ (выв. 3)],
[X2 (2-й элемент 1-й микросхемы)], [$overline(X_2)$], [X2, X2 (выв. 4, 5)], [$overline(X_2)$ (выв. 6)],
[X3 (3-й элемент 1-й микросхемы)], [A], [X1, X2 (выв. 9, 10)], [A (выв. 8)],
[X4 (4-й элемент 1-й микросхемы)], [C], [$overline(X_1)$, $overline(X_2)$ (выв. 12, 13)], [C (выв. 11)],
[X5 (1-й элемент 2-й микросхемы)], [B], [X4, A (выв. 1, 2)], [B (выв. 3)],
[X6 (2-й элемент 2-й микросхемы)], [Y], [C, B (выв. 4, 5)], [Y (выв. 6)]),
caption: [Подключение элементов 74HC00 на плате (пример; номера выводов – по даташиту 74HC00)]) <tab:wiring>
На плате выводы микросхем выведены на штыревые разъёмы (см. разводку в Приложении 2 методички), поэтому соединения делаются перемычками между соответствующими контактами.
#figure(placeholder[снимок DSView: весь цикл 1,6 мс], caption: [Временная диаграмма схемы индивидуального варианта, снятая в DSView (полный перебор 0000…1111)])
#figure(placeholder[снимок DSView: увеличенный фрагмент с ложным импульсом], caption: [Ложное срабатывание крупным планом (DSView)])
#figure(placeholder[снимок DSView после включения 74HC14], caption: [Устранение ложного срабатывания триггером Шмитта 74HC14 (DSView)])
Устранение ложного срабатывания (пп. 29–31 порядка выполнения). Выход схемы подключается ко входу инвертора с триггером Шмитта 74HC14; так как элемент инвертирующий, для получения прямого сигнала $Y$ ставят два таких инвертора последовательно (или анализируют $overline(Y)$). Короткий импульс длительностью в единицы наносекунд не успевает перезарядить входную ёмкость до верхнего порога $V_(T+)$ (≈ 2,5 В при 4,5 В питания), и триггер Шмитта его не пропускает. Если импульс длиннее, между выходом схемы и входом 74HC14 включают RC-цепочку (например, $R = 1$ кОм, $C = 100$ пФ, $tau = 100$ нс): она «растягивает» фронты, а гистерезис триггера Шмитта не даёт медленному фронту вызвать дребезг. Ложные импульсы короче ≈ $tau$ при этом подавляются, а полезный сигнал 10 кГц (100 мкс) лишь задерживается на ≈ 0,1 мкс.
#par(first-line-indent: 0pt)[#fill-in[опишите, какой вариант был выбран, сколько было ложных срабатываний до и после включения 74HC14]]
// =====================================================================
= 7 Сравнение модели с результатом в DSView
Модель Micro-Cap из раздела 3 предполагает, что все входы меняются строго одновременно. Микроконтроллер при записи через `Pin.value()` меняет выводы по очереди, с интервалом в несколько микросекунд. Чтобы предсказать, что покажет DSView, выполнено дополнительное моделирование: генератор меняет X1, X2, X3, X4 по очереди с шагом 8 мкс, новый набор – каждые 100 мкс (10 кГц), схема – та же, на 7400.
#figure(image("../img/mcu-tr.png", width: 100%), caption: [Прогноз для стенда: выводы МК переключаются по очереди (шаг 8 мкс), 10 кГц]) <fig:mcu>
#figure(
table(columns: (3.0cm, 4.2cm, 3.6cm, 5.2cm), align: center + horizon,
..hdr[Переход][Промежуточные наборы][Y по пути][Результат],
[0001 → 0010], [0000], [0 → 1 → 0], table.cell(fill: zero)[ложный импульс «1» ≈ 8 мкс],
[0011 → 0100], [0010, 0000], [0 → 0 → 1 → 1], [выход переключается раньше],
[0101 → 0110], [0100], [0 → 1 → 0], table.cell(fill: zero)[ложный импульс «1» ≈ 8 мкс],
[0111 → 1000], [0110, 0100, 0000], [0 → 0 → 1 → 1 → 1], [выход переключается раньше],
[1001 → 1010], [1000], [1 → 1 → 1], [без изменений],
[1011 → 1100], [1010, 1000], [0 → 1 → 1 → 1], [выход переключается раньше],
[1101 → 1110], [1100], [1 → 1 → 1], [без изменений]),
caption: [Промежуточные наборы при последовательной записи X1 → X2 → X3 → X4]) <tab:seq>
Моделирование (@fig:mcu) подтверждает анализ: на выходе появляются два ложных импульса – в моменты 200 мкс (0001 → 0010) и 600 мкс (0101 → 0110), каждый длительностью ≈ 8 мкс. Если в программе использовать одновременную запись всех четырёх битов в регистр GPIO (переменная `SIMULTANEOUS = True`, Приложение А), эти импульсы исчезают, и остаются только возможные наносекундные ложные срабатывания из-за разных задержек элементов (раздел 3.7.5). Такие импульсы триггер Шмитта (с RC-цепочкой) подавить может, а микросекундные – нет: они по сути являются «настоящими» промежуточными входными наборами.
#figure(
table(columns: (6.2cm, 4.8cm, 5.0cm), align: center + horizon,
..hdr[Параметр][Модель Micro-Cap][DSView (эксперимент)],
[Значения Y на 16 наборах], [совпадают с @tab:full], [#fill-in[]],
[Задержка выхода относительно входа], [25–29 нс (ТТЛ 7400)], [#fill-in[]],
[Ложные срабатывания при одновременной смене входов], [нет], [#fill-in[]],
[Ложные срабатывания при записи битов по очереди], [2 (на 200 и 600 мкс, ≈ 8 мкс)], [#fill-in[]],
[После включения 74HC14], [—], [#fill-in[]]),
caption: [Сравнение модели и эксперимента]) <tab:compare>
#par(first-line-indent: 0pt)[#fill-in[сравните: совпали ли значения Y с моделью, сколько ложных срабатываний и где, их длительность]]
// =====================================================================
= 8 Вывод
1. Для студента Бояров Данила по буквам имени и фамилии построена таблица истинности функции четырёх переменных (единицы на наборах 0000, 0100, 1001, 1110; нули на 0001, 0010, 0011, 1111), записана СДНФ.
2. С помощью карт Карно с доопределением безразличных наборов функция минимизирована по единицам ($Y = overline(X_2) thin overline(X_1) + X_4 overline(X_2) + X_4 overline(X_1)$) и по нулям ($Y = (X_4 + overline(X_1))(X_4 + overline(X_2))(overline(X_2) + overline(X_1))$); функция не зависит от X3. Прямой перевод этих форм в базисы 2И-НЕ и 2ИЛИ-НЕ требует по 8 элементов, а скобочные формы – по 6 элементов; перебором подтверждено, что 6 – минимум.
3. Моделирование в Micro-Cap подтвердило правильность варианта: схема СДНФ на идеальных примитивах и минимальные схемы на 7400 и 7402 дают на всех заданных наборах требуемые значения. У схем на реальных элементах выход запаздывает на 25–29 нс (7400) и 28–32 нс (7402), ложных срабатываний при одновременной смене входов в модели нет. Показано, что при последовательной записи битов микроконтроллером следует ожидать два ложных импульса.
4. Экспериментальная часть: #fill-in[задержка одного инвертора 74HC04 при 3,3 В составила … нс, при 5 В – … нс; задержка растёт пропорционально числу инверторов и уменьшается с ростом напряжения питания; в DSView наблюдалось … ложных срабатываний, после включения триггера Шмитта …]
// =====================================================================
#pagebreak()
= Приложение А. Программы для микроконтроллера
Микроконтроллер – ESP32-C3 Super Mini с MicroPython. Используемые выводы выведены на разъём J1 платы (GPIO6, 7, 8, 9, 10, 20, 21). GPIO20 и GPIO21 заняты последовательным портом (консолью) и не используются.
#par(first-line-indent: 0pt)[*А.1 Меандр 20 кГц (п. 3 порядка выполнения), файл main.py:*]
#block(fill: luma(242), stroke: 0.5pt, inset: 6pt, width: 100%)[
```python
# ЛР2601, п. 3 порядка выполнения: меандр 20 кГц на выводе микроконтроллера
# Плата: ESP32-C3 Super Mini, MicroPython.
# Сигнал снимается с GPIO6 (разъём J1, контакт 8) и подаётся на вход первого инвертора.
#
# Используется аппаратный ШИМ: частота выдерживается точно
# и не зависит от скорости интерпретатора Python.
from machine import Pin, PWM
OUT_PIN = 6 # номер GPIO, при необходимости поменять
FREQ = 20_000 # 20 кГц -> период 50 мкс
pwm = PWM(Pin(OUT_PIN, Pin.OUT), freq=FREQ, duty_u16=32768) # скважность 50 %
# Программа ничего больше не делает: ШИМ работает сам по себе.
# Остановить: pwm.deinit()
# ---------------------------------------------------------------------------
# Вариант только на классе Pin (как в Приложении 3 методички).
# Частота получится НЕ ровно 20 кГц: каждая команда Python на ESP32-C3
# выполняется несколько микросекунд. Используйте, если преподаватель
# требует решение именно через Pin.on()/Pin.off().
#
# from machine import Pin
# import time
# p = Pin(OUT_PIN, Pin.OUT)
# half = 25 # полпериода 25 мкс
# t = time.ticks_us()
# while True:
# p.on()
# t = time.ticks_add(t, half)
# while time.ticks_diff(t, time.ticks_us()) > 0:
# pass
# p.off()
# t = time.ticks_add(t, half)
# while time.ticks_diff(t, time.ticks_us()) > 0:
# pass
```
]
Используется аппаратный ШИМ: частота ровно 20 кГц и не зависит от скорости интерпретатора. Вариант через `Pin.on()`/`Pin.off()` приведён в комментарии – он даст частоту чуть ниже 20 кГц из-за времени выполнения команд Python.
#par(first-line-indent: 0pt)[*А.2 Перебор таблицы истинности с частотой 10 кГц (п. 22), файл main.py:*]
#block(fill: luma(242), stroke: 0.5pt, inset: 6pt, width: 100%)[
```python
# ЛР2601, п. 22 порядка выполнения: перебор таблицы истинности 0000..1111
# с частотой 10 кГц (новый входной набор каждые 100 мкс).
# Плата: ESP32-C3 Super Mini, MicroPython.
#
# Подключение (разъём J1):
# X1 (младший разряд) -> GPIO6 (J1, конт. 8)
# X2 -> GPIO7 (J1, конт. 7)
# X3 -> GPIO8 (J1, конт. 6)
# X4 (старший разряд) -> GPIO10 (J1, конт. 4)
# GPIO20/21 не используем: это UART, через него работает консоль MicroPython.
from machine import Pin
import time
PINS = [6, 7, 8, 10] # X1, X2, X3, X4
STEP_US = 100 # 10 кГц -> 100 мкс на один набор
x = [Pin(n, Pin.OUT, value=0) for n in PINS]
SIMULTANEOUS = True # True - все 4 бита меняются одной записью в регистр
# Регистр выходов GPIO ESP32-C3 (Technical Reference Manual, глава GPIO):
GPIO_OUT_REG = 0x60004004
MASK = 0
for n in PINS:
MASK |= 1 << n
def write_code(code):
if SIMULTANEOUS:
from machine import mem32
v = mem32[GPIO_OUT_REG] & ~MASK
for i, n in enumerate(PINS):
if code >> i & 1:
v |= 1 << n
mem32[GPIO_OUT_REG] = v # все выводы переключаются одновременно
else:
for i, p in enumerate(x): # по очереди X1, X2, X3, X4 (как в Приложении 3)
p.value(code >> i & 1)
t = time.ticks_us()
code = 0
while True:
write_code(code)
code = (code + 1) & 0x0F # 0000 -> 0001 -> ... -> 1111 -> 0000
t = time.ticks_add(t, STEP_US)
while time.ticks_diff(t, time.ticks_us()) > 0:
pass
```
]
При `SIMULTANEOUS = True` все четыре бита меняются одной записью в регистр выходов GPIO (адрес по техническому руководству ESP32-C3), при `False` – по очереди через `Pin.value()`, как в Приложении 3 методички. Сравнение этих двух режимов в DSView наглядно показывает, откуда берутся ложные срабатывания (раздел 7).
// =====================================================================
= Приложение Б. Памятка: как выполнить работу на стенде
#par(first-line-indent: 0pt)[_Порядок соответствует пунктам методички._]
#set par(first-line-indent: 0pt)
+ Получить у преподавателя плату, анализатор DSLogic, провода-перемычки и джамперы.
+ Запустить Visual Studio Code, открыть проект `/home/ros/Documents/DigitalLab`.
+ Создать в проекте файл main.py и вставить в него программу А.1 (меандр 20 кГц на GPIO6).
+ Подключить плату кабелем USB Type-C – USB Type-A к компьютеру, загрузить main.py на микроконтроллер (как именно – по инструктажу преподавателя, обычно кнопка Upload расширения MicroPython/Pymakr). Отключить плату.
+ Перемычками соединить последовательно 2 инвертора в секции «НЕ» (74HC04): выход 1-го → вход 2-го.
+ Джампер J3 поставить в положение 3,3 В (J3 выбирает, от чего питаются микросхемы: 5 В или 3,3 В).
+ Перемычкой соединить GPIO6 (J1) со входом первого инвертора.
+ Осциллограф: CH1 – на вход цепочки, CH2 – на выход, «крокодилы» щупов – на GND платы.
+ Подать питание на плату от блока питания USB Type-C. На осциллографе: синхронизация по CH1, по фронту; развёртка сначала 10 мкс/дел. (видно меандр 20 кГц), затем 10–20 нс/дел. (виден один фронт с задержкой).
+ Измерить задержку курсорами между точками 50 % амплитуды на CH1 и CH2 (или функцией Measure → Delay). Записать в @tab:delays, сохранить снимок экрана.
+ Переставить J3 на 5 В, повторить измерение.
+ Вернуть 3,3 В, собрать цепочку из 6 инверторов, повторить измерения при 3,3 В и 5 В. Вернуть 3,3 В. Отключить питание.
+ Записать в main.py программу А.2. Собрать на элементах 2И-НЕ схему @fig:nand-sch по @tab:wiring (две микросхемы 74HC00: инверторы X1, X2 и элементы A, C в первой, B и Y во второй).
+ Подключить GPIO6/7/8/10 к входам X1/X2/X3/X4, DSLogic: каналы 0–3 на X1–X4, канал 4 на выход Y, GND на GND.
+ Подключить плату к ПК, запустить программу. В DSView выставить частоту выборки 100 МГц или выше, длительность записи ≈ 2–5 мс, пороговое напряжение 1,6 В (для 3,3 В логики), нажать Start, сохранить диаграмму.
+ Повторить для вариантов других студентов бригады; выбрать вариант с наименьшим (но не нулевым) числом ложных срабатываний.
+ Включить после выхода схемы инвертирующий триггер Шмитта 74HC14 (при необходимости – с RC-цепочкой, раздел 6), зафиксировать в DSView, что ложное срабатывание исчезло.
+ Отключить плату от ПК и сдать преподавателю.
_Если ложных срабатываний в режиме `SIMULTANEOUS = True` не видно, переключите `SIMULTANEOUS = False` – по прогнозу (@fig:mcu) появятся два ложных импульса по несколько микросекунд._
// =====================================================================
= Приложение В. Файлы, прилагаемые к отчёту
- *MicroCap/LR2601\_1\_SDNF\_primitives.cir* – исходная функция (СДНФ) на примитивах (@fig:sdnf-sch, @fig:sdnf-tr);
- *MicroCap/LR2601\_2\_min\_7400\_NAND.cir* – минимальная функция на 7400 (@fig:nand-sch, @fig:nand-tr);
- *MicroCap/LR2601\_3\_min\_7402\_NOR.cir* – минимальная функция на 7402 (@fig:nor-sch, @fig:nor-tr);
- *MicroCap/LR2601\_4\_7400\_MCU\_seq.cir* – прогноз для стенда (последовательная запись битов, @fig:mcu);
- *micropython/main\_20kHz.py* – меандр 20 кГц;
- *micropython/main\_truth\_table.py* – перебор таблицы истинности 10 кГц.
Файлы .cir открываются в Micro-Cap 12 (File → Open); анализ запускается через Analysis → Transient → Run (F2).