debouncing sys_res_n
authorBernhard Urban <lewurm@gmail.com>
Sat, 22 May 2010 00:24:19 +0000 (02:24 +0200)
committerBernhard Urban <lewurm@gmail.com>
Sat, 22 May 2010 00:24:19 +0000 (02:24 +0200)
20 files changed:
quartus/project_gen.tcl
src/Makefile
src/TODO
src/calc.vhd
src/debouncing/counter.vhd [new file with mode: 0644]
src/debouncing/counter_beh.vhd [new file with mode: 0644]
src/debouncing/debounce.vhd [new file with mode: 0644]
src/debouncing/debounce_fsm.vhd [new file with mode: 0644]
src/debouncing/debounce_fsm_beh.vhd [new file with mode: 0644]
src/debouncing/debounce_pkg.vhd [new file with mode: 0644]
src/debouncing/debounce_struct.vhd [new file with mode: 0644]
src/debouncing/debounce_tb.vhd [new file with mode: 0644]
src/debouncing/debounce_top.vhd [new file with mode: 0644]
src/debouncing/debounce_top_struct.vhd [new file with mode: 0644]
src/debouncing/event_counter.vhd [new file with mode: 0644]
src/debouncing/event_counter_beh.vhd [new file with mode: 0644]
src/debouncing/event_counter_pkg.vhd [new file with mode: 0644]
src/debouncing/sync.vhd [new file with mode: 0644]
src/debouncing/sync_beh.vhd [new file with mode: 0644]
src/debouncing/sync_pkg.vhd [new file with mode: 0644]

