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;
+