最近在用FPGA写一个简单的类8042的键盘控制器,把阶段性的东西写一下,和大家分享下。目前控制器实现了接收键盘通断码,可向键盘发送命令功能,同志们或许有更好的做法,也可以指出来。
控制面板->系统->硬件选项卡中设备管理器->查看->依类型排序资源->输入输出,我们可以看到系统的IO分布,其中分配给8042键盘控制器的有0x0060和0x0064两个端口。
1.8042内部构成
8042内部由5个单字节寄存器构成:输入缓冲寄存器、输出缓冲寄存器、状态寄存器、命令寄存器和控制寄存器。
输入缓冲寄存器缓冲的是键盘数据,只读。
输出缓冲寄存器缓冲的是发给8042自身的命令或发送给键盘编码器8048的命令,只写。
状态寄存器记录的是8042控制器的工作状态,只读。
命令寄存器中可存放发送给8042的单条命令,只写。
控制寄存器存放的是各控制位。它不能由端口直接寻址,需要通过命令寄存器的中转。它也可以解释是存储在8042RAM中的第一条命令。
由于输入缓冲寄存器只读,输出缓冲缓冲寄存器只写,因此它们可以共享同一个端口号0x0060,同样状态寄存器和命令寄存器可以共享同一个端口号0x0064。
键盘接口PS/2的两根传输线PS2C和PS2D为集电极开路,通过连接一个上拉电阻将集电极电平拉高。
2.8042的通信时序
(1) 键盘到8042的时序
由上图:一次完整的发送由11位组成:起始位、1字节数据、校验位、停止位。时钟总是由键盘产生。当键盘需要发送数据时,首先检查时钟线是否为高电平,若为高,则可以开始一次发送。发送以拉低数据线为起始,8042在时钟下降沿将数据位读入。数据需在时钟下降沿之前5us建立,并在下降沿之后保持5us。停止位总是高电平。注意的是:键盘每发送一位之前都要对时钟线进行采样以确保时钟线为高电平,因为8042可通过拉低时钟线来抑制键盘通信。
(2)8042到键盘的时序
8042可在任意时候发送数据,当然输出缓冲中必须有发送给键盘的命令。8042拉低时钟线至少100us对键盘进行通信抑制,接着拉低数据线,再5us之后释放时钟线。键盘在时钟上升沿将数据位读入。同样数据需在时钟上升沿之前5us建立,并在上升沿之后保持5us。停止位总是高电平。注意的是:在键盘采样到校验位后的下一个时钟上升沿,8042需释放数据线,以接收键盘的应答。
3.接口设计
generic( PS2D_WIDTH : integer;
CONT_US5 : integer );
port( Clk : in std_logic;
Rst :in std_logic;
PS2C : inout std_logic;
PS2D : inout std_logic;
Cs : in std_logic;
Addr :in std_logic_vector((PS2D_WIDTH - 1) downto 0);
Cmd : in std_logic_vector((PS2D_WIDTH - 1) downto 0);
Wr_en : in std_logic;
Rd_en : in std_logic;
Data : out std_logic_vector((PS2D_WIDTH - 1) downto 0;
IRQ : out std_logic );
4.寄存器设计
(1)状态寄存器Stat_Reg
alias Stat_PERR is std_logic of Stat_Reg(7); -- 1:前一个字节奇校验错误 0:无校验错误
alias Stat_UUSD6 is std_logic of Stat_Reg(6); -- 保留
alias Stat_UUSD5 is std_logic of Stat_Reg(5); -- 保留
alias Stat_INH is std_logic of Stat_Reg(4); -- 1:键盘通信不被抑制 0:键盘通信被抑制
alias Stat_A2 is std_logi of Stat_Reg(3); -- 1:前一个通过0x0060端口写进的是发送给键盘的命令 0:前一个向0x0064端口写0x60命令后写进0x0060端口的是发送给8042自身的命令
alias Stat_UUSD2 is std_logic of Stat_Reg(2); -- 保留
alias Stat_IBF is std_logic of Stat_Reg(1); -- 1:输入缓冲满 0:空
alias Stat_OBF is std_logic of Stat_Reg(0); -- 1:输出缓冲满 0:空
(2)控制寄存器Ctrl_Reg
alias Ctrl_UUSD7 is std_logic of Ctrl_Reg(7); -- 保留
alias Ctrl_UUSD6 is std_logic of Ctrl_Reg(6); -- 保留
alias Ctrl_UUSD5 is std_logic of Ctrl_Reg(5); -- 保留
alias Ctrl_UUSD4 is std_logic of Ctrl_Reg(4); -- 1:键盘使能 0:通过拉低时钟线抑制键盘通信
alias Ctrl_UUSD3 is std_logic of Ctrl_Reg3); -- 保留
alias Ctrl_UUSD2 is std_logic of Ctrl_Reg(2); -- 保留
alias Ctrl_UUSD1 is std_logic of Ctrl_Reg(1); -- 保留
alias Ctrl_INT is std_logic of Ctrl_Reg(0); -- 0 :中断屏蔽 1:输入缓冲满时允许产生中断
5.状态机设计
6.测试
Xilinx_PicoBlaze是一款8位RISC处理器,麻雀虽小,功能却很强大。纽约时代广场LED显示屏的控制就用了上千个此控制器。有兴趣的朋友可以上Xilinx官网了解。