Триггеры и защёлки: память на один бит
Урок объясняет, как из обычных вентилей с обратной связью получается элемент, способный хранить один бит.
Триггер (flip-flop) — элемент памяти на один бит, меняющий состояние по тактовому сигналу. Защёлка (latch) — похожий элемент, но «прозрачный»: реагирует на вход уровнем сигнала, а не фронтом.
Зачем схемам память
Комбинационные схемы (сумматор, АЛУ) не помнят прошлого: их выход зависит только от текущих входов. Но процессору нужно хранить состояние — значение регистра, текущую команду, счётчик. Память появляется благодаря обратной связи: выход вентиля заводят обратно на его же вход, и схема «застревает» в одном из устойчивых состояний.
SR-защёлка из двух NOR
Самая простая ячейка — две NOR-схемы, выходы которых перекрёстно заведены на входы. Вход S (set) ставит 1, R (reset) — 0; при S=R=0 защёлка хранит прежнее значение.
S ──→┌──────┐
│ NOR │──┬──→ Q
┌───→└──────┘ │
│ │
│ ┌──────┐←──┘
└───┤ NOR │
R ─→└──────┘──────→ Q'
S=1,R=0 -> Q=1 (set)
S=0,R=1 -> Q=0 (reset)
S=0,R=0 -> Q хранит прежнее значение (ПАМЯТЬ!)
S=1,R=1 -> запрещено
D-триггер: один вход данных + такт
SR-защёлка неудобна (запрещённая комбинация, два входа). На практике используют D-триггер: один вход данных D и тактовый вход. По активному фронту такта он «защёлкивает» текущее D и хранит его до следующего фронта. Это базовый строительный блок регистров. Промоделируем D-триггер как объект с состоянием:
class DFlipFlop:
def __init__(self):
self.q = 0
def clock_edge(self, d):
# по фронту такта запоминаем вход D
self.q = d
return self.q
ff = DFlipFlop()
print("такт | D | Q после фронта")
for t, d in enumerate([1, 1, 0, 0, 1]):
q = ff.clock_edge(d)
print(f" {t} | {d} | {q}")Вывод:
такт | D | Q после фронта 0 | 1 | 1 1 | 1 | 1 2 | 0 | 0 3 | 0 | 0 4 | 1 | 1
Как работает под капотом: фронт против уровня
Защёлка «прозрачна»: пока тактовый уровень активен, выход следует за входом — это опасно, можно «проскочить» лишнее. Триггер срабатывает по фронту (моменту перехода 0→1), то есть мгновенно фиксирует значение. Поэтому почти вся синхронная логика построена на триггерах, тактируемых фронтом: все элементы обновляются одновременно, в один «щелчок» часов.
Глубже в тему
Стоит остановиться на парадоксе, который пугает при первой встрече с памятью: как схема без часов и без «места хранения» вообще что-то помнит? Ответ — в обратной связи. Когда выход вентиля заведён обратно на его собственный вход (через второй вентиль), схема перестаёт быть простой функцией входов: у неё появляются два устойчивых положения, в каждом из которых она поддерживает сама себя. Это похоже на выключатель с фиксацией или на шарик в одной из двух лунок — без внешнего толчка он остаётся, где был. Бит хранится не где-то «в ячейке», а в самом факте того, что схема устойчиво держится за одно из двух состояний. Это и есть фундаментальный переход от комбинационной логики (выход зависит только от текущих входов) к последовательностной (выход зависит ещё и от истории).
Почему запрещена комбинация S=R=1 в SR-защёлке — не каприз, а реальная физика. При одновременном «поставить» и «сбросить» оба выхода вынужденно становятся нулями, нарушая правило, что Q и Q' всегда противоположны. Хуже того, если затем убрать оба сигнала одновременно, схема не «знает», в какое из двух состояний свалиться, и исход зависит от ничтожных различий в задержках вентилей — возникает риск метастабильности, когда выход надолго зависает в неопределённом промежуточном уровне. Именно ради ухода от этих ловушек на практике почти никогда не используют голую SR-защёлку, а строят на её основе D-триггер с единственным входом данных, где запрещённая комбинация конструктивно невозможна.
Разница «уровень против фронта» — это разница между прозрачностью и мгновенным снимком, и она критична для синхронных схем. Защёлка, пока тактовый уровень активен, остаётся «прозрачной»: выход следует за входом, и если за это время вход дёрнется несколько раз, защёлка пропустит все изменения. В схеме с обратной связью такая прозрачность опасна — сигнал может «проскочить» через защёлку и вернуться к ней же в том же такте, испортив состояние. Триггер, тактируемый по фронту, снимает значение входа ровно в момент перепада такта 0→1 и держит его весь такт, оставаясь «непрозрачным» в остальное время. Поэтому почти вся синхронная логика процессора построена именно на фронтовых триггерах.
Практический вывод: фронтовое тактирование даёт дисциплину времени, на которой держится весь процессор. Все триггеры в системе подключены к общему тактовому сигналу и обновляются строго одновременно, в один «щелчок» часов. Между двумя фронтами комбинационная логика спокойно пересчитывает новые значения, а на следующем фронте они разом защёлкиваются. Эта строгая синхронность и позволяет рассуждать о процессоре как о машине, делающей по шагу за такт, — без неё пришлось бы отслеживать тысячи сигналов, меняющихся в произвольные моменты. Из этих самых триггеров в следующем уроке мы соберём регистры и счётчики, а ещё дальше — регистр состояния конечного автомата.
Частые ошибки
- Путать защёлку и триггер. Защёлка реагирует на уровень (прозрачна), триггер — на фронт (защёлкивает в момент).
- Подавать S=R=1. Для SR-защёлки это запрещённое состояние с неопределённым выходом.
- Думать, что триггер хранит много бит. Один триггер — ровно один бит; для n бит нужно n триггеров.
Итог
- Память рождается из обратной связи: выход вентиля заводится на его вход.
- SR-защёлка хранит бит, но имеет запрещённое состояние; D-триггер удобнее (один вход + такт).
- Триггеры срабатывают по фронту такта — основа синхронной логики процессора.