diff --git a/lib/ps2_port/src/ps2_core.vhd b/lib/ps2_port/src/ps2_core.vhd index 5beb50e..d6d749f 100644 --- a/lib/ps2_port/src/ps2_core.vhd +++ b/lib/ps2_port/src/ps2_core.vhd @@ -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 => diff --git a/lib/ps2_port/src/tb_ps2_core.vhd b/lib/ps2_port/src/tb_ps2_core.vhd index e013fba..b2aa534 100644 --- a/lib/ps2_port/src/tb_ps2_core.vhd +++ b/lib/ps2_port/src/tb_ps2_core.vhd @@ -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;