URL
https://opencores.org/ocsvn/forth-cpu/forth-cpu/trunk
Subversion Repositories forth-cpu
[/] [forth-cpu/] [trunk/] [kbd.vhd] - Rev 3
Go to most recent revision | Compare with Previous | Blame | View Log
-------------------------------------------------------------------------------- -- -- FileName: kbd.vhd -- Dependencies: debounce.vhd -- Design Software: Quartus II 32-bit Version 12.1 Build 177 SJ Full Version -- -- HDL CODE is PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY -- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY -- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL -- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF -- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS -- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), -- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. -- -- Version History -- Version 1.0 11/29/2013 Scott Larson -- Initial Public Release -- -- See https://eewiki.net/pages/viewpage.action?pageId=28279002 -- -- @note This file has been renamed and updated from the original. -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; package kbd_pkg is component ps2_kbd_top is generic( clock_frequency: integer := 50000000; -- system clock frequency in hz ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz) port( clk: in std_ulogic; -- system clock input ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard ps2_data: in std_ulogic; -- data signal from PS2 keyboard ascii_new: out std_ulogic := '0'; -- output flag indicating new ascii value ascii_code: out std_ulogic_vector(6 downto 0)); -- ASCII value end component; component ps2_kbd_core is generic( clock_frequency: integer := 50000000; -- system clock frequency in hz debounce_counter_size: integer := 8); -- set such that (2^size)/clock_frequency = 5us (size = 8 for 50mhz) port( clk: in std_ulogic; -- system clock ps2_clk: in std_ulogic; -- clock signal from PS/2 keyboard ps2_data: in std_ulogic; -- data signal from PS/2 keyboard ps2_code_new: out std_ulogic; -- flag that new PS/2 code is available on ps2_code bus ps2_code: out std_ulogic_vector(7 downto 0)); -- code received from PS/2 end component; component ps2_debounce is generic(counter_size: integer := 19); --counter size (19 bits gives 10.5ms with 50mhz clock) port( clk: in std_ulogic; button: in std_ulogic; --input signal to be debounced result: out std_ulogic := '0'); --debounced signal end component; component keyboard is generic( clock_frequency: integer := 50000000; -- system clock frequency in hz ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz) port( clk: in std_ulogic; -- system clock input rst: in std_ulogic; -- system reset ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard ps2_data: in std_ulogic; -- data signal from PS2 keyboard kbd_char_re: in std_ulogic; -- acknowledge kbd_char_buf_new kbd_char_buf_new: out std_ulogic := '0'; -- output flag indicating new ascii value kbd_char_buf: out std_ulogic_vector(6 downto 0)); -- ASCII value end component; end package; ------ Keyboard ---------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use work.kbd_pkg.all; entity keyboard is generic( clock_frequency: integer := 50000000; -- system clock frequency in hz ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz) port( clk: in std_ulogic; -- system clock input rst: in std_ulogic; -- system reset ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard ps2_data: in std_ulogic; -- data signal from PS2 keyboard kbd_char_re: in std_ulogic; -- acknowledge kbd_char_buf_new kbd_char_buf_new: out std_ulogic := '0'; -- output flag indicating new ascii value kbd_char_buf: out std_ulogic_vector(6 downto 0)); -- ASCII value end entity; architecture rtl of keyboard is signal kbd_new_c, kbd_new_n: std_ulogic := '0'; signal kbd_new_edge: std_ulogic := '0'; signal kbd_new: std_ulogic := '0'; -- new ASCII char available signal kbd_char: std_ulogic_vector(kbd_char_buf'range) := (others => '0'); -- ASCII char signal kbd_char_o: std_ulogic_vector(kbd_char_buf'range) := (others => '0'); -- ASCII char begin kbd_char_buf_new <= kbd_new_c; ps2_next: process(clk, rst) begin if rst = '1' then kbd_new_c <= '0'; elsif rising_edge(clk) then kbd_new_c <= kbd_new_n; end if; end process; new_char: entity work.reg generic map(N => kbd_char'high+1) port map( clk => clk, rst => rst, di => kbd_char, we => kbd_new_edge, do => kbd_char_o); char_buf: entity work.reg generic map(N => kbd_char'high+1) port map( clk => clk, rst => rst, di => kbd_char_o, we => kbd_char_re, do => kbd_char_buf); ps2_proc: process(kbd_new_edge, kbd_new_c, kbd_char_re) begin if kbd_new_edge = '1' then kbd_new_n <= '1'; elsif kbd_char_re = '1' then kbd_new_n <= '0'; else kbd_new_n <= kbd_new_c; end if; end process; -- Process a kbd_new into a single edge for the rest of the -- system. ps2_edge_new_character_0: entity work.rising_edge_detector port map( clk => clk, rst => rst, di => kbd_new, do => kbd_new_edge); ps2_0: work.kbd_pkg.ps2_kbd_top generic map( clock_frequency => clock_frequency, ps2_debounce_counter_size => ps2_debounce_counter_size) port map( clk => clk, ps2_clk => ps2_clk, ps2_data => ps2_data, ascii_new => kbd_new, ascii_code => kbd_char); end architecture; ------ Keyboard ---------------------------------------------------------------- ------ PS2 KBD TOP ------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use work.kbd_pkg.all; entity ps2_kbd_top is generic( clock_frequency: integer := 50000000; -- system clock frequency in hz ps2_debounce_counter_size: integer := 8); -- set such that 2^size/clock_frequency = 5us (size = 8 for 50mhz) port( clk: in std_ulogic; -- system clock input ps2_clk: in std_ulogic; -- clock signal from PS2 keyboard ps2_data: in std_ulogic; -- data signal from PS2 keyboard ascii_new: out std_ulogic := '0'; -- output flag indicating new ascii value ascii_code: out std_ulogic_vector(6 downto 0)); -- ASCII value end entity; architecture rtl of ps2_kbd_top is type machine is(ready, new_code, translate, output); -- needed states signal state: machine; -- state machine signal ps2_code_new: std_ulogic; -- new PS2 code flag from ps2_kbd_core component signal ps2_code: std_ulogic_vector(7 downto 0); -- PS2 code input form ps2_kbd_core component signal prev_ps2_code_new: std_ulogic := '1'; -- value of ps2_code_new flag on previous clock signal break: std_ulogic := '0'; -- '1' for break code, '0' for make code signal e0_code: std_ulogic := '0'; -- '1' for multi-code commands, '0' for single code commands signal caps_lock: std_ulogic := '0'; -- '1' if caps lock is active, '0' if caps lock is inactive signal control_r: std_ulogic := '0'; -- '1' if right control key is held down, else '0' signal control_l: std_ulogic := '0'; -- '1' if left control key is held down, else '0' signal shift_r: std_ulogic := '0'; -- '1' if right shift is held down, else '0' signal shift_l: std_ulogic := '0'; -- '1' if left shift is held down, else '0' signal ascii: std_ulogic_vector(7 downto 0) := x"FF"; -- internal value of ASCII translation begin -- instantiate PS2 keyboard interface logic ps2_kbd_core_0: work.kbd_pkg.ps2_kbd_core generic map( clock_frequency => clock_frequency, debounce_counter_size => ps2_debounce_counter_size) port map( clk => clk, ps2_clk => ps2_clk, ps2_data => ps2_data, ps2_code_new => ps2_code_new, ps2_code => ps2_code); process(clk) begin if rising_edge(clk) then prev_ps2_code_new <= ps2_code_new; -- keep track of previous ps2_code_new values to determine low-to-high transitions case state is -- ready state: wait for a new PS2 code to be received when ready => if(prev_ps2_code_new = '0' AND ps2_code_new = '1') then -- new PS2 code received ascii_new <= '0'; -- reset new ASCII code indicator state <= new_code; -- proceed to new_code state else -- no new PS2 code received yet state <= ready; -- remain in ready state end if; -- new_code state: determine what to do with the new PS2 code when new_code => if(ps2_code = x"F0") then -- code indicates that next command is break break <= '1'; -- set break flag state <= ready; -- return to ready state to await next PS2 code elsif(ps2_code = x"E0") then -- code indicates multi-key command e0_code <= '1'; -- set multi-code command flag state <= ready; -- return to ready state to await next PS2 code else -- code is the last PS2 code in the make/break code ascii(7) <= '1'; -- set internal ascii value to unsupported code (for verification) state <= translate; -- proceed to translate state end if; -- translate state: translate PS2 code to ASCII value when translate => break <= '0'; -- reset break flag e0_code <= '0'; -- reset multi-code command flag -- handle codes for control, shift, and caps lock case ps2_code is when x"58" => -- caps lock code if(break = '0') then -- if make command caps_lock <= NOT caps_lock; -- toggle caps lock end if; when x"14" => -- code for the control keys if(e0_code = '1') then -- code for right control control_r <= NOT break; -- update right control flag else -- code for left control control_l <= NOT break; -- update left control flag end if; when x"12" => -- left shift code shift_l <= NOT break; -- update left shift flag when x"59" => -- right shift code shift_r <= NOT break; -- update right shift flag when others => null; end case; -- translate control codes (these do not depend on shift or caps lock) if(control_l = '1' OR control_r = '1') then case ps2_code is when x"1E" => ascii <= x"00"; -- ^@ NUL when x"1C" => ascii <= x"01"; -- ^A SOH when x"32" => ascii <= x"02"; -- ^B STX when x"21" => ascii <= x"03"; -- ^C ETX when x"23" => ascii <= x"04"; -- ^D EOT when x"24" => ascii <= x"05"; -- ^E ENQ when x"2B" => ascii <= x"06"; -- ^F ACK when x"34" => ascii <= x"07"; -- ^G BEL when x"33" => ascii <= x"08"; -- ^H BS when x"43" => ascii <= x"09"; -- ^I HT when x"3B" => ascii <= x"0A"; -- ^J LF when x"42" => ascii <= x"0B"; -- ^K VT when x"4B" => ascii <= x"0C"; -- ^L FF when x"3A" => ascii <= x"0D"; -- ^M CR when x"31" => ascii <= x"0E"; -- ^N SO when x"44" => ascii <= x"0F"; -- ^O SI when x"4D" => ascii <= x"10"; -- ^P DLE when x"15" => ascii <= x"11"; -- ^Q DC1 when x"2D" => ascii <= x"12"; -- ^R DC2 when x"1B" => ascii <= x"13"; -- ^S DC3 when x"2C" => ascii <= x"14"; -- ^T DC4 when x"3C" => ascii <= x"15"; -- ^U NAK when x"2A" => ascii <= x"16"; -- ^V SYN when x"1D" => ascii <= x"17"; -- ^W ETB when x"22" => ascii <= x"18"; -- ^X CAN when x"35" => ascii <= x"19"; -- ^Y EM when x"1A" => ascii <= x"1A"; -- ^Z SUB when x"54" => ascii <= x"1B"; -- ^[ ESC when x"5D" => ascii <= x"1C"; -- ^\ FS when x"5B" => ascii <= x"1D"; -- ^] GS when x"36" => ascii <= x"1E"; -- ^^ RS when x"4E" => ascii <= x"1F"; -- ^_ US when x"4A" => ascii <= x"7F"; -- ^? DEL when others => null; end case; else -- if control keys are not pressed -- translate characters that do not depend on shift, or caps lock case ps2_code is when x"29" => ascii <= x"20"; -- space when x"66" => ascii <= x"08"; -- backspace (BS control code) when x"0D" => ascii <= x"09"; -- tab (HT control code) when x"5A" => ascii <= x"0D"; -- enter (CR control code) when x"76" => ascii <= x"1B"; -- escape (ESC control code) when x"71" => if(e0_code = '1') then -- ps2 code for delete is a multi-key code ascii <= x"7F"; -- delete end if; when others => null; end case; -- translate letters (these depend on both shift and caps lock) if((shift_r = '0' AND shift_l = '0' AND caps_lock = '0') OR ((shift_r = '1' OR shift_l = '1') AND caps_lock = '1')) then -- letter is lowercase case ps2_code is when x"1C" => ascii <= x"61"; -- a when x"32" => ascii <= x"62"; -- b when x"21" => ascii <= x"63"; -- c when x"23" => ascii <= x"64"; -- d when x"24" => ascii <= x"65"; -- e when x"2B" => ascii <= x"66"; -- f when x"34" => ascii <= x"67"; -- g when x"33" => ascii <= x"68"; -- h when x"43" => ascii <= x"69"; -- i when x"3B" => ascii <= x"6A"; -- j when x"42" => ascii <= x"6B"; -- k when x"4B" => ascii <= x"6C"; -- l when x"3A" => ascii <= x"6D"; -- m when x"31" => ascii <= x"6E"; -- n when x"44" => ascii <= x"6F"; -- o when x"4D" => ascii <= x"70"; -- p when x"15" => ascii <= x"71"; -- q when x"2D" => ascii <= x"72"; -- r when x"1B" => ascii <= x"73"; -- s when x"2C" => ascii <= x"74"; -- t when x"3C" => ascii <= x"75"; -- u when x"2A" => ascii <= x"76"; -- v when x"1D" => ascii <= x"77"; -- w when x"22" => ascii <= x"78"; -- x when x"35" => ascii <= x"79"; -- y when x"1A" => ascii <= x"7A"; -- z when others => null; end case; else -- letter is uppercase case ps2_code is when x"1C" => ascii <= x"41"; -- A when x"32" => ascii <= x"42"; -- B when x"21" => ascii <= x"43"; -- C when x"23" => ascii <= x"44"; -- D when x"24" => ascii <= x"45"; -- E when x"2B" => ascii <= x"46"; -- F when x"34" => ascii <= x"47"; -- G when x"33" => ascii <= x"48"; -- H when x"43" => ascii <= x"49"; -- I when x"3B" => ascii <= x"4A"; -- J when x"42" => ascii <= x"4B"; -- K when x"4B" => ascii <= x"4C"; -- L when x"3A" => ascii <= x"4D"; -- M when x"31" => ascii <= x"4E"; -- N when x"44" => ascii <= x"4F"; -- O when x"4D" => ascii <= x"50"; -- P when x"15" => ascii <= x"51"; -- Q when x"2D" => ascii <= x"52"; -- R when x"1B" => ascii <= x"53"; -- S when x"2C" => ascii <= x"54"; -- T when x"3C" => ascii <= x"55"; -- U when x"2A" => ascii <= x"56"; -- V when x"1D" => ascii <= x"57"; -- W when x"22" => ascii <= x"58"; -- X when x"35" => ascii <= x"59"; -- Y when x"1A" => ascii <= x"5A"; -- Z when others => null; end case; end if; -- translate numbers and symbols (these depend on shift but not caps lock) if(shift_l = '1' OR shift_r = '1') then -- key's secondary character is desired case ps2_code is when x"16" => ascii <= x"21"; -- | when x"52" => ascii <= x"22"; -- " when x"26" => ascii <= x"23"; -- # when x"25" => ascii <= x"24"; -- $ when x"2E" => ascii <= x"25"; -- % when x"3D" => ascii <= x"26"; -- & when x"46" => ascii <= x"28"; -- ( when x"45" => ascii <= x"29"; -- ) when x"3E" => ascii <= x"2A"; -- * when x"55" => ascii <= x"2B"; -- + when x"4C" => ascii <= x"3A"; -- : when x"41" => ascii <= x"3C"; -- < when x"49" => ascii <= x"3E"; -- > when x"4A" => ascii <= x"3F"; -- ? when x"1E" => ascii <= x"40"; -- @ when x"36" => ascii <= x"5E"; -- ^ when x"4E" => ascii <= x"5F"; -- _ when x"54" => ascii <= x"7B"; -- { when x"5D" => ascii <= x"7C"; -- | when x"5B" => ascii <= x"7D"; -- } when x"0E" => ascii <= x"7E"; -- ~ when others => null; end case; else -- key's primary character is desired case ps2_code is when x"45" => ascii <= x"30"; -- 0 when x"16" => ascii <= x"31"; -- 1 when x"1E" => ascii <= x"32"; -- 2 when x"26" => ascii <= x"33"; -- 3 when x"25" => ascii <= x"34"; -- 4 when x"2E" => ascii <= x"35"; -- 5 when x"36" => ascii <= x"36"; -- 6 when x"3D" => ascii <= x"37"; -- 7 when x"3E" => ascii <= x"38"; -- 8 when x"46" => ascii <= x"39"; -- 9 when x"52" => ascii <= x"27"; -- ' when x"41" => ascii <= x"2C"; -- , when x"4E" => ascii <= x"2D"; -- - when x"49" => ascii <= x"2E"; -- . when x"4A" => ascii <= x"2F"; -- / when x"4C" => ascii <= x"3B"; -- ; when x"55" => ascii <= x"3D"; -- = when x"54" => ascii <= x"5B"; -- [ when x"5D" => ascii <= x"5C"; -- \ when x"5B" => ascii <= x"5D"; -- ] when x"0E" => ascii <= x"60"; -- ` when others => null; end case; end if; end if; if(break = '0') then -- the code is a make state <= output; -- proceed to output state else -- code is a break state <= ready; -- return to ready state to await next PS2 code end if; -- output state: verify the code is valid and output the ASCII value when output => if(ascii(7) = '0') then -- the PS2 code has an ASCII output ascii_new <= '1'; -- set flag indicating new ASCII output ascii_code <= ascii(6 downto 0); -- output the ASCII value end if; state <= ready; -- return to ready state to await next PS2 code end case; end if; end process; end; -------------------------------------------------------------------------------- -- -- FileName: ps2_kbd_core.vhd -- Dependencies: debounce.vhd -- Design Software: Quartus II 32-bit Version 12.1 Build 177 SJ Full Version -- -- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY -- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY -- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL -- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF -- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS -- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), -- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. -- -- Version History -- Version 1.0 11/25/2013 Scott Larson -- Initial Public Release -- -- @note This file has been modified from the original one found at -- <https://eewiki.net/pages/viewpage.action?pageId=28279002> -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; entity ps2_kbd_core is generic( clock_frequency: integer := 50000000; -- system clock frequency in hz debounce_counter_size: integer := 8); -- set such that (2^size)/clock_frequency = 5us (size = 8 for 50mhz) port( clk: in std_ulogic; -- system clock ps2_clk: in std_ulogic; -- clock signal from PS/2 keyboard ps2_data: in std_ulogic; -- data signal from PS/2 keyboard ps2_code_new: out std_ulogic; -- flag that new PS/2 code is available on ps2_code bus ps2_code: out std_ulogic_vector(7 downto 0)); -- code received from PS/2 end entity; architecture rtl of ps2_kbd_core is signal sync_ffs: std_ulogic_vector(1 downto 0); -- synchronizer flip-flops for PS/2 signals signal ps2_clk_int: std_ulogic; -- debounced clock signal from PS/2 keyboard attribute buffer_type: string; attribute buffer_type of ps2_clk_int: signal is "BUFG"; signal ps2_data_int: std_ulogic; -- debounced data signal from PS/2 keyboard signal ps2_word: std_ulogic_vector(10 downto 0); -- stores the ps2 data word signal parity_error: std_ulogic; -- validate parity, start, and stop bits signal count_idle: integer range 0 to clock_frequency/18000; --counter to determine PS/2 is idle begin --synchronizer flip-flops process(clk) begin if rising_edge(clk) then -- rising edge of system clock sync_ffs(0) <= ps2_clk; -- synchronize PS/2 clock signal sync_ffs(1) <= ps2_data; -- synchronize PS/2 data signal end if; end process; -- debounce ps2 input signals debounce_ps2_clk: work.kbd_pkg.ps2_debounce generic map(counter_size => debounce_counter_size) port map(clk => clk, button => sync_ffs(0), result => ps2_clk_int); debounce_ps2_data: work.kbd_pkg.ps2_debounce generic map(counter_size => debounce_counter_size) port map(clk => clk, button => sync_ffs(1), result => ps2_data_int); -- input ps2 data process(ps2_clk_int) begin if(ps2_clk_int'event and ps2_clk_int = '0') then -- falling edge of ps2 clock ps2_word <= ps2_data_int & ps2_word(10 downto 1); -- shift in ps2 data bit end if; end process; -- verify that parity, start, and stop bits are all correct parity_error <= not (not ps2_word(0) and ps2_word(10) and (ps2_word(9) xor ps2_word(8) xor ps2_word(7) xor ps2_word(6) xor ps2_word(5) xor ps2_word(4) xor ps2_word(3) xor ps2_word(2) xor ps2_word(1))); -- determine if ps2 port is idle (i.e. last transaction is finished) and output result process(clk) begin if rising_edge(clk) then -- rising edge of system clock if(ps2_clk_int = '0') then -- low ps2 clock, PS/2 is active count_idle <= 0; -- reset idle counter elsif(count_idle /= clock_frequency/18_000) then -- ps2 clock has been high less than a half clock period (<55us) count_idle <= count_idle + 1; -- continue counting end if; if(count_idle = clock_frequency/18_000 and parity_error = '0') then -- idle threshold reached and no errors detected ps2_code_new <= '1'; -- set flag that new PS/2 code is available ps2_code <= ps2_word(8 downto 1); -- output new PS/2 code else -- PS/2 port active or error detected ps2_code_new <= '0'; -- set flag that PS/2 transaction is in progress end if; end if; end process; end; -------------------------------------------------------------------------------- -- -- FileName: (originally) debounce.vhd -- Dependencies: none -- Design Software: Quartus II 32-bit Version 11.1 Build 173 SJ Full Version -- -- HDL CODE IS PROVIDED "AS IS." DIGI-KEY EXPRESSLY DISCLAIMS ANY -- WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT -- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -- PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL DIGI-KEY -- BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL -- DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF -- PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS -- BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), -- ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. -- -- Version History -- Version 1.0 3/26/2012 Scott Larson -- Initial Public Release -- -- @note This file has been modified from the original one found -- on the web from: <https://eewiki.net/pages/viewpage.action?pageId=28279002> -- -------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity ps2_debounce is generic(counter_size: integer := 19); --counter size (19 bits gives 10.5ms with 50mhz clock) port( clk: in std_ulogic; button: in std_ulogic; --input signal to be debounced result: out std_ulogic := '0'); --debounced signal end entity; architecture rtl of ps2_debounce is signal flipflops: std_ulogic_vector(1 downto 0); --input flip flops signal counter_set: std_ulogic; --sync reset to zero signal counter_out: unsigned(counter_size downto 0) := (others => '0'); --counter output begin counter_set <= flipflops(0) xor flipflops(1); --determine when to start/reset counter process(clk) begin if rising_edge(clk) then flipflops(0) <= button; flipflops(1) <= flipflops(0); if(counter_set = '1') then --reset counter because input is changing counter_out <= (others => '0'); elsif(counter_out(counter_size) = '0') then --stable input time is not yet met counter_out <= counter_out + 1; else --stable input time is met result <= flipflops(1); end if; end if; end process; end;
Go to most recent revision | Compare with Previous | Blame | View Log