Видео в конце...
На этот раз мы проводим один интересный эксперимент и попутно рассматриваем очередные возможности языка Verilog. Аппаратные платформы зачастую имеют множество элементов взаимодействия с окружающим миром. Среди всего этого разнообразия есть механические устройства ввода информации. Это кнопки, клавиши, переключатели и прочее.
Их главное предназначение это отправлять на вход вычислителя сигналы в виде напряжения уровня логического нуля или единицы. Но не все так просто, как кажется на первый взгляд.
Что такое дребезг контактов?
Давайте соберем простое устройство, где по нажатию кнопки будет происходить счет. Возрастающий фронт импульса, порождающегося нажатием кнопки должен вызывать увеличение содержимого счетчика на единицу. Содержимое счетчика выводится на светодиоды. Синтез приводит вот к такой схеме:
От входного контакта button, связанного с кнопкой, сигнал проводится к тактовому входу CLK регистра how. Обратная связь c регистра проходит через сумматор Add0 с единицей и далее на вход D регистра. Это уже знакомый нам счетчик. Содержимое счетчика побитно отправляется на свои светодиоды, при этом каждый бит инвертируется, чтобы удобно восприниматься зрителем.
Получившийся счетчик ведет себя крайне неадекватно и никакого последовательного появления двоичных чисел не происходит (смотрите видео в конце). Это связано с таким явлением, как дребезг контактов. Это явление можно также назвать искрением.
В момент замыкания механических контактов возникает пробой воздушного пространства между ними, так как присутствует пусть и небольшое, но напряжение. Из за того, что проводимость то возникает, то пропадает, цифровое устройство воспринимает это искрение как многократную смену состояния на линии.
Дребезг контактов это вредное явление, так как не отражает реальные действия пользователя.
Для борьбы с этим явлением на аппаратных платформах размещают конденсаторы и резисторы, препятствующие многократной смене состояния на линии.
Заряд и разряд конденсатора обеспечивают изменение напряжения по гладкой траектории и цифровое устройство адекватно воспринимает вводимую информацию. Но что делать, если на платформе отсутствуют конденсаторы?
Устраняем дребезг
Оказывается, что проблему можно решать не только при помощи аналоговых элементов, но и цифровым способом непосредственно внутри вычислителя. Создадим устройство, устраняющее этот негативный эффект. На рисунке изображено напряжение на входе ПЛИС с явно выраженным дребезгом как на заднем фронте импульса, так и на переднем фронте.
Первое, что напрашивается в качестве решения это переждать неприятный участок и считать сигнал когда уровень напряжения будет стабильным. Будем считать уровень единицы стабильным если несколько раз подряд на линии считывается единица. Причем если считывать уровень слишком часто, то можно попасть в момент, когда все единицы подряд будут при дребезге. Очевидно, частоту считывания уровня нужно уменьшить и делать это нужно с такими шагами, чтобы обойти участок дребезга.
Опытным путем установлено, что десятка миллисекунд после переключения достаточно чтобы в большинстве случаев дребезг закончился. Поэтому, по сложившейся традиции, используя счетчик можно дождаться нужного момента. Чтобы придать устройству больше надежности, сделаем так, чтобы три подряд считанных уровня единицы с некоторым интервалом сигнализировали о нажатой кнопке. Во всех других случаях считаем, что кнопка не нажата. Это должно сработать в разных случаях. Как при частичном попадании на участок дребезга, так и при непопадании на этот участок.
Три уровня считанного напряжения нужно где-то хранить. Для этого необходим массив ячеек памяти. Лучше всего не заботиться об адресах этих ячеек и работать с ними по принципу "первый бит пришел, первый вышел". Каждый новый входящий бит запоминается в массиве ячеек, проталкивая в очереди остальные. Самый последний бит в очереди при этом исчезает. В программируемых логических интегральных схемах такая конструкция образуется при последовательном соединении триггеров в цепочку.
Пишем модуль
Приступим к написанию модуля. Для задержки времени нам будет необходим подсчет тактовых импульсов clk. При помощи кнопки button пользователь будет увеличивать число в регистре на единицу. Содержимое регистра выводится на восемь светодиодов HowMuch .
Для работы модуля будут необходимы некоторые регистры. Сам счетчик нажатий кнопки how, регистр счетчика задержки времени delay, три бита сдвигового регистра shift для хранения считанных подряд идущих уровней входной линии с кнопки. Также пригодятся провода ten_ms, level для передачи сигналов внутри модуля. Один из проводов служит для передачи сигнала на чтение уровня входной линии ten_ms, второй level передает итоговый уровень на основании трех ранее считанных.
Назначаем начальные значения всем регистрам:
В первом процедурном блоке по переднему фронту тактового импульса clk ведется счет, что обеспечивает задержку времени между считываниями уровня входного сигнала. Если считать до миллиона, то задержка между считываниями будет 20 миллисекунд (частота clk 50 МГц, сигнал приходит с кварцевого генератора на плате).
Сформируем первый из сигналов ten_ms. Каждое обнуленное значение счетчика delay вызывает сигнал для считывания уровня на входной линии. Буквально, если состояние счетчика 0, то результат истина 1, иначе ложно 0. Нулевое состояние счетчика будет появляться при каждом сбросе, то есть каждые 20 миллисекунд. По переднему фронту этого сигнала содержимое button сдвигается в регистре shift.
Переходим к следующему процедурному блоку. В нем по переднему фронту сигнала считывания ведется запись входного уровня сигнала в сдвиговый регистр. Синтаксис операции склейки компактнее всего описывает эту операцию. Слева от знака равенства будущее состояние сдвигового регистра. Оно представляет собой следующее. Старший разряд это состояние входной линии, два младших это те, которые были ст+аршим и средним. То есть произошел сдвиг бит вправо. На самое первое место записалось состояние входной линии.
Далее в проводник сигнала итогового уровня передается конъюнкция всех бит сдвигового регистра shift. Как только три бита в регистре единицы, то значит итоговый уровень единица.
Переходим к третьему процедурному блоку. По переднему фронту обработанного сигнала с кнопки level производится счет нажатий.
На светодиоды поступают инвертированные (~) биты со счетчика нажатий кнопки how.
Исходный код:
Поддержите статью лайком если понравилось и подпишитесь чтобы ничего не пропускать.