Clock Enable - что может быть проще?
nabbla1 — 08.11.2025
В заметке Безумный MAX3032: зазеркалье отрицательных фронтов мы
разобрали схему D-триггера со срабатыванием по фронту,
реализованную на КМОП элементах. Правда, её предпочитают чуточку
перекомпоновать - транзисторов остаётся столько же, но задержка от
фронта тактовой частоты до выдачи нового значения на выходе
снижается. Под катом покажу этот вариант.Данный драндулет иногда сокращённо называют DFF - D Flip Flop. В английской терминологии различают Flip Flop (FF), это когда срабатывает по фронту, и Latch, когда просто по уровню. У нас последний тоже зовут триггер-защёлка, иногда: прозрачный триггер (поскольку когда C=1, он просто передаёт сигнал со входа на выход, как бы "просвечивает насквозь").
Меня "с детства" (со 2го курса института) научили перестать бояться и полюбить разновидность этой штуки по имени DFFE - D Flip Flop with Enable, т.е кроме входов Clk и D появляется ещё один, CE (Clock Enable), который "разрешает" триггеру отработать фронт тактовой частоты. Поначалу кажется, что это совершенно тривиальная доработка, выполненная на одном логическом элементе:

(и бывает, люди БОЯТСЯ ИСПОЛЬЗОВАТЬ CE, поскольку это же clock gating, а это плохо-плохо-плохо, очень рискованно!)
Хитрость в том, что этот вход разрешения должен быть СИНХРОННЫМ, т.е вообще без проблем переносить всевозможные выбросы, покуда они затухнут к моменту фронта clk:

В этом вся прелесть синхронных схем: наверняка этот clock enable неким нетривиальным образом зависит от текущего состояния. Например, счётчик продолжит счёт, если ещё не досчитал до крайнего значения, при этом наш конечный автомат находится в состоянии Run, либо надо разрешить загрузить новое значение с шины данных, ежели пришёл разрешающий сигнал на ножку sload, и так далее. И в "многоэтажной" комбинаторной логике могут проскочить выбросы, когда clock enable ошибочно установится в единицу, а потом сбросится назад в ноль (или наоборот). А ещё, как только фронт пришёл, и выходы регистров начинают выдавать своё новое состояние, clock enable может уже начать меняться, и нам это не должно навредить!
И реализовать такой вход на удивление нетривиальная задача!
Повторим схему DFF из той заметки с кратким пояснением, как оно работает:

Изобразим более шуструю схему DFF на том же количестве транзисторов:

Тогда мы для наглядности изобразили буферные элементы, и всю сущность триггера - буферный элемент, замкнутый на самого себя, и размыкаемый временно, чтобы занести в него новое значение.
А здесь мы всё-таки "распилили" его назад на два инвертора, и один из них пустили только в "обратную связь", ведь так новое значение появится на выходе чуть раньше, ему надо пройти только через один инвертор, а не через два. А поскольку триггер двухступенчатый, то выход по-прежнему неинвертированный, т.е функционально работает точно так же.
Пока clk=0, первый триггер принимает в себя данные, идущие со входа. Поначалу они могут быть кривыми, потом устанавливаются, и самое последнее значение, которое было, прежде чем clk переключилось в 1, там фиксируется. И так должно происходить в любом случае: заставить его хранить старое значение именно здесь, а потом за наносекунду до переключения clk вдруг опомниться "опа, у нас ce=1, давайте быстро запоминать!" - нереально. Не может быть никаких "за наносекунду", для триггера clk=1 ПРИХОДИТ НЕОЖИДАННО, он внутри себя "не чувствует хода времени"!
Значит, чтобы при ce=0 мы могли сохранить старое значение, необходимо запретить второму триггеру переключаться в прозрачный режим, когда становится clk=1, и нужно НА ПОЛТАКТА ЗАПОМНИТЬ, что ему переключаться нельзя! Мы не можем рассчитывать, что на входе ce сохранится правильное значение, следовательно, если мы хотим пойти по этому пути, надо свой собственный триггер для ce. А это штука толстая, любой триггер, даже самый простенький RS. Там минимум два элемента И-НЕ, по КМОП технологии это 8 транзисторов. Картина маслом ПРИПЛЫЛИ.
Как ни странно, самым компактным выходом, когда нам нужен ИНДИВИДУАЛЬНЫЙ ce на один триггер, является следующий:

