lgyc 发表于 2011-5-29 12:11:01

有关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;       
                               
请谁能帮我改下,非常感谢啊

lgyc 发表于 2011-5-29 12:26:13

编译只有两个warning。问题应该是我对ps2协议的理解不清楚导致的。
一共五个进程,分别用来表示
1。分频
2。检测外部鼠标连上电源,检测发送字节使能(我来操控的),检测主机发送信号命令;
3。检测主机的抑制发送情况;
4。发送或者接受一个字节;
5。接受主机的命令后返回FA,并判断并发送发送三个字节的数据包;
开机启动信号发送和接受AA,00;(我把采样率等都省略了,主机发送的信息除了EB时会返回FA和三个数据包,其他的都只返回FA,目的是简化过程,只要显示器上有显示光标的移动)
页: [1]
查看完整版本: 有关ps2鼠标的问题,谁能帮解决啊,非常感谢~