---------------------------------------------------------------------------------- -- Company: ETH Zurich, Institute for Particle Physics -- Engineer: Q. Weitzel, P. Vogler -- -- Create Date: 08/06/2010 -- Design Name: -- Module Name: FTU_control - Behavioral -- Project Name: -- Target Devices: -- Tool versions: -- Description: Control FSM of FACT FTU board -- -- 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 ftu_definitions; USE ftu_definitions.ftu_array_types.all; USE ftu_definitions.ftu_constants.all; ---- Uncomment the following library declaration if instantiating ---- any Xilinx primitives in this code. --library UNISIM; --use UNISIM.VComponents.all; entity FTU_control is port( clk_50MHz : IN std_logic; clk_ready : IN std_logic; config_started : IN std_logic; config_ready : IN std_logic; ram_doa : IN STD_LOGIC_VECTOR(7 downto 0); ram_dob : IN STD_LOGIC_VECTOR(15 downto 0); rate_array : IN rate_array_type; overflow_array : in STD_LOGIC_VECTOR(7 downto 0); new_rates : IN std_logic; reset : OUT std_logic; config_start : OUT std_logic; ram_ena : OUT std_logic; ram_enb : OUT std_logic; ram_wea : OUT STD_LOGIC_VECTOR(0 downto 0); ram_web : OUT STD_LOGIC_VECTOR(0 downto 0); ram_ada : OUT STD_LOGIC_VECTOR(4 downto 0); ram_adb : OUT STD_LOGIC_VECTOR(3 downto 0); ram_dia : OUT STD_LOGIC_VECTOR(7 downto 0); ram_dib : OUT STD_LOGIC_VECTOR(15 downto 0); dac_array : OUT dac_array_type; enable_array : OUT enable_array_type; cntr_reset : OUT STD_LOGIC; prescaling : OUT STD_LOGIC_VECTOR(7 downto 0) ); end FTU_control; architecture Behavioral of FTU_control is signal reset_sig : STD_LOGIC := '0'; --initialize reset to 0 at power up --DAC/SPI interface, default DACs come from RAM during INIT signal config_start_sig : STD_LOGIC := '0'; signal dac_array_sig : dac_array_type := (0,0,0,0,0,0,0,0); --enable signals for pixels in trigger, default values come from RAM during INIT signal enable_array_sig : enable_array_type := ("0000000000000000", --patch A "0000000000000000", --patch B "0000000000000000", --patch C "0000000000000000");--patch D signal rate_array_sig : rate_array_type; -- initialized in FTU_top signal cntr_reset_sig : STD_LOGIC := '0'; signal prescaling_sig : STD_LOGIC_VECTOR(7 downto 0) := "00011101"; -- 29 signal ram_ena_sig : STD_LOGIC := '0'; -- RAM enable for port A signal ram_enb_sig : STD_LOGIC := '0'; -- RAM enable for port B signal ram_wea_sig : STD_LOGIC_VECTOR(0 downto 0) := "0"; -- RAM write enable for port A signal ram_web_sig : STD_LOGIC_VECTOR(0 downto 0) := "0"; -- RAM write enable for port B signal ram_ada_sig : STD_LOGIC_VECTOR(4 downto 0) := (others => '0'); --RAM port A address signal ram_adb_sig : STD_LOGIC_VECTOR(3 downto 0) := (others => '0'); --RAM port B address signal ram_dia_sig : STD_LOGIC_VECTOR(7 downto 0) := (others => '0'); --RAM data in A signal ram_dib_sig : STD_LOGIC_VECTOR(15 downto 0) := (others => '0'); --RAM data in B --counter to loop through RAM signal ram_ada_cntr : INTEGER range 0 to 2**RAM_ADDR_WIDTH_A := 0; signal ram_adb_cntr : INTEGER range 0 to 2**RAM_ADDR_WIDTH_B := 0; signal ram_dac_cntr : INTEGER range 0 to (NO_OF_DAC - NO_OF_DAC_NOT_USED + 2) := 0; signal ram_enable_cntr : INTEGER range 0 to (NO_OF_ENABLE + 1) := 0; signal ram_counter_cntr : INTEGER range 0 to (NO_OF_COUNTER + 2) := 0; --includes overflow register signal wait_cntr : INTEGER range 0 to 2**RAM_ADDR_WIDTH_A := 0; signal new_rates_sig : STD_LOGIC := '0'; signal new_rates_busy : STD_LOGIC := '0'; signal new_DACs_in_RAM : STD_LOGIC := '0'; signal new_enables_in_RAM : STD_LOGIC := '0'; signal new_prescaling_in_RAM : STD_LOGIC := '0'; type FTU_control_StateType is (IDLE, INIT, RUNNING, CONFIG_ENABLE, CONFIG_DAC, CONFIG_COUNTER, WRITE_RATES, RESET_ALL); signal FTU_control_State : FTU_control_StateType; begin --FTU control finite state machine FTU_control_FSM: process (clk_50MHz) begin if Rising_edge(clk_50MHz) then case FTU_control_State is when IDLE => -- wait for DCMs to lock reset_sig <= '0'; config_start_sig <= '0'; ram_ena_sig <= '0'; ram_wea_sig <= "0"; if (clk_ready = '1') then FTU_control_State <= INIT; end if; when INIT => -- load default config data to RAM, see also ftu_definitions.vhd for more info reset_sig <= '0'; new_rates_busy <= '1'; config_start_sig <= '0'; ram_ena_sig <= '1'; ram_wea_sig <= "1"; ram_ada_cntr <= ram_ada_cntr + 1; ram_ada_sig <= conv_std_logic_vector(ram_ada_cntr, RAM_ADDR_WIDTH_A); if (ram_ada_cntr < NO_OF_ENABLE*RAM_ADDR_RATIO) then -- default enables if (ram_ada_cntr mod 2 = 0) then ram_dia_sig <= DEFAULT_ENABLE(ram_ada_cntr / 2)(7 downto 0); else ram_dia_sig <= DEFAULT_ENABLE(ram_ada_cntr / 2)(15 downto 8); end if; FTU_control_State <= INIT; elsif (ram_ada_cntr < (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO)) then -- default counter values ram_dia_sig <= (others => '0'); FTU_control_State <= INIT; elsif (ram_ada_cntr < (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO)) then -- default DACs if (ram_ada_cntr < (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED - 1)*RAM_ADDR_RATIO)) then if (ram_ada_cntr mod 2 = 0) then ram_dia_sig <= conv_std_logic_vector(DEFAULT_DAC((ram_ada_cntr - (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO)) / 2),16)(7 downto 0); else ram_dia_sig <= conv_std_logic_vector(DEFAULT_DAC((ram_ada_cntr - (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO)) / 2),16)(15 downto 8); end if; else if (ram_ada_cntr mod 2 = 0) then ram_dia_sig <= conv_std_logic_vector(DEFAULT_DAC(((ram_ada_cntr - (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO)) / 2) + NO_OF_DAC_NOT_USED),16)(7 downto 0); else ram_dia_sig <= conv_std_logic_vector(DEFAULT_DAC(((ram_ada_cntr - (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO)) / 2) + NO_OF_DAC_NOT_USED),16)(15 downto 8); end if; end if; FTU_control_State <= INIT; elsif (ram_ada_cntr = (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO)) then -- default prescaling ram_dia_sig <= conv_std_logic_vector(DEFAULT_PRESCALING,8); FTU_control_State <= INIT; elsif (ram_ada_cntr = (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO) + 1) then -- default overflow register ram_dia_sig <= (others => '0'); FTU_control_State <= INIT; elsif (ram_ada_cntr = (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO) + 2) then -- default checksum ram_dia_sig <= (others => '0'); FTU_control_State <= INIT; elsif (ram_ada_cntr = (NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO) + 3) then -- empty RAM cell ram_dia_sig <= (others => '0'); FTU_control_State <= INIT; else ram_dia_sig <= (others => '0'); ram_ada_cntr <= 0; ram_ada_sig <= (others => '0'); ram_ena_sig <= '0'; ram_wea_sig <= "0"; new_DACs_in_RAM <= '1'; new_enables_in_RAM <= '1'; new_prescaling_in_RAM <= '1'; cntr_reset_sig <= '1'; new_rates_busy <= '0'; FTU_control_State <= RUNNING; end if; when RUNNING => -- count triggers and react to commands from FTM cntr_reset_sig <= '0'; reset_sig <= '0'; config_start_sig <= '0'; if (new_rates_sig = '1') then FTU_control_State <= WRITE_RATES; else if (new_DACs_in_RAM = '1') then ram_enb_sig <= '1'; ram_adb_sig <= conv_std_logic_vector((NO_OF_ENABLE + NO_OF_COUNTER), RAM_ADDR_WIDTH_B); FTU_control_State <= CONFIG_DAC; elsif (new_DACs_in_RAM = '0' and new_enables_in_RAM = '1') then ram_enb_sig <= '1'; ram_adb_sig <= conv_std_logic_vector(0, RAM_ADDR_WIDTH_B); FTU_control_State <= CONFIG_ENABLE; elsif (new_DACs_in_RAM = '0' and new_enables_in_RAM = '0' and new_prescaling_in_RAM = '1') then ram_ena_sig <= '1'; ram_ada_sig <= conv_std_logic_vector((NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO), RAM_ADDR_WIDTH_A); FTU_control_State <= CONFIG_COUNTER; else FTU_control_State <= RUNNING; end if; end if; when CONFIG_COUNTER => wait_cntr <= wait_cntr + 1; new_rates_busy <= '1'; if (wait_cntr = 0) then FTU_control_State <= CONFIG_COUNTER; elsif (wait_cntr = 1) then prescaling_sig <= ram_doa; FTU_control_State <= CONFIG_COUNTER; else cntr_reset_sig <= '1'; ram_ada_sig <= (others => '0'); wait_cntr <= 0; new_prescaling_in_RAM <= '0'; ram_ena_sig <= '0'; new_rates_busy <= '0'; FTU_control_State <= RUNNING; end if; when CONFIG_ENABLE => ram_enable_cntr <= ram_enable_cntr + 1; new_rates_busy <= '1'; if (ram_enable_cntr = 0) then ram_adb_sig <= conv_std_logic_vector(ram_enable_cntr + 1, RAM_ADDR_WIDTH_B); FTU_control_State <= CONFIG_ENABLE; elsif (ram_enable_cntr > 0 and ram_enable_cntr < NO_OF_ENABLE + 1) then ram_adb_sig <= conv_std_logic_vector(ram_enable_cntr + 1, RAM_ADDR_WIDTH_B); enable_array_sig(ram_enable_cntr - 1) <= ram_dob; FTU_control_State <= CONFIG_ENABLE; else ram_adb_sig <= (others => '0'); ram_enable_cntr <= 0; new_enables_in_RAM <= '0'; ram_enb_sig <= '0'; cntr_reset_sig <= '1'; new_rates_busy <= '0'; FTU_control_State <= RUNNING; end if; when CONFIG_DAC => new_rates_busy <= '1'; if (ram_dac_cntr <= (NO_OF_DAC - NO_OF_DAC_NOT_USED + 2)) then ram_dac_cntr <= ram_dac_cntr + 1; if (ram_dac_cntr = 0) then FTU_control_State <= CONFIG_DAC; ram_adb_sig <= conv_std_logic_vector((NO_OF_ENABLE + NO_OF_COUNTER + ram_dac_cntr + 1), RAM_ADDR_WIDTH_B); elsif (ram_dac_cntr > 0 and ram_dac_cntr < (NO_OF_DAC - NO_OF_DAC_NOT_USED)) then dac_array_sig(ram_dac_cntr - 1) <= conv_integer(unsigned(ram_dob)); ram_adb_sig <= conv_std_logic_vector((NO_OF_ENABLE + NO_OF_COUNTER + ram_dac_cntr + 1), RAM_ADDR_WIDTH_B); FTU_control_State <= CONFIG_DAC; elsif (ram_dac_cntr > 0 and ram_dac_cntr < (NO_OF_DAC - NO_OF_DAC_NOT_USED + 1)) then dac_array_sig(ram_dac_cntr - 1 + NO_OF_DAC_NOT_USED) <= conv_integer(unsigned(ram_dob)); ram_adb_sig <= (others => '0'); FTU_control_State <= CONFIG_DAC; else ram_adb_sig <= (others => '0'); config_start_sig <= '1'; FTU_control_State <= CONFIG_DAC; end if; else if (config_ready = '1') then ram_dac_cntr <= 0; new_DACs_in_RAM <= '0'; cntr_reset_sig <= '1'; new_rates_busy <= '0'; FTU_control_State <= RUNNING; elsif (config_ready = '0' and config_started = '1') then ram_enb_sig <= '0'; config_start_sig <= '0'; FTU_control_State <= CONFIG_DAC; else FTU_control_State <= CONFIG_DAC; end if; end if; when WRITE_RATES => -- write trigger/patch rates to RAM B and overflow register to RAM A new_rates_busy <= '1'; ram_counter_cntr <= ram_counter_cntr + 1; if (ram_counter_cntr < NO_OF_COUNTER) then ram_enb_sig <= '1'; ram_web_sig <= "1"; ram_adb_sig <= conv_std_logic_vector((NO_OF_ENABLE + ram_counter_cntr), RAM_ADDR_WIDTH_B); ram_dib_sig <= conv_std_logic_vector(rate_array_sig(ram_counter_cntr), 16); FTU_control_State <= WRITE_RATES; elsif (ram_counter_cntr = NO_Of_COUNTER) then ram_dib_sig <= (others => '0'); ram_adb_sig <= (others => '0'); ram_enb_sig <= '0'; ram_web_sig <= "0"; ram_ena_sig <= '1'; ram_wea_sig <= "1"; ram_ada_sig <= conv_std_logic_vector(NO_OF_ENABLE*RAM_ADDR_RATIO + NO_OF_COUNTER*RAM_ADDR_RATIO + (NO_OF_DAC - NO_OF_DAC_NOT_USED)*RAM_ADDR_RATIO + 1, RAM_ADDR_WIDTH_A); ram_dia_sig <= overflow_array; FTU_control_State <= WRITE_RATES; else ram_ena_sig <= '0'; ram_wea_sig <= "0"; ram_counter_cntr <= 0; new_rates_busy <= '0'; FTU_control_State <= RUNNING; end if; when RESET_ALL => -- reset/clear and start from scratch reset_sig <= '1'; config_start_sig <= '0'; FTU_control_State <= IDLE; end case; end if; end process FTU_control_FSM; detect_new_rates: process(new_rates, new_rates_busy) begin if(new_rates_busy = '1') then new_rates_sig <= '0'; elsif rising_edge(new_rates) then new_rates_sig <= '1'; end if; end process detect_new_rates; reset <= reset_sig; config_start <= config_start_sig; dac_array <= dac_array_sig; enable_array <= enable_array_sig; rate_array_sig <= rate_array; cntr_reset <= cntr_reset_sig; prescaling <= prescaling_sig; ram_ena <= ram_ena_sig; ram_enb <= ram_enb_sig; ram_wea <= ram_wea_sig; ram_web <= ram_web_sig; ram_ada <= ram_ada_sig; ram_adb <= ram_adb_sig; ram_dia <= ram_dia_sig; ram_dib <= ram_dib_sig; end Behavioral;