LVL1_TRG_INFORMATION_IN : in std_logic_vector(23 downto 0);
LVL1_ERROR_PATTERN_OUT : out std_logic_vector(31 downto 0); --errorbits to CTS
LVL1_TRG_RELEASE_OUT : out std_logic := '0'; --release to CTS
-
+
LVL1_INT_TRG_NUMBER_OUT : out std_logic_vector(15 downto 0); -- increased after trigger release
- LVL1_INT_TRG_RESET_IN : in std_logic; -- reset internal trigger counter
+-- LVL1_INT_TRG_RESET_IN : in std_logic; -- reset internal trigger counter
LVL1_INT_TRG_LOAD_IN : in std_logic; -- load internal trigger counter
- LVL1_INT_TRG_COUNTER_IN : in std_logic_vector(15 downto 0); -- load value for internal trigger counter
-
+ LVL1_INT_TRG_COUNTER_IN : in std_logic_vector(15 downto 0); -- load value for internal trigger counter
+
--FEE logic / Data Handler
LVL1_TRG_DATA_VALID_OUT : out std_logic; -- trigger type, number, code, information are valid
LVL1_VALID_TIMING_TRG_OUT : out std_logic; -- valid timing trigger has been received
LVL1_INVALID_TRG_OUT : out std_logic; -- the current trigger is invalid (e.g. no timing trigger, no LVL1...)
LVL1_MULTIPLE_TRG_OUT : out std_logic; -- more than one timing trigger detected
LVL1_DELAY_OUT : out std_logic_vector(15 downto 0);
-
+
LVL1_ERROR_PATTERN_IN : in std_logic_vector(31 downto 0); -- error pattern from FEE
LVL1_TRG_RELEASE_IN : in std_logic := '0'; -- trigger release from FEE
-
+
--Stat/Control
- STATUS_OUT : out std_logic_vector (31 downto 0); -- bits for status registers
+ STATUS_OUT : out std_logic_vector (63 downto 0); -- bits for status registers
TRG_ENABLE_IN : in std_logic; -- trigger enable flag
TRG_INVERT_IN : in std_logic; -- trigger invert flag
--Debug
end component pulse_stretch;
-- state machine signals
-type STATES is (IDLE, BADTRG, TRGFND, LVL1FND, WAITREL, TOCFND, RELEASE, DONE);
+type STATES is (IDLE, BADTRG, TRGFND, LVL1FND, WAITREL, TOCFND, DONE);
signal CURRENT_STATE, NEXT_STATE: STATES;
signal toc_ce : std_logic; -- count enable for TRG/LVL1 timeout
signal next_toc_ce : std_logic;
+signal toc_save : std_logic; -- count enable for TRG/LVL1 timeout
+signal next_toc_save : std_logic;
signal toc_rst : std_logic; -- reset for timout
signal next_toc_rst : std_logic;
signal trg_rel : std_logic; -- release LVL1 channel
signal val_trg : std_logic; -- valid timing + LVL1 trigger
signal next_val_trg : std_logic;
signal val_ttl_trg : std_logic; -- valid timingtriggerless trigger (who invented that name?)
-signal next_val_ttl_trg : std_logic;
+signal next_val_ttl_trg : std_logic;
signal invalid_trg : std_logic; -- invalid trigger: LVL1 missing, or wrong information
signal next_invalid_trg : std_logic;
signal timing_trg_comb : std_logic;
signal timing_trg_rising : std_logic;
signal timing_trg_found : std_logic;
-signal timeout_ctr : unsigned(8 downto 0);
+signal timeout_ctr : unsigned(10 downto 0);
signal timeout_found : std_logic;
signal next_timeout_found : std_logic;
signal trg_num_match : std_logic;
signal next_error_pattern : std_logic_vector(31 downto 0);
signal lvl1_delay : std_logic_vector(15 downto 0);
+signal trigger_edge_count : unsigned(15 downto 0);
+signal trigger_length : unsigned(15 downto 0);
signal debug : std_logic_vector(15 downto 0);
begin
----------------------------------------------------------------------------
--- Debug signals
----------------------------------------------------------------------------
-debug(15 downto 12) <= bsm_x;
-debug(11 downto 9) <= (others => '0');
-debug(8 downto 0) <= std_logic_vector(timeout_ctr);
-
-DEBUG_OUT <= debug;
---------------------------------------------------------------------------
-- One process for registering combinatorial signals
if( rising_edge(CLOCK) ) then
timeout_found <= next_timeout_found;
trg_num_match <= next_trg_num_match;
- data_valid <= next_data_valid;
error_pattern <= next_error_pattern;
end if;
end process THE_SYNC_PROC;
---------------------------------------------------------------------------
-- Sync the external timing trigger, if necessary.
---------------------------------------------------------------------------
-GEN_SYNC: if ( TIMING_TRIGGER_RAW = 1 ) generate
+GEN_SYNC: if ( TIMING_TRIGGER_RAW = c_YES ) generate
THE_TIMING_TRG_SYNC: signal_sync
generic map( WIDTH => 1, DEPTH => 2 )
port map(
D_IN(0) => LVL1_TIMING_TRG_IN,
D_OUT(0) => synced_timing_trg
);
+
+ THE_TRIGGER_SHIFT_PROC: process( CLOCK )
+ begin
+ if( rising_edge(CLOCK) ) then
+ if( RESET = '1' ) then
+ timing_trg_reg <= (others => '0');
+ else
+ timing_trg_reg <= timing_trg_reg(2 downto 0) & timing_trg_comb; -- could be generalized here
+ end if;
+ end if;
+ end process THE_TRIGGER_SHIFT_PROC;
+
+ -- detect rising edge and valid length
+ THE_RISING_EDGE_PROC: process( CLOCK )
+ begin
+ if( rising_edge(CLOCK) ) then
+ if( RESET = '1' ) then
+ timing_trg_rising <= '0';
+ else
+ -- 0111 sequence marks the rising edge
+ timing_trg_rising <= not timing_trg_reg(3) and timing_trg_reg(2) and timing_trg_reg(1) and timing_trg_reg(0);
+ end if;
+ end if;
+ end process THE_RISING_EDGE_PROC;
+
end generate GEN_SYNC;
-GEN_NOSYNC: if ( TIMING_TRIGGER_RAW = 0 ) generate
+GEN_NOSYNC: if ( TIMING_TRIGGER_RAW = c_NO ) generate
synced_timing_trg <= LVL1_TIMING_TRG_IN;
+ timing_trg_rising <= synced_timing_trg;
end generate GEN_NOSYNC;
---------------------------------------------------------------------------
---------------------------------------------------------------------------
timing_trg_comb <= ((synced_timing_trg xor TRG_INVERT_IN) and TRG_ENABLE_IN) or stretched_fake_trg;
-THE_TRIGGER_SHIFT_PROC: process( CLOCK )
-begin
- if( rising_edge(CLOCK) ) then
- if( RESET = '1' ) then
- timing_trg_reg <= (others => '0');
- else
- timing_trg_reg <= timing_trg_reg(2 downto 0) & timing_trg_comb; -- could be generalized here
- end if;
- end if;
-end process THE_TRIGGER_SHIFT_PROC;
-
--- detect rising edge and valid length
-THE_RISING_EDGE_PROC: process( CLOCK )
-begin
- if( rising_edge(CLOCK) ) then
- if( RESET = '1' ) then
- timing_trg_rising <= '0';
- else
- -- 0111 sequence marks the rising edge
- timing_trg_rising <= not timing_trg_reg(3) and timing_trg_reg(2) and timing_trg_reg(1) and timing_trg_reg(0);
- end if;
- end if;
-end process THE_RISING_EDGE_PROC;
-- latch the result for state machine
-- detect multiple timing triggers
end process THE_LATCH_PROC;
---------------------------------------------------------------------------
--- Timeout counter for LVL1
+-- Timeout counter for LVL1
---------------------------------------------------------------------------
THE_TIMEOUT_CTR_PROC: process( CLOCK )
begin
if( rising_edge(CLOCK) ) then
if ( (RESET = '1') or (toc_rst = '1') ) then
timeout_ctr <= (others => '0');
- elsif( (toc_ce = '1') and (timeout_found = '0') ) then
+ elsif( (toc_ce = '1') and (and_all(std_logic_vector(timeout_ctr)) = '0') ) then
timeout_ctr <= timeout_ctr + 1;
- end if;
+ end if;
end if;
end process THE_TIMEOUT_CTR_PROC;
--- 5.12us maximum
--- Jan, be fast :-)
-next_timeout_found <= '1' when ( timeout_ctr = b"1_1111_1111" ) else '0';
+-- 20.48us maximum
+next_timeout_found <= and_all(std_logic_vector(timeout_ctr));
--- store measured delay
--- BUG: register loading is not perfect!
-THE_MEASURED_DELAY_PROC: process( CLOCK )
-begin
- if( rising_edge(CLOCK) ) then
- if ( RESET = '1' ) then
- lvl1_delay <= (others => '0');
- elsif( toc_rst = '1' ) then
- lvl1_delay(15 downto 9) <= (others => '0'); -- here we can store nice status bits
- lvl1_delay(8 downto 0) <= std_logic_vector(timeout_ctr);
- end if;
- end if;
-end process THE_MEASURED_DELAY_PROC;
-
-LVL1_DELAY_OUT <= lvl1_delay;
---------------------------------------------------------------------------
-- State machine
CURRENT_STATE <= IDLE;
toc_ce <= '0';
toc_rst <= '1';
+ toc_save <= '0';
trg_rel <= '0';
trg_rst <= '0';
val_trg <= '0';
val_ttl_trg <= '0';
invalid_trg <= '0';
+ data_valid <= '0';
else
CURRENT_STATE <= NEXT_STATE;
toc_ce <= next_toc_ce;
toc_rst <= next_toc_rst;
+ toc_save <= next_toc_save;
trg_rel <= next_trg_rel;
trg_rst <= next_trg_rst;
val_trg <= next_val_trg;
val_ttl_trg <= next_val_ttl_trg;
invalid_trg <= next_invalid_trg;
+ data_valid <= next_data_valid;
end if;
end if;
end process STATE_MEM;
-- state transitions
STATE_TRANSFORM: process( CURRENT_STATE, LVL1_TRG_RECEIVED_IN, LVL1_TRG_TYPE_IN(3), LVL1_TRG_INFORMATION_IN(7),
- LVL1_TRG_RELEASE_IN, timing_trg_found, timing_trg_rising, timeout_found )
+ LVL1_TRG_RELEASE_IN, timing_trg_found, timing_trg_rising, timeout_found, data_valid )
begin
- NEXT_STATE <= IDLE; -- avoid latches
- next_toc_ce <= '0';
- next_toc_rst <= '0';
- next_trg_rel <= '0';
- next_trg_rst <= '0';
- next_val_trg <= val_trg;
- next_val_ttl_trg <= val_ttl_trg;
- next_invalid_trg <= invalid_trg;
+ NEXT_STATE <= IDLE; -- avoid latches
+ next_toc_ce <= '0';
+ next_toc_rst <= '0';
+ next_toc_save <= toc_save;
+ next_trg_rel <= '0';
+ next_trg_rst <= '0';
+ next_val_trg <= '0';
+ next_val_ttl_trg <= '0';
+ next_invalid_trg <= '0';
+ next_data_valid <= data_valid;
case CURRENT_STATE is
when IDLE => bsm_x <= x"0";
- if ( (timing_trg_found = '1') ) then
- -- timing trigger has a rising edge and valid length
- NEXT_STATE <= TRGFND;
- next_toc_rst <= '1';
- elsif( (timing_trg_found = '0') and (LVL1_TRG_RECEIVED_IN = '1') and
- (LVL1_TRG_TYPE_IN(3) = '1') and (LVL1_TRG_INFORMATION_IN(7) = '1')) then
- -- timingtriggerless trigger found
- NEXT_STATE <= LVL1FND;
- next_toc_rst <= '1';
- next_val_ttl_trg <= '1';
- elsif( (timing_trg_found = '0') and (LVL1_TRG_RECEIVED_IN = '1') and
- ((LVL1_TRG_TYPE_IN(3) = '0') or (LVL1_TRG_INFORMATION_IN(7) = '0')) ) then
- -- missing timing trigger
- NEXT_STATE <= BADTRG;
- next_invalid_trg <= '1';
- else
- NEXT_STATE <= IDLE;
- end if;
+ if ( (timing_trg_found = '1') ) then
+ -- timing trigger has a rising edge and valid length
+ NEXT_STATE <= TRGFND;
+ next_toc_rst <= '1';
+ next_val_trg <= '1';
+ elsif( (timing_trg_found = '0') and (LVL1_TRG_RECEIVED_IN = '1') and
+ (LVL1_TRG_TYPE_IN(3) = '1') and (LVL1_TRG_INFORMATION_IN(7) = '1')) then
+ -- timingtriggerless trigger found
+ NEXT_STATE <= LVL1FND;
+ next_toc_rst <= '1';
+ next_val_ttl_trg <= '1';
+ next_data_valid <= '1';
+ elsif( (timing_trg_found = '0') and (LVL1_TRG_RECEIVED_IN = '1') and
+ ((LVL1_TRG_TYPE_IN(3) = '0') or (LVL1_TRG_INFORMATION_IN(7) = '0')) ) then
+ -- missing timing trigger
+ NEXT_STATE <= BADTRG;
+ next_invalid_trg <= '1';
+ else
+ NEXT_STATE <= IDLE;
+ end if;
when TRGFND => bsm_x <= x"1";
- if ( LVL1_TRG_RECEIVED_IN = '1' ) then
- -- suitable LVL1 information has arrived
- NEXT_STATE <= LVL1FND;
- next_toc_rst <= '1';
- next_val_trg <= '1';
- elsif( timeout_found = '1' ) then
- -- LVL1 did not arrive in time
- NEXT_STATE <= TOCFND;
- next_toc_rst <= '1';
- next_trg_rst <= '1';
- next_invalid_trg <= '1';
- else
- -- wait for either timeout or LVL1
- NEXT_STATE <= TRGFND;
- next_toc_ce <= '1';
- end if;
- when TOCFND => bsm_x <= x"2";
- NEXT_STATE <= IDLE;
+ if ( LVL1_TRG_RECEIVED_IN = '1' ) then
+ -- suitable LVL1 information has arrived
+ NEXT_STATE <= LVL1FND;
+ next_data_valid <= '1';
+ next_toc_rst <= '1';
+-- was commented out
+ elsif( timeout_found = '1' ) then
+ -- LVL1 did not arrive in time
+ NEXT_STATE <= TOCFND;
+ next_toc_save <= '1';
+ next_toc_rst <= '1';
+ next_trg_rst <= '1';
+ next_invalid_trg <= '1';
+----------------------------
+ else
+ -- wait for either timeout or LVL1
+ NEXT_STATE <= TRGFND;
+ next_toc_ce <= '1';
+ end if;
+-- was commented out
+ when TOCFND => bsm_x <= x"2";
+ NEXT_STATE <= IDLE;
+----------------------------
when LVL1FND => bsm_x <= x"3";
- NEXT_STATE <= WAITREL;
- when WAITREL => bsm_x <= x"4";
- if( LVL1_TRG_RELEASE_IN = '1' ) then
- -- FEE logic releases trigger
- NEXT_STATE <= RELEASE;
- next_trg_rel <= '1';
- next_trg_rst <= '1';
- else
- -- FEE logic still busy
- NEXT_STATE <= WAITREL;
- end if;
+ if( LVL1_TRG_RELEASE_IN = '1' ) then
+ -- FEE logic releases trigger
+ NEXT_STATE <= DONE;
+ next_trg_rel <= '1';
+ next_trg_rst <= '1';
+ else
+ -- FEE logic still busy
+ NEXT_STATE <= LVL1FND; --WAITREL;
+ end if;
when BADTRG => bsm_x <= x"5";
- NEXT_STATE <= RELEASE;
- next_trg_rst <= '1';
- when RELEASE => bsm_x <= x"6";
- NEXT_STATE <= DONE;
- next_val_trg <= '0';
- next_val_ttl_trg <= '0';
- next_invalid_trg <= '0';
+ NEXT_STATE <= DONE;
+ next_trg_rel <= '1';
+ next_trg_rst <= '1';
when DONE => bsm_x <= x"7";
- if( LVL1_TRG_RECEIVED_IN = '0' ) then
- NEXT_STATE <= IDLE;
- else
- NEXT_STATE <= DONE;
- end if;
+ if( LVL1_TRG_RECEIVED_IN = '0' ) then
+ NEXT_STATE <= IDLE;
+ next_data_valid <= '0';
+ else
+ NEXT_STATE <= DONE;
+ next_trg_rst <= '1';
+ end if;
when others => bsm_x <= x"f";
- NEXT_STATE <= IDLE;
+ NEXT_STATE <= IDLE;
end case;
-end process STATE_TRANSFORM;
+end process STATE_TRANSFORM;
-next_data_valid <= '1' when ( CURRENT_STATE = WAITREL ) else '0';
-
-LVL1_TRG_RELEASE_OUT <= trg_rel;
-
-LVL1_TRG_DATA_VALID_OUT <= data_valid;
-LVL1_VALID_TIMING_TRG_OUT <= val_trg;
-LVL1_VALID_NOTIMING_TRG_OUT <= val_ttl_trg;
-LVL1_INVALID_TRG_OUT <= invalid_trg;
-LVL1_MULTIPLE_TRG_OUT <= mult_trg_found;
---------------------------------------------------------------------------
-- Internal trigger counter, compare internal and external counters
THE_INTERNAL_TRG_CTR_PROC: process( CLOCK )
begin
if( rising_edge(CLOCK) ) then
- if ( (RESET = '1') or (LVL1_INT_TRG_RESET_IN = '1') ) then
+ if ( (RESET = '1') ) then
lvl1_int_trg_number <= (others => '0');
elsif( LVL1_INT_TRG_LOAD_IN = '1' ) then
lvl1_int_trg_number <= unsigned(LVL1_INT_TRG_COUNTER_IN);
elsif( lvl1_int_trg_ce = '1' ) then
- lvl1_int_trg_number <= lvl1_int_trg_number + 1;
+ lvl1_int_trg_number <= lvl1_int_trg_number + to_unsigned(1,1);
end if;
end if;
end process THE_INTERNAL_TRG_CTR_PROC;
end if;
end process THE_INC_CTR_PROC;
-next_trg_num_match <= '1' when ( lvl1_int_trg_number = unsigned(LVL1_TRG_NUMBER_IN) )
- else '0';
+next_trg_num_match <= '1' when ( lvl1_int_trg_number = unsigned(LVL1_TRG_NUMBER_IN) )
+ else '0';
-LVL1_INT_TRG_NUMBER_OUT <= std_logic_vector(lvl1_int_trg_number);
+
+---------------------------------------------------------------------------
+-- Input Monitoring
+---------------------------------------------------------------------------
+COUNT_EDGES_AND_LENGTH_PROC: process(CLOCK)
+begin
+ if( rising_edge(CLOCK) ) then
+ if ( RESET = '1' ) then
+ trigger_edge_count <= (others => '0');
+ trigger_length <= (others => '0');
+ elsif( (timing_trg_reg(1) = '0') and (timing_trg_reg(0) = '1') and (TRG_ENABLE_IN = '1') ) then
+ trigger_edge_count <= trigger_edge_count + 1;
+ trigger_length <= x"0001";
+ elsif( (synced_timing_trg = '1') and (trigger_length /= 0) and (TRG_ENABLE_IN = '1') ) then
+ trigger_length <= trigger_length + 1;
+ trigger_edge_count <= trigger_edge_count;
+ end if;
+ end if;
+end process COUNT_EDGES_AND_LENGTH_PROC;
---------------------------------------------------------------------------
-- Error bits
next_error_pattern(16) <= LVL1_ERROR_PATTERN_IN(16) or trg_num_match; -- trigger counter mismatch
next_error_pattern(15 downto 0) <= LVL1_ERROR_PATTERN_IN(15 downto 0);
-LVL1_ERROR_PATTERN_OUT <= error_pattern;
+---------------------------------------------------------------------------
+-- Delay measurement
+---------------------------------------------------------------------------
+-- store measured delay
+-- BUG: register loading is not perfect!
+THE_MEASURED_DELAY_PROC: process( CLOCK )
+begin
+ if( rising_edge(CLOCK) ) then
+ if ( RESET = '1' ) then
+ lvl1_delay <= (others => '0');
+ elsif( toc_rst = '1' ) then
+ lvl1_delay(15 downto 11) <= (others => '0'); -- here we can store nice status bits
+ lvl1_delay(10 downto 0) <= std_logic_vector(timeout_ctr);
+ end if;
+ end if;
+end process THE_MEASURED_DELAY_PROC;
---------------------------------------------------------------------------
-- Status bits
---------------------------------------------------------------------------
+STATUS_OUT(63 downto 48) <= std_logic_vector(trigger_length);
+STATUS_OUT(47 downto 32) <= std_logic_vector(trigger_edge_count);
+STATUS_OUT(31 downto 16) <= lvl1_delay;
+STATUS_OUT(15) <= timing_trg_found;
+STATUS_OUT(14) <= data_valid;
+STATUS_OUT(13) <= mult_trg_found;
+STATUS_OUT(12) <= trg_num_match;
+STATUS_OUT(11) <= timeout_found;
+STATUS_OUT(10 downto 4) <= (others => '0');
+STATUS_OUT(3 downto 0) <= bsm_x;
+
+
+---------------------------------------------------------------------------
+-- Debug signals
+---------------------------------------------------------------------------
+debug(15 downto 12) <= bsm_x;
+debug(11) <= synced_timing_trg;
+debug(10) <= timing_trg_rising;
+debug(9) <= LVL1_TRG_RECEIVED_IN;
+debug(8) <= val_trg; --LVL1_VALID_TIMING_TRG_OUT;
+debug(7) <= invalid_trg; --LVL1_INVALID_TRG_OUT;
+debug(6) <= val_ttl_trg; --LVL1_VALID_NOTIMING_TRG_OUT;
+debug(5) <= LVL1_TRG_RELEASE_IN;
+debug(4) <= data_valid;
+debug(3 downto 0) <= std_logic_vector(timeout_ctr(8 downto 5));
+
+---------------------------------------------------------------------------
+-- Outputs
+---------------------------------------------------------------------------
+LVL1_TRG_RELEASE_OUT <= trg_rel;
+LVL1_TRG_DATA_VALID_OUT <= data_valid;
+LVL1_VALID_TIMING_TRG_OUT <= val_trg;
+LVL1_VALID_NOTIMING_TRG_OUT <= val_ttl_trg;
+LVL1_INVALID_TRG_OUT <= invalid_trg;
+LVL1_MULTIPLE_TRG_OUT <= mult_trg_found;
+LVL1_INT_TRG_NUMBER_OUT <= std_logic_vector(lvl1_int_trg_number);
+LVL1_DELAY_OUT <= lvl1_delay;
+LVL1_ERROR_PATTERN_OUT <= error_pattern;
-STATUS_OUT(31 downto 0) <= (others => '0');
+DEBUG_OUT <= debug;
end architecture;
\ No newline at end of file