OpenCores
URL https://opencores.org/ocsvn/layer2/layer2/trunk

Subversion Repositories layer2

[/] [layer2/] [trunk/] [vhdl/] [keyb/] [rtl/] [ps2.vhd] - Rev 2

Compare with Previous | Blame | View Log

--------------------------------------------------------------------------------
-- PS2 Controller                                                             --
--------------------------------------------------------------------------------
-- Copyright (C)2011  Mathias Hörtnagl <mathias.hoertnagl@gmail.comt>         --
--                                                                            --
-- This program is free software: you can redistribute it and/or modify       --
-- it under the terms of the GNU General Public License as published by       --
-- the Free Software Foundation, either version 3 of the License, or          --
-- (at your option) any later version.                                        --
--                                                                            --
-- This program is distributed in the hope that it will be useful,            --
-- but WITHOUT ANY WARRANTY; without even the implied warranty of             --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              --
-- GNU General Public License for more details.                               --
--                                                                            --
-- You should have received a copy of the GNU General Public License          --
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.      --
--------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity ps2 is
   port(
      clk      : in  std_logic;
      rst      : in  std_logic;
      PS2_CLK  : in  std_logic;
      PS2_DATA : in  std_logic;
      char     : out std_logic_vector(7 downto 0);
      rx_done  : out std_logic
   );
end ps2;
 
architecture rtl of ps2 is
 
   type ps2_state_t is (Start, Data, Parity, Stop, Ack);
 
   signal p, pin    : ps2_state_t := Start;
   signal s, sin    : std_logic_vector(7 downto 0);
   signal n, nin    : natural range 0 to 7;
   signal f, fin    : std_logic_vector(7 downto 0);
   signal t, tin    : std_logic;
   signal fall_edge : std_logic;
begin
 
   -----------------------------------------------------------------------------
   -- Input Signal Debounce                                                   --
   -----------------------------------------------------------------------------
   -- the frequency of the PS2 clock signal is about 20 to 30 KHz. To avoid   --
   -- undesired glitches, wait 8 cycles for a stable signal.                  --
   -----------------------------------------------------------------------------
   fin <= PS2_CLK & f(7 downto 1);
 
   tin <= '1' when f = x"FF" else
          '0' when f = x"00" else
          t;
 
     filter : process(clk)
   begin
      if rising_edge(clk) then
         f <= fin;
         t <= tin;
      end if;
   end process;
 
   fall_edge <= t and (not tin);
 
   -----------------------------------------------------------------------------
   -- PS2 Read                                                               --
   -----------------------------------------------------------------------------
   fsm : process(p, s, n, fall_edge, PS2_DATA)
   begin
 
      rx_done <= '0';
 
      pin <= p;
      sin <= s;
      nin <= n;
 
      case p is
 
         -- Wait for first falling edge. The first bit is a start bit with
         -- value '0'. We do not check that.
         when Start =>
            if fall_edge = '1' then
               nin <= 0;
               pin <= Data;
            end if;
 
         -- On the next 8 falling edges we shuffle data into the shift register.
         -- The keyboard sends the LSB first.
         when Data =>
            if fall_edge = '1' then
               sin <= PS2_DATA & s(7 downto 1);
               if n = 7 then
                  pin <= Parity;
               else
                  nin <= n + 1;
               end if;
            end if;
 
         -- Fetch odd parity bit. No parity check here.
         when Parity =>
            if fall_edge = '1' then
               sin <= PS2_DATA & s(7 downto 1);    -- A mystery.
               pin <= Stop;
            end if;
 
         -- Fetch stop bit. Always '1'.
         when Stop =>
            if fall_edge = '1' then
               pin <= Ack;
            end if;
 
         -- One cycle tick to indicate a complete reception.
         when Ack =>
            rx_done <= '1';
            pin     <= Start;
 
      end case;
   end process;
 
     reg : process(clk)
   begin
      if rising_edge(clk) then
         p <= pin;
         s <= sin;
         n <= nin;
         f <= fin;
 
         if rst = '1' then p <= Start; end if;
      end if;
   end process;
 
   char <= s;
end rtl;
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.