library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; use work.lx_rocon_pkg.all; -- Quadcounter (for IRC) entity qcounter is port ( -- Inputs clk_i : in std_logic; reset_i : in std_logic; a0_i, b0_i : in std_logic; index0_i : in std_logic; -- State reset_index_event_i : in std_logic; reset_index_event2_i : in std_logic; reset_ab_error_i : in std_logic; -- Outputs qcount_o : out std_logic_vector (7 downto 0); qcount_index_o : out std_logic_vector (7 downto 0); index_o : out std_logic; index_event_o : out std_logic; index_event2_o : out std_logic; a_rise_o, a_fall_o : out std_logic; b_rise_o, b_fall_o : out std_logic; ab_event_o : out std_logic; ab_error_o : out std_logic ); end qcounter; architecture behavioral of qcounter is signal last_reset_s : std_logic; signal a_s, b_s : std_logic; signal a_prev_s, b_prev_s : std_logic; signal ab_error_s : std_logic; signal ab_error_int_s : std_logic; signal index_event_int_s : std_logic; signal index_event2_int_s : std_logic; signal index_s : std_logic; signal index_prev_s : std_logic; signal count_prev_s : std_logic_vector (5 downto 0); signal count_s : std_logic_vector (5 downto 0); signal count_out_s : std_logic_vector (7 downto 0); signal count_index_s : std_logic_vector (7 downto 0); begin dff_a: dff3 port map ( clk_i => clk_i, d_i => a0_i, q_o => a_s ); dff_b: dff3 port map ( clk_i => clk_i, d_i => b0_i, q_o => b_s ); dff_index: dff3 port map ( clk_i => clk_i, d_i => index0_i, q_o => index_s ); count_out_s(0) <= a_s xor b_s; count_out_s(1) <= b_s; count_out_s(7 downto 2) <= count_s; -- qcount_o <= count_out_s; qcount_index_o <= count_index_s; -- ab_error_o <= ab_error_int_s; index_o <= index_s; index_event_o <= index_event_int_s; index_event2_o <= index_event2_int_s; comb_event: process (reset_i, last_reset_s, a_prev_s, b_prev_s, a_s, b_s) begin a_rise_o <= '0'; a_fall_o <= '0'; b_rise_o <= '0'; b_fall_o <= '0'; ab_event_o <= '0'; ab_error_s <= '0'; if reset_i = '0' and last_reset_s = '0' then if ((a_s xor a_prev_s) and (b_s xor b_prev_s)) = '1' then -- forbidden double transition ab_error_s <= '1'; ab_event_o <= '0'; else a_rise_o <= (a_s xor a_prev_s) and a_s; a_fall_o <= (a_s xor a_prev_s) and (not a_s); b_rise_o <= (b_s xor b_prev_s) and b_s; b_fall_o <= (b_s xor b_prev_s) and (not b_s); ab_event_o <= (a_s xor a_prev_s) or (b_s xor b_prev_s); end if; end if; end process; comb_count: process (reset_i, last_reset_s, a_prev_s, b_prev_s, a_s, b_s, index_s, count_prev_s) begin if reset_i = '1' or last_reset_s = '1' then count_s <= count_prev_s; elsif (a_prev_s = '0') and (b_prev_s = '1') and (a_s = '0') and (b_s = '0') then count_s <= count_prev_s + 1; elsif (a_prev_s = '0') and (b_prev_s = '0') and (a_s = '0') and (b_s = '1') then count_s <= count_prev_s - 1; else count_s <= count_prev_s; end if; end process; seq: process variable index_event_v : std_logic; begin -- Reset for qcounter is synchronous and lasts at least one more cycle -- to prevent hazardous states after releasing it wait until clk_i'event and clk_i = '1'; index_event_v := '0'; if reset_i = '1' then count_prev_s <= (others => '0'); count_index_s <= (others => '0'); index_event_int_s <= '0'; index_event2_int_s <= '0'; ab_error_int_s <= '0'; index_prev_s <= '1'; else if index_s = '1' and index_prev_s = '0' then count_index_s <= count_out_s; index_event_v := '1'; end if; -- if reset_index_event_i = '1' then index_event_int_s <= '0'; else index_event_int_s <= index_event_int_s or index_event_v; end if; -- if reset_index_event2_i = '1' then index_event2_int_s <= '0'; else index_event2_int_s <= index_event2_int_s or index_event_v; end if; -- if reset_ab_error_i = '1' then ab_error_int_s <= '0'; else ab_error_int_s <= ab_error_int_s or ab_error_s; end if; -- count_prev_s <= count_s; index_prev_s <= index_s; end if; a_prev_s <= a_s; b_prev_s <= b_s; last_reset_s <= reset_i; end process; end behavioral;