Initial version
Committed on the Free edition of March Hare Software CVSNT Server. Upgrade to CVS Suite for more features and support: http://march-hare.com/cvsnt/ git-svn-id: http://moon:8086/svn/vhdl/trunk@621 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
## NOTE: Do not edit this file.
|
||||||
|
##
|
||||||
|
|
||||||
|
vlib work
|
||||||
|
vcom -explicit -93 "../src/ps2_core.vhd"
|
||||||
|
vcom -explicit -93 "../src/tb_ps2_core.vhd"
|
||||||
|
|
||||||
|
vsim -t 1ps -lib work tb_ps2_core
|
||||||
|
do {tb_ps2_core.wdo}
|
||||||
|
view wave
|
||||||
|
view structure
|
||||||
|
view signals
|
||||||
|
run 5 ms
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
onerror {resume}
|
||||||
|
quietly WaveActivateNextPane {} 0
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/rst
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/clk
|
||||||
|
add wave -noupdate -format Literal /tb_ps2_core/din
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/tx_empty
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/din_vld
|
||||||
|
add wave -noupdate -format Literal /tb_ps2_core/dout
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/rx_present
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/read_en
|
||||||
|
add wave -noupdate -format Literal /tb_ps2_core/dout_reg
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/ps2_data_rx
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/ps2_clk_rx
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/ps2_clk_tx
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/ps2_data_tx
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/ps2_clk_i
|
||||||
|
add wave -noupdate -format Logic /tb_ps2_core/tx_trig
|
||||||
|
TreeUpdate [SetDefaultTree]
|
||||||
|
WaveRestoreCursors {{Cursor 1} {4999629518 ps} 0}
|
||||||
|
configure wave -namecolwidth 150
|
||||||
|
configure wave -valuecolwidth 100
|
||||||
|
configure wave -justifyvalue left
|
||||||
|
configure wave -signalnamewidth 1
|
||||||
|
configure wave -snapdistance 10
|
||||||
|
configure wave -datasetprefix 0
|
||||||
|
configure wave -rowmargin 4
|
||||||
|
configure wave -childrowmargin 2
|
||||||
|
configure wave -gridoffset 0
|
||||||
|
configure wave -gridperiod 100
|
||||||
|
configure wave -griddelta 40
|
||||||
|
configure wave -timeline 1
|
||||||
|
update
|
||||||
|
WaveRestoreZoom {0 ps} {5250 us}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Company:
|
||||||
|
-- Engineer:
|
||||||
|
--
|
||||||
|
-- Create Date: 19:34:24 10/23/05
|
||||||
|
-- Design Name:
|
||||||
|
-- Module Name: debounce - 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 debounce is
|
||||||
|
Generic ( ncyc_latency : integer := 100);
|
||||||
|
Port ( rst : in std_logic;
|
||||||
|
clk : in std_logic;
|
||||||
|
input : in std_logic;
|
||||||
|
output : out std_logic);
|
||||||
|
end debounce;
|
||||||
|
|
||||||
|
architecture Behavioral of debounce is
|
||||||
|
|
||||||
|
type debounce_state_t is (init_st, wait_st, rel_st);
|
||||||
|
signal debounce_cs : debounce_state_t;
|
||||||
|
signal debounce_ns : debounce_state_t;
|
||||||
|
signal count : integer range 0 to ncyc_latency-1;
|
||||||
|
signal input_last : std_logic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
debounce_clk: process(rst, clk, debounce_ns, debounce_cs, input)
|
||||||
|
begin
|
||||||
|
if (rst = '1') then
|
||||||
|
count <= 0;
|
||||||
|
output <= input;
|
||||||
|
input_last <= input;
|
||||||
|
else
|
||||||
|
if rising_edge(clk) then
|
||||||
|
debounce_cs <= debounce_ns;
|
||||||
|
if (debounce_cs = wait_st) then
|
||||||
|
if (count /= 0) then
|
||||||
|
count <= count - 1;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
count <= ncyc_latency-1;
|
||||||
|
if (debounce_cs = rel_st) then
|
||||||
|
output <= input;
|
||||||
|
input_last <= input;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
debounce_in: process(rst, clk, input, input_last, debounce_cs, count)
|
||||||
|
begin
|
||||||
|
debounce_ns <= debounce_cs;
|
||||||
|
case debounce_cs is
|
||||||
|
when init_st =>
|
||||||
|
if (input /= input_last) then
|
||||||
|
debounce_ns <= wait_st;
|
||||||
|
end if;
|
||||||
|
when wait_st =>
|
||||||
|
if (count = 0) then
|
||||||
|
debounce_ns <= rel_st;
|
||||||
|
end if;
|
||||||
|
when others =>
|
||||||
|
debounce_ns <= init_st;
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
@@ -0,0 +1,592 @@
|
|||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- 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.NUMERIC_STD.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_hz : integer := 100E6
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
rst : in std_logic;
|
||||||
|
clk : in std_logic;
|
||||||
|
din : in unsigned(7 downto 0);
|
||||||
|
dout : out unsigned(7 downto 0);
|
||||||
|
tx_empty : out std_logic;
|
||||||
|
rx_present : out std_logic;
|
||||||
|
din_vld : in std_logic;
|
||||||
|
read_en : in std_logic;
|
||||||
|
ps2_clk_rx : in std_logic;
|
||||||
|
ps2_data_rx : in std_logic;
|
||||||
|
ps2_clk_tx : out std_logic;
|
||||||
|
ps2_data_tx : out std_logic
|
||||||
|
);
|
||||||
|
|
||||||
|
end ps2_core;
|
||||||
|
|
||||||
|
architecture Behavioral of ps2_core is
|
||||||
|
|
||||||
|
-- Types
|
||||||
|
type line_state_rx_t is (start_wait_st, start_trans_st, start_sample_st,
|
||||||
|
data_wait_st, data_trans_st, data_sample_st,
|
||||||
|
parity_wait_st, parity_trans_st, parity_sample_st,
|
||||||
|
stop_wait_st, stop_trans_st, stop_sample_st,
|
||||||
|
valid_st);
|
||||||
|
|
||||||
|
type line_state_tx_t is (tx_idle_st, tx_clock_assert_st, tx_start_latency_st,
|
||||||
|
tx_start_assert_st, tx_clock_release_st, tx_dev_trans_st,
|
||||||
|
tx_data_wait_st, tx_data_trans_st, tx_data_sample_st,
|
||||||
|
tx_parity_update_st, tx_dev_wait_st,
|
||||||
|
tx_parity_wait_st, tx_parity_trans_st, tx_parity_sample_st,
|
||||||
|
tx_stop_wait_st, tx_stop_trans_st, tx_stop_sample_st,
|
||||||
|
tx_ack_trans_st, tx_ack_sample_st, tx_valid_st);
|
||||||
|
|
||||||
|
-- Constant
|
||||||
|
constant prescaler_us : integer := f_sys_clk_hz/1E6;
|
||||||
|
constant timeout_us : integer := 15000;
|
||||||
|
constant time_clock_assert : integer := 120;
|
||||||
|
|
||||||
|
-- Signals
|
||||||
|
signal en_us : std_logic;
|
||||||
|
signal timeout_rx_load_en : std_logic;
|
||||||
|
signal timeout_rx_en : std_logic;
|
||||||
|
signal timeout_rx_flag : std_logic;
|
||||||
|
|
||||||
|
signal timeout_tx_load_en : std_logic;
|
||||||
|
signal timeout_tx_en : std_logic;
|
||||||
|
signal timeout_tx_flag : std_logic;
|
||||||
|
|
||||||
|
signal read_cs : line_state_rx_t;
|
||||||
|
signal read_ns : line_state_rx_t;
|
||||||
|
signal write_cs : line_state_tx_t;
|
||||||
|
signal write_ns : line_state_tx_t;
|
||||||
|
|
||||||
|
signal data_cnt_en : std_logic;
|
||||||
|
signal data_cnt_rst : std_logic;
|
||||||
|
signal data_cnt : integer range 0 to 7;
|
||||||
|
|
||||||
|
signal data_cnt_tx_en : std_logic;
|
||||||
|
signal data_cnt_tx_rst : std_logic;
|
||||||
|
signal data_cnt_tx : integer range 0 to 7;
|
||||||
|
|
||||||
|
signal sipo_en : std_logic;
|
||||||
|
signal piso_en : std_logic;
|
||||||
|
signal piso_out : std_logic;
|
||||||
|
signal piso_load_en : std_logic;
|
||||||
|
signal rx_en : std_logic;
|
||||||
|
signal tx_en : std_logic;
|
||||||
|
signal rx_busy : std_logic;
|
||||||
|
signal tx_busy : std_logic;
|
||||||
|
signal rx_rdy : std_logic;
|
||||||
|
signal tx_rdy : std_logic;
|
||||||
|
signal tx_req : std_logic;
|
||||||
|
signal rx_reg : unsigned(7 downto 0);
|
||||||
|
signal tx_reg : unsigned(7 downto 0);
|
||||||
|
|
||||||
|
signal parity_rst : std_logic;
|
||||||
|
signal parity_en : std_logic;
|
||||||
|
signal parity : std_logic;
|
||||||
|
signal parity_tx_rst : std_logic;
|
||||||
|
signal parity_tx_en : std_logic;
|
||||||
|
signal parity_tx : std_logic;
|
||||||
|
|
||||||
|
signal timeout_count_rx : integer range 0 to timeout_us-1;
|
||||||
|
signal timeout_count_tx : integer range 0 to timeout_us-1;
|
||||||
|
signal timeval_tx : integer range 0 to timeout_us-1;
|
||||||
|
|
||||||
|
signal sipo_reg : unsigned(7 downto 0);
|
||||||
|
signal piso_reg : unsigned(7 downto 0);
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
proc_prescaler:
|
||||||
|
process(clk)
|
||||||
|
variable cnt_prescaler : integer range 0 to prescaler_us-1;
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if rst = '1' then
|
||||||
|
cnt_prescaler := prescaler_us - 1;
|
||||||
|
en_us <= '0';
|
||||||
|
elsif cnt_prescaler = 0 then
|
||||||
|
cnt_prescaler := prescaler_us - 1;
|
||||||
|
en_us <= '1';
|
||||||
|
else
|
||||||
|
cnt_prescaler := cnt_prescaler - 1;
|
||||||
|
en_us <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process proc_prescaler;
|
||||||
|
|
||||||
|
proc_timeout_counter_rx:
|
||||||
|
process (clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if timeout_rx_load_en ='1' then
|
||||||
|
timeout_count_rx <= timeout_us - 1;
|
||||||
|
timeout_rx_flag <= '0';
|
||||||
|
else
|
||||||
|
if (timeout_count_rx /= 0) then
|
||||||
|
if timeout_rx_en ='1' then
|
||||||
|
timeout_count_rx <= timeout_count_rx - 1;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
timeout_rx_flag <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_timeout_counter_tx:
|
||||||
|
process (clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if timeout_tx_load_en ='1' then
|
||||||
|
timeout_count_tx <= timeval_tx;
|
||||||
|
timeout_tx_flag <= '0';
|
||||||
|
else
|
||||||
|
if (timeout_count_tx /= 0) then
|
||||||
|
if timeout_tx_en ='1' then
|
||||||
|
timeout_count_tx <= timeout_count_tx - 1;
|
||||||
|
end if;
|
||||||
|
else
|
||||||
|
timeout_tx_flag <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_rx_sipo:
|
||||||
|
process (clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if (rst = '1') then
|
||||||
|
sipo_reg <= (others => '0');
|
||||||
|
elsif sipo_en = '1' then
|
||||||
|
sipo_reg <= ps2_data_rx & sipo_reg(sipo_reg'left downto 1);
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
rx_reg <= sipo_reg;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_tx_piso:
|
||||||
|
process (clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if rst ='1' then
|
||||||
|
piso_reg <= (others => '0');
|
||||||
|
elsif piso_load_en = '1' then
|
||||||
|
piso_reg <= tx_reg;
|
||||||
|
elsif piso_en = '1' then
|
||||||
|
piso_reg <= '0' & piso_reg(piso_reg'left downto 1);
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
piso_out <= piso_reg(0);
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_parity_bitser_rx:
|
||||||
|
process (clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if parity_rst='1' then
|
||||||
|
parity <= '1';
|
||||||
|
elsif parity_en = '1' and ps2_data_rx = '1' then
|
||||||
|
parity <= not parity;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_parity_bitser_tx:
|
||||||
|
process (clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if parity_tx_rst='1' then
|
||||||
|
parity_tx <= '1';
|
||||||
|
elsif parity_tx_en = '1' and piso_out = '1' then
|
||||||
|
parity_tx <= not parity_tx;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
tx_en <= tx_req and (not rx_busy);
|
||||||
|
rx_en <= not tx_busy;
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
proc_out_reg:
|
||||||
|
process(clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if rst = '1' then
|
||||||
|
dout <= (others => '0');
|
||||||
|
rx_present <= '0';
|
||||||
|
elsif rx_rdy = '1' then
|
||||||
|
dout <= rx_reg;
|
||||||
|
rx_present <= '1';
|
||||||
|
elsif read_en = '1' then
|
||||||
|
rx_present <= '0';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
proc_in_reg:
|
||||||
|
process(clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if rst = '1' then
|
||||||
|
tx_empty <= '1';
|
||||||
|
tx_req <= '0';
|
||||||
|
elsif piso_load_en = '1' then
|
||||||
|
tx_reg <= din;
|
||||||
|
tx_empty <= '1';
|
||||||
|
tx_req <= '0';
|
||||||
|
elsif din_vld = '1' then
|
||||||
|
tx_empty <= '0';
|
||||||
|
tx_req <= '1';
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
proc_read_state_clk:
|
||||||
|
process(clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if rst = '1' then
|
||||||
|
read_cs <= start_wait_st;
|
||||||
|
else
|
||||||
|
read_cs <= read_ns;
|
||||||
|
if (data_cnt_rst = '1') then
|
||||||
|
data_cnt <= 7;
|
||||||
|
elsif (data_cnt_en = '1') then
|
||||||
|
if (data_cnt /= 0) then
|
||||||
|
data_cnt <= data_cnt - 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
proc_write_state_clk:
|
||||||
|
process(rst, clk)
|
||||||
|
begin
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if rst = '1' then
|
||||||
|
write_cs <= tx_idle_st;
|
||||||
|
else
|
||||||
|
write_cs <= write_ns;
|
||||||
|
if (data_cnt_tx_rst = '1') then
|
||||||
|
data_cnt_tx <= 7;
|
||||||
|
elsif (data_cnt_tx_en = '1') then
|
||||||
|
if (data_cnt_tx /= 0) then
|
||||||
|
data_cnt_tx <= data_cnt_tx - 1;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
read_state_output:
|
||||||
|
process(read_cs, en_us)
|
||||||
|
begin
|
||||||
|
|
||||||
|
timeout_rx_load_en <= '0';
|
||||||
|
timeout_rx_en <= en_us;
|
||||||
|
data_cnt_en <= '0';
|
||||||
|
data_cnt_rst <= '0';
|
||||||
|
sipo_en <= '0';
|
||||||
|
rx_rdy <= '0';
|
||||||
|
parity_en <= '0';
|
||||||
|
parity_rst <= '0';
|
||||||
|
rx_busy <= '1';
|
||||||
|
case (read_cs) is
|
||||||
|
when start_wait_st =>
|
||||||
|
timeout_rx_load_en <= '1';
|
||||||
|
timeout_rx_en <= '0';
|
||||||
|
rx_busy <= '0';
|
||||||
|
when start_sample_st =>
|
||||||
|
data_cnt_rst <= '1';
|
||||||
|
parity_rst <= '1';
|
||||||
|
timeout_rx_load_en <= '1';
|
||||||
|
when data_sample_st =>
|
||||||
|
data_cnt_en <= '1';
|
||||||
|
parity_en <= '1';
|
||||||
|
sipo_en <= '1';
|
||||||
|
timeout_rx_load_en <= '1';
|
||||||
|
when parity_sample_st =>
|
||||||
|
timeout_rx_load_en <= '1';
|
||||||
|
parity_en <= '1';
|
||||||
|
when valid_st =>
|
||||||
|
rx_busy <= '0';
|
||||||
|
rx_rdy <= '1';
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
read_state_decode:
|
||||||
|
process (read_cs, timeout_rx_flag, rx_en, data_cnt, ps2_data_rx, ps2_clk_rx)
|
||||||
|
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 start_wait_st =>
|
||||||
|
if ps2_data_rx = '0' and ps2_clk_rx = '1' and rx_en = '1' then
|
||||||
|
read_ns <= start_trans_st;
|
||||||
|
end if;
|
||||||
|
when start_trans_st =>
|
||||||
|
if timeout_rx_flag = '1' then
|
||||||
|
read_ns <= start_wait_st;
|
||||||
|
elsif ps2_data_rx = '0' and ps2_clk_rx = '0' then
|
||||||
|
read_ns <= start_sample_st;
|
||||||
|
end if;
|
||||||
|
when start_sample_st =>
|
||||||
|
read_ns <= data_wait_st;
|
||||||
|
-- Wait data change
|
||||||
|
when data_wait_st =>
|
||||||
|
if timeout_rx_flag = '1' then
|
||||||
|
read_ns <= start_wait_st;
|
||||||
|
elsif ps2_clk_rx = '1' then
|
||||||
|
read_ns <= data_trans_st;
|
||||||
|
end if;
|
||||||
|
-- Wait data trans
|
||||||
|
when data_trans_st =>
|
||||||
|
if timeout_rx_flag = '1' then
|
||||||
|
read_ns <= start_wait_st;
|
||||||
|
elsif ps2_clk_rx = '0' then
|
||||||
|
read_ns <= data_sample_st;
|
||||||
|
end if;
|
||||||
|
-- Data sample
|
||||||
|
when data_sample_st =>
|
||||||
|
read_ns <= data_wait_st;
|
||||||
|
if data_cnt = 0 then
|
||||||
|
read_ns <= parity_wait_st;
|
||||||
|
end if;
|
||||||
|
when parity_wait_st =>
|
||||||
|
if timeout_rx_flag = '1' then
|
||||||
|
read_ns <= start_wait_st;
|
||||||
|
elsif ps2_clk_rx = '1' then
|
||||||
|
read_ns <= parity_trans_st;
|
||||||
|
end if;
|
||||||
|
when parity_trans_st =>
|
||||||
|
if timeout_rx_flag = '1' then
|
||||||
|
read_ns <= start_wait_st;
|
||||||
|
elsif ps2_clk_rx = '0' then
|
||||||
|
read_ns <= parity_sample_st;
|
||||||
|
end if;
|
||||||
|
when parity_sample_st =>
|
||||||
|
read_ns <= stop_wait_st;
|
||||||
|
when stop_wait_st =>
|
||||||
|
if timeout_rx_flag = '1' then
|
||||||
|
read_ns <= start_wait_st;
|
||||||
|
elsif ps2_clk_rx = '1' then
|
||||||
|
read_ns <= stop_trans_st;
|
||||||
|
end if;
|
||||||
|
when stop_trans_st =>
|
||||||
|
if timeout_rx_flag = '1' then
|
||||||
|
read_ns <= start_wait_st;
|
||||||
|
elsif ps2_clk_rx = '0' and ps2_data_rx = '1' then
|
||||||
|
read_ns <= stop_sample_st;
|
||||||
|
end if;
|
||||||
|
when stop_sample_st =>
|
||||||
|
if timeout_rx_flag = '1' then
|
||||||
|
read_ns <= start_wait_st;
|
||||||
|
elsif ps2_clk_rx = '1' then
|
||||||
|
read_ns <= valid_st;
|
||||||
|
end if;
|
||||||
|
when valid_st =>
|
||||||
|
read_ns <= start_wait_st;
|
||||||
|
when others =>
|
||||||
|
read_ns <= start_wait_st;
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
write_state_output:
|
||||||
|
process(write_cs, en_us, piso_out, parity_tx)
|
||||||
|
begin
|
||||||
|
|
||||||
|
timeout_tx_load_en <= '0';
|
||||||
|
timeout_tx_en <= en_us;
|
||||||
|
tx_rdy <= '0';
|
||||||
|
tx_busy <= '1';
|
||||||
|
piso_load_en <= '0';
|
||||||
|
ps2_clk_tx <= '1';
|
||||||
|
ps2_data_tx <= '1';
|
||||||
|
piso_en <= '0';
|
||||||
|
timeval_tx <= time_clock_assert - 1;
|
||||||
|
data_cnt_tx_en <= '0';
|
||||||
|
data_cnt_tx_rst <= '0';
|
||||||
|
parity_tx_rst <= '0';
|
||||||
|
parity_tx_en <= '0';
|
||||||
|
case (write_cs) is
|
||||||
|
when tx_idle_st =>
|
||||||
|
tx_busy <= '0';
|
||||||
|
timeout_tx_load_en <= '1';
|
||||||
|
timeout_tx_en <= '0';
|
||||||
|
when tx_clock_assert_st =>
|
||||||
|
parity_tx_rst <= '1';
|
||||||
|
piso_load_en <= '1';
|
||||||
|
data_cnt_tx_rst <= '1';
|
||||||
|
ps2_clk_tx <= '0';
|
||||||
|
when tx_start_assert_st =>
|
||||||
|
ps2_clk_tx <= '0';
|
||||||
|
ps2_data_tx <= '0';
|
||||||
|
when tx_clock_release_st =>
|
||||||
|
ps2_data_tx <= '0';
|
||||||
|
timeout_tx_load_en <= '1';
|
||||||
|
timeval_tx <= timeout_us - 1;
|
||||||
|
when tx_dev_wait_st =>
|
||||||
|
ps2_data_tx <= '0';
|
||||||
|
when tx_dev_trans_st =>
|
||||||
|
ps2_data_tx <= '0';
|
||||||
|
timeout_tx_load_en <= '1';
|
||||||
|
timeval_tx <= timeout_us - 1;
|
||||||
|
when tx_data_wait_st =>
|
||||||
|
ps2_data_tx <= piso_out;
|
||||||
|
when tx_data_trans_st =>
|
||||||
|
data_cnt_tx_en <= '1';
|
||||||
|
ps2_data_tx <= piso_out;
|
||||||
|
piso_en <= '1';
|
||||||
|
timeout_tx_load_en <= '1';
|
||||||
|
timeval_tx <= timeout_us - 1;
|
||||||
|
parity_tx_en <= '1';
|
||||||
|
when tx_data_sample_st =>
|
||||||
|
ps2_data_tx <= piso_out;
|
||||||
|
when tx_parity_update_st =>
|
||||||
|
parity_tx_en <= '1';
|
||||||
|
ps2_data_tx <= piso_out;
|
||||||
|
when tx_parity_sample_st =>
|
||||||
|
ps2_data_tx <= parity_tx;
|
||||||
|
when tx_parity_wait_st =>
|
||||||
|
ps2_data_tx <= parity_tx;
|
||||||
|
when tx_parity_trans_st =>
|
||||||
|
ps2_data_tx <= piso_out;
|
||||||
|
timeout_tx_load_en <= '1';
|
||||||
|
timeval_tx <= timeout_us - 1;
|
||||||
|
when tx_valid_st =>
|
||||||
|
tx_rdy <= '1';
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
write_state_decode:
|
||||||
|
process (write_cs, tx_en, data_cnt_tx, timeout_tx_flag, ps2_data_rx, ps2_clk_rx)
|
||||||
|
begin
|
||||||
|
--declare default state for next_state to avoid latches
|
||||||
|
write_ns <= write_cs; --default is to stay in current state
|
||||||
|
--insert statements to decode next_state
|
||||||
|
--below is a simple example
|
||||||
|
case (write_cs) is
|
||||||
|
when tx_idle_st =>
|
||||||
|
if tx_en = '1' then
|
||||||
|
write_ns <= tx_clock_assert_st;
|
||||||
|
end if;
|
||||||
|
when tx_clock_assert_st =>
|
||||||
|
if timeout_tx_flag = '1' then
|
||||||
|
write_ns <= tx_start_assert_st;
|
||||||
|
end if;
|
||||||
|
when tx_start_assert_st =>
|
||||||
|
write_ns <= tx_clock_release_st;
|
||||||
|
when tx_clock_release_st =>
|
||||||
|
write_ns <= tx_dev_wait_st;
|
||||||
|
when tx_dev_wait_st =>
|
||||||
|
if timeout_tx_flag = '1' then
|
||||||
|
write_ns <= tx_idle_st;
|
||||||
|
elsif ps2_clk_rx = '1' then
|
||||||
|
write_ns <= tx_dev_trans_st;
|
||||||
|
end if;
|
||||||
|
when tx_dev_trans_st =>
|
||||||
|
if timeout_tx_flag = '1' then
|
||||||
|
write_ns <= tx_idle_st;
|
||||||
|
elsif ps2_clk_rx = '0' then
|
||||||
|
write_ns <= tx_data_wait_st;
|
||||||
|
end if;
|
||||||
|
when tx_data_wait_st =>
|
||||||
|
if timeout_tx_flag = '1' then
|
||||||
|
write_ns <= tx_idle_st;
|
||||||
|
elsif ps2_clk_rx = '1' then
|
||||||
|
write_ns <= tx_data_sample_st;
|
||||||
|
end if;
|
||||||
|
when tx_data_sample_st =>
|
||||||
|
if timeout_tx_flag = '1' then
|
||||||
|
write_ns <= tx_idle_st;
|
||||||
|
elsif ps2_clk_rx = '0' then
|
||||||
|
write_ns <= tx_data_trans_st;
|
||||||
|
if (data_cnt_tx = 0) then
|
||||||
|
write_ns <= tx_parity_update_st;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
when tx_data_trans_st =>
|
||||||
|
write_ns <= tx_data_wait_st;
|
||||||
|
when tx_parity_update_st =>
|
||||||
|
write_ns <= tx_parity_trans_st;
|
||||||
|
when tx_parity_trans_st =>
|
||||||
|
write_ns <= tx_parity_wait_st;
|
||||||
|
when tx_parity_wait_st =>
|
||||||
|
if timeout_tx_flag = '1' then
|
||||||
|
write_ns <= tx_idle_st;
|
||||||
|
elsif ps2_clk_rx = '1' then
|
||||||
|
write_ns <= tx_parity_sample_st;
|
||||||
|
end if;
|
||||||
|
when tx_parity_sample_st =>
|
||||||
|
if timeout_tx_flag = '1' then
|
||||||
|
write_ns <= tx_idle_st;
|
||||||
|
elsif ps2_clk_rx = '0' then
|
||||||
|
write_ns <= tx_stop_trans_st;
|
||||||
|
end if;
|
||||||
|
when tx_stop_trans_st =>
|
||||||
|
write_ns <= tx_stop_wait_st;
|
||||||
|
when tx_stop_wait_st =>
|
||||||
|
if timeout_tx_flag = '1' then
|
||||||
|
write_ns <= tx_idle_st;
|
||||||
|
elsif ps2_clk_rx = '1' then
|
||||||
|
write_ns <= tx_ack_trans_st;
|
||||||
|
end if;
|
||||||
|
when tx_ack_trans_st =>
|
||||||
|
if timeout_tx_flag = '1' then
|
||||||
|
write_ns <= tx_idle_st;
|
||||||
|
elsif ps2_clk_rx = '0' and ps2_data_rx = '0' then
|
||||||
|
write_ns <= tx_ack_sample_st;
|
||||||
|
end if;
|
||||||
|
when tx_ack_sample_st =>
|
||||||
|
if timeout_tx_flag = '1' then
|
||||||
|
write_ns <= tx_idle_st;
|
||||||
|
elsif ps2_clk_rx = '1' and ps2_data_rx = '1' then
|
||||||
|
write_ns <= tx_valid_st;
|
||||||
|
end if;
|
||||||
|
when others =>
|
||||||
|
write_ns <= tx_idle_st;
|
||||||
|
end case;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-------------------------------------------
|
||||||
|
end Behavioral;
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Company:
|
||||||
|
-- Engineer:
|
||||||
|
--
|
||||||
|
-- Create Date: 20:52:44 10/26/05
|
||||||
|
-- Design Name:
|
||||||
|
-- Module Name: ps2_phy - 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_phy is
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
rst : in std_logic;
|
||||||
|
clk : in std_logic;
|
||||||
|
ps2_clk : inout std_logic;
|
||||||
|
ps2_data : inout std_logic;
|
||||||
|
rx_clk : out std_logic;
|
||||||
|
rx_data : out std_logic;
|
||||||
|
tx_clk : in std_logic;
|
||||||
|
tx_data : in std_logic
|
||||||
|
);
|
||||||
|
end ps2_phy;
|
||||||
|
|
||||||
|
architecture Behavioral of ps2_phy is
|
||||||
|
|
||||||
|
COMPONENT debounce
|
||||||
|
GENERIC (ncyc_latency : integer);
|
||||||
|
PORT
|
||||||
|
(
|
||||||
|
rst : IN std_logic;
|
||||||
|
clk : IN std_logic;
|
||||||
|
input : IN std_logic;
|
||||||
|
output : OUT std_logic
|
||||||
|
);
|
||||||
|
END COMPONENT;
|
||||||
|
|
||||||
|
signal clk_in : std_logic;
|
||||||
|
signal data_in : std_logic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
Inst_debounce_clk: debounce
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
ncyc_latency => 8
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => rst,
|
||||||
|
clk => clk,
|
||||||
|
input => clk_in,
|
||||||
|
output => rx_clk
|
||||||
|
);
|
||||||
|
|
||||||
|
Inst_debounce_data: debounce
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
ncyc_latency => 8
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => rst,
|
||||||
|
clk => clk,
|
||||||
|
input => data_in,
|
||||||
|
output => rx_data
|
||||||
|
);
|
||||||
|
|
||||||
|
IOBUF_inst_ps2_clk : IOBUF
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
DRIVE => 2,
|
||||||
|
IBUF_DELAY_VALUE => "0", -- Specify the amount of added input delay for buffer, "0"-"16" (Spartan-3E only)
|
||||||
|
IFD_DELAY_VALUE => "AUTO", -- Specify the amount of added delay for input register, "AUTO", "0"-"8" (Spartan-3E only)
|
||||||
|
IOSTANDARD => "DEFAULT",
|
||||||
|
SLEW => "SLOW"
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
O => clk_in, -- Buffer output
|
||||||
|
IO => ps2_clk, -- Buffer inout port (connect directly to top-level port)
|
||||||
|
I => tx_clk, -- Buffer input
|
||||||
|
T => tx_clk -- 3-state enable input
|
||||||
|
);
|
||||||
|
|
||||||
|
IOBUF_inst_ps2_data : IOBUF
|
||||||
|
generic map
|
||||||
|
(
|
||||||
|
DRIVE => 2,
|
||||||
|
IBUF_DELAY_VALUE => "0", -- Specify the amount of added input delay for buffer, "0"-"16" (Spartan-3E only)
|
||||||
|
IFD_DELAY_VALUE => "AUTO", -- Specify the amount of added delay for input register, "AUTO", "0"-"8" (Spartan-3E only)
|
||||||
|
IOSTANDARD => "DEFAULT",
|
||||||
|
SLEW => "SLOW"
|
||||||
|
)
|
||||||
|
port map
|
||||||
|
(
|
||||||
|
O => data_in, -- Buffer output
|
||||||
|
IO => ps2_data, -- Buffer inout port (connect directly to top-level port)
|
||||||
|
I => tx_data, -- Buffer input
|
||||||
|
T => tx_data -- 3-state enable input
|
||||||
|
);
|
||||||
|
|
||||||
|
end Behavioral;
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
LIBRARY IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
ENTITY ps2_wb IS
|
||||||
|
Generic
|
||||||
|
(
|
||||||
|
f_sys_clk_hz : integer := 100E6
|
||||||
|
);
|
||||||
|
Port
|
||||||
|
(
|
||||||
|
CLK_I : in STD_LOGIC;
|
||||||
|
RST_I : in STD_LOGIC;
|
||||||
|
CYC_I : in STD_LOGIC;
|
||||||
|
STB_I : in STD_LOGIC;
|
||||||
|
SEL_I : in unsigned(3 downto 0);
|
||||||
|
WE_I : in STD_LOGIC;
|
||||||
|
ACK_O : out STD_LOGIC;
|
||||||
|
SRDY_O : out STD_LOGIC;
|
||||||
|
MRDY_I : in STD_LOGIC;
|
||||||
|
ADDR_I : in unsigned(31 downto 0);
|
||||||
|
DAT_I : in unsigned(31 downto 0);
|
||||||
|
DAT_O : out unsigned(31 downto 0);
|
||||||
|
INT_O : out STD_LOGIC;
|
||||||
|
clk_rx : in std_logic;
|
||||||
|
data_rx : in std_logic;
|
||||||
|
clk_tx : out std_logic;
|
||||||
|
data_tx : out std_logic
|
||||||
|
);
|
||||||
|
END ps2_wb;
|
||||||
|
|
||||||
|
ARCHITECTURE behavior OF ps2_wb IS
|
||||||
|
|
||||||
|
|
||||||
|
-- Signals for ps2 connections
|
||||||
|
signal reg_we_ps2_tx : std_logic;
|
||||||
|
signal reg_re_ps2_rx : std_logic;
|
||||||
|
signal reg_ps2_tx : unsigned(7 downto 0);
|
||||||
|
signal reg_ps2_rx : unsigned(7 downto 0);
|
||||||
|
signal rx_data_present : std_logic;
|
||||||
|
signal ps2_status_port : unsigned(15 downto 0);
|
||||||
|
signal rx_int_en : std_logic;
|
||||||
|
signal tx_int_en : std_logic;
|
||||||
|
signal irq_rx : std_logic;
|
||||||
|
signal irq_tx : std_logic;
|
||||||
|
signal tx_empty : std_logic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
|
||||||
|
SRDY_O <= CYC_I;
|
||||||
|
|
||||||
|
------------------------------------------------------------------
|
||||||
|
registers_write:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
reg_we_ps2_tx <= '0';
|
||||||
|
if RST_I = '1' then
|
||||||
|
rx_int_en <= '0';
|
||||||
|
tx_int_en <= '0';
|
||||||
|
elsif (STB_I and CYC_I and WE_I) = '1' then
|
||||||
|
case ADDR_I(5 downto 2) is
|
||||||
|
|
||||||
|
when "0000" =>
|
||||||
|
reg_we_ps2_tx <= '1';
|
||||||
|
reg_ps2_tx <= DAT_I(7 downto 0);
|
||||||
|
|
||||||
|
when "0001" =>
|
||||||
|
rx_int_en <= DAT_I(6);
|
||||||
|
tx_int_en <= DAT_I(5);
|
||||||
|
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
registers_read:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
reg_re_ps2_rx <= '0';
|
||||||
|
ACK_O <= '0';
|
||||||
|
if (STB_I and CYC_I) = '1' then
|
||||||
|
ACK_O <= not WE_I;
|
||||||
|
DAT_O <= (others => '0');
|
||||||
|
case ADDR_I(5 downto 2) is
|
||||||
|
|
||||||
|
when "0000" =>
|
||||||
|
reg_re_ps2_rx <= not WE_I;
|
||||||
|
DAT_O(7 downto 0) <= unsigned(reg_ps2_rx);
|
||||||
|
|
||||||
|
when "0001" =>
|
||||||
|
DAT_O(15 downto 0) <= ps2_status_port;
|
||||||
|
|
||||||
|
when others => null;
|
||||||
|
end case;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
irq_register:
|
||||||
|
process(CLK_I)
|
||||||
|
begin
|
||||||
|
if rising_edge(CLK_I) then
|
||||||
|
INT_O <= irq_rx or irq_tx;
|
||||||
|
irq_tx <= tx_empty and tx_int_en;
|
||||||
|
irq_rx <= rx_data_present and rx_int_en;
|
||||||
|
end if;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
inst_ps2_core: entity work.ps2_core
|
||||||
|
GENERIC MAP
|
||||||
|
(
|
||||||
|
f_sys_clk_hz => f_sys_clk_hz
|
||||||
|
)
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => RST_I,
|
||||||
|
clk => CLK_I,
|
||||||
|
din => reg_ps2_tx,
|
||||||
|
dout => reg_ps2_rx,
|
||||||
|
tx_empty => tx_empty,
|
||||||
|
rx_present => rx_data_present,
|
||||||
|
din_vld => reg_we_ps2_tx,
|
||||||
|
read_en => reg_re_ps2_rx,
|
||||||
|
ps2_clk_rx => clk_rx,
|
||||||
|
ps2_data_rx => data_rx,
|
||||||
|
ps2_clk_tx => clk_tx,
|
||||||
|
ps2_data_tx => data_tx
|
||||||
|
);
|
||||||
|
|
||||||
|
ps2_status_port <= "000000" & irq_rx & irq_tx & '0' & rx_int_en & tx_int_en & '0' & '0' & rx_data_present & '0' & tx_empty;
|
||||||
|
-- INT_O <= irq_rx or irq_tx;
|
||||||
|
|
||||||
|
end behavior;
|
||||||
@@ -0,0 +1,290 @@
|
|||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Company:
|
||||||
|
-- Engineer:
|
||||||
|
--
|
||||||
|
-- Create Date: 20:35:49 10/22/2005
|
||||||
|
-- Design Name: ps2_core
|
||||||
|
-- Module Name: tb_ps2_core.vhd
|
||||||
|
-- Project Name: ps2if
|
||||||
|
-- Target Device:
|
||||||
|
-- Tool versions:
|
||||||
|
-- Description:
|
||||||
|
--
|
||||||
|
-- VHDL Test Bench Created by ISE for module: ps2_core
|
||||||
|
--
|
||||||
|
-- Dependencies:
|
||||||
|
--
|
||||||
|
-- Revision:
|
||||||
|
-- Revision 0.01 - File Created
|
||||||
|
-- Additional Comments:
|
||||||
|
--
|
||||||
|
-- Notes:
|
||||||
|
-- This testbench has been automatically generated using types std_logic and
|
||||||
|
-- std_logic_vector for the ports of the unit under test. Xilinx recommends
|
||||||
|
-- that these types always be used for the top-level I/O of a design in order
|
||||||
|
-- to guarantee that the testbench will bind correctly to the post-implementation
|
||||||
|
-- simulation model.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
LIBRARY IEEE;
|
||||||
|
USE IEEE.STD_LOGIC_1164.ALL;
|
||||||
|
USE IEEE.NUMERIC_STD.ALL;
|
||||||
|
|
||||||
|
ENTITY tb_ps2_core IS
|
||||||
|
END tb_ps2_core;
|
||||||
|
|
||||||
|
ARCHITECTURE behavior OF tb_ps2_core IS
|
||||||
|
|
||||||
|
-- Component Declaration for the Unit Under Test (UUT)
|
||||||
|
COMPONENT ps2_core
|
||||||
|
PORT(
|
||||||
|
rst : IN std_logic;
|
||||||
|
clk : IN std_logic;
|
||||||
|
din : IN unsigned(7 downto 0);
|
||||||
|
din_vld : IN std_logic;
|
||||||
|
read_en : IN std_logic;
|
||||||
|
ps2_clk_rx : IN std_logic;
|
||||||
|
ps2_data_rx : IN std_logic;
|
||||||
|
ps2_clk_tx : out std_logic;
|
||||||
|
ps2_data_tx : out std_logic;
|
||||||
|
dout : OUT unsigned(7 downto 0);
|
||||||
|
tx_empty : OUT std_logic;
|
||||||
|
rx_present : OUT std_logic
|
||||||
|
);
|
||||||
|
END COMPONENT;
|
||||||
|
|
||||||
|
--Constants
|
||||||
|
constant SYSPERIOD : time := 10 ns;
|
||||||
|
constant PS2PERIOD : time := 100 us;
|
||||||
|
|
||||||
|
--Inputs
|
||||||
|
SIGNAL rst : std_logic := '1';
|
||||||
|
SIGNAL clk : std_logic := '0';
|
||||||
|
SIGNAL din_vld : std_logic := '0';
|
||||||
|
SIGNAL read_en : std_logic := '0';
|
||||||
|
SIGNAL ps2_clk_rx : std_logic := '1';
|
||||||
|
SIGNAL ps2_data_rx : std_logic := '1';
|
||||||
|
SIGNAL din : unsigned(7 downto 0) := (others=>'0');
|
||||||
|
|
||||||
|
--Outputs
|
||||||
|
SIGNAL dout : unsigned(7 downto 0);
|
||||||
|
SIGNAL dout_reg : unsigned(7 downto 0);
|
||||||
|
SIGNAL tx_empty : std_logic;
|
||||||
|
SIGNAL rx_present : std_logic;
|
||||||
|
SIGNAL ps2_clk_i : std_logic := '1';
|
||||||
|
SIGNAL ps2_clk_j : std_logic := '1';
|
||||||
|
SIGNAL ps2_clk_tx : std_logic;
|
||||||
|
SIGNAL ps2_data_tx : std_logic;
|
||||||
|
SIGNAl tx_trig : std_logic := '0';
|
||||||
|
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
-- Instantiate the Unit Under Test (UUT)
|
||||||
|
uut: ps2_core
|
||||||
|
PORT MAP
|
||||||
|
(
|
||||||
|
rst => rst,
|
||||||
|
clk => clk,
|
||||||
|
din => din,
|
||||||
|
dout => dout,
|
||||||
|
tx_empty => tx_empty,
|
||||||
|
rx_present => rx_present,
|
||||||
|
din_vld => din_vld,
|
||||||
|
read_en => read_en,
|
||||||
|
ps2_clk_rx => ps2_clk_rx,
|
||||||
|
ps2_data_rx => ps2_data_rx,
|
||||||
|
ps2_clk_tx => ps2_clk_tx,
|
||||||
|
ps2_data_tx => ps2_data_tx
|
||||||
|
);
|
||||||
|
|
||||||
|
ps2_clk_j <= ps2_clk_i after PS2PERIOD/4;
|
||||||
|
tb_pswclk : PROCESS
|
||||||
|
BEGIN
|
||||||
|
wait until ps2_clk_j'event;
|
||||||
|
ps2_clk_rx <= ps2_clk_j;
|
||||||
|
|
||||||
|
-- wait for SYSPERIOD;
|
||||||
|
-- ps2_clk_rx <= not ps2_clk_j;
|
||||||
|
-- wait for SYSPERIOD;
|
||||||
|
-- ps2_clk_rx <= ps2_clk_j;
|
||||||
|
-- wait for SYSPERIOD;
|
||||||
|
-- ps2_clk_rx <= not ps2_clk_j;
|
||||||
|
-- wait for SYSPERIOD;
|
||||||
|
-- ps2_clk_rx <= ps2_clk_j;
|
||||||
|
-- wait for SYSPERIOD;
|
||||||
|
-- ps2_clk_rx <= not ps2_clk_j;
|
||||||
|
-- wait for SYSPERIOD;
|
||||||
|
-- ps2_clk_rx <= ps2_clk_j;
|
||||||
|
-- wait for SYSPERIOD;
|
||||||
|
-- ps2_clk_rx <= not ps2_clk_j;
|
||||||
|
-- wait for SYSPERIOD;
|
||||||
|
-- ps2_clk_rx <= ps2_clk_j;
|
||||||
|
END PROCESS;
|
||||||
|
|
||||||
|
tb_sysclk : PROCESS
|
||||||
|
BEGIN
|
||||||
|
clk <= not clk;
|
||||||
|
wait for SYSPERIOD/2;
|
||||||
|
END PROCESS;
|
||||||
|
|
||||||
|
read_en <= rx_present;
|
||||||
|
tb_read : PROCESS(clk)
|
||||||
|
BEGIN
|
||||||
|
if rising_edge(clk) then
|
||||||
|
if rx_present = '1' then
|
||||||
|
dout_reg <= dout;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
END PROCESS;
|
||||||
|
|
||||||
|
tb_write : PROCESS
|
||||||
|
BEGIN
|
||||||
|
wait until ps2_clk_tx = '0';
|
||||||
|
wait for PS2PERIOD;
|
||||||
|
wait until ps2_data_tx = '0';
|
||||||
|
wait until ps2_clk_tx = '1';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
tx_trig <= '1';
|
||||||
|
|
||||||
|
END PROCESS;
|
||||||
|
|
||||||
|
tb : PROCESS
|
||||||
|
BEGIN
|
||||||
|
|
||||||
|
wait for 20*SYSPERIOD;
|
||||||
|
rst <= '0';
|
||||||
|
|
||||||
|
for iter in 1 to 2 loop
|
||||||
|
-- wait for 2*PS2PERIOD;
|
||||||
|
|
||||||
|
--Start bit
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= '0';
|
||||||
|
ps2_data_rx <= '0';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
|
||||||
|
--Data bit 0
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= '0';
|
||||||
|
ps2_data_rx <= '1';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
|
||||||
|
--Data bit 1
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= '0';
|
||||||
|
ps2_data_rx <= '1';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
|
||||||
|
--Data bit 2
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= '0';
|
||||||
|
ps2_data_rx <= '0';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
|
||||||
|
--Data bit 3
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= '0';
|
||||||
|
ps2_data_rx <= '1';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
|
||||||
|
--Data bit 4
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= '0';
|
||||||
|
ps2_data_rx <= '1';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
|
||||||
|
--Data bit 5
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= '0';
|
||||||
|
ps2_data_rx <= '0';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
|
||||||
|
--Data bit 6
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= '0';
|
||||||
|
ps2_data_rx <= '1';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
|
||||||
|
--Data bit 7
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= '0';
|
||||||
|
ps2_data_rx <= '1';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
|
||||||
|
--Parity
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= '0';
|
||||||
|
ps2_data_rx <= '1';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
|
||||||
|
--Stop
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= '0';
|
||||||
|
ps2_data_rx <= '1';
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
ps2_data_rx <= '1';
|
||||||
|
ps2_clk_i <= '1';
|
||||||
|
|
||||||
|
wait for PS2PERIOD;
|
||||||
|
wait until rising_edge(clk);
|
||||||
|
din <= x"A5";
|
||||||
|
din_vld <= '1';
|
||||||
|
wait until rising_edge(clk);
|
||||||
|
din_vld <= '0';
|
||||||
|
|
||||||
|
wait until tx_trig = '1';
|
||||||
|
wait for 2*PS2PERIOD;
|
||||||
|
-- Start
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
|
||||||
|
for iter in 1 to 8 loop
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
-- Stop
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
|
||||||
|
-- Parity
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
|
||||||
|
ps2_data_rx <= '0';
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
|
||||||
|
ps2_clk_i <= not ps2_clk_i;
|
||||||
|
wait for PS2PERIOD/2;
|
||||||
|
ps2_data_rx <= '1';
|
||||||
|
ps2_clk_i <= '1';
|
||||||
|
-- Place stimulus here
|
||||||
|
|
||||||
|
wait; -- will wait forever
|
||||||
|
END PROCESS;
|
||||||
|
|
||||||
|
END;
|
||||||
Reference in New Issue
Block a user