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

📄 ps2.vhd

📁 Mars-XC2S50-S-Core-V2.0开发板核心板的说明和设计文档
💻 VHD
字号:

-- The FPGA-evb-S2 Xilinx Spartan-II evaluation board example
--
-- This example reads scan codes from a PS/2 keyboard and
-- displays them on LEDs.
--
-- (C)2001 Jan Pech, j.pech@sh.cvut.cz

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity ps2 is
  port (resetn:  in  std_logic;                     -- active low reset
        clock:   in  std_logic;                     -- system clock
        ps2_clk: in  std_logic;                     -- PS/2 clock line
        ps2_dta: in  std_logic;                     -- PS/2 data line
        leds:    out std_logic_vector(7 downto 0)); -- LED outputs
end ps2;


architecture behavioral of ps2 is

  type state_type is (IDLE, START, DATA, PARITY);   -- FSM states

  signal ps2_dv: std_logic;                         -- PS/2 data valid
  signal prv_ps2_clk, act_ps2_clk: std_logic;       -- auxiliary signals
  signal recdata: std_logic_vector(7 downto 0);     -- read data
  signal shift: std_logic;                          -- enable for shift reg.
  signal n_shift: std_logic;                        -- auxiliary signal
  signal latch: std_logic;                          -- latch read data
  signal n_latch: std_logic;                        -- auxiliary signal
  signal err: std_logic;                            -- parity or stop error
  signal n_err: std_logic;                          -- auxiliary signal
  signal parset: std_logic;                         -- preset for parity check
  signal n_parset: std_logic;                       -- auxiliary signal
  signal c_state, n_state: state_type;              -- current & next states
  signal cntval: std_logic_vector(2 downto 0);      -- counter of data bits
  signal zero: std_logic;                           -- counter is zero
  signal parbit: std_logic;                         -- odd parity of data

begin

  -- Provides a one-shot pulse after every falling edge of PS/2 clock
  PS_CLK_SYNC: process(clock, resetn)
  begin
    if (resetn = '0') then
      prv_ps2_clk <= '1';
      act_ps2_clk <= '1';
    elsif (clock'event and clock = '1') then
      act_ps2_clk <= ps2_clk;
      prv_ps2_clk <= act_ps2_clk;
    end if;
  end process;

  ps2_dv <= (not act_ps2_clk) and prv_ps2_clk;

  -- Serial input, parallel output shift register
  SIPO: process(clock, resetn)
  begin
    if (resetn = '0') then
      recdata <= (others => '0');
    elsif (clock'event and clock = '1') then
      if (shift = '1') then
        recdata <= ps2_dta & recdata(7 downto 1);
      end if;
    end if;
  end process;

  -- Counter of data bits
  COUNT8: process(resetn, clock)
  begin
    if (resetn = '0') then
      cntval <= (others => '0');
    elsif (clock'event and clock = '1') then
      if (shift = '1') then
        cntval <= cntval + 1;
      end if;
    end if;
  end process;

  zero <= not (cntval(0) or cntval(1) or cntval(2));

  -- Parity check of received data
  PARITY_CHECK: process(clock, parset)
  begin
    if (parset = '1') then
      parbit <= '1';
    elsif (clock'event and clock = '1') then
      if (shift = '1' and ps2_dta = '1') then
        parbit <= not parbit;
      end if;
    end if;
  end process;

  -- Synchronous process of control state machine
  FSM_SYNC: process(clock, resetn)
  begin
    if (resetn = '0') then
      c_state <= IDLE;
      shift <= '0';
      latch <= '0';
      err <= '0';
      parset <= '1';
    elsif (clock'event and clock = '1') then
      c_state <= n_state;
      shift <= n_shift;
      latch <= n_latch;
      err <= n_err;
      parset <= n_parset;
    end if;
  end process;

  -- Combinatorial process of control state machine
  FSM_COMB: process(c_state, ps2_dv, ps2_dta, zero)
  begin
    -- default values
    n_shift <= '0';
    n_latch <= '0';
    n_err <= '0';
    n_parset <= '0';
    case c_state is
      -- wait to receive data
      when IDLE =>   if ((ps2_dv and (not ps2_dta)) = '1') then
                       n_state <= START;
                       n_parset <= '1';
                     else
                       n_state <= IDLE;
                     end if;
      -- receive first data bit
      when START =>  if (ps2_dv = '0') then
                       n_state <= START;
                     else
                       n_state <= DATA;
                       n_shift <= '1';
                     end if;
      -- receive remaining data bits and parity
      when DATA =>   if (ps2_dv = '0') then
                       n_state <= DATA;
                     elsif (zero = '0') then
                       n_state <= DATA;
                       n_shift <= '1';
                     else
                       n_state <= PARITY;
                       if (parbit /= ps2_dta) then
                         n_err <= '1';
                       end if;
                     end if;
      -- receive stop bit
      when PARITY => if (ps2_dv = '0') then
                       n_state <= PARITY;
                     else
                       n_state <= IDLE;
                       n_latch <= '1';
                       n_err <= not ps2_dta;
                     end if;
    end case;
  end process;

  -- Output latch
  LED_OUTPUTS: process(resetn, clock)
  begin
    if (resetn = '0') then
      leds <= (others => '1');
    elsif (clock'event and clock = '1') then
      if (err = '1') then
        leds <= (others => '1');
      elsif (latch = '1') then
        leds <= not recdata;
      end if;
    end if;
  end process;

end behavioral;

⌨️ 快捷键说明

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