⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps2_mouse_interface.v

📁 周立功SOPC 嵌入式系统实验教程书籍配套光盘 PS2鼠标驱动代码
💻 V
📖 第 1 页 / 共 2 页
字号:
//*****************************************************************************//
//                               PS2鼠标接口程序                               //
//                                系统时钟48MHz                                //
//                            最后修改日期2006.03.27                           //
//*****************************************************************************//
//PS2鼠标数据包格式:
//使用标准的PS2接口,无扩展Intellimouse,数据包格式由3个字节,
//PS2数据格式
//         D7     D6      D5      D4      D3   D2     D1    D0
//字节0  Y溢出  X溢出  Y符号位  X符号位   1  中间键  右键  左键
//字节1                    X方向计数值
//字节2                    Y方向计数值
//------------------------------------------------------------------------------
//传输数据时帧格式:
//收低位在前,高位在后
//   bit0    bit1  bit2  bit3  bit4  bit5  bit6  bit7  bit8   bit9      bit10
//  开始(0)   D0    D1    D2    D3    D4    D5    D6    D7   奇校验位   停止(1) 
//------------------------------------------------------------------------------
//数据输出格式:
//PS2鼠标有按键按下,相应接口(left_button/right_button/middle_button)输出1,没按
//键按下输出0
//X、Y方向有位移,相应接口(x_increment/y_increment)输出位移增量,输出数据格式为9
//位二进制补码。  
//------------------------------------------------------------------------------
//说明:
//本程序只支持标准PS2鼠标(即只能使用左、右、中三键和X、Y方向位移数据)
//对于带滚轮及有第四、五按键的鼠标,其多扩展的功能键无效。
//本程序的复位信号不能对鼠标进行复位。
//鼠标正常工作于Stream模式,该模式的进入是利用鼠标上电自动复位而进入的。
//为简化程序,本程序没有写鼠标复位程序。如出现异常状况,需重新插拔鼠标。
//data_ready输出脉冲信号(脉冲宽度为系统时钟周期)时,说明有新的数据更新。
//******************************************************************************//

`define TOTAL_BITS   33  // 一个数据包有33位数据

module ps2_mouse_interface (
	clock,  
	reset,            //复位,高电平有效  
	ps2_clk_in,  
	ps2_data_in,  
	ps2_clk_out,  
	ps2_data_out,
	ps2_clk_dir,
	ps2_data_dir,   
	left_button,  
	right_button,  
	middle_button,  
	x_increment,  
	y_increment,  
	data_ready);     //数据已经正确收到  
  

//I/O 口定义
input clock;
input reset;
input ps2_clk_in;           //PS/2时钟线,输入口
input ps2_data_in;          //PS/2数据线,输入口
output ps2_clk_out;  		//PS/2时钟线,输出口
output ps2_data_out; 		//PS/2数据线,输出口
output ps2_clk_dir;         //PS/2时钟方向控制,高电平为输出,低电平为输入
output ps2_data_dir;        //PS/2数据方向控制,高电平为输出,低电平为输入
output left_button;
output right_button;
output middle_button;
output [8:0] x_increment;
output [8:0] y_increment;
output data_ready;

//输出寄存器
reg left_button_r;
reg right_button_r;
reg middle_button_r;
reg [8:0] x_increment_r;
reg [8:0] y_increment_r;
reg data_ready_r;
reg ps2_clk_out_r;
reg ps2_data_out_r;
reg ps2_clk_dir_r;
reg ps2_data_dir_r;

//内部节点
wire watchdog_timer_done; //看门狗状态指示,SP2无时钟脉冲超过400US置位
wire timer_5us_done;      //用于延时缓冲,防止毛刺干扰
wire packet_good;         //数据包正确收到-状态指示

//内部寄存器
reg [`TOTAL_BITS-1:0] q;  //移位寄存器
reg [2:0] m1_state;
reg [2:0] m1_next_state;
reg [3:0] m2_state;
reg [3:0] m2_next_state;
reg [5:0] bit_count;                //发送接收数据是的位计数器
reg [WATCHDOG_TIMER_BITS-1:0] watchdog_timer_count; //看门狗计时器,400us
reg [TIMER_5US_BITS-1:0]   timer_5us_count;         //5uS计时器
reg ps2_clk_in_r;     //同步后的PS2时钟
reg ps2_data_in_r;    //同步后的PS2数据
reg sync_clk;         //滤波后的PS2时钟--------由状态机M1产生输出
reg rising_edge;      //PS2时钟上升沿标志------由状态机M1产生输出
reg falling_edge;     //PS2时钟下降沿标志------由状态机M1产生输出



