|
Обработка нажатия кнопок |
|
|
|
Jun 18 2018, 18:12
|
Частый гость
 
Группа: Участник
Сообщений: 167
Регистрация: 24-12-08
Из: Россия
Пользователь №: 42 714

|
Всем доброго дня. Привожу нижеследующий код: Код 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. Код -> структура -> описание.
Сообщение отредактировал aBoomest - Jun 18 2018, 18:18
--------------------
C уважением!
|
|
|
|
|
Jun 19 2018, 04:43
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
Предлагаю все объединить в одном процессе. Заменить переменную на сигнал и таким образом описать суммирующие-вычитающий счетчик. Ну а далее все просто: Когда кнопка нажата счетчик считает "вверх". Когда кнопка отпущена счетчик считает "вниз". Если счетчик досчитал до конца (все разряды счетчика единички) - значит сигнал-флаг нажатой кнопки становится активным. Если счетчик досчитал до конца (все разряды счетчика нолики) - значит сигнал-флаг нажатой кнопки становится не активным. Задавая разрядность счетчика Вы задаете время фильтрации дребезга. Не забыть поставить регистр-синхронизатор для подавления метастабильности. В итоге Вы получите классический вариант антидребезга кнопки
|
|
|
|
|
Jun 19 2018, 06:48
|
Частый гость
 
Группа: Участник
Сообщений: 167
Регистрация: 24-12-08
Из: Россия
Пользователь №: 42 714

|
Цитата(Plain @ Jun 18 2018, 22:09)  Да потому что кнопки сейчас мифические. Перейдите в реальность и сделайте сперва синхронный подавитель дребезга для обеих, после него не останется никаких неоднозначностей. Ни в коем случае. Ничего мифического нет. 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. На счет того синхронный подавитель это или НЕ синхронный - таких подробностей пока не знаю. Спасибо за ответы. На счет объединения в один процесс . . . обязательно подумаю, тока пока не понимаю как это вообще возможно.  А как вообще в мире делается опрос клавиатуры (если например 10 кнопок)? Ведь например функция вверх-вниз хождения по меню - это явно уменьшение/увеличение одной и той же переменной описывающей текущее положение в меню. Так? К слову - философский вопрос о концепции того, что возможно построить на ПЛИС и нужно ли это делать? У меня есть набор Спартан 3Е. На нем есть какая-то память, ЖКИ и тд и тп. А вот такой вопрос вобще на ПЛИС " возможно" реализовать устройство например которое принимает сигнал с ацп и рассчитывает его спектр. Плюс вывод какой-то дополнительной информации на экран. Под словом " возможно", я подразумеваю не то возможно ли это вообще сделать, а то - целесообразно ли это, или надо делать применять другие микросхемы.
Сообщение отредактировал aBoomest - Jun 19 2018, 06:50
--------------------
C уважением!
|
|
|
|
|
Jun 19 2018, 07:08
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
Цитата Если есть знатоки как красиво делать антидребезг - буду только благодарен узнать/послушать. Не претендую на роль знатока, но совсем чуть-чуть про дребезг знаю. И один из вариантов подавителя дребезга был предложен мною выше. Вообще советую ознакомиться с темой: https://electronix.ru/forum/index.php?showtopic=147150 Удивительно что Вы её не нашли. Цитата На счет объединения в один процесс . . . обязательно подумаю, тока пока не понимаю как это вообще возможно.  Ну так работая с FPGA Вы не программу пишете а схему. Придется отказаться от "программисткого способа мышления" Представьте объединение процессов как обычный счетчик с сигналом управления. Если на него подается единичка - счетчик считает вверх. Если нолик - счетчик считает вниз. И по условию у вас формируется сигнал управления этим счетчиком. Цитата А как вообще в мире делается опрос клавиатуры (если например 10 кнопок)? Вертикальные счетчики (ссылка на статью дана в теме про антидребезг). Цитата К слову - философский вопрос о концепции того, что возможно построить на ПЛИС и нужно ли это делать? Построить на ПЛИС можно почти все, что можно сделать на микроконтроллерах и даже чуточку больше  И даже сам микроконтроллер. Вопрос в том, что сколько это займет времени, денег, и когда нужен результат. И вообще актуальность решения задачи на FPGA - это действительно философский вопрос. Цитата реализовать устройство например которое принимает сигнал с ацп и рассчитывает его спектр. Плюс вывод какой-то дополнительной информации на экран. Под словом " Сделать можно. Но очень долго, если самому с нуля проектировать. Связка МК+ куча микросхем скорее всего будет быстрее в несколько раз. Альтернатива - собрать на FPGA из готовых IP блоков, со всеми граблями, велосипедами, и глюками и прочими негативными факторами. Но за то быстро. Возможно быстрее чем на МК.
|
|
|
|
|
Jun 19 2018, 07:24
|
Частый гость
 
Группа: Участник
Сообщений: 167
Регистрация: 24-12-08
Из: Россия
Пользователь №: 42 714

