1i7

Лабораторная работа 3: делаем память (защелки и триггеры) (1)

Aug 21, 2012 04:02

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

Поэтому для реализации этих более сложных и полезных вещей используется другой подход, который называется секвенциальная (или последовательностная) логика (sequential logic).

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




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



Упражнение 1: RS защелка (RS latch) на макетной плате

Один из самых элементарных триггеров - это RS защелка (или RS триггер). Его можно сделать из 2х модулей NAND, зацикленных друг на друга.

Замечание: насколько я понял, жесткого устоявшегося различия между терминами защелка (latch) и триггер (flip-flop) не существует. В журнале Tron.ix и на многих ресурсах в интернете RS защелка (RS latch) называется RS flip-flop (RS триггер). Однако в книге Harris & Harris между защелками и триггерами проводится различие, обусловленное необходимостью отличать два типа триггеров - D latch (D защелка) и основанный на ней чуть более сложный D flip-flop (D триггер), ну и также некоторыми особенностями механизмов их работы, которые станут понятны после последнего упражнения ниже. Здесь и далее я буду следовать терминологии Harris & Harris и различать защелки и триггеры, хотя в другой литературе схемы аналогичные описанным здесь защелкам могут называться триггерами без потери корректности. В русской википедии D latch (D защелка) называется D-триггером, а D flip-flop (D триггер) называется двухтактным D-триггером.




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




1. R=0, S=0: Очевидно, что оба выхода Q и ~Q на схеме будут равны 1, т.к. для обоих NAND'ов для выдачи значения 1 на выход достаточно подать 1 хотябы на одну входящую ножку, а промежуточные обратные связи между NAND'ами при такой схеме роли не играют. Подобное состояния не итересно с точки зрения функционала защелки и считается некорректным. Итого: Q=1, ~Q=1.

2. R=0, S=1: Выход Q будет равен 1, т.к. для этого достаточно подать значение 0 на любую ножку его NAND'а (что мы и сделали, подав 0 на R), значение 2й "зацикленной" ножки роли не играет. Для ~Q смотрим дальше - 1я ножка его NAND'а S=1, т.е. по таблице истинности NAND финальное значение оператора может быть как 0, так и 1 и будет зависеть от значения 2й входной ножки. Смотрим, чему равно значение 2й ножки - оно равно результату работы 1го оператора NAND Q, который как только что выяснили обязательно равен 1. Итого получаем на втором операторе NAND два входа 1 и 1 - итоговое значение ~Q=0. Итого: Q=1, ~Q=0.

3. R=1, S=0: Цепочка рассуждений зеркальна пункту 2. Итого: Q=0, ~Q=1.

4. R=1, S=1: Самая интересная ситуация, которая собственно и определяет полезность этой RS защелки как модуля памяти. Судя по таблице истинности, финальные значения Q и ~Q  не могут быть определены, основываясь только на значениях R и S, если они оба равны 1, т.к. и для верхнего и для нижнего NAND'а требуется знать значение "зацикленной" ножки, но верхний NAND может получить его только от нижнего NANA'а (значение ~Q), а нижний NAND может получить его только от верхнего NAND'а (Q). Поэтому для решения это проблемы требуется рассмотреть ситуацию, которая произошла "за мгновение" до перехода в состояние в текущее состояние R=1, S=1.

4.1. Если значение R было равно 0 (S так и было 1), то значение Q было равно 1, т.е. "зацикленный" вход нижнего NAND'а был тоже равен 1, соответственно выход ~Q нижнего NAND'а равнялся 0 (полностью повторение ситуации 2). Теперь если мы из этого положения переходим в состояние 4, т.е. переносим вход R с 0 на 1, это ситуацию ни коим образом не меняет, т.к. "зацикленный" вход верхнего NAND'а равен ~Q=0, а это значит, что выход Q по таблице истинности все равно будет равен 1 вне зависимости от значения R, т.е. мы попали в начало цепочки 4.1 (или 2 - не важно), только с другим значением R. Итого: Q=1, ~Q=0.

4.2. Значение S было равно 0 (R так и было 1): зеркально предыдущему пункту 4.1. Итого: Q=0, ~Q=1.

В итоге мы получили, что в состоянии 4, когда и R=1 и S=1, система находится в стабильном состоянии, которая она запомнила с прошлого раза. Т.к. вариантов различных стабильных состояний всего 2 ("Q=1, ~Q=0" или "Q=0, ~Q=1"), то можно считать, что такая система может запоминать один бинарный бит информации (Q=1 или Q=0, ~Q вообще говоря можно отбросить), который устанавливается в 1 и сбрасывается в 0 через входы R и S соответственно (отсюда название защелки RESET и SET ... R и S при желании можно поменять местами).