//计时器参数
//当系统时钟改变时要得新计算参数值
//参数值要求:
//WATCHDOG_TIMER_VALUE: 大于100uS 小于15mS
//TIMER_5US_VALUE:   1uS到20uS都行
parameter WATCHDOG_TIMER_VALUE = 19200; //看门狗计时器,400uS
parameter WATCHDOG_TIMER_BITS  = 15;    //400uS计时器所需计数器位数
parameter TIMER_5US_VALUE   = 240;      // 5uS计数值
parameter TIMER_5US_BITS    = 8;        // 5uS计时器所需计数器位数


//状态机M1参数表
parameter m1_clk_h        = 3'b000,
  		  m1_falling_edge = 3'b001,
          m1_falling_wait = 3'b011,
          m1_clk_l        = 3'b010,
          m1_rising_edge  = 3'b110,
          m1_rising_wait  = 3'b100;

//状态机M2参数表
parameter m2_reset			 = 4'b0000,
		  m2_wait 			 = 4'b0001,
		  m2_gather 		 = 4'b0011,
		  m2_verify 		 = 4'b0010,
		  m2_use 			 = 4'b0110,
		  m2_hold_clk_l 	 = 4'b0111,
		  m2_data_low_1 	 = 4'b0101,
		  m2_data_high_1	 = 4'b0100,
		  m2_data_low_2 	 = 4'b1100,
		  m2_data_high_2	 = 4'b1101,
		  m2_data_low_3 	 = 4'b1001,
		  m2_data_high_3	 = 4'b1011,
		  m2_await_response  = 4'b1010;
//**********************************************************//


//**********************************************************//
//模块代码开始
//**********************************************************//
assign ps2_clk_out = ps2_clk_out_r;      //PS2时钟线输出
assign ps2_data_out = ps2_data_out_r;    //PS2数据线输出
assign ps2_clk_dir = ps2_clk_dir_r;      //PS2时钟方向
assign ps2_data_dir = ps2_data_dir_r;    //PS2数据方向
assign left_button = left_button_r;
assign right_button = right_button_r;
assign middle_button = middle_button_r;
assign y_increment = y_increment_r;
assign x_increment = x_increment_r;
assign data_ready = data_ready_r;


//**********************************************************//
//同步PS2时钟、数据信号
always @(posedge clock)
begin
	ps2_clk_in_r <= ps2_clk_in;
	ps2_data_in_r <= ps2_data_in;
end 
//**********************************************************//

//**********************************************************//
//状态机M1
//功能:同步PS2时钟,在PS2的时钟边沿产生边沿标志
//**********************************************************//
//M1状态转向
always @(posedge clock)
begin 
	if (reset == 1'b1) 
		m1_state <= m1_clk_h;
    else 
		m1_state <= m1_next_state;
end

//M1转换逻辑
always @(m1_state or ps2_clk_in_r or timer_5us_done or watchdog_timer_done)
begin 
    sync_clk <= 1'b0;
    rising_edge <= 1'b0;
    falling_edge <= 1'b0;
	case (m1_state)
	    m1_clk_h :                   //时钟高电平
	    begin
	        sync_clk <= 1'b1;
	        if(~ps2_clk_in_r)
				m1_next_state <= m1_falling_edge;
	        else 
				m1_next_state <= m1_clk_h;
	    end
	      
	    m1_falling_edge :           //时钟下降沿
	    begin
	        falling_edge <= 1'b1;
	        m1_next_state <= m1_falling_wait;
	    end
	      
	    m1_falling_wait :           //等待5US延时防止毛刺干扰
	    begin
	        if(timer_5us_done) 
				m1_next_state <= m1_clk_l;
	        else 
				m1_next_state <= m1_falling_wait;
	    end

	    m1_clk_l :                 //时钟低电平
	    begin
	        if(ps2_clk_in_r)
				m1_next_state <= m1_rising_edge;
	        else 
				m1_next_state <= m1_clk_l;
	    end

	    m1_rising_edge :           //时钟上升沿
	    begin
	        rising_edge <= 1'b1;
	        m1_next_state <= m1_rising_wait;
	    end

	    m1_rising_wait :           //等待5US延时防止毛刺干扰
	    begin
	        sync_clk <= 1'b1;
	        if(timer_5us_done) 
				m1_next_state <= m1_clk_h;
	        else 
				m1_next_state <= m1_rising_wait;
	    end
	
	    default : m1_next_state <= m1_clk_h;
	endcase
end
//**********************************************************//


//**********************************************************//
//状态机M2
//功能:初始化PS2鼠标,接收PS2鼠标数据包
//**********************************************************//
//M2状态转向
always @(posedge clock)
begin 
    if(reset == 1'b1) 
		m2_state <= m2_reset;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -