git-svn-id: http://moon:8086/svn/vhdl/trunk@1422 cc03376c-175c-47c8-b038-4cd826a8556b
241 lines
5.6 KiB
VHDL
241 lines
5.6 KiB
VHDL
--------------------------------------------------------------------------------
|
|
-- Company:
|
|
-- Engineer:
|
|
--
|
|
-- Create Date: 18:05:41 10/22/05
|
|
-- Design Name:
|
|
-- Module Name: ps2_core - Behavioral
|
|
-- Project Name:
|
|
-- Target Device:
|
|
-- Tool versions:
|
|
-- Description:
|
|
--
|
|
-- Dependencies:
|
|
--
|
|
-- Revision:
|
|
-- Revision 0.01 - File Created
|
|
-- Additional Comments:
|
|
--
|
|
--------------------------------------------------------------------------------
|
|
library IEEE;
|
|
use IEEE.STD_LOGIC_1164.ALL;
|
|
use IEEE.STD_LOGIC_ARITH.ALL;
|
|
use IEEE.STD_LOGIC_UNSIGNED.ALL;
|
|
|
|
---- Uncomment the following library declaration if instantiating
|
|
---- any Xilinx primitives in this code.
|
|
--library UNISIM;
|
|
--use UNISIM.VComponents.all;
|
|
|
|
entity ps2_core is
|
|
Generic (f_sys_clk : real := 100.0);
|
|
Port ( rst : in std_logic;
|
|
clk : in std_logic;
|
|
ce : in std_logic;
|
|
d_in : in std_logic_vector(7 downto 0);
|
|
d_out : out std_logic_vector(7 downto 0);
|
|
rdy_in : out std_logic;
|
|
rdy_out : out std_logic;
|
|
write_en : in std_logic;
|
|
read_en : in std_logic;
|
|
ps2_clk : in std_logic;
|
|
ps2_data : in std_logic);
|
|
|
|
end ps2_core;
|
|
|
|
architecture Behavioral of ps2_core is
|
|
|
|
COMPONENT prescaler
|
|
GENERIC (divide : integer);
|
|
PORT(
|
|
rst : IN std_logic;
|
|
clk : IN std_logic;
|
|
ce : IN std_logic;
|
|
rdy : OUT std_logic
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT timeout_counter
|
|
GENERIC (N : integer);
|
|
PORT(
|
|
rst : IN std_logic;
|
|
clk : IN std_logic;
|
|
ce : IN std_logic;
|
|
load : IN integer range 0 to N-1;
|
|
load_en : IN std_logic;
|
|
rdy : OUT std_logic
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT sipo
|
|
GENERIC (N : integer);
|
|
PORT(
|
|
rst : IN std_logic;
|
|
clk : IN std_logic;
|
|
ce : IN std_logic;
|
|
d_in : IN std_logic;
|
|
d_out : OUT std_logic_vector(7 downto 0)
|
|
);
|
|
END COMPONENT;
|
|
|
|
COMPONENT oneshot
|
|
GENERIC (mode : integer);
|
|
PORT(
|
|
rst : IN std_logic;
|
|
clk : IN std_logic;
|
|
input : IN std_logic;
|
|
output : OUT std_logic
|
|
);
|
|
END COMPONENT;
|
|
|
|
-- Types
|
|
type read_state_t is (read_start_st, read_data_st, read_parity_st, read_stop_st);
|
|
|
|
-- Constant
|
|
constant prescaler_us : integer := integer(f_sys_clk);
|
|
constant timeout_us : integer := 1000;
|
|
|
|
-- Signals
|
|
signal en_us : std_logic;
|
|
signal timeout_load_en : std_logic;
|
|
signal timeout_flag : std_logic;
|
|
signal read_cs : read_state_t;
|
|
signal read_ns : read_state_t;
|
|
signal data_cnt_en : std_logic;
|
|
signal data_cnt : integer range 0 to 7;
|
|
signal sipo_en : std_logic;
|
|
signal data_rdy : std_logic;
|
|
signal out_reg_ce : std_logic;
|
|
signal sipo_reg : std_logic_vector(7 downto 0);
|
|
|
|
begin
|
|
|
|
Inst_prescaler: prescaler
|
|
GENERIC MAP (
|
|
divide => prescaler_us)
|
|
PORT MAP(
|
|
rst => rst,
|
|
clk => clk,
|
|
ce => ce,
|
|
rdy => en_us
|
|
);
|
|
|
|
Inst_timeout_counter: timeout_counter
|
|
GENERIC MAP (
|
|
N => timeout_us)
|
|
PORT MAP(
|
|
rst => rst,
|
|
clk => clk,
|
|
ce => en_us,
|
|
load => timeout_us - 1,
|
|
load_en => timeout_load_en,
|
|
rdy => timeout_flag
|
|
);
|
|
|
|
Inst_sipo: sipo
|
|
GENERIC MAP (
|
|
N => 8)
|
|
PORT MAP(
|
|
rst => rst,
|
|
clk => ps2_clk,
|
|
ce => sipo_en,
|
|
d_in => ps2_data,
|
|
d_out => sipo_reg
|
|
);
|
|
|
|
Inst_oneshot: oneshot
|
|
GENERIC MAP (
|
|
mode => 1)
|
|
PORT MAP(
|
|
rst => rst,
|
|
clk => clk,
|
|
input => data_rdy,
|
|
output => out_reg_ce
|
|
);
|
|
|
|
-------------------------------------------
|
|
out_reg: process(rst, clk, out_reg_ce, read_en)
|
|
begin
|
|
if rst = '1' then
|
|
d_out <= (others => '0');
|
|
rdy_out <= '0';
|
|
elsif rising_edge(clk) then
|
|
if out_reg_ce = '1' then
|
|
d_out <= sipo_reg;
|
|
rdy_out <= '1';
|
|
elsif read_en = '1' then
|
|
rdy_out <= '0';
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
read_state_clk: process(rst, ps2_clk)
|
|
begin
|
|
if rst = '1' then
|
|
read_cs <= read_start_st;
|
|
else
|
|
if falling_edge(ps2_clk) then
|
|
read_cs <= read_ns;
|
|
if (data_cnt_en = '1') then
|
|
if (data_cnt /= 0) then
|
|
data_cnt <= data_cnt - 1;
|
|
end if;
|
|
else
|
|
data_cnt <= 7;
|
|
end if;
|
|
end if;
|
|
end if;
|
|
end process;
|
|
|
|
read_state_output: process(read_cs)
|
|
begin
|
|
|
|
timeout_load_en <= '0';
|
|
data_cnt_en <= '0';
|
|
rdy_in <= '0';
|
|
sipo_en <= '0';
|
|
data_rdy <= '0';
|
|
-- rdy_out <= '0';
|
|
case (read_cs) is
|
|
when read_start_st =>
|
|
data_rdy <= '1';
|
|
timeout_load_en <= '1';
|
|
-- rdy_out <= '1';
|
|
when read_data_st =>
|
|
sipo_en <= '1';
|
|
data_cnt_en <= '1';
|
|
when others => null;
|
|
end case;
|
|
end process;
|
|
|
|
read_state_decode: process (read_cs, timeout_flag, data_cnt, ps2_data)
|
|
begin
|
|
--declare default state for next_state to avoid latches
|
|
read_ns <= read_cs; --default is to stay in current state
|
|
--insert statements to decode next_state
|
|
--below is a simple example
|
|
case (read_cs) is
|
|
when read_start_st =>
|
|
if ps2_data = '0' then
|
|
read_ns <= read_data_st;
|
|
end if;
|
|
when read_data_st =>
|
|
if timeout_flag = '1' then
|
|
read_ns <= read_start_st;
|
|
elsif data_cnt = 0 then
|
|
read_ns <= read_parity_st;
|
|
end if;
|
|
when read_parity_st =>
|
|
read_ns <= read_stop_st;
|
|
if timeout_flag = '1' then
|
|
read_ns <= read_start_st;
|
|
end if;
|
|
when read_stop_st =>
|
|
read_ns <= read_start_st;
|
|
when others =>
|
|
read_ns <= read_start_st;
|
|
end case;
|
|
end process;
|
|
|
|
end Behavioral;
|