有关ps2鼠标的问题,谁能帮解决啊,非常感谢~
我想用做一个模拟的ps2鼠标控制芯片。给控制芯片输入X,Y位移量,控制芯片的串行(data,clk)输出连到电脑的ps2接口上,希望计算机的显示器上鼠标的位置能按照我给出的X,Y位移量移动。我按照在这个网站上找到的一份ps2协议,用VHDL写了一份代码。结果是连到电脑ps2接口后,主机箱开始一直滴滴的响,鼠标的位置一点改变也没有。
代码如下
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use IEEE.STD_LOGIC_ARITH.ALL;
entity mouse3 is
port
(distance_x,distance_y : in std_logic_vector(9 downto 4);--补码表示
rb,mb,lb :in std_logic; --right button,middle,left button
clk_mouse :in std_logic; --mouse clk,1us,1Mhz
clk_ps2,data:inout std_logic;
power:in std_logic; --应该就用ps/2的那个就行
send:in std_logic); --在变化的上升沿 发送三个字结
end mouse3;
architecture behaves of mouse3 is
signal reg1:std_logic:='0'; --power
signal reg2:std_logic:='0'; --send
signal trig1:bit;
signal reg_trig1:bit;
signal trig2:bit;
signal reg_trig2:bit;
signal trig3:bit;
signal reg_trig3:bit;
signal clk:bit; --与分频有关
signal reg_fromto:std_logic_vector( 9 downto 0);
signal reg_send: std_logic_vector(10 downto 0);
signal reg_recieve:std_logic_vector(7 downto 0);
signal recieve_bit_over:std_logic;
signal send_bit_over:std_logic;
signal response_bit_over:std_logic;
type fromto_type is(state_fromto_a,state_fromto_b,state_fromto_c,state_fromto_d);
signal reg3:fromto_type:=state_fromto_a; -- fromto
signal fromto_now:fromto_type:=state_fromto_a;
signal fromto_next:fromto_type;
type substate_type is(idle,sendbit_a,sendbit_b,sendbit_c,sendbit_d,sendbit_begin,sendbit_end,
recievebit_a,recievebit_b,recievebit_c,recievebit_begin,recievebit_end,
responsebit_a,responsebit_b,responsebit_c,responsebit_d);
signal substate_now:substate_type:=idle;
signal substate_next:substate_type;
type state_type is(power_begin,power_a1,power_a2,power_b1,power_b2,power_c1,power_c2,
power_d1,power_d2,power_stream,stream_a1,stream_a2,
stream_a3,stream_b1,stream_b2,stream_b3,stream_c1,stream_c2,
stream_d1,stream_d2,stream_d3,stream_d4);
signal state_now:state_type:=power_stream;
signal state_next:state_type;
begin
process(clk_mouse) --这就算个分频吧
begin
if clk_mouse'event and clk_mouse='0' then clk<=not clk;
end if;
end process;
process(clk_mouse)
begin
if clk_mouse'event and clk_mouse='1' then
if clk='1' then
if (reg1/=power and power='1') then
trig1<=not trig1;
elsif reg2/=send and send='1'then
trig2<=not trig2;
elsif reg3/=fromto_now and fromto_now=state_fromto_d then
trig3<=not trig3;
end if;
elsif clk='0' then
reg1<=power;
reg2<=send;
reg3<=fromto_now;
end if;
end if;
end process;
process(clk_mouse) --这个过程应该在15ms以外,不做检查,由计算机保证
variable n:integer range 0 to 10;
begin
if clk_mouse'event and clk_mouse='1' then
if clk='1' then
n:=n+1;reg_fromto(n)<=clk_ps2;
fromto_now<=fromto_next;
case fromto_now is
when state_fromto_a=>
if reg_fromto="0000000000" then fromto_next<=state_fromto_b;
end if;
when state_fromto_b=>
if data='0' then fromto_next<=state_fromto_c;
elsif clk_ps2='1' then fromto_next<=state_fromto_a;
end if;
when state_fromto_c=>
if data='1' and clk_ps2='1' then fromto_next<=state_fromto_d;
end if;
when state_fromto_d=>
if recieve_bit_over='1' then fromto_next<=state_fromto_a; --state_fromto_a表示又空闲了;
end if;
end case;
end if;
end if;
end process;
--上个进程还可以用wait语句做触发,但是不如这个好(毛刺)
process(clk_mouse)
variable n:integer;
variable i:integer;
begin --计数器80下的 --什么时候倒入到这个进程的敏感表
if clk_mouse'event and clk_mouse='1'then
if clk='0' then
if state_next/=state_now then
if state_next=power_a2 or state_next=power_b2 or state_next=power_d2 or state_next=stream_a2
or state_next=stream_b2 or state_next=stream_c2 or state_next=stream_d3 then substate_next<=sendbit_begin;n:=0; --这里还要添加状态
elsif state_next=power_c2 or state_next=stream_d1 then substate_next<=recievebit_begin;n:=0;
end if;
end if;
elsif clk='1' then
substate_now<=substate_next;
if n=40 then n:=0;
else n:=n+1;
end if;
case substate_now is
when sendbit_begin=>
if n=10 then i:=0;send_bit_over<='0';
elsif n=20 then substate_next<=sendbit_a;
end if;
when sendbit_a=>
if n=2 then data<=reg_send(i);substate_next<= sendbit_b;
end if;
when sendbit_b =>
if n=20 then clk_ps2<='0';substate_next<=sendbit_c;
end if;
when sendbit_c=>
if n=40 then clk_ps2<='Z';substate_next<=sendbit_d;
end if;
when sendbit_d =>
if n=10 then i:=i+1;
elsif n=20 then
if i<=9 then substate_next<=sendbit_a;
elsif i=10 then substate_next<=sendbit_end;
end if;
end if;
when sendbit_end=>
if n=30 then substate_next<=idle;send_bit_over<='1';
end if;
when recievebit_begin=>
if n=2 then i:=0;substate_next<=recievebit_a;recieve_bit_over<='0';
end if;
when recievebit_a=>
if n=20 then clk_ps2<='0';substate_next<=recievebit_b;
end if;
when recievebit_b=>
if n=40 then clk_ps2<='Z';
substate_next<=recievebit_c;
end if;
when recievebit_c=>
if n=20 then
if i<=7 then reg_recieve(i)<=data;
end if;
if i<=8 then substate_next<=recievebit_a;
elsif i=9 then substate_next<=responsebit_a;
end if;
i:=i+1;
end if;
when responsebit_a=>
if n=15 then
data<='0';
substate_next<=responsebit_b;
end if;
when responsebit_b=>
if n=5 then
clk_ps2<='0';
substate_next<=responsebit_c;
end if;
when responsebit_c=>
if n=40 then
clk_ps2<='Z';
substate_next<=responsebit_d;
end if;
when responsebit_d=>
if n=5 then
data<='Z';
substate_next<=recievebit_end;
end if;
when recievebit_end=>
if n=2 then --这里本来少个延迟45ms的条件
substate_next<=idle;recieve_bit_over<='1';
end if;
when others=>
null;
end case;
end if;
end if;
end process;
process(clk_mouse) --进程敏感表
variable m : integer range 0 to 500001;
variable parity : std_logic;
variable j : integer;
begin
--if power'event and power='1' then state_next<=power_begin;
--end if;
--if send'event and send='1' then state_next<=stream_a1;
--end if;
--if fromto_now'event and fromto_now=state_fromto_d then state_next<=stream_d1; --不知道状态变量改变能否用event
--end if;
if clk_mouse'event and clk_mouse='1'then --这就是说substate的变化一定能在半个时钟周期内变化
if clk='0' then
if state_now/=state_next then m:=0;
end if;
if reg_trig1/=trig1 then state_next<=power_begin;
elsif reg_trig2/=trig2 then state_next<=stream_a1;
elsif reg_trig3/=trig3 then state_next<=stream_d1;
end if;
elsifclk='1' then --开机为sleep?
reg_trig1<=trig1;
reg_trig2<=trig2;
reg_trig3<=trig3;
m:=m+1;
state_now<=state_next;
case state_now is
when power_begin=>
if m=500000 then state_next<=power_a1;j:=0;
end if;
when power_a1=>
if (j=0 and m=2) or (j>0 and send_bit_over='1' and reg_fromto/="0000000000") then
reg_send(8 downto 1)<="10101010";
reg_send(0)<='0';
parity:='0';
for k in 1 to 8 loop --这个计算是要用时间的吗?可能计算parity应该另外求
parity:= parity xor reg_send(k);
end loop;
reg_send(9)<=parity;
reg_send(10)<='1';
state_next<=power_a2;
end if;
when power_a2=>
if m=2 then state_next<=power_b1;
end if;
when power_b1=>
if send_bit_over='1' and reg_fromto/="0000000000" then --虽然没有用send_bit_over触发,但是应该也能用
reg_send(8 downto 1)<="00000000";
reg_send(0)<='0';
parity:='0';
for k in 1 to 8 loop
parity:=parity xor reg_send(k);
end loop;
reg_send(9)<=parity;
reg_send(10)<='1';
state_next<=power_b2;
end if;
when power_b2=>
if m=2 then state_next<=power_c1;
end if;
when power_c1=>
if send_bit_over='1' and reg_fromto/="0000000000" then state_next<=power_c2;
end if;
when power_c2=>
if m>45000 then
if recieve_bit_over='1' then state_next<=power_d1;
end if;
end if;
when power_d1=>
if m=2 then
reg_send(8 downto 1)<="11111010";
reg_send(0)<='0';
for k in 1 to 8 loop
parity:=parity xor reg_send(k);
end loop;
reg_send(9)<=parity;
reg_send(10)<='1';
j:=j+1;
state_next<=power_d2;
end if;
whenpower_d2=>
if m=2 then
if j<=2 then state_next<=power_a1;
elsif j>2 then state_next<=power_stream;
end if;
end if;
when stream_a1=>
if m=2 then
reg_send(0)<='0';
reg_send(8)<=distance_y(9);
reg_send(7)<=distance_x(9);
reg_send(6)<=distance_y(8);
reg_send(5)<=distance_x(8);
reg_send(4)<='1';
reg_send(3)<=mb;
reg_send(2)<=rb;
reg_send(1)<=lb;
parity:='0';
for k in 1 to 8 loop
parity:=parity xor reg_send(k);
end loop;
reg_send(9)<=parity;
reg_send(10)<='1';
state_next<=stream_a2;
end if;
when stream_a2=>
if m=2 then state_next<=stream_a3;
end if;
when stream_a3=>
if m=60000 and reg_fromto/="0000000000" then state_next<=stream_b1;
end if;
when stream_b1=>
if m=2 then
reg_send(0)<='0';
reg_send(8 downto 5)<=distance_x(7 downto 4);
reg_send(4 downto 1)<="1111";
parity:='0';
for k in 1 to 8 loop
parity:=parity xor reg_send(k);
end loop;
reg_send(9)<=parity;
reg_send(10)<='1';
state_next<=stream_b2;
end if;
when stream_b2=>
if m=2 then
state_next<=stream_b3;
end if;
when stream_b3=>
if m=60000 and reg_fromto/="0000000000"then
state_next<=stream_c1;
end if;
when stream_c1=>
if m=2 then
reg_send(0)<='0';
reg_send(8 downto 5)<=distance_y(7 downto 4);
reg_send(4 downto 1)<="1111";
parity:='0';
for k in 1 to 8 loop
parity:=parity xor reg_send(k);
end loop;
reg_send(9)<=parity;
reg_send(10)<='1';
state_next<=stream_c2;
end if;
when stream_c2=>
if m=2 then
state_next<=power_stream;
end if;
when stream_d1=>
if m=2 then
state_next<=stream_d2;
end if;
when stream_d2=>
if m>45000 then
if recieve_bit_over='1' then
reg_send(0)<='0';
reg_send(8 downto 1)<="11111010";
parity:='0';
for k in 1 to 8 loop
parity:=parity xor reg_send(k);
end loop;
reg_send(9)<=parity;
reg_send(10)<='1';
state_next<=stream_d3;
end if;
end if;
when stream_d3=>
if m=2 then
state_next<=stream_d4;
end if;
when stream_d4=>
if send_bit_over='1' then
if reg_recieve="11101011" then state_next<=stream_a1;
else state_next<=power_stream;
end if;
end if;
when others=>
null;
end case;
end if;
end if;
end process;
end behaves;
请谁能帮我改下,非常感谢啊 编译只有两个warning。问题应该是我对ps2协议的理解不清楚导致的。
一共五个进程,分别用来表示
1。分频
2。检测外部鼠标连上电源,检测发送字节使能(我来操控的),检测主机发送信号命令;
3。检测主机的抑制发送情况;
4。发送或者接受一个字节;
5。接受主机的命令后返回FA,并判断并发送发送三个字节的数据包;
开机启动信号发送和接受AA,00;(我把采样率等都省略了,主机发送的信息除了EB时会返回FA和三个数据包,其他的都只返回FA,目的是简化过程,只要显示器上有显示光标的移动)
页:
[1]