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

📄 mouse.vhd

📁 用vhdl实现ps2鼠标的源程序
💻 VHD
字号:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity mouse is
    Port (
	       clk : in std_logic;
          reset : in std_logic;
          ps2_clk : inout std_logic;
          ps2_data : inout std_logic;
          left_button : out std_logic;
          right_button : out std_logic;
			 xsign : out std_logic;
			 ysign : out std_logic;
          x_increment : out std_logic_vector(8 downto 0);
          y_increment : out std_logic_vector(8 downto 0);
          --data_ready : out std_logic;-- rx_read_o
          --read : in std_logic; -- rx_read_ack_i
          error_no_ack : out std_logic
			 );
end mouse;

architecture Behavioral of mouse is

constant TOTAL_BITS : integer :=33;  -- Number of bits in one full packet
-- The timer value can be up to (2^bits) inclusive.
constant WATCHDOG : integer :=320;-- Number of sys_clks for 400usec.160
constant DEBOUNCE_TIMER : integer := 4;   -- Number of sys_clks for debounce:2

type m1statetype is ( m1_clk_h, m1_falling_edge, m1_falling_wait, 
         m1_clk_l, m1_rising_edge, m1_rising_wait);
type m2statetype is (m2_reset, m2_wait, m2_gather, m2_verify, m2_use, m2_hold_clk_l,
         m2_data_low_1, m2_data_high_1, m2_data_low_2, m2_data_high_2, m2_data_low_3,
		   m2_data_high_3, m2_error_no_ack, m2_await_response);
signal m1_state,m1_next_state : m1statetype;
signal m2_state,m2_next_state : m2statetype;
--signal m3_state,m3_next_state : std_logic;

signal watchdog_timer_done,debounce_timer_done : std_logic;--signals of commanding out to mouse 
--signal data_out : std_logic;--command out

--signal n_ps2clkint,n_data_out,n_data,n_ackflag: std_logic;
 
--signal left,right,xsign,ysign,xover,yover : std_logic;------------recieve data state
--signal mouse : std_logic_vector(7 downto 0); 
--signal xnum,ynum : std_logic_vector(8 downto 0);---------------------present state
--signal n_left,n_right,n_xsign,n_ysign,n_xover,n_yover : std_logic;--and next state
--signal n_mouse : std_logic_vector(7 downto 0); 
--signal n_xnum,n_ynum : std_logic_vector(8 downto 0);----------------
--signal latch , n_latch : std_logic; --when a packet is all received then high latch;
signal q : std_logic_vector(TOTAL_BITS-1 downto 0);--bit sequence
signal bitcount : std_logic_vector(5 downto 0);--bit count

signal watchdog_timer_count : std_logic_vector(8 downto 0); --wait time
signal debounce_timer_count : std_logic_vector(1 downto 0); --debounce time
signal ps2_clk_hi_z : std_logic;     -- Without keyboard, high Z equals 1 due to pullups.
signal ps2_data_hi_z : std_logic;    -- Without keyboard, high Z equals 1 due to pullups.

signal clean_clk : std_logic;       -- Debounced output from m1, follows ps2_clk.
signal rise,n_rise: std_logic;      -- Output from m1 state machine.
signal fall,n_fall : std_logic;     -- Output from m1 state machine.
signal output_strobe : std_logic;    -- Latches data data into the output registers
signal packet_good : std_logic;--check the whether the data is valid 


begin
 
ps2_clk <= '0' when ps2_clk_hi_z='0' else 'Z';
ps2_data <= '0' when ps2_data_hi_z='0' else 'Z';

