Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Обработка нажатия кнопок
Форум разработчиков электроники ELECTRONIX.ru > Программируемая логика ПЛИС (FPGA,CPLD, PLD) > Языки проектирования на ПЛИС (FPGA)
aBoomest
Всем доброго дня.
Привожу нижеследующий код:
Код
  OnButtonLeft_Down:
  process(OnBtnLeft_DownEvent)
  begin
    if rising_edge(OnBtnLeft_DownEvent) then
        if (PulsePerPeriod_VAR > 0) then
              PulsePerPeriod_VAR := PulsePerPeriod_VAR - 1;           --<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
       end if;
     end if;
  end process OnButtonLeft_Down;

  OnButtonRight_Down:
  process(OnBtnRight_DownEvent)
  begin
    if rising_edge(OnBtnRight_DownEvent) then
        if (PulsePerPeriod_VAR < PulsePerPeriod_VAR_MAX) then
              PulsePerPeriod_VAR := PulsePerPeriod_VAR + 1;           --<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
       end if;
     end if;
  end process OnButtonRight_Down;
(PulsePerPeriod_VAR объявлена как shared variable)
Это обработка нажатия двух кнопок (вправо, влево)
Само нажатие работает нормально, по которому я формирую "событие-сигнал" нажатия кнопки (либо правой, либо левой - по названиям процессов все понятно)
при этом обращаю внимание на выделенные две строки. Если их закоментировать - все компилируется. Если оставить одну из них - тоже компилируется. А вот обе - сразу дает ошибку.
Я чую конечно что так писать нельзя. (Переменная PulsePerPeriod_VAR в обоих процессах одна и таже)
Но почему? Не могу понять и найти объяснение. Уже неделю копаю и в инете и в книгах Бибило.
1. Может кто-нибудь популярно объяснить почему так нельзя?
2. Как реализовать нажатие нескольких кнопок, когда по нажатию надо изменять значение одного и того же параметра (в данном случае увеличить или уменьшить значение переменной PulsePerPeriod_VAR)
3. Может кто посоветовать литературу такого плана - дается к.л. конструкция кода и далее какую структуру она порождает и описание это (примеры). Не готовые схемы счетчиков и т.п. а наоборот, с т.з. языка vhdl. Код -> структура -> описание.
Plain
Да потому что кнопки сейчас мифические. Перейдите в реальность и сделайте сперва синхронный подавитель дребезга для обеих, после него не останется никаких неоднозначностей.
Александр77
А может корректнее завести все в один процесс и там увеличивать/уменьшать содержимое переменной?
Flip-fl0p
Предлагаю все объединить в одном процессе. Заменить переменную на сигнал и таким образом описать суммирующие-вычитающий счетчик.

Ну а далее все просто:
Когда кнопка нажата счетчик считает "вверх".
Когда кнопка отпущена счетчик считает "вниз".

Если счетчик досчитал до конца (все разряды счетчика единички) - значит сигнал-флаг нажатой кнопки становится активным.
Если счетчик досчитал до конца (все разряды счетчика нолики) - значит сигнал-флаг нажатой кнопки становится не активным.

Задавая разрядность счетчика Вы задаете время фильтрации дребезга.
Не забыть поставить регистр-синхронизатор для подавления метастабильности.

В итоге Вы получите классический вариант антидребезга кнопки 1111493779.gif
aBoomest
Цитата(Plain @ Jun 18 2018, 22:09) *
Да потому что кнопки сейчас мифические. Перейдите в реальность и сделайте сперва синхронный подавитель дребезга для обеих, после него не останется никаких неоднозначностей.
Ни в коем случае. Ничего мифического нет. sm.gif
Key_01 и Key_02 - контролируют длительность нажатия.
Первый заход в процесс - устанавливается Key_01.
В конце устанавливается Key_02.
Второй заход в процесс (через 10 мс) - проверяется Key_01 = Key_02.
Т.е. антидребезг на 10 мс.
Код
UCF
Net "Btn_Left" Loc = "D18" | IOStandard = LVTTL | PullDown;
Net "Btn_Right" Loc = "H13" | IOStandard = LVTTL | PullDown;

