From dff05660b7b684393bfd8629842e8f7f99c3bf5a Mon Sep 17 00:00:00 2001 From: Jan Michel Date: Wed, 18 Feb 2015 18:32:40 +0100 Subject: [PATCH] added clock switch to gbe hub - if configured for external clock, it switches back to internal if locking fails after power-up --- base/code/clock_switch.vhd | 138 ++++++++++++++++++++++++++++++++++++ trb3_gbe/config_default.vhd | 2 +- trb3_gbe/trb3_central.prj | 1 + trb3_gbe/trb3_central.vhd | 66 +++++++++-------- 4 files changed, 176 insertions(+), 31 deletions(-) create mode 100644 base/code/clock_switch.vhd diff --git a/base/code/clock_switch.vhd b/base/code/clock_switch.vhd new file mode 100644 index 0000000..06fd622 --- /dev/null +++ b/base/code/clock_switch.vhd @@ -0,0 +1,138 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + +library work; + use work.trb_net_components.all; + use work.trb_net_std.all; + use work.config.all; + +entity clock_switch is + port ( + INT_CLK_IN : in std_logic; -- dont care which clock + SYS_CLK_IN : in std_logic; + + BUS_RX : in CTRLBUS_RX; + BUS_TX : out CTRLBUS_TX; + + PLL_LOCK : in std_logic; + RESET_IN : in std_logic; + RESET_OUT : out std_logic; + + CLOCK_SELECT : out std_logic; + TRIG_SELECT : out std_logic; + CLK_MNGR1_USER : out std_logic_vector(3 downto 0); + CLK_MNGR2_USER : out std_logic_vector(3 downto 0); + + DEBUG_OUT : out std_logic_vector(31 downto 0) + ); +end entity; + +architecture clock_switch_arch of clock_switch is + constant USE_EXTERNAL_CLOCK_std : std_logic := std_logic_vector(to_unsigned(USE_EXTERNAL_CLOCK,1))(0); + + type INT_FSM_STATES_T is (WAIT_FOR_LOCK, WAIT_PLL_STABLE, OPERATING); + signal int_fsm_i : INT_FSM_STATES_T := WAIT_FOR_LOCK; + signal int_fsm_code_i : std_logic_vector(3 downto 0); + + signal select_tc : std_logic_vector(7 downto 0); + signal select_trg : std_logic; + signal select_clk : std_logic := USE_EXTERNAL_CLOCK_std; +-- signal select_clk_sys : std_logic := USE_EXTERNAL_CLOCK_std; + signal select_clk_qsys : std_logic; + +begin + int_fsm_proc: process is + variable counter_v : integer range 0 to 2**16-1; + begin + wait until rising_edge(INT_CLK_IN); + RESET_OUT <= '1'; + case int_fsm_i is + when WAIT_FOR_LOCK => + int_fsm_code_i <= x"1"; + if PLL_LOCK = '1' then + int_fsm_i <= WAIT_PLL_STABLE; + counter_v := 0; + elsif counter_v = 2**16-1 then + select_clk <= '0'; + else + counter_v := counter_v + 1; + end if; + + when WAIT_PLL_STABLE => + int_fsm_code_i <= x"2"; + if PLL_LOCK = '0' then + counter_v := 0; + int_fsm_i <= WAIT_FOR_LOCK; + elsif counter_v = 2**12-1 then + int_fsm_i <= OPERATING; + else + counter_v := counter_v + 1; + end if; + + when OPERATING => + int_fsm_code_i <= x"3"; + RESET_OUT <= '0'; +-- if PLL_LOCK = '0' and RESET_IN = '0' then +-- int_fsm_i <= WAIT_FOR_LOCK; +-- elsif RESET_IN = '1' then +-- int_fsm_i <= WAIT_RESET; +-- counter_v := 0; +-- end if; +-- +-- when WAIT_RESET => +-- if RESET_IN = '0' then +-- counter_v := counter_v + 1;\ +-- elsif counter_v = 2**16-1 then +-- counter_v := 0; +-- int_fsm_i <= WAIT_FOR_LOCK; +-- else +-- counter_v := 0; +-- end if; + end case; + end process; + + + + TRIG_SELECT <= select_trg; + CLOCK_SELECT <= select_clk; --use on-board oscillator + CLK_MNGR1_USER <= select_tc(3 downto 0); + CLK_MNGR2_USER <= select_tc(7 downto 4); + + +proc_bus : process begin + wait until rising_edge(SYS_CLK_IN); + BUS_TX.ack <= '0'; + BUS_TX.nack <= '0'; + BUS_TX.unknown <= '0'; + BUS_TX.data <= (others => '0'); + + if BUS_RX.read = '1' then + BUS_TX.ack <= '1'; + if BUS_RX.addr(0) = '0' then + BUS_TX.data(0) <= select_trg; + BUS_TX.data(8) <= select_clk_qsys; + BUS_TX.data(19 downto 16) <= select_tc(3 downto 0); + BUS_TX.data(27 downto 24) <= select_tc(7 downto 4); + else + BUS_TX.data(3 downto 0) <= int_fsm_code_i; + end if; + elsif BUS_RX.write = '1' then + if BUS_RX.addr(0) = '0' then + select_trg <= BUS_RX.data(0); +-- select_clk_sys <= BUS_RX.data(8); + select_tc(3 downto 0) <= BUS_RX.data(19 downto 16); + select_tc(7 downto 4) <= BUS_RX.data(27 downto 24); + BUS_TX.ack <= '1'; + else + BUS_TX.unknown <= '1'; + end if; + end if; +end process; + + +SYNC_CLK_INT : signal_sync port map(RESET => '0', CLK0 => SYS_CLK_IN, CLK1 => SYS_CLK_IN, D_IN(0) => select_clk, D_OUT(0) => select_clk_qsys); +-- SYNC_CLK_SYS : signal_sync port map(RESET => '0', CLK0 => INT_CLK_IN, CLK1 => INT_CLK_IN, D_IN(0) => select_clk_sys, D_OUT(0) => select_clk_qint); + +end architecture; + diff --git a/trb3_gbe/config_default.vhd b/trb3_gbe/config_default.vhd index ba027b7..19997ff 100644 --- a/trb3_gbe/config_default.vhd +++ b/trb3_gbe/config_default.vhd @@ -29,7 +29,7 @@ package config is constant USE_RXCLOCK : integer := c_NO; --Run external 200 MHz clock source - constant USE_EXTERNAL_CLOCK : integer range c_NO to c_YES := c_NO; + constant USE_EXTERNAL_CLOCK : integer range c_NO to c_YES := c_YES; --Address settings constant INIT_ENDPOINT_ID : std_logic_vector := x"0005"; diff --git a/trb3_gbe/trb3_central.prj b/trb3_gbe/trb3_central.prj index 57a7bea..eabb418 100644 --- a/trb3_gbe/trb3_central.prj +++ b/trb3_gbe/trb3_central.prj @@ -60,6 +60,7 @@ add_file -vhdl -lib work "../../trbnet/trb_net16_hub_func.vhd" add_file -vhdl -lib work "config.vhd" add_file -vhdl -lib work "../../trbnet/trb_net_components.vhd" add_file -vhdl -lib work "../base/trb3_components.vhd" +add_file -vhdl -lib work "../base/code/clock_switch.vhd" add_file -vhdl -lib work "../../trbnet/basics/signal_sync.vhd" add_file -vhdl -lib work "../../trbnet/basics/pulse_sync.vhd" add_file -vhdl -lib work "../../trbnet/basics/priority_arbiter.vhd" diff --git a/trb3_gbe/trb3_central.vhd b/trb3_gbe/trb3_central.vhd index eb9048a..50d706c 100644 --- a/trb3_gbe/trb3_central.vhd +++ b/trb3_gbe/trb3_central.vhd @@ -255,11 +255,11 @@ signal gbe_stp_reg_write : std_logic; signal gbe_stp_reg_data_rd : std_logic_vector(31 downto 0); signal gbe_unknown : std_logic; -signal select_tc : std_logic_vector(31 downto 0) := (8 => USE_EXTERNAL_CLOCK_std, others => '0'); -signal select_tc_data_in : std_logic_vector(31 downto 0); -signal select_tc_write : std_logic; -signal select_tc_read : std_logic; -signal select_tc_ack : std_logic; +-- signal select_tc : std_logic_vector(31 downto 0) := (8 => USE_EXTERNAL_CLOCK_std, others => '0'); +-- signal select_tc_data_in : std_logic_vector(31 downto 0); +-- signal select_tc_write : std_logic; +-- signal select_tc_read : std_logic; +-- signal select_tc_ack : std_logic; signal trig_outputs : std_logic_vector(4 downto 0); signal trig_inputs : std_logic_vector(15 downto 0); @@ -280,8 +280,8 @@ signal stat_ack : std_logic := '0'; signal stat_nack : std_logic := '0'; signal stat_addr : std_logic_vector(15 downto 0) := (others => '0'); -signal busuart_rx : CTRLBUS_RX; -signal busuart_tx : CTRLBUS_TX; +signal busuart_rx, bustc_rx : CTRLBUS_RX; +signal busuart_tx, bustc_tx : CTRLBUS_TX; signal uart_tx : std_logic_vector(4 downto 0); signal uart_rx : std_logic_vector(4 downto 0); @@ -867,16 +867,16 @@ THE_BUS_HANDLER : trb_net16_regio_bus_handler BUS_UNKNOWN_ADDR_IN(4) => '0', -- Trigger and Clock Manager Settings - BUS_ADDR_OUT(6*16-1 downto 5*16) => open, - BUS_DATA_OUT(6*32-1 downto 5*32) => select_tc_data_in, - BUS_READ_ENABLE_OUT(5) => select_tc_read, - BUS_WRITE_ENABLE_OUT(5) => select_tc_write, + BUS_ADDR_OUT(6*16-1 downto 5*16) => bustc_rx.addr, + BUS_DATA_OUT(6*32-1 downto 5*32) => bustc_rx.data, + BUS_READ_ENABLE_OUT(5) => bustc_rx.read, + BUS_WRITE_ENABLE_OUT(5) => bustc_rx.write, BUS_TIMEOUT_OUT(5) => open, - BUS_DATA_IN(6*32-1 downto 5*32) => select_tc, - BUS_DATAREADY_IN(5) => select_tc_ack, - BUS_WRITE_ACK_IN(5) => select_tc_ack, - BUS_NO_MORE_DATA_IN(5) => '0', - BUS_UNKNOWN_ADDR_IN(5) => '0', + BUS_DATA_IN(6*32-1 downto 5*32) => bustc_tx.data, + BUS_DATAREADY_IN(5) => bustc_tx.ack, + BUS_WRITE_ACK_IN(5) => bustc_tx.ack, + BUS_NO_MORE_DATA_IN(5) => bustc_tx.nack, + BUS_UNKNOWN_ADDR_IN(5) => bustc_tx.unknown, --Trigger logic registers BUS_READ_ENABLE_OUT(6) => trig_read, @@ -1033,20 +1033,26 @@ end generate; -- Clock and Trigger Configuration --------------------------------------------------------------------------- -process begin - wait until rising_edge(clk_sys_i); - if select_tc_write = '1' then - select_tc <= select_tc_data_in; - end if; - select_tc_ack <= select_tc_read or select_tc_write; -end process; - - TRIGGER_SELECT <= select_tc(0); - CLOCK_SELECT <= select_tc(8); --use on-board oscillator - CLK_MNGR1_USER <= select_tc(19 downto 16); - CLK_MNGR2_USER <= select_tc(27 downto 24); - - + +THE_CLOCK_SWITCH: entity work.clock_switch + port map( + INT_CLK_IN => CLK_GPLL_RIGHT, + SYS_CLK_IN => clk_sys_i, + + BUS_RX => bustc_rx, + BUS_TX => bustc_tx, + + PLL_LOCK => pll_lock, + RESET_IN => reset_i, + RESET_OUT => open, + + CLOCK_SELECT => CLOCK_SELECT, + TRIG_SELECT => TRIGGER_SELECT, + CLK_MNGR1_USER => CLK_MNGR1_USER, + CLK_MNGR2_USER => CLK_MNGR2_USER, + + DEBUG_OUT => open + ); TRIGGER_OUT <= '0'; -- 2.43.0