- added error flags
- RX abort when rx_buffer already full (error flag set) - added parity error flag 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@631 cc03376c-175c-47c8-b038-4cd826a8556b
This commit is contained in:
+102
-74
@@ -39,6 +39,8 @@ entity ps2_core is
|
||||
dout : out unsigned(7 downto 0);
|
||||
tx_empty : out std_logic;
|
||||
rx_present : out std_logic;
|
||||
rx_err_flag : out std_logic;
|
||||
rx_err_par : out std_logic;
|
||||
din_vld : in std_logic;
|
||||
read_en : in std_logic;
|
||||
ps2_clk_rx : in std_logic;
|
||||
@@ -56,7 +58,7 @@ 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);
|
||||
valid_st, abort_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,
|
||||
@@ -70,15 +72,14 @@ type line_state_tx_t is (tx_idle_st, tx_clock_assert_st, tx_start_latency_st,
|
||||
constant prescaler_us : integer := f_sys_clk_hz/1E6;
|
||||
constant timeout_us : integer := 15000;
|
||||
constant time_clock_assert : integer := 120;
|
||||
constant time_clock_abort : integer := 500;
|
||||
|
||||
-- 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;
|
||||
@@ -101,6 +102,12 @@ signal piso_load_en : std_logic;
|
||||
signal rx_en : std_logic;
|
||||
signal tx_en : std_logic;
|
||||
signal rx_busy : std_logic;
|
||||
signal rx_full : std_logic;
|
||||
signal rx_err : std_logic;
|
||||
signal parity_rx_err_en : std_logic;
|
||||
signal rx_err_set : std_logic;
|
||||
signal rx_err_clr : std_logic;
|
||||
|
||||
signal tx_busy : std_logic;
|
||||
signal rx_rdy : std_logic;
|
||||
signal tx_rdy : std_logic;
|
||||
@@ -108,9 +115,9 @@ 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_rx_rst : std_logic;
|
||||
signal parity_rx_en : std_logic;
|
||||
signal parity_rx : std_logic;
|
||||
signal parity_tx_rst : std_logic;
|
||||
signal parity_tx_en : std_logic;
|
||||
signal parity_tx : std_logic;
|
||||
@@ -118,10 +125,15 @@ 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 timeval_rx : integer range 0 to timeout_us-1;
|
||||
|
||||
signal sipo_reg : unsigned(7 downto 0);
|
||||
signal piso_reg : unsigned(7 downto 0);
|
||||
|
||||
signal clk_tx : std_logic;
|
||||
signal data_tx : std_logic;
|
||||
signal rx_abort : std_logic;
|
||||
|
||||
begin
|
||||
|
||||
proc_prescaler:
|
||||
@@ -147,13 +159,11 @@ process (clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if timeout_rx_load_en ='1' then
|
||||
timeout_count_rx <= timeout_us - 1;
|
||||
timeout_count_rx <= timeval_rx;
|
||||
timeout_rx_flag <= '0';
|
||||
else
|
||||
elsif en_us = '1' then
|
||||
if (timeout_count_rx /= 0) then
|
||||
if timeout_rx_en ='1' then
|
||||
timeout_count_rx <= timeout_count_rx - 1;
|
||||
end if;
|
||||
timeout_count_rx <= timeout_count_rx - 1;
|
||||
else
|
||||
timeout_rx_flag <= '1';
|
||||
end if;
|
||||
@@ -168,11 +178,9 @@ begin
|
||||
if timeout_tx_load_en ='1' then
|
||||
timeout_count_tx <= timeval_tx;
|
||||
timeout_tx_flag <= '0';
|
||||
else
|
||||
elsif en_us = '1' then
|
||||
if (timeout_count_tx /= 0) then
|
||||
if timeout_tx_en ='1' then
|
||||
timeout_count_tx <= timeout_count_tx - 1;
|
||||
end if;
|
||||
timeout_count_tx <= timeout_count_tx - 1;
|
||||
else
|
||||
timeout_tx_flag <= '1';
|
||||
end if;
|
||||
@@ -212,10 +220,28 @@ 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;
|
||||
if parity_rx_rst='1' then
|
||||
parity_rx <= '1';
|
||||
elsif parity_rx_en = '1' and ps2_data_rx = '1' then
|
||||
parity_rx <= not parity_rx;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
proc_rx_error_reg:
|
||||
process (clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if rst='1' then
|
||||
rx_err_flag <= '0';
|
||||
rx_err_par <= '0';
|
||||
elsif parity_rx_err_en = '1' then
|
||||
rx_err_flag <= parity_rx;
|
||||
rx_err_par <= parity_rx;
|
||||
elsif rx_err_set = '1' then
|
||||
rx_err_flag <= '1';
|
||||
elsif rx_err_clr = '1' then
|
||||
rx_err_flag <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
@@ -238,18 +264,21 @@ end process;
|
||||
rx_en <= not tx_busy;
|
||||
|
||||
-------------------------------------------
|
||||
rx_present <= rx_full;
|
||||
proc_out_reg:
|
||||
process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
ps2_clk_tx <= clk_tx and not rx_abort;
|
||||
ps2_data_tx <= data_tx;
|
||||
if rst = '1' then
|
||||
dout <= (others => '0');
|
||||
rx_present <= '0';
|
||||
rx_full <= '0';
|
||||
elsif rx_rdy = '1' then
|
||||
dout <= rx_reg;
|
||||
rx_present <= '1';
|
||||
rx_full <= '1';
|
||||
elsif read_en = '1' then
|
||||
rx_present <= '0';
|
||||
rx_full <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
@@ -312,57 +341,38 @@ begin
|
||||
end if;
|
||||
end process;
|
||||
|
||||
-------------------------------------------
|
||||
read_state_output:
|
||||
process(read_cs, en_us)
|
||||
read_state_decode:
|
||||
process (read_cs, timeout_rx_flag, rx_en, data_cnt, ps2_data_rx, ps2_clk_rx, rx_full)
|
||||
begin
|
||||
|
||||
timeout_rx_load_en <= '0';
|
||||
timeout_rx_en <= en_us;
|
||||
timeval_rx <= timeout_us - 1;
|
||||
data_cnt_en <= '0';
|
||||
data_cnt_rst <= '0';
|
||||
sipo_en <= '0';
|
||||
rx_rdy <= '0';
|
||||
parity_en <= '0';
|
||||
parity_rst <= '0';
|
||||
parity_rx_en <= '0';
|
||||
parity_rx_rst <= '0';
|
||||
parity_rx_err_en <= '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
|
||||
rx_abort <= '0';
|
||||
rx_err_set <= '0';
|
||||
rx_err_clr <= '0';
|
||||
|
||||
--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 =>
|
||||
timeout_rx_load_en <= '1';
|
||||
rx_busy <= '0';
|
||||
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 =>
|
||||
data_cnt_rst <= '1';
|
||||
parity_rx_rst <= '1';
|
||||
timeout_rx_load_en <= '1';
|
||||
if timeout_rx_flag = '1' then
|
||||
read_ns <= start_wait_st;
|
||||
elsif ps2_data_rx = '0' and ps2_clk_rx = '0' then
|
||||
@@ -386,6 +396,10 @@ begin
|
||||
end if;
|
||||
-- Data sample
|
||||
when data_sample_st =>
|
||||
data_cnt_en <= '1';
|
||||
parity_rx_en <= '1';
|
||||
sipo_en <= '1';
|
||||
timeout_rx_load_en <= '1';
|
||||
read_ns <= data_wait_st;
|
||||
if data_cnt = 0 then
|
||||
read_ns <= parity_wait_st;
|
||||
@@ -403,7 +417,14 @@ begin
|
||||
read_ns <= parity_sample_st;
|
||||
end if;
|
||||
when parity_sample_st =>
|
||||
timeout_rx_load_en <= '1';
|
||||
parity_rx_en <= '1';
|
||||
read_ns <= stop_wait_st;
|
||||
if rx_full = '1' then -- buffer full
|
||||
timeval_rx <= time_clock_abort - 1;
|
||||
read_ns <= abort_st;
|
||||
rx_err_set <= '1';
|
||||
end if;
|
||||
when stop_wait_st =>
|
||||
if timeout_rx_flag = '1' then
|
||||
read_ns <= start_wait_st;
|
||||
@@ -423,7 +444,16 @@ begin
|
||||
read_ns <= valid_st;
|
||||
end if;
|
||||
when valid_st =>
|
||||
parity_rx_err_en <= '1';
|
||||
rx_busy <= '0';
|
||||
rx_rdy <= '1';
|
||||
rx_err_clr <= '1';
|
||||
read_ns <= start_wait_st;
|
||||
when abort_st =>
|
||||
rx_abort <= '1';
|
||||
if timeout_rx_flag = '1' then
|
||||
read_ns <= start_wait_st;
|
||||
end if;
|
||||
when others =>
|
||||
read_ns <= start_wait_st;
|
||||
end case;
|
||||
@@ -431,16 +461,15 @@ begin
|
||||
|
||||
-------------------------------------------
|
||||
write_state_output:
|
||||
process(write_cs, en_us, piso_out, parity_tx)
|
||||
process(write_cs, 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';
|
||||
clk_tx <= '1';
|
||||
data_tx <= '1';
|
||||
piso_en <= '0';
|
||||
timeval_tx <= time_clock_assert - 1;
|
||||
data_cnt_tx_en <= '0';
|
||||
@@ -451,45 +480,44 @@ process(write_cs, en_us, piso_out, parity_tx)
|
||||
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';
|
||||
clk_tx <= '0';
|
||||
when tx_start_assert_st =>
|
||||
ps2_clk_tx <= '0';
|
||||
ps2_data_tx <= '0';
|
||||
clk_tx <= '0';
|
||||
data_tx <= '0';
|
||||
when tx_clock_release_st =>
|
||||
ps2_data_tx <= '0';
|
||||
data_tx <= '0';
|
||||
timeout_tx_load_en <= '1';
|
||||
timeval_tx <= timeout_us - 1;
|
||||
when tx_dev_wait_st =>
|
||||
ps2_data_tx <= '0';
|
||||
data_tx <= '0';
|
||||
when tx_dev_trans_st =>
|
||||
ps2_data_tx <= '0';
|
||||
data_tx <= '0';
|
||||
timeout_tx_load_en <= '1';
|
||||
timeval_tx <= timeout_us - 1;
|
||||
when tx_data_wait_st =>
|
||||
ps2_data_tx <= piso_out;
|
||||
data_tx <= piso_out;
|
||||
when tx_data_trans_st =>
|
||||
data_cnt_tx_en <= '1';
|
||||
ps2_data_tx <= piso_out;
|
||||
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;
|
||||
data_tx <= piso_out;
|
||||
when tx_parity_update_st =>
|
||||
parity_tx_en <= '1';
|
||||
ps2_data_tx <= piso_out;
|
||||
data_tx <= piso_out;
|
||||
when tx_parity_sample_st =>
|
||||
ps2_data_tx <= parity_tx;
|
||||
data_tx <= parity_tx;
|
||||
when tx_parity_wait_st =>
|
||||
ps2_data_tx <= parity_tx;
|
||||
data_tx <= parity_tx;
|
||||
when tx_parity_trans_st =>
|
||||
ps2_data_tx <= piso_out;
|
||||
data_tx <= piso_out;
|
||||
timeout_tx_load_en <= '1';
|
||||
timeval_tx <= timeout_us - 1;
|
||||
when tx_valid_st =>
|
||||
|
||||
@@ -35,24 +35,6 @@ 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;
|
||||
@@ -71,6 +53,8 @@ ARCHITECTURE behavior OF tb_ps2_core IS
|
||||
SIGNAL dout_reg : unsigned(7 downto 0);
|
||||
SIGNAL tx_empty : std_logic;
|
||||
SIGNAL rx_present : std_logic;
|
||||
SIGNAL rx_err_flag : std_logic;
|
||||
SIGNAL rx_err_par : std_logic;
|
||||
SIGNAL ps2_clk_i : std_logic := '1';
|
||||
SIGNAL ps2_clk_j : std_logic := '1';
|
||||
SIGNAL ps2_clk_tx : std_logic;
|
||||
@@ -80,7 +64,7 @@ ARCHITECTURE behavior OF tb_ps2_core IS
|
||||
BEGIN
|
||||
|
||||
-- Instantiate the Unit Under Test (UUT)
|
||||
uut: ps2_core
|
||||
uut: entity work.ps2_core
|
||||
PORT MAP
|
||||
(
|
||||
rst => rst,
|
||||
@@ -89,6 +73,8 @@ uut: ps2_core
|
||||
dout => dout,
|
||||
tx_empty => tx_empty,
|
||||
rx_present => rx_present,
|
||||
rx_err_flag => rx_err_flag,
|
||||
rx_err_par => rx_err_par,
|
||||
din_vld => din_vld,
|
||||
read_en => read_en,
|
||||
ps2_clk_rx => ps2_clk_rx,
|
||||
@@ -127,7 +113,7 @@ uut: ps2_core
|
||||
wait for SYSPERIOD/2;
|
||||
END PROCESS;
|
||||
|
||||
read_en <= rx_present;
|
||||
read_en <= rx_present after 1.6 ms;
|
||||
tb_read : PROCESS(clk)
|
||||
BEGIN
|
||||
if rising_edge(clk) then
|
||||
@@ -155,8 +141,9 @@ uut: ps2_core
|
||||
wait for 20*SYSPERIOD;
|
||||
rst <= '0';
|
||||
|
||||
for iter in 1 to 2 loop
|
||||
for iter in 1 to 4 loop
|
||||
-- wait for 2*PS2PERIOD;
|
||||
wait until rising_edge(clk) and ps2_clk_tx = '1';
|
||||
|
||||
--Start bit
|
||||
wait for PS2PERIOD/2;
|
||||
@@ -225,6 +212,9 @@ uut: ps2_core
|
||||
wait for PS2PERIOD/2;
|
||||
ps2_clk_i <= '0';
|
||||
ps2_data_rx <= '1';
|
||||
if iter = 3 then
|
||||
ps2_data_rx <= '0';
|
||||
end if;
|
||||
wait for PS2PERIOD/2;
|
||||
ps2_clk_i <= not ps2_clk_i;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user