VHD
  shared variable PulsePerPeriod_VAR: integer range 0 to PulsePerPeriod_VAR_MAX := 624;

. . . . .
  
  ButtonsPolling:
  process(Clock_100Hz)
  begin
    if rising_edge(Clock_100Hz) then
        if Btn_Left = '1' then
            Key_01 := '1';
            if Key_01 = Key_02 then
                OnBtnLeft_DownEvent <= '1';
            end if;
        else
            OnBtnLeft_DownEvent <= '0';
        end if;
        if Btn_Right = '1' then
            Key_01 := '1';
            if Key_01 = Key_02 then
                OnBtnRight_DownEvent <= '1';
            end if;
        else
            OnBtnRight_DownEvent <= '0';
        end if;
    Key_02 := Key_01;
  end process ButtonsPolling;

  OnButtonLeft_Down:
  process(OnBtnLeft_DownEvent)
  begin
    if rising_edge(OnBtnLeft_DownEvent) then
        if (PulsePerPeriod_VAR > 0) then
            PulsePerPeriod_VAR := PulsePerPeriod_VAR - 1;
        end if;
    end if;
  end process OnButtonLeft_Down;

  OnButtonRight_Down:
  process(OnBtnRight_DownEvent)
  begin
    if rising_edge(OnBtnRight_DownEvent) then
        if (PulsePerPeriod_VAR < PulsePerPeriod_VAR_MAX) then
            PulsePerPeriod_VAR := PulsePerPeriod_VAR + 1;
        end if;
    end if;
  end process OnButtonRight_Down;
1. Если есть знатоки как красиво делать антидребезг - буду только благодарен узнать/послушать.
2. На счет того синхронный подавитель это или НЕ синхронный - таких подробностей пока не знаю.

Спасибо за ответы.

На счет объединения в один процесс . . . обязательно подумаю, тока пока не понимаю как это вообще возможно. sm.gif

А как вообще в мире делается опрос клавиатуры (если например 10 кнопок)?
Ведь например функция вверх-вниз хождения по меню - это явно уменьшение/увеличение одной и той же переменной описывающей текущее положение в меню. Так?

К слову - философский вопрос о концепции того, что возможно построить на ПЛИС и нужно ли это делать?
У меня есть набор Спартан 3Е. На нем есть какая-то память, ЖКИ и тд и тп. А вот такой вопрос вобще на ПЛИС "возможно" реализовать устройство например которое принимает сигнал с ацп и рассчитывает его спектр. Плюс вывод какой-то дополнительной информации на экран. Под словом "возможно", я подразумеваю не то возможно ли это вообще сделать, а то - целесообразно ли это, или надо делать применять другие микросхемы.
Flip-fl0p
Цитата
Если есть знатоки как красиво делать антидребезг - буду только благодарен узнать/послушать.

Не претендую на роль знатока, но совсем чуть-чуть про дребезг знаю. И один из вариантов подавителя дребезга был предложен мною выше.
Вообще советую ознакомиться с темой: https://electronix.ru/forum/index.php?showtopic=147150 Удивительно что Вы её не нашли.

Цитата
На счет объединения в один процесс . . . обязательно подумаю, тока пока не понимаю как это вообще возможно. sm.gif

Ну так работая с FPGA Вы не программу пишете а схему. Придется отказаться от "программисткого способа мышления"
Представьте объединение процессов как обычный счетчик с сигналом управления. Если на него подается единичка - счетчик считает вверх. Если нолик - счетчик считает вниз. И по условию у вас формируется сигнал управления этим счетчиком.

Цитата
А как вообще в мире делается опрос клавиатуры (если например 10 кнопок)?

Вертикальные счетчики (ссылка на статью дана в теме про антидребезг).

