-- with TDC and lattice diamond version >2.1
constant ADC_CHANNELS : integer := 36;
- --Include the TDC (only usefule for CFD readout mode)
+ --Include the TDC (only useful for CFD readout mode)
constant INCLUDE_TDC : integer := c_YES;
--double edge type: 0, 1, 2, 3
DEBUG_BUFFER_DATA => open,
DEBUG_BUFFER_READY => open,
READOUT_TX => readout_tx,
- READOUT_RX => readout_rx
+ READOUT_RX => readout_rx,
+ EPOCH_COUNTER_IN => (others => '0')
);
PROC_ADC : process
restart_i <= RESTART_IN when rising_edge(clk_data);
assert (ADC_CHANNELS = 48 or ADC_CHANNELS = 36)
- report "The number of either 48 or 36." severity error;
+ report "The number of ADC_CHANNELS must be either 48 or 36." severity error;
gen_7 : if NUM_DEVICES = 7 and ADC_CHANNELS = 48 generate
TRIGGER_FLAG_OUT : out std_logic;
--Readout
READOUT_RX : in READOUT_RX;
+ READOUT_TX_CFD : out READOUT_TX;
READOUT_TX : out readout_tx_array_t(0 to (DEVICES_1 + DEVICES_2) - 1);
+
--Slow control
BUS_RX : in CTRLBUS_RX;
BUS_TX : out CTRLBUS_TX;
signal adc_clk : std_logic_vector(DEVICES downto 1) := (others => '1');
signal adc_clk_left, adc_clk_right : std_logic := '1';
- signal adc_clk_tdc_out_i : std_logic_vector(DEVICES-1 downto 0);
+ signal epoch_counter, epoch_counter_save, epoch_counter_save_sys : unsigned(EPOCH_COUNTER_SIZE-1 downto 0) := (others => '0');
+ signal trigger_in_i : std_logic;
+ type state_cfd_t is (IDLE, DO_RELEASE, RELEASE_DIRECT, WAIT_FOR_END, WRITE_EPOCH);
+ signal state_cfd : state_cfd_t;
-- 000 - 0ff configuration
-- 000 reset, buffer clear strobes
DEBUG_BUFFER_READY => buffer_ready(i),
READOUT_RX => READOUT_RX,
READOUT_TX => READOUT_TX(i),
- ADC_CLK_TDC_OUT => adc_clk_tdc_out_i(i)
+ EPOCH_COUNTER_IN => epoch_counter
);
end generate;
- ADC_CLK_TDC_OUT <= adc_clk_tdc_out_i(5); -- select 5 as it's closest to the TDC placement
+ ADC_CLK_TDC_OUT <= epoch_counter(10);
+
+ PROC_EPOCH_COUNTER : process is
+ begin
+ wait until rising_edge(adc_clk_left);
+ epoch_counter <= epoch_counter + 1;
+ trigger_in_i <= TRIGGER_IN;
+ if trigger_in_i = '1' then
+ epoch_counter_save <= epoch_counter;
+ end if;
+ end process PROC_EPOCH_COUNTER;
+
+ PROC_READOUT_CFD : process is
+ begin
+ wait until rising_edge(CLK);
+ epoch_counter_save_sys <= epoch_counter_save;
+ READOUT_TX_CFD.busy_release <= '0';
+ READOUT_TX_CFD.data_finished <= '0';
+ READOUT_TX_CFD.data <= (others => '0');
+ READOUT_TX_CFD.data_write <= '0';
+
+ case state_cfd is
+ when IDLE =>
+ READOUT_TX_CFD.statusbits <= (others => '0');
+ if READOUT_RX.valid_notiming_trg = '1' then
+ state_cfd <= RELEASE_DIRECT;
+ elsif READOUT_RX.data_valid = '1' then --seems to have missed trigger...
+ READOUT_TX_CFD.statusbits <= (23 => '1', others => '0'); --event not found
+ state_cfd <= RELEASE_DIRECT;
+ elsif READOUT_RX.valid_timing_trg = '1' then
+ state_cfd <= WRITE_EPOCH;
+ end if;
+
+ when RELEASE_DIRECT =>
+ state_cfd <= DO_RELEASE;
+
+ when DO_RELEASE =>
+ if READOUT_RX.data_valid = '1' then
+ READOUT_TX_CFD.busy_release <= '1';
+ READOUT_TX_CFD.data_finished <= '1';
+ state_cfd <= WAIT_FOR_END;
+ end if;
+
+ when WAIT_FOR_END =>
+ if READOUT_RX.data_valid = '0' then
+ state_cfd <= IDLE;
+ end if;
+
+ when WRITE_EPOCH =>
+ READOUT_TX_CFD.data <= x"1" & std_logic_vector(resize(epoch_counter_save_sys,28));
+ READOUT_TX_CFD.data_write <= '1';
+ state_cfd <= RELEASE_DIRECT;
+ end case;
+ end process PROC_READOUT_CFD;
+
+
config_cfd.BaselineAlwaysOn <= buffer_ctrl_reg(4);
constant DEVICES_2 : integer := 5;
constant CHANNELS : integer := 4;
constant RESOLUTION : integer := 10;
+
+ constant EPOCH_COUNTER_SIZE : integer := 24;
type buffer_data_t is array (0 to DEVICES - 1) of std_logic_vector(31 downto 0);
InvalidWordCount : unsigned(31 downto 0);
Baseline : unsigned(RESOLUTION - 1 downto 0);
LastWord : unsigned(RESOLUTION - 1 downto 0);
- EpochCounter : unsigned(23 downto 0);
Trigger : std_logic;
end record;
READOUT_RX : in READOUT_RX;
READOUT_TX : out READOUT_TX;
- ADC_CLK_TDC_OUT : out std_logic
+ EPOCH_COUNTER_IN : in unsigned(EPOCH_COUNTER_SIZE-1 downto 0)
);
end entity adc_processor_cfd;
signal state : state_t;
signal statebits : std_logic_vector(7 downto 0);
- signal RDO_data_main : std_logic_vector(31 downto 0) := (others => '0');
- signal RDO_write_main : std_logic := '0';
signal readout_reset : std_logic := '0';
signal busy_in_adc, busy_in_sys : std_logic := '0';
signal busy_out_adc, busy_out_sys : std_logic_vector(CHANNELS-1 downto 0) := (others => '0');
- type epoch_counter_t is array(CHANNELS - 1 downto 0) of unsigned(23 downto 0);
- signal epoch_counter, epoch_counter_save : epoch_counter_t;
- signal epoch_counter_sys, epoch_counter_adc : epoch_counter_t;
+ --type epoch_counter_t is array(CHANNELS - 1 downto 0) of unsigned(23 downto 0);
+ --signal epoch_counter, epoch_counter_save : epoch_counter_t;
+ --signal epoch_counter_sys, epoch_counter_adc : epoch_counter_t;
begin
CONF_adc <= CONF_sys when rising_edge(CLK_ADC);
busy_in_adc <= busy_in_sys when rising_edge(CLK_ADC);
busy_out_sys <= busy_out_adc when rising_edge(CLK_SYS);
- ADC_CLK_TDC_OUT <= debug_adc(0).EpochCounter(10);
gen_cfd : for i in 0 to CHANNELS - 1 generate
trigger_gen(i) <= debug_sys(i).Trigger;
-- first convert to gray counting, then do clock domain crossing
- epoch_counter_adc(i) <= debug_adc(i).EpochCounter xor shift_right(debug_adc(i).EpochCounter,1);
- epoch_counter_sys(i) <= epoch_counter_adc(i) when rising_edge(CLK_SYS);
- epoch_counter(i) <= epoch_counter_sys(i); -- no back conversion to binary for now
+ --epoch_counter_adc(i) <= debug_adc(i).EpochCounter xor shift_right(debug_adc(i).EpochCounter,1);
+ --epoch_counter_sys(i) <= epoch_counter_adc(i) when rising_edge(CLK_SYS);
+ --epoch_counter(i) <= epoch_counter_sys(i); -- no back conversion to binary for now
THE_CFD : entity work.adc_processor_cfd_ch
generic map(
RAM_DATA => ram_data_adc(i),
RAM_BSY_IN => busy_in_adc,
RAM_BSY_OUT => busy_out_adc(i),
- DEBUG => debug_adc(i)
+ DEBUG => debug_adc(i),
+ EPOCH_COUNTER_IN => EPOCH_COUNTER_IN
);
ram_addr_sys(i) <= std_logic_vector(resize(ram_counter(i),ram_addr_sys(i)'length));
Q => ram_data_sys(i));
end generate;
- READOUT_TX.data_write <= RDO_write_main when rising_edge(CLK_SYS);
- READOUT_TX.data <= RDO_data_main when rising_edge(CLK_SYS);
+ -- <= RDO_write_main when rising_edge(CLK_SYS);
+ --READOUT_TX.data <= RDO_data_main when rising_edge(CLK_SYS);
readout_reset <= CONTROL(12) when rising_edge(CLK_SYS);
statebits <= std_logic_vector(to_unsigned(state_t'pos(state), 8));
wait until rising_edge(CLK_SYS);
READOUT_TX.busy_release <= '0';
READOUT_TX.data_finished <= '0';
- RDO_data_main <= (others => '0');
- RDO_write_main <= '0';
+ READOUT_TX.data <= (others => '0');
+ READOUT_TX.data_write <= '0';
busy_in_sys <= '0';
else
state <= WAIT_BSY;
end if;
- epoch_counter_save <= epoch_counter; -- all channels at the same time
+ --epoch_counter_save <= epoch_counter; -- all channels at the same time
end if;
when RELEASE_DIRECT =>
when WAIT_RAM =>
busy_in_sys <= '1';
ram_counter(channelselect) <= ram_counter(channelselect) + 1;
- RDO_data_main <= x"e0" & std_logic_vector(epoch_counter_save(channelselect));
- RDO_write_main <= not CONF_sys.ChannelDisable(DEVICE * CHANNELS + channelselect);
+ --RDO_data_main <= x"e0" & std_logic_vector(epoch_counter_save(channelselect));
+ --RDO_write_main <= not CONF_sys.ChannelDisable(DEVICE * CHANNELS + channelselect);
state <= READOUT;
state <= WAIT_BSY;
end if;
else
- RDO_data_main <= ram_data_sys(channelselect);
- RDO_write_main <= not CONF_sys.ChannelDisable(DEVICE * CHANNELS + channelselect);
+ READOUT_TX.data <= ram_data_sys(channelselect);
+ READOUT_TX.data_write <= not CONF_sys.ChannelDisable(DEVICE * CHANNELS + channelselect);
ram_counter(channelselect) <= ram_counter(channelselect) + 1;
end if;
when SEND_STATUS =>
- RDO_write_main <= '1';
- RDO_data_main <= x"20000000";
+ READOUT_TX.data_write <= '1';
+ READOUT_TX.data <= x"20000000";
-- nothing implemented yet
state <= RELEASE_DIRECT;
end case;
RAM_BSY_IN : in std_logic;
RAM_BSY_OUT : out std_logic;
- DEBUG : out debug_cfd_t
+ DEBUG : out debug_cfd_t;
+
+ EPOCH_COUNTER_IN : in unsigned(EPOCH_COUNTER_SIZE-1 downto 0)
);
end entity adc_processor_cfd_ch;
signal integral_sum : signed(RESOLUTION_CFD - 1 downto 0) := (others => '0');
- signal epoch_counter, epoch_counter_save : unsigned(23 downto 0) := (others => '0');
+ signal epoch_counter_save : unsigned(EPOCH_COUNTER_SIZE-1 downto 0) := (others => '0');
type state_t is (IDLE, INTEGRATE, WRITE1, WRITE2, WRITE3, FINISH, LOCKED, DEBUG_DUMP);
signal state : state_t := IDLE;
DEBUG.InvalidWordCount <= invalid_word_count when rising_edge(CLK);
DEBUG.Baseline <= baseline when rising_edge(CLK);
DEBUG.LastWord <= input when rising_edge(CLK);
- DEBUG.EpochCounter <= epoch_counter when rising_edge(CLK);
-- word checker, needed for ADC phase adjustment
gen_word_checker : for i in 0 to CHANNELS - 1 generate
begin
wait until rising_edge(CLK);
- epoch_counter <= epoch_counter + 1;
-
cfd_prev <= cfd.value;
if cfd_prev < 0 and cfd.value >= 0 and cfd.thresh = '1' then
zeroX := '1';
state <= INTEGRATE;
integral_counter := to_integer(CONF.IntegrateWindow);
integral_sum <= resize(delay_integral_out, RESOLUTION_CFD);
- cfd_prev_save <= cfd_prev;
+ cfd_prev_save <= cfd_prev;
cfd_save <= cfd.value;
- epoch_counter_save <= epoch_counter;
+ epoch_counter_save <= EPOCH_COUNTER_IN;
elsif CONF.DebugMode = 0 and RAM_BSY_IN = '1' then
state <= LOCKED;
elsif CONF.DebugMode /= 0 and RAM_BSY_IN = '1' then
signal regio_tx, busadc_tx, busspi_tx, busmem_tx, bussed_tx : CTRLBUS_TX;
-- always have enough signals for TDC
- -- readout_tx(0) is then used by TDC
- constant NUM_READOUTS : integer := DEVICES+1;
+ -- readout_tx(0) is used by (possibly available) TDC
+ -- readout_tx(1) is used by (possibly available) CFD EpochCounter
+ constant NUM_READOUTS : integer := DEVICES+2;
signal readout_rx : READOUT_RX;
signal readout_tx : readout_tx_array_t(0 to NUM_READOUTS-1);
TRIGGER_IN => TRIGGER_LEFT,
READOUT_RX => readout_rx,
- READOUT_TX => readout_tx(1 to DEVICES),
+ READOUT_TX => readout_tx(2 to DEVICES),
+ READOUT_TX_CFD => readout_tx(1),
BUS_RX => busadc_rx,
BUS_TX => busadc_tx,
CONTROL_REG_IN => tdc_ctrl_reg
);
- --tdc_inputs(1) used by CBM-MBS ETM
- --tdc_inputs(2) <= cbm_sync_pulser_i;
- --tdc_inputs(3) <= cbm_sync_timing_trigger_i;
- --tdc_inputs(4) <= JINLVDS(0); --NIM_IN(0);
- --JTTL(0 downto 15) <= (others => '0');
-
-
-
-
PROC_TDC_CTRL_REG : process
variable pos : integer range 0 to TDC_CONTROL_REG_NR-1;
begin