index e972811d60b8caffbc7263039ef9d55c79342d3d..2f5df6d0a6fdf78788e458698897dce3288cb80a 100644 (file)
@@ -83,6 +83,23 @@ if {$make_assignments} {
        #gen ip-core
        set_global_assignment -name VHDL_FILE ../../src/math_pkg.vhd
 
+       #debouncing
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/counter.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/counter_beh.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/debounce.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/debounce_fsm.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/debounce_fsm_beh.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/debounce_pkg.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/debounce_struct.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/debounce_tb.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/debounce_top.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/debounce_top_struct.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/event_counter.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/event_counter_beh.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/event_counter_pkg.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/sync.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/sync_beh.vhd
+       set_global_assignment -name VHDL_FILE ../../src/debouncing/sync_pkg.vhd
 
        #pin mapping/system
        set_location_assignment PIN_N3 -to sys_clk
index 10f5e593cf57ad8cbfa7e29c1f8ae6840e59248c..a09058aa05fbec67e574d6605d4534fe441cac06 100644 (file)
@@ -68,12 +68,12 @@ $(D_BEHSIM)/modelsim.ini:
 
 $(D_BEHSIM)/$(WORK)/%/_primary.dat: %.vhd $(D_BEHSIM)/modelsim.ini
        @echo " CC    $<"
-       @cd $(D_BEHSIM); \
-       vcom -work $(WORK) $(MPWD)/$<
+       cd $(D_BEHSIM); \
+       vcom -cover bcest -work $(WORK) $(MPWD)/$<
 
 beh_%: $(D_BEHSIM)/$(WORK)/beh_%_tb/_primary.dat beh_%_tb.do behsim
        cd $(D_BEHSIM); \
-       vsim "work.$@_tb(sim)" -f /dev/null -do $(MPWD)/$@_tb.do
+       vsim -coverage "work.$@_tb(sim)" -f /dev/null -do $(MPWD)/$@_tb.do
 
 #postsim
 postsim: $(POST_VHO) $(POST_SDO)
index 3a619e93c7f7feb47312ac4f69c4519ae6f31d34..e9df3f04123345ee66ff9d8bd280cd48df378881 100644 (file)
--- a/src/TODO
+++ b/src/TODO
@@ -13,6 +13,8 @@
        o vorteil: man kann auf der taste drauf bleiben und man kann
          keine zahlen mehr mit den coursertasten eingeben
 
+- uart rx oversampling, uart rx synchronizen (vlg. debouncing/sync*.vhd)
+
 == low prio ==
 - mehr testfaelle fuer alu/scanner/parser
 - parser refactor
index 41250e1432867e1a56e6ed73b774eb0ab85a7311..cdee994ba039e688a034856345e279613f82c02c 100644 (file)
@@ -6,6 +6,8 @@ use work.textmode_vga_component_pkg.all;
 use work.textmode_vga_pkg.all;
 use work.textmode_vga_platform_dependent_pkg.all;
 use work.ps2_keyboard_controller_pkg.all;
+use work.debounce_pkg.all;
+use work.sync_pkg.all;
 
 entity calc is
        port (
@@ -55,6 +57,8 @@ architecture top of calc is
        signal p_finished : std_logic;
        -- parser/scanner
        signal do_it, finished : std_logic;
+       -- debouncing
+       signal sys_res_n_sync : std_logic;
 begin
        -- vga/ipcore
        textmode_vga_inst : entity work.textmode_vga(struct)
@@ -65,12 +69,12 @@ begin
        )
        port map (
                sys_clk => sys_clk,
-               sys_res_n => sys_res_n,
+               sys_res_n => sys_res_n_sync,
                command => command,
                command_data => command_data,
                free => free,
                vga_clk => vga_clk,
-               vga_res_n => sys_res_n,
+               vga_res_n => sys_res_n_sync,
                vsync_n => vsync_n,
                hsync_n => hsync_n,
                r => r,
@@ -89,7 +93,7 @@ begin
        display_inst : entity work.display(beh)
        port map (
                sys_clk => sys_clk,
-               sys_res_n => sys_res_n,
+               sys_res_n => sys_res_n_sync,
                -- history
                d_new_eingabe => d_new_eingabe,
                d_new_result => d_new_result,
@@ -109,7 +113,7 @@ begin
        history_inst : entity work.history(beh)
        port map (
                sys_clk => sys_clk,
-               sys_res_n => sys_res_n,
+               sys_res_n => sys_res_n_sync,
                -- scanner
                s_char => s_char,
                s_take => s_take,
@@ -138,7 +142,7 @@ begin
        parser_inst : entity work.parser(beh)
        port map (
                sys_clk => sys_clk,
-               sys_res_n => sys_res_n,
+               sys_res_n => sys_res_n_sync,
                -- history
                p_rget => p_rget,
                p_rdone => p_rdone,
@@ -156,7 +160,7 @@ begin
        scanner_inst : entity work.scanner(beh)
        port map (
                sys_clk => sys_clk,
-               sys_res_n => sys_res_n,
+               sys_res_n => sys_res_n_sync,
                -- ps/2
                new_data => new_data,
                data => data,
@@ -178,12 +182,27 @@ begin
        )
        port map (
                sys_clk => sys_clk,
-               sys_res_n => sys_res_n,
+               sys_res_n => sys_res_n_sync,
                -- scanner
                new_data => new_data,
                data => data,
                ps2_clk => ps2_clk,
                ps2_data => ps2_data
        );
+
+       -- debouncer fuer sys_res_n
+       sys_res_n_debounce_inst : debounce
+       generic map (
+               CLK_FREQ => 33330000,
+               TIMEOUT => 1 ms,
+               RESET_VALUE => '1',
+               SYNC_STAGES => 2
+       )
+       port map (
+               sys_clk => sys_clk,
+               sys_res_n => '1',
+               data_in => sys_res_n,
+               data_out => sys_res_n_sync
+       );
 end architecture top;
 
diff --git a/src/debouncing/counter.vhd b/src/debouncing/counter.vhd
new file mode 100644 (file)
index 0000000..1aac4c3
--- /dev/null
@@ -0,0 +1,17 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use work.math_pkg.all;\r
+\r
+entity counter is\r
+  generic\r
+  (\r
+    CNT_MAX : integer range 2 to integer'high\r
+  );\r
+  port\r
+  (\r
+    sys_clk : in std_logic;\r
+    sys_res_n : in std_logic;\r
+    clear_cnt : in std_logic;\r
+    cnt : out std_logic_vector(log2c(CNT_MAX) - 1 downto 0)\r
+  );\r
+end entity counter;\r
diff --git a/src/debouncing/counter_beh.vhd b/src/debouncing/counter_beh.vhd
new file mode 100644 (file)
index 0000000..75b711c
--- /dev/null
@@ -0,0 +1,30 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+use work.math_pkg.all;\r
+\r
+architecture beh of counter is\r
+  signal cnt_int, cnt_next : integer range 0 to CNT_MAX;\r
+begin\r
+  cnt <= std_logic_vector(to_unsigned(cnt_int, log2c(CNT_MAX)));\r
+\r
+  process(sys_clk, sys_res_n)\r
+  begin\r
+    if sys_res_n = '0' then\r
+      cnt_int <= 0;\r
+    elsif rising_edge(sys_clk) then\r
+      cnt_int <= cnt_next;\r
+    end if;\r
+  end process;\r
+\r
+  process(cnt_int, clear_cnt)\r
+  begin\r
+    cnt_next <= cnt_int;\r
+\r
+    if clear_cnt = '1' then\r
+      cnt_next <= 0;\r
+    elsif cnt_int < CNT_MAX then\r
+      cnt_next <= cnt_int + 1;\r
+    end if;\r
+  end process;\r
+end architecture beh;\r
diff --git a/src/debouncing/debounce.vhd b/src/debouncing/debounce.vhd
new file mode 100644 (file)
index 0000000..79a8d26
--- /dev/null
@@ -0,0 +1,20 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+entity debounce is\r
+  generic\r
+  (\r
+    CLK_FREQ    : integer;\r
+    TIMEOUT     : time range 100 us to 100 ms := 1 ms;\r
+    RESET_VALUE : std_logic := '0';\r
+    SYNC_STAGES : integer range 2 to integer'high\r
+  );\r
+  port\r
+  (\r
+    sys_clk : in std_logic;\r
+    sys_res_n : in std_logic;\r
+\r
+    data_in : in std_logic;\r
+    data_out : out std_logic\r
+  );\r
+end entity debounce;\r
diff --git a/src/debouncing/debounce_fsm.vhd b/src/debouncing/debounce_fsm.vhd
new file mode 100644 (file)
index 0000000..dbc22b9
--- /dev/null
@@ -0,0 +1,20 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use work.math_pkg.all;\r
+\r
+entity debounce_fsm is\r
+  generic\r
+  (\r
+    RESET_VALUE : std_logic;\r
+    CNT_MAX : integer range 2 to integer'high\r
+  );\r
+  port\r
+  (\r
+    sys_clk : in std_logic;\r
+    sys_res_n : in std_logic;\r
+    i : in std_logic;\r
+    cnt : in std_logic_vector(log2c(CNT_MAX) - 1 downto 0);\r
+    clear_cnt : out std_logic;\r
+    o : out std_logic\r
+  );\r
+end entity debounce_fsm;\r
diff --git a/src/debouncing/debounce_fsm_beh.vhd b/src/debouncing/debounce_fsm_beh.vhd
new file mode 100644 (file)
index 0000000..f30d43b
--- /dev/null
@@ -0,0 +1,71 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+architecture beh of debounce_fsm is\r
+  type DEBOUNCE_FSM_STATE_TYPE is\r
+    (IDLE0, TIMEOUT0, IDLE1, TIMEOUT1);\r
+  signal debounce_fsm_state, debounce_fsm_state_next : DEBOUNCE_FSM_STATE_TYPE;\r
+begin\r
+  next_state : process(debounce_fsm_state, i, cnt)\r
+  begin\r
+    debounce_fsm_state_next <= debounce_fsm_state;\r
+    case debounce_fsm_state is\r
+      when IDLE0 =>\r
+        if i = '1' then\r
+          debounce_fsm_state_next <= TIMEOUT0;\r
+        end if;\r
+      when TIMEOUT0 =>\r
+        if i = '0' then\r
+          debounce_fsm_state_next <= IDLE0;\r
+        elsif to_integer(unsigned(cnt)) = CNT_MAX then\r
+          debounce_fsm_state_next <= IDLE1;\r
+        end if;\r
+      when IDLE1 =>\r
+        if i = '0' then\r
+          debounce_fsm_state_next <= TIMEOUT1;\r
+        end if;\r
+      when TIMEOUT1 =>\r
+        if i = '1' then\r
+          debounce_fsm_state_next <= IDLE1;\r
+        elsif to_integer(unsigned(cnt)) = CNT_MAX then\r
+          debounce_fsm_state_next <= IDLE0;\r
+        end if;\r
+    end case;\r
+  end process next_state;\r
+\r
+  output : process(debounce_fsm_state)\r
+  begin\r
+    o <= RESET_VALUE;\r
+    clear_cnt <= '1';\r
+\r
+    case debounce_fsm_state is\r
+      when IDLE0 =>\r
+        o <= '0';\r
+      when TIMEOUT0 =>\r
+        o <= '0';\r
+        clear_cnt <= '0';\r
+      when IDLE1 =>\r
+        o <= '1';\r
+      when TIMEOUT1 =>\r
+        o <= '1';\r
+        clear_cnt <= '0';\r
+    end case;\r
+  end process output;\r
+\r
+  assert RESET_VALUE = '0' or RESET_VALUE = '1' report\r
+    "RESET_VALUE may only be 0 or 1!" severity failure;\r
+\r
+  sync : process(sys_clk, sys_res_n)\r
+  begin\r
+    if sys_res_n = '0' then\r
+      if RESET_VALUE = '0' then\r
+        debounce_fsm_state <= IDLE0;\r
+      else\r
+        debounce_fsm_state <= IDLE1;\r
+      end if;\r
+    elsif rising_edge(sys_clk) then\r
+      debounce_fsm_state <= debounce_fsm_state_next;\r
+    end if;\r
+  end process sync;\r
+end architecture beh;\r
diff --git a/src/debouncing/debounce_pkg.vhd b/src/debouncing/debounce_pkg.vhd
new file mode 100644 (file)
index 0000000..1368846
--- /dev/null
@@ -0,0 +1,54 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use work.math_pkg.all;\r
+\r
+package debounce_pkg is\r
+  component debounce_fsm is\r
+    generic\r
+    (\r
+      RESET_VALUE : std_logic;\r
+      CNT_MAX : integer range 2 to integer'high\r
+    );\r
+    port\r
+    (\r
+      sys_clk : in std_logic;\r
+      sys_res_n : in std_logic;\r
+      i : in std_logic;\r
+      cnt : in std_logic_vector(log2c(CNT_MAX) - 1 downto 0);\r
+      clear_cnt : out std_logic;\r
+      o : out std_logic\r
+    );\r
+  end component debounce_fsm;\r
+\r
+  component counter is\r
+    generic\r
+    (\r
+      CNT_MAX : integer range 2 to integer'high\r
+    );\r
+    port\r
+    (\r
+      sys_clk : in std_logic;\r
+      sys_res_n : in std_logic;\r
+      clear_cnt : in std_logic;\r
+      cnt : out std_logic_vector(log2c(CNT_MAX) - 1 downto 0)\r
+    );\r
+  end component counter;\r
+\r
+  component debounce is\r
+    generic\r
+    (\r
+      CLK_FREQ    : integer;\r
+      TIMEOUT     : time range 100 us to 100 ms := 1 ms;\r
+      RESET_VALUE : std_logic := '0';\r
+      SYNC_STAGES : integer range 2 to integer'high\r
+    );\r
+    port\r
+    (\r
+      sys_clk : in std_logic;\r
+      sys_res_n : in std_logic;\r
+\r
+      data_in : in std_logic;\r
+      data_out : out std_logic\r
+    );\r
+  end component debounce;\r
+end package debounce_pkg;\r
diff --git a/src/debouncing/debounce_struct.vhd b/src/debouncing/debounce_struct.vhd
new file mode 100644 (file)
index 0000000..5e3684c
--- /dev/null
@@ -0,0 +1,56 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use work.sync_pkg.all;\r
+use work.debounce_pkg.all;\r
+use work.math_pkg.all;\r
+\r
+architecture struct of debounce is\r
+  constant CLK_PERIOD : time := 1E9 / CLK_FREQ * 1 ns;\r
+  constant CNT_MAX : integer := TIMEOUT / CLK_PERIOD;\r
+  signal data_sync : std_logic;\r
+  signal clear_cnt : std_logic;\r
+  signal cnt : std_logic_vector(log2c(CNT_MAX) - 1 downto 0);\r
+begin\r
+  sync_inst : sync\r
+    generic map\r
+    (\r
+      SYNC_STAGES => SYNC_STAGES,\r
+      RESET_VALUE => RESET_VALUE\r
+    )\r
+    port map\r
+    (\r
+      sys_clk => sys_clk,\r
+      sys_res_n => sys_res_n,\r
+      data_in => data_in,\r
+      data_out => data_sync\r
+    );\r
+\r
+  fsm_inst : debounce_fsm\r
+    generic map\r
+    (\r
+      RESET_VALUE => RESET_VALUE,\r
+      CNT_MAX => CNT_MAX\r
+    )\r
+    port map\r
+    (\r
+      sys_clk => sys_clk,\r
+      sys_res_n => sys_res_n,\r
+      i => data_sync,\r
+      o => data_out,\r
+      clear_cnt => clear_cnt,\r
+      cnt => cnt\r
+    );\r
+\r
+  counter_inst : counter\r
+    generic map\r
+    (\r
+      CNT_MAX => CNT_MAX\r
+    )\r
+    port map\r
+    (\r
+      sys_clk => sys_clk,\r
+      sys_res_n => sys_res_n,\r
+      clear_cnt => clear_cnt,\r
+      cnt => cnt\r
+    );\r
+end architecture struct;\r
diff --git a/src/debouncing/debounce_tb.vhd b/src/debouncing/debounce_tb.vhd
new file mode 100644 (file)
index 0000000..ce4744c
--- /dev/null
@@ -0,0 +1,97 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity debounce_tb is
+end entity debounce_tb;
+
+architecture sim of debounce_tb is
+  component debounce_top is
+    port
+    (
+      sys_clk : in std_logic;
+      sys_res_n : in std_logic;
+      btn_a : in std_logic;
+      seg_a : out std_logic_vector(6 downto 0);
+      seg_b : out std_logic_vector(6 downto 0)
+    );
+  end component debounce_top;
+  
+  signal sys_clk, sys_res_n : std_logic;
+  signal btn_a : std_logic;
+  signal seg_a, seg_b : std_logic_vector(6 downto 0);
+  signal stop : boolean := false;
+begin
+  uut : debounce_top
+    port map
+    (
+      sys_clk => sys_clk,
+      sys_res_n => sys_res_n,
+      btn_a => btn_a,
+      seg_a => seg_a,
+      seg_b => seg_b
+    );
+    
+  process
+  begin
+    sys_clk <= '0';
+    wait for 15 ns;
+    sys_clk <= '1';
+    if stop = true then
+      wait;
+    end if;
+    wait for 15 ns;
+  end process;
+  
+  process
+  begin
+    sys_res_n <= '0';
+    btn_a <= '1';
+    wait for 100 ns;
+    sys_res_n <= '1';
+    wait for 2 ms;
+    btn_a <= '0';
+    wait for 100 us;
+    btn_a <= '1';
+    wait for 50 us;
+    btn_a <= '0';
+    wait for 150 us;
+    btn_a <= '1';
+    wait for 25 us;
+    btn_a <= '0';
+    wait for 175 us;
+    btn_a <= '1';
+    wait for 1 us;
+    btn_a <= '0';
+    wait for 2 ms;
+    btn_a <= '1';
+    wait for 100 us;
+    btn_a <= '0';
+    wait for 50 us;
+    btn_a <= '1';
+    wait for 150 us;
+    btn_a <= '0';
+    wait for 25 us;
+    btn_a <= '1';
+    wait for 175 us;
+    btn_a <= '0';
+    wait for 1 us;
+    btn_a <= '1';
+    wait for 2 ms;
+    btn_a <= '0';
+    wait for 100 us;
+    btn_a <= '1';
+    wait for 50 us;
+    btn_a <= '0';
+    wait for 150 us;
+    btn_a <= '1';
+    wait for 25 us;
+    btn_a <= '0';
+    wait for 175 us;
+    btn_a <= '1';
+    wait for 1 us;
+    btn_a <= '0';
+    wait for 2 ms;
+    stop <= true;
+    wait;
+  end process;
+end architecture sim;
diff --git a/src/debouncing/debounce_top.vhd b/src/debouncing/debounce_top.vhd
new file mode 100644 (file)
index 0000000..0152c5c
--- /dev/null
@@ -0,0 +1,13 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+entity debounce_top is\r
+  port\r
+  (\r
+    sys_clk : in std_logic;\r
+    sys_res_n : in std_logic;\r
+    btn_a : in std_logic;\r
+    seg_a : out std_logic_vector(6 downto 0);\r
+    seg_b : out std_logic_vector(6 downto 0)\r
+  );\r
+end entity debounce_top;\r
diff --git a/src/debouncing/debounce_top_struct.vhd b/src/debouncing/debounce_top_struct.vhd
new file mode 100644 (file)
index 0000000..3d1bcb8
--- /dev/null
@@ -0,0 +1,90 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use work.debounce_pkg.all;\r
+use work.sync_pkg.all;\r
+use work.event_counter_pkg.all;\r
+\r
+architecture struct of debounce_top is\r
+  constant CLK_FREQ : integer := 33330000;\r
+  constant TIMEOUT : time := 1 ms;\r
+  constant RES_N_DEFAULT_VALUE : std_logic := '1';\r
+  constant SYNC_STAGES : integer := 2;\r
+  constant BTN_A_RESET_VALUE : std_logic := '1';\r
+  constant EVENT_CNT_WIDTH : integer := 8;\r
+\r
+  signal sys_res_n_sync, btn_a_sync : std_logic;\r
+  signal event_cnt : std_logic_vector(EVENT_CNT_WIDTH - 1 downto 0);\r
+\r
+  function to_segs(value : in std_logic_vector(3 downto 0)) return std_logic_vector is\r
+  begin\r
+    case value is\r
+      when x"0" => return "1000000";\r
+      when x"1" => return "1111001";\r
+      when x"2" => return "0100100";\r
+      when x"3" => return "0110000";\r
+      when x"4" => return "0011001";\r
+      when x"5" => return "0010010";\r
+      when x"6" => return "0000010";\r
+      when x"7" => return "1111000";\r
+      when x"8" => return "0000000";\r
+      when x"9" => return "0010000";\r
+      when x"A" => return "0001000";\r
+      when x"B" => return "0000011";\r
+      when x"C" => return "1000110";\r
+      when x"D" => return "0100001";\r
+      when x"E" => return "0000110";\r
+      when x"F" => return "0001110";\r
+      when others => return "1111111";\r
+    end case;\r
+  end function;  \r
+begin\r
+  sys_res_n_debounce_inst : debounce\r
+    generic map\r
+    (\r
+      CLK_FREQ => CLK_FREQ,\r
+      TIMEOUT => TIMEOUT,\r
+      RESET_VALUE => RES_N_DEFAULT_VALUE,\r
+      SYNC_STAGES => SYNC_STAGES\r
+    )\r
+    port map\r
+    (\r
+      sys_clk => sys_clk,\r
+      sys_res_n => '1',\r
+      data_in => sys_res_n,\r
+      data_out => sys_res_n_sync\r
+    );\r
+\r
+    btn_a_debounce_inst : debounce\r
+    generic map\r
+    (\r
+      CLK_FREQ => CLK_FREQ,\r
+      TIMEOUT => TIMEOUT,\r
+      RESET_VALUE => BTN_A_RESET_VALUE,\r
+      SYNC_STAGES => SYNC_STAGES\r
+    )\r
+    port map\r
+    (\r
+      sys_clk => sys_clk,\r
+      sys_res_n => sys_res_n_sync,\r
+      data_in => btn_a,\r
+      data_out => btn_a_sync\r
+    );\r
+\r
+  event_cnt_inst : event_counter\r
+    generic map\r
+    (\r
+      CNT_WIDTH => EVENT_CNT_WIDTH,\r
+      RESET_VALUE => BTN_A_RESET_VALUE\r
+    )\r
+    port map\r
+    (\r
+      sys_clk => sys_clk,\r
+      sys_res_n => sys_res_n_sync,\r
+      sense => btn_a_sync,\r
+      cnt => event_cnt\r
+    );\r
+\r
+  seg_a <= to_segs(event_cnt(3 downto 0));\r
+  seg_b <= to_segs(event_cnt(7 downto 4));\r
+\r
+end architecture struct;\r
diff --git a/src/debouncing/event_counter.vhd b/src/debouncing/event_counter.vhd
new file mode 100644 (file)
index 0000000..9d5aadc
--- /dev/null
@@ -0,0 +1,17 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+entity event_counter is\r
+  generic\r
+  (\r
+    CNT_WIDTH : integer range 4 to integer'high;\r
+    RESET_VALUE : std_logic\r
+  );\r
+  port\r
+  (\r
+    sys_clk : in std_logic;\r
+    sys_res_n : in std_logic;\r
+    sense : in std_logic;\r
+    cnt : out std_logic_vector(CNT_WIDTH - 1 downto 0)\r
+  );\r
+end entity event_counter;\r
diff --git a/src/debouncing/event_counter_beh.vhd b/src/debouncing/event_counter_beh.vhd
new file mode 100644 (file)
index 0000000..9d7b8b8
--- /dev/null
@@ -0,0 +1,31 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.numeric_std.all;\r
+\r
+architecture beh of event_counter is\r
+  signal sense_old, sense_old_next : std_logic;\r
+  signal cnt_int, cnt_next : std_logic_vector(CNT_WIDTH - 1 downto 0);\r
+begin\r
+  cnt <= cnt_int;\r
+\r
+  process(sys_clk, sys_res_n)\r
+  begin\r
+    if sys_res_n = '0' then\r
+      cnt_int <= (others => '0');\r
+      sense_old <= RESET_VALUE;\r
+    elsif rising_edge(sys_clk) then\r
+      cnt_int <= cnt_next;\r
+      sense_old <= sense_old_next;\r
+    end if;\r
+  end process;\r
+  \r
+  process(cnt_int, sense, sense_old)\r
+  begin\r
+    sense_old_next <= sense;\r
+    cnt_next <= cnt_int;\r
+\r
+    if sense_old /= sense and sense = '0' then\r
+      cnt_next <= std_logic_vector(unsigned(cnt_int) + 1);\r
+    end if;\r
+  end process;\r
+end architecture beh;\r
diff --git a/src/debouncing/event_counter_pkg.vhd b/src/debouncing/event_counter_pkg.vhd
new file mode 100644 (file)
index 0000000..3a2b36d
--- /dev/null
@@ -0,0 +1,19 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+package event_counter_pkg is\r
+  component event_counter is\r
+    generic\r
+    (\r
+      CNT_WIDTH : integer range 4 to integer'high;\r
+      RESET_VALUE : std_logic\r
+    );\r
+    port\r
+    (\r
+      sys_clk : in std_logic;\r
+      sys_res_n : in std_logic;\r
+      sense : in std_logic;\r
+      cnt : out std_logic_vector(CNT_WIDTH - 1 downto 0)\r
+    );\r
+  end component event_counter;\r
+end package event_counter_pkg;\r
diff --git a/src/debouncing/sync.vhd b/src/debouncing/sync.vhd
new file mode 100644 (file)
index 0000000..8515bd6
--- /dev/null
@@ -0,0 +1,17 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+entity sync is\r
+  generic\r
+  (\r
+    SYNC_STAGES : integer range 2 to integer'high;\r
+    RESET_VALUE : std_logic\r
+  );\r
+  port\r
+  (\r
+    sys_clk : in std_logic;\r
+    sys_res_n : in std_logic;\r
+    data_in : in std_logic;\r
+    data_out : out std_logic\r
+  );\r
+end entity sync;\r
diff --git a/src/debouncing/sync_beh.vhd b/src/debouncing/sync_beh.vhd
new file mode 100644 (file)
index 0000000..826bb12
--- /dev/null
@@ -0,0 +1,19 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+architecture beh of sync is\r
+  signal sync : std_logic_vector(1 to SYNC_STAGES);\r
+begin\r
+  process(sys_clk, sys_res_n)\r
+  begin\r
+    if sys_res_n = '0' then\r
+      sync <= (others => RESET_VALUE);\r
+    elsif rising_edge(sys_clk) then\r
+      sync(1) <= data_in;\r
+      for i in 2 to SYNC_STAGES loop\r
+        sync(i) <= sync(i - 1);\r
+      end loop;\r
+    end if;\r
+  end process;\r
+  data_out <= sync(SYNC_STAGES);\r
+end architecture beh;\r
diff --git a/src/debouncing/sync_pkg.vhd b/src/debouncing/sync_pkg.vhd
new file mode 100644 (file)
index 0000000..cf98e57
--- /dev/null
@@ -0,0 +1,19 @@
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+\r
+package sync_pkg is\r
+  component sync is\r
+    generic\r
+    (\r
+      SYNC_STAGES : integer range 2 to integer'high;\r
+      RESET_VALUE : std_logic\r
+    );\r
+    port\r
+    (\r
+      sys_clk : in std_logic;\r
+      sys_res_n : in std_logic;\r
+      data_in : in std_logic;\r
+      data_out : out std_logic\r
+    );\r
+  end component sync;\r
+end package sync_pkg;\r