📄 ps2mouse.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 + -