Перейти к содержанию
    

Схемотехнические трюки для ПЛИСоводов

Нет проверки на то, что что в DIRECTION будет нечто, отличное от "UP" и "DOWN". Например, "Up" или "Down". Не всем нравится верхний регистр. Лучше заменить строку на boolean.

В VHDL нет разницы между UP, Up, uP или up. Про Down можно сказать тоже самое.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В VHDL нет разницы между UP, Up, uP или up. Про Down можно сказать тоже самое.

Для типа string разница есть !

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В VHDL нет разницы между UP, Up, uP или up. Про Down можно сказать тоже самое.
Тащемта там строка, а не перечислимый тип.

 

Можете сказать навскидку где вообще такой счетчик мог бы пригодится ?
Дело в принципе. Если вы пишете модуль, претендующий на универсальность, пишите его на самом деле универсальным, с минимальным количеством ограничений.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тащемта там строка, а не перечислимый тип.

 

Дело в принципе. Если вы пишете модуль, претендующий на универсальность, пишите его на самом деле универсальным, с минимальным количеством ограничений.

Понял. Учтем !

А вообще в VHDL сделать модуль полностью универсальным очень сложно.

Например я как-то хотел сделать модуль полностью настраиваемым. Т.е в области generic настраивать все возможные комбинации входных и выходных портов. Например если нужен сигнал синхронного сброса, сигнал переноса, разрешения работы, и пр то их можно включить просто настройкой параметров модуля. Но столкнулся с проблемой отсутствием возможности генерировать по условию входные\выходные порты. Вернее не так, возможность есть, но она очень кривая и модуль выдает кучу предупреждений. Хотя синтезируется нормально.

Иногда даже жалко что у VHDL нет предпроцессора.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот. Последние варианты (4 и 5, одинаковые). Остальные показывают процесс разработки. :-)

 

`define LENTH	28
`define VAR5

`ifdef VAR1
`define TIM1
`elsif VAR2
`define TIM1
`elsif VAR3
`define TIM1
`else
`define TIM2
`endif

module Timer_m
`ifdef TIM1
(
 (* chip_pin = "91",
    altera_attribute = "-name global_signal on; -name io_standard lvds" *)
 input bit			clk,	// high-speed clock
 input bit	[`LENTH-1:0]	rld,	// reload data
 output bit			pls	// timer overload pulse
);
`endif

`ifdef VAR1
 bit [`LENTH:0]	cnt;
 always_ff @(posedge clk) begin
   if (cnt[`LENTH]) cnt <= {1'b0, rld};
   else             cnt <= cnt - 1;
 end
 assign pls = cnt[`LENTH];

`elsif VAR2
 bit [`LENTH-1:0]	cnt;
 always_ff @(posedge clk) begin
   if (cnt[`LENTH-1]) cnt <= rld;
   else               cnt <= cnt - 1;
 end
 assign pls = cnt[`LENTH-1];

`elsif VAR3
 bit [`LENTH-1:0]	cnt;
 always_ff @(posedge clk) begin
   if (cnt[`LENTH-1]) cnt <= rld;
   else	       cnt <= cnt[`LENTH-2:0] - 1;
 end
 assign pls = cnt[`LENTH-1];
`endif

`ifdef TIM2
(
 (* chip_pin = "91",
    altera_attribute = "-name global_signal on; -name io_standard lvds" *)
 input bit			clk,	// high-speed clock
 input bit	[`LENTH-1:0]	rld,	// reload data
 input bit			ldp,	// load pulse
 output bit			pls	// timer overload pulse
);
`endif

`ifdef VAR4
 bit [`LENTH:0]	cnt;
 always_ff @(posedge clk) begin
   if (cnt[`LENTH]) cnt <= {ldp, rld};
   else	     cnt <= cnt[`LENTH-1:0] - 1; 
 end
 assign pls = cnt[`LENTH];
