很好的PS2键盘接受程序,相应快而准 //测试开发板 spartan-3e

来源:互联网 发布:淘宝卖人参可以吗 编辑:程序博客网 时间:2024/05/15 06:40

花了几个小时才写了这么一段代码------PS2键盘接收程序

原来试了很多方法,如状态机等等。。。。。但是都没有这个好,在此共享,共同交流。。。。。


//很好的PS2键盘接受程序,相应快而准

//测试开发板  spartan-3e
//
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;


entity PS2 is
    Port ( clk50m : in  STD_LOGIC;  --50M晶振
           kbclk : in  STD_LOGIC;  --keyboard clk
           kbdata : in  STD_LOGIC;  --keyboard data
           led : out  STD_LOGIC_VECTOR (7 downto 0));  ---7个LED显示 按下0键 显示"00000000" 按下1键 显示 "00000001"  按下2键显示"00000010" 等等  按下9键显示 "00001001"

end PS2;


architecture Behavioral of PS2 is
signal clk2us:std_logic:='0';
signal kbclkin:std_logic;---keyboard clk after filter  对kbclk滤波后的信号
signal kbdatain:std_logic;----keyboard data after filter 对kbdata滤波后的信号
signal regclk,regdata:std_logic_vector(5 downto 0); --used as shift 用于对kbclk和kbdata滤波
signal data:std_logic_vector(10 downto 0);----接受的键值
signal mark:std_logic_vector(7 downto 0);---用来判断是否为起始位
signal n:integer range 0 to 10:=0; ---用来标记已接受了多少位键码
begin
process(clk50m)  --divider分频产生1us时钟 
variable cnt1:integer range 0 to 49:=0;
begin
if (rising_edge(clk50m)) then 
if cnt1=49 then clk2us<=not clk2us;cnt1:=0; else cnt1:=cnt1+1;end if;
end if;
end process;


process(clk2us) ---filter  对kbclk   kbdata 进行滤波
begin
if rising_edge(clk2us) then 
regclk(5 downto 1)<=regclk(4 downto 0);
regclk(0)<=kbclk;
if regclk="111111" then kbclkin<='1';elsif regclk="000000" then kbclkin<='0';end if;
regdata(5 downto 1)<=regdata(4 downto 0);
regdata(0)<=kbdata;
if regdata="111111" then kbdatain<='1';elsif regdata="000000" then kbdatain<='0';end if;
end if;
end process;


process(clk2us) ---每隔20US对 kbclk进行采样一次,并将其压入堆栈
variable cnt:integer range 0 to 10;
begin
if rising_edge(clk2us) then 
cnt:=cnt+1;
if(cnt=10) then cnt:=0;mark<=mark(6 downto 0) & kbclkin;end if;
end if;
end process;


process(kbclkin)
begin
if (kbclkin'event and kbclkin='0') then
if mark(7 downto 1)="1111111" or n/=0 then  //如果前面的时钟都是高电平(即意味着这个是起始位)或者 现在正在接受键码
data(n)<=kbdatain; 
n<=n+1;
if(n=9) then n<=0;end if;//接受完了一个键码后,将n置为0
end if;
end if;
end process;


process(data,n)   
begin
if n=9  then  //接受完一个完整的键码,提取键值并显示  按下0键 显示"00000000" 按下1键 显示 "00000001"  按下2键显示"00000010" 等等  按下9键显示 "00001001"
case data(8 downto 1) is
when X"45" =>led<=X"00";
when X"16" =>led<=X"01";
when X"1E" =>led<=X"02";
when X"26" =>led<=X"03";
when X"25" =>led<=X"04";
when X"2E" =>led<=X"05";
when X"36" =>led<=X"06";
when X"3D" =>led<=X"07";
when X"3E" =>led<=X"08";
when X"46" =>led<=X"09";
when others =>null;
end case;
end if;
end process;
end Behavioral;
原创粉丝点击