|
Цитата(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)  Построить на ПЛИС можно почти все, что можно сделать на микроконтроллерах и даже чуточку больше  И даже сам микроконтроллер. Вопрос в том, что сколько это займет времени, денег, и когда нужен результат. И вообще актуальность решения задачи на FPGA - это действительно философский вопрос. Примерно год, полтора в лучшем случае. Цитата(Flip-fl0p @ Jun 19 2018, 10:08)  Сделать можно. Но очень долго, если самому с нуля проектировать. Связка МК+ куча микросхем скорее всего будет быстрее в несколько раз. Альтернатива - собрать на FPGA из готовых IP блоков, со всеми граблями, велосипедами, и глюками и прочими негативными факторами. Но за то быстро. Возможно быстрее чем на МК. На счет АЛЬТЕРНАТИВЫ - честно сказать вообще пока не понимаю о чем это? Погуглил. Идея понятна. Но это чтото видится пока еще более долгим вариантом. (учитывая что только что первый раз услышал) Цитата(_Anatoliy @ Jun 19 2018, 10:18)  Спасибо!
--------------------
C уважением!
|
|
|
|
|
Jun 19 2018, 07:37
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
Цитата(aBoomest @ Jun 19 2018, 10:24)  На счет АЛЬТЕРНАТИВЫ - честно сказать вообще пока не понимаю о чем это? Погуглил. Идея понятна. Но это чтото видится пока еще более долгим вариантом. (учитывая что только что первый раз услышал) У многих производителей FPGA в составе их САПР есть готовые функциональные блоки, SDRAM контроллеры, MAC контроллеры, PCI, всякие DSP блоки, и многое другое. Зачастую пользуясь этими блоками, можно собирать необходимую схему, как из конструктора. Но очень часто в таких блоках может не хватать нужного функционала, или блок может содержать ошибки, или вообще быть "платным" где для пользования блоком надо приобретать отдельную лицензию, а пользователю доступен блок в демо-режиме, в котором ограничен функционал. Да и что скрывать, зачастую на эти блоки документация очень убогая, и приходиться тратить кучу времени на его изучение. Да и применяя все готовое самому не научиться делать правильно, что самое неприятное в этом подходе. Но собрать из таких блоков нужную схему будет, как правило проще и быстрее, чем самому во всем разобраться. И может даже все это будет работать. P.S. Но если система требует особой надежности - я бы не стал применять такой код, ибо непонятно как и кем он написан, посему доверия он не внушает. Но это уже мое личное мнение.
|
|
|
|
|
Jun 19 2018, 10:47
|
Частый гость
 
Группа: Участник
Сообщений: 167
Регистрация: 24-12-08
Из: Россия
Пользователь №: 42 714

|
Цитата(Plain @ Jun 19 2018, 11:39)  В этом-то и проблема. Он в наличии и синхронный, а вот его результат зачем-то выведен из-под данного такта — создайте в нём же условие "обе кнопки нажаты или отпущены" и не по нему меняйте счётчик. Простите мне мою глупость, но я не совсем понял о чем Вы. Сделать все в одном процессе, как писали коллеги выше по тексту? Цитата(Plain @ Jun 19 2018, 11:39)  а вот его результат зачем-то выведен из-под данного такта Конкретно вот эта фраза не понятна. Не могли бы вы мне ее растолковать как детсадовскому ребенку?
--------------------
C уважением!
|
|
|
|
|
Jun 19 2018, 11:07
|
Частый гость
 
Группа: Участник
Сообщений: 167
Регистрация: 24-12-08
Из: Россия
Пользователь №: 42 714

|
Так точно, работает!
PS: На счет того как засунуть в один процесс - ясно, это я тупанул жутко. Спасибо за советы.
--------------------
C уважением!
|
|
|
|
|
Jun 21 2018, 18:39
|
Частый гость
 
Группа: Участник
Сообщений: 167
Регистрация: 24-12-08
Из: Россия
Пользователь №: 42 714

|
Цитата(Flip-fl0p @ Jun 19 2018, 07:43)  Предлагаю все объединить в одном процессе. Заменить переменную на сигнал и таким образом описать суммирующие-вычитающий счетчик. Цитата(aBoomest @ Jun 19 2018, 14:07)  На счет того как засунуть в один процесс - ясно, это я тупанул жутко. Не, чего-то и где-то я не допонимаю.  Запихал все в один процесс, как советовали выше. И, как я понимаю, ошибка в том, что нельзя в двух местах изменять переменную 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;
--------------------
C уважением!
|
|
|
|
|
Jun 21 2018, 19:33
|

В поисках себя...
   
Группа: Свой
Сообщений: 729
Регистрация: 11-06-13
Из: Санкт-Петербург
Пользователь №: 77 140

|
Цитата(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; Но я бы так не делал  Я бы для начала сделал обычный антидребезг и подключил его кнопкам. А реакцию схемы на нажатие кнопок обрабатывал бы простой FSM. PS * Исключением из этого правила является специально сгенерированная на логике частота, например поделенная в 2 раза на триггере. Но даже в этом случае я предпочитаю применить PLL. Ибо частота сгенерированная на PLL имеет меньший джиттер, чем та-же частота сгенерированная на логике.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|