- 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:
2009-11-07 12:01:11 +00:00
parent 19f258f351
commit 570b03bca4
2 changed files with 113 additions and 95 deletions
+102 -74
View File
@@ -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 =>
+11 -21
View File
@@ -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;