花了几个小时才写了这么一段代码------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;