ЕЩЁ ОДИН АНАЛОГОВЫЙ ПЕРЕКЛЮЧАТЕЛЬ. Т.е мы вообще не лезем в тактовые цепи (раз они такие злые), а попросту решаем, что подать на вход триггера. То ли новые данные с входа D, то ли свой же собственный выход, чтобы сохранить старое значение.
На всё про всё - лишних 6 транзисторов. Два из них - для "размыкающего" ключа, два - для "замыкающего", плюс инвертор, чтобы они работали в противофазе (и чтобы подать правильное напряжение на затвор p-канальных транзисторов в ключе). Причём, если у нас один сигнал ce питает сразу много триггеров, инвертор можно поставить один общий. Для контекста: тривиальный логический элемент И, с которого мы начали, потребовал бы те же 6 транзисторов, 4 на И-НЕ и инвертор на выходе. Только он бы ещё не заработал, как нам надо, а здесь всё чётко. UPD: если так подумать, инвертор дополнительно не нужен, там один уже и так есть, так что 4 транзистора. Но это схоластика, всяко схема не рабочая.
И действительно, ровно так рисуют принципиальную схему регистров с clock enable в даташитах, хотя и с заметкой "чисто в качестве иллюстрации, не используйте эту схему для оценки задержек!" Например, вот:

Не знаю, почему, но вместо "аналогового переключателя" рисуют мультиплексор по классической схеме. Видимо, принципиальная схема "унаследована" с ТТЛ микросхем. Если было 74, а стало 74AC (advanced CMOS) - зачем логическую диаграмму менять!
Впрочем, встретил я и такую схему:

Тут, раз уж clock enable один на 9 триггеров, можно не пихать 9 переключателей, а поставить один-единственный триггер, который запомнит, чему же clock enable равнялся при фронте clk.
Меня поначалу очень сбила с толку буква n перед всеми названиями. Я привык, что это значит negative и используется, когда у нас нет возможности нарисовать черту над именем, например, где-нибудь в verilog / VHDL, хотя оттуда оно разбрелось уже очень широко.
Но здесь и чёрточки, и n, причём n повсюду, что за нафиг... Оказалось, это очень толстая микросхема, состоящая из двух половинок, каждая - это 9-битный регистр с отдельным входом разрешения работы. И n-это "переменная", которая равна или 1 или 2.
В схеме явная ошибка: у 8 триггеров тактовая частота нарисована с кружочком инверсии, но у последнего - без него.
Элемент И, у которого инвертированы ВХОДЫ, мне тоже как-то не близок. Так что перерисую по нашим ГОСТам (хотя ГОСТ не предполагает использование тетради в клеточку и рисование "от руки"):

А вход я обзову всё-таки nCE, т.е с обратным знаком. Так вот, если он равен единице, значит, триггер должен хранить своё старое значение. И действительно, единица на одном из входов верхнего ИЛИ-НЕ означает заведомый ноль на его выходе, поэтому gCLK (gated CLK) будет сидеть в нуле. По сути, nCE подключён к входу R (Reset, сброс) RS-триггера.
clk подключён, соответственно, к входу S.
Обычно говорят, что подавать активные сигналы одновременно на входы S и R запрещено, но здесь это будет происходить сплошь и рядом. Поскольку мы используем выход верхнего элемента ИЛИ-НЕ, у триггера вход R получается более приоритетным, т.е когда одновременно R=S=1, на выходе получим 0 (R победит). Если они теперь одновременно сбросятся в ноль, результат окажется неопределённым - как фишка ляжет.
Попытаемся понять, как эта штука поведёт себя, если nCE начнёт хаотично переключаться взад-вперёд.
Пока clk=0, эти переключения, как минимум, не пройдут на выход за счёт элемента И. Если хоть на одно короткое мгновение nCE переключится в 1 (т.е запрет защёлкивания новых данных в наши триггеры для данных), этого хватит, чтобы RS-триггер переключился в 0. Это уже подозрительно: выходит, что nCE должен установиться в правильное значение уже к моменту clk=0, т.е на полтакта раньше! Иначе случайный сбой нарушит нашу логику.
Но и дальше всё странно. Допустим, на всём протяжении clk=0 у нас было nCE = 0 (защёлкивание данных разрешено), поэтому как RS-триггер был установлен в единицу за счёт clk=1, так пока и хранит это состояние. Вот прошёл фронт clk, т.е снова установилось clk=1, и они переданы на выход, в gCLK. Но если мы сейчас установим nCE=1, то это БЕСПРЕПЯТСТВЕННО пройдёт в gCLK внезапным переключением в ноль! А возврат в nCE=0 - переключением в единицу!
В общем, на мой взгляд, схема неверная. Вероятно, они её тоже нарисовали для иллюстрации, и не шибко задумывались о её работе. Или я что-то не понимаю.
До сих пор для меня открыт вопрос - может ли превращение clk в троичный сигнал как-то упростить всю эту машинерию? И если да, то как вообще должен выглядеть этот сигнал - "пила" или "треугольник"?
|
|
</> |
Оплата зарубежных сервисов и подписок
Это конец!!!!
Салаты и прочее на Новогоднем застолье
Очередной скандал в стане раскольников между УПЦ КП и ПЦУ
Ольга Аристова «Раз, два, три — замри»
Котики
Доступность красной икры в СССР
Травма отвержения.
диалоговый вычислительный комплекс

