- 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
+99 -71
View File
@@ -39,6 +39,8 @@ entity ps2_core is
dout : out unsigned(7 downto 0); dout : out unsigned(7 downto 0);
tx_empty : out std_logic; tx_empty : out std_logic;
rx_present : 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; din_vld : in std_logic;
read_en : in std_logic; read_en : in std_logic;
ps2_clk_rx : 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, data_wait_st, data_trans_st, data_sample_st,
parity_wait_st, parity_trans_st, parity_sample_st, parity_wait_st, parity_trans_st, parity_sample_st,
stop_wait_st, stop_trans_st, stop_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, 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_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 prescaler_us : integer := f_sys_clk_hz/1E6;
constant timeout_us : integer := 15000; constant timeout_us : integer := 15000;
constant time_clock_assert : integer := 120; constant time_clock_assert : integer := 120;
constant time_clock_abort : integer := 500;
-- Signals -- Signals
signal en_us : std_logic; signal en_us : std_logic;
signal timeout_rx_load_en : std_logic; signal timeout_rx_load_en : std_logic;
signal timeout_rx_en : std_logic;
signal timeout_rx_flag : std_logic; signal timeout_rx_flag : std_logic;
signal timeout_tx_load_en : std_logic; signal timeout_tx_load_en : std_logic;
signal timeout_tx_en : std_logic;
signal timeout_tx_flag : std_logic; signal timeout_tx_flag : std_logic;
signal read_cs : line_state_rx_t; signal read_cs : line_state_rx_t;
@@ -101,6 +102,12 @@ signal piso_load_en : std_logic;
signal rx_en : std_logic; signal rx_en : std_logic;
signal tx_en : std_logic; signal tx_en : std_logic;
signal rx_busy : 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 tx_busy : std_logic;
signal rx_rdy : std_logic; signal rx_rdy : std_logic;
signal tx_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 rx_reg : unsigned(7 downto 0);
signal tx_reg : unsigned(7 downto 0); signal tx_reg : unsigned(7 downto 0);
signal parity_rst : std_logic; signal parity_rx_rst : std_logic;
signal parity_en : std_logic; signal parity_rx_en : std_logic;
signal parity : std_logic; signal parity_rx : std_logic;
signal parity_tx_rst : std_logic; signal parity_tx_rst : std_logic;
signal parity_tx_en : std_logic; signal parity_tx_en : std_logic;
signal parity_tx : 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_rx : integer range 0 to timeout_us-1;
signal timeout_count_tx : 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_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 sipo_reg : unsigned(7 downto 0);
signal piso_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 begin
proc_prescaler: proc_prescaler:
@@ -147,13 +159,11 @@ process (clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
if timeout_rx_load_en ='1' then if timeout_rx_load_en ='1' then
timeout_count_rx <= timeout_us - 1; timeout_count_rx <= timeval_rx;
timeout_rx_flag <= '0'; timeout_rx_flag <= '0';
else elsif en_us = '1' then
if (timeout_count_rx /= 0) then if (timeout_count_rx /= 0) then
if timeout_rx_en ='1' then
timeout_count_rx <= timeout_count_rx - 1; timeout_count_rx <= timeout_count_rx - 1;
end if;
else else
timeout_rx_flag <= '1'; timeout_rx_flag <= '1';
end if; end if;
@@ -168,11 +178,9 @@ begin
if timeout_tx_load_en ='1' then if timeout_tx_load_en ='1' then
timeout_count_tx <= timeval_tx; timeout_count_tx <= timeval_tx;
timeout_tx_flag <= '0'; timeout_tx_flag <= '0';
else elsif en_us = '1' then
if (timeout_count_tx /= 0) then if (timeout_count_tx /= 0) then
if timeout_tx_en ='1' then
timeout_count_tx <= timeout_count_tx - 1; timeout_count_tx <= timeout_count_tx - 1;
end if;
else else
timeout_tx_flag <= '1'; timeout_tx_flag <= '1';
end if; end if;
@@ -212,10 +220,28 @@ proc_parity_bitser_rx:
process (clk) process (clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
if parity_rst='1' then if parity_rx_rst='1' then
parity <= '1'; parity_rx <= '1';
elsif parity_en = '1' and ps2_data_rx = '1' then elsif parity_rx_en = '1' and ps2_data_rx = '1' then
parity <= not parity; 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 if; end if;
end process; end process;
@@ -238,18 +264,21 @@ end process;
rx_en <= not tx_busy; rx_en <= not tx_busy;
------------------------------------------- -------------------------------------------
rx_present <= rx_full;
proc_out_reg: proc_out_reg:
process(clk) process(clk)
begin begin
if rising_edge(clk) then if rising_edge(clk) then
ps2_clk_tx <= clk_tx and not rx_abort;
ps2_data_tx <= data_tx;
if rst = '1' then if rst = '1' then
dout <= (others => '0'); dout <= (others => '0');
rx_present <= '0'; rx_full <= '0';
elsif rx_rdy = '1' then elsif rx_rdy = '1' then
dout <= rx_reg; dout <= rx_reg;
rx_present <= '1'; rx_full <= '1';
elsif read_en = '1' then elsif read_en = '1' then
rx_present <= '0'; rx_full <= '0';
end if; end if;
end if; end if;
end process; end process;
@@ -312,57 +341,38 @@ begin
end if; end if;
end process; end process;
------------------------------------------- read_state_decode:
read_state_output: process (read_cs, timeout_rx_flag, rx_en, data_cnt, ps2_data_rx, ps2_clk_rx, rx_full)
process(read_cs, en_us)
begin begin
timeout_rx_load_en <= '0'; timeout_rx_load_en <= '0';
timeout_rx_en <= en_us; timeval_rx <= timeout_us - 1;
data_cnt_en <= '0'; data_cnt_en <= '0';
data_cnt_rst <= '0'; data_cnt_rst <= '0';
sipo_en <= '0'; sipo_en <= '0';
rx_rdy <= '0'; rx_rdy <= '0';
parity_en <= '0'; parity_rx_en <= '0';
parity_rst <= '0'; parity_rx_rst <= '0';
parity_rx_err_en <= '0';
rx_busy <= '1'; rx_busy <= '1';
case (read_cs) is rx_abort <= '0';
when start_wait_st => rx_err_set <= '0';
timeout_rx_load_en <= '1'; rx_err_clr <= '0';
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 --declare default state for next_state to avoid latches
read_ns <= read_cs; --default is to stay in current state read_ns <= read_cs; --default is to stay in current state
--insert statements to decode next_state --insert statements to decode next_state
--below is a simple example --below is a simple example
case (read_cs) is case (read_cs) is
when start_wait_st => 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 if ps2_data_rx = '0' and ps2_clk_rx = '1' and rx_en = '1' then
read_ns <= start_trans_st; read_ns <= start_trans_st;
end if; end if;
when start_trans_st => when start_trans_st =>
data_cnt_rst <= '1';
parity_rx_rst <= '1';
timeout_rx_load_en <= '1';
if timeout_rx_flag = '1' then if timeout_rx_flag = '1' then
read_ns <= start_wait_st; read_ns <= start_wait_st;
elsif ps2_data_rx = '0' and ps2_clk_rx = '0' then elsif ps2_data_rx = '0' and ps2_clk_rx = '0' then
@@ -386,6 +396,10 @@ begin
end if; end if;
-- Data sample -- Data sample
when data_sample_st => 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; read_ns <= data_wait_st;
if data_cnt = 0 then if data_cnt = 0 then
read_ns <= parity_wait_st; read_ns <= parity_wait_st;
@@ -403,7 +417,14 @@ begin
read_ns <= parity_sample_st; read_ns <= parity_sample_st;
end if; end if;
when parity_sample_st => when parity_sample_st =>
timeout_rx_load_en <= '1';
parity_rx_en <= '1';
read_ns <= stop_wait_st; 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 => when stop_wait_st =>
if timeout_rx_flag = '1' then if timeout_rx_flag = '1' then
read_ns <= start_wait_st; read_ns <= start_wait_st;
@@ -423,7 +444,16 @@ begin
read_ns <= valid_st; read_ns <= valid_st;
end if; end if;
when valid_st => when valid_st =>
parity_rx_err_en <= '1';
rx_busy <= '0';
rx_rdy <= '1';
rx_err_clr <= '1';
read_ns <= start_wait_st; 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 => when others =>
read_ns <= start_wait_st; read_ns <= start_wait_st;
end case; end case;
@@ -431,16 +461,15 @@ begin
------------------------------------------- -------------------------------------------
write_state_output: write_state_output:
process(write_cs, en_us, piso_out, parity_tx) process(write_cs, piso_out, parity_tx)
begin begin
timeout_tx_load_en <= '0'; timeout_tx_load_en <= '0';
timeout_tx_en <= en_us;
tx_rdy <= '0'; tx_rdy <= '0';
tx_busy <= '1'; tx_busy <= '1';
piso_load_en <= '0'; piso_load_en <= '0';
ps2_clk_tx <= '1'; clk_tx <= '1';
ps2_data_tx <= '1'; data_tx <= '1';
piso_en <= '0'; piso_en <= '0';
timeval_tx <= time_clock_assert - 1; timeval_tx <= time_clock_assert - 1;
data_cnt_tx_en <= '0'; data_cnt_tx_en <= '0';
@@ -451,45 +480,44 @@ process(write_cs, en_us, piso_out, parity_tx)
when tx_idle_st => when tx_idle_st =>
tx_busy <= '0'; tx_busy <= '0';
timeout_tx_load_en <= '1'; timeout_tx_load_en <= '1';
timeout_tx_en <= '0';
when tx_clock_assert_st => when tx_clock_assert_st =>
parity_tx_rst <= '1'; parity_tx_rst <= '1';
piso_load_en <= '1'; piso_load_en <= '1';
data_cnt_tx_rst <= '1'; data_cnt_tx_rst <= '1';
ps2_clk_tx <= '0'; clk_tx <= '0';
when tx_start_assert_st => when tx_start_assert_st =>
ps2_clk_tx <= '0'; clk_tx <= '0';
ps2_data_tx <= '0'; data_tx <= '0';
when tx_clock_release_st => when tx_clock_release_st =>
ps2_data_tx <= '0'; data_tx <= '0';
timeout_tx_load_en <= '1'; timeout_tx_load_en <= '1';
timeval_tx <= timeout_us - 1; timeval_tx <= timeout_us - 1;
when tx_dev_wait_st => when tx_dev_wait_st =>
ps2_data_tx <= '0'; data_tx <= '0';
when tx_dev_trans_st => when tx_dev_trans_st =>
ps2_data_tx <= '0'; data_tx <= '0';
timeout_tx_load_en <= '1'; timeout_tx_load_en <= '1';
timeval_tx <= timeout_us - 1; timeval_tx <= timeout_us - 1;
when tx_data_wait_st => when tx_data_wait_st =>
ps2_data_tx <= piso_out; data_tx <= piso_out;
when tx_data_trans_st => when tx_data_trans_st =>
data_cnt_tx_en <= '1'; data_cnt_tx_en <= '1';
ps2_data_tx <= piso_out; data_tx <= piso_out;
piso_en <= '1'; piso_en <= '1';
timeout_tx_load_en <= '1'; timeout_tx_load_en <= '1';
timeval_tx <= timeout_us - 1; timeval_tx <= timeout_us - 1;
parity_tx_en <= '1'; parity_tx_en <= '1';
when tx_data_sample_st => when tx_data_sample_st =>
ps2_data_tx <= piso_out; data_tx <= piso_out;
when tx_parity_update_st => when tx_parity_update_st =>
parity_tx_en <= '1'; parity_tx_en <= '1';
ps2_data_tx <= piso_out; data_tx <= piso_out;
when tx_parity_sample_st => when tx_parity_sample_st =>
ps2_data_tx <= parity_tx; data_tx <= parity_tx;
when tx_parity_wait_st => when tx_parity_wait_st =>
ps2_data_tx <= parity_tx; data_tx <= parity_tx;
when tx_parity_trans_st => when tx_parity_trans_st =>
ps2_data_tx <= piso_out; data_tx <= piso_out;
timeout_tx_load_en <= '1'; timeout_tx_load_en <= '1';
timeval_tx <= timeout_us - 1; timeval_tx <= timeout_us - 1;
when tx_valid_st => when tx_valid_st =>
+11 -21
View File
@@ -35,24 +35,6 @@ END tb_ps2_core;
ARCHITECTURE behavior OF tb_ps2_core IS 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 --Constants
constant SYSPERIOD : time := 10 ns; constant SYSPERIOD : time := 10 ns;
constant PS2PERIOD : time := 100 us; constant PS2PERIOD : time := 100 us;
@@ -71,6 +53,8 @@ ARCHITECTURE behavior OF tb_ps2_core IS
SIGNAL dout_reg : unsigned(7 downto 0); SIGNAL dout_reg : unsigned(7 downto 0);
SIGNAL tx_empty : std_logic; SIGNAL tx_empty : std_logic;
SIGNAL rx_present : 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_i : std_logic := '1';
SIGNAL ps2_clk_j : std_logic := '1'; SIGNAL ps2_clk_j : std_logic := '1';
SIGNAL ps2_clk_tx : std_logic; SIGNAL ps2_clk_tx : std_logic;
@@ -80,7 +64,7 @@ ARCHITECTURE behavior OF tb_ps2_core IS
BEGIN BEGIN
-- Instantiate the Unit Under Test (UUT) -- Instantiate the Unit Under Test (UUT)
uut: ps2_core uut: entity work.ps2_core
PORT MAP PORT MAP
( (
rst => rst, rst => rst,
@@ -89,6 +73,8 @@ uut: ps2_core
dout => dout, dout => dout,
tx_empty => tx_empty, tx_empty => tx_empty,
rx_present => rx_present, rx_present => rx_present,
rx_err_flag => rx_err_flag,
rx_err_par => rx_err_par,
din_vld => din_vld, din_vld => din_vld,
read_en => read_en, read_en => read_en,
ps2_clk_rx => ps2_clk_rx, ps2_clk_rx => ps2_clk_rx,
@@ -127,7 +113,7 @@ uut: ps2_core
wait for SYSPERIOD/2; wait for SYSPERIOD/2;
END PROCESS; END PROCESS;
read_en <= rx_present; read_en <= rx_present after 1.6 ms;
tb_read : PROCESS(clk) tb_read : PROCESS(clk)
BEGIN BEGIN
if rising_edge(clk) then if rising_edge(clk) then
@@ -155,8 +141,9 @@ uut: ps2_core
wait for 20*SYSPERIOD; wait for 20*SYSPERIOD;
rst <= '0'; rst <= '0';
for iter in 1 to 2 loop for iter in 1 to 4 loop
-- wait for 2*PS2PERIOD; -- wait for 2*PS2PERIOD;
wait until rising_edge(clk) and ps2_clk_tx = '1';
--Start bit --Start bit
wait for PS2PERIOD/2; wait for PS2PERIOD/2;
@@ -225,6 +212,9 @@ uut: ps2_core
wait for PS2PERIOD/2; wait for PS2PERIOD/2;
ps2_clk_i <= '0'; ps2_clk_i <= '0';
ps2_data_rx <= '1'; ps2_data_rx <= '1';
if iter = 3 then
ps2_data_rx <= '0';
end if;
wait for PS2PERIOD/2; wait for PS2PERIOD/2;
ps2_clk_i <= not ps2_clk_i; ps2_clk_i <= not ps2_clk_i;