Files
cschem-lab1/pages/content.typ
dboyarov 6d53a2451e lab1
2026-09-24 18:31:50 +03:00

507 lines
54 KiB
Typst
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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).