Учебный курс. Счетчики и сумматоры.

Одним из важных и широко используемых цифровых элементов является счетчик. Мы попробуем разобраться в том, какие счетчики бывают, и как их соорудить из базовых строительных блоков цифровой схемотехники. Мимоходом придется рассмотреть и сумматоры, поскольку они потребуются нам для создания синхронного счетчика. Что же это за счетчик такой и что он считает?

счетчик

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

Ранее мы уже обсуждали недостатки асинхронного дизайна цифровых схем, но в качестве примера все же хочу показать вариант реализации асинхронного счетчика (ripple counter). И хотя он проще, чем синхронный счетчик, и требует меньшее количество логических элементов, никогда не используйте его в своих проектах! Это чревато возникновением ошибок в работе схемы и он может стать причиной появления непонятных глюков. На рисунке ниже представлена схема 4-разрядного асинхронного счетчика на двухтактных D-триггерах:

ripple_counter

Асинхронный счетчик представляет собой последовательное соединение двухтактных D-триггеров. По активному фронту тактового сигнала (CLK) происходит инвертирование состояния первого триггера в цепочке (младший разряд), т. е. выход сменяется с 0 в 1 и наоборот. Тактовый сигнал каждого последующего триггера берется с выхода предыдущего, таким образом, каждый последующий триггер переключается в 2 раза реже предыдущего (DD2 переключается каждый второй такт, DD3 — каждый четвертый такт и т. д.). Эта схема асинхронна и выходы данных будут обновляться поочередно по мере прохождения сигнала по цепочке триггеров.

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

Сумматор, как следует из названия, просто складывает два двоичных числа. Сложение двоичных чисел происходит так же, как и десятичных. В десятичной арифметике доступно 10 цифр — от 0 до 9. Если прибавить к 9 единицу, то происходит переполнение разряда (позиции) числа и происходит перенос единицы в следующий разряд, таким образом, если к 29 прибавить 1, то младший разряд переполнится, там окажется 0, а единица переносится в следующий разряд и прибавляется к его значению (2+1=3), получаем 30. Точно такая же логика справедлива и для двоичных чисел.

Для начала следует рассмотреть одноразрядный сумматор. Как же его сделать из логических элементов? Одноразрядный сумматор имеет два входа (для слагаемых) и два выхода — сумма и перенос в следующий разряд (переполнение). Давайте попытаемся определить, какой логической функции соответствует бит суммы и бит переноса. Очевидно, что перенос в следующий разряд (бит C — Carry) появляется только в том случае, если на входе будут обе единицы, при этом бит суммы будет равен 0, поскольку произошло переполнение разряда. Получается, что бит суммы есть ни что иное, как исключающее ИЛИ входов сумматора (посмотрите на таблицу истинности исключающего ИЛИ и убедитесь в этом сами). При этом, бит переноса С представляет собой логическое И входов (ведь перенос появляется только при обеих единицах на входе).

pic5_2

Эта схема называется полусумматором, поскольку не учитывает бит переноса из предыдущего разряда, хотя сама формирует перенос в следующий разряд. Для учета переноса из предыдущего разряда необходимо прибавить к сумме А и В еще и бит переноса из предыдущего разряда, то есть добавить второй полусумматор:

pic5_3

Таким образом, если перенос сформировался хотя бы на одном из полусумматоров, то он должен появиться на выходе полного сумматора, для этого применим логическое ИЛИ.

pic5_4

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

full_adder

pic5_1

Чтобы реализовать n-разрядный сумматор, нужно n полных сумматоров. На их входы А и В подаются соответствующие разряды чисел, которые необходимо сложить, а вход Cin каждого разряда соединяется с выходом Cout предыдущего разряда, причем на вход Cin младшего разряда подается лог. 0. Ниже показана схема 4-разрядного сумматора ([0] — младший разряд, [3] — старший разряд):

adder

Теперь все готово для реализации синхронного счетчика. Немного усложним задачу и сделаем счетчик, который смог бы вести счет как в прямом, так и в обратном направлении. Введем дополнительный бит направления счета и если он равен 0 — будем прибавлять единицу каждый такт, а если равен 1 — вычитать единицу каждый такт. Со сложением все понятно, но как вычесть единицу? Вычесть единицу из числа это то же самое, что и прибавить к числу «минус единицу». Двоичные числа со знаком представляются в так называемом дополнительном коде. Чтобы получить двоичное представление отрицательного числа необходимо инвертировать все его разряды и прибавить к нему единицу. Например, 4-разрядное число «5» в двоичном виде выглядит как 0101, чтобы получить число «-5» инвертируем биты — получаем 1010 и прибавляем единицу — получаем 1011. Теперь если сложить эти числа 5 и -5, то получим: 0101+1011=10000, при этом произойдет переполнение, единица уйдет в следующий разряд, но мы ее не учитываем (этот разряд «отбрасывается»). Поскольку мы суммировали 4-разрядные числа, то на выходе увидим только 4 младших разряда, т. е. 0000. Важно отметить, что в дополнительном коде старший разряд определяет знак (единица — признак отрицательного числа). Таким образом, в прямом коде 4-разрядным числом можно представить десятичные числа от 0 до 15, а в обратном коде от -8 до 7. 

Итак, приступим к реализации 4-разрядного синхронного счетчика. Счетчик будет иметь 3 входа: тактовый сигнал, направления счета и сигнал сброса (обнуления). Текущее значение счетчика будет хранится в регистре (4 двухтактных D-триггера). С выхода регистра текущее значение счетчика приходит на вход сумматора (скажем, на вход В). На другой вход сумматора (А) поступает значение «1» (0001) или «-1» (1111) в зависимости от направления счета. На выходе сумматора появляется новое значение, увеличенное или уменьшенное на единицу, которое поступает на вход регистра. По активному фронту тактового сигнала это значение сохраняется в регистре и выход счетчика обновляется.

sync_cnt

Если DOWN=0, то на вход A сумматора поступает число 0001 (прибавляем единицу), в противном случае (DOWN=1) на входе сумматора оказывается число 1111 (вычитаем единицу). Заметьте, что все триггеры тактируются единственным сигналом CLK, и все разряды счетчика обновляются одновременно по активному фронту тактового сигнала. Важно понимать, что для правильной работы схемы на выходе сумматора должны успеть появиться новые данные до следующего активного фронта CLK (задержка сумматора не должна превышать период тактового сигнала).

Временная диаграмма сигналов счетчика (счетчик сбрасывается по низкому уровню сигнала RSTn, о чем свидетельствует суффикс «n»):

result_scnt

Вот мы и сделали простейший синхронный счетчик. Далее попробуем описать его на языке Verilog и познакомимся со средой для моделирования ModelSim.

1 комментарий

  1. Уведомление: Часы на ПЛИС | ICDEVICES.RU

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *