--- /dev/null
+sim/work
+transcript
+*mti
+*wlf
--- /dev/null
+library IEEE;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+
+
+entity ChannelRegs is
+ port(
+ CLK : in std_logic_vector(3 downto 0);
+ CLK_TDC : in std_logic;
+ CLK_SYS : in std_logic;
+ INP : in std_logic;
+
+ CHANNEL_ENABLE : in std_logic;
+ CALIB_PULSE : in std_logic;
+ HIT_OUT : out std_logic_vector(5 downto 0);
+ HIT_VALID : out std_logic
+ );
+end entity;
+
+
+architecture arch of ChannelRegs is
+
+ signal FFregs, TDCregs : std_logic_vector(7 downto 0);
+
+-- signal finetime : std_logic_vector(6 downto 0); -- valid, edge, error, fine_4
+ signal gated_inp : std_logic;
+
+ signal nCLK : std_logic_vector(3 downto 0);
+
+ attribute syn_keep : boolean;
+ attribute syn_preserve : boolean;
+ attribute syn_keep of gated_inp : signal is true;
+ attribute syn_preserve of gated_inp : signal is true;
+
+ attribute syn_hier : string;
+ attribute syn_hier of arch : architecture is "firm,hard";
+
+begin
+
+nCLK <= not CLK;
+
+THE_INP : entity work.InpLut
+ port map(
+ INP => INP,
+ ENABLE => CHANNEL_ENABLE,
+ PULSER => CALIB_PULSE,
+ OUTP => gated_inp
+ );
+
+THE_FF : entity work.FFregs
+ port map(
+ CLK => CLK,
+ INP => gated_inp,
+ OUTP => FFregs(3 downto 0)
+ );
+
+THE_FFF : entity work.FFregs
+ port map(
+ CLK => nCLK,
+ INP => gated_inp,
+ OUTP => FFregs(7 downto 4)
+ );
+
+THE_FF2 : entity work.FFregs2
+ port map(
+ CLK => CLK,
+ INP => FFregs,
+ OUTP => TDCregs
+ );
+
+THE_DECODER : entity work.Decoder
+ port map(
+ CLK_FAST => CLK(0),
+ CLK_TDC => CLK_TDC,
+ TDC_IN => TDCregs,
+ HIT_OUT => HIT_OUT,
+ HIT_VALID => HIT_VALID
+ );
+
+end architecture;
--- /dev/null
+library IEEE;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+
+
+entity Decoder is
+ port(
+ CLK_FAST: in std_logic;
+ CLK_TDC : in std_logic;
+ TDC_IN : in std_logic_vector(7 downto 0);
+ HIT_OUT : out std_logic_vector(5 downto 0);
+ HIT_VALID : out std_logic
+ );
+end entity;
+
+architecture arch of Decoder is
+ attribute HGROUP: string;
+ attribute HGROUP of arch : architecture is "Decoder";
+ attribute BBOX: string;
+-- attribute BBOX of arch: architecture is "1,16";
+
+ signal TDCregs, last_TDCregs : std_logic_vector(7 downto 0);
+ signal TDCregs_slow : std_logic_vector(16 downto 0);
+ signal final_cycle : std_logic;
+ signal final : std_logic_vector(8 downto 0);
+ signal finetime : std_logic_vector(5 downto 0); -- edge, error, fine_4
+
+
+begin
+
+
+TDCregs <= TDC_IN when rising_edge(CLK_FAST);
+last_TDCregs <= TDCregs when rising_edge(CLK_FAST);
+
+TDCregs_slow <= TDCregs & last_TDCregs & TDCregs_slow(16) when rising_edge(CLK_TDC);
+
+PROC_SELECT : process begin
+ wait until rising_edge(CLK_TDC);
+ if (TDCregs_slow(8) xor TDCregs_slow(0)) = '1' then
+ final <= TDCregs_slow(8 downto 0);
+ final_cycle <= '0';
+ else
+ final <= TDCregs_slow(16 downto 8);
+ final_cycle <= '1';
+ end if;
+end process;
+
+PROC_DECODE : process begin
+ wait until rising_edge(CLK_TDC);
+ finetime <= (others => '0');
+
+
+ finetime(3) <= final_cycle; --4th Bit
+ finetime(5) <= final(8); --Edge
+ HIT_VALID <= final(8) xor final(0); --Valid
+
+ case final(7 downto 0) is
+ when x"01" | x"fe" => finetime(2 downto 0) <= "000";
+ when x"03" | x"fc" => finetime(2 downto 0) <= "001";
+ when x"07" | x"f8" => finetime(2 downto 0) <= "010";
+ when x"0f" | x"f0" => finetime(2 downto 0) <= "011";
+ when x"1f" | x"e0" => finetime(2 downto 0) <= "100";
+ when x"3f" | x"c0" => finetime(2 downto 0) <= "101";
+ when x"7f" | x"80" => finetime(2 downto 0) <= "110";
+ when x"ff" | x"00" => finetime(2 downto 0) <= "111";
+ when others => finetime(4) <= '1'; --Error
+ end case;
+
+end process;
+
+HIT_OUT <= finetime;
+
+end architecture;
--- /dev/null
+library IEEE;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+
+
+entity FFregs is
+ port(
+ CLK : in std_logic_vector(3 downto 0);
+ INP : in std_logic;
+ OUTP : out std_logic_vector(3 downto 0)
+ );
+end entity;
+
+architecture arch of FFregs is
+ attribute HGROUP: string;
+ attribute BBOX: string;
+ attribute HGROUP of arch : architecture is "FFregs";
+ attribute BBOX of arch: architecture is "1,2";
+
+ signal CLKa : std_logic_vector(3 downto 0);
+ signal ffarr : std_logic_vector(3 downto 0);
+
+begin
+
+CLKa(3 downto 0) <= CLK(3 downto 0);
+-- CLKa(7 downto 4) <= not CLK(3 downto 0);
+
+
+gen_ffarr_first : for i in 0 to 3 generate
+ ffarr(i) <= INP when rising_edge(CLKa(i));
+-- OUTP(i) <= ffarr(i) when rising_edge(CLKa((i/4)*4));
+
+end generate;
+OUTP <= ffarr;
+
+end architecture;
--- /dev/null
+library IEEE;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+
+
+entity FFregs2 is
+ port(
+ CLK : in std_logic_vector(3 downto 0);
+ INP : in std_logic_vector(7 downto 0);
+ OUTP : out std_logic_vector(7 downto 0)
+ );
+end entity;
+
+architecture arch of FFregs2 is
+ attribute HGROUP: string;
+ attribute BBOX: string;
+ attribute HGROUP of arch : architecture is "FFregs2";
+ attribute BBOX of arch: architecture is "1,2";
+
+ signal CLKa : std_logic_vector(7 downto 0);
+ signal FFregs : std_logic_vector(7 downto 0);
+
+begin
+
+CLKa(3 downto 0) <= CLK(3 downto 0);
+CLKa(7 downto 4) <= not CLK(3 downto 0);
+
+
+gen_ffarr_first : for i in 0 to 7 generate
+ FFregs(i) <= INP(i) when rising_edge(CLKa((i/4)*4));
+end generate;
+
+OUTP <= FFregs when rising_edge(CLK(0));
+
+
+end architecture;
--- /dev/null
+library IEEE;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+
+
+entity HitBuffer is
+ port(
+ CLK_TDC : in std_logic;
+ CLK_SYS : in std_logic;
+ RESET_IN : in std_logic;
+
+ HIT_IN : in std_logic_vector(5 downto 0); -- edge, error, fine_4
+ HIT_VALID : in std_logic;
+
+ COARSE_TIME_IN : in std_logic_vector(8 downto 0);
+ READOUT_ACTIVE : in std_logic;
+ SPIKE_SETTING : in unsigned(3 downto 0);
+
+ DATA_OUT : out std_logic_vector(27 downto 0);
+ DATA_VALID : out std_logic;
+ DATA_EMPTY : out std_logic;
+ DATA_READ : in std_logic;
+
+ STATUS_OUT : out std_logic_vector(95 downto 0)
+ );
+end entity;
+
+
+architecture arch of HitBuffer is
+
+ attribute HGROUP: string;
+ attribute HGROUP of arch : architecture is "HitBuffer";
+
+signal reg_hit, cdc_data : std_logic_vector(17 downto 0);
+signal reg_hit_valid : std_logic;
+
+signal cdc_empty, cdc_nextvalid, cdc_valid, cdc_read : std_logic;
+
+signal edge_rising : std_logic_vector(15 downto 0);
+alias edge_rising_valid : std_logic is edge_rising(15);
+alias edge_rising_error : std_logic is edge_rising(14);
+
+alias cdc_data_error : std_logic is cdc_data(4);
+
+signal full_hit : std_logic_vector(35 downto 0);
+signal hit_buffer_write, hit_buffer_read : std_logic;
+signal hit_buffer_empty, hit_buffer_full : std_logic;
+signal last_hit_buffer_full : std_logic;
+signal hit_buffer_reset : std_logic;
+signal hit_buffer_dout : std_logic_vector(35 downto 0);
+signal hit_buffer_level : std_logic_vector(5 downto 0);
+
+signal spike_timer : unsigned(3 downto 0) := (others => '0');
+signal hit_store : std_logic_vector(35 downto 0);
+alias hit_store_coarse : std_logic_vector(8 downto 0) is hit_store(25 downto 17);
+
+signal count_fallingedges, count_risingedges : unsigned(23 downto 0);
+
+type buffer_state_t is (EMPTY,WAIT_HIT,WAIT_HIT2,GOT_HIT,HAS_HIT,DO_READOUT,WAIT_READOUT);
+signal buffer_state : buffer_state_t;
+
+begin
+----------------------------------------------------------------------
+-- Clock domain transfer
+----------------------------------------------------------------------
+reg_hit <= "000" & COARSE_TIME_IN & HIT_IN when rising_edge(CLK_TDC);
+reg_hit_valid <= HIT_VALID when rising_edge(CLK_TDC);
+--
+-- THE_CDC_BUFFER : entity work.lattice_ecp3_fifo_18x16_dualport_oreg
+-- port map(
+-- DATA => reg_hit,
+-- WrClock => CLK_TDC,
+-- RdClock => CLK_SYS,
+-- WrEn => reg_hit_valid,
+-- RdEn => cdc_read,
+-- Reset => RESET_IN,
+-- RPReset => RESET_IN,
+-- Q => cdc_data,
+-- Empty => cdc_empty,
+-- Full => open,
+-- AlmostFull => open
+-- );
+--
+-- cdc_read <= '1';
+-- cdc_nextvalid <= cdc_read and not cdc_empty when rising_edge(CLK_SYS);
+-- cdc_valid <= cdc_nextvalid when rising_edge(CLK_SYS);
+--
+--
+
+cdc_data <= reg_hit;
+cdc_valid <= reg_hit_valid;
+----------------------------------------------------------------------
+-- Build full hits
+----------------------------------------------------------------------
+PROC_BUILD_HIT : process begin
+ wait until rising_edge(CLK_TDC);
+ hit_buffer_write <= '0';
+ full_hit <= (others => '0');
+ if spike_timer /= x"0" then
+ spike_timer <= spike_timer - 1;
+ end if;
+
+
+ if cdc_valid = '1' and cdc_data(5) = '1' then
+ edge_rising <= '1' & cdc_data(4) & '0' & cdc_data(14 downto 6) & cdc_data(3 downto 0);
+-- count_risingedges <= count_risingedges + 1;
+ spike_timer <= SPIKE_SETTING;
+ end if;
+
+ if cdc_valid = '1' and cdc_data(5) = '0' then
+ full_hit <= x"00" & cdc_data_error & edge_rising_error & edge_rising(12 downto 0) & cdc_data(14 downto 6) & cdc_data(3 downto 0);
+ edge_rising_valid <= '0';
+ if READOUT_ACTIVE = '0' and spike_timer = x"0" then
+ hit_buffer_write <= '1';
+ count_fallingedges <= count_fallingedges + 1;
+ end if;
+-- count_fallingedges <= count_fallingedges + 1;
+ end if;
+
+ if RESET_IN = '1' then
+-- count_risingedges <= (others => '0');
+ count_fallingedges <= (others => '0');
+ end if;
+
+end process;
+
+----------------------------------------------------------------------
+-- Hit Buffer
+----------------------------------------------------------------------
+THE_HIT_BUF : entity work.fifo_36x32
+ port map (
+ Data => full_hit,
+ Clock => CLK_TDC,
+ WrEn => hit_buffer_write,
+ RdEn => hit_buffer_read,
+ Reset => hit_buffer_reset,
+ AmFullThresh => "01000",
+ Q => hit_buffer_dout,
+ WCNT => hit_buffer_level,
+ Empty => hit_buffer_empty,
+ Full => open,
+ AlmostFull => hit_buffer_full
+ );
+
+last_hit_buffer_full <= hit_buffer_full when rising_edge(CLK_TDC);
+
+-- hit_buffer_nextvalid <= hit_buffer_read and not hit_buffer_empty when rising_edge(CLK_TDC);
+-- hit_buffer_valid <= hit_buffer_nextvalid when rising_edge(CLK_TDC);
+
+
+----------------------------------------------------------------------
+-- Buffer Handling
+----------------------------------------------------------------------
+PROC_BUF : process begin
+ wait until rising_edge(CLK_TDC);
+ hit_buffer_read <= '0';
+ hit_buffer_reset <= '0';
+ DATA_EMPTY <= '0';
+
+ if hit_buffer_read = '1' then
+ count_risingedges <= count_risingedges + 1;
+ end if;
+
+ case buffer_state is
+ when EMPTY =>
+ DATA_EMPTY <= '1';
+ if hit_buffer_empty = '0' then
+ hit_buffer_read <= '1';
+ buffer_state <= WAIT_HIT;
+ end if;
+ if READOUT_ACTIVE = '1' then
+ buffer_state <= WAIT_READOUT;
+ end if;
+
+ when WAIT_HIT =>
+ if hit_buffer_empty = '1' then
+ if READOUT_ACTIVE = '0' then
+ buffer_state <= EMPTY;
+ else
+ buffer_state <= WAIT_READOUT;
+ end if;
+ else
+ if READOUT_ACTIVE = '0' then
+ buffer_state <= GOT_HIT;
+ else
+ buffer_state <= DO_READOUT;
+ end if;
+ end if;
+
+ when WAIT_HIT2 =>
+ buffer_state <= GOT_HIT;
+
+ when GOT_HIT =>
+ hit_store <= hit_buffer_dout;
+ buffer_state <= HAS_HIT;
+
+ when HAS_HIT =>
+ if READOUT_ACTIVE = '0' then
+ if hit_buffer_full = '1' then
+ hit_buffer_read <= '1';
+ buffer_state <= WAIT_HIT;
+ elsif hit_store_coarse = COARSE_TIME_IN then --too old
+ hit_buffer_read <= '1';
+ buffer_state <= WAIT_HIT;
+ end if;
+ else
+ buffer_state <= DO_READOUT;
+ end if;
+
+ when DO_READOUT =>
+ if DATA_READ = '1' then
+ hit_buffer_read <= '1';
+ buffer_state <= WAIT_HIT;
+ end if;
+
+ if READOUT_ACTIVE = '0' then
+ buffer_state <= EMPTY;
+ hit_buffer_reset <= '1';
+ end if;
+
+ when WAIT_READOUT =>
+ DATA_EMPTY <= '1';
+ if READOUT_ACTIVE = '0' then
+ buffer_state <= EMPTY;
+ hit_buffer_reset <= '1';
+ end if;
+ end case;
+
+
+ if RESET_IN = '1' then
+ buffer_state <= EMPTY;
+ hit_buffer_reset <= '1';
+ count_risingedges <= (others => '0');
+ end if;
+end process;
+
+DATA_OUT <= hit_store(27 downto 0);
+
+----------------------------------------------------------------------
+-- Statistics
+----------------------------------------------------------------------
+STATUS_OUT(31 downto 0) <= x"00" & std_logic_vector(count_risingedges) when rising_edge(CLK_SYS);
+STATUS_OUT(63 downto 32) <= x"00" & std_logic_vector(count_fallingedges) when rising_edge(CLK_SYS);
+STATUS_OUT(71 downto 64) <= "00" & hit_buffer_level when rising_edge(CLK_SYS);
+STATUS_OUT(75 downto 72) <= std_logic_vector(spike_timer) when rising_edge(CLK_SYS);
+
+
+----------------------------------------------------------------------
+-- Dummy
+----------------------------------------------------------------------
+-- DATA_OUT(5 downto 0) <= hit_buffer_dout(5 downto 0);
+
+end architecture;
--- /dev/null
+library IEEE;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+
+
+entity InpLut is
+ port(
+ INP : in std_logic;
+ ENABLE : in std_logic;
+ PULSER : in std_logic;
+ OUTP : out std_logic
+ );
+end entity;
+
+architecture arch of InpLut is
+ attribute HGROUP: string;
+ attribute BBOX: string;
+ attribute HGROUP of arch : architecture is "InpLut";
+ attribute BBOX of arch: architecture is "1,1";
+
+ attribute syn_hier : string;
+ attribute syn_hier of arch : architecture is "firm,hard";
+
+-- attribute syn_keep : boolean;
+-- attribute syn_preserve : boolean;
+-- attribute syn_keep of OUTP : signal is true;
+-- attribute syn_preserve of OUTP : signal is true;
+
+
+begin
+
+OUTP <= (INP and ENABLE) or PULSER;
+
+end architecture;
--- /dev/null
+library IEEE;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+use work.clocked_tdc_pkg.all;
+
+entity ReadoutHandler is
+ generic(
+ NUM_CHANNELS : integer range 2 to 32 := 16;
+ GROUP_NUM : std_logic := '0'
+ );
+ port(
+ CLK_TDC : in std_logic;
+ CLK_SYS : in std_logic;
+ RESET_IN : in std_logic;
+
+
+ REFERENCE_IN : in std_logic_vector(12 downto 0);
+ DATA_IN : in tdc_data_t(NUM_CHANNELS-1 downto 0);
+ DATA_VALID_IN : in std_logic_vector(NUM_CHANNELS-1 downto 0);
+ DATA_EMPTY_IN : in std_logic_vector(NUM_CHANNELS-1 downto 0);
+ DATA_READ_OUT : out std_logic_vector(NUM_CHANNELS-1 downto 0);
+ READOUT_ACTIVE: out std_logic;
+ CALIB_PULSE : out std_logic;
+-- BUS_RX : in CTRLBUS_RX;
+-- BUS_TX : out CTRLBUS_TX;
+
+ READOUT_RX : in READOUT_RX;
+ READOUT_TX : out READOUT_TX;
+ STATUS_OUT : out std_logic_vector(31 downto 0)
+
+ );
+end entity;
+
+
+architecture arch of ReadoutHandler is
+
+signal timer, timer_d : unsigned(7 downto 0);
+
+type state_rdo_t is (IDLE,CALIB,WAIT_WINDOW, COLLECT, FINISH);
+signal state_rdo : state_rdo_t;
+
+type state_data_t is (IDLE, CHANNEL_FIRST, END1, END2, FINISH);
+signal state_data : state_data_t;
+
+signal cdc_data_out : std_logic_vector(35 downto 0);
+signal cdc_data_in : std_logic_vector(31 downto 0);
+signal cdc_valid, cdc_nextvalid, cdc_read, cdc_empty, cdc_write : std_logic;
+signal last_cdc_empty : std_logic;
+
+signal collect_start_sys, collect_start_tdc : std_logic;
+signal collect_finish_sys, collect_finish_tdc : std_logic;
+signal got_collect_finish : std_logic;
+signal is_calib_sys : std_logic;
+
+signal hit_valid, hit_calc_valid, hit_check_valid : std_logic;
+signal hit_data : std_logic_vector(31 downto 0);
+signal hit_calc_data, hit_check_data : std_logic_vector(31 downto 0);
+
+signal buf_READOUT_ACTIVE : std_logic;
+begin
+
+READOUT_ACTIVE <= buf_READOUT_ACTIVE when rising_edge(CLK_TDC);
+
+----------------------------------------------------------------------
+-- Readout Handler
+----------------------------------------------------------------------
+PROC_RDO_SYSTEM : process begin
+ wait until rising_edge(CLK_SYS);
+
+ READOUT_TX.data_finished <= '0';
+ READOUT_TX.busy_release <= '0';
+ READOUT_TX.data_write <= '0';
+ collect_start_sys <= '0';
+ got_collect_finish <= '0';
+ last_cdc_empty <= cdc_empty;
+ CALIB_PULSE <= '0';
+
+ case state_rdo is
+ when IDLE =>
+ buf_READOUT_ACTIVE <= '0';
+ if READOUT_RX.valid_timing_trg = '1' then
+ state_rdo <= COLLECT;
+ collect_start_sys <= '1';
+ is_calib_sys <= '0';
+ buf_READOUT_ACTIVE <= '1';
+ elsif READOUT_RX.valid_notiming_trg = '1' then
+ state_rdo <= CALIB;
+ is_calib_sys <= '1';
+ timer <= (others => '0');
+ elsif READOUT_RX.invalid_trg = '1' then
+ state_rdo <= FINISH;
+ end if;
+
+ when CALIB =>
+ timer <= timer + 1;
+ if timer >= x"05" and timer <= x"09" then
+ CALIB_PULSE <= '1';
+ elsif timer = x"F0" then
+ state_rdo <= COLLECT;
+ buf_READOUT_ACTIVE <= '1';
+ collect_start_sys <= '1';
+ end if;
+
+ when WAIT_WINDOW =>
+ null;
+
+ when COLLECT =>
+ READOUT_TX.data <= cdc_data_out(31 downto 0);
+ READOUT_TX.data_write <= cdc_valid;
+ got_collect_finish <= got_collect_finish or collect_finish_sys;
+ if (got_collect_finish = '1') and last_cdc_empty = '1' then
+ state_rdo <= FINISH;
+ end if;
+
+ when FINISH =>
+ READOUT_TX.data_finished <= '1';
+ READOUT_TX.busy_release <= '1';
+ state_rdo <= IDLE;
+ end case;
+
+
+end process;
+
+----------------------------------------------------------------------
+-- TDC Data Collector & Processor
+----------------------------------------------------------------------
+PROC_RDO_TDC : process
+ variable channel : integer range 0 to 16 := 0;
+begin
+ wait until rising_edge(CLK_TDC);
+ collect_finish_tdc <= '0';
+ hit_valid <= '0';
+
+ cdc_write <= hit_check_valid;
+ cdc_data_in <= hit_check_data;
+ DATA_READ_OUT <= (others => '0');
+
+ case state_data is
+ when IDLE =>
+ channel := 0;
+ if collect_start_tdc = '1' then
+ cdc_data_in <= x"1DC0" & "000" & REFERENCE_IN;
+ if GROUP_NUM = '0' then
+ cdc_write <= '1';
+ end if;
+ state_data <= CHANNEL_FIRST;
+ end if;
+
+ when CHANNEL_FIRST =>
+ if DATA_EMPTY_IN(channel) = '0' then
+ hit_data <= std_logic_vector(to_unsigned(channel,4)) & DATA_IN(channel);
+ hit_valid <= '1';
+ DATA_READ_OUT(channel) <= '1';
+ end if;
+-- else
+ if channel < 15 then
+ channel := channel + 1;
+ else
+ state_data <= END1;
+ end if;
+-- end if;
+
+ when END1 =>
+ state_data <= END2;
+ timer_d <= (others => '0');
+
+ when END2 =>
+ timer_d <= timer_d + 1;
+ if timer_d = x"02" and and(DATA_EMPTY_IN) = '0' then
+ channel := 0;
+ state_data <= CHANNEL_FIRST;
+ elsif timer_d = x"03" then
+ state_data <= FINISH;
+ end if;
+
+ when FINISH =>
+ collect_finish_tdc <= '1';
+ state_data <= IDLE;
+ end case;
+
+
+end process;
+
+----------------------------------------------------------------------
+-- Calculate hit data
+----------------------------------------------------------------------
+hit_calc_valid <= hit_valid when rising_edge(CLK_TDC);
+-- hit_calc_data <= GROUP_NUM & hit_data(31 downto 28) --5 channel
+-- & (hit_data(27) or hit_data(26)) --1 error
+-- & std_logic_vector(unsigned(REFERENCE_IN) - unsigned(hit_data(25 downto 13))) --13 leading edge
+-- & std_logic_vector(unsigned(hit_data(25 downto 13)) - unsigned(hit_data(12 downto 0))) --13 ToT
+-- when rising_edge(CLK_TDC);
+hit_calc_data <= GROUP_NUM & hit_data(31 downto 28) --5 channel
+ & (hit_data(27) or hit_data(26)) --1 error
+ & std_logic_vector(unsigned(hit_data(25 downto 13))) --13 leading edge
+ & std_logic_vector(unsigned(hit_data(12 downto 0))) --13 ToT
+ when rising_edge(CLK_TDC);
+
+hit_check_valid <= hit_calc_valid;
+hit_check_data <= hit_calc_data;
+
+----------------------------------------------------------------------
+-- Signal CDC
+----------------------------------------------------------------------
+
+THE_SYS_TO_TDC : entity work.pulse_sync
+ port map(
+ CLK_A_IN => CLK_SYS,
+ RESET_A_IN => RESET_IN,
+ PULSE_A_IN => collect_start_sys,
+ CLK_B_IN => CLK_TDC,
+ RESET_B_IN => RESET_IN,
+ PULSE_B_OUT => collect_start_tdc
+ );
+
+THE_TDC_TO_SYS : entity work.pulse_sync
+ port map(
+ CLK_A_IN => CLK_TDC,
+ RESET_A_IN => RESET_IN,
+ PULSE_A_IN => collect_finish_tdc,
+ CLK_B_IN => CLK_SYS,
+ RESET_B_IN => RESET_IN,
+ PULSE_B_OUT => collect_finish_sys
+ );
+
+
+
+----------------------------------------------------------------------
+-- CDC Buffer
+----------------------------------------------------------------------
+THE_CDC_BUFFER : entity work.fifo_36x512_dualport_oreg
+ port map(
+ DATA(31 downto 0) => cdc_data_in,
+ DATA(35 downto 32) => x"0",
+ WrClock => CLK_TDC,
+ RdClock => CLK_SYS,
+ WrEn => cdc_write,
+ RdEn => cdc_read,
+ Reset => RESET_IN,
+ RPReset => RESET_IN,
+ Q => cdc_data_out,
+ Empty => cdc_empty,
+ Full => open,
+ AlmostFull => open
+ );
+
+cdc_read <= '1';
+cdc_nextvalid <= cdc_read and not cdc_empty when rising_edge(CLK_SYS);
+cdc_valid <= cdc_nextvalid when rising_edge(CLK_SYS);
+
+
+ STATUS_OUT(3 downto 0) <= x"0" when state_rdo = IDLE else
+ x"1" when state_rdo = CALIB else
+ x"2" when state_rdo = WAIT_WINDOW else
+ x"3" when state_rdo = COLLECT else
+ x"4" when state_rdo = FINISH else x"F";
+ STATUS_OUT(7 downto 4) <= x"0" when state_data = IDLE else
+ x"1" when state_data = CHANNEL_FIRST else
+ x"2" when state_data = END1 else
+ x"3" when state_data = END2 else
+ x"4" when state_data = FINISH else x"F";
+ STATUS_OUT(8) <= buf_READOUT_ACTIVE;
+ STATUS_OUT(9) <= got_collect_finish;
+
+end architecture;
--- /dev/null
+library IEEE;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+use work.clocked_tdc_pkg.all;
+
+entity TDC_FF is
+ generic(
+ NUM_CHANNELS : integer range 2 to 32 := 32
+ );
+ port(
+ CLK_FAST : in std_logic;
+ CLK_SYS : in std_logic;
+ RESET_IN : in std_logic;
+
+ SIGNAL_IN : in std_logic_vector(31 downto 0);
+ TRIGGER_IN: in std_logic;
+ CALIBRATION_OUT : out std_logic;
+
+ BUS_RX : in CTRLBUS_RX;
+ BUS_TX : out CTRLBUS_TX;
+
+ READOUT_RX : in READOUT_RX;
+ READOUT_TX : out readout_tx_array_t(0 to 1);
+
+ DUMMY : out std_logic
+ );
+end entity;
+
+
+architecture arch of TDC_FF is
+
+signal clk_pll : std_logic_vector(3 downto 0);
+type tdc_hit_t is array(0 to 31) of std_logic_vector(5 downto 0);
+signal tdc_hit : tdc_hit_t;
+signal tdc_valid : std_logic_vector(NUM_CHANNELS-1 downto 0);
+signal tdc_data_valid, tdc_data_read, tdc_data_empty : std_logic_vector(NUM_CHANNELS-1 downto 0);
+
+signal ref_valid : std_logic;
+signal ref_hit : std_logic_vector(5 downto 0);
+signal ref_timestamp : std_logic_vector(12 downto 0);
+signal readout_active_i : std_logic_vector(1 downto 0);
+signal calibration_pulse, calibration_pulse_i : std_logic_vector(1 downto 0);
+
+signal tdc_data : tdc_data_t(NUM_CHANNELS-1 downto 0);
+
+signal coarse_time : unsigned(8 downto 0) := (others => '0');
+
+type status_t is array(0 to 31) of std_logic_vector(95 downto 0);
+signal hitbuffer_status : status_t;
+
+signal CONF_enable : std_logic_vector(31 downto 0) := (others => '1');
+signal CONF_configure : std_logic_vector(31 downto 0) := x"00000300";
+alias CONF_externalcalibration : std_logic is CONF_configure(0);
+alias CONF_SPIKE : std_logic_vector(3 downto 0) is CONF_configure(11 downto 8);
+
+signal status_rdo_handler : std_logic_vector(63 downto 0);
+begin
+----------------------------------------------------------------------
+-- Infrastructure
+----------------------------------------------------------------------
+coarse_time <= coarse_time + 1 when rising_edge(CLK_FAST);
+
+THE_PLL : entity work.PLL_TDC
+ port map(
+ CLKI => CLK_FAST,
+ CLKOP => clk_pll(0),
+ CLKOS => clk_pll(1),
+ CLKOS2 => clk_pll(2),
+ CLKOS3 => clk_pll(3)
+ );
+
+
+----------------------------------------------------------------------
+-- Reference Channel
+----------------------------------------------------------------------
+
+THE_REF_CHANNEL : entity work.ChannelRegs
+ port map(
+ CLK => clk_pll,
+ CLK_TDC => CLK_FAST,
+ CLK_SYS => CLK_SYS,
+ INP => TRIGGER_IN,
+ CHANNEL_ENABLE => '1',
+ CALIB_PULSE => calibration_pulse(0),
+ HIT_OUT => ref_hit,
+ HIT_VALID => ref_valid
+ );
+
+PROC_REF_CHANNEL : process begin
+ wait until rising_edge(CLK_FAST);
+ if ref_valid = '1' and ref_hit(5) = '1' then
+ ref_timestamp <= std_logic_vector(coarse_time) & ref_hit(3 downto 0);
+ end if;
+end process;
+
+----------------------------------------------------------------------
+-- The TDCs
+----------------------------------------------------------------------
+
+gen_CHANNELS : for i in 0 to NUM_CHANNELS-1 generate
+ THE_CHANNEL : entity work.ChannelRegs
+ port map(
+ CLK => clk_pll,
+ CLK_TDC => CLK_FAST,
+ CLK_SYS => CLK_SYS,
+ INP => SIGNAL_IN(i),
+ CHANNEL_ENABLE => CONF_enable(i),
+ CALIB_PULSE => calibration_pulse_i(i/16),
+ HIT_OUT => tdc_hit(i),
+ HIT_VALID => tdc_valid(i)
+ );
+
+ THE_HITBUF : entity work.HitBuffer
+ port map(
+ CLK_TDC => CLK_FAST,
+ CLK_SYS => CLK_SYS,
+ RESET_IN => RESET_IN,
+ HIT_IN => tdc_hit(i),
+ HIT_VALID => tdc_valid(i),
+
+ COARSE_TIME_IN => std_logic_vector(coarse_time),
+ READOUT_ACTIVE => readout_active_i(i/16),
+ SPIKE_SETTING => unsigned(CONF_SPIKE),
+
+ DATA_OUT => tdc_data(i),
+ DATA_VALID => tdc_data_valid(i),
+ DATA_EMPTY => tdc_data_empty(i),
+ DATA_READ => tdc_data_read(i),
+ STATUS_OUT => hitbuffer_status(i)
+ );
+
+end generate;
+
+----------------------------------------------------------------------
+-- Readout Handler
+----------------------------------------------------------------------
+THE_RDO_HANDLER_1 : entity work.ReadoutHandler
+ generic map(
+ GROUP_NUM => '0'
+ )
+ port map(
+ CLK_TDC => CLK_FAST,
+ CLK_SYS => CLK_SYS,
+ RESET_IN => RESET_IN,
+
+ REFERENCE_IN => ref_timestamp,
+
+ DATA_IN => tdc_data(15 downto 0),
+ DATA_VALID_IN => tdc_data_valid(15 downto 0),
+ DATA_EMPTY_IN => tdc_data_empty(15 downto 0),
+ DATA_READ_OUT => tdc_data_read(15 downto 0),
+ READOUT_ACTIVE => readout_active_i(0),
+ CALIB_PULSE => calibration_pulse(0),
+
+ READOUT_RX => READOUT_RX,
+ READOUT_TX => READOUT_TX(0),
+ STATUS_OUT => status_rdo_handler(31 downto 0)
+
+ );
+
+THE_RDO_HANDLER_2 : entity work.ReadoutHandler
+ generic map(
+ GROUP_NUM => '1'
+ )
+ port map(
+ CLK_TDC => CLK_FAST,
+ CLK_SYS => CLK_SYS,
+ RESET_IN => RESET_IN,
+
+ REFERENCE_IN => ref_timestamp,
+
+ DATA_IN => tdc_data(31 downto 16),
+ DATA_VALID_IN => tdc_data_valid(31 downto 16),
+ DATA_EMPTY_IN => tdc_data_empty(31 downto 16),
+ DATA_READ_OUT => tdc_data_read(31 downto 16),
+ READOUT_ACTIVE => readout_active_i(1),
+ CALIB_PULSE => calibration_pulse(1),
+
+ READOUT_RX => READOUT_RX,
+ READOUT_TX => READOUT_TX(1),
+ STATUS_OUT => status_rdo_handler(63 downto 32)
+
+ );
+
+
+CALIBRATION_OUT <= calibration_pulse(0) when CONF_externalcalibration = '1' else '0';
+calibration_pulse_i <= calibration_pulse when CONF_externalcalibration = '0' else "00";
+
+----------------------------------------------------------------------
+-- Slow Control
+----------------------------------------------------------------------
+PROC_REGS : process
+ variable addr : integer range 0 to 31;
+begin
+ wait until rising_edge(CLK_SYS);
+ BUS_TX.ack <= '0';
+ BUS_TX.unknown <= '0';
+ BUS_TX.nack <= '0';
+ BUS_TX.data <= (others => '0');
+ addr := to_integer(unsigned(BUS_RX.addr(4 downto 0)));
+ if BUS_RX.write = '1' then
+ BUS_TX.ack <= '1';
+ if BUS_RX.addr = x"0000" then
+ CONF_enable <= BUS_RX.data;
+ elsif BUS_RX.addr = x"0001" then
+ CONF_configure <= BUS_RX.data;
+ else
+ BUS_TX.ack <= '0';
+ BUS_TX.unknown <= '1';
+ end if;
+ elsif BUS_RX.read = '1' then
+ BUS_TX.ack <= '1';
+ if BUS_RX.addr = x"0000" then
+ BUS_TX.data <= CONF_enable;
+ elsif BUS_RX.addr = x"0001" then
+ BUS_TX.data <= CONF_configure;
+ elsif BUS_RX.addr = x"0010" then
+ BUS_TX.data <= status_rdo_handler(31 downto 0);
+ elsif BUS_RX.addr = x"0002" then
+ BUS_TX.data <= status_rdo_handler(63 downto 32);
+ elsif BUS_RX.addr(15 downto 5) = x"01" & "000" then
+ BUS_TX.data <= hitbuffer_status(addr)(31 downto 0);
+ elsif BUS_RX.addr(15 downto 5) = x"01" & "001" then
+ BUS_TX.data <= hitbuffer_status(addr)(63 downto 32);
+ elsif BUS_RX.addr(15 downto 5) = x"01" & "010" then
+ BUS_TX.data <= hitbuffer_status(addr)(95 downto 64);
+ else
+ BUS_TX.ack <= '0';
+ BUS_TX.unknown <= '1';
+
+ end if;
+ end if;
+end process;
+
+
+end architecture;
--- /dev/null
+library IEEE;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+package clocked_tdc_pkg is
+
+type tdc_data_t is array(integer range <>) of std_logic_vector(27 downto 0);
+
+
+end package;
+
+package body clocked_tdc_pkg is
+
+end package body;