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, minus_irc, plus_per, correction, plus_irc, save_base, load_irc, minus_base, save_angle, done, compare, compare2); 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 ALU_EN : std_logic; signal ALU_ACK : std_logic; signal ALU_STB : std_logic; signal ALU_N : std_logic; signal ALU_C : std_logic; signal ALU_Z : std_logic; signal ALU_INS : std_logic_vector (1 downto 0); signal ALU_RA : std_logic; signal ALU_RB : std_logic; signal state : state_t; -------------------------------------------------------------------------------- begin ALU_STB <= ALU_EN; alu_1 : entity work.alu port map ( ACK_O => ALU_ACK, CLK_I => CLK_I, RST_I => RST_I, STB_I => ALU_STB, DAT_I => IRF_DAT_I, DAT_O => IRF_DAT_O, N_O => ALU_N, C_O => ALU_C, Z_O => ALU_Z, INSTR_I => ALU_INS, REGA_I => ALU_RA, REGB_I => ALU_RB); 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_ADR_O <= BASE_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '0'; ALU_EN <= '0'; ALU_INS <= "XX"; ALU_RA <= 'X'; ALU_RB <= 'X'; else case state is when ready => IRF_ADR_O <= BASE_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '0'; ALU_EN <= '0'; ALU_INS <= "XX"; ALU_RA <= 'X'; ALU_RB <= 'X'; if STB_I = '1' then state <= minus_irc; IRF_ADR_O <= IRC_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '0'; ALU_EN <= '1'; ALU_INS <= "00"; ALU_RA <= '1'; ALU_RB <= 'X'; end if; when minus_irc => state <= compare; IRF_ADR_O <= (others => 'X'); IRF_STB_O <= '0'; IRF_WE_O <= 'X'; ALU_EN <= '1'; ALU_INS <= "10"; ALU_RA <= '1'; ALU_RB <= 'X'; when compare => IRF_STB_O <= '0'; ALU_EN <= '0'; if ALU_EN = '0' then if ALU_N = '0' and ALU_Z = '0' then state <= correction; IRF_ADR_O <= PER_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '0'; ALU_INS <= "10"; else state <= plus_per; IRF_ADR_O <= PER_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '0'; end if; end if; when plus_per => IRF_STB_O <= '0'; ALU_EN <= '1'; ALU_INS <= "01"; ALU_RA <= '0'; ALU_RB <= 'X'; if ALU_EN = '1' then state <= compare2; ALU_EN <= '0'; end if; when compare2 => if ALU_N = '1' or ALU_Z = '1' then state <= correction; IRF_ADR_O <= PER_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '0'; ALU_INS <= "01"; else state <= plus_irc; IRF_ADR_O <= IRC_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '0'; end if; when correction => state <= plus_irc; IRF_ADR_O <= IRC_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '0'; ALU_EN <= '1'; ALU_RA <= '1'; ALU_RB <= 'X'; when plus_irc => state <= save_base; IRF_STB_O <= '0'; ALU_EN <= '1'; ALU_INS <= "01"; ALU_RA <= 'X'; ALU_RB <= '1'; when save_base => IRF_ADR_O <= BASE_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '1'; ALU_EN <= '0'; ALU_INS <= "XX"; ALU_RA <= 'X'; ALU_RB <= 'X'; if ALU_EN = '0' then state <= load_irc; IRF_ADR_O <= IRC_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '0'; end if; when load_irc => state <= minus_base; IRF_ADR_O <= BASE_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '0'; ALU_EN <= '1'; ALU_INS <= "00"; ALU_RA <= '1'; ALU_RB <= 'X'; when minus_base => state <= save_angle; IRF_STB_O <= '0'; ALU_EN <= '1'; ALU_INS <= "10"; ALU_RA <= 'X'; ALU_RB <= '1'; when save_angle => state <= done; ACK_O <= '1'; IRF_ADR_O <= ANG_ADR; IRF_STB_O <= '1'; IRF_WE_O <= '1'; ALU_EN <= '0'; ALU_INS <= "XX"; ALU_RA <= 'X'; ALU_RB <= 'X'; when done => IRF_ADR_O <= (others => 'X'); IRF_STB_O <= '0'; IRF_WE_O <= 'X'; ALU_EN <= '0'; ALU_INS <= "XX"; ALU_RA <= 'X'; ALU_RB <= 'X'; if STB_I = '0' then state <= ready; ACK_O <= '0'; IRF_ADR_O <= (others => 'X'); IRF_STB_O <= '0'; IRF_WE_O <= 'X'; ALU_EN <= '0'; ALU_INS <= "XX"; ALU_RA <= 'X'; ALU_RB <= 'X'; end if; end case; end if; end if; end process; end architecture behavioral;