library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; -------------------------------------------------------------------------------- entity irc_base is generic ( IRF_ADR_W : integer := 5; BASE : integer := 0; IRC_OFF : integer := 1; ABASE_OFF : integer := 2; APER_OFF : integer := 3; A_OFF : integer := 4); port ( -- Primary slave interface ACK_O : out std_logic := '0'; CLK_I : in std_logic; RST_I : in std_logic; STB_I : in std_logic; -- Master interface to the interface memory IRF_ACK_I : in std_logic; IRF_ADR_O : out std_logic_vector (IRF_ADR_W-1 downto 0); IRF_DAT_I : in std_logic_vector (15 downto 0); IRF_DAT_O : out std_logic_vector (15 downto 0); IRF_STB_O : out std_logic := '0'; IRF_WE_O : out std_logic := '0'; -- Error flag BAD_BASE : out std_logic); end entity irc_base; -------------------------------------------------------------------------------- architecture behavioral of irc_base is type state_t is (ready, nop, load_irc, load_base, load_per, do_correction, save, done); subtype irf_adr_t is std_logic_vector (IRF_ADR_W-1 downto 0); constant IRC_ADR : irf_adr_t := conv_std_logic_vector(BASE+IRC_OFF, IRF_ADR_W); constant BASE_ADR : irf_adr_t := conv_std_logic_vector(BASE+ABASE_OFF, IRF_ADR_W); constant PER_ADR : irf_adr_t := conv_std_logic_vector(BASE+APER_OFF, IRF_ADR_W); constant ANG_ADR : irf_adr_t := conv_std_logic_vector(BASE+A_OFF, IRF_ADR_W); signal state : state_t := ready; signal irc : std_logic_vector (15 downto 0); signal irc_base : std_logic_vector (15 downto 0); signal irc_per : std_logic_vector (15 downto 0); signal angle : std_logic_vector (15 downto 0); signal new_base : std_logic_vector (15 downto 0); signal lower : std_logic; signal higher : std_logic; -------------------------------------------------------------------------------- begin BAD_BASE <= '1' when state = save and (lower = '1' or higher = '1') else '0'; lower <= angle (angle'HIGH); higher <= '1' when angle >= irc_per and lower = '0' else '0'; angle <= irc - irc_base; new_base <= irc_base - irc_per when lower = '1' else irc_base + irc_per when higher = '1' else irc_base; FSM : process (CLK_I) is begin if rising_edge(CLK_I) then if RST_I = '1' or STB_I = '0' then state <= ready; ACK_O <= '0'; IRF_STB_O <= '0'; IRF_WE_O <= '0'; else case state is when ready => if STB_I = '1' then state <= nop; IRF_ADR_O <= IRC_ADR; IRF_STB_O <= '1'; end if; when nop => state <= load_irc; IRF_ADR_O <= BASE_ADR; when load_irc => state <= load_base; irc <= IRF_DAT_I; IRF_ADR_O <= PER_ADR; when load_base => state <= load_per; irc_base <= IRF_DAT_I; when load_per => state <= do_correction; irc_per <= IRF_DAT_I; IRF_STB_O <= '0'; when do_correction => state <= save; irc_base <= new_base; IRF_ADR_O <= BASE_ADR; IRF_DAT_O <= new_base; IRF_STB_O <= '1'; IRF_WE_O <= '1'; when save => state <= done; IRF_ADR_O <= ANG_ADR; IRF_DAT_O <= angle; ACK_O <= '1'; when done => IRF_STB_O <= '0'; IRF_WE_O <= '0'; if STB_I = '0' then state <= ready; ACK_O <= '0'; end if; end case; end if; end if; end process; end architecture behavioral;