原创 我写的读PS/2键盘VHDL代码

2009-7-30 15:16 5094 5 5 分类: FPGA/CPLD

程序功能:读取PS/2键盘发送过来的11位数据,取出其中的8位数据位送8个发光二极管显示(低有效),此程序不判断 开始位 , 奇校验位 ,停止位正确与否;只读取与显示;


PS2键盘的时钟比较抖,我原先用系统时钟22.1184M触发触发器,让PS2键盘的时钟过2次D触发器;如果这2个的D触发器的输出是10,就认为是PS2键盘时钟下降沿了;实际验证的时候发现接受到的8位数据位会出错;现在我让PS2键盘的时钟过3次D触发器,如果是110的话认为是PS2键盘的时钟下降沿来临了;然后就开始读取;直到读完11位数据;


下面程序的过3次触发器是个比较不错的过滤PS2时钟的方法,用CPLD/FPGA去接此类设备时,一定经过适当的滤波;CPLD/FPGA对边缘是十分敏感的,奈何PS2键盘的时钟并不完美,所以我们一定要注意适当滤波;我用的PS2键盘的时钟频率在12K左右,波形并不平坦;切记切记滤波;


当插上PS2 键盘时(键盘上电)时,键盘会发出数据AA到主机,这里的主机当然是CPLD/FPGA了!这表示键盘自测试通过;键盘控制器初始化;


前前后后写了3天,光接受就写了7,8个,有状态机的,加计数判断的,IF的,等等。效果多不好,原来滤波没有加,数据错的厉害,后来加了过2次reg,好点,但是还是有几次错误;直到现在的3次reg才效果很好。按了好几次,没有错误,就没有再浪费力气去按了;不停的整机上电断电也正常,这下就没有去试过了;


接着我拔下键盘有插入,重复操作;有几次没有显示AA,原因还不得而知;


大家参考下


还有键盘的3个灯亮不起来,接下来要弄弄这个查查主机到设备的操作;和起始位,检验位,停止位;希望这次过3次reg的键盘时钟是好的!


 


--1 start bit. This is always 0.
--8 data bits, least significant bit first.
--1 parity bit (odd parity).
--1 stop bit. This is always 1.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_unsigned.ALL;
use IEEE.STD_LOGIC_arith.ALL;


entity PS2_Keyboard_01 is                                  --IO description
Port ( sysclk: in std_logic;                               --22.1184M system clock
    ps2clk: in std_logic;                               --PS/2 Keyboard clock
    ps2data: in std_logic;                              --PS/2 Keyboard data
    reset: in std_logic;
    led: out std_logic_vector(7 downto 0)               --PS/2 8bits data
 );
end PS2_Keyboard_01;                                       --end entity
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
architecture behav of PS2_Keyboard_01 is                   -- architecture of PS2_Keyboard_01
signal ps2clk_r : std_logic_vector(2 downto 0);      -- reg ps2clk         
signal ps2clkfall : std_logic;                             -- ps2clk falling flag
signal q : std_logic_vector(11 downto 0);                  -- shift  data
signal ps2serialdata : std_logic_vector(10 downto 0) ;     -- 11 bit ps2 keyboard serial data;
begin
-----------------------------------------------------------------------------------------------
--filter ps2clk  
-----------------------------------------------------------------------------------------------
process(sysclk,reset) 
begin
 if reset='0' then
  ps2clk_r <= "000";
 elsif rising_edge(sysclk) then
     ps2clk_r(2) <= ps2clk_r(1);
  ps2clk_r(1) <= ps2clk_r(0);
  ps2clk_r(0) <= ps2clk;
 end if;
end process;
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
ps2clkfall<='1' when ps2clk_r="110" else '0';
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
process(sysclk) 
begin
 if rising_edge(sysclk) then                        --sysclk ring_edge;
  if reset='0' then q <= (others =>'0');         --clear q;
   elsif ps2clkfall='1' then                  --ps2clk falling_edge;
    if q(0)='0' then                       --q(0)=0 when shift finish or reset reload data;
     q <= ps2data & "01111111111";      --X01111111111,X is psdata's start bit.
    else
     q <= ps2data & q(11 downto 1);
            end if;
        end if;
    end if;
end process;
-----------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------
process(q)
begin
 if q(0) = '0' then
  ps2serialdata <= q(11 downto 1);
  led <= not ps2serialdata(8 downto 1);
 else
  led <="11111111";
 end if;
end process;
end behav;


 


 


 

文章评论0条评论)

登录后参与讨论
我要评论
0
5
关闭 站长推荐上一条 /2 下一条