?? 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 + -