---------------------------------------------------------------------------------- -- Company: ETH Zurich, Institute for Particle Physics -- Engineer: Q. Weitzel -- -- Create Date: 17:54:04 02/02/2011 -- Design Name: -- Module Name: FTM_ftu_control - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: Communication of FTM with the 40 FTU boards of the FACT camera -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; library ftm_definitions; USE ftm_definitions.ftm_array_types.all; USE ftm_definitions.ftm_constants.all; ---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity FTM_ftu_control is port( clk_50MHz : in std_logic; -- main clock -- global bus enables for FTU crates 0-3 rx_en : out STD_LOGIC; -- receiver enable tx_en : out STD_LOGIC; -- transmitter enable -- FTU crate 0 data I/O rx_d_0 : in STD_LOGIC; tx_d_0 : out STD_LOGIC; -- FTU crate 1 data I/O rx_d_1 : in STD_LOGIC; tx_d_1 : out STD_LOGIC; -- FTU crate 2 data I/O rx_d_2 : in STD_LOGIC; tx_d_2 : out STD_LOGIC; -- FTU crate 3 data I/O rx_d_3 : in STD_LOGIC; tx_d_3 : out STD_LOGIC; -- commands from FTM main control new_config : in std_logic; ping_all : in std_logic; read_rates : in std_logic; -- answers to FTM main control read_rates_started : out std_logic := '0'; read_rates_done : out std_logic := '0'; new_config_started : out std_logic := '0'; new_config_done : out std_logic := '0'; ping_all_started : out std_logic := '0'; ping_all_done : out std_logic := '0'; -- communication with static (config) RAM -- this RAM is only read by FTU_control static_RAM_busy : in std_logic; static_RAM_started : in std_logic; static_RAM_ready : in std_logic; data_static_RAM : in std_logic_vector(15 downto 0) := (others => '0'); read_static_RAM : out std_logic := '0'; addr_static_RAM : out std_logic_vector(11 downto 0) := (others => '0'); -- communication with dynamic RAM (e.g. rates) -- this RAM is only written by FTU_control dynamic_RAM_busy : in std_logic; dynamic_RAM_started : in std_logic; dynamic_RAM_ready : in std_logic; data_dynamic_RAM : out std_logic_vector(15 downto 0) := (others => '0'); write_dynamic_RAM : out std_logic := '0'; addr_dynamic_RAM : out std_logic_vector(11 downto 0) := (others => '0'); -- communication with FTU-list RAM -- this RAM is only written by FTU_control FTUlist_RAM_busy : in std_logic; FTUlist_RAM_started : in std_logic; FTUlist_RAM_ready : in std_logic; data_FTUlist_RAM : out std_logic_vector(15 downto 0) := (others => '0'); write_FTUlist_RAM : out std_logic := '0'; addr_FTUlist_RAM : out std_logic_vector(11 downto 0) := (others => '0') ); end FTM_ftu_control; architecture Behavioral of FTM_ftu_control is -- list of active FTUs, read out from static RAM before starting to contact FTUs signal active_FTU_array_sig : active_FTU_array_type := ((others => '0'), (others => '0'), (others => '0'), (others => '0')); -- signals to count the number of responding FTUs (per crate and total) in case of a ping signal FTU_answer_array_sig : FTU_answer_array_type := (0,0,0,0); signal no_of_FTU_answer_sig : integer range 0 to (NO_OF_CRATES * NO_OF_FTUS_PER_CRATE) := 0; -- FTU configuration data, read out from static RAM (board by board) signal FTU_dac_array_RAM_sig : FTU_dac_array_type := ((others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0')); signal FTU_enable_array_RAM_sig : FTU_enable_array_type := ((others => '0'), (others => '0'), (others => '0'), (others => '0')); signal FTU_prescaling_RAM_sig : std_logic_vector(15 downto 0) := (others => '0'); -- signals for receiver of FTU communication signal rec_reset_sig : std_logic := '0'; -- reset signal rec_data_sig : std_logic_vector (7 DOWNTO 0); signal rec_block_sig : std_logic_vector (FTU_RS485_BLOCK_WIDTH - 1 downto 0); -- initialized in FTM_ftu_rs485_receiver signal rec_valid_sig : std_logic; -- initialized in FTM_ftu_rs485_receiver -- select signal to multiplex the different crates signal sel_crate_sig : STD_LOGIC_VECTOR (2 downto 0) := "111"; -- global signals after multiplexer signal rx_en_sig : std_logic; signal tx_en_sig : std_logic; signal rx_valid_sig : std_logic; signal tx_busy_sig : std_logic; signal tx_start_sig : std_logic; signal tx_data_sig : std_logic_vector (7 DOWNTO 0); -- signals for interpreter of FTU communication signal FTU_brd_add_sig : std_logic_vector (5 DOWNTO 0) := (others => '0'); signal FTU_command_sig : std_logic_vector (7 DOWNTO 0) := (others => '1'); signal FTU_answer_ok_sig : std_logic; -- initialized in interpreter signal FTU_dac_array_sig : FTU_dac_array_type; -- initialized in interpreter signal FTU_enable_array_sig : FTU_enable_array_type; -- initialized in interpreter signal FTU_rate_array_sig : FTU_rate_array_type; -- initialized in interpreter signal FTU_prescaling_sig : std_logic_vector(7 downto 0); -- initialized in interpreter signal FTU_crc_error_cnt_sig : std_logic_vector(7 downto 0); -- initialized in interpreter signal FTU_dna_sig : std_logic_vector(63 downto 0); -- initialized in interpreter -- rx_enable and tx_enable lines from different FTM_ftu_rs485_interface -- initialized in corresponding interface signal rx_en_0_sig : STD_LOGIC; signal tx_en_0_sig : STD_LOGIC; signal rx_en_1_sig : STD_LOGIC; signal tx_en_1_sig : STD_LOGIC; signal rx_en_2_sig : STD_LOGIC; signal tx_en_2_sig : STD_LOGIC; signal rx_en_3_sig : STD_LOGIC; signal tx_en_3_sig : STD_LOGIC; signal tx_start_0_sig : std_logic := '0'; signal tx_data_0_sig : std_logic_vector (7 DOWNTO 0) := (others => '0'); signal tx_busy_0_sig : std_logic; -- initialized in FTM_ftu_rs485_interface_0 signal rx_valid_0_sig : std_logic; -- initialized in FTM_ftu_rs485_interface_0 signal rx_data_0_sig : std_logic_vector (7 DOWNTO 0); -- initialized in FTM_ftu_rs485_interface_0 signal tx_start_1_sig : std_logic := '0'; signal tx_data_1_sig : std_logic_vector (7 DOWNTO 0) := (others => '0'); signal tx_busy_1_sig : std_logic; -- initialized in FTM_ftu_rs485_interface_1 signal rx_valid_1_sig : std_logic; -- initialized in FTM_ftu_rs485_interface_1 signal rx_data_1_sig : std_logic_vector (7 DOWNTO 0); -- initialized in FTM_ftu_rs485_interface_1 signal tx_start_2_sig : std_logic := '0'; signal tx_data_2_sig : std_logic_vector (7 DOWNTO 0) := (others => '0'); signal tx_busy_2_sig : std_logic; -- initialized in FTM_ftu_rs485_interface_2 signal rx_valid_2_sig : std_logic; -- initialized in FTM_ftu_rs485_interface_2 signal rx_data_2_sig : std_logic_vector (7 DOWNTO 0); -- initialized in FTM_ftu_rs485_interface_2 signal tx_start_3_sig : std_logic := '0'; signal tx_data_3_sig : std_logic_vector (7 DOWNTO 0) := (others => '0'); signal tx_busy_3_sig : std_logic; -- initialized in FTM_ftu_rs485_interface_3 signal rx_valid_3_sig : std_logic; -- initialized in FTM_ftu_rs485_interface_3 signal rx_data_3_sig : std_logic_vector (7 DOWNTO 0); -- initialized in FTM_ftu_rs485_interface_3 -- signals to control and read out CRC signal sel_crc_input_source_sig : std_logic := '0'; -- 0 -> FSM, 1 -> interpreter signal reset_crc_sig : std_logic; signal enable_crc_sig : std_logic; signal crc_data_sig : std_logic_vector (FTU_RS485_BLOCK_WIDTH - 9 downto 0) := (others => '0'); signal reset_crc_from_FSM_sig : std_logic := '0'; signal reset_crc_from_interpreter_sig : std_logic; signal enable_crc_from_FSM_sig : std_logic := '0'; signal enable_crc_from_interpreter_sig : std_logic; signal crc_data_from_FSM_sig : std_logic_vector (FTU_RS485_BLOCK_WIDTH - 9 downto 0) := (others => '0'); signal crc_sig : std_logic_vector(CRC_POLYNOMIAL'length - 1 downto 0); signal crc_sig_inv : std_logic_vector(CRC_POLYNOMIAL'length - 1 downto 0); -- various loop counters signal active_FTU_list_cnt : integer range 0 to NO_OF_CRATES := 0; signal crate_cnt : integer range 0 to NO_OF_CRATES := 0; signal FTU_cnt : integer range 0 to NO_OF_FTUS_PER_CRATE := 0; signal FTU_register_cnt : integer range 0 to (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG + 1) := 0; signal FTU_command_cnt : integer range 0 to 3 := 0; signal frame_cnt : integer range 0 to (FTU_RS485_BLOCK_WIDTH / 8) := 0; signal FTU_list_reg_cnt : integer range 0 to NO_OF_FTU_LIST_REG := 0; signal FTU_list_header_cnt : integer range 0 to FTU_LIST_RAM_OFFSET := 0; -- counter to define timeout and number of retries signal timeout_cnt : integer range 0 to FTU_RS485_TIMEOUT := 0; signal retry_cnt : integer range 0 to FTU_RS485_NO_OF_RETRY := 0; component FTM_ftu_rs485_interface port( clk : IN std_logic; -- RS485 rx_d : IN std_logic; rx_en : OUT std_logic; tx_d : OUT std_logic; tx_en : OUT std_logic; -- FPGA rx_data : OUT std_logic_vector (7 DOWNTO 0); --rx_busy : OUT std_logic := '0'; rx_valid : OUT std_logic := '0'; tx_data : IN std_logic_vector (7 DOWNTO 0); tx_busy : OUT std_logic := '0'; tx_start : IN std_logic ); end component; component FTM_ftu_rs485_receiver port( rec_clk : in std_logic; rec_reset : in std_logic; --rx_busy : in std_logic; rec_din : in std_logic_vector(7 downto 0); rec_den : in std_logic; rec_dout : out std_logic_vector(FTU_RS485_BLOCK_WIDTH - 1 downto 0) := (others => '0'); rec_valid : out std_logic := '0' ); end component; component FTM_ftu_rs485_interpreter port( clk : IN std_logic; data_block : IN std_logic_vector(FTU_RS485_BLOCK_WIDTH - 1 downto 0); block_valid : IN std_logic; crc : IN std_logic_vector(7 downto 0); FTU_brd_add : IN std_logic_vector(5 downto 0); FTU_command : IN std_logic_vector(7 downto 0); reset_crc : OUT std_logic := '0'; enable_crc : OUT std_logic := '0'; FTU_answer_ok : OUT std_logic := '0'; FTU_dac_array : OUT FTU_dac_array_type; FTU_enable_array : OUT FTU_enable_array_type; FTU_rate_array : OUT FTU_rate_array_type; FTU_prescaling : OUT std_logic_vector(7 downto 0); FTU_crc_error_cnt : OUT std_logic_vector(7 downto 0); FTU_dna : OUT std_logic_vector(63 downto 0) ); end component; component ucrc_par generic( POLYNOMIAL : std_logic_vector; INIT_VALUE : std_logic_vector; DATA_WIDTH : integer range 2 to 256; SYNC_RESET : integer range 0 to 1 ); port( clk_i : in std_logic; rst_i : in std_logic; clken_i : in std_logic; data_i : in std_logic_vector(DATA_WIDTH - 1 downto 0); match_o : out std_logic; crc_o : out std_logic_vector(POLYNOMIAL'length - 1 downto 0) ); end component; type FTM_ftu_rs485_control_StateType is (INIT, IDLE, ACTIVE_LIST, READ_CONFIG, TRANSMIT_CONFIG, PING, PING_END, FTU_LIST, RATES, ACTIVE_LIST_1, ACTIVE_LIST_2, ACTIVE_LIST_3, READ_CONFIG_1, READ_CONFIG_2, READ_CONFIG_3, TRANSMIT_CONFIG_1, TRANSMIT_CONFIG_2, TRANSMIT_CONFIG_3, PING_1, PING_2, PING_3, PING_END_1, PING_END_2, PING_END_3, FTU_LIST_1, FTU_LIST_2, FTU_LIST_3); signal FTM_ftu_rs485_control_State : FTM_ftu_rs485_control_StateType; begin Inst_FTM_fTU_rs485_interface_0 : FTM_ftu_rs485_interface -- crate 0 port map( clk => clk_50MHz, -- RS485 rx_d => rx_d_0, rx_en => rx_en_0_sig, tx_d => tx_d_0, tx_en => tx_en_0_sig, -- FPGA rx_data => rx_data_0_sig, --rx_busy => , rx_valid => rx_valid_0_sig, tx_data => tx_data_0_sig, tx_busy => tx_busy_0_sig, tx_start => tx_start_0_sig ); Inst_FTM_fTU_rs485_interface_1 : FTM_ftu_rs485_interface -- crate 1 port map( clk => clk_50MHz, -- RS485 rx_d => rx_d_1, rx_en => rx_en_1_sig, tx_d => tx_d_1, tx_en => tx_en_1_sig, -- FPGA rx_data => rx_data_1_sig, --rx_busy => , rx_valid => rx_valid_1_sig, tx_data => tx_data_1_sig, tx_busy => tx_busy_1_sig, tx_start => tx_start_1_sig ); Inst_FTM_fTU_rs485_interface_2 : FTM_ftu_rs485_interface -- crate 2 port map( clk => clk_50MHz, -- RS485 rx_d => rx_d_2, rx_en => rx_en_2_sig, tx_d => tx_d_2, tx_en => tx_en_2_sig, -- FPGA rx_data => rx_data_2_sig, --rx_busy => , rx_valid => rx_valid_2_sig, tx_data => tx_data_2_sig, tx_busy => tx_busy_2_sig, tx_start => tx_start_2_sig ); Inst_FTM_fTU_rs485_interface_3 : FTM_ftu_rs485_interface -- crate 3 port map( clk => clk_50MHz, -- RS485 rx_d => rx_d_3, rx_en => rx_en_3_sig, tx_d => tx_d_3, tx_en => tx_en_3_sig, -- FPGA rx_data => rx_data_3_sig, --rx_busy => , rx_valid => rx_valid_3_sig, tx_data => tx_data_3_sig, tx_busy => tx_busy_3_sig, tx_start => tx_start_3_sig ); Inst_FTM_ftu_rs485_receiver : FTM_ftu_rs485_receiver port map( rec_clk => clk_50MHz, rec_reset => rec_reset_sig, --rx_busy =>, rec_din => rec_data_sig, rec_den => rx_valid_sig, rec_dout => rec_block_sig, rec_valid => rec_valid_sig ); Inst_FTM_ftu_rs485_interpreter : FTM_ftu_rs485_interpreter port map( clk => clk_50MHz, data_block => rec_block_sig, block_valid => rec_valid_sig, crc => crc_sig, FTU_brd_add => FTU_brd_add_sig, FTU_command => FTU_command_sig, reset_crc => reset_crc_from_interpreter_sig, enable_crc => enable_crc_from_interpreter_sig, FTU_answer_ok => FTU_answer_ok_sig, FTU_dac_array => FTU_dac_array_sig, FTU_enable_array => FTU_enable_array_sig, FTU_rate_array => FTU_rate_array_sig, FTU_prescaling => FTU_prescaling_sig, FTU_crc_error_cnt => FTU_crc_error_cnt_sig, FTU_dna => FTU_dna_sig ); Inst_ucrc_par : ucrc_par generic map( POLYNOMIAL => CRC_POLYNOMIAL, INIT_VALUE => CRC_INIT_VALUE, DATA_WIDTH => (FTU_RS485_BLOCK_WIDTH - 8), SYNC_RESET => 1 ) port map( clk_i => clk_50MHz, rst_i => reset_crc_sig, clken_i => enable_crc_sig, data_i => crc_data_sig, match_o => open, crc_o => crc_sig_inv ); -- Main finite state machine to control all 40 FTUs FTM_ftu_rs485_control_FSM: process (clk_50MHz) begin if Rising_edge(clk_50MHz) then case FTM_ftu_rs485_control_State is when INIT => -- reset CRC register reset_crc_from_FSM_sig <= '1'; FTM_ftu_rs485_control_State <= IDLE; when IDLE => -- wait for command from outside sel_crate_sig <= "111"; sel_crc_input_source_sig <= '0'; reset_crc_from_FSM_sig <= '0'; enable_crc_from_FSM_sig <= '0'; new_config_done <= '0'; ping_all_done <= '0'; read_rates_done <= '0'; if (new_config = '1') then new_config_started <= '1'; ping_all_started <= '0'; read_rates_started <= '0'; FTM_ftu_rs485_control_State <= ACTIVE_LIST; elsif (new_config = '0' and ping_all = '1') then new_config_started <= '0'; ping_all_started <= '1'; read_rates_started <= '0'; FTM_ftu_rs485_control_State <= PING; elsif (new_config = '0' and ping_all = '0' and read_rates = '1') then new_config_started <= '0'; ping_all_started <= '0'; read_rates_started <= '1'; FTM_ftu_rs485_control_State <= RATES; else new_config_started <= '0'; ping_all_started <= '0'; read_rates_started <= '0'; FTM_ftu_rs485_control_State <= IDLE; end if; when ACTIVE_LIST => -- loop over 4 crates to get active FTU list if (active_FTU_list_cnt < NO_OF_CRATES) then active_FTU_list_cnt <= active_FTU_list_cnt + 1; FTM_ftu_rs485_control_State <= ACTIVE_LIST_1; else active_FTU_list_cnt <= 0; FTM_ftu_rs485_control_State <= READ_CONFIG; end if; when ACTIVE_LIST_1 => if (static_RAM_busy = '0') then read_static_RAM <= '1'; addr_static_RAM <= conv_std_logic_vector(STATIC_RAM_ACT_FTU_OFFSET + (active_FTU_list_cnt - 1), STATIC_RAM_ADDR_WIDTH); FTM_ftu_rs485_control_State <= ACTIVE_LIST_2; end if; when ACTIVE_LIST_2 => if (static_RAM_started = '1') then FTM_ftu_rs485_control_State <= ACTIVE_LIST_3; end if; when ACTIVE_LIST_3 => if (static_RAM_ready = '1') then active_FTU_array_sig(active_FTU_list_cnt - 1) <= data_static_RAM; read_static_RAM <= '0'; FTM_ftu_rs485_control_State <= ACTIVE_LIST; end if; when READ_CONFIG => -- read configuration of FTUs (one by one) if (crate_cnt < NO_OF_CRATES) then sel_crate_sig <= conv_std_logic_vector(crate_cnt, 3); if (FTU_cnt < NO_OF_FTUS_PER_CRATE) then if (FTU_register_cnt < (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG + 1)) then FTU_register_cnt <= FTU_register_cnt + 1; FTM_ftu_rs485_control_State <= READ_CONFIG_1; else FTU_cnt <= FTU_cnt + 1; FTU_register_cnt <= 0; if (active_FTU_array_sig(crate_cnt)(FTU_cnt) = '1') then FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG; else FTM_ftu_rs485_control_State <= READ_CONFIG; end if; end if; else crate_cnt <= crate_cnt + 1; FTU_cnt <= 0; FTM_ftu_rs485_control_State <= READ_CONFIG; end if; else crate_cnt <= 0; new_config_started <= '0'; new_config_done <= '1'; sel_crate_sig <= "111"; FTM_ftu_rs485_control_State <= IDLE; end if; when READ_CONFIG_1 => if (static_RAM_busy = '0') then read_static_RAM <= '1'; addr_static_RAM <= conv_std_logic_vector(STATIC_RAM_CFG_FTU_OFFSET + crate_cnt * NO_OF_FTUS_PER_CRATE * (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG + 1) + FTU_cnt * (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG + 1) + (FTU_register_cnt - 1), STATIC_RAM_ADDR_WIDTH); FTM_ftu_rs485_control_State <= READ_CONFIG_2; end if; when READ_CONFIG_2 => if (static_RAM_started = '1') then FTM_ftu_rs485_control_State <= READ_CONFIG_3; end if; when READ_CONFIG_3 => if (static_RAM_ready = '1') then if ((FTU_register_cnt - 1) < NO_OF_FTU_ENABLE_REG) then FTU_enable_array_RAM_sig(FTU_register_cnt - 1) <= data_static_RAM; elsif ((FTU_register_cnt - 1) < (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG)) then FTU_dac_array_RAM_sig((FTU_register_cnt - 1) - NO_OF_FTU_ENABLE_REG) <= data_static_RAM; elsif ((FTU_register_cnt - 1) = (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG)) then FTU_prescaling_RAM_sig <= data_static_RAM; end if; read_static_RAM <= '0'; FTM_ftu_rs485_control_State <= READ_CONFIG; end if; when TRANSMIT_CONFIG => -- send configuration to FTUs (one by one) rec_reset_sig <= '0'; if (FTU_command_cnt = 0) then -- DACs FTU_command_cnt <= FTU_command_cnt + 1; enable_crc_from_FSM_sig <= '1'; crc_data_from_FSM_sig <= "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & FTU_dac_array_RAM_sig(4)(15 downto 8) & FTU_dac_array_RAM_sig(4)(7 downto 0) & FTU_dac_array_RAM_sig(3)(15 downto 8) & FTU_dac_array_RAM_sig(3)(7 downto 0) & FTU_dac_array_RAM_sig(2)(15 downto 8) & FTU_dac_array_RAM_sig(2)(7 downto 0) & FTU_dac_array_RAM_sig(1)(15 downto 8) & FTU_dac_array_RAM_sig(1)(7 downto 0) & FTU_dac_array_RAM_sig(0)(15 downto 8) & FTU_dac_array_RAM_sig(0)(7 downto 0) & "00000000" & FIRMWARE_ID & FTM_ADDRESS & "00" & conv_std_logic_vector(FTU_cnt,4) & conv_std_logic_vector(crate_cnt,2) & FTU_RS485_START_DELIM; FTU_brd_add_sig <= conv_std_logic_vector(FTU_cnt,4) & conv_std_logic_vector(crate_cnt,2); FTU_command_sig <= "00000000"; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_1; elsif (FTU_command_cnt = 1) then -- enables FTU_command_cnt <= FTU_command_cnt + 1; enable_crc_from_FSM_sig <= '1'; crc_data_from_FSM_sig <= "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & FTU_enable_array_RAM_sig(3)(15 downto 8) & FTU_enable_array_RAM_sig(3)(7 downto 0) & FTU_enable_array_RAM_sig(2)(15 downto 8) & FTU_enable_array_RAM_sig(2)(7 downto 0) & FTU_enable_array_RAM_sig(1)(15 downto 8) & FTU_enable_array_RAM_sig(1)(7 downto 0) & FTU_enable_array_RAM_sig(0)(15 downto 8) & FTU_enable_array_RAM_sig(0)(7 downto 0) & "00000011" & FIRMWARE_ID & FTM_ADDRESS & "00" & conv_std_logic_vector(FTU_cnt,4) & conv_std_logic_vector(crate_cnt,2) & FTU_RS485_START_DELIM; FTU_brd_add_sig <= conv_std_logic_vector(FTU_cnt,4) & conv_std_logic_vector(crate_cnt,2); FTU_command_sig <= "00000011"; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_1; elsif (FTU_command_cnt = 2) then -- prescaling FTU_command_cnt <= FTU_command_cnt + 1; enable_crc_from_FSM_sig <= '1'; crc_data_from_FSM_sig <= "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & FTU_prescaling_RAM_sig(15 downto 8) & FTU_prescaling_RAM_sig(7 downto 0) & "00000110" & FIRMWARE_ID & FTM_ADDRESS & "00" & conv_std_logic_vector(FTU_cnt,4) & conv_std_logic_vector(crate_cnt,2) & FTU_RS485_START_DELIM; FTU_brd_add_sig <= conv_std_logic_vector(FTU_cnt,4) & conv_std_logic_vector(crate_cnt,2); FTU_command_sig <= "00000110"; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_1; else FTU_command_cnt <= 0; enable_crc_from_FSM_sig <= '0'; FTM_ftu_rs485_control_State <= READ_CONFIG; end if; when TRANSMIT_CONFIG_1 => -- wait one cycle for CRC calculation enable_crc_from_FSM_sig <= '0'; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_2; when TRANSMIT_CONFIG_2 => -- transmit byte by byte if (tx_busy_sig = '0') then if (frame_cnt < 27) then frame_cnt <= frame_cnt + 1; tx_data_sig <= crc_data_from_FSM_sig (7 downto 0); crc_data_from_FSM_sig <= "00000000" & crc_data_from_FSM_sig ((FTU_RS485_BLOCK_WIDTH - 9) downto 8); tx_start_sig <= '1'; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_2; elsif (frame_cnt = 27) then frame_cnt <= frame_cnt + 1; tx_data_sig <= crc_sig; tx_start_sig <= '1'; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_2; else frame_cnt <= 0; reset_crc_from_FSM_sig <= '1'; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_3; end if; else tx_start_sig <= '0'; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_2; end if; when TRANSMIT_CONFIG_3 => -- wait for FTU answer reset_crc_from_FSM_sig <= '0'; if (FTU_answer_ok_sig = '1') then timeout_cnt <= 0; retry_cnt <= 0; sel_crc_input_source_sig <= '0'; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG; else if (timeout_cnt < FTU_RS485_TIMEOUT) then timeout_cnt <= timeout_cnt + 1; sel_crc_input_source_sig <= '1'; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_3; else timeout_cnt <= 0; sel_crc_input_source_sig <= '0'; rec_reset_sig <= '1'; if (retry_cnt < FTU_RS485_NO_OF_RETRY) then retry_cnt <= retry_cnt + 1; FTU_command_cnt <= FTU_command_cnt - 1; -- try this command again FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG; else retry_cnt <= 0; FTU_command_cnt <= FTU_command_cnt; -- move to next command; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG; end if; end if; end if; when PING => -- ping all FTUs rec_reset_sig <= '0'; if (crate_cnt < NO_OF_CRATES) then sel_crate_sig <= conv_std_logic_vector(crate_cnt, 3); if (FTU_cnt < NO_OF_FTUS_PER_CRATE) then FTU_cnt <= FTU_cnt + 1; if (active_FTU_array_sig(crate_cnt)(FTU_cnt) = '1') then enable_crc_from_FSM_sig <= '1'; crc_data_from_FSM_sig <= "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000000" & "00000101" & FIRMWARE_ID & FTM_ADDRESS & "00" & conv_std_logic_vector(FTU_cnt,4) & conv_std_logic_vector(crate_cnt,2) & FTU_RS485_START_DELIM; FTU_brd_add_sig <= conv_std_logic_vector(FTU_cnt,4) & conv_std_logic_vector(crate_cnt,2); FTU_command_sig <= "00000101"; FTM_ftu_rs485_control_State <= PING_1; else FTM_ftu_rs485_control_State <= PING; end if; else crate_cnt <= crate_cnt + 1; FTU_cnt <= 0; FTM_ftu_rs485_control_State <= PING; end if; else crate_cnt <= 0; FTM_ftu_rs485_control_State <= PING_END; end if; when PING_1 => -- wait one cycle for CRC calculation enable_crc_from_FSM_sig <= '0'; FTM_ftu_rs485_control_State <= PING_2; when PING_2 => -- transmit byte by byte if (tx_busy_sig = '0') then if (frame_cnt < 27) then frame_cnt <= frame_cnt + 1; tx_data_sig <= crc_data_from_FSM_sig (7 downto 0); crc_data_from_FSM_sig <= "00000000" & crc_data_from_FSM_sig ((FTU_RS485_BLOCK_WIDTH - 9) downto 8); tx_start_sig <= '1'; FTM_ftu_rs485_control_State <= PING_2; elsif (frame_cnt = 27) then frame_cnt <= frame_cnt + 1; tx_data_sig <= crc_sig; tx_start_sig <= '1'; FTM_ftu_rs485_control_State <= PING_2; else frame_cnt <= 0; reset_crc_from_FSM_sig <= '1'; FTM_ftu_rs485_control_State <= PING_3; end if; else tx_start_sig <= '0'; FTM_ftu_rs485_control_State <= PING_2; end if; when PING_3 => -- wait for FTU answer reset_crc_from_FSM_sig <= '0'; if (FTU_answer_ok_sig = '1') then FTU_answer_array_sig(crate_cnt) <= FTU_answer_array_sig(crate_cnt) + 1; no_of_FTU_answer_sig <= no_of_FTU_answer_sig + 1; timeout_cnt <= 0; sel_crc_input_source_sig <= '0'; FTM_ftu_rs485_control_State <= FTU_LIST; else if (timeout_cnt < FTU_RS485_TIMEOUT) then timeout_cnt <= timeout_cnt + 1; sel_crc_input_source_sig <= '1'; FTM_ftu_rs485_control_State <= PING_3; else timeout_cnt <= 0; sel_crc_input_source_sig <= '0'; rec_reset_sig <= '1'; if (retry_cnt < FTU_RS485_NO_OF_RETRY) then retry_cnt <= retry_cnt + 1; FTU_cnt <= FTU_cnt - 1; -- repeat this FTU FTM_ftu_rs485_control_State <= PING; else FTU_cnt <= FTU_cnt; -- move on FTM_ftu_rs485_control_State <= FTU_LIST; end if; end if; end if; when FTU_LIST => -- fill FTU-list for actual FTU rec_reset_sig <= '0'; if (FTU_list_reg_cnt < NO_OF_FTU_LIST_REG) then FTU_list_reg_cnt <= FTU_list_reg_cnt + 1; FTM_ftu_rs485_control_State <= FTU_LIST_1; else FTU_list_reg_cnt <= 0; retry_cnt <= 0; FTM_ftu_rs485_control_State <= PING; end if; when FTU_LIST_1 => if (FTUlist_RAM_busy = '0') then write_FTUlist_RAM <= '1'; addr_FTUlist_RAM <= conv_std_logic_vector(FTU_LIST_RAM_OFFSET + FTU_cnt * NO_OF_FTU_LIST_REG + (FTU_list_reg_cnt - 1), FTU_LIST_RAM_ADDR_WIDTH); if (retry_cnt < FTU_RS485_NO_OF_RETRY) then if ((FTU_list_reg_cnt - 1) = 0) then data_FTUlist_RAM <= "000000" & conv_std_logic_vector((retry_cnt + 1),2) & "00" & FTU_brd_add_sig; elsif ((FTU_list_reg_cnt - 1) = 1) then data_FTUlist_RAM <= FTU_dna_sig(63 downto 48); elsif ((FTU_list_reg_cnt - 1) = 2) then data_FTUlist_RAM <= FTU_dna_sig(47 downto 32); elsif ((FTU_list_reg_cnt - 1) = 3) then data_FTUlist_RAM <= FTU_dna_sig(31 downto 16); elsif ((FTU_list_reg_cnt - 1) = 4) then data_FTUlist_RAM <= FTU_dna_sig(15 downto 0); elsif ((FTU_list_reg_cnt - 1) = 5) then data_FTUlist_RAM <= "00000000" & FTU_crc_error_cnt_sig; end if; else data_FTUlist_RAM <= (others => '0'); end if; FTM_ftu_rs485_control_State <= FTU_LIST_2; end if; when FTU_LIST_2 => if (FTUlist_RAM_started = '1') then write_FTUlist_RAM <= '0'; FTM_ftu_rs485_control_State <= FTU_LIST_3; end if; when FTU_LIST_3 => if (FTUlist_RAM_ready = '1') then FTM_ftu_rs485_control_State <= FTU_LIST; end if; when PING_END => -- add final ping statistics to FTU-list if (FTU_list_header_cnt < FTU_LIST_RAM_OFFSET) then FTU_list_header_cnt <= FTU_list_header_cnt + 1; FTM_ftu_rs485_control_State <= PING_END_1; else FTU_list_header_cnt <= 0; ping_all_started <= '0'; ping_all_done <= '1'; sel_crate_sig <= "111"; FTM_ftu_rs485_control_State <= IDLE; end if; when PING_END_1 => if (FTUlist_RAM_busy = '0') then write_FTUlist_RAM <= '1'; addr_FTUlist_RAM <= conv_std_logic_vector((FTU_list_header_cnt - 1), FTU_LIST_RAM_ADDR_WIDTH); if ((FTU_list_header_cnt - 1) = 0) then data_FTUlist_RAM <= conv_std_logic_vector(no_of_FTU_answer_sig, 16); elsif ((FTU_list_header_cnt - 1) < 5) then data_FTUlist_RAM <= conv_std_logic_vector(FTU_answer_array_sig(FTU_list_header_cnt - 2), 16); elsif ((FTU_list_header_cnt - 1) < 9) then data_FTUlist_RAM <= active_FTU_array_sig(FTU_list_header_cnt - 6); end if; FTM_ftu_rs485_control_State <= PING_END_2; end if; when PING_END_2 => if (FTUlist_RAM_started = '1') then write_FTUlist_RAM <= '0'; FTM_ftu_rs485_control_State <= PING_END_3; end if; when PING_END_3 => if (FTUlist_RAM_ready = '1') then FTM_ftu_rs485_control_State <= PING_END; end if; when RATES => -- read all FTU rates FTM_ftu_rs485_control_State <= IDLE; end case; end if; end process FTM_ftu_rs485_control_FSM; -- Process to multiplex the different crate buses sel_crate_process: process (sel_crate_sig, rx_en_0_sig, rx_en_1_sig, rx_en_2_sig, rx_en_3_sig, tx_en_0_sig, tx_en_1_sig, tx_en_2_sig, tx_en_3_sig, rx_valid_0_sig, rx_valid_1_sig, rx_valid_2_sig, rx_valid_3_sig, rx_data_0_sig, rx_data_1_sig, rx_data_2_sig, rx_data_3_sig, tx_busy_0_sig, tx_busy_1_sig, tx_busy_2_sig, tx_busy_3_sig, tx_start_sig, tx_data_sig) begin case sel_crate_sig is when "000" => -- crate 0 rx_en_sig <= rx_en_0_sig; tx_en_sig <= tx_en_0_sig; rx_valid_sig <= rx_valid_0_sig; rec_data_sig <= rx_data_0_sig; tx_busy_sig <= tx_busy_0_sig; tx_start_0_sig <= tx_start_sig; tx_start_1_sig <= '0'; tx_start_2_sig <= '0'; tx_start_3_sig <= '0'; tx_data_0_sig <= tx_data_sig; tx_data_1_sig <= (others => '0'); tx_data_2_sig <= (others => '0'); tx_data_3_sig <= (others => '0'); when "001" => -- crate 1 rx_en_sig <= rx_en_1_sig; tx_en_sig <= tx_en_1_sig; rx_valid_sig <= rx_valid_1_sig; rec_data_sig <= rx_data_1_sig; tx_busy_sig <= tx_busy_1_sig; tx_start_0_sig <= '0'; tx_start_1_sig <= tx_start_sig; tx_start_2_sig <= '0'; tx_start_3_sig <= '0'; tx_data_0_sig <= (others => '0'); tx_data_1_sig <= tx_data_sig; tx_data_2_sig <= (others => '0'); tx_data_3_sig <= (others => '0'); when "010" => -- crate 2 rx_en_sig <= rx_en_2_sig; tx_en_sig <= tx_en_2_sig; rx_valid_sig <= rx_valid_2_sig; rec_data_sig <= rx_data_2_sig; tx_busy_sig <= tx_busy_2_sig; tx_start_0_sig <= '0'; tx_start_1_sig <= '0'; tx_start_2_sig <= tx_start_sig; tx_start_3_sig <= '0'; tx_data_0_sig <= (others => '0'); tx_data_1_sig <= (others => '0'); tx_data_2_sig <= tx_data_sig; tx_data_3_sig <= (others => '0'); when "011" => -- crate 3 rx_en_sig <= rx_en_3_sig; tx_en_sig <= tx_en_3_sig; rx_valid_sig <= rx_valid_3_sig; rec_data_sig <= rx_data_3_sig; tx_busy_sig <= tx_busy_3_sig; tx_start_0_sig <= '0'; tx_start_1_sig <= '0'; tx_start_2_sig <= '0'; tx_start_3_sig <= tx_start_sig; tx_data_0_sig <= (others => '0'); tx_data_1_sig <= (others => '0'); tx_data_2_sig <= (others => '0'); tx_data_3_sig <= tx_data_sig; when others => -- no crate specified rx_en_sig <= '0'; tx_en_sig <= '0'; rx_valid_sig <= '0'; rec_data_sig <= (others => '0'); tx_busy_sig <= '0'; tx_start_0_sig <= '0'; tx_start_1_sig <= '0'; tx_start_2_sig <= '0'; tx_start_3_sig <= '0'; tx_data_0_sig <= (others => '0'); tx_data_1_sig <= (others => '0'); tx_data_2_sig <= (others => '0'); tx_data_3_sig <= (others => '0'); end case; end process; -- Process to select the CRC input source (FSM or interpreter) sel_crc_cource_process : process (sel_crc_input_source_sig, reset_crc_from_interpreter_sig, reset_crc_from_FSM_sig, enable_crc_from_interpreter_sig, enable_crc_from_FSM_sig, rec_block_sig((FTU_RS485_BLOCK_WIDTH - 9) downto 0), crc_data_from_FSM_sig) begin case sel_crc_input_source_sig is when '0' => -- FSM reset_crc_sig <= reset_crc_from_FSM_sig; enable_crc_sig <= enable_crc_from_FSM_sig; crc_data_sig <= crc_data_from_FSM_sig; when '1' => -- interpreter reset_crc_sig <= reset_crc_from_interpreter_sig; enable_crc_sig <= enable_crc_from_interpreter_sig; crc_data_sig <= rec_block_sig((FTU_RS485_BLOCK_WIDTH - 9) downto 0); when others => -- signal undefined reset_crc_sig <= reset_crc_from_FSM_sig; enable_crc_sig <= enable_crc_from_FSM_sig; crc_data_sig <= crc_data_from_FSM_sig; end case; end process; rx_en <= rx_en_sig; tx_en <= tx_en_sig; crc_sig <= crc_sig_inv(0) & crc_sig_inv(1) & crc_sig_inv(2) & crc_sig_inv(3) & crc_sig_inv(4) & crc_sig_inv(5) & crc_sig_inv(6) & crc_sig_inv(7); end Behavioral;