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

📄 ps2_mouse_interface.v

📁 周立功SOPC 嵌入式系统实验教程书籍配套光盘 PS2鼠标驱动代码
💻 V
📖 第 1 页 / 共 2 页
字号:
    else 
		m2_state <= m2_next_state;
end

//M2转换逻辑
always @(m2_state
         or q
         or falling_edge
         or rising_edge
         or watchdog_timer_done
         or bit_count
         or packet_good
         or ps2_data_in_r
         or sync_clk
         )
begin 
    ps2_clk_out_r <= 1'b1;
    ps2_data_out_r <= 1'b1;
	ps2_clk_dir_r <= 1'b0;
	ps2_data_dir_r <= 1'b0;
    data_ready_r <= 1'b0;
   
    case (m2_state)
  
	    m2_reset :                        //复位后,发送命令到PS2鼠标
	    begin
	        m2_next_state <= m2_hold_clk_l;
	    end

	    m2_wait :     
	    begin
	        if (falling_edge) 
				m2_next_state <= m2_gather;
	        else
				m2_next_state <= m2_wait;
	    end

	    m2_gather :                     //判断数据是否收完
	    begin
	        if (watchdog_timer_done && (bit_count == `TOTAL_BITS))
	            m2_next_state <= m2_verify;
	        else if (watchdog_timer_done && (bit_count < `TOTAL_BITS))
	            m2_next_state <= m2_hold_clk_l;
	        else
				m2_next_state <= m2_gather;
	    end

	    m2_verify :                     //检验数据包是否正确
	    begin
	        if (packet_good) 
				m2_next_state <= m2_use;
	        else 
				m2_next_state <= m2_wait;
	    end

	    m2_use :                        //数据包是否正确
	    begin
	        data_ready_r <= 1'b1;
	        m2_next_state <= m2_wait;
	    end