Цитата
К слову - философский вопрос о концепции того, что возможно построить на ПЛИС и нужно ли это делать?

Построить на ПЛИС можно почти все, что можно сделать на микроконтроллерах и даже чуточку больше rolleyes.gif И даже сам микроконтроллер.
Вопрос в том, что сколько это займет времени, денег, и когда нужен результат. И вообще актуальность решения задачи на FPGA - это действительно философский вопрос.

Цитата
реализовать устройство например которое принимает сигнал с ацп и рассчитывает его спектр. Плюс вывод какой-то дополнительной информации на экран. Под словом "

Сделать можно. Но очень долго, если самому с нуля проектировать. Связка МК+ куча микросхем скорее всего будет быстрее в несколько раз. Альтернатива - собрать на FPGA из готовых IP блоков, со всеми граблями, велосипедами, и глюками и прочими негативными факторами. Но за то быстро. Возможно быстрее чем на МК.
_Anatoliy
Цитата(aBoomest @ Jun 19 2018, 09:48) *

aBoomest
Цитата(Flip-fl0p @ Jun 19 2018, 10:08) *
Не претендую на роль знатока, но совсем чуть-чуть про дребезг знаю. И один из вариантов подавителя дребезга был предложен мною выше.
Вообще советую ознакомиться с темой: https://electronix.ru/forum/index.php?showtopic=147150 Удивительно что Вы её не нашли.
Спасибо!
Цитата(Flip-fl0p @ Jun 19 2018, 10:08) *
Ну так работая с FPGA Вы не программу пишете а схему. Придется отказаться от "программисткого способа мышления"
Представьте объединение процессов как обычный счетчик с сигналом управления. Если на него подается единичка - счетчик считает вверх. Если нолик - счетчик считает вниз. И по условию у вас формируется сигнал управления этим счетчиком.
Да, борюсь с этим. Учусь переключаться с того на это.
На счет счетчиков - спасибо. По больше бы таких фраз. Очень популярно многое объясняет.
Цитата(Flip-fl0p @ Jun 19 2018, 10:08) *
Построить на ПЛИС можно почти все, что можно сделать на микроконтроллерах и даже чуточку больше rolleyes.gif И даже сам микроконтроллер.
Вопрос в том, что сколько это займет времени, денег, и когда нужен результат. И вообще актуальность решения задачи на FPGA - это действительно философский вопрос.
Примерно год, полтора в лучшем случае.
Цитата(Flip-fl0p @ Jun 19 2018, 10:08) *
Сделать можно. Но очень долго, если самому с нуля проектировать. Связка МК+ куча микросхем скорее всего будет быстрее в несколько раз. Альтернатива - собрать на FPGA из готовых IP блоков, со всеми граблями, велосипедами, и глюками и прочими негативными факторами. Но за то быстро. Возможно быстрее чем на МК.
На счет АЛЬТЕРНАТИВЫ - честно сказать вообще пока не понимаю о чем это? Погуглил. Идея понятна. Но это чтото видится пока еще более долгим вариантом. (учитывая что только что первый раз услышал)






Цитата(_Anatoliy @ Jun 19 2018, 10:18) *
Спасибо!
Flip-fl0p
Цитата(aBoomest @ Jun 19 2018, 10:24) *
На счет АЛЬТЕРНАТИВЫ - честно сказать вообще пока не понимаю о чем это? Погуглил. Идея понятна. Но это чтото видится пока еще более долгим вариантом. (учитывая что только что первый раз услышал)

У многих производителей FPGA в составе их САПР есть готовые функциональные блоки, SDRAM контроллеры, MAC контроллеры, PCI, всякие DSP блоки, и многое другое. Зачастую пользуясь этими блоками, можно собирать необходимую схему, как из конструктора.
Но очень часто в таких блоках может не хватать нужного функционала, или блок может содержать ошибки, или вообще быть "платным" где для пользования блоком надо приобретать отдельную лицензию, а пользователю доступен блок в демо-режиме, в котором ограничен функционал.
Да и что скрывать, зачастую на эти блоки документация очень убогая, и приходиться тратить кучу времени на его изучение.
Да и применяя все готовое самому не научиться делать правильно, что самое неприятное в этом подходе.
Но собрать из таких блоков нужную схему будет, как правило проще и быстрее, чем самому во всем разобраться. И может даже все это будет работать.
P.S. Но если система требует особой надежности - я бы не стал применять такой код, ибо непонятно как и кем он написан, посему доверия он не внушает. Но это уже мое личное мнение.
Plain
Цитата(aBoomest @ Jun 19 2018, 09:48) *
синхронный подавитель это или НЕ синхронный - таких подробностей пока не знаю

В этом-то и проблема. Он в наличии и синхронный, а вот его результат зачем-то выведен из-под данного такта — создайте в нём же условие "обе кнопки нажаты или отпущены" и не по нему меняйте счётчик.
aBoomest
Цитата(Plain @ Jun 19 2018, 11:39) *
В этом-то и проблема. Он в наличии и синхронный, а вот его результат зачем-то выведен из-под данного такта — создайте в нём же условие "обе кнопки нажаты или отпущены" и не по нему меняйте счётчик.
Простите мне мою глупость, но я не совсем понял о чем Вы. Сделать все в одном процессе, как писали коллеги выше по тексту?
Цитата(Plain @ Jun 19 2018, 11:39) *
а вот его результат зачем-то выведен из-под данного такта
Конкретно вот эта фраза не понятна. Не могли бы вы мне ее растолковать как детсадовскому ребенку?
iosifk
[quote name='aBoomest' date='Jun 19 2018, 13:47' post='156
Не могли бы вы мне ее растолковать как детсадовскому ребенку?
[/quote]
У Вас личная почта работает?
aBoomest
Так точно, работает!

PS: На счет того как засунуть в один процесс - ясно, это я тупанул жутко.
Спасибо за советы.
aBoomest
Цитата(Flip-fl0p @ Jun 19 2018, 07:43) *
Предлагаю все объединить в одном процессе. Заменить переменную на сигнал и таким образом описать суммирующие-вычитающий счетчик.
Цитата(aBoomest @ Jun 19 2018, 14:07) *
На счет того как засунуть в один процесс - ясно, это я тупанул жутко.
Не, чего-то и где-то я не допонимаю. sad.gif
Запихал все в один процесс, как советовали выше. И, как я понимаю, ошибка в том, что нельзя в двух местах изменять переменную PulsePerPeriod_VAR. Как из ситуации-то выходить? Если по нажатию одной кнопки мне нужно увеличить значение на 1цу, по нажатию другой, соответственно уменьшить. Существует какое-то классическое/общепринятое решение в данном случае? МОжет в этот процесс надо как-то Clock какой-нибудь добавить.
Код
  OnButtonLeftRight_Down:
  process(OnBtnLeft_DownEvent,OnBtnRight_DownEvent) -- изменение длительности импульса
  begin
    if rising_edge(OnBtnLeft_DownEvent) then
       if (PulsePerPeriod_VAR > 0) then
           PulsePerPeriod_VAR := PulsePerPeriod_VAR - 1;
       end if;
    elsif rising_edge(OnBtnRight_DownEvent) then
       if (PulsePerPeriod_VAR < PulsePerPeriod_VAR_MAX) then
           PulsePerPeriod_VAR := PulsePerPeriod_VAR + 1;
       end if;
    end if;
  end process OnButtonLeftRight_Down;
Flip-fl0p
Цитата(aBoomest @ Jun 21 2018, 21:39) *

Первое и основное правило синхронных проектов - на тактовый вход триггера должен приходить только синхросигнал*. Т.е при вызове функции rising_edge\faling_edge использовать только синхросигнал.
Если нужно детектировать передний или задний фронт какого-либо сигнала, не являющегося тактовым - применяйте схемы, называемые детекторы фронта.
Вот кстати я недавно выкладывал свой модуль детектора фронта: https://electronix.ru/forum/index.php?showt...5&start=195

А вот кусок счетчика, который считает вверх, или вниз в зависимости от того, какие кнопки нажаты:
Код
  
   --================================================
    -- 0 разряд сигнала buttons соответствует кнопке 0
    -- 1 разряд сигнала buttons соответствует кнопке 1
    --================================================
    OnButtonLeftRight_Down : process(clk)
    begin
        if rising_edge(clk) then
            case buttons is
                when "10"   =>  PulsePerPeriod_VAR := PulsePerPeriod_VAR - 1;
                            
                when "01"   =>  PulsePerPeriod_VAR := PulsePerPeriod_VAR + 1;
                            
                when others => null;
           end case;
        end if;
    end process;

Но я бы так не делал rolleyes.gif Я бы для начала сделал обычный антидребезг и подключил его кнопкам. А реакцию схемы на нажатие кнопок обрабатывал бы простой FSM.
PS * Исключением из этого правила является специально сгенерированная на логике частота, например поделенная в 2 раза на триггере. Но даже в этом случае я предпочитаю применить PLL. Ибо частота сгенерированная на PLL имеет меньший джиттер, чем та-же частота сгенерированная на логике.
Plain
В схеме по-прежнему несколько тактовых сигналов, а должен быть один 100 Гц. И стандартное решение — это цифровой автомат (FSM).

Например, создать для каждой кнопки 2-разрядный сдвиговый регистр подавления дребезга и 2-разрядный сдвиговый регистр автомата ловли её нажатия.

Соответственно, в сумме получаются 4 бита, описывающих из 16 состояний лишь два, меняющих счётчик.
Flip-fl0p
Цитата(Plain @ Jun 21 2018, 22:42) *
Например, создать для каждой кнопки 2-разрядный сдвиговый регистр подавления дребезга и 2-разрядный сдвиговый регистр автомата ловли её нажатия.

Простите, но как 2 разрядный регистр избавит от дребезга ?
iosifk
Цитата(aBoomest @ Jun 21 2018, 21:39) *
Не, чего-то и где-то я не допонимаю. sad.gif

process(OnBtnLeft_DownEvent,OnBtnRight_DownEvent) -- изменение длительности импульса
begin
if rising_edge(OnBtnLeft_DownEvent) then

Ситуация примерно такая. Садитесь в "готовый" автомобиль. Нажимаете педали, крутите руль - едете. Структура автомобиля фиксированная, а Вы определяете "действия". Вот так работает микроконтроллер.
А в ПЛИС - другая ситуация. Вот куча, в ней лежат колеса, руль, мотор и другие железяки. Так вот в ПЛИС дело выглядит так: надо взять одну железку, к ней привинтить другую, потом мотор, потом колеса, потом руль. А уж куда поедет - так это как руль и мотор привинтили. Т.е. структуру Вы определяете сами. Восемь колес накрутите, получите БТР. Руль в одну сторону заклините, получите авто для гонок по кругу...
Поэтому перестаньте мыслить Сишными функциями, как например OnBtnLeft_DownEvent... В ПЛИС это никак не пойдет. Тут как в авто, есть мотор, вот от его вала и шестерни и ремень на вентилятор, и чего-то на распределитель...
Так что "старые мозги" - выкинуть, "новые" - вставить... Трудно, но кто говорил, что будет легко. А еще эти кривые скобки вместо которых "begin-end". .. laughing.gif
Plain
Цитата(Flip-fl0p @ Jun 21 2018, 22:53) *
как 2 разрядный регистр избавит от дребезга ?

Результат 3-входовой мажоритарной функции 2-х бит этого регистра и первого бита регистра автомата задвигается в регистр автомата, т.е. подавляется 1-тактный дребезг.
Flip-fl0p
Цитата(Plain @ Jun 21 2018, 23:15) *
Результат 3-входовой мажоритарной функции 2-х бит этого регистра и первого бита регистра автомата задвигается в регистр автомата, т.е. подавляется 1-тактный дребезг.

К примеру при частоте 100 Мгц - это дребезг в 10 нс. А кнопки могут дребезжать вплоть до миллисекунд....
Plain
У автора тактовая частота 100 Гц.
aBoomest
Спасибо всем за ответы!
Все говорят и советуют FSM, например . . .
Цитата(Plain @ Jun 21 2018, 22:42) *
В схеме по-прежнему несколько тактовых сигналов, а должен быть один 100 Гц. И стандартное решение — это цифровой автомат (FSM).

Например, создать для каждой кнопки 2-разрядный сдвиговый регистр подавления дребезга и 2-разрядный сдвиговый регистр автомата ловли её нажатия.

Соответственно, в сумме получаются 4 бита, описывающих из 16 состояний лишь два, меняющих счётчик.
Так вроде нечто подобное и есть, по тактовой частоте 100 Гц я определяю нажатость. Контролирую ее два раза. Т.е. антидребезг на 10 мс. См.пост #5
А далее уже как раз событие нажатия ловлю.

Вопрос был еще немного в другом, как по нажатию разных кнопок менять значение одной и той же переменной?

Может правильнее будет изменение PulsePerPeriod_VAR засунуть вообще внутрь процесса антидребезга? Или я тут уже перегибаю?
Код
ButtonsPolling:
  process(Clock_100Hz)
  begin
    if rising_edge(Clock_100Hz) then
        if Btn_Left = '1' then
            Key_01 := '1';
            if Key_01 = Key_02 then
                OnBtnLeft_DownEvent <= '1';
            end if;
        else
            OnBtnLeft_DownEvent <= '0';
        end if;
        if Btn_Right = '1' then
            Key_01 := '1';
            if Key_01 = Key_02 then
                OnBtnRight_DownEvent <= '1';
            end if;
        else
            OnBtnRight_DownEvent <= '0';
        end if;
    Key_02 := Key_01;
  end process ButtonsPolling;
Flip-fl0p
Цитата(aBoomest @ Jun 22 2018, 08:48) *

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

Например есть 2 сигнала с кнопки button0_in, и button1_in. Вы эти сигналы подаете на модули антедребезза и получаете нормальные стабильные сигналы. Пусть будут названы
button0_deb и button1_deb. Затем вы эти сигналы (button0_deb и button1_deb) передаете модулю-обработчику(который может быть FSM или не быть) и обрабатываете как хотите в зависимости от алгоритма обработки.
Фактически у вас есть 4 комбинации этих сигналов:
"00" т.е button1_deb = '0' button0_deb '0'
"01" т.е button1_deb = '0' button0_deb '1'
"10" т.е button1_deb = '1' button0_deb '0'
"11" т.е button1_deb = '1' button0_deb '1'

Вот пример одного из вариантов огрызка модуля обрабатывающего нажатия, достаточного для понимания как можно в зависимости от нажатия кнопок что-то делать:
Код
entity module_name is
    port
    (
        ....
        ....
        clk            : in  std_logic;
        button0_deb    : in  std_logic;
        button1_deb    : in  std_logic;
        ....                    ;
        ....
    );
end entity;

architecture RTL of module_name is
    ....
    ....
    signal selector    : std_logic_vector(1 downto 0);  -- Промежуточный сигнал для обьединения button0_deb и button1_deb
    ....
    ....
begin
    selector <= button1_deb & button0_deb;
    
    process_name : process(clk)
    begin
        if (rising_edge(clk)) then
            case selector is                       -- Анализируем состояние кнопок
                when "00"   => -- что-то делаем;
                when "01"   => -- что-то делаем;
                when "10"   => -- что-то делаем;
                when "11"   => -- что-то делаем;
                when others => null;
            end case
        end if;
    end process;
end architecture;


Ну либо обрабатывать нажатия кнопок автоматом. Тут все зависит от алгоритма обработки.
Если интересно, как я реализую антидребезг, то можете посмотреть его там-же где я выкладывал детектор фронта. Но любое применение этих файлов - это на ваш страх и риск biggrin.gif
Plain
Цитата(aBoomest @ Jun 22 2018, 08:48) *
вроде нечто подобное и есть

Я извиняюсь, ранее не стал вглядываться, но сейчас у Вас мало того, что одна переменная на две кнопки, так она ещё и ничего не давит, потому как всегда в "1".
Plain
Цитата(Plain @ Jun 21 2018, 22:42) *
создать для каждой кнопки 2-разрядный сдвиговый регистр подавления дребезга и 2-разрядный сдвиговый регистр автомата ловли её нажатия.

Цитата(aBoomest @ Jun 22 2018, 15:27)
могли бы Вы пояснить то, что написали? ... в какую схему "превращается" код конструкции if - много где показано. А вот чуть более сложные вариации - уже не найти

"Да наоборот же! ©" Сперва надо составить требуемую схему, на бумаге или в голове, а затем выбирать из десятков вариантов возможностей языка, как заставить компилятор родить её.

Сдвиговый регистр (shift register) — это в пределе просто оператор присваивания под тактом, двухбитный регистр — два таких оператора последовательно. Также, первый триггер из этой цепочки, принимая асинхронный сигнал с кнопки, делает его однозначным для всей последующей тактируемой схемы, т.е. играет важную роль пресловутого избавления от метастабильности.

В результате, сигнал с кнопки с каждым тактом начинает ползти по регистру, который таким образом становится эдакой машиной времени, позволяющей создать пороговую схему, перекидывающую выходной сигнал только когда кнопка перестала дребезжать, т.е. при достижении ею устойчивого состояния, т.е. когда её предыдущее и текущее состояние стали одинаковыми, а этот сдвиговый регистр, соответственно, в "00" или "11".

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

Итого, в наличии есть два бита регистра давилки дребезга и ещё один бит с выхода третьего триггера. Мажоритарная функция (majority function) от этих трёх бит повторяет выход третьего триггера, пока кнопка дребезжит и меняет его значение на установившееся, когда она перестаёт дребезжать, т.е. остаётся просто присвоить третьему триггеру значение данного логического выражения (созданного соответствующей комбинацией логических операторов), а четвёртому значение третьего.

Теперь можем ловить подлинно факты нажатия обеих кнопок, т.е. когда их "чистые" регистры в состоянии "01", но сперва требуется исключить запрещённую комбинацию, когда эти регистры оба в "01", при которой счётчик не должен меняться, т.е. просто условие в виде логической функции от этих четырёх бит, а в нём уже можно без оглядки двумя вложенными условиями проверять "чистые" регистры каждой из кнопок и менять счётчик.
aBoomest
Цитата(Plain @ Jun 24 2018, 14:42) *
"Да наоборот же! ©" ............
Спасибо. Дельно.

Вот такой вопрос, чтобы понять нюанс, по сообщениям номер 15 и номер 23:

Какую частоту должны иметь сигналы clk?

В моем случае антидребезг с временем 10 мс. (используется частота 100 Гц)
А та частота о которой говорю, она же , как я понимаю должна быть <100 Гц (или <=100Гц). По крайней мере, вроде как она не должна быть больше.
Т.е. эта частота определяет с какой скоростью PulsePerPeriod_VAR будет увеличиваться/уменьшаться на 1.
Т.е. если clk = 1 Гц, то при нажатой кнопке UP один раз в секунду PulsePerPeriod_VAR будет увеличиваться на единицу. Правильные рассуждения?
Если да, то что всетаки может помешать сделать clk > 100 Гц?
iosifk
Цитата(aBoomest @ Jun 27 2018, 22:17) *
Какую частоту должны иметь сигналы clk?

Давайте вспомним учебник.
У триггера есть входы:
сброс
данные
тактовый
разрешение счета...

И при любой тактовой триггер считает ТОЛЬКО тогда, когда есть сигнал разрешения. Дальше объяснять?
Plain
Цитата(aBoomest @ Jun 27 2018, 22:17) *
при нажатой кнопке ... будет увеличиваться на единицу. Правильные рассуждения?

Неправильные. При нажатии кнопки счётчик один раз увеличится и на этом всё — можно дальше держать эту кнопку нажатой до опупения, ничего не произойдёт.

Если же Вам дополнительно требуется функция автоповтора — как у компьютерной клавиатуры, т.е. с программируемой паузой с момента удержания кнопки нажатой до начала автоповтора её функции и программируемой частотой автоповтора — то для этого к вышеприведённому описанию требуется добавить соответствующее описание соответствующего довеска к схеме.
Flip-fl0p
Цитата(aBoomest @ Jun 27 2018, 22:17) *

Чтобы понять нюанс по сообщениям - надо понять в первую очередь какую мысль я до Вас пытаюсь донести.
А для этого надо сесть и нарисовать на бумажке структуру прохождения данных в проекте:


Инвертор уровня - нужен для того, чтобы всегда работать с активным уровнем сигнала- лог.1. Иначе легко допустить ошибку. Во всяком случае я предпочитаю работать по возможности с активным уровнем лог.1

Регистры-синхронизаторы - для синхронизации с клоковым доменом.

Антидребезг - удаление дребезга собственно rolleyes.gif .

В моем случае у меня все это делает один модуль, который называется KAA_button_debounce, пример которого я привел на форуме: https://electronix.ru/forum/index.php?showt...5&start=195

С выхода антидребезга стабильный, синхронный сигнал подаете на автомат и что-то с ними делаете по Вашему алгоритму.

Забудьте про частоты 1 Гц, 100 Гц и прочее. Не плодите разные частоты без крайней необходимости, это лишено смысла.
Советую прочитать про тактовые домены, чтобы пришло понимание почему без особой необходимость не надо плодить разные частоты:
http://www.kit-e.ru/articles/circuit/2009_02_102.php
https://habr.com/post/254869/

Если есть возможность - обрабатывать на одной частоте. В приведенном примере я взял за основу системную частоту с тактового генератора, но можно на блоках PLL или DCM синтезировать нужную Вам. Смысл примера - то что все действия можно производить только на одной частоте.
P.S. К сожалению я лучше уж объяснить не смогу. Не умею...
Plain
Конкретизирую по повторам. Минимальный период ручного повтора, т.е. возникновения ключевого сигнала с двухбитового сдвигового регистра узла подавления дребезга, составляет 4 такта — это комбинация "0011" в случае идеальной недребезжащей кнопки — при нынешней частоте 100 Гц это соответственно 25 Гц, а минимальный период автоповтора составляет 1 такт, т.е. 100 Гц.

Насчёт тактовых частот вообще. Надо понимать, что ПЛИС — это набор однобитовых синхронных ячеек памяти, т.е. D-триггера с переключателем сигнала данных на входе.

Если сигнал управления этого переключателя в "0", триггер в данном такте перезапомнит своё текущее состояние, т.е. его состояние не изменится, а если в "1", то запомнит новое значение, созданное 3...N-входовой комбинационной логической схемой.

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

В моём вышеизложенном примере сигналы разрешения ячеек памяти не используются, потому что они изменяются в каждом такте, поэтому я называл их просто триггерами. В реальной жизни затактовать ПЛИС можно, к примеру, частотой 100 МГц, тогда сигнал 100 Гц должен быть получен внутри этого такта соответствующим делителем, по сигналу которого будет работать вся последующая вышеописанная схема кнопок — вот тогда компилятор задействует сигналы разрешения этих 8-ми ячеек памяти и каждые 999999 тактов они будут оставаться неизменными.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.