---------------------------------------------------------------------------------- -- 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 central control new_config : in std_logic; ping_all : in std_logic; read_rates : in std_logic; config_single_FTU : in std_logic; -- answers to FTM central 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'; config_single_FTU_started : out std_logic := '0'; config_single_FTU_done : out std_logic := '0'; -- active FTU lists ftu_active_cr0 : in std_logic_vector (15 downto 0); ftu_active_cr1 : in std_logic_vector (15 downto 0); ftu_active_cr2 : in std_logic_vector (15 downto 0); ftu_active_cr3 : in std_logic_vector (15 downto 0); -- parameter for config single FTU command config_single_FTU_param : in std_logic_vector (15 DOWNTO 0); --error message interface to ethernet control ftu_error_calls : out std_logic_vector (15 DOWNTO 0) := (others => '0'); ftu_error_data : out std_logic_vector ((FTU_RS485_BLOCK_WIDTH - 1) downto 0) := (others => '0'); ftu_error_send : out std_logic := '0'; ftu_error_send_ack : in std_logic; ftu_error_send_ready : in std_logic; -- 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')); --signal active_FTU_array_sig : active_FTU_array_type := ("0000000000000001", (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_dac_array_RAM_sig_2 : 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_enable_array_RAM_sig_2 : 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 := '0'; signal tx_en_sig : std_logic := '0'; signal rx_valid_sig : std_logic := '0'; signal tx_busy_sig : std_logic := '0'; signal tx_start_sig : std_logic := '0'; signal tx_data_sig : std_logic_vector (7 DOWNTO 0) := (others => '0'); signal rx_busy_sig : std_logic := '0'; signal start_int_sig : std_logic := '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_overflow_sig : std_logic_vector(7 downto 0); -- 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 rx_busy_0_sig : std_logic; -- initialized in 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 rx_busy_1_sig : std_logic; -- initialized in 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 rx_busy_2_sig : std_logic; -- initialized in 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 signal rx_busy_3_sig : std_logic; -- initialized in 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_data_from_FSM_sig_cp : 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_register_cnt_2 : integer range 0 to (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG) := 0; signal FTU_command_cnt : integer range 0 to 3 := 0; signal FTU_command_cnt_2 : integer range 0 to 2 := 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 + 1):= 0; signal DD_RAM_reg_cnt : integer range 0 to NO_OF_DD_RAM_REG := 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; --Zwischenrechnungen signal FTU_cnt_offset_sig : integer range 0 to (NO_OF_DD_RAM_REG * NO_OF_FTUS_PER_CRATE) := 0; signal crate_cnt_offset_sig : integer range 0 to (NO_OF_CRATES * NO_OF_FTUS_PER_CRATE * NO_OF_DD_RAM_REG) := 0; --Crate and Slot number for config_single_FTU command signal single_FTU_crate_sig : integer range 0 to 7 := 0; signal single_FTU_slot_sig : integer range 0 to 15 := 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_overflow : OUT std_logic_vector(7 downto 0); 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, SEND_ERROR_1, SEND_ERROR_2, RATES, RATES_1, RATES_2, RATES_3, DD_RAM, DD_RAM_1, DD_RAM_2, DD_RAM_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, GET_FTU_PAR, READ_CONFIG_SINGLE_FTU, READ_CONFIG_SINGLE_FTU_1, READ_CONFIG_SINGLE_FTU_2, READ_CONFIG_SINGLE_FTU_3, TRANSMIT_CONFIG_SINGLE_FTU_1, TRANSMIT_CONFIG_SINGLE_FTU_2, TRANSMIT_CONFIG_SINGLE_FTU_3, TRANSMIT_CONFIG_SINGLE_FTU, CONFIG_SINGLE_FTU_END); signal FTM_ftu_rs485_control_State : FTM_ftu_rs485_control_StateType; signal after_error_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_busy_0_sig, 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_busy_1_sig, 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_busy_2_sig, 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_busy_3_sig, 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 => start_int_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_overflow => FTU_overflow_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_done <= '0'; new_config_started <= '1'; ping_all_started <= '0'; read_rates_started <= '0'; config_single_FTU_started <= '0'; FTM_ftu_rs485_control_State <= ACTIVE_LIST; elsif (new_config = '0' and ping_all = '1') then ping_all_done <= '0'; new_config_started <= '0'; ping_all_started <= '1'; read_rates_started <= '0'; config_single_FTU_started <= '0'; rec_reset_sig <= '1'; FTM_ftu_rs485_control_State <= PING; elsif (new_config = '0' and ping_all = '0' and read_rates = '1') then read_rates_done <= '0'; new_config_started <= '0'; ping_all_started <= '0'; read_rates_started <= '1'; config_single_FTU_started <= '0'; FTM_ftu_rs485_control_State <= RATES; elsif (new_config = '0' and ping_all = '0' and read_rates = '0' and config_single_FTU = '1') then config_single_FTU_done <= '0'; new_config_started <= '0'; ping_all_started <= '0'; read_rates_started <= '0'; config_single_FTU_started <= '1'; FTM_ftu_rs485_control_State <= GET_FTU_PAR; else new_config_started <= '0'; ping_all_started <= '0'; read_rates_started <= '0'; config_single_FTU_started <= '0'; FTM_ftu_rs485_control_State <= IDLE; end if; when ACTIVE_LIST => -- copy active FTU list from inputs to array active_FTU_array_sig(0) <= ftu_active_cr0; active_FTU_array_sig(1) <= ftu_active_cr1; active_FTU_array_sig(2) <= ftu_active_cr2; active_FTU_array_sig(3) <= ftu_active_cr3; FTM_ftu_rs485_control_State <= READ_CONFIG; when GET_FTU_PAR => -- copy FTU parameter (crate and slot) from input single_FTU_crate_sig <= conv_integer(unsigned(config_single_FTU_param( 2 downto 0))); single_FTU_slot_sig <= conv_integer(unsigned(config_single_FTU_param(11 downto 8))); FTM_ftu_rs485_control_State <= READ_CONFIG_SINGLE_FTU; -- 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 rec_reset_sig <= '1'; 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_SINGLE_FTU => -- read configuration of one FTU sel_crate_sig <= conv_std_logic_vector(single_FTU_crate_sig, 3); if (FTU_register_cnt_2 < (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG)) then FTU_register_cnt_2 <= FTU_register_cnt_2 + 1; FTM_ftu_rs485_control_State <= READ_CONFIG_SINGLE_FTU_1; else FTU_register_cnt_2 <= 0; if (active_FTU_array_sig(single_FTU_crate_sig)(single_FTU_slot_sig) = '1') then rec_reset_sig <= '1'; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU; else FTM_ftu_rs485_control_State <= CONFIG_SINGLE_FTU_END; end if; 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_SINGLE_FTU_1 => if (static_RAM_busy = '0') then read_static_RAM <= '1'; addr_static_RAM <= conv_std_logic_vector(STATIC_RAM_CFG_FTU_OFFSET + single_FTU_crate_sig * NO_OF_FTUS_PER_CRATE * (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG + 1) + single_FTU_slot_sig * (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG + 1) + (FTU_register_cnt_2 - 1), STATIC_RAM_ADDR_WIDTH); FTM_ftu_rs485_control_State <= READ_CONFIG_SINGLE_FTU_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_SINGLE_FTU_2 => if (static_RAM_started = '1') then FTM_ftu_rs485_control_State <= READ_CONFIG_SINGLE_FTU_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 READ_CONFIG_SINGLE_FTU_3 => if (static_RAM_ready = '1') then if ((FTU_register_cnt_2 - 1) < NO_OF_FTU_ENABLE_REG) then FTU_enable_array_RAM_sig_2(FTU_register_cnt_2 - 1) <= data_static_RAM; elsif ((FTU_register_cnt_2 - 1) < (NO_OF_FTU_ENABLE_REG + NO_OF_FTU_DAC_REG)) then FTU_dac_array_RAM_sig_2((FTU_register_cnt_2 - 1) - NO_OF_FTU_ENABLE_REG) <= data_static_RAM; end if; read_static_RAM <= '0'; FTM_ftu_rs485_control_State <= READ_CONFIG_SINGLE_FTU; 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 - 1),4) & conv_std_logic_vector(crate_cnt,2) & FTU_RS485_START_DELIM; FTU_brd_add_sig <= conv_std_logic_vector((FTU_cnt - 1),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 - 1),4) & conv_std_logic_vector(crate_cnt,2) & FTU_RS485_START_DELIM; FTU_brd_add_sig <= conv_std_logic_vector((FTU_cnt - 1),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 - 1),4) & conv_std_logic_vector(crate_cnt,2) & FTU_RS485_START_DELIM; FTU_brd_add_sig <= conv_std_logic_vector((FTU_cnt - 1),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_SINGLE_FTU => -- send configuration to one FTU rec_reset_sig <= '0'; if (FTU_command_cnt_2 = 0) then -- DACs FTU_command_cnt_2 <= FTU_command_cnt_2 + 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_2(4)(15 downto 8) & FTU_dac_array_RAM_sig_2(4)(7 downto 0) & FTU_dac_array_RAM_sig_2(3)(15 downto 8) & FTU_dac_array_RAM_sig_2(3)(7 downto 0) & FTU_dac_array_RAM_sig_2(2)(15 downto 8) & FTU_dac_array_RAM_sig_2(2)(7 downto 0) & FTU_dac_array_RAM_sig_2(1)(15 downto 8) & FTU_dac_array_RAM_sig_2(1)(7 downto 0) & FTU_dac_array_RAM_sig_2(0)(15 downto 8) & FTU_dac_array_RAM_sig_2(0)(7 downto 0) & "00000000" & FIRMWARE_ID & FTM_ADDRESS & "00" & conv_std_logic_vector(single_FTU_slot_sig,4) & conv_std_logic_vector(single_FTU_crate_sig,2) & FTU_RS485_START_DELIM; FTU_brd_add_sig <= conv_std_logic_vector(single_FTU_slot_sig,4) & conv_std_logic_vector(single_FTU_crate_sig,2); FTU_command_sig <= "00000000"; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_1; elsif (FTU_command_cnt_2 = 1) then -- enables FTU_command_cnt_2 <= FTU_command_cnt_2 + 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_2(3)(15 downto 8) & FTU_enable_array_RAM_sig_2(3)(7 downto 0) & FTU_enable_array_RAM_sig_2(2)(15 downto 8) & FTU_enable_array_RAM_sig_2(2)(7 downto 0) & FTU_enable_array_RAM_sig_2(1)(15 downto 8) & FTU_enable_array_RAM_sig_2(1)(7 downto 0) & FTU_enable_array_RAM_sig_2(0)(15 downto 8) & FTU_enable_array_RAM_sig_2(0)(7 downto 0) & "00000011" & FIRMWARE_ID & FTM_ADDRESS & "00" & conv_std_logic_vector(single_FTU_slot_sig,4) & conv_std_logic_vector(single_FTU_crate_sig,2) & FTU_RS485_START_DELIM; FTU_brd_add_sig <= conv_std_logic_vector(single_FTU_slot_sig,4) & conv_std_logic_vector(single_FTU_crate_sig,2); FTU_command_sig <= "00000011"; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_1; else FTU_command_cnt_2 <= 0; enable_crc_from_FSM_sig <= '0'; FTM_ftu_rs485_control_State <= CONFIG_SINGLE_FTU_END; end if; when TRANSMIT_CONFIG_1 => -- wait one cycle for CRC calculation enable_crc_from_FSM_sig <= '0'; crc_data_from_FSM_sig_cp <= crc_data_from_FSM_sig; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_2; when TRANSMIT_CONFIG_SINGLE_FTU_1 => -- wait one cycle for CRC calculation enable_crc_from_FSM_sig <= '0'; crc_data_from_FSM_sig_cp <= crc_data_from_FSM_sig; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_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; ftu_error_data <= crc_sig & crc_data_from_FSM_sig_cp; 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_SINGLE_FTU_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_SINGLE_FTU_2; elsif (frame_cnt = 27) then frame_cnt <= frame_cnt + 1; ftu_error_data <= crc_sig & crc_data_from_FSM_sig_cp; tx_data_sig <= crc_sig; tx_start_sig <= '1'; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_2; else frame_cnt <= 0; reset_crc_from_FSM_sig <= '1'; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_3; end if; else tx_start_sig <= '0'; FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU_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'; if (retry_cnt = 0) then -- no errors FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG; else -- send error message and move to next command; ftu_error_calls <= conv_std_logic_vector((retry_cnt + 1), 16); after_error_State <= TRANSMIT_CONFIG; FTM_ftu_rs485_control_State <= SEND_ERROR_1; end if; 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; -- send error message and move to next command ftu_error_calls <= (others => '0'); after_error_State <= TRANSMIT_CONFIG; FTM_ftu_rs485_control_State <= SEND_ERROR_1; end if; end if; end if; when TRANSMIT_CONFIG_SINGLE_FTU_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'; if (retry_cnt = 0) then -- no errors FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU; else -- send error message and move to next command; ftu_error_calls <= conv_std_logic_vector((retry_cnt + 1), 16); after_error_State <= TRANSMIT_CONFIG_SINGLE_FTU; FTM_ftu_rs485_control_State <= SEND_ERROR_1; end if; 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_SINGLE_FTU_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_2 <= FTU_command_cnt_2 - 1; -- try this command again FTM_ftu_rs485_control_State <= TRANSMIT_CONFIG_SINGLE_FTU; else retry_cnt <= 0; FTU_command_cnt_2 <= FTU_command_cnt_2; -- send error message and move to next command ftu_error_calls <= (others => '0'); after_error_State <= TRANSMIT_CONFIG_SINGLE_FTU; FTM_ftu_rs485_control_State <= SEND_ERROR_1; end if; end if; end if; when SEND_ERROR_1 => -- send an error message ftu_error_send <= '1'; if (ftu_error_send_ack = '1') then ftu_error_send <= '0'; FTM_ftu_rs485_control_State <= SEND_ERROR_2; end if; when SEND_ERROR_2 => if (ftu_error_send_ready = '1') then FTM_ftu_rs485_control_State <= after_error_state; end if; when CONFIG_SINGLE_FTU_END => config_single_FTU_started <= '0'; config_single_FTU_done <= '1'; sel_crate_sig <= "111"; FTM_ftu_rs485_control_State <= IDLE; 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'; --rec_reset_sig <= '1'; FTM_ftu_rs485_control_State <= PING_2; when PING_2 => -- transmit byte by byte rec_reset_sig <= '0'; 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'; rec_reset_sig <= '1'; -- new 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 + (crate_cnt * NO_OF_FTUS_PER_CRATE * NO_OF_FTU_LIST_REG) + ((FTU_cnt - 1) * 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"; FTU_answer_array_sig(0) <= 0; FTU_answer_array_sig(1) <= 0; FTU_answer_array_sig(2) <= 0; FTU_answer_array_sig(3) <= 0; no_of_FTU_answer_sig <= 0; 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); addr_FTUlist_RAM <= conv_std_logic_vector((FTU_list_header_cnt), FTU_LIST_RAM_ADDR_WIDTH); --if ((FTU_list_header_cnt - 1) = 0) then if ((FTU_list_header_cnt) = 0) then data_FTUlist_RAM <= conv_std_logic_vector(no_of_FTU_answer_sig, 16); --elsif ((FTU_list_header_cnt - 1) < 5) then elsif ((FTU_list_header_cnt) < 5) then --data_FTUlist_RAM <= conv_std_logic_vector(FTU_answer_array_sig(FTU_list_header_cnt - 2), 16); data_FTUlist_RAM <= conv_std_logic_vector(FTU_answer_array_sig(FTU_list_header_cnt - 1), 16); --elsif ((FTU_list_header_cnt - 1) < 9) then elsif ((FTU_list_header_cnt) < 9) then --data_FTUlist_RAM <= active_FTU_array_sig(FTU_list_header_cnt - 6); --data_FTUlist_RAM <= conv_std_logic_vector(FTU_list_header_cnt - 6, 16); data_FTUlist_RAM <= active_FTU_array_sig(FTU_list_header_cnt - 5); 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 FTU_list_header_cnt <= FTU_list_header_cnt + 1; FTM_ftu_rs485_control_State <= PING_END; end if; when RATES => -- read all FTU rates 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" & "00000010" & 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 <= "00000010"; FTM_ftu_rs485_control_State <= RATES_1; else FTM_ftu_rs485_control_State <= RATES; end if; else crate_cnt <= crate_cnt + 1; FTU_cnt <= 0; FTM_ftu_rs485_control_State <= RATES; end if; else crate_cnt <= 0; read_rates_started <= '0'; read_rates_done <= '1'; sel_crate_sig <= "111"; FTM_ftu_rs485_control_State <= IDLE; end if; when RATES_1 => -- wait one cycle for CRC calculation enable_crc_from_FSM_sig <= '0'; --rec_reset_sig <= '1'; --new crc_data_from_FSM_sig_cp <= crc_data_from_FSM_sig; FTM_ftu_rs485_control_State <= RATES_2; when RATES_2 => -- transmit byte by byte rec_reset_sig <= '0'; --new 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 <= RATES_2; elsif (frame_cnt = 27) then frame_cnt <= frame_cnt + 1; ftu_error_data <= crc_sig & crc_data_from_FSM_sig_cp; tx_data_sig <= crc_sig; tx_start_sig <= '1'; rec_reset_sig <= '1'; FTM_ftu_rs485_control_State <= RATES_2; else frame_cnt <= 0; reset_crc_from_FSM_sig <= '1'; FTM_ftu_rs485_control_State <= RATES_3; end if; else tx_start_sig <= '0'; FTM_ftu_rs485_control_State <= RATES_2; end if; when RATES_3 => -- wait for FTU answer reset_crc_from_FSM_sig <= '0'; if (FTU_answer_ok_sig = '1') then timeout_cnt <= 0; sel_crc_input_source_sig <= '0'; --FTM_ftu_rs485_control_State <= RATES; if (retry_cnt = 0) then -- no errors FTM_ftu_rs485_control_State <= DD_RAM; else -- send error message and move to next command; ftu_error_calls <= conv_std_logic_vector((retry_cnt + 1), 16); after_error_State <= DD_RAM; FTM_ftu_rs485_control_State <= SEND_ERROR_1; end if; else if (timeout_cnt < FTU_RS485_TIMEOUT) then timeout_cnt <= timeout_cnt + 1; sel_crc_input_source_sig <= '1'; FTM_ftu_rs485_control_State <= RATES_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 <= RATES; else --retry_cnt <= 0; FTU_cnt <= FTU_cnt; -- move on ftu_error_calls <= (others => '0'); after_error_State <= DD_RAM; FTM_ftu_rs485_control_State <= SEND_ERROR_1; end if; end if; end if; when DD_RAM => -- write rates of actual FTU to DD RAM rec_reset_sig <= '0'; if (DD_RAM_reg_cnt < NO_OF_DD_RAM_REG) then DD_RAM_reg_cnt <= DD_RAM_reg_cnt + 1; FTU_cnt_offset_sig <= ((FTU_cnt - 1) * NO_OF_DD_RAM_REG); crate_cnt_offset_sig <= (crate_cnt * NO_OF_FTUS_PER_CRATE * NO_OF_DD_RAM_REG); FTM_ftu_rs485_control_State <= DD_RAM_1; else DD_RAM_reg_cnt <= 0; retry_cnt <= 0; FTM_ftu_rs485_control_State <= RATES; end if; when DD_RAM_1 => if (dynamic_RAM_busy = '0') then write_dynamic_RAM <= '1'; addr_dynamic_RAM <= conv_std_logic_vector(DD_BLOCK_SIZE_GENERAL + crate_cnt_offset_sig + --(crate_cnt * NO_OF_FTUS_PER_CRATE * NO_OF_DD_RAM_REG) + --((FTU_cnt - 1) * NO_OF_DD_RAM_REG) + FTU_cnt_offset_sig + (DD_RAM_reg_cnt - 1), DYNAMIC_RAM_ADDR_WIDTH); if ( (retry_cnt < FTU_RS485_NO_OF_RETRY) and (FTU_cnt_offset_sig < (NO_OF_FTUS_PER_CRATE * NO_OF_DD_RAM_REG)) and (crate_cnt_offset_sig < (NO_OF_CRATES * NO_OF_FTUS_PER_CRATE * NO_OF_DD_RAM_REG)) ) then if ((DD_RAM_reg_cnt - 1) = 0) then data_dynamic_RAM <= FTU_rate_array_sig(0)(31 downto 16); elsif ((DD_RAM_reg_cnt - 1) = 1) then data_dynamic_RAM <= FTU_rate_array_sig(0)(15 downto 0); elsif ((DD_RAM_reg_cnt - 1) = 2) then data_dynamic_RAM <= FTU_rate_array_sig(1)(31 downto 16); elsif ((DD_RAM_reg_cnt - 1) = 3) then data_dynamic_RAM <= FTU_rate_array_sig(1)(15 downto 0); elsif ((DD_RAM_reg_cnt - 1) = 4) then data_dynamic_RAM <= FTU_rate_array_sig(2)(31 downto 16); elsif ((DD_RAM_reg_cnt - 1) = 5) then data_dynamic_RAM <= FTU_rate_array_sig(2)(15 downto 0); elsif ((DD_RAM_reg_cnt - 1) = 6) then data_dynamic_RAM <= FTU_rate_array_sig(3)(31 downto 16); elsif ((DD_RAM_reg_cnt - 1) = 7) then data_dynamic_RAM <= FTU_rate_array_sig(3)(15 downto 0); elsif ((DD_RAM_reg_cnt - 1) = 8) then data_dynamic_RAM <= FTU_rate_array_sig(4)(31 downto 16); elsif ((DD_RAM_reg_cnt - 1) = 9) then data_dynamic_RAM <= FTU_rate_array_sig(4)(15 downto 0); elsif ((DD_RAM_reg_cnt - 1) = 10) then data_dynamic_RAM <= "00000000" & FTU_overflow_sig; elsif ((DD_RAM_reg_cnt - 1) = 11) then data_dynamic_RAM <= "00000000" & FTU_crc_error_cnt_sig; -- elsif ((DD_RAM_reg_cnt - 1) = 10) then -- data_dynamic_RAM <= "0000" & conv_std_logic_vector(DD_BLOCK_SIZE_GENERAL + -- --((FTU_cnt - 1) * NO_OF_DD_RAM_REG) + -- FTU_cnt_offset_sig + -- (DD_RAM_reg_cnt - 1), DYNAMIC_RAM_ADDR_WIDTH); -- elsif ((DD_RAM_reg_cnt - 1) = 11) then -- --data_dynamic_RAM <= "0000" & conv_std_logic_vector(FTU_cnt_offset_sig, DYNAMIC_RAM_ADDR_WIDTH); -- data_dynamic_RAM <= "0000" & conv_std_logic_vector(DD_BLOCK_SIZE_GENERAL + -- --((FTU_cnt - 1) * NO_OF_DD_RAM_REG) + -- FTU_cnt_offset_sig + -- (DD_RAM_reg_cnt - 1), DYNAMIC_RAM_ADDR_WIDTH); end if; else data_dynamic_RAM <= (others => '0'); end if; FTM_ftu_rs485_control_State <= DD_RAM_2; end if; when DD_RAM_2 => if (dynamic_RAM_started = '1') then write_dynamic_RAM <= '0'; FTM_ftu_rs485_control_State <= DD_RAM_3; end if; when DD_RAM_3 => if (dynamic_RAM_ready = '1') then FTM_ftu_rs485_control_State <= DD_RAM; end if; 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, rx_busy_0_sig, rx_busy_1_sig, rx_busy_2_sig, rx_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; rx_busy_sig <= rx_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; rx_busy_sig <= rx_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; rx_busy_sig <= rx_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; rx_busy_sig <= rx_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'; rx_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); start_int_sig <= rec_valid_sig and (not rx_busy_sig); -- avoid continuing to early after FTU answer end Behavioral;