library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity ix_resets is
	Port (
		------------------------------------------------------------------------
		-- INTERFACE WITH USER FPGA LOGIC
		------------------------------------------------------------------------

		-- reset outputs
		nReset_ctrl : out std_logic;                          -- active-low, activated when code running and PWM enabled, typically used for PID controller
		nReset_sync : out std_logic;                          -- active-low, asserted when loading user code

		------------------------------------------------------------------------
		-- INTERFACE WITH IMPERIX FIRMWARE IP
		------------------------------------------------------------------------
		
		-- core state
		cpu_core_state : in std_logic_vector(1 downto 0);     -- core state with 0=FAULT ; 1=BLOCKED ; 2=OPERATING
        sync_pulse : in std_logic;                            -- sync pulse, set to 1 for one cycle once the user code is launched

		-- main clock running at 250 MHz
		clk : in std_logic
	);
end ix_resets;

architecture Behavioral of ix_resets is

	ATTRIBUTE X_INTERFACE_INFO : STRING;
	ATTRIBUTE X_INTERFACE_PARAMETER : STRING;
	ATTRIBUTE X_INTERFACE_INFO of clk: SIGNAL is "xilinx.com:signal:clock:1.0 clk CLK";
	
	signal r_cpu_core_state_is_2 : std_logic := '0';
	signal r_cpu_core_state_is_2_prev : std_logic := '0';
	
	signal r_nReset_ctrl_0 : std_logic := '1';
	signal r_nReset_ctrl_1 : std_logic := '1';
	signal r_nReset_ctrl_2 : std_logic := '1';
	signal r_nReset_ctrl_3 : std_logic := '1';
	
	signal r_nReset_sync_0 : std_logic := '1';
	signal r_nReset_sync_1 : std_logic := '1';
	signal r_nReset_sync_2 : std_logic := '1';
	signal r_nReset_sync_3 : std_logic := '1';

begin
	P : process(clk)
	begin
		if rising_edge(clk) then
           r_nReset_ctrl_0 <= '1'; -- default value
           
		   -- 0=FAULT ; 1=BLOCKED ; 2=OPERATING
           if (cpu_core_state = "10") then
                r_cpu_core_state_is_2 <= '1';
           else
                r_cpu_core_state_is_2 <= '0';
           end if;
           
		   -- value stored for comparison with previous state
           r_cpu_core_state_is_2_prev <= r_cpu_core_state_is_2;

           if r_cpu_core_state_is_2 = '1' and r_cpu_core_state_is_2_prev = '0' then
                r_nReset_ctrl_0 <= '0';
           end if;
           
           -- delay for nReset_ctrl
           r_nReset_ctrl_1 <= r_nReset_ctrl_0;
           r_nReset_ctrl_2 <= r_nReset_ctrl_1;
           r_nReset_ctrl_3 <= r_nReset_ctrl_2;
           
           -- delay for nReset_sync
           r_nReset_sync_0 <= not sync_pulse;
           r_nReset_sync_1 <= r_nReset_sync_0;
           r_nReset_sync_2 <= r_nReset_sync_1;
           r_nReset_sync_3 <= r_nReset_sync_2;
        end if;
    end process P;

   -- resets are asserted for 4 clock cycles
   nReset_ctrl <= r_nReset_ctrl_0 and r_nReset_ctrl_1 and r_nReset_ctrl_2 and r_nReset_ctrl_3;
   nReset_sync <= r_nReset_sync_0 and r_nReset_sync_1 and r_nReset_sync_2 and r_nReset_sync_3;

end Behavioral;