//复位或出错时进入以下状态,主机向PS2发送复位指令0xFF,PS2鼠标收到
//复位指令时应答0xFA,大约360mS后,鼠标完成自检,自检成功发送0xAA,
//不成功发送0xFC;然后发送ID号0x00.之后进入Stream 模式Stream 模式.
//此时PS2鼠标默认属性为:采样速率100 采样点/秒;分辨率4 个计数值/毫米;
//缩放比例1:1;数据报告被禁止,为简化程序,不修改默认属性。
//最后发送0xF4命令使能数据报告,等PS2鼠标应答0xFA.致此,初使化PS2鼠标完毕.
//为简化程序,发送复位指令部分省略(复位由鼠标上电复位完成),只发送使能数据报告指令。
	   
	    m2_hold_clk_l :           //拉低时钟线400US,准备发送命令
	    begin
			ps2_clk_dir_r <= 1'b1;
	        ps2_clk_out_r <= 1'b0;  
	        if(watchdog_timer_done && ~sync_clk)
				m2_next_state <= m2_data_low_1;
	        else 
				m2_next_state <= m2_hold_clk_l;
	    end

	    m2_data_low_1 :          //发送起始位"0",d[0],d[1]
	    begin
			ps2_data_dir_r <= 1'b1;
	        ps2_data_out_r <= 1'b0; 
	        if (falling_edge && (bit_count == 6'd2))
	            m2_next_state <= m2_data_high_1;
	        else 
				m2_next_state <= m2_data_low_1;
	    end

	    m2_data_high_1 :        //发送位d[2]
	    begin
			ps2_data_dir_r <= 1'b1;
	        if (falling_edge)
	            m2_next_state <= m2_data_low_2;
	        else
			    m2_next_state <= m2_data_high_1;
	      end

	    m2_data_low_2 :
	    begin
			ps2_data_dir_r <= 1'b1;
	        ps2_data_out_r <= 1'b0;  //发送位d[3]
	        if (falling_edge)
	            m2_next_state <= m2_data_high_2;
	        else 
	           m2_next_state <= m2_data_low_2;
	    end

	    m2_data_high_2 :        //发送位d[4],d[5],d[6],d[7]
	    begin
			ps2_data_dir_r <= 1'b1;
	        if (falling_edge && (bit_count == 6'd8))
	            m2_next_state <= m2_data_low_3;
	        else 
				m2_next_state <= m2_data_high_2;
	    end

	    m2_data_low_3 :         //发送奇偶校验位
	    begin
			ps2_data_dir_r <= 1'b1;
	        ps2_data_out_r <= 1'b0; 
	        if(falling_edge)
	            m2_next_state <= m2_data_high_3;
	        else
				m2_next_state <= m2_data_low_3;
	    end

	    m2_data_high_3 :       //停止位"1",应答处理
	    begin
	        if (falling_edge && ps2_data_in_r)
				m2_next_state <= m2_hold_clk_l; //有错误产生,重新复位
	        else if (falling_edge && ~ps2_data_in_r)
	            m2_next_state <= m2_await_response;
	        else 
				m2_next_state <= m2_data_high_3;
	    end
//等待SP2鼠标回应:这里不对回应做处理,如果指令没有被鼠标正确收到,
//鼠标会回应(0xFC)要求重新发送指令,也可能回应(0xFE)表示收到的数
//据出错。如果正确收到会回应(0xFA)。
//注:如果鼠标的回应时间超过400us,bit_count将被复位,这时应收到
//的位数应该是11。但一般鼠标的回应时间较短,所以bit_count没被复,
//这时的位数值应该是22。

	    m2_await_response :
	    begin
	        if (bit_count == 6'd22)
				m2_next_state <= m2_verify;
	        else 
				m2_next_state <= m2_await_response;
	    end

	    default : m2_next_state <= m2_wait;
  endcase
end
//**********************************************************//




//移位计数器
//在PS2时钟的下降沿加计数
always @(posedge clock)
begin
    if(reset == 1'b1)
		bit_count <= 6'd0;             //复位时计数器清零
    else if(falling_edge) 
		bit_count <= bit_count + 6'd1;
    else if(watchdog_timer_done) 
		bit_count <= 6'd0;             //接收完一个数据包后计数器清零
end

//移位寄存器,在时钟的下降沿锁存数据
//功能:接收PS2发送到来的数据
always @(posedge clock)
begin
    if (reset == 1'b1)
    	q <= `TOTAL_BITS'd0;
  else if (falling_edge)
	    q <= {ps2_data_in_r,q[`TOTAL_BITS-1:1]};
end

//看门狗计时器
//PS2无时钟脉冲超过400us,watchdog_timer_done 置位
//功能:发送数据时抑制时钟线标志,接收数据包后状态指示。
always @(posedge clock)
begin
    if(reset || rising_edge || falling_edge) 
		 watchdog_timer_count <= 0;
    else if(~watchdog_timer_done)
    	 watchdog_timer_count <=  watchdog_timer_count + 1;
end
assign watchdog_timer_done = (watchdog_timer_count==WATCHDOG_TIMER_VALUE-1);

//缓冲时间5US计数器
always @(posedge clock)
begin
    if (reset || falling_edge || rising_edge ) 
		timer_5us_count <= 0;
    else 
		timer_5us_count <= timer_5us_count + 1;
end
assign timer_5us_done = (timer_5us_count == TIMER_5US_VALUE-1);


//验证收到的数据包数据是否有效、正确
assign packet_good = (
                         (q[0]  == 1'b0)        //第一字节起始位
                      && (q[10] == 1'b1)        //第一字节停止位
                      && (q[11] == 1'b0)		//第二字节起始位
                      && (q[21] == 1'b1)		//第二字节停止位
                      && (q[22] == 1'b0)		//第三字节起始位
                      && (q[32] == 1'b1)		//第三字节停止位
                      && (q[9]  == ~^q[8:1])    //第一字节奇验证位
                      && (q[20] == ~^q[19:12])  //第二字节奇验证位
                      && (q[31] == ~^q[30:23])  //第三字节奇验证位
                      );


//锁存输出新的数据
always @(posedge clock)
begin
  	if (reset == 1'b1)
  	begin
    	left_button_r <= 1'b0;
    	right_button_r <= 1'b0;
   	 	middle_button_r <= 1'b0;
    	x_increment_r <= 1'b0;
    	y_increment_r <= 1'b0;
    end
    else if (data_ready_r == 1'b1)
    begin
	    left_button_r <= q[1];             //BIT1[0]
        right_button_r <= q[2];            //BIT1[1]
        middle_button_r <= q[3];           //BIT1[2]
        x_increment_r <= {q[5],q[19:12]};  //BIT1[4],BIT2
        y_increment_r <= {q[6],q[30:23]};  //BIT1[5],BIT3
    end
end

endmodule


⌨️ 快捷键说明

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