--- /dev/null
+library IEEE;
+use IEEE.STD_LOGIC_UNSIGNED.ALL;
+library UNISIM;
+use UNISIM.VCOMPONENTS.all;
+library ieee;
+library work;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.all;
+
+entity vulom_interface is
+ generic (
+ TRBNET_ENABLE : positive
+ );
+ port (
+ CLK : in std_logic;
+ DATA_CLK : in std_logic;
+ RESET : in std_logic;
+ DATA_IN : in std_logic_vector(1 downto 0);
+ BUSY : out std_logic;
+ ACK_TO_VULOM : out std_logic;
+ ERR_TO_VULOM : out std_logic;
+ API_DATA : out std_logic_vector(47 downto 0);
+ API_RUN_OUT : in std_logic;
+ API_SHORT_TRANSFER : out std_logic;
+ API_DTYPE : out std_logic_vector(3 downto 0);
+ API_SEND : out std_logic;
+ API_WRITE_IN : out std_logic;
+ API_TARGET_ADDRESS : out std_logic_vector(15 downto 0);
+ API_SEQNR_OUT : in std_logic_vector(7 downto 0);
+ VULOM_INT_REG : out std_logic_vector(31 downto 0);
+ INTERFACE_CONTROL : in std_logic_vector(3 downto 0);
+ EVENT_OUT : out std_logic_vector(31 downto 0);
+ EVENT_VALID : out std_logic;
+ EVENT_READOUT_START : in std_logic;
+ EVENT_READOUT_END : out std_logic;
+ START_READOUT : out std_logic;
+ LVL1_TRANSFER_BUSY : in std_logic
+ );
+end vulom_interface;
+
+architecture vulom_interface of vulom_interface is
+ component edge_to_pulse
+ port (
+ clock : in std_logic;
+ en_clk : in std_logic;
+ signal_in : in std_logic;
+ pulse : out std_logic
+ );
+ end component;
+ type VULOM_TO_API is (IDLE, SEND_TRIGGER_a,SEND_TRIGGER_b,SEND_TRIGGER_c,
+ WAIT_FOR_END_BUSY,TRIGGER_MISSMATCH);
+ signal VULOM_TO_API_current,VULOM_TO_API_next : VULOM_TO_API;
+ type CHECK_TRANSMITION is (IDLE, CHECK_1, CHECK_2, CHECK_3 , WAIT_FOR_END, CHECK_SUM, SEND_ERROR, SEND_ACK_1, SEND_ACK_2 );
+ signal CHECK_current, CHECK_next : CHECK_TRANSMITION;
+ signal trigger_code : std_logic_vector(3 downto 0);
+ signal trigger_tag : std_logic_vector(15 downto 0);
+ signal api_ready_pulse : std_logic;
+ signal vulom_interface_debug : std_logic_vector(7 downto 0);
+ signal trigger_pulse : std_logic;
+ signal trigger_error : std_logic;
+ signal trigger_counter : std_logic_vector(15 downto 0);
+ signal not_api_run_out : std_logic;
+ signal data_trigg : std_logic;
+ signal fast_trigg : std_logic;
+ signal data_trigg_pulse : std_logic;
+ type event_register_array is array (10 downto 0) of std_logic_vector(31 downto 0);
+ signal event_register : event_register_array;
+ type vulom_data is array (160 downto 0) of std_logic_vector(1 downto 0);
+-- signal v_data : vulom_data;
+ signal v_data : std_logic_vector(321 downto 0);
+ signal busy_i : std_logic;
+ signal data_clock_counter : std_logic_vector(7 downto 0):=x"00";
+ signal not_transfer_busy : std_logic;
+ signal not_transfer_busy_pulse : std_logic;
+ signal err : std_logic;
+ signal ack : std_logic;
+ signal seq_ok : std_logic;
+ signal err_counter : std_logic_vector(3 downto 0);
+ signal ack_counter : std_logic_vector(3 downto 0);
+ signal check_sum_ok : std_logic;
+ signal not_event_valid : std_logic;
+ signal event_end_pulse : std_logic;
+
+begin
+ trigger_code <= "00" & v_data(1 downto 0);
+ trigger_tag <= v_data(17 downto 2);
+ API_WRITE_IN <= '0';
+ API_DATA <= (others => '0');
+ API_DTYPE <= trigger_code;
+ API_TARGET_ADDRESS <= x"FFFF";
+ API_SHORT_TRANSFER <= '1';
+ not_api_run_out <= not API_RUN_OUT;
+ check_sum_ok <= '1'; --for crc
+
+
+ -------------------------------------------------------------------------------
+ --to check begin sequence and send ACK(after full data transfer) to Vulom
+ -------------------------------------------------------------------------------
+ CHECK_BEG_SEQUENCE : process (CLK, RESET)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ CHECK_current <= IDLE;
+ else
+ CHECK_current <= CHECK_next;
+ end if;
+ end if;
+ end process CHECK_BEG_SEQUENCE;
+
+ CHECK_BEG_SEQUENCE_FSM: process (CLK, DATA_CLK, DATA_IN, check_sum_ok,fast_trigg ,trigger_pulse,trigger_counter,trigger_tag, api_ready_pulse)
+ begin
+ case (CHECK_current) is
+ when IDLE =>
+ vulom_interface_debug(7 downto 4) <=x"1";
+ seq_ok <= '0';
+ ack <= '0';
+ err <= '0';
+ if rising_edge(DATA_CLK) then
+ if DATA_IN(0)='1' and DATA_IN(1)='0' then
+ CHECK_next <= CHECK_1;
+ else
+ CHECK_next <= IDLE;
+ end if;
+ end if;
+ when CHECK_1 =>
+ vulom_interface_debug(7 downto 4) <=x"2";
+ seq_ok <= '0';
+ ack <= '0';
+ err <= '0';
+ if rising_edge(DATA_CLK) then
+ if DATA_IN(0)='0' and DATA_IN(1)='1' then
+ CHECK_next <= CHECK_2;
+ else
+ CHECK_next <= IDLE;
+ end if;
+ end if;
+ when CHECK_2 =>
+ vulom_interface_debug(7 downto 4) <=x"3";
+ seq_ok <= '0';
+ ack <= '0';
+ err <= '0';
+ if rising_edge(DATA_CLK) then
+ if DATA_IN(0)='1' and DATA_IN(1)='0' then
+ CHECK_next <= CHECK_3;
+ else
+ CHECK_next <= IDLE;
+ end if;
+ end if;
+ when CHECK_3 =>
+ vulom_interface_debug(7 downto 4) <=x"4";
+ seq_ok <= '0';
+ ack <= '0';
+ err <= '0';
+ if rising_edge(DATA_CLK) then
+ if DATA_IN(0)='0' and DATA_IN(1)='1' then
+ CHECK_next <= WAIT_FOR_END;
+ else
+ CHECK_next <= IDLE;
+ end if;
+ end if;
+ when WAIT_FOR_END =>
+ vulom_interface_debug(7 downto 4) <=x"5";
+ seq_ok <= '1';
+ ack <= '0';
+ if data_clock_counter = 161 then
+ CHECK_next <= CHECK_SUM;
+ end if;
+ when CHECK_SUM =>
+ vulom_interface_debug(7 downto 4) <=x"6";
+ seq_ok <= '0';
+ ack <= '0';
+ err <= '0';
+-- if check_sum_ok = '0' then
+-- CHECK_next <= SEND_ERROR;
+-- else
+ CHECK_next <= SEND_ACK_1;
+-- end if;
+ when SEND_ACK_1 =>
+ vulom_interface_debug(7 downto 4) <=x"7";
+ seq_ok <= '0';
+ ack <= '0';
+ err <= '0';
+-- if not_transfer_busy_pulse = '1' then
+ if VULOM_TO_API_current = IDLE then
+ CHECK_next <= SEND_ACK_2;
+ else
+ CHECK_next <= SEND_ACK_1;
+ end if;
+ when SEND_ACK_2 =>
+ vulom_interface_debug(7 downto 4) <=x"8";
+ seq_ok <= '0';
+ ack <= '1';
+ err <= '0';
+ if ack_counter = 15 then
+ CHECK_next <= IDLE;
+ else
+ CHECK_next <= SEND_ACK_2;
+ end if;
+ when SEND_ERROR =>
+ vulom_interface_debug(7 downto 4) <=x"9";
+ seq_ok <= '0';
+ ack <= '0';
+ err <= '1';
+ if err_counter = x"f" then
+ CHECK_next <= IDLE;
+ else
+ CHECK_next <= SEND_ERROR;
+ end if;
+ when others =>
+ vulom_interface_debug(7 downto 4) <=x"a";
+ CHECK_next <= IDLE;
+ end case;
+ end process CHECK_BEG_SEQUENCE_FSM;
+
+ ACK_TO_VULOM <= ack;
+ ERR_TO_VULOM <= err;
+
+ ERR_COUNTER_CLK: process (CLK, RESET)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' or CHECK_current = IDLE then
+ err_counter <= x"0";
+ elsif CHECK_current = SEND_ERROR then
+ err_counter <= err_counter + 1;
+ else
+ err_counter <= err_counter;
+ end if;
+ end if;
+ end process ERR_COUNTER_CLK;
+
+ ACK_COUNTER_CLK: process (CLK, RESET)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' or CHECK_current = IDLE then
+ ack_counter <= x"0";
+ elsif CHECK_current = SEND_ACK_2 then
+ ack_counter <= ack_counter + 1;
+ else
+ ack_counter <= ack_counter;
+ end if;
+ end if;
+ end process ACK_COUNTER_CLK;
+
+ --2 bits to vector
+ SAVE_VULOM_DATA: process (DATA_CLK, seq_ok)
+ variable vulom_data_array_counter : integer:=0;
+ begin
+ if rising_edge (DATA_CLK) then
+ if vulom_data_array_counter = 161 then
+ vulom_data_array_counter := 0;
+ data_clock_counter <= (others => '0');
+ elsif seq_ok = '1' then
+ vulom_data_array_counter := vulom_data_array_counter + 1;
+ v_data(vulom_data_array_counter*2+1 downto vulom_data_array_counter*2) <= DATA_IN(1 downto 0);
+ data_clock_counter <= data_clock_counter + 1;
+ end if;
+ end if;
+ end process SAVE_VULOM_DATA;
+
+
+ API_READY_PULSER : edge_to_pulse
+ port map (
+ clock => CLK,
+ en_clk => '1',
+ signal_in => not_api_run_out,
+ pulse => api_ready_pulse);
+
+ data_trigg <= '1' when CHECK_current = SEND_ACK_1 else '0'; --160
+
+ FAST_TRIGG_PULSER : edge_to_pulse
+ port map (
+ clock => CLK,
+ en_clk => '1',
+ signal_in => data_trigg,
+ pulse => data_trigg_pulse);
+
+ SYNCH_START: process (CLK, RESET)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ START_READOUT <= '0';
+ else
+ START_READOUT <= data_trigg_pulse;
+ end if;
+ end if;
+ end process SYNCH_START;
+
+ SEND_EVENT: process (CLK, RESET)
+ variable WORD_NUMBER : integer := 0;
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' or EVENT_READOUT_START = '1' then
+ WORD_NUMBER := 0;
+ not_event_valid <= '0';
+ EVENT_VALID <= '0';
+ elsif WORD_NUMBER < 11 then
+ WORD_NUMBER := WORD_NUMBER + 1;
+ EVENT_OUT <= v_data((WORD_NUMBER+1)*32-1 +2 downto WORD_NUMBER*32 + 2);
+ EVENT_VALID <= '1';
+ not_event_valid <= '0';
+ else
+ WORD_NUMBER := WORD_NUMBER;
+ EVENT_OUT <= (others => '0');
+ EVENT_VALID <= '0';
+ not_event_valid <= '1';
+ end if;
+ end if;
+ end process SEND_EVENT;
+
+
+ READOUT_END_PULSER : edge_to_pulse
+ port map (
+ clock => CLK,
+ en_clk => '1',
+ signal_in => not_event_valid,
+ pulse => EVENT_READOUT_END);
+
+
+ fast_trigg <= '1' when data_clock_counter = 17 else '0'; --when trigger
+ --number and code
+ --is known
+
+ TRIGGER_TAG_COUNTER: process (CLK, RESET)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ trigger_counter <= (others => '0');
+ elsif data_trigg_pulse ='1' then
+ trigger_counter <= trigger_counter + 1;
+ else
+ trigger_counter <= trigger_counter;
+ end if;
+ end if;
+ end process TRIGGER_TAG_COUNTER;
+
+ not_transfer_busy <= not LVL1_TRANSFER_BUSY;
+
+ TRANSFER_BUSY_PULSER : edge_to_pulse
+ port map (
+ clock => CLK,
+ en_clk => '1',
+ signal_in => not_transfer_busy,
+ pulse => not_transfer_busy_pulse);
+
+ VULOM_TO_API_CLK : process (CLK, RESET)
+ begin
+ if rising_edge(CLK) then
+ if RESET = '1' then
+ VULOM_TO_API_current <= IDLE;
+ else
+ VULOM_TO_API_current <= VULOM_TO_API_next;
+ end if;
+ end if;
+ end process VULOM_TO_API_CLK;
+
+ VULOM_TO_API_FSM : process (CLK, fast_trigg, trigger_pulse, trigger_counter, trigger_tag, api_ready_pulse)
+ begin
+ case (VULOM_TO_API_current) is
+ when IDLE =>
+ vulom_interface_debug(3 downto 0) <= x"1";
+ busy_i <= '0';
+ API_SEND <= '0';
+ if fast_trigg = '1' then
+ VULOM_TO_API_next <= SEND_TRIGGER_a;
+ else
+ VULOM_TO_API_next <= IDLE;
+ end if;
+ when SEND_TRIGGER_a =>
+ vulom_interface_debug(3 downto 0) <= x"2";
+ busy_i <= '1';
+ API_SEND <= '0';
+ VULOM_TO_API_next <= SEND_TRIGGER_b;
+ when SEND_TRIGGER_b =>
+ vulom_interface_debug(3 downto 0) <= x"3";
+ busy_i <= '1';
+ API_SEND <= '1';
+ if trigger_counter /= trigger_tag then
+ VULOM_TO_API_next <= TRIGGER_MISSMATCH;
+ else
+ VULOM_TO_API_next <= WAIT_FOR_END_BUSY;
+ end if;
+ when WAIT_FOR_END_BUSY =>
+ vulom_interface_debug(3 downto 0) <= x"6";
+ busy_i <= '1';
+ API_SEND <= '0';
+ if api_ready_pulse = '1' and TRBNET_ENABLE = 1 then
+ VULOM_TO_API_next <= IDLE;
+ elsif not_transfer_busy_pulse = '1' and TRBNET_ENABLE = 0 then
+ VULOM_TO_API_next <= IDLE;
+ else
+ VULOM_TO_API_next <= WAIT_FOR_END_BUSY;
+ end if;
+ when TRIGGER_MISSMATCH =>
+ vulom_interface_debug(3 downto 0) <= x"7";
+ busy_i <= '1';
+ API_SEND <= '0';
+ VULOM_TO_API_next <= TRIGGER_MISSMATCH;
+ when others =>
+ vulom_interface_debug(3 downto 0) <= x"8";
+ busy_i <= '0';
+ API_SEND <= '0';
+ VULOM_TO_API_next <= IDLE;
+ end case;
+ end process VULOM_TO_API_FSM;
+
+ BUSY <=busy_i;-- or LVL1_TRANSFER_BUSY);6e1b17
+-- BUSY <= ack;
+ VULOM_INT_REG(3 downto 0) <= vulom_interface_debug(3 downto 0);
+ VULOM_INT_REG(7 downto 4) <= vulom_interface_debug(7 downto 4);
+ VULOM_INT_REG(15 downto 8) <= trigger_tag(7 downto 0);
+ VULOM_INT_REG(23 downto 16) <= trigger_counter(7 downto 0);
+ VULOM_INT_REG(31 downto 24) <= data_clock_counter(7 downto 0);
+end vulom_interface;