+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;
+ 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;
+ IRF_WE_O : out std_logic;
+ -- 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;
+ 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;
+