diff --git a/replacements/dtc/dtc-be/common/firmware/hdl/L1DataAggregator.vhd b/replacements/dtc/dtc-be/common/firmware/hdl/L1DataAggregator.vhd new file mode 100644 index 0000000000000000000000000000000000000000..53de7f902a410265ec9a3093fb18fab71dec27ac --- /dev/null +++ b/replacements/dtc/dtc-be/common/firmware/hdl/L1DataAggregator.vhd @@ -0,0 +1,275 @@ +library ieee; + use ieee.std_logic_1164.all; + use ieee.numeric_std.all; + --- + use work.ipbus.all; + use work.ipbus_reg_types.all; + use work.ipbus_decode_dtc_data_aggregator.all; + --- + use work.emp_data_types.all; + use work.emp_daqpath_types_package.all; + use work.emp_daqpath_user_package.all; + --- + use work.dtc_link_maps.all; + use work.dtc_constants.all; + use work.dtc_data_types.all; + + +entity L1DataAggregator is + generic ( + INPUT_LINKS : integer := cNumberOfFEModules + ); + port ( + --- Input Ports --- + clk_p : in std_logic; + daq_in : in tDaqDataLinkArray(INPUT_LINKS - 1 downto 0); + empty : in tDaqFlagLinkArray(INPUT_LINKS - 1 downto 0); + backpressure : in std_logic; + --- Output Ports --- + read : out tDaqFlagLinkArray(INPUT_LINKS - 1 downto 0); + data_out : out lword; + --- IPBus Ports --- + clk : in std_logic; + rst : in std_logic; + ipb_in : in ipb_wbus; + ipb_out : out ipb_rbus + ); +end entity L1DataAggregator; + + +architecture rtl of L1DataAggregator is + + + -- IPBus fabric + + signal ipb_to_slaves : ipb_wbus_array(N_SLAVES - 1 downto 0); + signal ipb_from_slaves : ipb_rbus_array(N_SLAVES - 1 downto 0); + + + -- Daqpath interface + + constant cNUM_CHANNELS : integer := INPUT_LINKS * cNumberOfCICs; + + signal word_fifo_rdata : generic_data_fifo_data_array(cNUM_CHANNELS - 1 downto 0); + signal id_fifo_rdata : ctrl_fifo_data_array(cNUM_CHANNELS - 1 downto 0); + signal nw_fifo_rdata : ctrl_fifo_data_array(cNUM_CHANNELS - 1 downto 0); + signal word_fifo_re : std_logic_vector(cNUM_CHANNELS - 1 downto 0); + signal id_fifo_re : std_logic_vector(cNUM_CHANNELS - 1 downto 0); + signal nw_fifo_re : std_logic_vector(cNUM_CHANNELS - 1 downto 0); + signal word_fifo_empty : std_logic_vector(cNUM_CHANNELS - 1 downto 0); + signal id_fifo_empty : std_logic_vector(cNUM_CHANNELS - 1 downto 0); + signal nw_fifo_empty : std_logic_vector(cNUM_CHANNELS - 1 downto 0); + signal daqpath_en : std_logic; + signal daqpath_rst : std_logic; + signal daqpath_ext_creg : ipb_reg_v(3 downto 0) := (others => (others => '0')); + signal daqpath_ext_sreg : ipb_reg_v(3 downto 0) := (others => (others => '0')); + + + -- Daqpath core + + signal int_data_out : std_logic_vector(63 downto 0); + signal int_data_we_out : std_logic; + signal int_idnw_out : std_logic_vector(31 downto 0); + signal int_idnw_we_out : std_logic; + signal slink : lword; + + + -- Output IPBus FIFO interface + + constant cNUM_LINKS : integer := 1; + signal output_data_fifo_wdata : data_fifo_data_array(0 to cNUM_LINKS - 1); + signal output_data_fifo_we : std_logic_vector(0 to cNUM_LINKS - 1); + signal output_data_fifo_empty : std_logic_vector(0 to cNUM_LINKS - 1); + signal output_data_fifo_full : std_logic_vector(0 to cNUM_LINKS - 1); + signal output_idnw_fifo_wdata : ipbus_data_array(0 to cNUM_LINKS - 1); + signal output_idnw_fifo_we : std_logic_vector(0 to cNUM_LINKS - 1); + signal output_idnw_fifo_empty : std_logic_vector(0 to cNUM_LINKS - 1); + signal output_idnw_fifo_full : std_logic_vector(0 to cNUM_LINKS - 1); + +begin + + --==============================-- + -- IPBus fabric + --==============================-- + + --==============================-- + fabric : entity work.ipbus_fabric_sel + --==============================-- + generic map ( + NSLV => N_SLAVES, + SEL_WIDTH => IPBUS_SEL_WIDTH + ) + port map ( + ipb_in => ipb_in, + ipb_out => ipb_out, + sel => ipbus_sel_dtc_data_aggregator(ipb_in.ipb_addr), + ipb_to_slaves => ipb_to_slaves, + ipb_from_slaves => ipb_from_slaves + ); + + --==============================-- + daq_control : entity work.ipbus_syncreg_v + --==============================-- + generic map ( + N_CTRL => 4, + N_STAT => 4 + ) + port map ( + clk => clk, + rst => rst, + ipb_in => ipb_to_slaves(N_SLV_DAQPATH_EXT_CTRL), + ipb_out => ipb_from_slaves(N_SLV_DAQPATH_EXT_CTRL), + slv_clk => clk_p, + d => daqpath_ext_sreg, + q => daqpath_ext_creg + ); + + + -- Status register 1-3 presents input FIFO status + -- Status register 0 presents output FIFO status + -- if output FIFOs not empty -> read them out through IPBus + + --==============================-- + status_registers_i : for i in 0 to cNUM_CHANNELS - 1 generate + --==============================-- + + daqpath_ext_sreg(1)(i) <= word_fifo_empty(i); + daqpath_ext_sreg(2)(i) <= id_fifo_empty(i); + daqpath_ext_sreg(3)(i) <= nw_fifo_empty(i); + + end generate status_registers_i; + + --==============================-- + status_registers_o : for i in 0 to cNUM_LINKS - 1 generate + --==============================-- + + daqpath_ext_sreg(0)(i * 4) <= output_data_fifo_empty(i); + daqpath_ext_sreg(0)(i * 4 + 1) <= output_idnw_fifo_empty(i); + daqpath_ext_sreg(0)(i * 4 + 2) <= output_data_fifo_full(i); + daqpath_ext_sreg(0)(i * 4 + 3) <= output_idnw_fifo_full(i); + + end generate status_registers_o; + + daqpath_ext_sreg(0)(31 downto 4 * cNUM_LINKS) <= (others => '0'); + + + -- Enable/reset signals for daqpath + + -- if daqpath_en=1 -> enabled + daqpath_en <= daqpath_ext_creg(0)(0); + + -- if daqpath_rst=1 -> all blocks internal to daqpath in reset + daqpath_rst <= daqpath_ext_creg(0)(4); + + + --==============================-- + -- DAQPATH + --==============================-- + + --==============================-- + map_links : for i in 0 to INPUT_LINKS - 1 generate + --==============================-- + + --==============================-- + map_channels : for j in 0 to cNumberOfCICs - 1 generate + --==============================-- + + word_fifo_rdata (i * cNumberOfCICs + j) <= daq_in(i)(j).data_word; + id_fifo_rdata (i * cNumberOfCICs + j) <= daq_in(i)(j).event_id; + nw_fifo_rdata (i * cNumberOfCICs + j) <= daq_in(i)(j).n_words; + word_fifo_empty (i * cNumberOfCICs + j) <= empty(i)(j).data_word; + id_fifo_empty (i * cNumberOfCICs + j) <= empty(i)(j).event_id; + nw_fifo_empty (i * cNumberOfCICs + j) <= empty(i)(j).n_words; + + read(i)(j).data_word <= word_fifo_re (i * cNumberOfCICs + j); + read(i)(j).event_id <= id_fifo_re (i * cNumberOfCICs + j); + read(i)(j).n_words <= nw_fifo_re (i * cNumberOfCICs + j); + + end generate map_channels; + + end generate map_links; + + -- Daqpath core instance + -- Version 1.1 with : - input data flexibility (1,2,4,8 bytes) + -- - header insertion programmable through ipbus (hdr_en) in daqpath_regs + -- - Data formatter to have 64-bits words @clk_p at the output side + -- - channel mask + -- slink output stream also provided - used in the MProcessor by the Ethernet interface + + --==============================-- + DaqpathCore : entity work.emp_daqpath_module + --==============================-- + generic map ( + NUM_CHANNELS => cNUM_CHANNELS, + N_CHAN_PER_GROUP => N_CHAN_PER_GROUP + ) + port map ( + ipb_clk => clk, + ipb_rst => rst, + ipb_in => ipb_to_slaves(N_SLV_DAQPATH_CSR), + ipb_out => ipb_from_slaves(N_SLV_DAQPATH_CSR), + clk => clk_p, + rst => daqpath_rst, + en => daqpath_en, + pause => backpressure, + data_out => int_data_out, + data_we_out => int_data_we_out, + idnw_out => int_idnw_out, + idnw_we_out => int_idnw_we_out, + slink_data => slink.data, + slink_dv => slink.valid, + slink_start => slink.start, + slink_end => slink.strobe, + word_fifo_rdata => word_fifo_rdata, + nw_fifo_rdata => nw_fifo_rdata, + id_fifo_rdata => id_fifo_rdata, + id_fifo_re => id_fifo_re, + nw_fifo_re => nw_fifo_re, + word_fifo_re => word_fifo_re, + word_fifo_empty => word_fifo_empty, + id_fifo_empty => id_fifo_empty, + nw_fifo_empty => nw_fifo_empty + ); + + -- daqpath stream exposed 'as is' + data_out <= slink; + + --==============================-- + -- IPBus Output FIFO + --==============================-- + + --==============================-- + map_output : for i in 0 to cNUM_LINKS - 1 generate + --==============================-- + + output_data_fifo_wdata(i) <= int_data_out; + output_data_fifo_we(i) <= int_data_we_out; + output_idnw_fifo_wdata(i) <= int_idnw_out; + output_idnw_fifo_we(i) <= int_idnw_we_out; + + end generate map_output; + + --==============================-- + OutputFifo : entity work.emp_daqpath_ipbus_output_FIFOs_array + --==============================-- + generic map ( + NUM_CHANNELS => cNUM_LINKS + ) + port map ( + dp_clk => clk_p, + ipb_clk => clk, + rst => daqpath_rst, + en => daqpath_en, + ipb_in => ipb_to_slaves(N_SLV_DAQPATH_OUT), + ipb_out => ipb_from_slaves(N_SLV_DAQPATH_OUT), + data_fifo_wdata => output_data_fifo_wdata, + data_fifo_we => output_data_fifo_we, + data_fifo_empty => output_data_fifo_empty, + data_fifo_full => output_data_fifo_full, + idnw_fifo_wdata => output_idnw_fifo_wdata, + idnw_fifo_we => output_idnw_fifo_we, + idnw_fifo_empty => output_idnw_fifo_empty, + idnw_fifo_full => output_idnw_fifo_full + ); + +end architecture rtl;