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

📄 ps2mouse.v

📁 PS2鼠标实验Verilog HDL代码
💻 V
字号:
/************************************************************
**模块名称:ps2mouse
**模块功能:用于初始化鼠标并接受鼠标的数据发往串口发送模块
*************************************************************/
module ps2mouse(clk,reset,ps2mouse_clk,ps2mouse_data,data_uart,wr_uart);
  input clk;
  input reset;
  inout ps2mouse_clk;
  inout ps2mouse_data;
  output wr_uart;
  output[7:0] data_uart;
  reg wr_uart;
  reg [7:0] data_uart;
  reg r1_BIT_CLK,r2_BIT_CLK;
  reg data_enio;                                        //鼠标数据输出允许,低有效
  reg ps2clk_enio;                                      //鼠标时钟输出允许,低有效
  reg regdata;                                          //发往鼠标数据
  reg regps2clk;                                        //鼠标时钟
  reg [12:0] state;                                     //状态机定义
  reg en_mouse;                                          
  reg [16:0] count;
  reg [3:0]count1;
  reg [7:0] data;
  wire nDone;
  wire ps2mouse_data,ps2mouse_clk;
  //assign  ps2mouse_data=(data_enio)?regdata:1'bz;
  //assign  ps2mouse_clk=(ps2clk_enio)?regps2clk:1'bz;
  /*synplify 8.8 存在一个BUG,会在Fusion器件的三态缓冲器使能端错误地加上一个非门。如果不是用synplify 8.8版本综合的的请用以上两条语句 */
  assign  ps2mouse_data=(data_enio)?1'bz:regdata;     
  assign  ps2mouse_clk=(ps2clk_enio)?1'bz:regps2clk;

  parameter data_dirout=14'b0000_0000_0000_1,
            low_ps2clk=14'b0000_0000_0001_0,
            low_data=14'b0000_0000_0010_0,
            release_ps2clk=14'b0000_0000_0100_0,
            ps2clk_dirin=14'b0000_0000_1000_0,
            senddata=14'b0000_0001_0000_0,
            wait_ps2clkhigh=14'b0000_0010_0000_0,
            wait_ps2clklow=14'b0000_0100_0000_0,
            waitclkhigh=14'b0000_1000_0000_0,
            waitclklow=14'b0001_0000_0000_0,
            data_dirin=14'b0010_0000_0000_0,
            checkdata=14'b0100_0000_0000_0,
            dataclk_dirin=14'b1000_0000_0000_0;
/***********************检测鼠标时钟信号下降沿*******************/
always@(posedge clk)
   begin
	   r1_BIT_CLK <= ps2mouse_clk;
   	   r2_BIT_CLK <= r1_BIT_CLK;
   end
assign	nDone = ~r1_BIT_CLK&r2_BIT_CLK;                //如果nDone值为1就是下降沿

/************主机发往通讯设备(鼠标)************************/
always@(posedge clk)
 begin
  if(reset)
   begin
    count<=17'd0;
    en_mouse<=1'b1;
    regdata<=1'b1;
    regps2clk<=1'b1;
    state<=data_dirout;
    data_enio<=1'b1;
    ps2clk_enio<=1'b1;
   end
  else
   begin
   if(en_mouse)
     begin
       case(state)
         data_dirout:                                  //数据和时钟管脚作为输出
           begin
             data_enio  <= 1'b1;
             ps2clk_enio<= 1'b1;
             regdata    <= 1'b1;
             regps2clk  <= 1'b1;
             state      <= low_ps2clk;
           end
         low_ps2clk:                                  //拉低时钟线150us
           begin
             count<=count+1'b1;
             regps2clk<=1'b0;
             if(count==13'd7200)
               begin
                count<=13'd0;
                state<=low_data;
               end
             else  state<=low_ps2clk;
           end
          low_data:                                    //拉低数据线10uS
            begin
              regdata<=1'b0;
              count<=count+1'b1;
              if(count==9'd480)
                begin
                  count<=9'd0;
                  state<=release_ps2clk;
                end
             else  state<=low_data;
            end
           release_ps2clk:                             //释放时钟线
             begin
               regps2clk<=1'b1;
               state    <=ps2clk_dirin;
             end
           ps2clk_dirin:                               //时钟管脚作为输入
             begin
               ps2clk_enio<=1'b0;
               state<=wait_ps2clklow;
             end
           wait_ps2clklow:                             //等待时钟线为低
             begin
               if(ps2mouse_clk)  state<=wait_ps2clklow;
               else   state<=senddata;
             end
           senddata:                                   //发送鼠标8位使能数据0xf4,加上1位奇偶校验位0和停止位1,下降沿改变数据,高电平保持数据,低位发送在前
             begin
                count   <=count+1'b1;
                regdata <=((10'b1011_1101_00>>count)&10'b0000_0000_01);
                if(count==4'd9) 
                  begin
                   state<=waitclkhigh;
                   count<=4'd0;
                  end
                 else  state<=wait_ps2clkhigh;
              end
            wait_ps2clkhigh:                          //等待时钟线拉高
              begin
                 if(ps2mouse_clk)  state<=wait_ps2clklow;
                 else   state<=wait_ps2clkhigh;
              end
            waitclkhigh:                              //发送完数据位,等待时钟线拉高         
              begin
                 if(ps2mouse_clk)  state<=data_dirin;
                 else      state<=waitclkhigh;  
              end
            data_dirin:                               //数据脚设为输入
              begin
                data_enio<=1'b0;
                state<=waitclklow;  
              end
            waitclklow:                               //等待时钟线拉低
              begin
                 if(ps2mouse_clk)  state<=waitclklow;
                 else        state<=checkdata;
              end   
            checkdata:                                //检查应答信号,正确则将数据和时钟都设为输出,错误继续再发
              begin
                 if(ps2mouse_data)  state<=low_ps2clk;
                 else  
                  begin
                    data_enio<=1'b1;
                    ps2clk_enio<=1'b1;
                    regdata<=1'b1;
                    regps2clk<=1'b1;
                    state<=dataclk_dirin;
                  end  
              end 
            dataclk_dirin:                            //数据和时钟都置为输入
              begin
                data_enio<=1'b0;
                ps2clk_enio<=1'b0;
                en_mouse<=1'b0;
              end   
            default: begin 
                     end
           endcase
         end//if(en_mouse)对应
     end//(reset)
end

/**************************鼠标发往主机的数据**************************/
always@(posedge clk)
     begin
        if(!en_mouse)
          begin
            if(nDone)                                  //如果为下降沿,表示有数据来,低位在前
              begin
                if((count1>1)&&(count1<10))
                   begin
                    data=data>>1;
                    if(ps2mouse_data)  data=data|8'b1000_0000;
                   end 
                if(count1>4'd10)                       //接收完10位,则串口发送使能
                   begin
                     wr_uart  =1'b1;
                     data_uart=data;
                     count1   =4'b0;
                     data     =8'b0;
                   end  
                count1=count1+1'b1; 
              end//(ndone)
            else   wr_uart=1'b0;
         end
       else 
           begin
             data  =8'b0;
             count1=4'b0;
           end
   end

endmodule 

⌨️ 快捷键说明

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