--- /dev/null
+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;
+
+library UNISIM;
+use UNISIM.VCOMPONENTS.all;
+
+entity etrax_interface is
+ generic(
+ STATUS_REGISTERS : integer := 4;
+ CONTROL_REGISTERS : integer := 4
+ );
+ port (
+ CLK : in std_logic;
+ RESET : in std_logic;
+ --Connection to Etrax
+ ETRAX_DATA_BUS_B : out std_logic_vector(17 downto 0);
+ ETRAX_DATA_BUS_C : inout std_logic_vector(17 downto 0);
+ ETRAX_BUS_BUSY : out std_logic;
+ ETRAX_IS_READY_TO_READ : out std_logic;
+ --Connection to internal FPGA logic (all addresses above 0x100)
+ INTERNAL_DATA_OUT : out std_logic_vector(31 downto 0);
+ INTERNAL_DATA_IN : in std_logic_vector(31 downto 0);
+ INTERNAL_READ_OUT : out std_logic;
+ INTERNAL_WRITE_OUT : out std_logic;
+ INTERNAL_DATAREADY_IN : in std_logic;
+ INTERNAL_ADDRESS_OUT : out std_logic_vector(15 downto 0);
+ --Easy-to-use status and control registers (Addresses 0-15 (stat) and 16-31 (ctrl)
+ FPGA_REGISTER_IN : in std_logic_vector(STATUS_REGISTERS*32-1 downto 0);
+ FPGA_REGISTER_OUT : out std_logic_vector(CONTROL_REGISTERS*32-1 downto 0);
+ --Reset FPGA via Etrax
+ EXTERNAL_RESET : out std_logic
+ );
+end etrax_interface;
+architecture etrax_interface of etrax_interface is
+
+ component signal_sync is
+ generic(
+ WIDTH : integer := 2; --
+ DEPTH : integer := 1
+ );
+ port(
+ RESET : in std_logic; --Reset is neceessary to avoid optimization to shift register
+ CLK0 : in std_logic; --clock for first FF
+ CLK1 : in std_logic; --Clock for other FF
+ D_IN : in std_logic_vector(WIDTH-1 downto 0); --Data input
+ D_OUT : out std_logic_vector(WIDTH-1 downto 0) --Data output
+ );
+ end component;
+
+ type ETRAX_RW_STATE_MACHINE is (IDLE, SAVE_ADDRESS_1, SAVE_ADDRESS_2, SAVE_DATA_1 ,SAVE_DATA_2 , SEND_DATA_1, SEND_ZERO, SEND_DATA_2, WAIT_FOR_DATA, SAVING_EXTERNAL_DATA, SEND_VALID, SEND_EXTERNAL_TRIGGER );
+ signal ETRAX_RW_STATE_currentstate,ETRAX_RW_STATE_nextstate : ETRAX_RW_STATE_MACHINE;
+
+ signal etrax_trigger_pulse : std_logic;
+ signal saved_rw_mode : std_logic_vector(17 downto 0);
+ signal saved_address : std_logic_vector (15 downto 0);
+ signal saved_data : std_logic_vector(31 downto 0);
+ signal saved_data_fpga : std_logic_vector(31 downto 0);
+
+ signal read_cycle : std_logic;
+ signal write_cycle : std_logic;
+
+ signal etrax_is_ready_to_read_i : std_logic;
+ signal internal_reset_i : std_logic;
+ signal communication_state : std_logic_vector(3 downto 0);
+ signal buf_FPGA_REGISTER_OUT : std_logic_vector(CONTROL_REGISTERS*32-1 downto 0);
+ signal reg_BUSC, last_BUSC : std_logic_vector(1 downto 0);
+
+begin
+ MAKE_RESET: process (CLK)
+ begin
+ if rising_edge(CLK) then
+ if (ETRAX_DATA_BUS_C(16)='1' and ETRAX_DATA_BUS_C(17)='1') then
+ internal_reset_i <= '1';
+ elsif ETRAX_DATA_BUS_C(16)='0' and ETRAX_DATA_BUS_C(17)='0' then
+ internal_reset_i <= '0';
+ else
+ internal_reset_i <= '0';
+ end if;
+ end if;
+ end process MAKE_RESET;
+
+ BUSC_SYNC : signal_sync
+ port map(
+ RESET => RESET,
+ CLK0 => CLK,
+ CLK1 => CLK,
+ D_IN => ETRAX_DATA_BUS_C(17 downto 16),
+ D_OUT => reg_BUSC
+ );
+
+ process(CLK)
+ begin
+ if rising_edge(CLK) then
+ last_BUSC <= reg_BUSC;
+ etrax_trigger_pulse <= '0';
+ etrax_is_ready_to_read_i <= '0';
+ if (not last_BUSC(0) and reg_BUSC(0)) = '1' then
+ etrax_trigger_pulse <= '1';
+ end if;
+ if (not last_BUSC(1) and reg_BUSC(1)) = '1' then
+ etrax_is_ready_to_read_i <= '1';
+ end if;
+ end if;
+ end process;
+
+
+ EXTERNAL_RESET <= internal_reset_i;
+ ETRAX_BUS_BUSY <= '0' when ETRAX_RW_STATE_currentstate = IDLE else '1';
+ ETRAX_IS_READY_TO_READ <= etrax_is_ready_to_read_i;
+
+ read_cycle <= saved_rw_mode(15);
+ write_cycle <= not saved_rw_mode(15);
+
+
+ ETRAX_FPGA_COMUNICATION_CLOCK : process (CLK)
+ begin
+ if rising_edge(CLK) then
+ if internal_reset_i = '1' then
+ ETRAX_RW_STATE_currentstate <= IDLE;
+ else
+ ETRAX_RW_STATE_currentstate <= ETRAX_RW_STATE_nextstate;
+ end if;
+ end if;
+ end process ETRAX_FPGA_COMUNICATION_CLOCK;
+
+ ETRAX_FPGA_COMUNICATION: process (ETRAX_RW_STATE_currentstate,etrax_trigger_pulse,
+ saved_rw_mode(15), read_cycle, write_cycle,
+ INTERNAL_DATAREADY_IN, saved_address)
+ begin
+ communication_state <= x"1";
+ ETRAX_RW_STATE_nextstate <= ETRAX_RW_STATE_currentstate;
+ case ETRAX_RW_STATE_currentstate is
+ when IDLE =>
+ communication_state <= x"1";
+ if etrax_trigger_pulse = '1' then
+ ETRAX_RW_STATE_nextstate <= SAVE_ADDRESS_1;
+ end if;
+
+ when SAVE_ADDRESS_1 =>
+ communication_state <= x"2";
+ if etrax_trigger_pulse = '1' then
+ ETRAX_RW_STATE_nextstate <= SAVE_ADDRESS_2;
+ end if;
+
+ when SAVE_ADDRESS_2 =>
+ communication_state <= x"3";
+ if etrax_trigger_pulse = '1' then
+ if read_cycle = '1' then
+ ETRAX_RW_STATE_nextstate <= SEND_EXTERNAL_TRIGGER;
+ else
+ ETRAX_RW_STATE_nextstate <= SAVE_DATA_1;
+ end if;
+ end if;
+
+ when SAVE_DATA_1 =>
+ communication_state <= x"4";
+ if etrax_trigger_pulse = '1' then
+ ETRAX_RW_STATE_nextstate <= SAVE_DATA_2;
+ end if;
+
+ when SAVE_DATA_2 =>
+ communication_state <= x"5";
+ if etrax_trigger_pulse = '1' then
+ ETRAX_RW_STATE_nextstate <= SEND_EXTERNAL_TRIGGER;
+ end if;
+
+ when SEND_EXTERNAL_TRIGGER =>
+ ETRAX_RW_STATE_nextstate <= WAIT_FOR_DATA;
+
+ when WAIT_FOR_DATA =>
+ communication_state <= x"6";
+ if write_cycle = '1' then
+ ETRAX_RW_STATE_nextstate <= SEND_VALID;
+ elsif INTERNAL_DATAREADY_IN = '1' or saved_address(15 downto 8) = 0 then
+ ETRAX_RW_STATE_nextstate <= SAVING_EXTERNAL_DATA;
+ end if;
+
+ when SEND_VALID =>
+ communication_state <= x"7";
+ if etrax_trigger_pulse = '1' then
+ ETRAX_RW_STATE_nextstate <= IDLE;
+ end if;
+
+ when SAVING_EXTERNAL_DATA =>
+ ETRAX_RW_STATE_nextstate <= SEND_DATA_1;
+
+ when SEND_DATA_1 =>
+ communication_state <= x"8";
+ if etrax_trigger_pulse = '1' then
+ ETRAX_RW_STATE_nextstate <= SEND_ZERO;
+ end if;
+
+ when SEND_ZERO =>
+ communication_state <= x"a";
+ if etrax_trigger_pulse = '1' then
+ ETRAX_RW_STATE_nextstate <= SEND_DATA_2;
+ end if;
+
+ when SEND_DATA_2 =>
+ communication_state <= x"9";
+ if etrax_trigger_pulse = '1' then
+ ETRAX_RW_STATE_nextstate <= IDLE;
+ end if;
+ end case;
+ end process ETRAX_FPGA_COMUNICATION;
+
+ REGISTER_ETRAX_BUS: process (CLK)
+ begin
+ if rising_edge(CLK) then
+ if internal_reset_i = '1' then
+ saved_rw_mode <= (others => '0');
+ saved_address <= (others => '0');
+ saved_data <= (others => '0');
+ elsif ETRAX_RW_STATE_currentstate = IDLE and etrax_trigger_pulse = '1' then
+ saved_rw_mode <= ETRAX_DATA_BUS_C;
+ elsif ETRAX_RW_STATE_currentstate = SAVE_ADDRESS_2 and etrax_trigger_pulse = '1' then
+ saved_address(15 downto 0) <= ETRAX_DATA_BUS_C(15 downto 0);
+ elsif ETRAX_RW_STATE_currentstate = SAVE_DATA_1 and etrax_trigger_pulse = '1' then
+ saved_data(31 downto 16) <= ETRAX_DATA_BUS_C(15 downto 0);
+ elsif ETRAX_RW_STATE_currentstate = SAVE_DATA_2 and etrax_trigger_pulse = '1' then
+ saved_data(15 downto 0) <= ETRAX_DATA_BUS_C(15 downto 0);
+ end if;
+ end if;
+ end process REGISTER_ETRAX_BUS;
+
+
+ INTERNAL_ADDRESS_OUT <= saved_address;
+ INTERNAL_DATA_OUT <= saved_data;
+
+ INTERNAL_WRITE_OUT <= '1' when write_cycle = '1' and saved_address(15 downto 8) /= 0 and ETRAX_RW_STATE_currentstate = SEND_EXTERNAL_TRIGGER else '0';
+ INTERNAL_READ_OUT <= '1' when read_cycle = '1' and saved_address(15 downto 8) /= 0 and ETRAX_RW_STATE_currentstate = SEND_EXTERNAL_TRIGGER else '0';
+
+ FPGA_REGISTER_OUT <= buf_FPGA_REGISTER_OUT;
+
+ ETRAX_DATA_BUS_CHOOSE : process (CLK)
+ begin
+ if rising_edge(CLK) then
+ if internal_reset_i = '1' then
+ ETRAX_DATA_BUS_B(16 downto 0) <= "0"& x"0000";--(others => 'Z');
+ elsif ETRAX_RW_STATE_currentstate = SEND_DATA_1 then
+ ETRAX_DATA_BUS_B(15 downto 0) <= saved_data_fpga(31 downto 16);--fpga_register_07_i(15 downto 0);--
+ ETRAX_DATA_BUS_B(16) <= '1';
+ elsif ETRAX_RW_STATE_currentstate = SEND_DATA_2 or ETRAX_RW_STATE_currentstate = SEND_VALID then
+ ETRAX_DATA_BUS_B(15 downto 0) <= saved_data_fpga(15 downto 0);--fpga_register_07_i(15 downto 0);--
+ ETRAX_DATA_BUS_B(16) <= '1';
+ else
+ ETRAX_DATA_BUS_B(16 downto 0) <= "0"& x"0000";
+ end if;
+ end if;
+ end process ETRAX_DATA_BUS_CHOOSE;
+
+ ETRAX_DATA_BUS_B(17) <= '1';
+ ETRAX_DATA_BUS_C <= (others => 'Z');
+
+ DATA_SOURCE_SELECT : process (CLK)
+ variable stat_num : integer range 0 to STATUS_REGISTERS-1;
+ variable ctrl_num : integer range 0 to CONTROL_REGISTERS-1;
+ begin
+ if rising_edge(CLK) then
+ stat_num := conv_integer(saved_address(3 downto 0));
+ ctrl_num := conv_integer(saved_address(3 downto 0));
+ case saved_rw_mode(7 downto 0) is
+ when x"00" =>
+ if saved_rw_mode(15) = '1' then
+ if saved_address(15 downto 8) = 0 then
+ if saved_address(7 downto 4) = 0 then --status regs
+ saved_data_fpga <= FPGA_REGISTER_IN((stat_num)*32+31 downto stat_num*32);
+ elsif saved_address(4) = '1' then
+ saved_data_fpga <= buf_FPGA_REGISTER_OUT((ctrl_num)*32+31 downto (ctrl_num)*32);
+ else
+ saved_data_fpga <= (others => '0');
+ end if;
+ elsif INTERNAL_DATAREADY_IN = '1' then
+ saved_data_fpga <= INTERNAL_DATA_IN;
+ end if;
+ elsif saved_rw_mode(15) = '0' and ETRAX_RW_STATE_currentstate = WAIT_FOR_DATA then
+ buf_FPGA_REGISTER_OUT((ctrl_num+1)*32-1 downto (ctrl_num)*32) <= saved_data;
+ end if;
+ when others =>
+ saved_data_fpga <= x"deadface";
+ end case;
+ end if;
+ end process DATA_SOURCE_SELECT;
+end architecture;