|
程序功能:读取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 deion
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;