diff --git a/README.md b/README.md index aea2de9c5605855ed25ca65038165369c8f9c8b6..2a46eb3c0698b6b2b943e1053410ae5d14bdec0e 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# MProcessor Firmware - 2x10gbe +# MProcessor Firmware - 2x10gbe - OUTDATED ## Instructions to Run ```bash # Pull the package onto the Serenity card diff --git a/common/addr_table/link_aggregator.xml b/common/addr_table/link_aggregator.xml index ce2c72808222577139aaf0aeca6cfb7895965644..1d4ee0bb29767d2cfd90965c97319c29853c2d9b 100644 --- a/common/addr_table/link_aggregator.xml +++ b/common/addr_table/link_aggregator.xml @@ -1,12 +1,28 @@ <node description="Link Aggregator control and status" fwinfo="endpoint"> <node id="chan_sel" address="0x000" description="Bx channel select" fwinfo="endpoint;width=0"/> - <node id="control" address="0x001" fwinfo="endpoint;width=0"> - <node id="input_link_mask" mask="0x03f"/> - <node id="reset" mask="0x40"/> - <node id="trigger_threshold" mask="0x780"/> + <node id="control" address="0x002" fwinfo="endpoint;width=1"> + <node id="control_l" address="0x0"> + <node id="input_link_mask" mask="0x03f"/> + <node id="reset" mask="0x40"/> + <node id="trigger_threshold_l_0" mask="0x00000780"/> + <node id="trigger_threshold_l_1" mask="0x00007800"/> + <node id="trigger_threshold_l_2" mask="0x00078000"/> + <node id="trigger_threshold_l_3" mask="0x00780000"/> + <node id="trigger_threshold_l_4" mask="0x07800000"/> + <node id="trigger_threshold_l_5" mask="0x78000000"/> + </node> + <node id="control_u" address="0x1"> + <node id="trigger_threshold_u_0" mask="0x0000000f"/> + <node id="trigger_threshold_u_1" mask="0x000000f0"/> + <node id="trigger_threshold_u_2" mask="0x00000f00"/> + <node id="trigger_threshold_u_3" mask="0x0000f000"/> + <node id="trigger_threshold_u_4" mask="0x000f0000"/> + <node id="trigger_threshold_u_5" mask="0x00f00000"/> + </node> </node> <node id="rate_monitoring" address="0x004" fwinfo="endpoint;width=2"> <node id="bx_valid_count" address="0x0"/> + <node id="tracking_event_count" address="0x1"/> </node> <node id="monitoring" address="0x008" fwinfo="endpoint;width=3"> <node id="non_empty_count_0" address="0x0"/> diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml index 3075dce5e54dad2556a4ab30b501be3f7c8afb67..1381fe9cc119449a00faadd66694afae4d03176b 100644 --- a/common/addr_table/mprocessor.xml +++ b/common/addr_table/mprocessor.xml @@ -10,9 +10,19 @@ <node id="header_user_bits" address="0x1"/> </node> - <node id="csr" address="0x24" description="MProcessor control and status" fwinfo="endpoint;width=2"> + <node id="csr" address="0x30" description="MProcessor control and status" fwinfo="endpoint;width=4"> <node id="header_start_select" address="0x0" mask="0x7"/> - <node id="lff" address="0x2" mask="0x0001"/> - <node id="super_id" address="0x3"/> + <node id="occupancy_windowL" address="0x1"/> + <node id="occupancy_windowH" address="0x2" mask="0x000f"/> + <node id="localx_windowL" address="0x3"/> + <node id="localx_windowH" address="0x4" mask="0x000f"/> + <node id="lff" address="0x8" mask="0x0001"/> + <node id="super_id" address="0x9"/> + <node id="occupancy_max_value" address="0xa"/> + <node id="localx_max_value" address="0xb"/> </node> + + <node id="occupancy_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/> + + <!-- <node id="track_finder" address="0x800" module="file://track_finder.xml" fwinfo="endpoint;width=11"/> --> </node> diff --git a/common/addr_table/track_finder.xml b/common/addr_table/track_finder.xml new file mode 100644 index 0000000000000000000000000000000000000000..cbe8cca84f3951d08315b5e1fcd52e3d7155abf6 --- /dev/null +++ b/common/addr_table/track_finder.xml @@ -0,0 +1,15 @@ +<node description="TrackFinder Control and Status" fwinfo="endpoint"> + <node id="csr" address="0x00" description="TrackFinder control and status" fwinfo="endpoint;width=3"> + <node id="localx_windowL" address="0x0"/> + <node id="localx_windowH" address="0x1" mask="0x000f"/> + <node id="localx_max_value" address="0x4"/> + <node id="deltax_max_value" address="0x5"/> + <node id="localy_max_value" address="0x6"/> + <node id="deltay_max_value" address="0x7"/> + </node> + + <node id="tracking_localx_mem" address="0x100" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/> + <node id="tracking_deltax_mem" address="0x200" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/> + <node id="tracking_localy_mem" address="0x300" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/> + <node id="tracking_deltay_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/> +</node> \ No newline at end of file diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep index f8a06571bcd54844ef87fc64bc6df49d81c00ff4..113f50c93b68131d417995869b9891cd02bc603b 100644 --- a/common/firmware/cfg/module.dep +++ b/common/firmware/cfg/module.dep @@ -3,6 +3,7 @@ setup -f --cd ../cfg settings.tcl src fixed_pkg_2008.vhd src mprocessor_constants.vhd +src tracking_constants.vhd src MProcessor.vhd src LinkAggregatorCore.vhd @@ -10,12 +11,18 @@ src LinkAggregatorIPBus.vhd src LinkCombinerCore.vhd src LinkCombinerIPBus.vhd src --vhdl2008 TrackReconstructor.vhd +src mprocessor_data_types.vhd +src PayloadHeaderGenerator.vhd +src TrackFinder.vhd src ipbus_decode_link_aggregator.vhd src ipbus_decode_mprocessor.vhd +src ipbus_decode_track_finder.vhd addrtab -t mprocessor.xml addrtab -t link_aggregator.xml +addrtab -t track_finder.xml + # IP Cores src --cd ../cgn link_agg_single_link_fifo.xci @@ -28,4 +35,4 @@ src --cd ../cgn link_agg_all_links_fifo.xci setup -f --cd ../cgn link_agg_all_links_fifo.tcl src --cd ../cgn link_combin_buffer.xci -setup -f --cd ../cgn link_combin_buffer.tcl \ No newline at end of file +setup -f --cd ../cgn link_combin_buffer.tcl diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd index de44256fa46d86a904347903b91f5215562ac75e..fc81c2f1f245d2a3f88164cc4aba9d3810ea4bdf 100644 --- a/common/firmware/hdl/LinkAggregatorCore.vhd +++ b/common/firmware/hdl/LinkAggregatorCore.vhd @@ -1,15 +1,19 @@ library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; +use IEEE.STD_LOGIC_MISC.ALL; use work.emp_data_types.all; +use work.tracking_constants.all; use work.ipbus.all; use work.ipbus_reg_types.all; +use work.mprocessor_data_types.all; entity LinkAggregatorCore is generic ( - N_LINKS : integer + N_LINKS : integer; + INDEX : integer := 0 ); port ( --- Input Ports --- @@ -17,14 +21,16 @@ entity LinkAggregatorCore is reset : in std_logic; packet_start : in std_logic; links_in : in ldata(N_LINKS - 1 downto 0); - trigger_threshold : in integer := 0; + thresholds_l : in tIntegerArray := (others => 0); + thresholds_u : in tIntegerArray := (others => 0); --- Output Ports --- links_out : out ldata(7 downto 0) := (others => LWORD_NULL); uncompressed_stubs : out ldata(N_LINKS * 8 - 1 downto 0) := (others => LWORD_NULL); readout_reset : out std_logic := '0'; --- Debug Ports --- status_bits : out std_logic_vector(15 downto 0); - --- IPBus Ports --- + debug_tracking_event_count : out std_logic_vector(31 downto 0) := (others => '0'); + debug_tracking_stubs_out : out ldata(N_LINKS - 1 downto 0) := (others => LWORD_NULL); non_empty_counts : out ipb_reg_v(8*N_LINKS - 1 downto 0); bx_valid_count_out : out ipb_reg_v(0 downto 0) ); @@ -125,19 +131,40 @@ architecture compressed of LinkAggregatorCore is output(31 downto 28) := (others => '0'); return output; end function; + + signal packet_start_buffered : std_logic := '0'; signal output_overflow_array : std_logic_vector(cBoxcarBx - 1 downto 0) := (others => '0'); signal route_overflow_array : tEnableArray := cNullEnableArray; signal cache_overflow_array : tEnableArray := cNullEnableArray; signal bx_valid_array : std_logic_vector(N_LINKS * cBoxcarBx - 1 downto 0) := (others => '0'); - + signal bx_alllinks_valid_array : std_logic_vector(8 - 1 downto 0) := (others => '0'); + signal non_empty_fifo_count : ipb_reg_v(8*N_LINKS - 1 downto 0) := (others => (others => '0')); signal bx_valid_count : ipb_reg_v(0 downto 0) := (others => (others => '0')); signal pBx_counter : integer := 0; + + signal readout_reset_signal : std_logic := '0'; + signal links_out_signal : ldata(7 downto 0) := (others => LWORD_NULL); + signal uncompressed_stubs_signal : ldata(N_LINKS * 8 - 1 downto 0) := (others => LWORD_NULL); + + signal track_stubs : ldata(N_LINKS - 1 downto 0) := (others => LWORD_NULL); + signal single_stub_event : std_logic_vector(N_LINKS - 1 downto 0) := (others => '0'); + signal event_valid_for_tracking : std_logic := '0'; + signal tracking_event_count : unsigned(31 downto 0) := (others => '0'); begin + --==============================-- + pBufferPacketStart: process(clk_p) + --==============================-- + begin + if rising_edge(clk_p) then + packet_start_buffered <= packet_start; + end if; + end process; + --==============================-- genLinkCache : for i in N_LINKS - 1 downto 0 generate -- Generator to produce the caching and routing FIFOs for each link @@ -156,7 +183,7 @@ begin if rising_edge(clk_p) then wr_en_array_cache <= (others => '0'); wr_en_array_cache(to_integer(unsigned(links_in(i).data(21 downto 19)))) <= links_in(i).valid; - data_in <= std_logic_vector(to_unsigned(i, 4)) & links_in(i).data(cFIFOWidth - 1 - 4 downto 0); + data_in <= std_logic_vector(to_unsigned(INDEX*N_LINKS + i, 4)) & links_in(i).data(cFIFOWidth - 1 - 4 downto 0); end if; end process pRouteInputData; @@ -184,7 +211,7 @@ begin begin if rising_edge(clk_p) then -- If FIFO is not empty at start of packet, enable readout to routing FIFO - if packet_start = '1' then + if packet_start_buffered = '1' then if empty_cache = '0' then rd_en_cache <= '1'; countdown_iterator <= unsigned(count_cache) - 1; @@ -195,11 +222,11 @@ begin else countdown_iterator <= countdown_iterator; rd_en_cache <= '0'; - end if; + end if; end if; -- Check for non-empty FIFOs at reset if reset = '1' then - non_empty_fifo_count(N_LINKS*j + i) <= (others => '0'); + non_empty_fifo_count(N_LINKS*j + i) <= (others => '0'); else if route_reset = '1' then if empty_route = '0' then @@ -215,8 +242,8 @@ begin --==============================-- begin if rising_edge(clk_p) then - if packet_start = '1' then - if unsigned(count_cache) >= trigger_threshold then + if packet_start_buffered = '1' then + if unsigned(count_cache) >= thresholds_l(i) and (unsigned(count_cache) <= thresholds_u(i) or thresholds_u(i) < thresholds_l(i)) then bx_valid_array(N_LINKS*j + i) <= '1'; else bx_valid_array(N_LINKS*j + i) <= '0'; @@ -225,12 +252,29 @@ begin end if; end process pCheckBxValidConditionPerLink; + --==============================-- + genTrackingEventCheck : if j = 0 generate + --==============================-- + begin + --==============================-- + pCheckForTrackingEvent : process(clk_p) + --==============================-- + begin + if rising_edge(clk_p) then + if unsigned(count_cache) = 1 then + single_stub_event(i) <= '1'; + else + single_stub_event(i) <= '0'; + end if; + end if; + end process pCheckForTrackingEvent; + end generate; -- Enable writing of routing FIFO using the valid flag of the cache FIFO wr_en_route <= valid_cache; din_route <= dout_cache; - uncompressed_stubs(cBoxcarBx * i + j).data <= dout_cache; - uncompressed_stubs(cBoxcarBx * i + j).valid <= valid_cache; + uncompressed_stubs_signal(cBoxcarBx * i + j).data <= dout_cache; + uncompressed_stubs_signal(cBoxcarBx * i + j).valid <= valid_cache; --==============================-- @@ -273,7 +317,7 @@ begin ); -- Combine the IPBus 'reset' with the 'packet_start' signal to generate the reset signal for the routing FIFO. - route_reset <= reset or packet_start; + route_reset <= reset or packet_start_buffered; end generate genLinkBxCache; @@ -281,7 +325,7 @@ begin --==============================-- - genAggregatedFIFOs : for i in 7 downto 0 generate + genAggregatedFIFOs : for i in cBoxcarBx - 1 downto 0 generate -- Generate the output FIFO instances, one per Bx, as well as the logic to route the stubs from the link FIFOs to the output. --==============================-- signal pointer : integer := 0; @@ -303,7 +347,6 @@ begin -- Process to iterate of the link FIFOs and route the data to the output FIFO, if data is present on a given link. -- The process uses a rotating pointer to repeatedly iterate over all links, taking one stub per iteration, until all link FIFOs are empty. --==============================-- - variable bx_valid_variable : std_logic := '0'; begin @@ -344,12 +387,8 @@ begin wr_en <= '0'; end if; - -- Check if Bx is valid - bx_valid_variable := '1'; - for j in 0 to N_LINKS - 1 loop - bx_valid_variable := bx_valid_variable and bx_valid_array(N_LINKS*i + j); - end loop; - bx_valid <= bx_valid_variable; + bx_valid <= and_reduce(bx_valid_array(N_LINKS*(i+1) - 1 downto N_LINKS*i)); + bx_alllinks_valid_array(i) <= bx_valid; -- If counter is at the end of a packet, then start to readout the contents of the aggregated FIFOs if counter = 47 then @@ -364,14 +403,13 @@ begin end if; if valid = '1' then - links_out(i).valid <= '1'; - links_out(i).data <= dout; + links_out_signal(i).valid <= '1'; + links_out_signal(i).data <= dout; else - links_out(i).valid <= '0'; - links_out(i).data <= (others => '0'); + links_out_signal(i).valid <= '0'; + links_out_signal(i).data <= (others => '0'); end if; - links_out(i).strobe <= '1'; - + links_out_signal(i).strobe <= '1'; end if; end process pIteratePointer; @@ -398,7 +436,7 @@ begin data_count => data_count ); - all_links_reset <= reset or packet_start; + all_links_reset <= reset or packet_start_buffered; end generate; @@ -408,7 +446,7 @@ begin --==============================-- begin if rising_edge(clk_p) then - if packet_start = '1' then + if packet_start_buffered = '1' then counter <= 0; else if counter = 64 then @@ -418,18 +456,17 @@ begin end if; end if; -- If counter is at the end of a packet, then start to readout the contents of the aggregated FIFOs - if counter = 48 then - readout_reset <= '1'; + if counter = 49 then + readout_reset_signal <= '1'; else - readout_reset <= '0'; + readout_reset_signal <= '0'; end if; end if; end process pReadoutReset; - + --==============================-- pCountValidBits : process(clk_p) --==============================-- - variable bx_valid_variable : std_logic := '0'; begin if rising_edge(clk_p) then if counter = 47 then @@ -442,23 +479,44 @@ begin end if; end if; - if pBx_counter < 8 then - bx_valid_variable := '1'; - for j in 0 to N_LINKS - 1 loop - bx_valid_variable := bx_valid_variable and bx_valid_array(N_LINKS*pBx_counter + j); - end loop; - end if; - -- Increment counter if bx_valid is set high when readout is started if reset = '1' then bx_valid_count(0) <= (others => '0'); else - if bx_valid_variable = '1' and pBx_counter < 8 then - bx_valid_count(0) <= std_logic_vector(unsigned(bx_valid_count(0)) + 1); + if pBx_counter < 8 then + if bx_alllinks_valid_array(pBx_counter) = '1' then + bx_valid_count(0) <= std_logic_vector(unsigned(bx_valid_count(0)) + 1); + end if; end if; end if; end if; end process pCountValidBits; + + --==============================-- + pExtractTrackingEvent : process(clk_p) + --==============================-- + begin + if rising_edge(clk_p) then + event_valid_for_tracking <= and_reduce(single_stub_event); + + if readout_reset_signal = '1' then + if event_valid_for_tracking = '1' then + tracking_event_count <= tracking_event_count + 1; + + for i in 0 to N_LINKS - 1 loop + track_stubs(i).valid <= '1'; + track_stubs(i).data <= uncompressed_stubs_signal(8*i).data; + end loop; + else + track_stubs <= (others => LWORD_NULL); + end if; + end if; + end if; + end process pExtractTrackingEvent; + + readout_reset <= readout_reset_signal; + links_out <= links_out_signal; + uncompressed_stubs <= uncompressed_stubs_signal; --==============================-- -- Debug @@ -475,5 +533,7 @@ begin status_bits(9) <= route_overflow_array(0)(0); -- link_aggregator_route_0_0_overflow; non_empty_counts <= non_empty_fifo_count; bx_valid_count_out <= bx_valid_count; + debug_tracking_event_count <= std_logic_vector(tracking_event_count); + debug_tracking_stubs_out <= track_stubs; end compressed; diff --git a/common/firmware/hdl/LinkAggregatorIPBus.vhd b/common/firmware/hdl/LinkAggregatorIPBus.vhd index 43b94dd07529d7d179376fdc4eae9e5cd1505d03..3969e55b8370f67eb2a740ce10b33d78d92ca027 100644 --- a/common/firmware/hdl/LinkAggregatorIPBus.vhd +++ b/common/firmware/hdl/LinkAggregatorIPBus.vhd @@ -5,13 +5,15 @@ use work.emp_data_types.all; use work.ipbus.all; use work.ipbus_reg_types.all; +use work.mprocessor_data_types.all; use work.ipbus_decode_link_aggregator.all; entity LinkAggregatorIPBus is generic ( - N_LINKS : integer + N_LINKS : integer; + INDEX : integer := 0 ); port ( --- Input Ports --- @@ -22,6 +24,7 @@ entity LinkAggregatorIPBus is links_out : out ldata(7 downto 0) := (others => LWORD_NULL); uncompressed_stubs : out ldata(N_LINKS * 8 - 1 downto 0) := (others => LWORD_NULL); readout_reset : out std_logic := '0'; + tracking_stubs : out ldata(N_LINKS - 1 downto 0) := (others => LWORD_NULL); --- IPBus Ports --- ipb_clk : in std_logic; ipb_rst : in std_logic; @@ -39,12 +42,16 @@ architecture Behavorial of LinkAggregatorIPBus is signal ipb_chain : ipbdc_bus_array(8 downto 0); -- signal link_aggregator_status_registers : ipb_reg_v(4 - 1 downto 0) := (others => (others => '0')); - signal control_registers : ipb_reg_v(1 - 1 downto 0) := (others => (others => '0')); + signal control_registers : ipb_reg_v(1 downto 0) := (others => (others => '0')); signal mprocessor_monitoring_registers : ipb_reg_v(8*N_LINKS - 1 downto 0) := (others => (others => '0')); - signal rate_monitoring_registers : ipb_reg_v(1 - 1 downto 0) := (others => (others => '0')); + signal rate_monitoring_registers : ipb_reg_v(2 - 1 downto 0) := (others => (others => '0')); signal bx_valid_count : ipb_reg_v(1 - 1 downto 0) := (others => (others => '0')); signal masked_links : ldata(N_LINKS - 1 downto 0) := (others => LWORD_NULL); + signal thresholds_l : tIntegerArray := (others => 0); + signal thresholds_u : tIntegerArray := (others => 0); + + signal tracking_event_count : std_logic_vector(31 downto 0) := (others => '0'); begin @@ -86,7 +93,7 @@ begin ControlInstance: entity work.ipbus_ctrlreg_v --==============================-- generic map( - N_CTRL => 1, + N_CTRL => 2, N_STAT => 0 ) port map( @@ -103,7 +110,7 @@ begin --==============================-- generic map( N_CTRL => 0, - N_STAT => 1 + N_STAT => 2 ) port map( clk => ipb_clk, @@ -187,28 +194,40 @@ begin end generate gMonitoringRegisters; + genThresholds: for i in 0 to N_LINKS - 1 generate + begin + thresholds_l(i) <= to_integer(unsigned(control_registers(0)(4*(i+1) - 1 + 7 downto 4*i + 7))); + thresholds_u(i) <= to_integer(unsigned(control_registers(1)(4*(i+1) - 1 downto 4*i))); + end generate; + + --==============================-- LinkAggregatorInstance: entity work.LinkAggregatorCore --==============================-- generic map ( - N_LINKS => N_LINKS + N_LINKS => N_LINKS, + INDEX => INDEX ) port map ( --- Input Ports --- clk_p => clk_p, - reset => control_registers(0)(N_LINKS + 1 - 1), + reset => control_registers(0)(6), packet_start => packet_start, links_in => masked_links, - trigger_threshold => to_integer(unsigned(control_registers(0)(N_LINKS + 5 - 1 downto N_LINKS + 1))), + thresholds_l => thresholds_l, + thresholds_u => thresholds_u, --- Output Ports --- links_out => links_out, readout_reset => readout_reset, --- Debug Ports --- -- status_bits => link_aggregator_status_registers(3)(15 downto 0), non_empty_counts => mprocessor_monitoring_registers, - bx_valid_count_out => bx_valid_count + bx_valid_count_out => bx_valid_count, + debug_tracking_event_count => tracking_event_count, + debug_tracking_stubs_out => tracking_stubs ); rate_monitoring_registers(0) <= bx_valid_count(0); + rate_monitoring_registers(1) <= tracking_event_count; end Behavorial; diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd index 5770215a5f77e1218f812ccbd46bb9df3e6f70df..66086644dccc63c58fd09e47e4c28ba0cd4acc5e 100644 --- a/common/firmware/hdl/LinkCombinerCore.vhd +++ b/common/firmware/hdl/LinkCombinerCore.vhd @@ -2,11 +2,10 @@ library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; use work.emp_data_types.all; -use work.front_end_data_types.all; -use work.module_constants.all; use work.dtc_link_maps.all; -use work.dtc_data_types.all; use work.dtc_constants.all; +use work.dtc_data_types.all; +use IEEE.std_logic_misc.all; entity LinkCombinerCore is @@ -21,14 +20,14 @@ entity LinkCombinerCore is output_enable : in std_logic := '0'; links_in : in ldata(N_INPUT_LINKS - 1 downto 0); packet_start : in std_logic; - header_in : in tCICHeaderArray(cNumberOfFEModules * cNumberOfCICs - 1 downto 0) := (others => ('0', (others => '0'), (others => '0'), (others => '0'))); - header_user_bits : in std_logic_vector(31 downto 0) := (others => '0'); + payload_header : in std_logic_vector(127 downto 0) := (others => '0'); --- Ouput Ports --- link_out : out lword := LWORD_NULL; --- Debug Ports --- debug : out lword := LWORD_NULL; debug_super_id : out std_logic_vector(31 downto 0); - debug_fifo : out std_logic_vector(31 downto 0) := (others => '0') + debug_fifo : out std_logic_vector(31 downto 0) := (others => '0'); + debug_packet_size : out lword := LWORD_NULL ); end LinkCombinerCore; @@ -89,7 +88,7 @@ architecture Behavioral of LinkCombinerCore is constant cNullValidArray : std_logic_vector(N_INPUT_LINKS - 1 downto 0) := (others => '0'); constant cFullEmptyArray : std_logic_vector(N_INPUT_LINKS - 1 downto 0) := (others => '1'); - -- Signals + -- Signals signal input_dout_array : tWordArray(0 to N_INPUT_LINKS - 1) := (others => (others => '0')); signal input_rd_en_array : std_logic_vector(N_INPUT_LINKS - 1 downto 0) := (others => '0'); signal input_almost_empty_array, input_valid_array : std_logic_vector(N_INPUT_LINKS - 1 downto 0) := (others => '0'); @@ -115,7 +114,6 @@ architecture Behavioral of LinkCombinerCore is signal output_rd_en : std_logic := '0'; signal counter : integer := 0; - signal status_sr : tStatusShiftRegister := (others => (others => '0')); signal bcid_sr : tBCIDShiftRegister := (others => (others => '0')); signal super_id : unsigned(32 - 1 downto 0) := (others => '0'); @@ -126,6 +124,7 @@ architecture Behavioral of LinkCombinerCore is begin + --==============================-- genInputLinkBuffers : for i in 0 to N_INPUT_LINKS - 1 generate --==============================-- @@ -195,6 +194,8 @@ begin variable data_count : unsigned(7 downto 0); begin if rising_edge(clk_p) then + debug_packet_size <= LWORD_NULL; + output_valid_previous <= output_valid; if output_valid = '1' and output_rd_en_check = '1' then link_out.valid <= '1'; @@ -214,6 +215,9 @@ begin if data_count >= 2 and output_readout_countdown = 0 then output_rd_en_check <= output_enable; output_readout_countdown <= to_integer(data_count); + + debug_packet_size.valid <= '1'; + debug_packet_size.data(7 downto 0) <= output_data_count; elsif output_almost_full = '1' and output_readout_countdown = 0 then output_rd_en_check <= output_enable; output_readout_countdown <= to_integer(data_count); @@ -268,7 +272,7 @@ begin begin if rising_edge(clk_p) then -- Iterate pointer to successively empty the input FIFOs - if input_data_valid = '1' and counter = 4 then + if input_data_valid = '1' and counter = 3 then if input_almost_empty_array(output_pointer) = '0' then input_rd_en_array(output_pointer) <= '1'; else @@ -286,6 +290,8 @@ begin end if; end if; else + output_pointer <= 0; + next_pointer_location := 0; input_rd_en_array(output_pointer) <= '0'; end if; @@ -293,7 +299,7 @@ begin if packet_start = '1' then counter <= 0; else - if counter < 4 then + if counter < 3 then counter <= counter + 1; else counter <= counter; @@ -301,83 +307,27 @@ begin end if; output_pointer_buffered <= output_pointer; output_din <= input_dout_array(output_pointer_buffered); - output_wr_en <= input_valid_array(output_pointer_buffered); - - - if reset = '1' then - packet_stub_count <= (others => '0'); - packet_stub_count_previous <= packet_stub_count; - packet_stub_counter_pointer <= 0; - packet_stub_count_done <= '0'; - else - if packet_stub_count_done = '0' then - if packet_stub_counter_pointer = (cNumberOfFEModules - 1) * cNumberOfCICs then - packet_stub_count_done <= '1'; - end if; - packet_stub_count <= packet_stub_count + unsigned(header_in(packet_stub_counter_pointer).stub_count) + unsigned(header_in(packet_stub_counter_pointer + 1).stub_count); - packet_stub_counter_pointer <= packet_stub_counter_pointer + cNumberOfCICs; - end if; - end if; + output_wr_en <= input_valid_array(output_pointer_buffered) and (not reset); if counter = 1 then - output_wr_en_buf <= '1'; - output_din_buf(63 downto 32) <= header_user_bits; - output_din_buf(31 downto 0) <= std_logic_vector(super_id); - elsif counter = 2 then - output_din_buf <= (others => '0'); - output_din_buf(63 downto 56) <= std_logic_vector(packet_stub_count_previous); - output_din_buf(47 downto 36) <= bcid_sr(bcid_sr'high); output_wr_en_buf <= '1'; - if cNumberOfFEModules < 3 then - output_din_buf(cNumberOfFEModules * cNumberOfCICs * 9 - 1 downto 0) <= status_sr(status_sr'high); - else - output_din_buf(2 * cNumberOfCICs * 9 - 1 downto 0) <= status_sr(status_sr'high)(2 * cNumberOfCICs * 9 - 1 downto 0); - end if; - elsif counter = 3 then + output_din_buf <= payload_header(63 downto 0); + elsif counter = 2 then output_din_buf <= (others => '0'); + output_din_buf(19 downto 0) <= payload_header(83 downto 64); output_wr_en_buf <= '1'; - if cNumberOfFEModules >= 3 and cNumberOfFEModules < 6 then - output_din_buf((cNumberOfFEModules - 2) * cNumberOfCICs * 9 - 1 downto 0) <= status_sr(status_sr'high)(cNumberOfFEModules * cNumberOfCICs * 9 - 1 downto 2 * cNumberOfCICs * 9); - end if; else - output_wr_en_buf <= output_wr_en; + output_wr_en_buf <= output_wr_en and (not reset); output_din_buf <= output_din; end if; end if; end process pCombineBuffers; - - --==============================-- - pBufferHeader: process(clk_p) - --==============================-- - variable status : std_logic_vector(cNumberOfFEModules * cNumberOfCICs * 9 - 1 downto 0) := (others => '0'); - variable bcid : std_logic_vector(12 - 1 downto 0) := (others => '0'); - begin - if rising_edge(clk_p) then - if output_reset = '1' then - super_id <= (others => '0'); - else - if packet_start = '1' then - for i in cNumberOfFEModules - 1 downto 0 loop - status(i*cNumberOfCICs*9 + 8 downto i*cNumberOfCICs*9) := std_logic_vector(header_in(i*cNumberOfCICs).status); - status(i*cNumberOfCICs*9 + 17 downto i*cNumberOfCICs*9 + 9) := std_logic_vector(header_in(i*cNumberOfCICs + 1).status); - end loop; - status_sr <= status_sr(status_sr'high - 1 downto 0) & status; - bcid := std_logic_vector(header_in(0).bcid); - bcid_sr <= bcid_sr(bcid_sr'high - 1 downto 0) & bcid; - if unsigned(bcid_sr(bcid_sr'high)) > unsigned(bcid_sr(bcid_sr'high - 1)) then - super_id <= super_id + 1; - end if; - end if; - end if; - end if; - end process pBufferHeader; - --==============================-- -- Debug --==============================-- - debug.data(31 downto 0) <= std_logic_vector(super_id); + debug.data(31 downto 0) <= payload_header(31 downto 0); debug.data(39 downto 32) <= output_data_count; debug.data(47 downto 40) <= "00" & input_data_count(0); debug.data(51 downto 48) <= std_logic_vector(to_unsigned(counter, 4)); @@ -387,7 +337,7 @@ begin debug.data(58) <= input_data_valid; debug.valid <= '1'; debug.strobe <= '1'; - debug_super_id <= std_logic_vector(super_id); + debug_super_id <= payload_header(31 downto 0); debug_fifo(7 downto 0) <= output_data_count; debug_fifo(8) <= output_full; debug_fifo(9) <= output_rd_en; diff --git a/common/firmware/hdl/LinkCombinerIPBus.vhd b/common/firmware/hdl/LinkCombinerIPBus.vhd index 4270a665761cea862179ce7abde47dfd9da80518..47ce10783312434bb69d77950bc6bf5868e5dc6f 100644 --- a/common/firmware/hdl/LinkCombinerIPBus.vhd +++ b/common/firmware/hdl/LinkCombinerIPBus.vhd @@ -6,11 +6,9 @@ use work.emp_data_types.all; use work.ipbus.all; use work.ipbus_reg_types.all; -use work.front_end_data_types.all; -use work.module_constants.all; use work.dtc_link_maps.all; -use work.dtc_data_types.all; use work.dtc_constants.all; +use work.dtc_data_types.all; entity LinkCombinerIPBus is @@ -23,7 +21,7 @@ entity LinkCombinerIPBus is reset : in std_logic; links_in : in ldata(N_INPUT_LINKS - 1 downto 0); packet_start : in std_logic; - header_in : in tCICHeaderArray(cNumberOfFEModules * cNumberOfCICs - 1 downto 0) := (others => ('0', (others => '0'), (others => '0'), (others => '0'))); + payload_header : in std_logic_vector(127 downto 0) := (others => '0'); lff : in std_logic; output_srst : in std_logic := '0'; --- Ouput Ports --- @@ -34,7 +32,8 @@ entity LinkCombinerIPBus is ipb_in : in ipb_wbus; ipb_out : out ipb_rbus; --- Debug Ports --- - super_id : out std_logic_vector(31 downto 0) + super_id : out std_logic_vector(31 downto 0); + debug_packet_size : out lword := LWORD_NULL ); end LinkCombinerIPBus; @@ -110,14 +109,13 @@ begin output_enable => link_combiner_rd_en, links_in => masked_input, packet_start => packet_start, - header_in => header_in, - header_user_bits => control_registers(1), + payload_header => payload_header, --- Output Ports --- link_out => link_out, --- Debug Ports --- -- debug => link_combiner_debug, - debug_super_id => super_id - -- debug_fifo => link_aggregator_status_registers(2) + debug_super_id => super_id, + debug_packet_size => debug_packet_size ); end Behavioral; diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd index c6b2ec042a243d8235e7458bd70f41335648d59d..6179cd1d4fb9e88d7ff29cdcccba9dc698d5fdf6 100644 --- a/common/firmware/hdl/MProcessor.vhd +++ b/common/firmware/hdl/MProcessor.vhd @@ -9,23 +9,22 @@ use work.ipbus_reg_types.all; use work.ipbus_decode_mprocessor.all; use work.dtc_link_maps.all; -use work.front_end_data_types.all; -use work.module_constants.all; use work.mprocessor_constants.all; -use work.dtc_data_types.all; use work.dtc_constants.all; +use work.dtc_data_types.all; entity MProcessor is generic ( - N_LINKS : integer + N_LINKS : integer; + INDEX : integer := 0 ); port ( --- Input Ports --- clk_p : in std_logic; links_in : in ldata(N_LINKS - 1 downto 0); - header_in : in tCICHeaderArray(cNumberOfFEModules * cNumberOfCICs - 1 downto 0) := (others => ('0', (others => '0'), (others => '0'), (others => '0'))); header_start_array : in tHeaderStartArray := (others => (others => '0')); + payload_header : in std_logic_vector(127 downto 0) := (others => '0'); gbe_backpressure : in std_logic := '0'; srst : in std_logic := '0'; --- Output Ports --- @@ -34,7 +33,9 @@ entity MProcessor is ipb_clk : in std_logic; ipb_rst : in std_logic; ipb_in : in ipb_wbus; - ipb_out : out ipb_rbus + ipb_out : out ipb_rbus; + --- Debug Ports --- + debug_readout_reset : out std_logic := '0' ); end MProcessor; @@ -49,11 +50,20 @@ architecture Behavorial of MProcessor is signal aggregated_stubs : ldata(7 downto 0) := (others => LWORD_NULL); signal link_aggregator_input : ldata(N_LINKS - 1 downto 0) := (others => LWORD_NULL); - signal status_registers : ipb_reg_v(2 - 1 downto 0) := (others => (others => '0')); - signal control_registers : ipb_reg_v(1 - 1 downto 0) := (others => (others => '0')); + signal status_registers : ipb_reg_v(4 - 1 downto 0) := (others => (others => '0')); + signal control_registers : ipb_reg_v(5 - 1 downto 0) := (others => (others => '0')); signal super_id : std_logic_vector(31 downto 0) := (others => '0'); + signal occupancy_trigger_window_lower : std_logic_vector(31 downto 0) := (others => '0'); + signal occupancy_trigger_window_upper : std_logic_vector(3 downto 0) := (others => '0'); + signal occupancy_trigger_window : std_logic_vector(36 - 1 downto 0) := X"0ffffffff"; + signal occupancy_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0'); + signal occupancy_histogram_reset : std_logic := '0'; + signal debug_packet_size : lword := LWORD_NULL; + + signal tracking_stubs : ldata(N_LINKS - 1 downto 0) := (others => LWORD_NULL); + begin --==============================-- @@ -80,8 +90,8 @@ begin MProcessorControlInstance: entity work.ipbus_ctrlreg_v --==============================-- generic map( - N_CTRL => 1, - N_STAT => 2 + N_CTRL => 5, + N_STAT => 4 ) port map( clk => ipb_clk, @@ -96,21 +106,23 @@ begin LinkAggregatorInstance: entity work.LinkAggregatorIPBus --==============================-- generic map ( - N_LINKS => N_LINKS + N_LINKS => N_LINKS, + INDEX => INDEX ) port map ( --- Input Ports --- - clk_p => clk_p, - packet_start => packet_start, - links_in => link_aggregator_input, + clk_p => clk_p, + packet_start => packet_start, + links_in => link_aggregator_input, --- Output Ports --- - links_out => aggregated_stubs, - readout_reset => readout_reset, + links_out => aggregated_stubs, + readout_reset => readout_reset, + tracking_stubs => tracking_stubs, --- IPBus Ports --- - ipb_clk => ipb_clk, - ipb_rst => ipb_rst, - ipb_in => ipb_to_slaves(N_SLV_LINK_AGGREGATOR), - ipb_out => ipb_from_slaves(N_SLV_LINK_AGGREGATOR) + ipb_clk => ipb_clk, + ipb_rst => ipb_rst, + ipb_in => ipb_to_slaves(N_SLV_LINK_AGGREGATOR), + ipb_out => ipb_from_slaves(N_SLV_LINK_AGGREGATOR) ); --==============================-- @@ -125,7 +137,7 @@ begin reset => readout_reset, links_in => aggregated_stubs, packet_start => packet_start, - header_in => header_in, + payload_header => payload_header, lff => gbe_backpressure, output_srst => srst, --- Output Ports --- @@ -136,7 +148,8 @@ begin ipb_in => ipb_to_slaves(N_SLV_LINK_COMBINER), ipb_out => ipb_from_slaves(N_SLV_LINK_COMBINER), --- Debug Ports --- - super_id => super_id + super_id => super_id, + debug_packet_size => debug_packet_size ); -- --==============================-- @@ -148,10 +161,67 @@ begin -- stubs_in => aggregated_stubs(0) -- ); + -- --==============================-- + -- TrackFinderInstance : entity work.TrackFinder + -- --==============================-- + -- port map ( + -- -- Input Ports -- + -- clk_p => clk_p, + -- stubs_in => tracking_stubs, + -- header_start => packet_start, + -- --- IPBus Ports --- + -- ipb_clk => ipb_clk, + -- ipb_rst => ipb_rst, + -- ipb_in => ipb_to_slaves(N_SLV_TRACK_FINDER), + -- ipb_out => ipb_from_slaves(N_SLV_TRACK_FINDER) + -- ); + link_aggregator_input(N_LINKS - 1 downto 0) <= links_in; status_registers(0)(0) <= gbe_backpressure; status_registers(1) <= super_id; packet_start <= header_start_array(to_integer(unsigned(control_registers(0)(2 downto 0))))(0); + debug_readout_reset <= readout_reset; + + + --==============================-- + PacketSizeHistogramInstance : entity work.IPBusHistogram + --==============================-- + generic map ( + input_width => 8, + bin_width => 32, + data_offset => 0 + ) + port map ( + --- Input Ports --- + clk_p => clk_p, + data_in => debug_packet_size, + histogram_reset => occupancy_histogram_reset, + --- Output Ports --- + max_bin_value => occupancy_max_value, + --- IPBus Ports --- + clk => ipb_clk, + rst => ipb_rst, + ipb_in => ipb_to_slaves(N_SLV_OCCUPANCY_MEM), + ipb_out => ipb_from_slaves(N_SLV_OCCUPANCY_MEM) + ); + + --==============================-- + OccupancyHistogramResetter : entity work.HistogramResetter + --==============================-- + port map ( + --- Input Ports --- + clk_p => clk_p, + trigger_window => occupancy_trigger_window, + --- Output Ports --- + histogram_reset => occupancy_histogram_reset + ); + + occupancy_trigger_window_lower <= control_registers(1); + occupancy_trigger_window_upper <= control_registers(2)(3 downto 0); + occupancy_trigger_window <= occupancy_trigger_window_upper & occupancy_trigger_window_lower; + + status_registers(2)(32 - 1 downto 0) <= occupancy_max_value; + end Behavorial; diff --git a/common/firmware/hdl/PayloadHeaderGenerator.vhd b/common/firmware/hdl/PayloadHeaderGenerator.vhd new file mode 100644 index 0000000000000000000000000000000000000000..e4af8cc9f97a382e25225e9f53233d2b6fe97ad0 --- /dev/null +++ b/common/firmware/hdl/PayloadHeaderGenerator.vhd @@ -0,0 +1,109 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; +use work.emp_data_types.all; +use work.dtc_link_maps.all; +use work.dtc_constants.all; +use work.dtc_data_types.all; +use IEEE.std_logic_misc.all; +use work.mprocessor_constants.all; + + +entity PayloadHeaderGenerator is + port ( + --- Input Ports --- + clk_p : in std_logic; + reset : in std_logic; + readout_reset : in std_logic; + header_start : in std_logic; + module_header_in : in tCICHeaderArray(cNumberOfFEModules * cNumberOfCICs - 1 downto 0) := (others => ('0', (others => '0'), (others => '0'), (others => '0'))); + user_bits : in std_logic_vector(31 downto 0); + --- Ouput Ports --- + header_out : out tPayloadHeaderArray := (others => (others => '0')); + --- Debug Ports --- + debug_super_id : out std_logic_vector(31 downto 0) := (others => '0') + ); +end PayloadHeaderGenerator; + +architecture Behavioral of PayloadHeaderGenerator is + + type tBCIDShiftRegister is array(1 downto 0) of std_logic_vector(12 - 1 downto 0); + type tInputDataCountArray is array(integer range <>) of std_logic_vector(5 downto 0); + + signal bcid_sr : tBCIDShiftRegister := (others => (others => '0')); + signal super_id : unsigned(32 - 1 downto 0) := (others => '0'); + + signal packet_stub_count, packet_stub_count_previous : unsigned(7 downto 0) := (others => '0'); + signal packet_stub_counter_pointer : integer := 0; + signal packet_stub_count_done : std_logic := '0'; + + signal header_word : std_logic_vector(127 downto 0) := (others => '0'); + +begin + + --==============================-- + pBufferHeader: process(clk_p) + --==============================-- + variable bcid : std_logic_vector(12 - 1 downto 0) := (others => '0'); + begin + if rising_edge(clk_p) then + if reset = '1' then + super_id <= (others => '0'); + header_word <= (others => '0'); + else + if header_start = '1' then + bcid := std_logic_vector(module_header_in(0).bcid); + bcid_sr <= bcid_sr(bcid_sr'high - 1 downto 0) & bcid; + if unsigned(bcid_sr(bcid_sr'high)) > unsigned(bcid_sr(bcid_sr'high - 1)) then + super_id <= super_id + 1; + end if; + end if; + + -- header_word <= (others => '0'); + header_word(31 downto 0) <= std_logic_vector(super_id); + header_word(63 downto 32) <= user_bits; + header_word(75 downto 64) <= bcid_sr(bcid_sr'high); + end if; + end if; + end process pBufferHeader; + + + --==============================-- + genOutput : for i in 0 to cNumberOfMProcessors - 1 generate + --==============================-- + + signal packet_stub_count, packet_stub_count_previous : unsigned(7 downto 0) := (others => '0'); + signal packet_stub_counter_pointer : integer := 0; + signal packet_stub_count_done : std_logic := '0'; + + begin + --==============================-- + pCountStubs : process(clk_p) + --==============================-- + begin + if rising_edge(clk_p) then + if readout_reset = '1' then + packet_stub_count <= (others => '0'); + packet_stub_count_previous <= packet_stub_count; + packet_stub_counter_pointer <= 0; + packet_stub_count_done <= '0'; + else + if packet_stub_count_done = '0' then + if packet_stub_counter_pointer = (6 - 1) * cNumberOfCICs then + packet_stub_count_done <= '1'; + end if; + packet_stub_count <= packet_stub_count + unsigned(module_header_in((6*i) + packet_stub_counter_pointer).stub_count) + unsigned(module_header_in((6*i) + packet_stub_counter_pointer + 1).stub_count); + packet_stub_counter_pointer <= packet_stub_counter_pointer + cNumberOfCICs; + end if; + end if; + + header_out(i)(75 downto 0 ) <= header_word(75 downto 0); + header_out(i)(83 downto 76) <= std_logic_vector(packet_stub_count_previous); + end if; + end process pCountStubs; + + end generate ; -- genOutput + + debug_super_id <= std_logic_vector(super_id); + +end Behavioral; diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd new file mode 100644 index 0000000000000000000000000000000000000000..36a7c9cffd926047842f2be80d329cded439226f --- /dev/null +++ b/common/firmware/hdl/TrackFinder.vhd @@ -0,0 +1,302 @@ +---------------------------------------------------------------------------------- +-- Company: +-- Engineer: +-- +-- Create Date: 09/09/2023 11:30:24 PM +-- Design Name: +-- Module Name: TrackFinder - Behavioral +-- Project Name: +-- Target Devices: +-- Tool Versions: +-- Description: +-- +-- Dependencies: +-- +-- Revision: +-- Revision 0.01 - File Created +-- Additional Comments: +-- +---------------------------------------------------------------------------------- + + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; +use IEEE.STD_LOGIC_MISC.ALL; + +use work.emp_data_types.all; +use work.tracking_constants.all; + +use work.ipbus.all; +use work.ipbus_reg_types.all; +use work.ipbus_decode_track_finder.all; + + +entity TrackFinder is + port ( + clk_p : in STD_LOGIC; + stubs_in : in ldata(5 downto 0) := (others => LWORD_NULL); + header_start : in std_logic; + --- IPBus Ports --- + ipb_clk : in std_logic; + ipb_rst : in std_logic; + ipb_in : in ipb_wbus; + ipb_out : out ipb_rbus + ); +end TrackFinder; + +architecture Behavioral of TrackFinder is + + signal ipb_to_slaves : ipb_wbus_array(N_SLAVES - 1 downto 0); + signal ipb_from_slaves : ipb_rbus_array(N_SLAVES - 1 downto 0); + + signal status_registers : ipb_reg_v(4 - 1 downto 0) := (others => (others => '0')); + signal control_registers : ipb_reg_v(2 - 1 downto 0) := (others => (others => '0')); + + signal stub_array : tDecodedStubArray := (others => cNullDecodedStub); + signal valid_event_array : std_logic_vector(5 downto 0); + signal valid_event : std_logic := '0'; + + signal counter : integer := 0; + signal track_delta_x : integer := 0; + signal track_delta_y : integer := 0; + + signal localx_histogram_input : lword := LWORD_NULL; + signal deltax_histogram_input : lword := LWORD_NULL; + signal localy_histogram_input : lword := LWORD_NULL; + signal deltay_histogram_input : lword := LWORD_NULL; + + signal localx_trigger_window_lower : std_logic_vector(31 downto 0) := (others => '0'); + signal localx_trigger_window_upper : std_logic_vector(3 downto 0) := (others => '0'); + signal localx_trigger_window : std_logic_vector(36 - 1 downto 0) := X"0ffffffff"; + signal localx_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0'); + signal localx_histogram_reset : std_logic := '0'; + + signal deltax_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0'); + signal localy_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0'); + signal deltay_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0'); + +begin + + --==============================-- + 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_track_finder(ipb_in.ipb_addr), + ipb_to_slaves => ipb_to_slaves, + ipb_from_slaves => ipb_from_slaves + ); + + --==============================-- + TrackFinderControlInstance: entity work.ipbus_ctrlreg_v + --==============================-- + generic map( + N_CTRL => 2, + N_STAT => 4 + ) + port map( + clk => ipb_clk, + reset => ipb_rst, + ipbus_in => ipb_to_slaves(N_SLV_CSR), + ipbus_out => ipb_from_slaves(N_SLV_CSR), + d => status_registers, + q => control_registers + ); + + --==============================-- + genValidEventArray: for i in 0 to 5 generate + --==============================-- + begin + valid_event_array(i) <= stubs_in(i).valid; + end generate; + + --==============================-- + pMain : process(clk_p) + --==============================-- + begin + if rising_edge(clk_p) then + if header_start = '1' then + valid_event <= and_reduce(valid_event_array); + for i in 0 to 5 loop + if stubs_in(i).valid = '1' then + stub_array(i) <= convertStubtoDecodedStub(convertSLVtoStub(stubs_in(i).data)); + end if; + end loop; + end if; + valid_event <= and_reduce(valid_event_array) and header_start; + + if valid_event = '1' then + track_delta_x <= stub_array(4).localx - stub_array(0).localx + 1; + end if; + if counter = 1 then + if (track_delta_x > -127) and (track_delta_x < 127) then + deltax_histogram_input.valid <= '1'; + deltax_histogram_input.data(7 downto 0) <= std_logic_vector(to_unsigned(track_delta_x + 128, 8)); + else + deltax_histogram_input <= LWORD_NULL; + end if; + else + deltax_histogram_input <= LWORD_NULL; + end if; + + if valid_event = '1' then + track_delta_y <= stub_array(5).localx - stub_array(1).localx + 1; + end if; + if counter = 1 then + if (track_delta_y > -127) and (track_delta_y < 127) then + deltay_histogram_input.valid <= '1'; + deltay_histogram_input.data(7 downto 0) <= std_logic_vector(to_unsigned(track_delta_y + 128, 8)); + else + deltay_histogram_input <= LWORD_NULL; + end if; + else + deltax_histogram_input <= LWORD_NULL; + end if; + + if valid_event = '1' then + localx_histogram_input.valid <= '1'; + localx_histogram_input.data(10 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 11)); + localy_histogram_input.valid <= '1'; + localy_histogram_input.data(10 downto 0) <= std_logic_vector(to_unsigned(stub_array(1).localx, 11)); + else + localx_histogram_input <= LWORD_NULL; + localy_histogram_input <= LWORD_NULL; + end if; + end if; + end process pMain; + + --==============================-- + pCounter : process(clk_p) + --==============================-- + begin + if rising_edge(clk_p) then + if header_start = '1' then + counter <= 0; + else + if valid_event = '1' then + counter <= 1; + else + if counter > 0 then + counter <= counter + 1; + end if; + end if; + end if; + end if; + end process pCounter; + + + --==============================-- + LocalXHistogramInstance : entity work.IPBusHistogram + --==============================-- + generic map ( + input_width => 8, + bin_width => 32, + data_offset => 3 + ) + port map ( + --- Input Ports --- + clk_p => clk_p, + data_in => localx_histogram_input, + histogram_reset => localx_histogram_reset, + --- Output Ports --- + max_bin_value => localx_max_value, + --- IPBus Ports --- + clk => ipb_clk, + rst => ipb_rst, + ipb_in => ipb_to_slaves(N_SLV_TRACKING_LOCALX_MEM), + ipb_out => ipb_from_slaves(N_SLV_TRACKING_LOCALX_MEM) + ); + + --==============================-- + LocalXHistogramResetter : entity work.HistogramResetter + --==============================-- + port map ( + --- Input Ports --- + clk_p => clk_p, + trigger_window => localx_trigger_window, + --- Output Ports --- + histogram_reset => localx_histogram_reset + ); + + --==============================-- + DeltaXHistogramInstance : entity work.IPBusHistogram + --==============================-- + generic map ( + input_width => 8, + bin_width => 32, + data_offset => 0 + ) + port map ( + --- Input Ports --- + clk_p => clk_p, + data_in => deltax_histogram_input, + histogram_reset => localx_histogram_reset, + --- Output Ports --- + max_bin_value => deltax_max_value, + --- IPBus Ports --- + clk => ipb_clk, + rst => ipb_rst, + ipb_in => ipb_to_slaves(N_SLV_TRACKING_DELTAX_MEM), + ipb_out => ipb_from_slaves(N_SLV_TRACKING_DELTAX_MEM) + ); + + --==============================-- + LocalYHistogramInstance : entity work.IPBusHistogram + --==============================-- + generic map ( + input_width => 8, + bin_width => 32, + data_offset => 3 + ) + port map ( + --- Input Ports --- + clk_p => clk_p, + data_in => localy_histogram_input, + histogram_reset => localx_histogram_reset, + --- Output Ports --- + max_bin_value => localy_max_value, + --- IPBus Ports --- + clk => ipb_clk, + rst => ipb_rst, + ipb_in => ipb_to_slaves(N_SLV_TRACKING_LOCALY_MEM), + ipb_out => ipb_from_slaves(N_SLV_TRACKING_LOCALY_MEM) + ); + + --==============================-- + DeltaYHistogramInstance : entity work.IPBusHistogram + --==============================-- + generic map ( + input_width => 8, + bin_width => 32, + data_offset => 0 + ) + port map ( + --- Input Ports --- + clk_p => clk_p, + data_in => deltay_histogram_input, + histogram_reset => localx_histogram_reset, + --- Output Ports --- + max_bin_value => deltay_max_value, + --- IPBus Ports --- + clk => ipb_clk, + rst => ipb_rst, + ipb_in => ipb_to_slaves(N_SLV_TRACKING_DELTAY_MEM), + ipb_out => ipb_from_slaves(N_SLV_TRACKING_DELTAY_MEM) + ); + + localx_trigger_window_lower <= control_registers(0); + localx_trigger_window_upper <= control_registers(1)(3 downto 0); + localx_trigger_window <= localx_trigger_window_upper & localx_trigger_window_lower; + + status_registers(0)(32 - 1 downto 0) <= localx_max_value; + status_registers(1)(32 - 1 downto 0) <= deltax_max_value; + status_registers(2)(32 - 1 downto 0) <= localy_max_value; + status_registers(3)(32 - 1 downto 0) <= deltay_max_value; + +end Behavioral; diff --git a/common/firmware/hdl/fixed_pkg_2008.vhd b/common/firmware/hdl/fixed_pkg_2008.vhd old mode 100755 new mode 100644 diff --git a/common/firmware/hdl/mprocessor_constants.vhd b/common/firmware/hdl/mprocessor_constants.vhd index 367eb0996372120aec21e2d4da72d9240ed3ce45..ca208d3f10371e20567bdf6273cacbfac1ead8d6 100644 --- a/common/firmware/hdl/mprocessor_constants.vhd +++ b/common/firmware/hdl/mprocessor_constants.vhd @@ -7,8 +7,17 @@ use work.dtc_link_maps.all; package mprocessor_constants is type tHeaderStartArray is array(cNumberOfFEModules - 1 downto 0) of std_logic_vector(1 downto 0); + type tPayloadHeaderArray is array(cNumberOfMProcessors - 1 downto 0) of std_logic_vector(127 downto 0); function convertSLVtoHeaderStartArray (input_vector : in std_logic_vector(2*cNumberOfFEModules - 1 downto 0)) return tHeaderStartArray; + + + constant cNumberOfEcalChannels : integer := 28; + + type tDaqEcalLinkData is array(integer range 0 to 6) of std_logic_vector(15 downto 0); + type tDaqEcalLinkDataArray is array(integer range 0 to 3) of tDaqEcalLinkData; + type tDaqEcalDataArray is array(integer range 0 to cNumberOfEcalChannels - 1) of std_logic_vector(15 downto 0); + end package mprocessor_constants; @@ -29,4 +38,4 @@ package body mprocessor_constants is end; -end package body mprocessor_constants; \ No newline at end of file +end package body mprocessor_constants; diff --git a/common/firmware/hdl/mprocessor_data_types.vhd b/common/firmware/hdl/mprocessor_data_types.vhd new file mode 100644 index 0000000000000000000000000000000000000000..b08d9986b5958e30583817e291261c22491c3398 --- /dev/null +++ b/common/firmware/hdl/mprocessor_data_types.vhd @@ -0,0 +1,15 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +package mprocessor_data_types is + +type tIntegerArray is array(0 to 5) of integer; + + +end package mprocessor_data_types; + + +package body mprocessor_data_types is + +end mprocessor_data_types; \ No newline at end of file diff --git a/common/firmware/hdl/tracking_constants.vhd b/common/firmware/hdl/tracking_constants.vhd new file mode 100644 index 0000000000000000000000000000000000000000..32964941729fbc89cee9afcb8f0701fbff3e68b9 --- /dev/null +++ b/common/firmware/hdl/tracking_constants.vhd @@ -0,0 +1,66 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +use work.emp_data_types.all; + +package tracking_constants is + + type tTrackStubs is array (0 to 5) of lword; + + type tStub is record + z : std_logic_vector(3 downto 0); + bend : std_logic_vector(3 downto 0); + address : std_logic_vector(7 downto 0); + cbc : std_logic_vector(2 downto 0); + cic : std_logic_vector(0 downto 0); + end record; + constant cNullStub : tStub := ((others => '0'), (others => '0'), (others => '0'), (others => '0'), (others => '0')); + type tStubArray is array(0 to 5) of tStub; + + function convertSLVtoStub(word_in : in std_logic_vector(63 downto 0)) return tStub; + + type tCICMappingArray is array (0 to 7) of integer; + constant cCICMapping : tCICMappingArray := (0, 1, 2, 3, 7, 6, 5, 4); + + + + type tDecodedStub is record + localx : integer; + localy : integer; + end record; + constant cNullDecodedStub : tDecodedStub := (0, 0); + type tDecodedStubArray is array(0 to 5) of tDecodedStub; + + function convertStubtoDecodedStub(stub_in: tStub) return tDecodedStub; + +end package tracking_constants; + + +package body tracking_constants is + + function convertSLVtoStub(word_in : in std_logic_vector(63 downto 0)) return tStub is + variable stub : tStub; + begin + stub.z := word_in(3 downto 0); + stub.bend := word_in(7 downto 4); + stub.address := word_in(15 downto 8); + stub.cbc := word_in(18 downto 16); + stub.cic := word_in(50 downto 50); + return stub; + end convertSLVtoStub; + + function convertStubtoDecodedStub(stub_in: tStub) return tDecodedStub is + variable decoded_stub : tDecodedStub; + begin + if stub_in.cic = "1" then + decoded_stub.localy := 1; + decoded_stub.localx := 2032 - to_integer(unsigned(stub_in.address)) - 254*cCICMapping(to_integer(unsigned(stub_in.cbc))) + 2; + else + decoded_stub.localy := 0; + decoded_stub.localx := to_integer(unsigned(stub_in.address)) + 254* cCICMapping(to_integer(unsigned(stub_in.cbc))); + end if; + return decoded_stub; + end convertStubtoDecodedStub; + +end tracking_constants; diff --git a/dependencies.yml b/dependencies.yml index 8d80ad91ecb806de048ee1205bb6532cd5d996a7..b192bbca8cc96bb8a5fa698d6523f29d085b4ec3 100644 --- a/dependencies.yml +++ b/dependencies.yml @@ -67,4 +67,3 @@ sources: daqpath-toolkit: branch: master url: https://gitlab.cern.ch/dmonk/daqpath-toolkit.git - diff --git a/ecal/addr_table/eprocessor.xml b/ecal/addr_table/eprocessor.xml new file mode 100644 index 0000000000000000000000000000000000000000..4d191f631397da2c66d8b283c9808306f43c53e8 --- /dev/null +++ b/ecal/addr_table/eprocessor.xml @@ -0,0 +1,19 @@ +<node description="EcalDataProcessor Control and Status" fwinfo="endpoint"> + <node id="DP" address="0x0" description="DataProcessor control and status" fwinfo="endpoint;width=1"> + <node id="ctrl" address="0x0" description="control registers"> + <node id="reset" mask="0x1" description="reset"/> + <node id="latency" mask="0x3fe" description="latency"/> + <node id="trig_lat_offset" mask="0x7fc00" description="trigger latency offset"/> + </node> + <node id="stat" address="0x1" description="status"> + <node id="latency" mask="0x1ff" description="latency"/> + <node id="trig_lat_offset" mask="0x3fe00" description="latency"/> + <node id="backpressure" mask="0x40000" description="backpressure"/> + </node> + </node> + <node id="dfilter" address="0x40" description="Data filter control and status" fwinfo="endpoint;width=6"> + <node id="bypass" address="0x0" mask="0x1" description="bypass zs filter logic"/> + <node id="bypass_prescale" address="0x0" mask="0x1fffe" description="bypass trigger prescale"/> + <node id="zs_sc" address="0x1" mode="block" size="32" description="zs filter registers"/> + </node> +</node> diff --git a/ecal/firmware/cfg/module.dep b/ecal/firmware/cfg/module.dep new file mode 100644 index 0000000000000000000000000000000000000000..ca4a547e6d515fcaf0f55dd973ff2f2d0d935c9e --- /dev/null +++ b/ecal/firmware/cfg/module.dep @@ -0,0 +1,19 @@ +src ecal_zsf_type_pckg.vhd + +src EcalLinkInterface.vhd +src EcalDataDecoder.vhd +src EcalDataProcessor.vhd +src EcalDataAggregator.vhd +src EcalDataFilter.vhd +src EcalZeroSuppressionFilter.vhd +src EcalDataMonitor.vhd + +src ipbus_decode_eprocessor.vhd + +addrtab -t eprocessor.xml + + +# IP Cores + +src --cd ../cgn ecal_data_ram.xci +src --cd ../cgn ecal_trig_ram.xci \ No newline at end of file diff --git a/ecal/firmware/cgn/ecal_data_ram.xci b/ecal/firmware/cgn/ecal_data_ram.xci new file mode 100644 index 0000000000000000000000000000000000000000..91e6aca69815bf8399b9cc269c2d8dfbdd29c9ff --- /dev/null +++ b/ecal/firmware/cgn/ecal_data_ram.xci @@ -0,0 +1,281 @@ +{ + "schema": "xilinx.com:schema:json_instance:1.0", + "ip_inst": { + "xci_name": "ecal_data_ram", + "component_reference": "xilinx.com:ip:blk_mem_gen:8.4", + "ip_revision": "5", + "gen_directory": "../../../../ecaltest.gen/sources_1/ip/ecal_data_ram", + "parameters": { + "component_parameters": { + "Component_Name": [ { "value": "ecal_data_ram", "resolve_type": "user", "usage": "all" } ], + "Interface_Type": [ { "value": "Native", "resolve_type": "user", "usage": "all" } ], + "AXI_Type": [ { "value": "AXI4_Full", "resolve_type": "user", "usage": "all" } ], + "AXI_Slave_Type": [ { "value": "Memory_Slave", "resolve_type": "user", "usage": "all" } ], + "Use_AXI_ID": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "AXI_ID_Width": [ { "value": "4", "resolve_type": "user", "format": "long", "enabled": false, "usage": "all" } ], + "Memory_Type": [ { "value": "Simple_Dual_Port_RAM", "value_src": "user", "resolve_type": "user", "usage": "all" } ], + "PRIM_type_to_Implement": [ { "value": "BRAM", "resolve_type": "user", "usage": "all" } ], + "Enable_32bit_Address": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "ecctype": [ { "value": "No_ECC", "resolve_type": "user", "usage": "all" } ], + "ECC": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "softecc": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "EN_SLEEP_PIN": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "EN_DEEPSLEEP_PIN": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "EN_SHUTDOWN_PIN": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "EN_ECC_PIPE": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "RD_ADDR_CHNG_A": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "RD_ADDR_CHNG_B": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Use_Error_Injection_Pins": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Error_Injection_Type": [ { "value": "Single_Bit_Error_Injection", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Use_Byte_Write_Enable": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Byte_Size": [ { "value": "9", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Algorithm": [ { "value": "Minimum_Area", "resolve_type": "user", "usage": "all" } ], + "Primitive": [ { "value": "8kx2", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Assume_Synchronous_Clk": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Write_Width_A": [ { "value": "67", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Write_Depth_A": [ { "value": "512", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Read_Width_A": [ { "value": "67", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Operating_Mode_A": [ { "value": "NO_CHANGE", "resolve_type": "user", "usage": "all" } ], + "Enable_A": [ { "value": "Use_ENA_Pin", "resolve_type": "user", "usage": "all" } ], + "Write_Width_B": [ { "value": "67", "resolve_type": "user", "usage": "all" } ], + "Read_Width_B": [ { "value": "67", "resolve_type": "user", "usage": "all" } ], + "Operating_Mode_B": [ { "value": "WRITE_FIRST", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Enable_B": [ { "value": "Use_ENB_Pin", "resolve_type": "user", "usage": "all" } ], + "Register_PortA_Output_of_Memory_Primitives": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Register_PortA_Output_of_Memory_Core": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Use_REGCEA_Pin": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Register_PortB_Output_of_Memory_Primitives": [ { "value": "true", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Register_PortB_Output_of_Memory_Core": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Use_REGCEB_Pin": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "register_porta_input_of_softecc": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "register_portb_output_of_softecc": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Pipeline_Stages": [ { "value": "0", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Load_Init_File": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Coe_File": [ { "value": "no_coe_file_loaded", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Fill_Remaining_Memory_Locations": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Remaining_Memory_Locations": [ { "value": "0", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Use_RSTA_Pin": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Reset_Memory_Latch_A": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Reset_Priority_A": [ { "value": "CE", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Output_Reset_Value_A": [ { "value": "0", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Use_RSTB_Pin": [ { "value": "false", "value_src": "user", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Reset_Memory_Latch_B": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Reset_Priority_B": [ { "value": "CE", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Output_Reset_Value_B": [ { "value": "0", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Reset_Type": [ { "value": "SYNC", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Additional_Inputs_for_Power_Estimation": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Port_A_Clock": [ { "value": "100", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Port_A_Write_Rate": [ { "value": "50", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Port_B_Clock": [ { "value": "100", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Port_B_Write_Rate": [ { "value": "0", "resolve_type": "user", "format": "long", "enabled": false, "usage": "all" } ], + "Port_A_Enable_Rate": [ { "value": "100", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Port_B_Enable_Rate": [ { "value": "100", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Collision_Warnings": [ { "value": "ALL", "resolve_type": "user", "usage": "all" } ], + "Disable_Collision_Warnings": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Disable_Out_of_Range_Warnings": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "use_bram_block": [ { "value": "Stand_Alone", "resolve_type": "user", "usage": "all" } ], + "MEM_FILE": [ { "value": "no_mem_loaded", "resolve_type": "user", "usage": "all" } ], + "CTRL_ECC_ALGO": [ { "value": "NONE", "resolve_type": "user", "usage": "all" } ], + "EN_SAFETY_CKT": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "READ_LATENCY_A": [ { "value": "1", "resolve_type": "user", "format": "long", "enabled": false, "usage": "all" } ], + "READ_LATENCY_B": [ { "value": "1", "resolve_type": "user", "format": "long", "enabled": false, "usage": "all" } ] + }, + "model_parameters": { + "C_FAMILY": [ { "value": "kintexuplus", "resolve_type": "generated", "usage": "all" } ], + "C_XDEVICEFAMILY": [ { "value": "kintexuplus", "resolve_type": "generated", "usage": "all" } ], + "C_ELABORATION_DIR": [ { "value": "./", "resolve_type": "generated", "usage": "all" } ], + "C_INTERFACE_TYPE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_AXI_TYPE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_AXI_SLAVE_TYPE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_BRAM_BLOCK": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_ENABLE_32BIT_ADDRESS": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_CTRL_ECC_ALGO": [ { "value": "NONE", "resolve_type": "generated", "usage": "all" } ], + "C_HAS_AXI_ID": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_AXI_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_MEM_TYPE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_BYTE_SIZE": [ { "value": "9", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_ALGORITHM": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_PRIM_TYPE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_LOAD_INIT_FILE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_INIT_FILE_NAME": [ { "value": "no_coe_file_loaded", "resolve_type": "generated", "usage": "all" } ], + "C_INIT_FILE": [ { "value": "ecal_data_ram.mem", "resolve_type": "generated", "usage": "all" } ], + "C_USE_DEFAULT_DATA": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_DEFAULT_DATA": [ { "value": "0", "resolve_type": "generated", "usage": "all" } ], + "C_HAS_RSTA": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_RST_PRIORITY_A": [ { "value": "CE", "resolve_type": "generated", "usage": "all" } ], + "C_RSTRAM_A": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_INITA_VAL": [ { "value": "0", "resolve_type": "generated", "usage": "all" } ], + "C_HAS_ENA": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_REGCEA": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_BYTE_WEA": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WEA_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WRITE_MODE_A": [ { "value": "NO_CHANGE", "resolve_type": "generated", "usage": "all" } ], + "C_WRITE_WIDTH_A": [ { "value": "67", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_WIDTH_A": [ { "value": "67", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WRITE_DEPTH_A": [ { "value": "512", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_DEPTH_A": [ { "value": "512", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_ADDRA_WIDTH": [ { "value": "9", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_RSTB": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_RST_PRIORITY_B": [ { "value": "CE", "resolve_type": "generated", "usage": "all" } ], + "C_RSTRAM_B": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_INITB_VAL": [ { "value": "0", "resolve_type": "generated", "usage": "all" } ], + "C_HAS_ENB": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_REGCEB": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_BYTE_WEB": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WEB_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WRITE_MODE_B": [ { "value": "WRITE_FIRST", "resolve_type": "generated", "usage": "all" } ], + "C_WRITE_WIDTH_B": [ { "value": "67", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_WIDTH_B": [ { "value": "67", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WRITE_DEPTH_B": [ { "value": "512", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_DEPTH_B": [ { "value": "512", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_ADDRB_WIDTH": [ { "value": "9", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_MEM_OUTPUT_REGS_A": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_MEM_OUTPUT_REGS_B": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_MUX_OUTPUT_REGS_A": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_MUX_OUTPUT_REGS_B": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_MUX_PIPELINE_STAGES": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_SOFTECC_INPUT_REGS_A": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_SOFTECC_OUTPUT_REGS_B": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_SOFTECC": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_ECC": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_ECC_PIPE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_LATENCY_A": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_LATENCY_B": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_INJECTERR": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_SIM_COLLISION_CHECK": [ { "value": "ALL", "resolve_type": "generated", "usage": "all" } ], + "C_COMMON_CLK": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_DISABLE_WARN_BHV_COLL": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_SLEEP_PIN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_URAM": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_RDADDRA_CHG": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_RDADDRB_CHG": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_DEEPSLEEP_PIN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_SHUTDOWN_PIN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_SAFETY_CKT": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_DISABLE_WARN_BHV_RANGE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_COUNT_36K_BRAM": [ { "value": "1", "resolve_type": "generated", "usage": "all" } ], + "C_COUNT_18K_BRAM": [ { "value": "0", "resolve_type": "generated", "usage": "all" } ], + "C_EST_POWER_SUMMARY": [ { "value": "Estimated Power for IP : 2.436194 mW", "resolve_type": "generated", "usage": "all" } ] + }, + "project_parameters": { + "ARCHITECTURE": [ { "value": "kintexuplus" } ], + "BASE_BOARD_PART": [ { "value": "" } ], + "BOARD_CONNECTIONS": [ { "value": "" } ], + "DEVICE": [ { "value": "xcku15p" } ], + "PACKAGE": [ { "value": "ffva1760" } ], + "PREFHDL": [ { "value": "VHDL" } ], + "SILICON_REVISION": [ { "value": "" } ], + "SIMULATOR_LANGUAGE": [ { "value": "MIXED" } ], + "SPEEDGRADE": [ { "value": "-2" } ], + "STATIC_POWER": [ { "value": "" } ], + "TEMPERATURE_GRADE": [ { "value": "E" } ], + "USE_RDI_CUSTOMIZATION": [ { "value": "TRUE" } ], + "USE_RDI_GENERATION": [ { "value": "TRUE" } ] + }, + "runtime_parameters": { + "IPCONTEXT": [ { "value": "IP_Flow" } ], + "IPREVISION": [ { "value": "5" } ], + "MANAGED": [ { "value": "TRUE" } ], + "OUTPUTDIR": [ { "value": "../../../../ecaltest.gen/sources_1/ip/ecal_data_ram" } ], + "SELECTEDSIMMODEL": [ { "value": "" } ], + "SHAREDDIR": [ { "value": "." } ], + "SWVERSION": [ { "value": "2022.2" } ], + "SYNTHESISFLOW": [ { "value": "OUT_OF_CONTEXT" } ] + } + }, + "boundary": { + "ports": { + "clka": [ { "direction": "in", "driver_value": "0" } ], + "ena": [ { "direction": "in", "driver_value": "0" } ], + "wea": [ { "direction": "in", "size_left": "0", "size_right": "0", "driver_value": "0" } ], + "addra": [ { "direction": "in", "size_left": "8", "size_right": "0", "driver_value": "0" } ], + "dina": [ { "direction": "in", "size_left": "66", "size_right": "0", "driver_value": "0" } ], + "clkb": [ { "direction": "in", "driver_value": "0" } ], + "enb": [ { "direction": "in", "driver_value": "0" } ], + "addrb": [ { "direction": "in", "size_left": "8", "size_right": "0", "driver_value": "0" } ], + "doutb": [ { "direction": "out", "size_left": "66", "size_right": "0" } ] + }, + "interfaces": { + "CLK.ACLK": { + "vlnv": "xilinx.com:signal:clock:1.0", + "abstraction_type": "xilinx.com:signal:clock_rtl:1.0", + "mode": "slave", + "parameters": { + "ASSOCIATED_BUSIF": [ { "value": "AXI_SLAVE_S_AXI:AXILite_SLAVE_S_AXI", "value_src": "constant", "usage": "all" } ], + "ASSOCIATED_RESET": [ { "value": "s_aresetn", "value_src": "constant", "usage": "all" } ], + "FREQ_HZ": [ { "value": "100000000", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "PHASE": [ { "value": "0.0", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ], + "CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "RST.ARESETN": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "BRAM_PORTA": { + "vlnv": "xilinx.com:interface:bram:1.0", + "abstraction_type": "xilinx.com:interface:bram_rtl:1.0", + "mode": "slave", + "parameters": { + "MEM_SIZE": [ { "value": "8192", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "MEM_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "MEM_ECC": [ { "value": "NONE", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "MASTER_TYPE": [ { "value": "OTHER", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "READ_WRITE_MODE": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "READ_LATENCY": [ { "value": "1", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ] + }, + "port_maps": { + "ADDR": [ { "physical_name": "addra" } ], + "CLK": [ { "physical_name": "clka" } ], + "DIN": [ { "physical_name": "dina" } ], + "EN": [ { "physical_name": "ena" } ], + "WE": [ { "physical_name": "wea" } ] + } + }, + "BRAM_PORTB": { + "vlnv": "xilinx.com:interface:bram:1.0", + "abstraction_type": "xilinx.com:interface:bram_rtl:1.0", + "mode": "slave", + "parameters": { + "MEM_SIZE": [ { "value": "8192", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "MEM_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "MEM_ECC": [ { "value": "NONE", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "MASTER_TYPE": [ { "value": "OTHER", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "READ_WRITE_MODE": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "READ_LATENCY": [ { "value": "1", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ] + }, + "port_maps": { + "ADDR": [ { "physical_name": "addrb" } ], + "CLK": [ { "physical_name": "clkb" } ], + "DOUT": [ { "physical_name": "doutb" } ], + "EN": [ { "physical_name": "enb" } ] + } + } + }, + "memory_maps": { + "S_1": { + "address_blocks": { + "Mem0": { + "base_address": "0", + "range": "4096", + "usage": "memory", + "access": "read-write", + "parameters": { + "OFFSET_BASE_PARAM": [ { "value": "C_BASEADDR" } ], + "OFFSET_HIGH_PARAM": [ { "value": "C_HIGHADDR" } ] + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/ecal/firmware/cgn/ecal_trig_ram.xci b/ecal/firmware/cgn/ecal_trig_ram.xci new file mode 100644 index 0000000000000000000000000000000000000000..efccb8257bc93f9ee2340ca0133325a53ac80396 --- /dev/null +++ b/ecal/firmware/cgn/ecal_trig_ram.xci @@ -0,0 +1,281 @@ +{ + "schema": "xilinx.com:schema:json_instance:1.0", + "ip_inst": { + "xci_name": "ecal_trig_ram", + "component_reference": "xilinx.com:ip:blk_mem_gen:8.4", + "ip_revision": "5", + "gen_directory": "../../../../ecaltest.gen/sources_1/ip/ecal_trig_ram_1", + "parameters": { + "component_parameters": { + "Component_Name": [ { "value": "ecal_trig_ram", "resolve_type": "user", "usage": "all" } ], + "Interface_Type": [ { "value": "Native", "resolve_type": "user", "usage": "all" } ], + "AXI_Type": [ { "value": "AXI4_Full", "resolve_type": "user", "usage": "all" } ], + "AXI_Slave_Type": [ { "value": "Memory_Slave", "resolve_type": "user", "usage": "all" } ], + "Use_AXI_ID": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "AXI_ID_Width": [ { "value": "4", "resolve_type": "user", "format": "long", "enabled": false, "usage": "all" } ], + "Memory_Type": [ { "value": "Simple_Dual_Port_RAM", "value_src": "user", "resolve_type": "user", "usage": "all" } ], + "PRIM_type_to_Implement": [ { "value": "BRAM", "resolve_type": "user", "usage": "all" } ], + "Enable_32bit_Address": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "ecctype": [ { "value": "No_ECC", "resolve_type": "user", "usage": "all" } ], + "ECC": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "softecc": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "EN_SLEEP_PIN": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "EN_DEEPSLEEP_PIN": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "EN_SHUTDOWN_PIN": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "EN_ECC_PIPE": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "RD_ADDR_CHNG_A": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "RD_ADDR_CHNG_B": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Use_Error_Injection_Pins": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Error_Injection_Type": [ { "value": "Single_Bit_Error_Injection", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Use_Byte_Write_Enable": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Byte_Size": [ { "value": "9", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Algorithm": [ { "value": "Minimum_Area", "resolve_type": "user", "usage": "all" } ], + "Primitive": [ { "value": "8kx2", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Assume_Synchronous_Clk": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Write_Width_A": [ { "value": "32", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Write_Depth_A": [ { "value": "64", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Read_Width_A": [ { "value": "32", "value_src": "user", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Operating_Mode_A": [ { "value": "NO_CHANGE", "value_src": "user", "resolve_type": "user", "usage": "all" } ], + "Enable_A": [ { "value": "Use_ENA_Pin", "resolve_type": "user", "usage": "all" } ], + "Write_Width_B": [ { "value": "32", "value_src": "user", "resolve_type": "user", "usage": "all" } ], + "Read_Width_B": [ { "value": "32", "value_src": "user", "resolve_type": "user", "usage": "all" } ], + "Operating_Mode_B": [ { "value": "WRITE_FIRST", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Enable_B": [ { "value": "Use_ENB_Pin", "value_src": "user", "resolve_type": "user", "usage": "all" } ], + "Register_PortA_Output_of_Memory_Primitives": [ { "value": "false", "value_src": "user", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Register_PortA_Output_of_Memory_Core": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Use_REGCEA_Pin": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Register_PortB_Output_of_Memory_Primitives": [ { "value": "true", "value_src": "user", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Register_PortB_Output_of_Memory_Core": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Use_REGCEB_Pin": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "register_porta_input_of_softecc": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "register_portb_output_of_softecc": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Pipeline_Stages": [ { "value": "0", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Load_Init_File": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Coe_File": [ { "value": "no_coe_file_loaded", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Fill_Remaining_Memory_Locations": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Remaining_Memory_Locations": [ { "value": "0", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Use_RSTA_Pin": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Reset_Memory_Latch_A": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Reset_Priority_A": [ { "value": "CE", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Output_Reset_Value_A": [ { "value": "0", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Use_RSTB_Pin": [ { "value": "false", "value_src": "user", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Reset_Memory_Latch_B": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "Reset_Priority_B": [ { "value": "CE", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Output_Reset_Value_B": [ { "value": "0", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Reset_Type": [ { "value": "SYNC", "resolve_type": "user", "enabled": false, "usage": "all" } ], + "Additional_Inputs_for_Power_Estimation": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Port_A_Clock": [ { "value": "100", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Port_A_Write_Rate": [ { "value": "50", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Port_B_Clock": [ { "value": "100", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Port_B_Write_Rate": [ { "value": "0", "resolve_type": "user", "format": "long", "enabled": false, "usage": "all" } ], + "Port_A_Enable_Rate": [ { "value": "100", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Port_B_Enable_Rate": [ { "value": "100", "value_src": "user", "resolve_type": "user", "format": "long", "usage": "all" } ], + "Collision_Warnings": [ { "value": "ALL", "resolve_type": "user", "usage": "all" } ], + "Disable_Collision_Warnings": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "Disable_Out_of_Range_Warnings": [ { "value": "false", "resolve_type": "user", "format": "bool", "usage": "all" } ], + "use_bram_block": [ { "value": "Stand_Alone", "resolve_type": "user", "usage": "all" } ], + "MEM_FILE": [ { "value": "no_mem_loaded", "resolve_type": "user", "usage": "all" } ], + "CTRL_ECC_ALGO": [ { "value": "NONE", "resolve_type": "user", "usage": "all" } ], + "EN_SAFETY_CKT": [ { "value": "false", "resolve_type": "user", "format": "bool", "enabled": false, "usage": "all" } ], + "READ_LATENCY_A": [ { "value": "1", "resolve_type": "user", "format": "long", "enabled": false, "usage": "all" } ], + "READ_LATENCY_B": [ { "value": "1", "resolve_type": "user", "format": "long", "enabled": false, "usage": "all" } ] + }, + "model_parameters": { + "C_FAMILY": [ { "value": "kintexuplus", "resolve_type": "generated", "usage": "all" } ], + "C_XDEVICEFAMILY": [ { "value": "kintexuplus", "resolve_type": "generated", "usage": "all" } ], + "C_ELABORATION_DIR": [ { "value": "./", "resolve_type": "generated", "usage": "all" } ], + "C_INTERFACE_TYPE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_AXI_TYPE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_AXI_SLAVE_TYPE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_BRAM_BLOCK": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_ENABLE_32BIT_ADDRESS": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_CTRL_ECC_ALGO": [ { "value": "NONE", "resolve_type": "generated", "usage": "all" } ], + "C_HAS_AXI_ID": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_AXI_ID_WIDTH": [ { "value": "4", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_MEM_TYPE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_BYTE_SIZE": [ { "value": "9", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_ALGORITHM": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_PRIM_TYPE": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_LOAD_INIT_FILE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_INIT_FILE_NAME": [ { "value": "no_coe_file_loaded", "resolve_type": "generated", "usage": "all" } ], + "C_INIT_FILE": [ { "value": "ecal_trig_ram.mem", "resolve_type": "generated", "usage": "all" } ], + "C_USE_DEFAULT_DATA": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_DEFAULT_DATA": [ { "value": "0", "resolve_type": "generated", "usage": "all" } ], + "C_HAS_RSTA": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_RST_PRIORITY_A": [ { "value": "CE", "resolve_type": "generated", "usage": "all" } ], + "C_RSTRAM_A": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_INITA_VAL": [ { "value": "0", "resolve_type": "generated", "usage": "all" } ], + "C_HAS_ENA": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_REGCEA": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_BYTE_WEA": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WEA_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WRITE_MODE_A": [ { "value": "NO_CHANGE", "resolve_type": "generated", "usage": "all" } ], + "C_WRITE_WIDTH_A": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_WIDTH_A": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WRITE_DEPTH_A": [ { "value": "64", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_DEPTH_A": [ { "value": "64", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_ADDRA_WIDTH": [ { "value": "6", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_RSTB": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_RST_PRIORITY_B": [ { "value": "CE", "resolve_type": "generated", "usage": "all" } ], + "C_RSTRAM_B": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_INITB_VAL": [ { "value": "0", "resolve_type": "generated", "usage": "all" } ], + "C_HAS_ENB": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_REGCEB": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_BYTE_WEB": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WEB_WIDTH": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WRITE_MODE_B": [ { "value": "WRITE_FIRST", "resolve_type": "generated", "usage": "all" } ], + "C_WRITE_WIDTH_B": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_WIDTH_B": [ { "value": "32", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_WRITE_DEPTH_B": [ { "value": "64", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_DEPTH_B": [ { "value": "64", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_ADDRB_WIDTH": [ { "value": "6", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_MEM_OUTPUT_REGS_A": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_MEM_OUTPUT_REGS_B": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_MUX_OUTPUT_REGS_A": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_MUX_OUTPUT_REGS_B": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_MUX_PIPELINE_STAGES": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_SOFTECC_INPUT_REGS_A": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_SOFTECC_OUTPUT_REGS_B": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_SOFTECC": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_ECC": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_ECC_PIPE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_LATENCY_A": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_READ_LATENCY_B": [ { "value": "1", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_HAS_INJECTERR": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_SIM_COLLISION_CHECK": [ { "value": "ALL", "resolve_type": "generated", "usage": "all" } ], + "C_COMMON_CLK": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_DISABLE_WARN_BHV_COLL": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_SLEEP_PIN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_USE_URAM": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_RDADDRA_CHG": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_RDADDRB_CHG": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_DEEPSLEEP_PIN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_SHUTDOWN_PIN": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_EN_SAFETY_CKT": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_DISABLE_WARN_BHV_RANGE": [ { "value": "0", "resolve_type": "generated", "format": "long", "usage": "all" } ], + "C_COUNT_36K_BRAM": [ { "value": "0", "resolve_type": "generated", "usage": "all" } ], + "C_COUNT_18K_BRAM": [ { "value": "1", "resolve_type": "generated", "usage": "all" } ], + "C_EST_POWER_SUMMARY": [ { "value": "Estimated Power for IP : 1.375111 mW", "resolve_type": "generated", "usage": "all" } ] + }, + "project_parameters": { + "ARCHITECTURE": [ { "value": "kintexuplus" } ], + "BASE_BOARD_PART": [ { "value": "" } ], + "BOARD_CONNECTIONS": [ { "value": "" } ], + "DEVICE": [ { "value": "xcku15p" } ], + "PACKAGE": [ { "value": "ffva1760" } ], + "PREFHDL": [ { "value": "VHDL" } ], + "SILICON_REVISION": [ { "value": "" } ], + "SIMULATOR_LANGUAGE": [ { "value": "MIXED" } ], + "SPEEDGRADE": [ { "value": "-2" } ], + "STATIC_POWER": [ { "value": "" } ], + "TEMPERATURE_GRADE": [ { "value": "E" } ], + "USE_RDI_CUSTOMIZATION": [ { "value": "TRUE" } ], + "USE_RDI_GENERATION": [ { "value": "TRUE" } ] + }, + "runtime_parameters": { + "IPCONTEXT": [ { "value": "IP_Flow" } ], + "IPREVISION": [ { "value": "5" } ], + "MANAGED": [ { "value": "TRUE" } ], + "OUTPUTDIR": [ { "value": "../../../../ecaltest.gen/sources_1/ip/ecal_trig_ram_1" } ], + "SELECTEDSIMMODEL": [ { "value": "" } ], + "SHAREDDIR": [ { "value": "." } ], + "SWVERSION": [ { "value": "2022.2" } ], + "SYNTHESISFLOW": [ { "value": "OUT_OF_CONTEXT" } ] + } + }, + "boundary": { + "ports": { + "clka": [ { "direction": "in", "driver_value": "0" } ], + "ena": [ { "direction": "in", "driver_value": "0" } ], + "wea": [ { "direction": "in", "size_left": "0", "size_right": "0", "driver_value": "0" } ], + "addra": [ { "direction": "in", "size_left": "5", "size_right": "0", "driver_value": "0" } ], + "dina": [ { "direction": "in", "size_left": "31", "size_right": "0", "driver_value": "0" } ], + "clkb": [ { "direction": "in", "driver_value": "0" } ], + "enb": [ { "direction": "in", "driver_value": "0" } ], + "addrb": [ { "direction": "in", "size_left": "5", "size_right": "0", "driver_value": "0" } ], + "doutb": [ { "direction": "out", "size_left": "31", "size_right": "0" } ] + }, + "interfaces": { + "CLK.ACLK": { + "vlnv": "xilinx.com:signal:clock:1.0", + "abstraction_type": "xilinx.com:signal:clock_rtl:1.0", + "mode": "slave", + "parameters": { + "ASSOCIATED_BUSIF": [ { "value": "AXI_SLAVE_S_AXI:AXILite_SLAVE_S_AXI", "value_src": "constant", "usage": "all" } ], + "ASSOCIATED_RESET": [ { "value": "s_aresetn", "value_src": "constant", "usage": "all" } ], + "FREQ_HZ": [ { "value": "100000000", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "FREQ_TOLERANCE_HZ": [ { "value": "0", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "PHASE": [ { "value": "0.0", "resolve_type": "generated", "format": "float", "is_ips_inferred": true, "is_static_object": false } ], + "CLK_DOMAIN": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "ASSOCIATED_PORT": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "RST.ARESETN": { + "vlnv": "xilinx.com:signal:reset:1.0", + "abstraction_type": "xilinx.com:signal:reset_rtl:1.0", + "mode": "slave", + "parameters": { + "POLARITY": [ { "value": "ACTIVE_LOW", "value_src": "constant", "usage": "all" } ], + "INSERT_VIP": [ { "value": "0", "resolve_type": "user", "format": "long", "usage": "simulation.rtl", "is_ips_inferred": true, "is_static_object": false } ] + } + }, + "BRAM_PORTA": { + "vlnv": "xilinx.com:interface:bram:1.0", + "abstraction_type": "xilinx.com:interface:bram_rtl:1.0", + "mode": "slave", + "parameters": { + "MEM_SIZE": [ { "value": "8192", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "MEM_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "MEM_ECC": [ { "value": "NONE", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "MASTER_TYPE": [ { "value": "OTHER", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "READ_WRITE_MODE": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "READ_LATENCY": [ { "value": "1", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ] + }, + "port_maps": { + "ADDR": [ { "physical_name": "addra" } ], + "CLK": [ { "physical_name": "clka" } ], + "DIN": [ { "physical_name": "dina" } ], + "EN": [ { "physical_name": "ena" } ], + "WE": [ { "physical_name": "wea" } ] + } + }, + "BRAM_PORTB": { + "vlnv": "xilinx.com:interface:bram:1.0", + "abstraction_type": "xilinx.com:interface:bram_rtl:1.0", + "mode": "slave", + "parameters": { + "MEM_SIZE": [ { "value": "8192", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "MEM_WIDTH": [ { "value": "32", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ], + "MEM_ECC": [ { "value": "NONE", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "MASTER_TYPE": [ { "value": "OTHER", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "READ_WRITE_MODE": [ { "value": "", "resolve_type": "generated", "is_ips_inferred": true, "is_static_object": false } ], + "READ_LATENCY": [ { "value": "1", "resolve_type": "generated", "format": "long", "is_ips_inferred": true, "is_static_object": false } ] + }, + "port_maps": { + "ADDR": [ { "physical_name": "addrb" } ], + "CLK": [ { "physical_name": "clkb" } ], + "DOUT": [ { "physical_name": "doutb" } ], + "EN": [ { "physical_name": "enb" } ] + } + } + }, + "memory_maps": { + "S_1": { + "address_blocks": { + "Mem0": { + "base_address": "0", + "range": "4096", + "usage": "memory", + "access": "read-write", + "parameters": { + "OFFSET_BASE_PARAM": [ { "value": "C_BASEADDR" } ], + "OFFSET_HIGH_PARAM": [ { "value": "C_HIGHADDR" } ] + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/ecal/firmware/hdl/EcalDataAggregator.vhd b/ecal/firmware/hdl/EcalDataAggregator.vhd new file mode 100644 index 0000000000000000000000000000000000000000..a6c216db82cadbfec940be2567c58f856d710679 --- /dev/null +++ b/ecal/firmware/hdl/EcalDataAggregator.vhd @@ -0,0 +1,116 @@ +------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +use work.emp_data_types.all; +use work.mprocessor_constants.all; + + +entity EcalDataAggregator is +port ( + --- Input Ports --- + clk_p : in std_logic; + data_in : in tDaqEcalLinkDataArray; + --- Output Ports --- + data_out_start : out std_logic; -- '1' for one clock when the data_out is valid and updated. (should be 'start'?) + data_out_last : out std_logic; + data_out : out std_logic_vector(28 * 16 -1 downto 0) +); +end EcalDataAggregator; + +architecture rtl of EcalDataAggregator is + + signal ecal_data : std_logic_vector(28 * 16 -1 downto 0); + alias padding is ecal_data(ecal_data'high downto ecal_data'high-2); + alias bcid is ecal_data(ecal_data'high-4 downto ecal_data'high-4-11); + + signal ecal_data_p : std_logic_vector(28 * 16 -1 downto 0); + alias padding_p is ecal_data(ecal_data'high downto ecal_data'high-2); + + signal data_out_s : std_logic_vector(28 * 16 -1 downto 0) := (others => '0'); + signal data_out_s_start : std_logic := '0'; + signal data_out_s_last : std_logic := '0'; + + signal sync : std_logic := '0'; + + type tBcIdPipe is array (integer range 0 to 8) of std_logic_vector(11 downto 0); + signal bcid_p : tBcIdPipe; + signal last_valid_bcid : std_logic_vector(11 downto 0); + +begin + + EclDataFormatter : for i in 0 to 3 generate + type tEclLinkToGroupIndexArray is array (integer range 0 to 3) of integer; + constant ecal_link_to_group_indices : tEclLinkToGroupIndexArray := (1,0,2,3); + begin + + -- rearanging data + ch : for j in 0 to 6 generate + signal chid : integer range 0 to 27; + begin + + chid <= i+j*4; + ecal_data((chid+1)*16-1 downto chid *16) <= data_in(ecal_link_to_group_indices(i))(j); + + end generate ch; + + end generate EclDataFormatter; + + + data_check: process(clk_p) + variable timer : integer range 0 to 7 := 0; + begin + + if rising_edge(clk_p) then + + -- ecal_data pipeline + ecal_data_p <= ecal_data; + bcid_p(0) <= bcid; + for i in 0 to 7 loop + bcid_p(i+1) <= bcid_p(i); + end loop; + + -- data_out pipeline + data_out <= data_out_s; + data_out_start <= data_out_s_start; + data_out_last <= data_out_s_last; + + -- capturing frames + data_out_s_start <= '0'; + data_out_s_last <= '0'; + if sync = '0' then + if padding_p = "111" and (unsigned(bcid_p(0)) = unsigned(bcid_p(8)) + 1 or (unsigned(bcid_p(0)) = 0 and unsigned(bcid_p(8)) = 3563) ) then + timer := 0; + data_out_s <= ecal_data_p; + data_out_s_start <= '1'; + last_valid_bcid <= bcid_p(0); + sync <= '1'; + elsif timer = 7 then + timer := 0; + else + timer := timer + 1; + end if; + else + if timer = 7 then + timer := 0; + if padding_p = "111" and (unsigned(bcid_p(0)) = unsigned(bcid_p(8)) + 1 or (unsigned(bcid_p(0)) = 0 and unsigned(bcid_p(8)) = 3563) ) then + data_out_s <= ecal_data_p; + data_out_s_start <= '1'; + last_valid_bcid <= bcid_p(0); + else + sync <= '0'; + end if; + else + timer := timer + 1; + if timer = 7 then + data_out_s_last <= '1'; + end if; + end if; + end if; + + end if; + end process; + +end rtl; + diff --git a/ecal/firmware/hdl/EcalDataDecoder.vhd b/ecal/firmware/hdl/EcalDataDecoder.vhd new file mode 100644 index 0000000000000000000000000000000000000000..680001ec716ad430c0d29af85123e9faaf20cd1b --- /dev/null +++ b/ecal/firmware/hdl/EcalDataDecoder.vhd @@ -0,0 +1,56 @@ +------------------------------------------------------------- +-- tDaqEcalLinkData : type tDaqEcalLinkData is array(integer range 0 to 6) of std_logic_vector(15 downto 0); +-- contains 7 of 16-bit ecal channel data +------------------------------------------------------------- +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; + +use work.emp_data_types.all; +use work.mprocessor_constants.all; + +entity EcalDataDecoder is +port ( + --- Input Ports --- + clk_p : in std_logic; + data_in : in lword := LWORD_NULL; + --- Output Ports --- + ecal_out : out tDaqEcalLinkData +); +end EcalDataDecoder; + +architecture rtl of EcalDataDecoder is + + type tElinkDataArray is array(integer range 0 to 13) of std_logic_vector(7 downto 0); + constant ElinkDataArray_NULL : tElinkDataArray := (others => (others => '0')); + + signal elink_data : tElinkDataArray := ElinkDataArray_NULL; + + type elink_to_lword_type is array(integer range 0 to 13) of integer; + constant elink_to_lword : elink_to_lword_type := (3,2,1,6,0,4,5,32+3,32+2,32+1,32+6,32+0,32+4,32+5); + +begin + + decoder: process (clk_p) + + begin + if rising_edge(clk_p) then + + for i in 0 to 13 loop + elink_data(i) <= elink_data(i)(6 downto 0) & data_in.data(elink_to_lword(i)); + end loop; + + end if; + +end process decoder; + +--==============================-- +LinkEcalDataFormatter : for i in 0 to 6 generate +--==============================-- + + ecal_out(i) <= elink_data(i+7) & elink_data(i); + +end generate LinkEcalDataFormatter; + +end rtl; + diff --git a/ecal/firmware/hdl/EcalDataFilter.vhd b/ecal/firmware/hdl/EcalDataFilter.vhd new file mode 100644 index 0000000000000000000000000000000000000000..12471a16407150ca98fecb2c521489904bd581ff --- /dev/null +++ b/ecal/firmware/hdl/EcalDataFilter.vhd @@ -0,0 +1,156 @@ +------------------------------------------------------------- +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.emp_data_types.all; +use work.mprocessor_constants.all; +use work.ecal_zsf_type_pckg.all; + + +entity EcalDataFilter is +port ( + --- Input Ports --- + clk_p : in std_logic; + clk40 : in std_logic; + reset : in std_logic; + data_in_start : in std_logic; + data_in : in std_logic_vector(28 * 16 -1 downto 0); + --- Output Ports --- + trig_o_lat : out std_logic_vector(5 downto 0); + trig_o : out std_logic_vector(31 downto 0); -- bit31 : start, bit30 : last, bit27-1 : all_valids, bit0 : valid + --- IPBus Ports --- + ipb_clk : in std_logic; + ipb_rst : in std_logic; + ipb_in : in ipb_wbus; + ipb_out : out ipb_rbus +); +end EcalDataFilter; + +architecture rtl of EcalDataFilter is + + + signal regs : ipb_reg_v(32 downto 0) := (others => (others => '0')); + + signal bypass_s : std_logic; + signal bypass_prescale_s : std_logic_vector(15 downto 0); + signal b_trg : std_logic; + signal b_counter : std_logic_vector(15 downto 0); + + signal data_s : std_logic_vector(28 * 16 -1 downto 0); + + signal trig_meta : std_logic_vector(31 downto 0); + signal trig_sync : std_logic_vector(31 downto 0); + + signal zs_sc_regs : array_32bit(0 to 31); + signal zs_valid : std_logic; + signal zs_all_valids : std_logic_vector(26 downto 0); + signal zs_valid_lat : std_logic_vector(5 downto 0); + + + + signal trig40 : std_logic_vector(31 downto 0); + signal zs_valid_p : std_logic_vector(1 downto 0); + signal zs_all_valids_p0 : std_logic_vector(26 downto 0); + signal zs_all_valids_p1 : std_logic_vector(26 downto 0); +begin + + + --==============================-- + ctrl_reg: entity work.ipbus_reg_v + --==============================-- + generic map( + N_REG => 33 + ) + port map( + clk => ipb_clk, + reset => ipb_rst, + ipbus_in => ipb_in, + ipbus_out => ipb_out, + q => regs, + qmask => (others => (others => '1')), + stb => open + ); + + bypass_s <= regs(0)(0); + bypass_prescale_s <= regs(0)(16 downto 1); + zs_sc_regs_gen : for i in 0 to 31 generate + zs_sc_regs(i) <= regs(i+1); + end generate; + + trig_o_lat <= zs_valid_lat when bypass_s = '0' else "000011"; + trig_o <= trig40 when bypass_s = '0' else b_trg & b_trg & "00" & x"000000" & "000" & b_trg; + + -- trig_o <= trig_sync when bypass_s = '0' else x"c0000001"; + + --data_in_proc : process(clk_p) + -- variable timer : integer range 0 to 7 := 0; + --begin + -- if rising_edge(clk_p) then + + -- if data_in_start = '1' then + -- timer := 0; + -- elsif timer = 3 then + -- data_s <= data_in; + -- end if; + + -- if timer < 7 then + -- timer := timer + 1; + -- else + -- timer := 0; + -- end if; + + -- end if; + --end process; + + --trig_meta <= trig40 when rising_edge(clk_p); + --trig_sync <= trig_meta when rising_edge(clk_p); + + trig40_proc : process(clk40) + begin + if reset = '1' then + trig40 <= (others => '0'); + b_counter <= (others => '0'); + elsif rising_edge(clk40) then + + data_s <= data_in; + + b_counter <= std_logic_vector(unsigned(b_counter) + 1); + b_trg <= '0'; + if b_counter = std_logic_vector(unsigned(bypass_prescale_s) - 1) then + b_trg <= '1'; + b_counter <= (others => '0'); + end if; + + zs_valid_p(0) <= zs_valid; + zs_valid_p(1) <= zs_valid_p(0); + zs_all_valids_p0 <= zs_all_valids; + zs_all_valids_p1 <= zs_all_valids_p0; + trig40 <= (others => '0'); + if zs_valid_p(1) = '0' and zs_valid_p(0) = '1' then + trig40(31) <= '1'; + end if; + if zs_valid_p(0) = '1' and zs_valid = '0' then + trig40(30) <= '1'; + end if; + trig40(27 downto 0) <= zs_all_valids_p0 & zs_valid_p(0); + end if; + end process; + + --==============================-- + EcalDataZSInstance : entity work.EcalDataZSFilter + --==============================-- + port map ( + clk => clk40, + rst => reset, + lpgbt_payload_i => data_s, + sc_regs_i => zs_sc_regs, + valid_o => zs_valid, + all_valids_o => zs_all_valids, + valid_lat_o => zs_valid_lat + ); + +end rtl; + diff --git a/ecal/firmware/hdl/EcalDataMonitor.vhd b/ecal/firmware/hdl/EcalDataMonitor.vhd new file mode 100644 index 0000000000000000000000000000000000000000..17abd38da4360502fe71b46ffa005d6c30f41c19 --- /dev/null +++ b/ecal/firmware/hdl/EcalDataMonitor.vhd @@ -0,0 +1,52 @@ +------------------------------------------------------------- +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.emp_data_types.all; +use work.mprocessor_constants.all; + + +entity EcalDataMonitor is +port ( + --- Input Ports --- + clk_p : in std_logic; + data_in_valid : in std_logic; + data_in_all_valid : in std_logic_vector(26 downto 0); + data_in : in std_logic_vector(28 * 16 -1 downto 0); + --- IPBus Ports --- + ipb_clk : in std_logic; + ipb_rst : in std_logic; + ipb_in : in ipb_wbus; + ipb_out : out ipb_rbus +); +end EcalDataMonitor; + +architecture rtl of EcalDataMonitor is + + signal ctrl_regs : ipb_reg_v(1 downto 0) := (others => (others => '0')); + signal stat_regs : ipb_reg_v(0 downto 0); + +begin + + --==============================-- + EcalDataMonitorReg: entity work.ipbus_ctrlreg_v + --==============================-- + generic map( + N_CTRL => 2, + N_STAT => 1 + ) + port map( + clk => ipb_clk, + reset => ipb_rst, + ipbus_in => ipb_in, + ipbus_out => ipb_out, + d => stat_regs, + q => ctrl_regs + ); + +end rtl; + + diff --git a/ecal/firmware/hdl/EcalDataProcessor.vhd b/ecal/firmware/hdl/EcalDataProcessor.vhd new file mode 100644 index 0000000000000000000000000000000000000000..bebd5bc59e152dafd1e8079618285c54bf190551 --- /dev/null +++ b/ecal/firmware/hdl/EcalDataProcessor.vhd @@ -0,0 +1,484 @@ +------------------------------------------------------------- +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.emp_data_types.all; +use work.mprocessor_constants.all; +use work.ipbus_decode_eprocessor.all; +use work.dtc_link_maps.all; + +entity EcalDataProcessor is +port ( + --- Input Ports --- + clk_p : in std_logic; + clk40 : in std_logic; + data_in : in tDaqEcalLinkDataArray; + gbe_backpressure : in std_logic; + --- Output Ports --- + data_out : out ldata(cNumberOfEcalOutputLinks - 1 downto 0); + --- IPBus Ports --- + ipb_clk : in std_logic; + ipb_rst : in std_logic; + ipb_in : in ipb_wbus; + ipb_out : out ipb_rbus +); +end EcalDataProcessor; + +architecture rtl of EcalDataProcessor is + + signal ipb_to_slaves : ipb_wbus_array(N_SLAVES - 1 downto 0); + signal ipb_from_slaves : ipb_rbus_array(N_SLAVES - 1 downto 0); + + signal ctrl_regs : ipb_reg_v(0 to 0) := (others => (others => '0')); + signal stat_regs : ipb_reg_v(0 to 0); + + signal reset : std_logic; + signal latency : std_logic_vector(8 downto 0); + + -- 448 length data with valid(1 clock at 320MHz when the data changes at 40MHz) + signal data_start : std_logic; + signal data_last : std_logic; + signal data : std_logic_vector(28 * 16 -1 downto 0); + + signal trig_lat : std_logic_vector(5 downto 0); + signal trig : std_logic_vector(31 downto 0); + + signal data_ram_ena : std_logic; + signal data_ram_wea : std_logic; + signal data_ram_addra : std_logic_vector(8 DOWNTO 0); + signal data_ram_dina : std_logic_vector(66 DOWNTO 0); + signal data_ram_enb : std_logic; + signal data_ram_addrb : std_logic_vector(8 DOWNTO 0); + signal data_ram_doutb : std_logic_vector(66 DOWNTO 0); + + signal trig_ram_ena : std_logic; + signal trig_ram_wea : std_logic; + signal trig_ram_addra : std_logic_vector(5 downto 0); + signal trig_ram_dina : std_logic_vector(31 DOWNTO 0); + signal trig_ram_enb : std_logic; + signal trig_ram_addrb : std_logic_vector(5 downto 0); + signal trig_ram_doutb : std_logic_vector(31 DOWNTO 0); + + signal trig_ram_doutb_l : std_logic_vector(31 DOWNTO 0); + + signal trig_ram_enb_p : std_logic_vector(1 downto 0); + signal trig_valid_p : std_logic_vector(2 downto 0); + signal data_out_p : ldata(2 downto 0); + + signal data_ready_i : std_logic; + signal d_waddr_valid_i : std_logic; + signal t_waddr_valid_i : std_logic; + signal raddr_valid_i : std_logic; + + signal trig_lat_offset : std_logic_vector(8 downto 0); + + signal data_out_s : lword; + + type ostate_type is (wait_start, wait_last, wait_bpoff); -- This state machine does not allow a single frame packet. The packet length >= 2. + signal ostate : ostate_type; + +begin + + --==============================-- + 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_eprocessor(ipb_in.ipb_addr), + ipb_to_slaves => ipb_to_slaves, + ipb_from_slaves => ipb_from_slaves + ); + + --==============================-- + ctrl_reg: entity work.ipbus_ctrlreg_v + --==============================-- + generic map( + N_CTRL => 1, + N_STAT => 1 + ) + port map( + clk => ipb_clk, + reset => ipb_rst, + ipbus_in => ipb_to_slaves(N_SLV_DP), + ipbus_out => ipb_from_slaves(N_SLV_DP), + d => stat_regs, + q => ctrl_regs + ); + reset <= ctrl_regs(0)(0); + latency <= ctrl_regs(0)(9 downto 1); + trig_lat_offset <= ctrl_regs(0)(18 downto 10); + stat_regs(0)(8 downto 0) <= latency; + stat_regs(0)(17 downto 9) <= trig_lat_offset; + stat_regs(0)(18) <= gbe_backpressure; + -- stat_regs(0)(10) <= d_waddr_valid_i; + -- stat_regs(0)(11) <= t_waddr_valid_i; + -- stat_regs(0)(12) <= raddr_valid_i; + -- stat_regs(0)(13) <= zsf_bypass; + -- stat_regs(0)(17) <= trig_ram_dina(0); + -- stat_regs(0)(18) <= trig_ram_doutb(0); + -- stat_regs(0)(19) <= trig_valid_p(0); + -- stat_regs(0)(20) <= trig_valid_p(1); + -- stat_regs(0)(20) <= trig_valid_p(2); + + --==============================-- + EcalDataAggregatorInstance : entity work.EcalDataAggregator + --==============================-- + port map ( + clk_p => clk_p, + data_in => data_in, + data_out_start => data_start, + data_out_last => data_last, + data_out => data + ); + + --==============================-- + EcalDataFilterInstance : entity work.EcalDataFilter + --==============================-- + port map ( + clk_p => clk_p, + clk40 => clk40, + reset => reset, + data_in_start => data_start, + data_in => data, + trig_o_lat => trig_lat, + trig_o => trig, + --- IPBus Ports --- + ipb_clk => ipb_clk, + ipb_rst => ipb_rst, + ipb_in => ipb_to_slaves(N_SLV_DFilter), + ipb_out => ipb_from_slaves(N_SLV_DFilter) + ); + + +-- --==============================-- +-- EcalDataMonitorInstance : entity work.EcalDataMonitor +-- --==============================-- +-- port map ( +-- clk_p => clk_p, +-- data_in_valid => data_valid, +-- data_in_all_valid => data_all_valid, +-- data_in => df_data, +-- --- IPBus Ports --- +-- ipb_clk => ipb_clk, +-- ipb_rst => ipb_rst, +-- ipb_in => ipb_to_slaves(N_SLV_MON), +-- ipb_out => ipb_from_slaves(N_SLV_MON) +-- ); + + --==============================-- + ecal_data_ram : entity work.ecal_data_ram + --==============================-- + PORT MAP ( + clka => clk_p, + ena => data_ram_ena, + wea(0)=> data_ram_wea, + addra => data_ram_addra, + dina => data_ram_dina, + clkb => clk_p, + enb => data_ram_enb, + addrb => data_ram_addrb, + doutb => data_ram_doutb + ); + --==============================-- + ecal_trig_ram : entity work.ecal_trig_ram + --==============================-- + PORT MAP ( + clka => clk_p, + ena => trig_ram_ena, + wea(0)=> trig_ram_wea, + addra => trig_ram_addra, + dina => trig_ram_dina, + clkb => clk_p, + enb => trig_ram_enb, + addrb => trig_ram_addrb, + doutb => trig_ram_doutb + ); + + bp: process(clk_p) + constant FMAX : integer := 255; + variable fsize : integer := 0; + begin + if reset = '1' then + fsize := 0; + data_out(0).data <= (others => '0'); + data_out(0).valid <= '0'; + data_out(0).start <= '0'; + data_out(0).last <= '0'; + data_out(0).strobe <= '0'; + ostate <= wait_start; + elsif rising_edge(clk_p) then + + data_out(0).data <= data_out_s.data; + data_out(0).valid <= '0'; + data_out(0).start <= '0'; + data_out(0).last <= '0'; + data_out(0).strobe <= '0'; + case ostate is + when wait_start => + fsize := 0; + if data_out_s.start = '1' and data_out_s.valid = '1' then + fsize := 1; + data_out(0).start <= data_out_s.start; + data_out(0).valid <= data_out_s.valid; + ostate <= wait_last; + else + ostate <= wait_start; + end if; + when wait_last => + data_out(0).valid <= data_out_s.valid; + fsize := fsize + 1; + if data_out_s.valid = '0' or fsize = FMAX then + data_out(0).valid <= '1'; + data_out(0).last <= '1'; + data_out(0).strobe <= '1'; + data_out(0).data <= (others => '1'); + if gbe_backpressure = '0' then + ostate <= wait_start; + else + ostate <= wait_bpoff; + end if; + elsif data_out_s.last = '1' then + data_out(0).valid <= data_out_s.valid; + data_out(0).last <= data_out_s.last; + data_out(0).strobe <= data_out_s.strobe; + if gbe_backpressure = '0' then + ostate <= wait_start; + else + ostate <= wait_bpoff; + end if; + end if; + when wait_bpoff => + if gbe_backpressure = '0' then + ostate <= wait_start; + end if; + end case; + + end if; + end process; + + ram_rw: process(clk_p) + variable data_ready : boolean := false; + variable f_timer : integer range 0 to 7 := 0; + variable g_timer : integer range 0 to 7 := 0; + -- for writing data ram + variable d_waddr : integer range 0 to 511 := 0; + variable d_waddr_valid : boolean := false; + variable d_waddr_wcount : integer range 0 to 8 := 0; + -- for writing trig ram + variable t_waddr : integer range 0 to 63 := 0; + variable t_waddr_valid : boolean := false; + variable t_waddr_wcount : integer range 0 to 63 := 0; + -- for reading rams + variable raddr : integer range 0 to 511 := 0; + variable raddr_valid : boolean := false; + variable raddr_wcount : integer range 0 to 511 := 0; + + -- data ram + constant bit_valid : integer := 64; + constant bit_start : integer := 65; + constant bit_last : integer := 66; + begin + + if reset = '1' then + data_ready := false; + d_waddr := 0; + t_waddr := 0; + raddr := 0; + data_ram_ena <= '0'; + data_ram_wea <= '0'; + data_ram_addra <= (others => '0'); + data_ram_dina <= (others => '0'); + data_ram_enb <= '0'; + data_ram_addrb <= (others => '0'); + trig_ram_ena <= '0'; + trig_ram_wea <= '0'; + trig_ram_addra <= (others => '0'); + trig_ram_dina <= (others => '0'); + trig_ram_enb <= '0'; + trig_ram_enb_p <= (others => '0'); + trig_ram_addrb <= (others => '0'); + + g_timer := 0; + d_waddr_valid := false; + d_waddr_wcount := 0; + t_waddr_valid := false; + t_waddr_wcount := 0; + raddr_valid := false; + raddr_wcount := 0; + elsif rising_edge(clk_p) then + + trig_ram_enb_p(0) <= trig_ram_enb; + trig_ram_enb_p(1) <= trig_ram_enb_p(0); + if data_ready then + data_ready_i <= '1'; + else + data_ready_i <= '0'; + end if; + if d_waddr_valid then + d_waddr_valid_i <= '1'; + else + d_waddr_valid_i <= '0'; + end if; + if t_waddr_valid then + t_waddr_valid_i <= '1'; + else + t_waddr_valid_i <= '0'; + end if; + if raddr_valid then + raddr_valid_i <= '1'; + else + raddr_valid_i <= '0'; + end if; + + if d_waddr_valid then + data_ram_ena <= '1'; + data_ram_wea <= '1'; + data_ram_addra <= std_logic_vector(to_unsigned(d_waddr,9)); + trig_ram_ena <= '1'; + end if; + + trig_ram_wea <= '0'; + if g_timer = 0 then + if t_waddr_valid then + trig_ram_wea <= '1'; + trig_ram_addra <= std_logic_vector(to_unsigned(t_waddr,6)); + end if; + end if; + + data_out_s.data <= (others => '0'); + data_out_s.valid <= '0'; + data_out_s.start <= '0'; + data_out_s.strobe <= '0'; + if trig_ram_enb = '1' and trig_ram_enb_p(1) = '1' then + + data_ram_addrb <= std_logic_vector(to_unsigned(raddr,9)); + trig_ram_addrb <= std_logic_vector(to_unsigned(raddr,9)(8 downto 3)); + + data_out_s.data <= data_ram_doutb(63 downto 0); + if data_ram_doutb(bit_start) = '1' then + data_out_s.data(63 downto 32) <= trig_ram_doutb; + trig_ram_doutb_l <= trig_ram_doutb; + data_out_s.start <= trig_ram_doutb(31); + data_out_s.valid <= trig_ram_doutb(0) and data_ram_doutb(bit_valid); + else + data_out_s.valid <= trig_ram_doutb_l(0) and data_ram_doutb(bit_valid); + data_out_s.last <= trig_ram_doutb_l(30) and data_ram_doutb(bit_last); + data_out_s.strobe <= trig_ram_doutb_l(30) and data_ram_doutb(bit_last); + end if; + end if; + + -- data to write + data_ram_dina(63 downto 0) <= (others => '0'); + data_ram_dina(bit_valid) <= '0'; + data_ram_dina(bit_start) <= '0'; + data_ram_dina(bit_last) <= '0'; + if data_start = '1' then + if data_ready = false then + g_timer := 0; + data_ready := true; + end if; + -- data frame 0 , timer 7 + data_ram_dina(31 downto 0) <= data(data'high - 16 downto data'high - 16 - 31); -- oc? super id? + data_ram_dina(bit_valid) <= '1'; + data_ram_dina(bit_start) <= '1'; + -- data frame 0 + f_timer := 0; + else + if f_timer = 7 then + f_timer := 7; + else + -- data frame 1 - 7, timer 0 - 6 + if f_timer = 0 then + data_ram_dina(63 downto 32) <= data(data'high - 16 downto data'high - 16 - 31); -- calib + data_ram_dina(31 downto 16) <= data(data'high - 48 downto data'high - 48 - 15); -- channel 24 + data_ram_dina(12) <= data(data'high - 3); -- spill + data_ram_dina(11 downto 0) <= data(data'high - 4 downto data'high - 4 - 11); -- bcid + elsif f_timer < 7 then + data_ram_dina(63 downto 0) <= data(64*(7-f_timer)-1 downto 64*(6-f_timer)); + end if; + data_ram_dina(bit_valid) <= '1'; + f_timer := f_timer + 1; + if f_timer = 7 then + data_ram_dina(bit_last) <= '1'; + end if; + -- data frame 1 - 7 + end if; -- f_timer + end if; -- data_valid + + -- trigger to write + trig_ram_dina <= trig; + + -- data ram write address counters + if data_ready then + if d_waddr_valid = false then + d_waddr_wcount := d_waddr_wcount + 1; + else + if d_waddr = 511 then + d_waddr := 0; + else + d_waddr := d_waddr + 1; + end if; + end if; + if d_waddr_wcount = 8 then -- to get the data events in the address [8 * i:8 * i + 7] + d_waddr_valid := true; + end if; + end if; + + -- read rams + if t_waddr_valid then + if raddr_valid = false then + raddr_wcount := raddr_wcount + 1; + else + if raddr = 511 then + raddr := 0; + else + raddr := raddr + 1; + end if; + end if; + + if raddr_wcount = to_integer(unsigned(latency)) then + raddr_valid := true; + data_ram_enb <= '1'; + trig_ram_enb <= '1'; + end if; + end if; + + -- trigger ram write data + if g_timer = 0 then + + if d_waddr_valid then + + if t_waddr_valid = false then + t_waddr_wcount := t_waddr_wcount + 1; + else + if t_waddr = 63 then + t_waddr := 0; + else + t_waddr := t_waddr + 1; + end if; + end if; + + if t_waddr_wcount = to_integer(unsigned(trig_lat)) + to_integer(unsigned(trig_lat_offset)) then + t_waddr_valid := true; + end if; + end if; + end if; + + if g_timer = 7 then + g_timer := 0; + else + g_timer := g_timer + 1; + end if; + + end if; + end process; + +end rtl; diff --git a/ecal/firmware/hdl/EcalLinkInterface.vhd b/ecal/firmware/hdl/EcalLinkInterface.vhd new file mode 100644 index 0000000000000000000000000000000000000000..3d5f84fae0f8e7d8cabef2c04154ad53e4ce995e --- /dev/null +++ b/ecal/firmware/hdl/EcalLinkInterface.vhd @@ -0,0 +1,42 @@ +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.emp_data_types.all; +use work.mprocessor_constants.all; + + +entity EcalLinkInterface is + +port ( + --- Input Ports --- + clk_p : in std_logic; + link_in : in lword := LWORD_NULL; + --- Output Ports --- + link_out : out lword := LWORD_NULL; + ecal_out : out tDaqEcalLinkData +); +end EcalLinkInterface; + +architecture rtl of EcalLinkInterface is + +begin + +link_out.data <= (others => '0'); + +--==============================-- +EcalDataDecoder : entity work.EcalDataDecoder +--==============================-- +port map( + --- Input Ports --- + clk_p => clk_p, + data_in => link_in, + --- Output Ports --- + ecal_out => ecal_out +); + +end rtl; + diff --git a/ecal/firmware/hdl/EcalZeroSuppressionFilter.vhd b/ecal/firmware/hdl/EcalZeroSuppressionFilter.vhd new file mode 100644 index 0000000000000000000000000000000000000000..ed8dde99fd9e92d16dcacd637a48fc7fce2ef7a6 --- /dev/null +++ b/ecal/firmware/hdl/EcalZeroSuppressionFilter.vhd @@ -0,0 +1,423 @@ +---------------------------------------------------------------------------------- +-- ZeroSuppression filter module. +-- Designed for MuOne experiment - August 2023 +-- Fabio Montecassiano - INFN Padova + +--- TODO +--- a lot... +-- + +-- MEMO ------------------------------------------ +-- a: short name for 'no. of samples AFTER trg has been asserted' +-- b: short name for 'no. of samples BEFORE trg will be asserted' +-- c: short name for 'no. of samples to be CHECKED vs. threshold in order to assert the trg signal' + + +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +use ieee.math_real.all; -- for static elaboration of log2() +use WORK.ecal_zsf_type_pckg.all; + +entity EcalDataZSFilter is +generic( + N_ch: POSITIVE:= 27; -- Sets the no. of channels (Ecal August 2023 requires 27ch=25+2 calib ch) + DeadTime_MAX: + POSITIVE:= 2**16-1; -- Set the the limit for the DeadTime between 2 consecutive 'valid' assertion in in terms of no. of clocks + -- + -- NB The generics "a_LEFT, b_LEFT, c_LEFT" control the sharing of the slow control register 'sc_regs_i(28)' among the 3 parameters Nsmpl_a, Nsmpl_b, Nsmpl_c + -- + a_MAX: POSITIVE:= 2**8-1; -- Sets the limit of the observable future in in terms of no. of samples after the C1 assertion when in 'BASIC mode' + a_LEFT: NATURAL:= 16; -- Sets the lower bound of the index inside slow ctrl reg 'sc_regs_i(28)' for parameter Nsmpl_a + + b_MAX: POSITIVE:= 2**5-1; -- A.K.A. 'D' deepth of delay line (they must match!). Sets the limit of the observable past in terms of no. of samples before C1 assertion + b_LEFT: NATURAL:= 8; -- Sets the lower bound of the index inside slow ctrl reg 'sc_regs_i(28)' for parameter Nsmpl_b + + c1_MAX: POSITIVE:= 2**4-1; -- Sets the limit for the no. of consecutive checks "over threshold" + c_LEFT: NATURAL:= 0; -- Sets the lower bound of the index inside slow ctrl reg 'sc_regs_i(28)' for parameter Nsmpl_c + + ch_trg_MAX: POSITIVE:= 32 -- Maximum no. of clocks after that the deassertion of the channel trigger signal 'ch_trgs()' is forced +); +port +( + clk: in std_logic; -- 40 MHz + rst: in std_logic; + + ---------------------------------------------------------------- + -- PORT 'lpgbt_payload_i' assumes the following map on 56 byte. + -- IT NEEDS TO BE REMAPPED ACCORDING TO THE SERENITY FW <<<<<<<<<<<<<<<<<<<< TODO + -- lpgbt_payload_i(447..445): reserved/sync [ 3 bit] + -- lpgbt_payload_i(444): spill_mskd [ 1 bit] + -- lpgbt_payload_i(443..432): bc [12 bit] + -- lpgbt_payload_i(431..400): oc_OR_calib_ch [32 bit] + -- lpgbt_payload_i(399..0): adc_data_i(24)..adc_data_i(0) [25x16 bit] + lpgbt_payload_i: in std_logic_vector(447 downto 0); + ---------------------------------------------------------------- + -- Slow control operated through an array of ipbus registers delivering + -- threshold 27x16bit, mask_trg_ch 1x 27bit, ... + -- Provisional map of each of 32 bits register: + -- 0: thrsld_ch(0) [highest 16 b RESERVED / lowest 16 b 'threshold physic ch #0'] + -- ... + -- 24: thrsld_ch(24) [highest 16 b RESERVED / lowest 16 b 'threshold physic ch #24'] + -- 25: thrsld_clbr(0)[highest 16 b RESERVED / lowest 16 b 'threshold calibration ch #0'] + -- 26: thrsld_clbr(1)[highest 16 b RESERVED / lowest 16 b 'threshold calibration ch #1'] + -- 27: mask_trg_ch [highest 5 b RESERVED / lowest 27 b 'mask_trg_ch'] + -- 28: Nsmpl_* [highest 8 b RESERVED / 8 b 'Nsmpl_a' / 8 b 'Nsmpl_b' / 4 b RESERVED / 4 b 'Nsmpl_c'] + -- 29: DeadTime [highest 16 b RESERVED / lowest 16 b 'DeadTime'] + -- 30: RESERVED + -- 31: Control [highest 29 b RESERVED / 2:'en_adv'/ 1:'en_dtime' / 0:'en_rtrg'] + sc_regs_i: in array_32bit(0 to 31); -- array (0 to 31) of std_logic_vector(31 downto 0) --std_logic_vector(1023 downto 0); + valid_o: out std_logic; + all_valids_o: out std_logic_vector(N_ch-1 downto 0); + valid_lat_o: out std_logic_vector(5 downto 0) +); +end entity; + +architecture rtl of EcalDataZSFilter is + + -- Derived constants ---------------------------------- + constant Nsmpl_c_BITS: POSITIVE:=positive(ceil(log2(real(c1_MAX)))); + constant Nsmpl_a_BITS: POSITIVE:=positive(ceil(log2(real(a_MAX)))); + constant vld_MAX: POSITIVE:= a_MAX+b_MAX+1; + constant Nsmpl_b_BITS: POSITIVE:=positive(ceil(log2(real(b_MAX)))); + constant DeadTime_BITS:POSITIVE:=positive(ceil(log2(real(DeadTime_MAX)))); + + ------- Slow control by IpBus registers + signal Nsmpl_c: unsigned(Nsmpl_c_BITS-1 downto 0); + signal Nsmpl_b: unsigned(Nsmpl_b_BITS-1 downto 0); + signal Nsmpl_a: unsigned(Nsmpl_a_BITS-1 downto 0); + signal mask_trg_ch: std_logic_vector(N_ch-1 downto 0); + signal DeadTime: unsigned(DeadTime_BITS-1 downto 0); + signal en_dtime, en_rtrg, en_adv: std_logic; + -- + -- State Machine checking threshold, one per each channel -- + -- States + type t_State_ch is (WAIT_T, COUNT_C1, ASSRT_CH_TRG); + -- Counters + type r_cnt_ch is + record + c1: NATURAL range 0 to c1_MAX+ch_trg_MAX+1; + trg: NATURAL range 0 to ch_trg_MAX+1; + end record; + -- Channel signals we want to observe as group/array + type t_array_cnt_ch is array (integer range <>) of r_cnt_ch; + type t_array_16bit is array (integer range <>) of std_logic_vector(15 downto 0); + type t_array_State_ch is array (integer range <>) of t_State_ch; + signal ch: t_array_16bit(N_ch-1 downto 0); + signal T: std_logic_vector(N_ch-1 downto 0):=(others=>'0'); + signal thrsld_ch: t_array_16bit(N_ch-1 downto 0); + signal State_ch, NxtState_ch : t_array_State_ch(N_ch-1 downto 0); + signal Cnt_ch, NxtCnt_ch: t_array_cnt_ch(N_ch-1 downto 0); + -- Output of channels' State Machines + signal trgs_ch: std_logic_vector(N_ch-1 downto 0); + -- + procedure BuildNxtState_ch( + constant State: in t_State_ch; + signal NxtState_ch: out t_State_ch; + signal Cnt_ch: in r_cnt_ch; + signal NxtCnt_ch: out r_cnt_ch; + variable ch_trg: out std_logic + ) is + begin + NxtState_ch <= State; + NxtCnt_ch <= Cnt_ch; + case State is + when WAIT_T => + ch_trg:='0'; + NxtCnt_ch.c1 <=0; + NxtCnt_ch.trg<=0; + when COUNT_C1 => + ch_trg:='0'; + NxtCnt_ch.c1 <=Cnt_ch.c1+1; + NxtCnt_ch.trg<=0; + when ASSRT_CH_TRG => + ch_trg:='1'; + NxtCnt_ch.c1 <=Cnt_ch.c1+1; + NxtCnt_ch.trg<=Cnt_ch.trg+1; + when OTHERS => + REPORT "FAULT CONDITION in 'BuildNextState_ch(NxtState_ch<=<'" & t_State_ch'IMAGE(State) &">,....)" + SEVERITY FAILURE; + end case; + end procedure BuildNxtState_ch; + -- + -- Common State Machine elaborating the valid signal, one for all channels + -- States + type t_State_com is (WAIT_TRG, CNT_BFR, TRG_ASSRTD, CNT_AFTR_TRG, WAIT_DTIME); + signal State_com, NextState_com: t_State_com; + -- Input of common State Machine + signal trg: std_logic:='0'; + -- Counters + type r_cnt_com is + record + bfrvld: NATURAL range 0 to b_MAX+1+1; + aftrtrg: NATURAL range 0 to a_MAX+1; + dtime: NATURAL range 0 to 2**DeadTime'LENGTH; --TODO check this vs. +1 + vld: NATURAL range 0 to vld_MAX+1; + end record; + signal Cnt_com, NxtCnt_com: r_cnt_com; + +------------------------------------------------------ +begin + valid_lat_o <= std_logic_vector(to_unsigned(b_MAX, 6)); + -- + -- TODO: add assert checks for size of sc register VS. IpBus reserved widths + -- + + -- Decode slow control IpBus registers + mask_trg_ch <= sc_regs_i(27)(mask_trg_ch'RANGE); + Nsmpl_c <= unsigned(sc_regs_i(28)(c_LEFT+Nsmpl_c_BITS-1 downto c_LEFT)); + Nsmpl_b <= unsigned(sc_regs_i(28)(b_LEFT+Nsmpl_b_BITS-1 downto b_LEFT)); + Nsmpl_a <= unsigned(sc_regs_i(28)(a_LEFT+Nsmpl_a_BITS-1 downto a_LEFT)); + + DeadTime<= unsigned(sc_regs_i(29)(DeadTime'RANGE)); + en_rtrg <= sc_regs_i(31)(0); + en_dtime<= sc_regs_i(31)(1); + en_adv <= sc_regs_i(31)(2); + + ---------------------------------------------------- + -- Channels State Machines + ---------------------------------------------------- +SMs_ch: + FOR I in 0 to N_ch-1 GENERATE + BEGIN + -- Check ADC threshold + ch(I) <= lpgbt_payload_i((I+1)*16-1 downto I*16); + thrsld_ch(I) <= sc_regs_i(I)(15 downto 0); + T(I)<= '1' when ch(I) > thrsld_ch(I) else '0'; + -- State registers -- + p_regs:process(Clk) is + begin + if rising_edge(clk) then + if rst = '1' then + State_ch(I) <= WAIT_T; + Cnt_ch(I) <= (others => 0); + else + State_ch(I) <= NxtState_ch(I); + Cnt_ch(I) <= NxtCnt_ch(I); + end if; + end if; + end process; + + p_comb:process(T(I), State_ch(I), Cnt_ch(I)) is + variable ch_trg: std_logic; + -- Local PROCEDURE to facilitate signal updating + procedure BuildNxtState_ch( + constant StateToSet: in t_State_ch; + signal NxtState_ch: out t_State_ch; + signal Cnt_ch: in r_cnt_ch; + signal NxtCnt_ch: out r_cnt_ch; + variable ch_trg: out std_logic + ) is + begin + NxtState_ch <= StateToSet; + NxtCnt_ch <= Cnt_ch; + case StateToSet is + when WAIT_T => + ch_trg:='0'; + NxtCnt_ch.c1 <=0; + NxtCnt_ch.trg<=0; + when COUNT_C1 => + ch_trg:='0'; + NxtCnt_ch.c1 <=Cnt_ch.c1+1; + NxtCnt_ch.trg<=0; + when ASSRT_CH_TRG => + ch_trg:='1'; + NxtCnt_ch.c1 <=Cnt_ch.c1+1; + NxtCnt_ch.trg<=Cnt_ch.trg+1; + when OTHERS => + REPORT "FAULT CONDITION in 'BuildNxtState_ch(NxtState_ch<=<'" & t_State_ch'IMAGE(StateToSet) &">,....)" + SEVERITY FAILURE; + end case; + end procedure BuildNxtState_ch; + + begin -- p_comb + NxtState_ch(I) <= State_ch(I); + NxtCnt_ch(I) <= Cnt_ch(I); + case State_ch(I) is + when WAIT_T => + if T(I)='0' then + BuildNxtState_ch(WAIT_T, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + elsif (T(I)='1' and Nsmpl_c/=1) then + BuildNxtState_ch(COUNT_C1, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + elsif (T(I)='1' and Nsmpl_c=1) then + BuildNxtState_ch(ASSRT_CH_TRG, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + else + REPORT LF & "FAULT CONDITION in process 'SMs_ch.p_comb' with State_ch='" & t_State_ch'IMAGE(State_ch(I)) &",....)" & LF SEVERITY FAILURE; + BuildNxtState_ch(WAIT_T, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + end if; + when COUNT_C1 => + if T(I)='0' then + BuildNxtState_ch(WAIT_T, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + elsif (T(I)='1' and Cnt_ch(I).c1 < Nsmpl_c) then + BuildNxtState_ch(COUNT_C1, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + elsif (T(I)='1' and Cnt_ch(I).c1 >= Nsmpl_c) then + BuildNxtState_ch(ASSRT_CH_TRG, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + else + REPORT LF & "FAULT CONDITION in process 'SMs_ch.p_comb' with State_ch='" & t_State_ch'IMAGE(State_ch(I)) &",....)" & LF SEVERITY FAILURE; + BuildNxtState_ch(WAIT_T, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + end if; + when ASSRT_CH_TRG => + if (T(I)='0' or (T(I)='1' and Cnt_ch(I).trg >= ch_trg_MAX)) then + BuildNxtState_ch(WAIT_T, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + elsif (T(I)='1' and Cnt_ch(I).trg < ch_trg_MAX) then + BuildNxtState_ch(ASSRT_CH_TRG, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + else + REPORT LF & "FAULT CONDITION in process 'SMs_ch.p_comb' with State_ch='" & t_State_ch'IMAGE(State_ch(I)) &",....)" & LF SEVERITY FAILURE; + BuildNxtState_ch(WAIT_T, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + end if; + when OTHERS => + REPORT LF & "FAULT CONDITION in process 'SMs_ch.p_comb' with State_ch='" & t_State_ch'IMAGE(State_ch(I)) &",....)" & LF SEVERITY FAILURE; + BuildNxtState_ch(WAIT_T, NxtState_ch(I), Cnt_ch(I), NxtCnt_ch(I), ch_trg); + end case; + -- output of the SM + trgs_ch(I) <= ch_trg; + end process; + ------------------------------------------ + END GENERATE; + + ---------------------------------------------------- + -- Common State Machine + ---------------------------------------------------- + -- Input of common SM + trg <= '0' when (unsigned(mask_trg_ch(trgs_ch'RANGE) AND trgs_ch) = 0) else '1'; + +p_SM_com_reg: process(clk) is + begin + if rising_edge(clk) then + if rst = '1' then + State_com <= WAIT_TRG ; + Cnt_com <= (others => 0); + else + State_com <= NextState_com; + Cnt_com <= NxtCnt_com; + end if; + end if; + end process; + ----- +p_SM_com_comb:process(State_com, trg, Cnt_com) is + variable vld: std_logic; + variable CONDITION: boolean; + -- Local PROCEDURE to facilitate signal updating + -- NB being local to the process, its arguments can be simplified + procedure BuildNextState_com( + constant StateToSet: in t_State_com; + signal NxtState_com:out t_State_com; + signal Cnt_com: in r_cnt_com; + signal NxtCnt_com: out r_cnt_com; + variable vld: out std_logic + ) is + begin + NxtState_com <= StateToSet; + NxtCnt_com <= Cnt_com; + case StateToSet is + when WAIT_TRG => + vld:='0'; + NxtCnt_com.vld <= 0; + NxtCnt_com.bfrvld <= 0; + NxtCnt_com.aftrtrg<= 0; + NxtCnt_com.dtime <= 0; + when CNT_BFR => + vld:='0'; + NxtCnt_com.vld <= 0; + NxtCnt_com.bfrvld <= Cnt_com.bfrvld+1; + NxtCnt_com.aftrtrg<= 0; + NxtCnt_com.dtime <= 0; + when TRG_ASSRTD => + vld :='1'; + NxtCnt_com.vld <= Cnt_com.vld+1; + NxtCnt_com.aftrtrg <= 0; + NxtCnt_com.dtime <= 0; + when CNT_AFTR_TRG => + vld :='1'; + NxtCnt_com.vld <= Cnt_com.vld+1; + NxtCnt_com.aftrtrg <= Cnt_com.aftrtrg+1; + NxtCnt_com.dtime <= 0; + when WAIT_DTIME => + vld:='0'; + NxtCnt_com.dtime <= Cnt_com.dtime+1; + when OTHERS => + REPORT "FAULT CONDITION in 'BuildNextState_com(NxtState_com<=<'" & t_State_com'IMAGE(StateToSet) &">,....)" + SEVERITY FAILURE; + end case; + end procedure BuildNextState_com; + + begin -- p_SM_com_comb + NextState_com<= State_com; + NxtCnt_com <= Cnt_com; + case State_com is + when WAIT_TRG => + if trg='0' then + BuildNextState_com(WAIT_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + elsif trg='1' then + BuildNextState_com(CNT_BFR, NextState_com, Cnt_com, NxtCnt_com, vld); + else + REPORT LF & "FAULT CONDITION in process 'p_SM_com_comb' with State_com='" & t_State_com'IMAGE(State_com) &",....)" & LF SEVERITY FAILURE; + BuildNextState_com(WAIT_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + end if; + when CNT_BFR => + CONDITION := Cnt_com.bfrvld<b_MAX-Nsmpl_b; + if CONDITION then + BuildNextState_com(CNT_BFR, NextState_com, Cnt_com, NxtCnt_com, vld); + elsif not(CONDITION) then + BuildNextState_com(CNT_AFTR_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); +-- elsif (not(CONDITION) and not(trg='0' or en_adv='0')) then +-- BuildNextState_com(TRG_ASSRTD, NextState_com, Cnt_com, NxtCnt_com, vld); +-- elsif (not(CONDITION) and (trg='0' or en_adv='0')) then +-- BuildNextState_com(CNT_AFTR_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + else + REPORT LF & "FAULT CONDITION in process 'p_SM_com_comb' with State_com='" & t_State_com'IMAGE(State_com) &",....)" & LF SEVERITY FAILURE; + BuildNextState_com(WAIT_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + end if; + when TRG_ASSRTD => + CONDITION := Cnt_com.vld<vld_MAX; + if (trg='1' and CONDITION) then + BuildNextState_com(TRG_ASSRTD, NextState_com, Cnt_com, NxtCnt_com, vld); + elsif trg='0' then + BuildNextState_com(CNT_AFTR_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + elsif (en_dtime='1' and not(CONDITION)) then + BuildNextState_com(WAIT_DTIME, NextState_com, Cnt_com, NxtCnt_com, vld); + elsif (en_dtime='0' and not(CONDITION)) then + BuildNextState_com(WAIT_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + else + REPORT LF & LF & "FAULT CONDITION in process 'p_SM_com_comb' with State_com='" & t_State_com'IMAGE(State_com) &",....)" & LF SEVERITY FAILURE; + BuildNextState_com(WAIT_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + end if; + when CNT_AFTR_TRG => + CONDITION := ((en_adv='0' and Cnt_com.aftrtrg<Nsmpl_b+Nsmpl_a) or (en_adv='1' and Cnt_com.aftrtrg<Nsmpl_a)) + and Cnt_com.vld<vld_MAX; + if (trg='1' and en_rtrg='1' and en_adv='1') then + BuildNextState_com(TRG_ASSRTD, NextState_com, Cnt_com, NxtCnt_com, vld); + elsif CONDITION then + BuildNextState_com(CNT_AFTR_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + elsif en_dtime='1' and not(CONDITION) then + BuildNextState_com(WAIT_DTIME, NextState_com, Cnt_com, NxtCnt_com, vld); + elsif en_dtime='0' and not(CONDITION) then + BuildNextState_com(WAIT_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + else + REPORT LF & "FAULT CONDITION in process 'p_SM_com_comb' with State_com='" & t_State_com'IMAGE(State_com) &",....)" & LF SEVERITY FAILURE; + BuildNextState_com(WAIT_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + end if; + when WAIT_DTIME => + CONDITION := Cnt_com.dtime<DeadTime; + if CONDITION then + BuildNextState_com(WAIT_DTIME, NextState_com, Cnt_com, NxtCnt_com, vld); + elsif not CONDITION then + BuildNextState_com(WAIT_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + else + REPORT LF & "FAULT CONDITION in process 'p_SM_com_comb' with State_com='" & t_State_com'IMAGE(State_com) &",....)" & LF SEVERITY FAILURE; + BuildNextState_com(WAIT_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + end if; + when OTHERS => + REPORT LF & "FAULT CONDITION in process 'p_SM_com_comb' with State_com='" & t_State_com'IMAGE(State_com) &",....)" & LF SEVERITY FAILURE; + BuildNextState_com(WAIT_TRG, NextState_com, Cnt_com, NxtCnt_com, vld); + end case; + -- out + valid_o <= vld; + end process; + ----------------------------------------- + +-- all_valids_o(15 downto 0) <= thrsld_ch(0); + all_valids_o <= mask_trg_ch(trgs_ch'RANGE) AND trgs_ch; + +end architecture; diff --git a/ecal/firmware/hdl/ecal_zsf_type_pckg.vhd b/ecal/firmware/hdl/ecal_zsf_type_pckg.vhd new file mode 100644 index 0000000000000000000000000000000000000000..536ad2760843fd26acaf7cd5d06b19ca2d5aed96 --- /dev/null +++ b/ecal/firmware/hdl/ecal_zsf_type_pckg.vhd @@ -0,0 +1,10 @@ +library ieee; +use ieee.std_logic_1164.all; + +package ecal_zsf_type_pckg is + type array_32bit is array (integer range <>) of std_logic_vector(31 downto 0); + type array_NATURAL is array (integer range <>) of NATURAL; +end ecal_zsf_type_pckg; + +package body ecal_zsf_type_pckg is +end ecal_zsf_type_pckg; diff --git a/ecal/firmware/ucf/eprocessor_constraints.tcl b/ecal/firmware/ucf/eprocessor_constraints.tcl new file mode 100644 index 0000000000000000000000000000000000000000..ee205f2510d7d38b3935a896680e43f5ba1137ff --- /dev/null +++ b/ecal/firmware/ucf/eprocessor_constraints.tcl @@ -0,0 +1,4 @@ +#fast to slow +set_multicycle_path 3 -setup -from [get_pins {payload/EcalDataProcessorInstance/EcalDataAggregatorInstance/data_out_reg[*]/C}] +set_multicycle_path 2 -hold -from [get_pins {payload/EcalDataProcessorInstance/EcalDataAggregatorInstance/data_out_reg[*]/C}] + diff --git a/replacements/emp-fwk/components/top/firmware/hdl/emp_top_pcie_both_ttc.vhd b/replacements/emp-fwk/components/top/firmware/hdl/emp_top_pcie_both_ttc.vhd index bb48838f1a700742281480df98d233187f537e41..4b638bc352e24c6ddbf1390356ecd83f044d6402 100644 --- a/replacements/emp-fwk/components/top/firmware/hdl/emp_top_pcie_both_ttc.vhd +++ b/replacements/emp-fwk/components/top/firmware/hdl/emp_top_pcie_both_ttc.vhd @@ -128,11 +128,11 @@ begin -- Infrastructure - pcie_rst_invert : if emp_slim_top_decl.PCIE_RST_ACTIVE_LEVEL = '1' generate - pcie_sys_rst_n <= not pcie_sys_rst; - else generate -- pcie_rst_invert - pcie_sys_rst_n <= pcie_sys_rst; - end generate pcie_rst_invert; +pcie_rst_invert : if emp_slim_top_decl.PCIE_RST_ACTIVE_LEVEL = '1' generate +pcie_sys_rst_n <= not pcie_sys_rst; +else generate -- pcie_rst_invert +pcie_sys_rst_n <= pcie_sys_rst; +end generate pcie_rst_invert; infra : entity work.emp_infra_pcie port map( @@ -274,7 +274,7 @@ begin rst => ipb_rst, ipb_in => ipb_w_array(N_SLV_PAYLOAD), ipb_out => ipb_r_array(N_SLV_PAYLOAD), - clk40 => clk40, + clk40 => clk40, clk_payload => clks_aux, rst_payload => rsts_aux, clk_p => clk_p, @@ -292,30 +292,30 @@ begin -- 10g gbe_q => gbe_ldata, gbe_backpressure => gbe_backpressure - ); + ); - slink_check : if slink_quads_enabled(SLINK_CONF) > 0 generate - slink : entity work.emp_slink_interface - generic map ( - throughput => SLINK_THROUGHPUT, - technology => SLINK_XCVR_TYPE, - ref_clock_freq => SLINK_REFCLK_FREQ, - ref_clock_index => IO_REGION_SPEC(SLINK_CONF(0).region).io_async_refclk + slink_check : if slink_quads_enabled(SLINK_CONF) > 0 generate + slink : entity work.emp_slink_interface + generic map ( + throughput => SLINK_THROUGHPUT, + technology => SLINK_XCVR_TYPE, + ref_clock_freq => SLINK_REFCLK_FREQ, + ref_clock_index => IO_REGION_SPEC(SLINK_CONF(0).region).io_async_refclk ) - port map ( - ipb_clk => ipb_clk, - ipb_rst => ipb_rst, - ipb_in => ipb_w_array(N_SLV_SLINK), - ipb_out => ipb_r_array(N_SLV_SLINK), + port map ( + ipb_clk => ipb_clk, + ipb_rst => ipb_rst, + ipb_in => ipb_w_array(N_SLV_SLINK), + ipb_out => ipb_r_array(N_SLV_SLINK), - clk_40 => clk40ish, - clk_p => clk_p, + clk_40 => clk40ish, + clk_p => clk_p, - slink_d => slink_payload_data, - backpressure => slink_backpressure, + slink_d => slink_payload_data, + backpressure => slink_backpressure, - refclkp => refclkp, - refclkn => refclkn + refclkp => refclkp, + refclkn => refclkn ); end generate; diff --git a/top/charm/addr_table/emp_payload.xml b/top/charm/addr_table/emp_payload.xml index 6565fe20613346e07da6f821af442fd0cb72fd54..711814852db7c1a3a33674eafc5e5aaa83efd27b 100644 --- a/top/charm/addr_table/emp_payload.xml +++ b/top/charm/addr_table/emp_payload.xml @@ -1,23 +1,25 @@ <node description="Payload ipbus registers and RAM" fwinfo="endpoint"> - <node id="fe" address="0x0000" description="FE channel select" fwinfo="endpoint;width=1"> + <node id="fe" address="0x00" description="FE channel select" fwinfo="endpoint;width=1"> <node id="chan_sel" address="0x00" mask="0x7f"/> <node id="num_links" address="0x01"/> </node> <node id="fe_chan" address="0x200" module="file://dtc_link_interface.xml" fwinfo="endpoint;width=9"/> - - <node id="mprocessor" address="0x400" description="MProcessor control and status" module="file://mprocessor.xml" fwinfo="endpoint;width=7"/> - <node id="mproc_ctrl" address="0x4ff" description="MProcessor channel control" fwinfo="endpoint;width=0"> - <node id="chan_sel" mask="0x7f"/> - <node id="srst" mask="0x80"/> - <node id="sync_fastreset" mask="0x100"/> - </node> - <node id="tcds_fast_cmd" address="0x600" module="file://dtc_tcds_fastcmd.xml"/> <node id="link_monitor" address="0x10000" module="file://LinkMonitorInterface.xml"/> + + <node id="mprocessor" address="0x40000" description="MProcessor control and status" module="file://mprocessor.xml" fwinfo="endpoint;width=13"/> + <node id="mproc_ctrl" address="0x4fff0" description="MProcessor channel control" fwinfo="endpoint;width=1"> + <node id="control" address="0x0"> + <node id="chan_sel" mask="0x7f"/> + <node id="srst" mask="0x80"/> + <node id="sync_fastreset" mask="0x100"/> + </node> + <node id="header_user_bits" address="0x1"/> + </node> <node id="be_daq" address="0x40000000" module="file://dtc_data_aggregator.xml" fwinfo="endpoint;width=30"/> </node> diff --git a/top/charm/firmware/hdl/emp_payload.vhd b/top/charm/firmware/hdl/emp_payload.vhd index 1ff76fb2aeb5777f60d1b1acb922dd7b42074b65..ac9e640368bf462e5bf4e620077f121bd5b4e894 100644 --- a/top/charm/firmware/hdl/emp_payload.vhd +++ b/top/charm/firmware/hdl/emp_payload.vhd @@ -59,10 +59,10 @@ architecture rtl of emp_payload is signal ipb_to_slaves : ipb_wbus_array(N_SLAVES - 1 downto 0); signal ipb_from_slaves : ipb_rbus_array(N_SLAVES - 1 downto 0); - signal fe_control_registers : ipb_reg_v(0 downto 0); - signal fe_status_registers : ipb_reg_v(0 downto 0); - - signal mproc_channel_sel : ipb_reg_v(0 downto 0); + signal fe_control_registers : ipb_reg_v(0 downto 0); + signal fe_status_registers : ipb_reg_v(0 downto 0); + signal mproc_control_registers : ipb_reg_v(1 downto 0); + signal mproc_status_registers : ipb_reg_v(0 downto 0); signal link_aggr_control : ipb_reg_v(0 downto 0); @@ -71,14 +71,13 @@ architecture rtl of emp_payload is signal ipb_chain : ipbdc_bus_array(cNumberOfFEModules downto 0); signal stubs : ldata(cNumberOfFEModules - 1 downto 0); signal header_array : tCICHeaderArray(cNumberOfFEModules*cNumberOfCICs - 1 downto 0) := (others => ('0', (others => '0'), (others => '0'), (others => '0'))); - signal header_start_array : std_logic_vector(cNumberOfFEModules*cNumberOfCICs - 1 downto 0) := (others => '0'); + signal header_start_array, header_start_array_buffered : std_logic_vector(cNumberOfFEModules*cNumberOfCICs - 1 downto 0) := (others => '0'); signal eth_link_out : ldata(3 downto 0) := (others => LWORD_NULL); -- MProcessor - constant cNumberOfMProcessors : integer := 1; signal mprocessor_ipb_chain : ipbdc_bus_array(cNumberOfMProcessors downto 0); signal srst : std_logic := '0'; signal ttc_resync_reset, ttc_resync_reset_prev : std_logic := '0'; @@ -86,6 +85,8 @@ architecture rtl of emp_payload is signal orbit_counter : unsigned(31 downto 0) := to_unsigned(0 , 32); signal bunch_counter : unsigned(11 downto 0) := to_unsigned(3564, 12); + signal readout_reset : std_logic_vector(cNumberOfMProcessors - 1 downto 0) := (others => '0'); + signal payload_headers : tPayloadHeaderArray := (others => (others => '0')); -- Daqpath @@ -93,6 +94,8 @@ architecture rtl of emp_payload is signal daq_read : tDaqFlagLinkArray(cNumberOfFEModules - 1 downto 0); signal daq_data : tDaqDataLinkArray(cNumberOfFEModules - 1 downto 0); signal daq_empty : tDaqFlagLinkArray(cNumberOfFEModules - 1 downto 0); + signal daq_data_buffered : tDaqDataLinkArray(cNumberOfFEModules - 1 downto 0); + signal daq_empty_buffered : tDaqFlagLinkArray(cNumberOfFEModules - 1 downto 0); -- TCDS & Fast commands @@ -124,11 +127,11 @@ begin ); --==============================-- - channel_ctrl : entity work.ipbus_ctrlreg_v + fe_channel_ctrl : entity work.ipbus_ctrlreg_v --==============================-- - generic map ( - N_CTRL => 1, - N_STAT => 1 + generic map( + N_CTRL => 1, + N_STAT => 1 ) port map ( clk => clk, @@ -158,24 +161,20 @@ begin ); --==============================-- - mproc_channel_ctrl: entity work.ipbus_reg_v + mproc_ctrl: entity work.ipbus_ctrlreg_v --==============================-- generic map( - N_REG => 1 + N_CTRL => 2 ) port map( clk => clk, reset => rst, ipbus_in => ipb_to_slaves(N_SLV_MPROC_CTRL), ipbus_out => ipb_from_slaves(N_SLV_MPROC_CTRL), - q => mproc_channel_sel, - qmask => (0 => X"00000fff") + q => mproc_control_registers ); - - - --==============================-- -- FE data extraction and monitoring --==============================-- @@ -272,14 +271,22 @@ begin -- L1 Data Aggregator --==============================-- + pBufferL1Data : process(clk_p) + begin + if rising_edge(clk_p) then + daq_data_buffered <= daq_data; + daq_empty_buffered <= daq_empty; + end if; + end process pBufferL1Data; + --==============================-- L1DataAggregator : entity work.L1DataAggregator --==============================-- port map ( --- Input Ports --- clk_p => clk_p, - daq_in => daq_data, - empty => daq_empty, + daq_in => daq_data_buffered, + empty => daq_empty_buffered, --- Output Ports --- read => daq_read, --- IPBus Ports --- @@ -299,6 +306,8 @@ begin q(cDTCOutputLinkMap(i)).data <= d(cDTCInputLinkMap(i).index).data; q(cDTCOutputLinkMap(i)).strobe <= '1'; end loop; + + header_start_array_buffered <= header_start_array; end if; end process pRouteStubsToOutput; @@ -308,14 +317,14 @@ begin LinkMonitorInterfaceInstance : entity work.LinkMonitorInterface --==============================-- generic map ( - N_LINKS => 3 + N_LINKS => cNumberOfFEModules ) port map ( --- Input Ports --- clk_p => clk_p, - stubs => stubs(2 downto 0), - headers => header_array(5 downto 0), - header_start => header_start_array(5 downto 0), + stubs => stubs(cNumberOfFEModules - 1 downto 0), + headers => header_array(2*cNumberOfFEModules - 1 downto 0), + header_start => header_start_array(2*cNumberOfFEModules - 1 downto 0), --- IPBus Ports --- clk => clk, rst => rst, @@ -324,7 +333,6 @@ begin ); - --==============================-- -- Link Aggregation and Combination --==============================-- @@ -338,7 +346,7 @@ begin port map( clk => clk, rst => rst, - sel => mproc_channel_sel(0)(6 downto 0), + sel => mproc_control_registers(0)(6 downto 0), ipb_in => ipb_to_slaves(N_SLV_MPROCESSOR), ipb_out => ipb_from_slaves(N_SLV_MPROCESSOR), ipbdc_out => mprocessor_ipb_chain(0), @@ -377,14 +385,15 @@ begin MProcessorInstance: entity work.MProcessor --==============================-- generic map( - N_LINKS => cNumberofInputLinks + N_LINKS => cNumberofInputLinks, + INDEX => i ) port map( --- Input Ports --- clk_p => clk_p, links_in => stubs(cNumberofInputLinks*i + (cNumberofInputLinks - 1) downto cNumberofInputLinks*i), - header_in => header_array, - header_start_array => convertSLVtoHeaderStartArray(header_start_array), + header_start_array => convertSLVtoHeaderStartArray(header_start_array_buffered), + payload_header => payload_headers(i), gbe_backpressure => gbe_backpressure(i), srst => srst, --- Output Ports --- @@ -393,12 +402,32 @@ begin ipb_clk => clk, ipb_rst => rst, ipb_in => ipb_to_channel, - ipb_out => ipb_from_channel + ipb_out => ipb_from_channel, + --- Debug Ports --- + debug_readout_reset => readout_reset(i) ); end generate genMProcessors; + --==============================-- + PayloadHeadeGeneratorInstance : entity work.PayloadHeaderGenerator + --==============================-- + port map ( + --- Input Ports --- + clk_p => clk_p, + reset => srst, + readout_reset => readout_reset(0), + header_start => header_start_array_buffered(0), + module_header_in => header_array, + user_bits => mproc_control_registers(1), + --- Ouput Ports --- + header_out => payload_headers + ); + + - gbe_q <= eth_link_out; + gbe_q(cNumberOfMProcessors-1 downto 0) <= eth_link_out(cNumberOfMProcessors-1 downto 0); + q(25) <= eth_link_out(0); + q(26) <= eth_link_out(1); --==============================-- @@ -440,8 +469,8 @@ begin end if; end process; - ttc_resync_reset <= mproc_channel_sel(0)(8); - srst <= mproc_channel_sel(0)(7) or ttc_oc0; + ttc_resync_reset <= mproc_control_registers(0)(8); + srst <= mproc_control_registers(0)(7) or ttc_oc0; q(24).valid <= '1'; q(24).data <= "0000" & std_logic_vector(bunch_counter) & "0000000000000000" & std_logic_vector(orbit_counter); diff --git a/top/charm/firmware/hdl/link_maps.vhd b/top/charm/firmware/hdl/link_maps.vhd index 75269aa6132d16e3e4ca58adec6e1f5192d97a0e..5cecd2edfa07176176fb5431e180dc2cf94b181b 100644 --- a/top/charm/firmware/hdl/link_maps.vhd +++ b/top/charm/firmware/hdl/link_maps.vhd @@ -7,6 +7,7 @@ package dtc_link_maps is constant cNumberOfFEModules : integer := 3; constant cNumberOfOutputLinks : integer := 3; + constant cNumberOfMProcessors : integer := 1; type tDTCInputLinkMap is array(0 to cNumberOfFEModules - 1) of tDTCInputLinkConfig; constant cDTCInputLinkMap : tDTCInputLinkMap := ( diff --git a/top/muone/addr_table/emp_payload.xml b/top/muone/addr_table/emp_payload.xml new file mode 100644 index 0000000000000000000000000000000000000000..65601aff8b667bca11a0fd6c3af46136eb6b8f35 --- /dev/null +++ b/top/muone/addr_table/emp_payload.xml @@ -0,0 +1,27 @@ +<node description="Payload ipbus registers and RAM" fwinfo="endpoint"> + + <node id="fe" address="0x00" description="FE channel select" fwinfo="endpoint;width=1"> + <node id="chan_sel" address="0x00" mask="0x7f"/> + <node id="num_links" address="0x01"/> + </node> + + <node id="fe_chan" address="0x200" module="file://dtc_link_interface.xml" fwinfo="endpoint;width=9"/> + + <node id="eprocessor" address="0x500" description="EcalDataProcessor control and status" module="file://eprocessor.xml" fwinfo="endpoint;width=8"/> + + <node id="tcds_fast_cmd" address="0x600" module="file://dtc_tcds_fastcmd.xml"/> + + <node id="link_monitor" address="0x10000" module="file://LinkMonitorInterface.xml"/> + + <node id="mprocessor" address="0x40000" description="MProcessor control and status" module="file://mprocessor.xml" fwinfo="endpoint;width=13"/> + <node id="mproc_ctrl" address="0x4fff0" description="MProcessor channel control" fwinfo="endpoint;width=1"> + <node id="control" address="0x0"> + <node id="chan_sel" mask="0x7f"/> + <node id="srst" mask="0x80"/> + <node id="sync_fastreset" mask="0x100"/> + </node> + <node id="header_user_bits" address="0x1"/> + </node> + + <node id="be_daq" address="0x40000000" module="file://dtc_data_aggregator.xml" fwinfo="endpoint;width=30"/> +</node> diff --git a/top/muone/firmware/cfg/top.dep b/top/muone/firmware/cfg/top.dep new file mode 100644 index 0000000000000000000000000000000000000000..0f54808fb32be2d0babe105a76bda51f169cf6f8 --- /dev/null +++ b/top/muone/firmware/cfg/top.dep @@ -0,0 +1,31 @@ +include -c histogram:top histogram.dep +include -c dtc:dtc-fe common.dep +include -c dtc:dtc-fe framers.dep +include -c dtc:dtc-be/common daqpath.dep +include -c dtc:dtc-be/common common.dep +include -c dtc-stub-processing:common tools.dep + +src -c emp-fwk:components/payload ../ucf/emp_simple_payload.tcl +src -c ipbus-firmware:components/ipbus_slaves ipbus_dpram.vhd +src -c ipbus-firmware:components/ipbus_slaves ipbus_reg_v.vhd +src -c ipbus-firmware:components/ipbus_slaves ipbus_ctrlreg_v.vhd +src -c ipbus-firmware:components/ipbus_slaves ipbus_reg_types.vhd +src -c ipbus-firmware:components/ipbus_core ipbus_dc_node.vhd +src -c ipbus-firmware:components/ipbus_core ipbus_dc_fabric_sel.vhd +include -c emp-fwk:boards/serenity/dc_ku15p dc_ku15p_sm1_v1.dep +include -c emp-fwk:components/links/fe_mgt/interface interface.dep +include -c emp-fwk:components/links/fe_mgt/lpgbt/interface interface_lpgbt.dep + +? toolset.lower() == "vivado" ? setup -c emp-fwk:components/payload emp_simple_payload_msg_suppressions.tcl + +include -c 10gb-ethernet:eth10g emp_eth10g.dep +include -c dtc-monitoring:common module.dep +include -c common module.dep + +src emp_project_decl.vhd +src emp_payload.vhd +src link_maps.vhd + +src ipbus_decode_emp_payload.vhd + +addrtab -t emp_payload.xml diff --git a/top/muone/firmware/hdl/emp_payload.vhd b/top/muone/firmware/hdl/emp_payload.vhd new file mode 100644 index 0000000000000000000000000000000000000000..3035a4dd776d7b0976071db4e4571179e96c6a53 --- /dev/null +++ b/top/muone/firmware/hdl/emp_payload.vhd @@ -0,0 +1,550 @@ +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_emp_payload.all; +--- +use work.emp_data_types.all; +use work.emp_project_decl.all; +use work.emp_device_decl.all; +use work.emp_ttc_decl.all; +use work.emp_slink_types.all; +--- +use work.dtc_link_maps.all; +use work.front_end_data_types.all; +use work.mprocessor_constants.all; +use work.dtc_constants.all; +use work.dtc_data_types.all; + + +entity emp_payload is + port ( + --- Input Ports --- + clk_p : in std_logic; + clk40 : in std_logic := '0'; + clk_payload : in std_logic_vector(2 downto 0); + rst_payload : in std_logic_vector(2 downto 0); + rst_loc : in std_logic_vector(N_REGION - 1 downto 0); + clken_loc : in std_logic_vector(N_REGION - 1 downto 0); + ctrs : in ttc_stuff_array; + d : in ldata(4 * N_REGION - 1 downto 0); + backpressure : in std_logic_vector(SLINK_MAX_QUADS-1 downto 0); + ttc_cmd : in ttc_cmd_t; + --- Output Ports --- + bc0 : out std_logic; + gpio : out std_logic_vector(29 downto 0); + gpio_en : out std_logic_vector(29 downto 0); + q : out ldata(4 * N_REGION - 1 downto 0); + slink_q : out slink_input_data_quad_array(SLINK_MAX_QUADS-1 downto 0); + --- IPBus Ports --- + clk : in std_logic; + rst : in std_logic; + ipb_in : in ipb_wbus; + ipb_out : out ipb_rbus; + -- KH + gbe_q : out ldata := (others => LWORD_NULL); + gbe_backpressure : in std_logic_vector(3 downto 0) + ); +end entity emp_payload; + + +architecture rtl of emp_payload 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); + + signal fe_control_registers : ipb_reg_v(0 downto 0); + signal fe_status_registers : ipb_reg_v(0 downto 0); + signal mproc_control_registers : ipb_reg_v(1 downto 0); + signal mproc_status_registers : ipb_reg_v(0 downto 0); + signal link_aggr_control : ipb_reg_v(0 downto 0); + + + -- FE data extraction and monitoring + + signal ipb_chain : ipbdc_bus_array(cNumberOfFEModules downto 0); + signal stubs : ldata(cNumberOfFEModules - 1 downto 0); + signal header_array : tCICHeaderArray(cNumberOfFEModules*cNumberOfCICs - 1 downto 0) := (others => ('0', (others => '0'), (others => '0'), (others => '0'))); + signal header_start_array, header_start_array_buffered : std_logic_vector(cNumberOfFEModules*cNumberOfCICs - 1 downto 0) := (others => '0'); + + signal eth_link_out : ldata(3 downto 0) := (others => LWORD_NULL); + + + + -- MProcessor + signal mprocessor_ipb_chain : ipbdc_bus_array(cNumberOfMProcessors downto 0); + signal srst : std_logic := '0'; + signal ttc_resync_reset, ttc_resync_reset_prev : std_logic := '0'; + signal ttc_bc0, ttc_oc0, ttc_resync : std_logic := '0'; + + signal orbit_counter : unsigned(31 downto 0) := to_unsigned(0 , 32); + signal bunch_counter : unsigned(11 downto 0) := to_unsigned(3564, 12); + signal readout_reset : std_logic_vector(cNumberOfMProcessors - 1 downto 0) := (others => '0'); + signal payload_headers : tPayloadHeaderArray := (others => (others => '0')); + + + -- Daqpath + + signal daq_read : tDaqFlagLinkArray(cNumberOfFEModules - 1 downto 0); + signal daq_data : tDaqDataLinkArray(cNumberOfFEModules - 1 downto 0); + signal daq_empty : tDaqFlagLinkArray(cNumberOfFEModules - 1 downto 0); + signal daq_data_buffered : tDaqDataLinkArray(cNumberOfFEModules - 1 downto 0); + signal daq_empty_buffered : tDaqFlagLinkArray(cNumberOfFEModules - 1 downto 0); + + + -- TCDS & Fast commands + + signal global_fcmd : tFastCommand; + signal tcds_fcmd : tFastCommand; + + + -- Ecal + + signal ecal_link_data : tDaqEcalLinkDataArray; + signal ecal_data : ldata(cNumberOfEcalOutputLinks - 1 downto 0); + + + +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_emp_payload(ipb_in.ipb_addr), + ipb_to_slaves => ipb_to_slaves, + ipb_from_slaves => ipb_from_slaves + ); + + --==============================-- + fe_channel_ctrl : entity work.ipbus_ctrlreg_v + --==============================-- + generic map( + N_CTRL => 1, + N_STAT => 1 + ) + port map ( + clk => clk, + reset => rst, + ipbus_in => ipb_to_slaves(N_SLV_FE), + ipbus_out => ipb_from_slaves(N_SLV_FE), + d => fe_status_registers, + q => fe_control_registers + ); + + fe_status_registers(0) <= std_logic_vector(to_unsigned(cNumberOfFEModules, 32)); + + + --==============================-- + channel_select : entity work.ipbus_dc_fabric_sel + --==============================-- + generic map ( + SEL_WIDTH => 7 + ) + port map ( + clk => clk, + rst => rst, + sel => fe_control_registers(0)(6 downto 0), + ipb_in => ipb_to_slaves(N_SLV_FE_CHAN), + ipb_out => ipb_from_slaves(N_SLV_FE_CHAN), + ipbdc_out => ipb_chain(0), + ipbdc_in => ipb_chain(cNumberOfFEModules) + ); + + --==============================-- + mproc_ctrl: entity work.ipbus_ctrlreg_v + --==============================-- + generic map( + N_CTRL => 2 + ) + port map( + clk => clk, + reset => rst, + ipbus_in => ipb_to_slaves(N_SLV_MPROC_CTRL), + ipbus_out => ipb_from_slaves(N_SLV_MPROC_CTRL), + q => mproc_control_registers + ); + + + --==============================-- + -- FE data extraction and monitoring + --==============================-- + + --==============================-- + genLinkInterface: for i in 0 to cNumberOfFEModules - 1 generate + --==============================-- + + signal ipb_to_channel : ipb_wbus; + signal ipb_from_channel : ipb_rbus; + + begin + + --==============================-- + channel_node : entity work.ipbus_dc_node + --==============================-- + generic map ( + I_SLV => i, + SEL_WIDTH => 7, + PIPELINE => false + ) + port map ( + clk => clk, + rst => rst, + ipb_out => ipb_to_channel, + ipb_in => ipb_from_channel, + ipbdc_in => ipb_chain(i), + ipbdc_out => ipb_chain(i + 1) + ); + + --==============================-- + LinkInterfaceInstance : entity work.LinkInterface + --==============================-- + generic map ( + module_type => cDTCInputLinkMap(i).module_type, + data_rate => cDTCInputLinkMap(i).data_rate, + cic_type => cDTCInputLinkMap(i).cic_type + ) + port map ( + --- Input Ports --- + clk_p => clk_p, + clk40 => clk40, + link_in => d(cDTCInputLinkMap(i).index), + daq_read => daq_read(i), + global_fcmd => global_fcmd, + --- Output Ports --- + link_out => q(cDTCInputLinkMap(i).index), + stub_out => stubs(i), + header_out => header_array(cNumberOfCICs * i + cNumberOfCICs - 1 downto cNumberOfCICs * i), + daq_out => daq_data(i), + daq_empty => daq_empty(i), + --- IPBus Ports --- + clk => clk, + rst => rst, + ipb_in => ipb_to_channel, + ipb_out => ipb_from_channel, + --- Debug Ports --- + debug_header_start => header_start_array(cNumberOfCICs*(i + 1) - 1 downto cNumberOfCICs*i) + ); + end generate genLinkInterface; + + + --==============================-- + -- Global TCDS + --==============================-- + + --==============================-- + GlobalFastCommand: entity work.GlobalFastCommand + --==============================-- + port map ( + --- Input Ports --- + clk_p => clk_p, + clk40 => clk40, + ext_fcmd => tcds_fcmd, + --- Output Ports --- + global_fcmd => global_fcmd, + --- IPBus Ports --- + clk => clk, + rst => rst, + ipb_in => ipb_to_slaves(N_SLV_TCDS_FAST_CMD), + ipb_out => ipb_from_slaves(N_SLV_TCDS_FAST_CMD) + ); + + tcds_fcmd.fast_reset <= ttc_resync; + tcds_fcmd.l1a_trig <= '0'; + tcds_fcmd.cal_pulse <= '0'; + tcds_fcmd.counter_reset <= ttc_bc0; + + + + + + --==============================-- + -- L1 Data Aggregator + --==============================-- + + pBufferL1Data : process(clk_p) + begin + if rising_edge(clk_p) then + daq_data_buffered <= daq_data; + daq_empty_buffered <= daq_empty; + end if; + end process pBufferL1Data; + + --==============================-- + L1DataAggregator : entity work.L1DataAggregator + --==============================-- + port map ( + --- Input Ports --- + clk_p => clk_p, + daq_in => daq_data_buffered, + empty => daq_empty_buffered, + --- Output Ports --- + read => daq_read, + --- IPBus Ports --- + clk => clk, + rst => rst, + ipb_in => ipb_to_slaves(N_SLV_BE_DAQ), + ipb_out => ipb_from_slaves(N_SLV_BE_DAQ) + ); + + --==============================-- + pRouteStubsToOutput : process (clk_p) is + --==============================-- + begin + if rising_edge(clk_p) then + for i in 0 to cNumberOfOutputLinks - 1 loop + q(cDTCOutputLinkMap(i)).valid <= d(cDTCInputLinkMap(i).index).valid; + q(cDTCOutputLinkMap(i)).data <= d(cDTCInputLinkMap(i).index).data; + q(cDTCOutputLinkMap(i)).strobe <= '1'; + end loop; + + header_start_array_buffered <= header_start_array; + end if; + end process pRouteStubsToOutput; + + + + --==============================-- + LinkMonitorInterfaceInstance : entity work.LinkMonitorInterface + --==============================-- + generic map ( + N_LINKS => cNumberOfFEModules + ) + port map ( + --- Input Ports --- + clk_p => clk_p, + stubs => stubs(cNumberOfFEModules - 1 downto 0), + headers => header_array(2*cNumberOfFEModules - 1 downto 0), + header_start => header_start_array(2*cNumberOfFEModules - 1 downto 0), + --- IPBus Ports --- + clk => clk, + rst => rst, + ipb_in => ipb_to_slaves(N_SLV_LINK_MONITOR), + ipb_out => ipb_from_slaves(N_SLV_LINK_MONITOR) + ); + + + + --==============================-- + -- ECAL + --==============================-- + + --==============================-- + genEcalLinkInterface: for i in 0 to cNumberOfEcalInputLinks - 1 generate + --==============================-- + begin + + EcalLinkInterface : entity work.EcalLinkInterface + port map ( + --- Input Ports --- + clk_p => clk_p, + link_in => d(cECALInputLinkMap(i)), + --- Output Ports --- + link_out => q(cECALInputLinkMap(i)), + ecal_out => ecal_link_data(i) + ); + end generate genEcalLinkInterface; + + --==============================-- + EcalDataProcessorInstance: entity work.EcalDataProcessor + --==============================-- + port map( + --- Input Ports --- + clk_p => clk_p, + clk40 => clk40, + data_in => ecal_link_data, + gbe_backpressure => gbe_backpressure(2), + --- Output Ports --- + data_out => ecal_data, + --- IPBus Ports --- + ipb_clk => clk, + ipb_rst => rst, + ipb_in => ipb_to_slaves(N_SLV_EPROCESSOR), + ipb_out => ipb_from_slaves(N_SLV_EPROCESSOR) + ); + + q(cECALOutputLink).valid <= ecal_data(0).valid; + q(cECALOutputLink).start <= ecal_data(0).start; + q(cECALOutputLink).last <= ecal_data(0).last; + q(cECALOutputLink).data <= ecal_data(0).data; + q(cECALOutputLink).strobe <= ecal_data(0).strobe; + gbe_q(2) <= ecal_data(0); + + --==============================-- + -- Link Aggregation and Combination + --==============================-- + + --==============================-- + mprocessor_channel_select: entity work.ipbus_dc_fabric_sel + --==============================-- + generic map( + SEL_WIDTH => 7 + ) + port map( + clk => clk, + rst => rst, + sel => mproc_control_registers(0)(6 downto 0), + ipb_in => ipb_to_slaves(N_SLV_MPROCESSOR), + ipb_out => ipb_from_slaves(N_SLV_MPROCESSOR), + ipbdc_out => mprocessor_ipb_chain(0), + ipbdc_in => mprocessor_ipb_chain(cNumberOfMProcessors) + ); + + + --==============================- + genMProcessors : for i in 0 to cNumberOfMProcessors - 1 generate + --==============================- + + signal ipb_to_channel : ipb_wbus; + signal ipb_from_channel : ipb_rbus; + constant cNumberofInputLinks : integer := 6; + + begin + + --==============================-- + channel_node: entity work.ipbus_dc_node + --==============================-- + generic map( + I_SLV => i, + SEL_WIDTH => 7, + PIPELINE => false + ) + port map( + clk => clk, + rst => rst, + ipb_out => ipb_to_channel, + ipb_in => ipb_from_channel, + ipbdc_in => mprocessor_ipb_chain(i), + ipbdc_out => mprocessor_ipb_chain(i + 1) + ); + + --==============================-- + MProcessorInstance: entity work.MProcessor + --==============================-- + generic map( + N_LINKS => cNumberofInputLinks, + INDEX => i + ) + port map( + --- Input Ports --- + clk_p => clk_p, + links_in => stubs(cNumberofInputLinks*i + (cNumberofInputLinks - 1) downto cNumberofInputLinks*i), + header_start_array => convertSLVtoHeaderStartArray(header_start_array_buffered), + payload_header => payload_headers(i), + gbe_backpressure => gbe_backpressure(i), + srst => srst, + --- Output Ports --- + link_out => eth_link_out(i), + --- IPBus Ports --- + ipb_clk => clk, + ipb_rst => rst, + ipb_in => ipb_to_channel, + ipb_out => ipb_from_channel, + --- Debug Ports --- + debug_readout_reset => readout_reset(i) + ); + end generate genMProcessors; + + --==============================-- + PayloadHeadeGeneratorInstance : entity work.PayloadHeaderGenerator + --==============================-- + port map ( + --- Input Ports --- + clk_p => clk_p, + reset => srst, + readout_reset => readout_reset(0), + header_start => header_start_array_buffered(0), + module_header_in => header_array, + user_bits => mproc_control_registers(1), + --- Ouput Ports --- + header_out => payload_headers + ); + + + + gbe_q(cNumberOfMProcessors-1 downto 0) <= eth_link_out(cNumberOfMProcessors-1 downto 0); + q(5) <= eth_link_out(0); + q(6) <= eth_link_out(1); + + + --==============================-- + pTTC: process(clk40) + --==============================-- + begin + if rising_edge(clk40) then + + ttc_bc0 <= '0'; + ttc_oc0 <= '0'; + ttc_resync <= '0'; + + if ttc_cmd = TTC_BCMD_BC0 then + orbit_counter <= orbit_counter + 1; + bunch_counter <= (others => '0'); + ttc_bc0 <= '1'; + + if ttc_resync_reset = '1' and ttc_resync_reset_prev = '0' then + + ttc_resync <= '1'; + + end if; + + ttc_resync_reset_prev <= ttc_resync_reset; + + + elsif ttc_cmd = TTC_BCMD_OC0 then + + orbit_counter <= (others => '0'); + bunch_counter <= to_unsigned(3564, bunch_counter'length); + ttc_oc0 <= '1'; + + elsif bunch_counter < 3564 then + + bunch_counter <= bunch_counter + 1; + + end if; + + end if; + end process; + + ttc_resync_reset <= mproc_control_registers(0)(8); + srst <= mproc_control_registers(0)(7) or ttc_oc0; + + q(4).valid <= '1'; + q(4).data <= "0000" & std_logic_vector(bunch_counter) & "0000000000000000" & std_logic_vector(orbit_counter); + q(4).start <= '1'; + q(4).strobe <= '1'; + + + + + bc0 <= '0'; + gpio <= (others => '0'); + gpio_en <= (others => '0'); + + + --==============================-- + slink_q_gen : for q in SLINK_MAX_QUADS-1 downto 0 generate + --==============================-- + begin + slink_q(q) <= SLINK_INPUT_DATA_ARRAY_NULL; + end generate slink_q_gen; + + + +end architecture rtl; diff --git a/top/muone/firmware/hdl/emp_project_decl.vhd b/top/muone/firmware/hdl/emp_project_decl.vhd new file mode 100644 index 0000000000000000000000000000000000000000..d704bc636351a0c8a6d942025e3d012c0ad507c0 --- /dev/null +++ b/top/muone/firmware/hdl/emp_project_decl.vhd @@ -0,0 +1,115 @@ +-- emp_project_decl +-- +-- Defines constants for the whole device + +library ieee; +use ieee.std_logic_1164.all; + +library lpgbt_lib; +use lpgbt_lib.lpgbtfpga_package.all; + +use work.emp_framework_decl.all; +use work.emp_device_decl.all; +use work.emp_device_types.all; +use work.emp_lpgbt_decl.all; +use work.emp_data_framer_decl.all; +use work.emp_slink_types.all; +use work.emp_eth10g_types.all; + +------------------------------------------------------------------------------- +package emp_project_decl is + + constant PAYLOAD_REV : std_logic_vector(31 downto 0) := X"d451d001"; + + -- Latency buffer size + constant LB_ADDR_WIDTH : integer := 10; + + -- Clock setup + constant CLOCK_COMMON_RATIO : integer := 32; + constant CLOCK_RATIO : integer := 8; + constant CLOCK_AUX_DIV : clock_divisor_array_t := (16, 8, 4); -- Dividers of CLOCK_COMMON_RATIO * 40 MHz + + -- Only used by nullalgo + constant PAYLOAD_LATENCY : integer := 5; + + -- mgt -> buf -> fmt -> (algo) -> (fmt) -> buf -> mgt -> clk -> altclk + constant REGION_CONF : region_conf_array_t := ( + -- 0 => (no_mgt, buf, no_fmt, buf, no_mgt), --Bank 225 -- Right Column + 1 => (no_mgt, buf, no_fmt, buf, no_mgt), --Bank 226 + -- 2 => (lpgbt, buf, no_fmt, buf, lpgbt), --Bank 227 + 3 => (lpgbt, buf, no_fmt, buf, lpgbt), --Bank 228 + 4 => (lpgbt, buf, no_fmt, buf, lpgbt), --Bank 229 + 5 => (lpgbt, buf, no_fmt, buf, lpgbt), --Bank 230 + 6 => (lpgbt, buf, no_fmt, buf, lpgbt), --Bank 231 + 7 => (no_mgt, buf, no_fmt, buf, no_mgt), --Bank 232 + 8 => (no_mgt, buf, no_fmt, buf, no_mgt), --Bank 233 + 9 => (no_mgt, buf, no_fmt, buf, no_mgt), --Bank 234 +-- -- Cross-chip +-- KH used for gbe + --10 => (gty25, buf, no_fmt, buf, gty25), + --11 => (gty25, buf, no_fmt, buf, gty25), + --12 => (gty25, buf, no_fmt, buf, gty25), +-- KH used for gbe + 13 => (no_mgt, buf, no_fmt, buf, no_mgt), --Bank 131 + 14 => (no_mgt, buf, no_fmt, buf, no_mgt), --Bank 130 + 15 => (no_mgt, buf, no_fmt, buf, no_mgt), --Bank 129 +-- 16 => (gty25, buf, no_fmt, buf, gty25), --Bank 128 +-- 17 => (gty25, buf, no_fmt, buf, gty25), --Bank 127 + others => kDummyRegion + ); + + -- for data framer (ic_simple, no_ec, n_ec_spare, ec_broadcast) + constant REGION_DATA_FRAMER_CONF : region_data_framer_conf_array_t := ( +-- 2 => ( 0=>(false, true, 0, false, lpgbtv0), 1=>(false, true, 0, false, lpgbtv0), 2=>(false, true, 0, false, lpgbtv1), 3=>(false, true, 0, false, lpgbtv0)), +-- 3 => ( 0=>(false, true, 0, false, lpgbtv0), 1=>(false, true, 0, false, lpgbtv0), 2=>(false, true, 0, false, lpgbtv0), 3=>(false, true, 0, false, lpgbtv0)), + 3 => ( + 0=>(false, true, 0, false, lpgbtv0), + 1=>(false, true, 0, false, lpgbtv0), + 2=>(false, true, 0, false, lpgbtv0), + 3=>(false, true, 0, false, lpgbtv0) + ), + 4 => ( + 0=>(false, true, 0, false, lpgbtv0), + 1=>(false, true, 0, false, lpgbtv0), + 2=>(false, true, 0, false, lpgbtv0), + 3=>(false, true, 0, false, lpgbtv0) + ), + 5 => ( + 0=>(false, true, 0, false, lpgbtv1), + 1=>(false, true, 0, false, lpgbtv0), + 2=>(false, true, 0, false, lpgbtv0), + 3=>(false, true, 0, false, lpgbtv1) + ), + 6 => ( + 0=>(false, true, 0, false, lpgbtv0), + 1=>(false, true, 0, false, lpgbtv0), + 2=>(false, true, 0, false, lpgbtv0), + 3=>(false, true, 0, false, lpgbtv1) + ), + others => kDummyRegionDataFramer + ); + + -- for lpgbt + constant REGION_LPGBT_CONF : region_lpgbt_conf_array_t := ( +-- 2 => (FEC5, DATARATE_5G12, PCS), + 3 => (FEC5, DATARATE_5G12, PCS), + 4 => (FEC5, DATARATE_5G12, PCS), + 5 => (FEC5, DATARATE_5G12, PCS), + 6 => (FEC5, DATARATE_5G12, PCS), + others => kDummyRegionLpgbt + ); + + -- Specify the slink quad using the corresponding region conf ID + -- Specify slink channels to enable using the channel mask + constant SLINK_CONF : slink_conf_array_t := ( + others => kNoSlink + ); + + constant ETH10G_CONF : eth10g_conf_array_t := ( + 0 => (10, "1111", (x"aabbccddef51", x"aabbccddef52", x"aabbccddef53", x"aabbccddef54")) + ); + + + +end emp_project_decl; +------------------------------------------------------------------------------- diff --git a/top/muone/firmware/hdl/link_maps.vhd b/top/muone/firmware/hdl/link_maps.vhd new file mode 100644 index 0000000000000000000000000000000000000000..215bf5a39fe018fba048266733b275c989f38a6b --- /dev/null +++ b/top/muone/firmware/hdl/link_maps.vhd @@ -0,0 +1,39 @@ +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.NUMERIC_STD.ALL; +use work.dtc_link_maps_func.all; + +package dtc_link_maps is + + constant cNumberOfFEModules : integer := 12; + constant cNumberOfOutputLinks : integer := 12; + constant cNumberOfEcalInputLinks : integer := 4; + constant cNumberOfEcalOutputLinks : integer := 1; + + type tDTCInputLinkMap is array(0 to cNumberOfFEModules - 1) of tDTCInputLinkConfig; + constant cDTCInputLinkMap : tDTCInputLinkMap := ( + 0 => (16, "2S", 5, "CIC2"), + 1 => (17, "2S", 5, "CIC2"), + 2 => (18, "2S", 5, "CIC2"), + 3 => (19, "2S", 5, "CIC2"), + 4 => (20, "2S", 5, "CIC2"), + 5 => (21, "2S", 5, "CIC2"), + 6 => (22, "2S", 5, "CIC2"), + 7 => (23, "2S", 5, "CIC2"), + 8 => (24, "2S", 5, "CIC2"), + 9 => (25, "2S", 5, "CIC2"), + 10 => (26, "2S", 5, "CIC2"), + 11 => (27, "2S", 5, "CIC2") + ); + + type tECALInputLinkMap is array(0 to cNumberOfEcalInputLinks - 1) of integer; + constant cECALInputLinkMap : tECALInputLinkMap := (12, 13, 14, 15); + -- type tECALOutputLinkMap is array(0 to cNumberOfEcalOutputLinks - 1) of integer; + -- constant cECALOutputLinkMap : tECALOutputLinkMap := (28); + constant cECALOutputLink : integer := 7; + + type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer; + constant cDTCOutputLinkMap : tDTCOutputLinkMap := (28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39); + +end package dtc_link_maps; +