Замечание: в журнале Tron.ix на странице со схемой RS защелки (там она называется RS flip-flop, т.е. RS триггер) в разъяснениях разобраны только случаи 2 и 3, которые обозначаются как стабильные состояния системы и говорится, что по этой причине их можно считать за память, а случаи 1 и 4 не разобраны вообще. Лично мне было не очень понятно, в чем фишка такой стабильности, которая однозначно определена текущими значениями входов системы, ведь элементарный оператор NOT или прямое подключение такого входа к светодиоду будет также давать на выходе стабильный +/-. Но книга Harris & Harris полностью прояснила ситуацию, т.к. там RS защелка (там она называется как раз RS latch, а не RS flip-flop) была разобрана во всех подробностях - перечисленные 5 случаев по сути взяты оттуда.

Подобную схему довольно легко собрать на макетной плате - для этого вспоминаем модуль 4011, состоящий из 4х элементов NAND из 1й лабораторной работы:




Для визуализации значений Q и ~Q используем 2 светодиода, входы R и S оставляем торчать свободными проводами:




Для наглядности - смотрим как работает на живой плате:

1. Следим за желтым проводом (пусть это будет RESET) - он воткнут в (-) (RESET=0), коричневый (SET) в (+) (SET=1) - правая лампа (Q) горит (Q=1), левая (~Q) не горит (~Q=0).




2. Теперь перетыкаем желтый провод в (+) (RESET=1, SET=1) - лампочки остаются в старом состоянии (Q=1, ~Q=0), т.е. они его запомнили.




3. Аналогично для коричневого провода SET - втыкаем в (-) - состояние системы меняется - левая лампочка загорается, правая гаснет (Q=0, ~Q=1).




4. Возвращаем коричневый провод SET на место в (+) - лампочки остаются в предыдущем состоянии.




Можно обратить внимание, что состояния 2 и 4 идентичны с точки зрения значений входных сигналов (SET=RESET=1), но лампочки горят поразному из-за описанного эффекта.



Хотя RS защелка уже позволяет сохранять 1 бит информации, очевидно, что практическое ее применение не видится оптимальным - в первую очередь потому, что для установки значения требуется управлять 2мя входными сигналами, а если подать значение 0 на оба входа одновременно, то ее состояние и вовсе считается некорректным. По этой причине для более практичных в повседневном использовании вещей были придуманы такие чуть более сложные модели как D-защелка и D-триггер. Однако имплементация их на макетной плате в формате небольшой лабораторной работы мне не показалась достаточно оптимальной (хотя это тоже вполне возможно - в Tron.ix для D-триггера есть специальное упражнение, однако прилагаемая к нему схема довольно громоздка) как в плане времени, так и в плане получения новых полезных практических навыков, поэтому дальнейшие упражнения было решено реализовать при помощи ПЛИС+Verilog, которые дают удобную возможность крайне быстро и наглядно имплементировать логические схемы с нужным аппаратным результатом.









Далее упражнения для быстроты и удобства синтезируем на ПЛИС - имеющихся навыков соединения "внутренних проводков" при помощи логических операторов на языке Verilog для этого уже вполне достаточно. Правда при анализе кода  RS-защелки Xilinx выдает предупреждение:

WARNING:Xst:2170 - Unit rs_latch_top : the following signal(s) form a combinatorial loop: rs/not_q_or0000.

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


Упражнение 2: RS защелка (RS latch) на ПЛИС+Verilog

Но чтобы начать упражнения с ПЛИС, сначала имплементируем на ней опять же RS защелку, только основанную не на 2х операторах NAND, а на 2х операторах NOR.




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

Попробуем теперь реализовать эту схему на ПЛИС (FPGA).

flip_flops.v и flip_flops_top.v

/**
 * RS latch
 */
module rs_latch(
    input r, input s,
    output q, output not_q
    );

assign q = ~(r | not_q);
    assign not_q = ~(s | q);
endmodule

// RS latch test top module
module rs_latch_top(
    input [72:73] pio,
    output [0:1] ld
    );

// RS Latch
    rs_latch rs (.r(pio[72]), .s(pio[73]),
            .q(ld[0]), .not_q(ld[1]));  
endmodule
назначаем на R и S два внешних порта PIO, Q и ~Q показываем на двух лампочках LED

basys2_rs_latch.ucf

# RS latch
NET "PIO<72>" LOC = "B2";
NET "PIO<73>" LOC = "A3";
NET "ld<1>" LOC = "m11" ;
NET "ld<0>" LOC = "m5" ;
Перетыкиваем провода RESET и SET аналогично предыдущему варианту защелки с NAND, только не забываем о смене полярности для ключевых состояний.


















далее в следующей записи >>

плис, цифровая электроника для программистов, verilog

Previous post Next post
Up