-- -- Analog acquisition chain. -- -- Joris van Rantwijk 2024 -- library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.puzzlefw_pkg.all; entity acquisition_chain is generic ( -- Number of analog input channels. It should be either 2 or 4. -- If num_channels == 2, the acquisition always runs in 2-channel mode. -- IF num_channels == 4, the acquisition can run in 2-channel mode -- or 4-channel mode. num_channels: integer range 2 to 4 ); port ( -- Main clock, active on rising edge. clk: in std_logic; -- Reset, active high, synchronous to main clock. reset: in std_logic; -- High to enable data acquisition. -- Low to disable data acquisition, ignore triggers, stop emitting -- samples and clear the trigger status. acquisition_en: in std_logic; -- Trigger delay in clock cycles. trigger_delay: in std_logic_vector(15 downto 0); -- Number of decimated samples per trigger minus 1. record_length: in std_logic_vector(15 downto 0); -- Decimation factor minus 1. decimation_factor: in std_logic_vector(17 downto 0); -- High to sum input samples; low to select single samples. averaging: in std_logic; -- Number of right-shift steps to apply to ADC data. -- When set to zero, the least significant ADC sample bit aligns -- with the least significant decimated sample bit. shift_steps: in std_logic_vector(3 downto 0); -- High to enable 4-channel mode. -- Ignored if num_channels == 2. ch4_mode: in std_logic; -- High to enable automatic (continuous) triggering. trig_auto_en: in std_logic; -- High to enable external triggering. trig_ext_en: in std_logic; -- High to force a trigger event (if the acquisition chain is ready). trig_force: in std_logic; -- Select external input signal to use as trigger. trig_ext_select: in std_logic_vector(1 downto 0); -- High to trigger on falling edge, low to trigger on rising edge. trig_ext_falling: in std_logic; -- Global timestamp counter. timestamp_in: in std_logic_vector(timestamp_bits - 1 downto 0); -- ADC input data. adc_data_in: in adc_data_array(0 to num_channels - 1); -- External trigger signals, already synchronized and de-glitched. trig_ext_in: in std_logic_vector(3 downto 0); -- High if the acquisition chain is waiting for a trigger. trig_waiting: out std_logic; -- Output data stream. out_valid: out std_logic; out_ready: in std_logic; out_empty: in std_logic; out_data: out dma_data_type ); end entity; architecture arch of acquisition_chain is -- Number of data bits for accumulating ADC samples when averaging. constant accum_data_bits: natural := 32; subtype accum_data_type is std_logic_vector(accum_data_bits - 1 downto 0); type accum_data_array is array(natural range <>) of accum_data_type; signal s_trigger: std_logic; signal s_trig_ack: std_logic; signal s_sample_start: std_logic; signal s_sample_integrate: std_logic; signal s_sample_done: std_logic; signal s_adc_sample: adc_data_array(0 to num_channels - 1); signal s_adc_shifted: accum_data_array(0 to num_channels - 1); signal s_sample_decimated: sample_data_array(0 to num_channels - 1); begin -- External trigger detector. inst_trigger_detector: entity work.trigger_detector port map ( clk => clk, reset => reset, trig_auto_en => trig_auto_en, trig_ext_en => trig_ext_en, trig_force => trig_force, trig_select => trig_ext_select, trig_falling => trig_ext_falling, trig_ext_in => trig_ext_in, trig_out => s_trigger ); -- Timing of sampling and decimation. inst_acquisition_manager: entity work.acquisition_manager port map ( clk => clk, reset => reset, acquisition_en => acquisition_en, trigger_delay => trigger_delay, record_length => record_length, decimation_factor => decimation_factor, averaging => averaging, trig_in => s_trigger, trig_waiting => trig_waiting, trig_ack => s_trig_ack, sample_start => s_sample_start, sample_integrate => s_sample_integrate, sample_done => s_sample_done ); -- Shift and decimation chains for each ADC channel. inst_channels: for i in 0 to num_channels - 1 generate inst_shift: entity work.shift_engine generic map ( input_data_bits => adc_data_bits, output_data_bits => accum_data_bits, pre_shift_left => accum_data_bits - sample_data_bits, signed_data => false ) port map ( clk => clk, in_data => adc_data_in(i), in_shift => shift_steps, out_data => s_adc_shifted(i) ); inst_decimation: entity work.sample_decimation generic map ( input_data_bits => accum_data_bits, output_data_bits => sample_data_bits ) port map ( clk => clk, reset => reset, start => s_sample_start, integrate => s_sample_integrate, in_data => s_adc_shifted(i), out_data => s_sample_decimated(i) ); end generate; -- Format sample data stream and insert trigger timestamps. inst_stream: entity work.acquisition_stream generic map ( num_channels => num_channels ) port map ( clk => clk, reset => reset, ch4_mode => ch4_mode, timestamp_in => timestamp_in, trig_ack => s_trig_ack, sample_valid => s_sample_done, sample_data => s_sample_decimated, out_valid => out_valid, out_ready => out_ready, out_empty => out_empty, out_data => out_data ); end architecture;