---------------------------------------------------------------------------------- -- Company: ETH Zurich, Institute for Particle Physics -- Engineer: Q. Weitzel -- -- Create Date: 15:56:13 02/28/2011 -- Design Name: -- Module Name: FTM_central_control - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: Central FSM for FTM firmware -- -- 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_central_control is port( clk : IN std_logic; clk_ready : in std_logic; clk_scaler : IN std_logic; new_config : IN std_logic; config_started : OUT std_logic := '0'; config_started_ack : IN std_logic; config_start_eth : OUT std_logic := '0'; config_started_eth : IN std_logic; config_ready_eth : IN std_logic; config_start_ftu : OUT std_logic := '0'; config_started_ftu : IN std_logic ; config_ready_ftu : IN std_logic ; ping_ftu_start : IN std_logic; ping_ftu_started : OUT std_logic := '0'; ping_ftu_ready : OUT std_logic := '0'; ping_ftu_start_ftu : OUT std_logic := '0'; ping_ftu_started_ftu : IN std_logic; ping_ftu_ready_ftu : IN std_logic; rates_ftu : OUT std_logic := '0'; rates_started_ftu : IN std_logic; rates_ready_ftu : IN std_logic; prescaling_FTU01 : IN std_logic_vector(7 downto 0); dd_send : OUT std_logic := '0'; dd_send_ack : IN std_logic; dd_send_ready : IN std_logic; dd_block_ready_ftu : out std_logic := '0'; dd_block_start_ack_ftu : in std_logic; dd_block_start_ftu : out std_logic := '0'; config_start_cc : out std_logic := '0'; config_started_cc : in std_logic; config_ready_cc : in std_logic; config_trigger : out std_logic := '0'; config_trigger_done : in std_logic; dna_start : out std_logic := '0'; dna_ready : in std_logic; crate_reset : IN std_logic; crate_reset_ack : OUT std_logic := '0'; crate_reset_param : IN std_logic_vector (15 DOWNTO 0); start_run : IN std_logic; start_run_ack : OUT std_logic := '0'; stop_run : IN std_logic; stop_run_ack : OUT std_logic := '0'; current_cc_state : OUT std_logic_vector (15 DOWNTO 0) := X"FFFF"; cc_state_test : OUT std_logic_vector ( 7 downto 0) := X"FF"; start_run_param : IN std_logic_vector (15 DOWNTO 0); start_run_num_events : IN std_logic_vector (31 DOWNTO 0); trigger_start : out std_logic := '0'; trigger_stop : out std_logic := '1'; enable_ID_sending : out std_logic := '0'; reset_timer : out std_logic := '0'; crate_res_0 : out std_logic := '1'; crate_res_1 : out std_logic := '1'; crate_res_2 : out std_logic := '1'; crate_res_3 : out std_logic := '1' ); end FTM_central_control; architecture Behavioral of FTM_central_control is signal reset_scaler_sig : std_logic := '0'; signal reset_period_sig : std_logic := '0'; signal scaler_counts_sig : integer := 0; signal scaler_period_sig : integer range 0 to 128 * (LOW_FREQUENCY / SCALER_FREQ_DIVIDER) := 128 * (LOW_FREQUENCY / SCALER_FREQ_DIVIDER); signal period_finished_sig : std_logic := '0'; signal wait_cnt_sig : integer range 0 to 10 := 0; signal new_period_sr_sig : std_logic_vector(1 downto 0) := (others => '0'); signal new_period_sig : std_logic := '0'; signal new_period_ack_sig : std_logic := '0'; signal prescaling_FTU01_sig : std_logic_vector(7 downto 0) := "00100111"; signal reset_cnt_sig : integer range 0 to RESET_TIME := 0; signal crate_reset_param_sig : std_logic_vector (15 DOWNTO 0) := (others => '0'); type state_central_proc_type is (CP_INIT, CP_INIT_DNA, CP_INIT_TIMER, CP_RUNNING, CP_RUNNING_01, CP_RUNNING_02, CP_CONFIG_ACK, CP_CONFIG_START, CP_CONFIG, CP_CONFIG_01, CP_CONFIG_CC, CP_CONFIG_CC_01, CP_CONFIG_FTU, CP_CONFIG_FTU_01, CP_CONFIG_SCALER, CP_CONFIG_SCALER_01, CP_CONFIG_TRIGGER, CP_CONFIG_TRIGGER_01, CP_IDLE, CP_PING, CP_START_RATES, CP_READ_RATES, CP_READ_RATES_01, CP_SEND_START, CP_SEND_END, CP_CRATE_RESET, CP_CRATE_RESET_01, CP_CRATE_RESET_ACK); signal state_central_proc : state_central_proc_type := CP_INIT; signal after_rates_state : state_central_proc_type := CP_IDLE; signal after_ping_state : state_central_proc_type := CP_IDLE; begin --central_proc : process (clk, prescaling_FTU01) central_proc : process (clk) begin if rising_edge (clk) then case state_central_proc is when CP_INIT => -- wait for DCMs to lock current_cc_state <= X"FFFF"; cc_state_test <= X"01"; if (clk_ready = '1') then state_central_proc <= CP_INIT_DNA; end if; when CP_INIT_DNA => -- get FPGA DNA current_cc_state <= X"FFFF"; cc_state_test <= X"01"; if (dna_ready = '1') then state_central_proc <= CP_INIT_TIMER; dna_start <= '0'; reset_timer <= '1'; -- reset timer after power-up else dna_start <= '1'; state_central_proc <= CP_INIT_DNA; end if; when CP_INIT_TIMER => current_cc_state <= X"FFFF"; cc_state_test <= X"01"; reset_timer <= '0'; -- finish reset timer after power-up state_central_proc <= CP_CONFIG; when CP_CONFIG_START => current_cc_state <= FTM_STATE_CFG; cc_state_test <= X"02"; if (config_started_ack = '1') then config_started <= '0'; state_central_proc <= CP_CONFIG; end if; when CP_CONFIG => current_cc_state <= FTM_STATE_CFG; cc_state_test <= X"03"; config_start_eth <= '1'; if (config_started_eth = '1') then config_start_eth <= '0'; state_central_proc <= CP_CONFIG_01; end if; when CP_CONFIG_01 => current_cc_state <= FTM_STATE_CFG; cc_state_test <= X"04"; if (config_ready_eth = '1') then state_central_proc <= CP_CONFIG_CC; --state_central_proc <= CP_CONFIG_SCALER; --state_central_proc <= CP_IDLE; --state_central_proc <= CP_CRATE_RESET; end if; when CP_CONFIG_CC => current_cc_state <= FTM_STATE_CFG; cc_state_test <= X"05"; config_start_cc <= '1'; if (config_started_cc = '1') then config_start_cc <= '0'; state_central_proc <= CP_CONFIG_CC_01; end if; when CP_CONFIG_CC_01 => current_cc_state <= FTM_STATE_CFG; cc_state_test <= X"06"; if (config_ready_cc = '1') then state_central_proc <= CP_CONFIG_FTU; end if; when CP_CONFIG_FTU => current_cc_state <= FTM_STATE_CFG; cc_state_test <= X"07"; config_start_ftu <= '1'; if (config_started_ftu = '1') then config_start_ftu <= '0'; state_central_proc <= CP_CONFIG_FTU_01; end if; when CP_CONFIG_FTU_01 => current_cc_state <= FTM_STATE_CFG; cc_state_test <= X"08"; if (config_ready_ftu = '1') then state_central_proc <= CP_CONFIG_SCALER; end if; when CP_CONFIG_SCALER => current_cc_state <= FTM_STATE_CFG; cc_state_test <= X"09"; prescaling_FTU01_sig <= prescaling_FTU01; --reset_period_sig <= '1'; state_central_proc <= CP_CONFIG_SCALER_01; when CP_CONFIG_SCALER_01 => current_cc_state <= FTM_STATE_CFG; cc_state_test <= X"0A"; --reset_period_sig <= '0'; if wait_cnt_sig < 5 then wait_cnt_sig <= wait_cnt_sig + 1; reset_scaler_sig <= '1'; state_central_proc <= CP_CONFIG_SCALER_01; else wait_cnt_sig <= 0; reset_scaler_sig <= '0'; state_central_proc <= CP_CONFIG_TRIGGER; end if; when CP_CONFIG_TRIGGER => current_cc_state <= FTM_STATE_CFG; cc_state_test <= X"0B"; --config trigger_manager block config_trigger <= '1'; state_central_proc <= CP_CONFIG_TRIGGER_01; when CP_CONFIG_TRIGGER_01 => current_cc_state <= FTM_STATE_CFG; cc_state_test <= X"0C"; config_trigger <= '0'; if (config_trigger_done = '1') then state_central_proc <= CP_IDLE; end if; when CP_IDLE => current_cc_state <= FTM_STATE_IDLE; reset_timer <= '0'; cc_state_test <= X"0D"; stop_run_ack <= '1'; start_run_ack <= '0'; if (new_config = '1') then config_started <= '1'; start_run_ack <= '1'; --remove this line??? state_central_proc <= CP_CONFIG_START; elsif (ping_ftu_start = '1') then ping_ftu_start_ftu <= '1'; if (ping_ftu_started_ftu = '1') then ping_ftu_start_ftu <= '0'; ping_ftu_started <= '1'; ping_ftu_ready <= '0'; after_ping_state <= CP_IDLE; state_central_proc <= CP_PING; end if; --elsif (scaler_counts_sig = scaler_period_sig) then elsif (new_period_sig = '1') then new_period_ack_sig <= '1'; --rates_ftu <= '1'; --state_central_proc <= CP_READ_RATES; after_rates_state <= CP_IDLE; state_central_proc <= CP_START_RATES; elsif (start_run = '1') then start_run_ack <= '1'; if (start_run_param = PAR_START_RUN) then reset_timer <= '1'; state_central_proc <= CP_RUNNING; end if; elsif (crate_reset = '1') then crate_reset_param_sig <= crate_reset_param; crate_reset_ack <= '1'; state_central_proc <= CP_CRATE_RESET; end if; when CP_RUNNING => reset_timer <= '0'; current_cc_state <= FTM_STATE_RUN; cc_state_test <= X"0E"; if (start_run = '0') then start_run_ack <= '0'; stop_run_ack <= '0'; state_central_proc <= CP_RUNNING_01; end if; when CP_RUNNING_01 => current_cc_state <= FTM_STATE_RUN; cc_state_test <= X"0F"; start_run_ack <= '1'; trigger_start <= '1'; trigger_stop <= '0'; enable_Id_sending <= '1'; if (new_config = '1') then config_started <= '1'; state_central_proc <= CP_CONFIG_ACK; elsif (ping_ftu_start = '1') then ping_ftu_start_ftu <= '1'; if (ping_ftu_started_ftu = '1') then ping_ftu_start_ftu <= '0'; ping_ftu_started <= '1'; ping_ftu_ready <= '0'; after_ping_state <= CP_RUNNING_01; state_central_proc <= CP_PING; end if; elsif (new_period_sig = '1') then new_period_ack_sig <= '1'; --rates_ftu <= '1'; --state_central_proc <= CP_READ_RATES; after_rates_state <= CP_RUNNING_01; state_central_proc <= CP_START_RATES; elsif (stop_run = '1') then stop_run_ack <= '1'; trigger_start <= '0'; trigger_stop <= '1'; enable_Id_sending <= '0'; state_central_proc <= CP_RUNNING_02; elsif (crate_reset = '1') then crate_reset_ack <= '1'; state_central_proc <= CP_CRATE_RESET_ACK; end if; when CP_RUNNING_02 => current_cc_state <= FTM_STATE_RUN; cc_state_test <= X"10"; if (stop_run = '0') then stop_run_ack <= '0'; reset_timer <= '1'; state_central_proc <= CP_IDLE; end if; when CP_CONFIG_ACK => cc_state_test <= X"11"; if (config_started_ack = '1') then config_started <= '0'; state_central_proc <= CP_RUNNING_01; end if; when CP_PING => cc_state_test <= X"12"; if (ping_ftu_ready_ftu = '1') then if (ping_ftu_start = '0') then ping_ftu_started <= '0'; ping_ftu_ready <= '1'; --state_central_proc <= CP_IDLE; state_central_proc <= after_ping_state; end if; end if; when CP_START_RATES => cc_state_test <= X"13"; new_period_ack_sig <= '0'; dd_block_start_ftu <= '1'; dd_block_ready_ftu <= '0'; if (dd_block_start_ack_ftu = '1') then dd_block_start_ftu <= '0'; rates_ftu <= '1'; state_central_proc <= CP_READ_RATES; end if; when CP_READ_RATES => cc_state_test <= X"14"; new_period_ack_sig <= '0'; if (rates_started_ftu = '1') then rates_ftu <= '0'; state_central_proc <= CP_READ_RATES_01; end if; when CP_READ_RATES_01 => cc_state_test <= X"15"; if (rates_ready_ftu = '1') then dd_block_ready_ftu <= '1'; if ( (start_run = '1') or (stop_run = '1') ) then state_central_proc <= after_rates_state; else state_central_proc <= CP_SEND_START; end if; end if; when CP_SEND_START => cc_state_test <= X"16"; dd_send <= '1'; if (dd_send_ack = '1') then dd_send <= '0'; state_central_proc <= CP_SEND_END; end if; when CP_SEND_END => cc_state_test <= X"17"; if (dd_send_ready = '1') then --state_central_proc <= CP_IDLE; state_central_proc <= after_rates_state; end if; when CP_CRATE_RESET_ACK => cc_state_test <= X"18"; if (crate_reset = '0') then crate_reset_ack <= '0'; state_central_proc <= CP_RUNNING_01; end if; when CP_CRATE_RESET => cc_state_test <= X"19"; if (crate_reset = '0') then crate_reset_ack <= '0'; state_central_proc <= CP_CRATE_RESET_01; end if; when CP_CRATE_RESET_01 => cc_state_test <= X"1A"; if (reset_cnt_sig < RESET_TIME) then reset_cnt_sig <= reset_cnt_sig + 1; if (crate_reset_param_sig = "0000000000000001") then crate_res_0 <= '0'; elsif (crate_reset_param_sig = "0000000000000010") then crate_res_1 <= '0'; elsif (crate_reset_param_sig = "0000000000000100") then crate_res_2 <= '0'; elsif (crate_reset_param_sig = "0000000000001000") then crate_res_3 <= '0'; end if; else reset_cnt_sig <= 0; crate_res_0 <= '1'; crate_res_1 <= '1'; crate_res_2 <= '1'; crate_res_3 <= '1'; state_central_proc <= CP_IDLE; end if; when others => cc_state_test <= X"1B"; end case; end if; end process central_proc; scaler_process: process(reset_scaler_sig, clk_scaler) begin if (reset_scaler_sig = '1') then scaler_counts_sig <= 0; period_finished_sig <= '0'; elsif rising_edge(clk_scaler) then if (scaler_counts_sig < (scaler_period_sig - 1)) then scaler_counts_sig <= scaler_counts_sig + 1; period_finished_sig <= '0'; else period_finished_sig <= '1'; scaler_counts_sig <= 0; end if; end if; end process scaler_process; -- process(reset_period_sig) -- begin -- if rising_edge(reset_period_sig) then -- if ((conv_integer(unsigned(prescaling_FTU01))) mod 2 = 0) then -- scaler_period_sig <= ((((conv_integer(unsigned(prescaling_FTU01)) / 2)) * (LOW_FREQUENCY / SCALER_FREQ_DIVIDER)) + (LOW_FREQUENCY / (2 * SCALER_FREQ_DIVIDER))); -- else -- scaler_period_sig <= (((conv_integer(unsigned(prescaling_FTU01)) - 1) / 2) + 1) * (LOW_FREQUENCY / SCALER_FREQ_DIVIDER); -- end if; -- end if; -- end process; process(prescaling_FTU01_sig) begin if ((conv_integer(unsigned(prescaling_FTU01_sig))) mod 2 = 0) then scaler_period_sig <= ((((conv_integer(unsigned(prescaling_FTU01_sig)) / 2)) * (LOW_FREQUENCY / SCALER_FREQ_DIVIDER)) + (LOW_FREQUENCY / (2 * SCALER_FREQ_DIVIDER))); else scaler_period_sig <= (((conv_integer(unsigned(prescaling_FTU01_sig)) - 1) / 2) + 1) * (LOW_FREQUENCY / SCALER_FREQ_DIVIDER); end if; end process; detect_period_finished: process(clk) begin if rising_edge(clk) then new_period_sr_sig <= new_period_sr_sig(new_period_sr_sig'left - 1 downto 0) & period_finished_sig; if(new_period_ack_sig = '1') then new_period_sig <= '0'; else if (new_period_sr_sig(1 downto 0) = "01") then new_period_sig <= '1'; end if; end if; end if; end process detect_period_finished; end Behavioral;