---------------m1 state State register
m1statechg: process (reset, clk)
begin 
  if (reset='0') then
     rise <= '0';
	  fall <= '0';
     m1_state <= m1_clk_h;
	  --clean_clk <= '0';
  elsif (clk'event and clk='1') then 
     m1_state <= m1_next_state;
	  rise <= n_rise;
	  fall <= n_fall;
  end if;
end process;

-- State transition logic
m1statetr: process (m1_state, ps2_clk, debounce_timer_done)
begin 
  -- Output signals default to this value, unless changed in a state condition.
  clean_clk <= '0';
  n_rise <= '0';
  N_fall <= '0';

  case m1_state is
    when m1_clk_h =>
      clean_clk <= '1';
      if (ps2_clk='0') then
		   m1_next_state <= m1_falling_edge;
      else 
		   m1_next_state <= m1_clk_h;
      end if;
    when m1_falling_edge =>
      n_fall <= '1';
      m1_next_state <= m1_falling_wait;--m1_next_state <= m1_falling_wait;
    when m1_falling_wait =>
      if (debounce_timer_done='1') then
		   m1_next_state <= m1_clk_l;
      else 
		   m1_next_state <= m1_falling_wait;
      end if;
    when m1_clk_l =>
      if (ps2_clk='1') then
		   m1_next_state <= m1_rising_edge;
      else 
		  m1_next_state <= m1_clk_l;
      end if;
    when m1_rising_edge =>
      n_rise <= '1';
      m1_next_state <= m1_rising_wait;--m1_next_state <= m1_rising_wait;
    when m1_rising_wait =>
      clean_clk <= '1';
      if (debounce_timer_done='1') then
		   m1_next_state <= m1_clk_h;
      else m1_next_state <= m1_rising_wait;
      end if;
    when others => m1_next_state <= m1_clk_h;
  end case;
end process;----------------------------end m1 atate


------------------m2 State 
m2statech: process (reset, clk)
begin 
  if (reset='0') then
     m2_state <= m2_reset;
  elsif (clk'event and clk='1') then 
     m2_state <= m2_next_state;
  end if;
end process;

--m2 State transition logic
m2statetr: process (m2_state, fall,rise,watchdog_timer_done,bitcount,ps2_data,packet_good)
begin
  -- Output signals default to this value, unless changed in a state condition.
  ps2_clk_hi_z <= '1';
  ps2_data_hi_z <= '1';
  error_no_ack <= '0';
  output_strobe <= '0';
  --data_out <= '0';

  case m2_state is
    when m2_reset =>    -- After reset, sends command to mouse.
      m2_next_state <= m2_hold_clk_l;
    when m2_wait =>
      if (fall='1') then
		   m2_next_state <= m2_gather;
      else 
		   m2_next_state <= m2_wait;
      end if;
    when m2_gather =>
      if (watchdog_timer_done='1') then  -- and (bitcount=TOTAL_BITS)
          m2_next_state <= m2_verify;
      else 
		    m2_next_state <= m2_gather;
      end if;
    when m2_verify =>
      --if (bitcount < TOTAL_BITS) then  --replace " packet_good='1' "
		   --m2_next_state <= m2_wait;
      --else 
		   m2_next_state <= m2_use;
      --end if;
    when m2_use =>
      output_strobe <= '1';
      m2_next_state <= m2_wait;

    -- The following sequence of 9 states is designed to transmit the
    -- "enable streaming mode" command to the mouse, and then await the
    -- response from the mouse.  
   when m2_hold_clk_l =>
      ps2_clk_hi_z <= '0';   -- This starts the watchdog timer!
      if (watchdog_timer_done='1') then  -- cut "and (clean_clk='0')"
		   m2_next_state <= m2_data_low_1;
      else 
		   m2_next_state <= m2_hold_clk_l;
      end if;
    when m2_data_low_1 =>
      ps2_data_hi_z <= '0';  -- Forms start bit, d[0] and d[1]
		--data_out <= '0';
      if (fall='1' and (bitcount = 2)) then
          m2_next_state <= m2_data_high_1;
      else 
		   m2_next_state <= m2_data_low_1;
      end if;
    when m2_data_high_1 =>
      ps2_data_hi_z <= '1';  -- Forms d[2]
		--data_out <= '1';
      if (fall='1' and (bitcount = 3)) then
          m2_next_state <= m2_data_low_2;
      else 
		   m2_next_state <= m2_data_high_1;
      end if;
    when m2_data_low_2 =>
      ps2_data_hi_z <= '0';  -- Forms d[3]
		--data_out <= '0';
      if (fall='1' and (bitcount = 4)) then
          m2_next_state <= m2_data_high_2;
      else 
		    m2_next_state <= m2_data_low_2;
      end if;
    when m2_data_high_2 =>
      ps2_data_hi_z <= '1';  -- Forms d[4],d[5],d[6],d[7]
		--data_out <= '1';
      if (fall='1' and (bitcount = 8)) then
          m2_next_state <= m2_data_low_3;
      else 
		    m2_next_state <= m2_data_high_2;
      end if;
    when m2_data_low_3 =>
      ps2_data_hi_z <= '0';  -- Forms parity bit
		--data_out <= '0';
      if (fall='1') then
		   m2_next_state <= m2_data_high_3;
      else 
		   m2_next_state <= m2_data_low_3;
      end if;
    when m2_data_high_3 =>
        ps2_data_hi_z <= '1';  -- Allow mouse to pull low (ack pulse)
      if (fall='1' and (ps2_data='1')) then
		    m2_next_state <= m2_error_no_ack;
      elsif (fall='1' and (ps2_data='0')) then
          m2_next_state <= m2_await_response;
      else 
		    m2_next_state <= m2_data_high_3;
      end if;
    when m2_error_no_ack =>
      error_no_ack <= '1';
      m2_next_state <= m2_error_no_ack;
    
    -- In order to "cleanly" exit the setting of the mouse into "streaming"
    -- data mode, the state machine should wait for a long enough time to
    -- ensure the FA response is done being sent by the mouse. 
    when m2_await_response =>
      --if (bitcount = 22) then
		    m2_next_state <= m2_verify;
      --else 
		   -- m2_next_state <= m2_await_response;
      --end if;
    when others => m2_next_state <= m2_wait;
  end case;
end process;-----------------------------end m2 state

-------------m3 State register
--datach: process (reset, clk)
--begin 
--  if (reset='1') then
 --     m3_state <= '0';
 -- else 
 --    m3_state <= m3_next_state;
 -- end if;
--end process;

--State transition logic
--datastattr: process (m3_state,output_strobe,read)
--begin 
--  case m3_state is
 --   when '0' =>
 --     data_ready <= '0';
 --     if (output_strobe='1') then
--		    m3_next_state <= '1';
 --     else 
	--	    m3_next_state <= '0';
 --     end if;
  --  when '1' =>
  --    data_ready <= '1';
  --    if (read='1') then
	--	    m3_next_state <= '0';
  --    else 
--		    m3_next_state <= '1';
 --     end if;
 --   when others => m3_next_state <= '0';
--  end case;
--end process;--------------end m3 state fsm

--This is the bit counter
bitcoun: process (reset, clk)
begin
  if (reset='0') then
     bitcount <= (others=>'0');  -- normal reset
  elsif (clk'event and clk='1') then
    if (fall='1') then
      bitcount <= bitcount + 1;
    elsif (watchdog_timer_done='1') then
       bitcount <= (others=>'0');  -- rx watchdog timer reset
	 end if;
  end if;
end process;

-- This is the shift data register
dataseq: process (reset, clk)
begin
  if (reset='0') then
     q <= (others=>'0');
  elsif (clk'event and clk='1') then
    if (fall='1') then
       q <= ps2_data & q(TOTAL_BITS-1 downto 1);
	 end if;
  end if;
end process;

-- This is the watchdog timer counter
-- The watchdog timer is always "enabled" to operate.
watchcount: process (reset,rise,fall, clk)
begin
  if ((reset='0') or (rise='1') or (fall='1')) then
    watchdog_timer_count <= (others=>'0');
  elsif (clk'event and clk='1') then
    if (watchdog_timer_done='0') then
      watchdog_timer_count <= watchdog_timer_count + 1;
	 end if;
  end if;
end process;

watchdog_timer_done <= '1' when (watchdog_timer_count=WATCHDOG-1) else '0';

--This is the debounce timer counter
deboucount: process (reset,rise,fall, clk)
begin
  if ((reset='0') or (rise='1') or (fall='1')) then
    debounce_timer_count <= (others=>'0');
  elsif (clk'event and clk='1') then
    if (debounce_timer_done='0') then
      debounce_timer_count <= debounce_timer_count + 1;
	 end if;
  end if;
end process;

debounce_timer_done <= '1' when(debounce_timer_count=DEBOUNCE_TIMER-1) else '0';

--This is the logic to verify that a received data packet is "valid" or good.
packet_good <= '1';

-- Output the special scan code flags, the scan code and the ascii
outdata: process (reset, clk)
begin
  if (reset='0') then
    left_button <= '0';
    right_button <= '0';
	 xsign <= '0';
	 ysign <= '0';
    x_increment <= (others=>'0');
    y_increment <= (others=>'0');
  elsif (clk'event and clk='1') then
    if (output_strobe='1') then
      left_button <= q(1);
      right_button <= q(2);
		xsign <= q(5);
		ysign <= q(6);
      x_increment <= q(7) & q(8 downto 1);--q(19 downto 12)
      y_increment <= q(8) & q(30 downto 23);
	 end if;
  end if;						
end process;

end Behavioral;

⌨️ 快捷键说明

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