`endif

`ifdef VAR5
 bit [`LENTH-1:0]	cnt;
 always_ff @(posedge clk) begin
   if (pls) {pls, cnt} <= {ldp, rld};
   else     {pls, cnt} <= cnt - 1;
 end
`endif

endmodule : Timer_m

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Простенький ФНЧ Uout = Uout-1 + (Utek - Uout-1)>> K

 

Выручал неоднократно... Делюсь

 

Все-таки добавлю к нему TestBanch...

IQ_filtr.vhd

IQ_tb.vhd

RND.vhd

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Поскольку в последнее время часто возникает вопрос про детекторы фронта, то выложу сюда свой модуль детектора.

Собственно сам текст:

--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | File name       | KAA_edge_dtct | 
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Properties      | Tab type = space | HDL type =  VHDL2008 | Languege - Russian | Syntesis tool = Quartus 13.1 | Sim = Modelsim ASE
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Author          | Клементьев Алексей Александрович | Email = [email protected]
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Description     | Детектор фронтов. Встроенный CDC синхронизатор, который можно применить в качеств элемента задержки
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Notes           | 
-- |                 | 
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Change history  | (1) 19.02.2018 - исправлен закомментированный кусок для вставки
-- |                 | (2) 02.03.2018 - Регистр синхронизатор - отдельный модуль с внутренними констрейнами
-- |                 | (3) 14.03.2018 - Убран отдельный модуль CDC синхронизатора. Встроенные констрейны не работают. Да и неудобно.
-- |                 | (3) 14.03.2018 - Убран параметр детектирования фронта посредством 2 регистров. Нет необходимости в парамтре
-- |                 | (3) 14.03.2018 - Добавлен параметр регистрового выхода. Мало ли когда понадобится.
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
———————————————————————————————— 
   -- edge_dtct_comp : entity work.KAA_edge_dtct
   -- generic map
   -- ( 
       -- clock_domain_sync        => "Disable", -- Enable / Disable   включение / выключение CDC- синхронизатора. Можно использовать как элемент задержки
       -- sync_stages              => 3,         -- Количество триггеров для  синхронизации (или время задержки)
       -- edge_type                => "Rising",   -- Rising / Falling / All_edge тип детектированного фронта
       -- Individual_wire_for_edge => "Disable",  --  edge(0) - rising  edge(1)  - faling
       -- Reg_output               => "Enable"   -- Enable / Disable включение/выключение регистрового выхода (создает дополнительную задержку в 1 такт)
   -- )
   -- port map
   -- (
       -- clk         =>
       -- input       =>
       -- edge(0)     =>
   -- );   
-- ————————————————————————————————————————————————————————————————————————————————
——————————————————————————————————————————————————————   

--================================================================================
======================================================
-- Пакет для функции, которая нужна для определения разрядности выходной шины если включен режим Individual_wire_for_edge
-- Пакет должен идти перед описанием модуля KAA_edge_dtct. Иначе Modelsim не поддецпит его и будет ругаться на отуствтие пакета.
--================================================================================
======================================================   
library ieee;
   use ieee.std_logic_1164.all;

package KAA_edge_dtct_pkg is
   function type_wire
   (
       a                : string;  
       b                : string
   ) return natural;
end package;

package body KAA_edge_dtct_pkg is

   function type_wire
   (
       a                : string;  
       b                : string
   ) return natural is
   begin
       if (a = "Enable" and b = "All_edge") then
           return 1;
       else 
           return 0;
       end if;
   end type_wire;
end package body;

--================================================================================
======================================================
-- Собственно модуля KAA_edge_dtct
--================================================================================
======================================================   
library ieee;
   use ieee.std_logic_1164.all;
   use work.KAA_edge_dtct_pkg.all;

entity KAA_edge_dtct is
   generic
   ( 
       Clock_domain_sync        : string  := "Enable";  -- Enable / Disable   включение / выключение CDC- синхронизатора. Можно использовать как элемент задержки
       Sync_stages              : natural := 1;          -- Количество триггеров для  синхронизации (или время задержки)
       Edge_type                : string  := "Falling";  -- Rising / Falling / All_edge тип детектированного фронта
       Individual_wire_for_edge : string  := "Disable";  -- Enable / Disable  включение отдельного выхода для каждого типа стрба режиме если включен режим all_edge
       Reg_output               : string  := "Disable"   -- Enable / Disable включение/выключение регистрового выхода (создает дополнительную задержку в 1 такт)
   );
   port
   (
       clk                    : in  std_logic;          
       input                  : in  std_logic;
       edge                   : out std_logic_vector(type_wire(a => individual_wire_for_edge, b => Edge_type  ) downto 0)  -- Функция определена в KAA_edge_dtct_pkg (выше по тексту)
   );
end entity;

architecture RTL of KAA_edge_dtct is 
   signal CDC_sync           : std_logic_vector(sync_stages - 1 downto 0) := (others => '0');  -- Сдвиговый регистр - синхронизатор (или линия задержки 
   signal input_stable       : std_logic                                  := '0';              -- Промежуточный сигнал для возможности подключения синхронизатора
   signal edge_detector      : std_logic                                  := '0';              -- Регистр для детектирования фронта
begin

   --================================================================================
===========
   -- Если включён входной синхронизатор, пропустим данные через сдвиговый регистр  
   -- (2) Добавил отдельный модуль синхронизатор.
   -- (3) Убрал отдельный модуль синхронизатор. Неудобно. И констрейны не работают...
   --================================================================================
===========   
   clock_domain_sync_enable_generating :  if (clock_domain_sync = "Enable") generate 
       CDC_sync_proc : process (clk)
       begin
           if (rising_edge(clk)) then      
               if (Sync_stages = 1) then   -- Если стадий синхронизации 1 - то записшем сразу в регистр (сделано чтобы не Quartus не ругался на null_rage)
                   CDC_sync(CDC_sync'left) <= input;  
               else
                   CDC_sync <= CDC_sync(sync_stages - 2 downto 0) & input;  
               end if;
           end if;
       end process; 
       input_stable <=  CDC_sync(CDC_sync'left);
   end generate;

   --================================================================================
======================================
   -- Если отключён входной синхронизатор, считается что данные стабильны т.к формируются в том-же клоковом домене.
   --================================================================================
======================================    
   clock_domain_sync_disable_generating  :  if (clock_domain_sync = "Disable") generate 
       input_stable <= input; 
   end generate;    

   --================================================================================
===========
   -- Запишем входной сигнал в регистр для последующего детектирования фронтов
   --================================================================================
===========
   signal_latch : process (clk)
   begin
       if (rising_edge(clk)) then                   
           edge_detector <= input_stable;  
       end if;
   end process; 

   --================================================================================
===========
   -- Детектирование заднего фронта сигнала
   --================================================================================
===========
   falling_edge_detection_generating :  if (edge_type = "Falling") generate 
       --================================================================================
===========
       -- Если включен регистровый выход (3)
       --================================================================================
===========
       Reg_output_enable_generate : if (Reg_output = "Enable") generate
           edge(0) <= not input_stable and edge_detector when rising_edge(clk);                  
       end generate;

       --================================================================================
===========
       -- Если выключен регистровый выход
       --================================================================================
===========        
       Reg_output_disable_generate : if (Reg_output = "Disable") generate
           edge(0) <= not input_stable and edge_detector;                  
       end generate;

   end generate;

   --================================================================================
===========
   -- Детектирование переднего фронта сигнала
   --================================================================================
===========
   rising_edge_detection_generating :  if (edge_type = "Rising") generate  
       --================================================================================
===========
       -- Если включен регистровый выход (3) 
       --================================================================================
===========
       Reg_output_enable_generate : if (Reg_output = "Enable") generate
           edge(0) <= not edge_detector and input_stable  when rising_edge(clk);  
       end generate;

       --================================================================================
===========
       -- Если выключен регистровый выход
       --================================================================================
===========
       Reg_output_disable_generate : if (Reg_output = "Disable") generate
           edge(0) <= not edge_detector and input_stable;  
       end generate;
   end generate;

   --================================================================================
===========
   -- Детектирование всех фронтов сигнала если нужен только один выход из модуля
   --================================================================================
===========
   non_individual : if (individual_wire_for_edge = "Disable" and edge_type = "All_edge" ) generate
       --================================================================================
===========
       -- Если включен регистровый выход (3)
       --================================================================================
===========
       Reg_output_enable_generate : if (Reg_output = "Enable") generate
           edge(0) <=  edge_detector xor input_stable  when rising_edge(clk);  
       end generate;

       --================================================================================
===========
       -- Если выключен регистровый выход
       --================================================================================
===========
       Reg_output_disable_generate : if (Reg_output = "Disable") generate
           edge(0) <=  edge_detector xor input_stable;  
       end generate;
   end generate;    

   --================================================================================
===========
   -- Детектирование всех фронтов сигнала. Каждый фронт имеет отдельный выход
   --================================================================================
===========    
   individual : if (individual_wire_for_edge = "Enable" and edge_type = "All_edge" ) generate
       --================================================================================
===========
       -- Если включен регистровый выход (3)
       --================================================================================
===========
       Reg_output_enable_generate : if (Reg_output = "Enable") generate
           edge(0)  <= not edge_detector and input_stable when rising_edge(clk);    -- Rising
           edge(1)  <= not input_stable  and edge_detector when rising_edge(clk);   -- Faling
       end generate;

       --================================================================================
===========
       -- Если выключен регистровый выход
       --================================================================================
===========
       Reg_output_disable_generate : if (Reg_output = "Disable") generate
           edge(0)  <= not edge_detector and input_stable;    -- Rising
           edge(1)  <= not input_stable  and edge_detector;   -- Faling
       end generate;
   end generate;

   --================================================================================
===========
   -- Проверка правильности ввода парамтеров Clock_domain_sync
   --================================================================================
===========    
   assert (Clock_domain_sync  = "Enable" or Clock_domain_sync  = "Disable") 
   report LF&
   "Incorrect parametr 'Clock_domain_sync'. Check the syntax !" &LF& 
   "Note : parametr case-sensitive !"&LF severity error;

 --================================================================================
===========
   -- Проверка правильности ввода парамтеров Edge_type
   --================================================================================
===========    
   assert (Edge_type  = "Rising" or Edge_type  = "Falling" or Edge_type  = "All_edge") 
   report LF&
   "Incorrect parametr 'Edge_type'. Check the syntax !" &LF& 
   "Note : parametr case-sensitive !"&LF severity error;

  --================================================================================
===========
   -- Проверка правильности ввода парамтеров Reg_output (3)
   --================================================================================
===========    
   assert (Reg_output  = "Enable" or Reg_output  = "Disable") 
   report LF&
   "Incorrect parametr 'Reg_output'. Check the syntax !" &LF& 
   "Note : parametr case-sensitive !"&LF severity error;

end architecture;

 

Ну и отдельным файлом для скачивания.:

KAA_edge_dtct.vhd

 

Критикуйте, если есть ляпы :rolleyes: .

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тоже в связи с частыми вопросами про дребезг я решил выложить сюда свой модуль антидребезга.

Параметрами модуля можно ностроить:

1. Разрядность счетчика - определяющее время интегрирования.

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

3. Какой лог. уровень соответствует нажатой кнопке.

Как всегда приветствуются все замечания и предложения.

--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | File name       | KAA_button_debouncer | 
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Properties      | Tab type = space | HDL type =  VHDL2008 | Languege - Russian | Syntesis tool = Quartus 13.1 | Sim = Modelsim ASE
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Author          | Клементьев Алексей Александрович | Email = [email protected]
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Description     | Антидребезг кнопки с синхронизатором CDC и выбором активного уровня нажатой кнопки.
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Notes           | 1. В модуле предусмотрена настройка какому лог. уровню соответствует нажатая кнопка.
-- |                 |    За счет этого у нас сигнал-флаг нажатой кнопки всегда имеет логический уровень "1"
-- |                 | 2. Сдвиговый регистр-синхронизатор не может быть менше 2 разрядов.
-- |                 | 
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
————————————————————————————————
-- | Change history  | 
-- |                 | 
-- |                 | 
--  —————————————————  ————————————————————————————————————————————————————————————————————————————————
———————————————————————————————— 

   -- KAA_button_debouncer_comp : entity work.KAA_button_debouncer
   -- generic map
   -- (
       -- active_level    => "Negative",  --"Positive" / "Negative" Активный уровень нажатой кнопки
       -- sync_stages     =>  3,          -- Количество стадий синхронизации с клоковым доменом
       -- debouncer_width =>  7           -- Разрядность счетчика, который досчитав до конца выдаст фалг нажатой кнопки
   -- )
   -- port map
   -- (
       -- clk            =>
       -- debouncer_in   =>
       -- button_pressed =>
   -- );

--————————————————————————————————————————————————————————————————————————————————
——————————————————————————————————————————————————————     
library ieee;
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;

entity KAA_button_debouncer is
   generic
   (
       active_level    : string  := "Positive"; -- "Positive" / "Negative" Активный уровень нажатой кнопки
       sync_stages     : natural := 3;          -- Количество стадий синхронизации с клоковым доменом
       debouncer_width : natural := 6           -- Разрядность счетчика, который досчитав до конца выдаст фалг нажатой кнопки
   );
   port
   (
       clk            : in  std_logic;
       debouncer_in   : in  std_logic;       
       button_pressed : out std_logic
   );
end entity;

architecture rtl of KAA_button_debouncer is
   --=====================================================================
   -- Константы для удобства
   --=====================================================================
   constant up             : std_logic := '1';                                              -- Нажатая кнопка - счетчик считает вверх               
   constant down           : std_logic := '0';                                              -- Кнопка отпущна - счетчик считает вниз

   signal shreg            : std_logic_vector(sync_stages - 1 downto 0) := (others => '0');  -- Регистр - синхронизатор
   signal up_dissable      : std_logic                                                       -- Сигнал отключения счета вверх
   signal down_dissable    : std_logic                                                       -- Сигнал отключения счета вниз
   signal counter_unsigned : unsigned(debouncer_width -1 Downto 0)      := (others => '0');  -- Счетчик 
begin

   --=====================================================================
   -- Синхронизируем сигнал с клоковым доменом. 
   -- Так-же автоматически переводим активный уровень сигнала в лог.1
   -- Это позволит на выходе иметь сигнал-флаг нажатой кнопки лог.1
   --=====================================================================
   meta_harden_reg : process(clk)
   begin
       if (rising_edge(clk)) then
           if (active_level = "Positive") then                               -- Если активный уровнь лог.1 
               shreg <= shreg(shreg'left - 1 downto 0) & debouncer_in;       -- То записываем сигнал в регистр как есть.
           end if;

           if (active_level = "Negative") then                                -- Если активный уровнь лог.1 
               shreg <= shreg(shreg'left - 1 downto 0) & (not debouncer_in);  -- То записываем в ренгистр инверсию сигнала
           end if;
       end if;
   end process;

   --=====================================================================
   -- Сигналы отключения счета счетчика
   --=====================================================================
   up_dissable   <= '1' when (counter_unsigned = (counter_unsigned'left downto 0 => '1')) else '0'; -- Если все единички - запрети счетчику считать вверх
   down_dissable <= '1' when (counter_unsigned = (counter_unsigned'left downto 0 => '0')) else '0'; -- Если все нолики   - запрети счетчику считать вниз

   --=====================================================================
   -- Собственно сам счетчтик
   --=====================================================================
   cnt_proc : process(clk)
   begin    
       if (rising_edge(clk)) then      
           case shreg(shreg'left) is                                              -- Анализируем сигнал перенесенный в наш клоковый домен
               when up     =>                                                     -- Если кнопка нажата
                               if (up_dissable = '0') then                        -- Если счетчику не запрещено считать вверх
                                   counter_unsigned <= counter_unsigned + "1";    -- Инкрементируем счетчтик
                               end if;
               when down   =>                                                     -- Если кнопка отпущена
                               if (down_dissable = '0') then                      -- Если счетчику не запрещено считать вниза
                                   counter_unsigned <= counter_unsigned - "1";    -- Декрементируем счетчтик
                               end if;
               when others => null;    
           end case;
       end if;
   end process;   

   --=====================================================================
   -- Выходной триггер для формирования сигнала-флага нажатой кнопки
   --=====================================================================
   output_flip_flop : process(clk)
   begin    
       if (rising_edge(clk)) then      
           case counter_unsigned is  
               when (counter_unsigned'left downto 0 => '1') => button_pressed    <= '1';  -- Счетчик досчитал до конца(все единцы) - значит кнопка была нажата
               when (counter_unsigned'left downto 0 => '0') => button_pressed    <= '0';  -- Счетчик досчитал до конца(все нули)   - считаем что была отпущена
               when others                                  => null;                      -- В оостальных случаях триггер хранит свое значение
           end case;
       end if;
   end process;  

   --================================================================================
===========
   -- Счетчик не может быть равен 0 !!
   --================================================================================
=========== 
   assert (debouncer_width /= 0) 
   report LF& 
   "Incorrect parametr 'debouncer_width'. Check the syntax !" &LF& 
   "Note : parametr Must be > 0 !"&LF severity error;

   --================================================================================
===========
   -- Проверка правильности параметров active_level
   --================================================================================
===========  
   assert (active_level = "Negative" or active_level = "Positive") 
   report LF&
   "Incorrect parametr 'active_level'. Check the syntax !" &LF& 
   "Note : parametr case-sensitive !"&LF severity failure;

   -- ================================================================================
===========
   -- Разрядность регистра-синхронизатора не может быть меньше 2 !
   --================================================================================
=========== 
   assert (sync_stages >= 2) 
   report LF& 
   "Incorrect parametr 'sync_stages'. Check the syntax !" &LF& 
   "Note : parametr Must be > 2 !"&LF severity error;

end architecture;

 

KAA_button_debouncer.vhd

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 22.06.2018 в 07:22, Flip-fl0p сказал:

Не слишком ли много букв?

debounce.vhd

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, _sda сказал:

Не слишком ли много букв?

debounce.vhd

Когда встречаю такое

use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

возникают очень сильные сомния в квалификации автора.

Ну и без utils_pak этот код бесполезен.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, andrew_b сказал:

Когда встречаю такое

 


use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

 

возникают очень сильные сомния в квалификации автора.

Если сомния есть - сомнийтесь на здоровье. Мне за мою более чем двадцатилетнюю практику работы с FPGA эта сладкая парочка не преподнесла ни одного сюрприза.

 

2 часа назад, andrew_b сказал:

Ну и без utils_pak этот код бесполезен.

Это только Ваше уникальное мнение. В этом файле,в частности, просто описание типов sl и slv, которые и так понятны, но уменьшают количество букв(std_logic и std_logic_vector).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 часов назад, _sda сказал:

Не слишком ли много букв?

debounce.vhd

Букв достаточно, чтобы компонент можно было применять для любого вида кнопок с любым активным уровнем.

Алгоритм простой:

Мы настраиваем порог, досчитав до которого делается вывод о том, что кнопка нажата. Т.е. если кнопка нажата - счетчик считает вверх. Кнопка отпущена - счетчик считает вниз. Соответственно если счетчик смог досчитать вверх - значит у нас формируется сигнал button_pressed равный лог.1, говорящая о том, что кнопка была нажата.

Из преимуществ я вижу:

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

2. Отсутствие привязки к активному уровню сигнала, за счет того, что нажатой кнопке всегда соответствует флаг button_pressed = '1' . 

3. Максимальная простота работы модуля.

4. Хоть для современных FPGA уже не так актуально, однако мой модуль занимает минимальное количество ресурсов.

5. Контроль правильности вводимых параметров.

6. Защита от метастабильности.

7. Ну и самое главное, как я считаю - у меня достаточно подробно описано как, что и зачем в модуле сделано.

В вашем модуле мне не нравится:

 

1. вот эта строчка:

    if (ireset = '1') then
        cnt   <= (others => '0');
        odata <= idata;

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

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

P.S. и я не экономлю строчки кода. Я экономлю время, которое затрачивается на разработку.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 часов назад, _sda сказал:

Если сомния есть - сомнийтесь на здоровье.

Ну посмейтесь над обычной опечаткой, если больше не над чем. Да и клавиатурка старенькая, иногда не срабатывает.

11 часов назад, _sda сказал:

Мне за мою более чем двадцатилетнюю практику работы с FPGA эта сладкая парочка не преподнесла ни одного сюрприза.

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

11 часов назад, _sda сказал:

Это только Ваше уникальное мнение.

Разумеется, капитан Очевидность. Я где-то утверждал обратное?

11 часов назад, _sda сказал:

В этом файле,в частности

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 6/1/2019 at 2:40 AM, Flip-fl0p said:

Т.е. если кнопка нажата - счетчик считает вверх. Кнопка отпущена - счетчик считает вниз. Соответственно

Так это ж алгоритмически неверно. Нажата - увеличиваем. Ненажата - обнуляем. Иначе это не антидребезг совсем. Если счётчик достигнет порог-1 величины, то он же дальше будет этот самый дребезг пропускать на выход. Не так?

Ну а если в обе стороны надо, то после достижения верхнего предела - наооборот. Декремент , если состояние изменилось, но если вернулось к прежнему - установка на максимум сразу. Иными словами - антидребезг срабатывает тогда, когда состояние кнопки противоположно изначальному  N раз подряд без пропусков

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 часов назад, DASM сказал:

Так это ж алгоритмически неверно. Нажата - увеличиваем. Ненажата - обнуляем. Иначе это не антидребезг совсем. Если счётчик достигнет порог-1 величины, то он же дальше будет этот самый дребезг пропускать на выход. Не так?

Ну а если в обе стороны надо, то после достижения верхнего предела - наооборот. Декремент , если состояние изменилось, но если вернулось к прежнему - установка на максимум сразу. Иными словами - антидребезг срабатывает тогда, когда состояние кнопки противоположно изначальному  N раз подряд без пропусков

Почему алгоритмически неверно ?  Изначально счетчик в нуле, что соответствует не нажатой кнопке. Флаг button_pressed = '0'. Затем мы нажали на кнопку. Счетчик начал считать вверх. Из-за дребезга у нас с выхода кнопки то нули то единицы. Соответственно счетчик считает то вверх, то вниз. Когда счетчик смог досчитать до значения 2**debouncer_width - 1 ( во всех разрядах счетчика единицы) - значит что нажатие кнопки действительно было, и она была нажата достаточное время.  И мы выдаем флаг button_pressed = '1'. Ни о каком дребезге с кнопки речи быть не может.  Флаг button_pressed  станет снова нулем только тогда, когда счетчик досчитает до нуля ( во всех разрядах счетчика нули). Ежели у Вас такой сильный дребезг, что при нажатии кнопки счетчик прыгает от состояния "все единицы" <----> "все нули" - значит у вас сильно фиговая кнопка или неправильно настроен модуль - выбрана слишком маленькая разрядность счетчика, поэтому мы в настройках модуля выбираем бОльшую разрядность счетчика. Например 

debouncer_width =>  7 меняем на debouncer_width => 15

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...