diff --git a/README.md b/README.md
index 796343e6761886a27640dbf912b9ffee5333032e..aea2de9c5605855ed25ca65038165369c8f9c8b6 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# MProcessor Firmware
+# MProcessor Firmware - 2x10gbe
 ## Instructions to Run
 ```bash
 # Pull the package onto the Serenity card
diff --git a/dependencies.yml b/dependencies.yml
index 84de3fc6ae30163ac6b76c7ef90e6344ccbc2ff7..0eab637d15dc099d71b8d6d9b5ab3d70a25c1e1a 100644
--- a/dependencies.yml
+++ b/dependencies.yml
@@ -49,5 +49,5 @@ sources:
         url: https://github.com/KristianHahn/verilog-ethernet.git
 
     10gb-ethernet:
-        tag: v1.0.0
+        tag: v2.0.0
         url: https://gitlab.cern.ch/cms-tracker-phase2-data-processing/BE_firmware/10gb-ethernet.git
diff --git a/replacements/emp-fwk/components/top/addr_table/top_emp.xml b/replacements/emp-fwk/components/top/addr_table/top_emp.xml
index d18a7fd07d948d566e678a7c26aaa2e8a6a27c2e..1dbfd363469346dc91c8246cdb91dd03529efd01 100644
--- a/replacements/emp-fwk/components/top/addr_table/top_emp.xml
+++ b/replacements/emp-fwk/components/top/addr_table/top_emp.xml
@@ -3,7 +3,7 @@
     <node id="ctrl" module="file://emp_ctrl.xml" address="0x200"/>
     <node id="ttc" module="file://emp_ttc.xml" address="0x400"/>
     <node id="datapath" module="file://emp_datapath.xml" address="0x2000"/>
-    <node id="eth10g" module="file://emp_eth10g.xml" address="0x4000"/>
+    <node id="eth10g" module="file://emp_eth10g_interface.xml" address="0x4000"/>
     <node id="freq" module="file://ipbus_freq_ctr.xml" address="0x40000000"/>
     <node id="payload" module="file://emp_payload.xml" address="0x80000000" fwinfo="endpoint;width=31"/>
 </node>
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 4325d53fdd4647e92239ece5bceb818d1ba7c0e2..092073ff1e78995b1e4b4baf347c743a645b25ef 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
@@ -57,10 +57,10 @@ entity top is
     tcds_tx_p      : out std_logic;
     tcds_tx_n      : out std_logic;
     -- 10g eth signals
-    gbe_rx_p          : in std_logic;
-    gbe_rx_n          : in std_logic;
-    gbe_tx_p          : out std_logic;
-    gbe_tx_n          : out std_logic;
+    gbe_rx_p          : in std_logic_vector(1 downto 0);
+    gbe_rx_n          : in std_logic_vector(1 downto 0);
+    gbe_tx_p          : out std_logic_vector(1 downto 0);
+    gbe_tx_n          : out std_logic_vector(1 downto 0);
     gbe_mgt_refclk_p  : in std_logic;
     gbe_mgt_refclk_n  : in std_logic;
     -- Transceiver ref-clocks
@@ -115,18 +115,10 @@ architecture rtl of top is
 
   signal clk125_s             : std_logic;
 
-  signal gbe_ldata : lword;
-
-  signal dbg_pause_count :  std_logic_vector(31 downto 0);
-  signal dbg_pkt_count :  std_logic_vector(15 downto 0);
-  signal dbg_pkt_ctrl  :  std_logic_vector(2 downto 0);
-  signal dbg_pkt_rdy   :  std_logic;
-  signal dbg_pkt_go    :  std_logic;
-
-  -- aug28
-  signal lff,lff_rcvd : std_logic;
-  signal payload_rst : std_logic; -- sep2
-
+  -- 10g
+  signal gbe_ldata : ldata(1 downto 0);
+  signal gbe_lff : std_logic_vector(1 downto 0);
+  
   -- KH tmp
   signal clk_40_div, clk_p_div : std_logic;
 
@@ -298,34 +290,40 @@ begin
       q           => payload_q,
       gpio        => open,
       gpio_en     => open,
-      --
-      ldata_out   => gbe_ldata,
-      lff         => lff
+      -- 10g
+      gbe_q             => gbe_ldata,
+      gbe_backpressure  => gbe_lff
       );
 
 
-  eth : entity work.emp_eth10g 
-    generic map( ILA_DEBUG => true)
-               --ILA_DEBUG_MORE => false)
-    port map ( 
+  --
+  -- 10g
+  --
+  eth10g : entity work.emp_eth10g_interface
+    generic map ( ETH10G_CHANNELS => 2 )
+    port map (
       clk_ipb         => ipb_clk,
       rst_ipb         => ipb_rst,
       ipb_in          => ipb_w_array(N_SLV_ETH10G),
       ipb_out         => ipb_r_array(N_SLV_ETH10G),
       --
-      clk_p              => clk_p,
-      rst_p              => rst_p,      
-      clk125 	         => clk125,
-      gbe_rx_p           => gbe_rx_p,
-      gbe_rx_n           => gbe_rx_n,
-      gbe_tx_p           => gbe_tx_p,
-      gbe_tx_n           => gbe_tx_n,
-      gbe_mgt_refclk_p   => gbe_mgt_refclk_p,
-      gbe_mgt_refclk_n   => gbe_mgt_refclk_n,
-      ldata_in           => gbe_ldata,
-      --
-      lff => lff
+      clk_p           => clk_p,
+      rst_p           => rst_p,
+      clk125          => clk125,
+      -- Input from payload
+      ldata_in        => gbe_ldata,
+      -- backpressure to payload
+      lff             => gbe_lff,
+      --10g
+      gbe_rx_p          => gbe_rx_p,
+      gbe_rx_n          => gbe_rx_n,
+      gbe_tx_p          => gbe_tx_p,
+      gbe_tx_n          => gbe_tx_n,
+      gbe_mgt_refclk_p  => gbe_mgt_refclk_p,
+      gbe_mgt_refclk_n  => gbe_mgt_refclk_n
       );
+  
+  
 
 
 -- KH tmp to check clk_p
diff --git a/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index 15d20dcb009db551c6e412d035ca5f23fb510146..2eaa7ffad503522e0fe60c40af66ecc7205788f1 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -14,43 +14,11 @@
     </node>
 
     <node id="fe_chan" address="0x040" description="FE channel control and status" module="file://link_interface.xml" fwinfo="endpoint;width=6"/>
-    
-    <node id="mprocessor" address="0x080" description="Link Aggregator control and status" fwinfo="endpoint;width=3">
-        <node id="link_aggregator_control" address="0x0">
-            <node id="reset" mask="0x0001"/>
-        </node>
-        <node id="link_combiner_control" address="0x1">
-            <node id="reset" mask="0x0001"/>
-            <node id="enable" mask="0x0002"/>
-        </node>
-        <node id="input_link_mask" address="0x2">
-            <node id="link_aggregator" mask="0xf"/>
-            <node id="link_combiner" mask="0xff0"/>
-            <node id="head_start_select" mask="0x3000"/>
-        </node>
-        <node id="header_user_bits" address="0x3"/>
-        
-        <node id="super_id" address="0x4"/>
-        <node id="lff" address="0x5" mask="0x0001"/>
-        <node id="link_combiner_fifo" address="0x6">
-            <node id="data_count" mask="0xff"/>
-            <node id="full" mask="0x100"/>
-            <node id="rd_en" mask="0x200"/>
-            <node id="overflow" mask="0x400"/>
-        </node>
-        <node id="status" address="0x7">
-            <node id="link_aggregator_output_0_overflow" mask="0x1"/>
-            <node id="link_aggregator_output_1_overflow" mask="0x2"/>
-            <node id="link_aggregator_output_2_overflow" mask="0x4"/>
-            <node id="link_aggregator_output_3_overflow" mask="0x8"/>
-            <node id="link_aggregator_output_4_overflow" mask="0x10"/>
-            <node id="link_aggregator_output_5_overflow" mask="0x20"/>
-            <node id="link_aggregator_output_6_overflow" mask="0x40"/>
-            <node id="link_aggregator_output_7_overflow" mask="0x80"/>
-            <node id="link_aggregator_cache_0_0_overflow" mask="0x100"/>
-            <node id="link_aggregator_route_0_0_overflow" mask="0x200"/>
-        </node>
+
+    <node id="mproc_ctrl" address="0x1ff" description="MProcessor channel control" fwinfo="endpoint;width=0">
+        <node id="chan_sel" mask="0x7f"/>
     </node>
+    <node id="mprocessor" address="0x200" description="MProcessor control and status" module="file://mprocessor.xml" fwinfo="endpoint;width=7"/>
 
     <node id="mem1" address="0x1000" size="0x200" mode="incremental" fwinfo="endpoint;width=9"/>
     <node id="mem2" address="0x2000" size="0x200" mode="incremental" fwinfo="endpoint;width=9"/>
diff --git a/top/addr_table/link_aggregator.xml b/top/addr_table/link_aggregator.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a6ab3964ed27d2a1a7dfae821b7f8819e3b06e2a
--- /dev/null
+++ b/top/addr_table/link_aggregator.xml
@@ -0,0 +1,15 @@
+<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>
+    <node id="monitoring" address="0x008" fwinfo="endpoint;width=3">
+        <node id="non_empty_count_0" address="0x0"/>
+        <node id="non_empty_count_1" address="0x1"/>
+        <node id="non_empty_count_2" address="0x2"/>
+        <node id="non_empty_count_3" address="0x3"/>
+        <node id="non_empty_count_4" address="0x4"/>
+        <node id="non_empty_count_5" address="0x5"/>
+    </node>
+</node>
diff --git a/top/addr_table/mprocessor.xml b/top/addr_table/mprocessor.xml
new file mode 100644
index 0000000000000000000000000000000000000000..57de74f4a685f1dfc83ce13ac3df042663237bb8
--- /dev/null
+++ b/top/addr_table/mprocessor.xml
@@ -0,0 +1,17 @@
+<node description="MProcessor Control and Status" fwinfo="endpoint">
+    <node id="link_aggregator" address="0x0" description="Link Aggregator control and status" module="file://link_aggregator.xml" fwinfo="endpoint;width=5"/>
+    
+    <node id="link_combiner" address="0x20" description="Link Combiner control and status" fwinfo="endpoint;width=1">
+        <node id="control" address="0x000">
+            <node id="input_link_mask" mask="0x0ff"/>
+            <node id="reset" mask="0x100"/>
+            <node id="enable" mask="0x200"/>
+        </node>
+        <node id="header_user_bits" address="0x1"/>
+    </node>
+    
+    <node id="csr" address="0x22" description="MProcessor control and status" fwinfo="endpoint;width=1">
+        <node id="header_start_select" address="0x0" mask="0x7"/>
+        <node id="lff" address="0x1" mask="0x0001"/>
+    </node>
+</node>
diff --git a/top/firmware/cfg/top.dep b/top/firmware/cfg/top.dep
index 0bb0b67169fd2743d2d1fa2987cf3a4aaa4df205..3c062d39ee76f45ee98d5288ea826c403ff0a0a0 100644
--- a/top/firmware/cfg/top.dep
+++ b/top/firmware/cfg/top.dep
@@ -22,10 +22,16 @@ src emp_project_decl.vhd
 src emp_payload.vhd
 src link_maps.vhd
 src ipbus_decode_emp_payload.vhd
-src LinkAggregator.vhd
+src mprocessor_constants.vhd
+src MProcessor.vhd
+src ipbus_decode_mprocessor.vhd
+src LinkAggregatorCore.vhd
+src LinkAggregatorIPBus.vhd
+src ipbus_decode_link_aggregator.vhd
 src fixed_pkg_2008.vhd
 src --vhdl2008 TrackReconstructor.vhd
-src LinkCombiner.vhd
+src LinkCombinerCore.vhd
+src LinkCombinerIPBus.vhd
 
 src --cd ../cgn link_agg_single_link_fifo.xci
 setup -f --cd ../cgn link_agg_single_link_fifo.tcl
@@ -40,4 +46,6 @@ src --cd ../cgn link_combin_buffer.xci
 setup -f --cd ../cgn link_combin_buffer.tcl
 
 
+addrtab link_aggregator.xml
 addrtab emp_payload.xml
+addrtab mprocessor.xml
diff --git a/top/firmware/hdl/LinkAggregator.vhd b/top/firmware/hdl/LinkAggregatorCore.vhd
similarity index 59%
rename from top/firmware/hdl/LinkAggregator.vhd
rename to top/firmware/hdl/LinkAggregatorCore.vhd
index 351ccfd1860902acd0c0044260435cefd93cbea0..609f1499e10917b19cd0eda63c956c51f2391cba 100644
--- a/top/firmware/hdl/LinkAggregator.vhd
+++ b/top/firmware/hdl/LinkAggregatorCore.vhd
@@ -3,31 +3,38 @@ use IEEE.STD_LOGIC_1164.ALL;
 use IEEE.NUMERIC_STD.ALL;
 use work.emp_data_types.all;
 
-entity LinkAggregator is
-  generic (
-    N_LINKS : integer
-  );
-  port (
-    --- Input Ports ---
-    clk_p              : in std_logic;
-    reset              : in std_logic;
-    packet_start       : in std_logic;
-    links_in           : in ldata(N_LINKS - 1 downto 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)
-  );
-end LinkAggregator;
-
-architecture compressed of LinkAggregator is
+use work.ipbus.all;
+use work.ipbus_reg_types.all;
+
+
+entity LinkAggregatorCore is
+    generic (
+        N_LINKS : integer
+    );
+    port (
+        --- Input Ports ---
+        clk_p              : in std_logic;
+        reset              : in std_logic;
+        packet_start       : in std_logic;
+        links_in           : in ldata(N_LINKS - 1 downto 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 ---
+        non_empty_counts   : out ipb_reg_v(8*N_LINKS - 1 downto 0)
+    );
+end LinkAggregatorCore;
+
+
+architecture compressed of LinkAggregatorCore is
 
     constant cFIFOWidth : integer := 64;
 
 
-    -- FIFO IP Cores
+    -- FIFO IP Coress
 
     COMPONENT link_agg_single_link_fifo
     PORT (
@@ -117,8 +124,11 @@ architecture compressed of LinkAggregator is
     end function;
 
     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 route_overflow_array  : tEnableArray                             := cNullEnableArray;
+    signal cache_overflow_array  : tEnableArray                             := cNullEnableArray;
+
+    
+    signal non_empty_fifo_count  : ipb_reg_v(8*N_LINKS - 1 downto 0)        := (others => (others => '0'));
 
 begin
 
@@ -178,6 +188,12 @@ begin
                             rd_en_cache <= '0';
                         end if;
                     end if;
+                    -- Check for non-empty FIFOs at reset
+                    if route_reset = '1' then
+                        if empty_route = '0' then
+                            non_empty_fifo_count(N_LINKS*j + i) <= std_logic_vector(unsigned(non_empty_fifo_count(N_LINKS*j + i)) + 1);
+                        end if;
+                    end if;
                 end if;
             end process pTransferToRoutingFIFO;
             
@@ -381,269 +397,6 @@ begin
     status_bits(7) <= output_overflow_array(7); -- link_aggregator_output_7_overflow;
     status_bits(8) <= cache_overflow_array(0)(0); -- link_aggregator_cache_0_0_overflow;
     status_bits(9) <= route_overflow_array(0)(0); -- link_aggregator_route_0_0_overflow;
+    non_empty_counts <= non_empty_fifo_count;
 
 end compressed;
-
-
-
---======================================================================================================================================================--
-
-
-
-architecture uncompressed of LinkAggregator is
-
-    constant cFIFOWidth : integer := 64;
-
-
-    -- FIFO IP Cores
-
-    COMPONENT link_agg_single_link_fifo
-    PORT (
-        --- Input Ports ---
-        clk          : IN STD_LOGIC;
-        srst         : IN STD_LOGIC;
-        din          : IN STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
-        wr_en        : IN STD_LOGIC;
-        rd_en        : IN STD_LOGIC;
-        --- Output Ports ---
-        dout         : OUT STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
-        full         : OUT STD_LOGIC;
-        empty        : OUT STD_LOGIC;
-        almost_empty : OUT STD_LOGIC;
-        valid        : OUT STD_LOGIC;
-        data_count   : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
-        wr_rst_busy  : OUT STD_LOGIC;
-        rd_rst_busy  : OUT STD_LOGIC
-    );
-    END COMPONENT;
-    COMPONENT link_agg_single_link_fifo_fwft
-    PORT (
-        --- Input Ports ---
-        clk          : IN STD_LOGIC;
-        srst         : IN STD_LOGIC;
-        din          : IN STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
-        wr_en        : IN STD_LOGIC;
-        rd_en        : IN STD_LOGIC;
-        --- Output Ports ---
-        dout         : OUT STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
-        full         : OUT STD_LOGIC;
-        empty        : OUT STD_LOGIC;
-        almost_empty : OUT STD_LOGIC;
-        valid        : OUT STD_LOGIC;
-        data_count   : OUT STD_LOGIC_VECTOR(4 DOWNTO 0);
-        wr_rst_busy  : OUT STD_LOGIC;
-        rd_rst_busy  : OUT STD_LOGIC
-    );
-    END COMPONENT;
-    COMPONENT link_agg_all_links_fifo
-    PORT (
-        --- Input Ports ---
-        clk          : IN STD_LOGIC;
-        srst         : IN STD_LOGIC;
-        din          : IN STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
-        wr_en        : IN STD_LOGIC;
-        rd_en        : IN STD_LOGIC;
-        --- Output Ports ---
-        dout         : OUT STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
-        full         : OUT STD_LOGIC;
-        empty        : OUT STD_LOGIC;
-        almost_empty : OUT STD_LOGIC;
-        valid        : OUT STD_LOGIC;
-        data_count   : OUT STD_LOGIC_VECTOR(5 DOWNTO 0);
-        wr_rst_busy  : OUT STD_LOGIC;
-        rd_rst_busy  : OUT STD_LOGIC
-    );
-    END COMPONENT;
-
-    constant cBoxcarBx  : integer := 8;
-    
-    type tLinkDataArray is array(N_LINKS - 1 downto 0) of std_logic_vector(cFIFOWidth - 1 downto 0);
-    type t2DDataArray is array(cBoxcarBx - 1 downto 0) of tLinkDataArray;
-    type tEnableArray is array(cBoxcarBx - 1 downto 0) of std_logic_vector(N_LINKS - 1 downto 0);
-    
-    signal data              : t2DDataArray := (others => (others => (others => '0')));
-    signal rd_en_route_array : tEnableArray := (others => (others => '0'));
-    signal valid_route_array : tEnableArray := (others => (others => '0'));
-    signal counter           : integer      := 0;
-
-begin
-    --==============================--
-    genLinkCache : for i in N_LINKS - 1 downto 0 generate
-    --==============================--
-        signal wr_en_array_cache : std_logic_vector(cBoxcarBx - 1 downto 0) := (others => '0');
-        signal data_in           : std_logic_vector(cFIFOWidth - 1 downto 0);       
-    begin
-    
-        -- Send the data to the correct FIFO, using the Bx field of the stub
-        pRouteInputData : process(clk_p)
-        begin
-            if rising_edge(clk_p) then
-                wr_en_array_cache <= (others => '0');
-                wr_en_array_cache(to_integer(unsigned(links_in(i).data(17 downto 15)))) <= links_in(i).valid;
-                data_in <= std_logic_vector(to_unsigned(i, 4)) & links_in(i).data(cFIFOWidth - 1 - 4 downto 0);
-            end if;
-        end process;
-
-
-        --==============================--
-        genLinkBxCache : for j in cBoxcarBx - 1 downto 0 generate
-        --==============================--
-            signal dout_cache                                                                         : std_logic_vector(cFIFOWidth - 1 downto 0);
-            signal rd_en_cache, full_cache, empty_cache, valid_cache, almost_empty_cache              : std_logic                                 := '0';
-            signal count_cache                                                                        : std_logic_vector(3 downto 0);
-            
-            signal wr_en_route, rd_en_route, empty_route, full_route, valid_route, almost_empty_route : std_logic                                 := '0';
-            signal din_route, dout_route                                                              : std_logic_vector(cFIFOWidth - 1 downto 0) := (others => '0');
-            signal count_route                                                                        : std_logic_vector(4 downto 0);
-            signal route_reset                                                                        : std_logic                                 := '0';
-
-        begin
-            
-            pTransferToRoutingFIFO : process(clk_p)
-            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 empty_cache = '0' then
-                            rd_en_cache <= '1';
-                        end if;
-                    end if;
-                    if rd_en_cache = '1' then
-                        -- Use almost empty flag to avoid underflow
-                        if almost_empty_cache = '1' then
-                            rd_en_cache <= '0';
-                        end if;
-                    end if;
-                end if;
-            end process;
-            
-            -- Enable writing of routing FIFO using the validflag of the cache FIFO
-            wr_en_route <= valid_cache;
-            din_route <= dout_cache;
-            
-            SingleLinkCacheInstance : link_agg_single_link_fifo
-            PORT MAP (
-                --- Input Ports ---
-                clk          => clk_p,
-                srst         => reset,
-                din          => data_in,
-                wr_en        => wr_en_array_cache(j),
-                rd_en        => rd_en_cache,
-                --- Output Ports ---
-                dout         => dout_cache,
-                full         => full_cache,
-                empty        => empty_cache,
-                valid        => valid_cache,
-                almost_empty => almost_empty_cache,
-                data_count   => count_cache
-            );
-            SingleLinkRoutingFIFOInstance : link_agg_single_link_fifo_fwft
-            PORT MAP (
-                --- Input Ports ---
-                clk        => clk_p,
-                srst       => route_reset, -- Reset FIFO for every packet
-                din        => din_route,
-                wr_en      => wr_en_route,
-                rd_en      => rd_en_route_array(j)(i),
-                --- Output Ports ---
-                dout       => data(j)(i),
-                full       => full_route,
-                empty      => empty_route,
-                valid      => valid_route_array(j)(i),
-                data_count => count_route
-            );
-
-            route_reset <= reset or packet_start;
-                
-        end generate;
-     end generate;
-     
-     genAggregatedFIFOs : for i in 7 downto 0 generate
-        signal pointer : integer                       := 0;
-        signal din     : std_logic_vector(cFIFOWidth - 1 downto 0) := (others => '0');
-        
-        signal wr_en, rd_en, full, empty, almost_empty, valid : std_logic                     := '0';
-        signal dout                                           : std_logic_vector(cFIFOWidth - 1 downto 0) := (others => '0');
-        signal data_count                                     : std_logic_vector(5 downto 0);
-        signal all_links_reset                                : std_logic                     := '0';
-
-     begin
-        pIteratePointer : process(clk_p)
-        begin
-            if rising_edge(clk_p) then
-                -- Loop pointer over all the links
-                if pointer = N_LINKS - 1 then
-                    pointer <= 0;
-                else
-                    pointer <= pointer + 1;
-                end if;
-                -- Readout value of FIFO which is currently pointed to
-                rd_en_route_array(i) <= (others => '0');
-                rd_en_route_array(i)(pointer) <= valid_route_array(i)(pointer);
-                din <= data(i)(pointer);
-                
-                -- If counter is at the end of a packet, then start to readout the contents of the aggregated FIFOs
-                if counter = 48 then
-                    rd_en <= '1';
-                end if;
-                if rd_en = '1' then
-                    if almost_empty = '1' then
-                        rd_en <= '0';
-                    end if;
-                end if;
-
-                if valid = '1' then
-                    links_out(i).valid <= '1';
-                    links_out(i).data <= dout;
-                    links_out(i).strobe <= '1';
-                else
-                    links_out(i).valid <= '0';
-                    links_out(i).data <= (others => '0');
-                    links_out(i).strobe <= '1';
-                end if;               
-                wr_en <= valid_route_array(i)(pointer);
-            end if;
-            
-        end process;
-        
-        
-        AllLinksFIFOInstance : link_agg_all_links_fifo
-        PORT MAP (
-            --- Input Ports ---
-            clk          => clk_p,
-            srst         => all_links_reset, -- Reset FIFO on every packet
-            din          => din,
-            wr_en        => wr_en,
-            rd_en        => rd_en,
-            --- Output Ports ---
-            dout         => dout,
-            full         => full,
-            empty        => empty,
-            almost_empty => almost_empty,
-            valid        => valid,
-            data_count   => data_count
-        );
-
-        all_links_reset <= packet_start or reset;
-
-     end generate;
-     
-     pReadoutReset : process(clk_p)
-     begin
-        if rising_edge(clk_p) then
-            if packet_start = '1' then
-                counter <= 0;
-            else
-                counter <= counter + 1;
-            end if;
-            -- If counter is at the end of a packet, then start to readout the contents of the aggregated FIFOs
-            readout_reset <= '0';
-            if counter = 64 then
-                counter <= counter;
-            elsif counter = 48 then
-                readout_reset <= '1';
-            end if;
-        end if;
-    end process pReadoutReset;
-
-end uncompressed;
diff --git a/top/firmware/hdl/LinkAggregatorIPBus.vhd b/top/firmware/hdl/LinkAggregatorIPBus.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..25bad0443646df2d35d9865bc63acb5d12653f76
--- /dev/null
+++ b/top/firmware/hdl/LinkAggregatorIPBus.vhd
@@ -0,0 +1,194 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+use work.emp_data_types.all;
+
+use work.ipbus.all;
+use work.ipbus_reg_types.all;
+
+use work.ipbus_decode_link_aggregator.all;
+
+
+entity LinkAggregatorIPBus is
+    generic (
+        N_LINKS : integer
+    );
+    port (
+        --- Input Ports ---
+        clk_p              : in std_logic;
+        packet_start       : in std_logic;
+        links_in           : in ldata(N_LINKS - 1 downto 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';
+        --- IPBus Ports ---
+        ipb_clk            : in  std_logic;
+        ipb_rst            : in  std_logic;
+        ipb_in             : in  ipb_wbus;
+        ipb_out            : out ipb_rbus
+    );
+end LinkAggregatorIPBus;
+
+
+architecture Behavorial of LinkAggregatorIPBus 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 channel_sel             : ipb_reg_v(0 downto 0);
+    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 mprocessor_monitoring_registers : ipb_reg_v(8*N_LINKS - 1 downto 0) := (others => (others => '0'));
+
+    signal masked_links : ldata(N_LINKS - 1 downto 0) := (others => LWORD_NULL);
+
+begin
+
+    --==============================--
+    -- IPBus
+    --==============================--
+
+    --==============================--
+    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_link_aggregator(ipb_in.ipb_addr),
+        ipb_to_slaves   => ipb_to_slaves,
+        ipb_from_slaves => ipb_from_slaves
+    );
+
+    --==============================--
+    channel_ctrl: entity work.ipbus_reg_v
+    --==============================--
+    generic map(
+        N_REG           => 1
+    )
+    port map(
+        clk             => ipb_clk,
+        reset           => ipb_rst,
+        ipbus_in        => ipb_to_slaves(N_SLV_CHAN_SEL),
+        ipbus_out       => ipb_from_slaves(N_SLV_CHAN_SEL),
+        q               => channel_sel,
+        qmask           => (0 => X"0000007f")
+    );
+
+    --==============================--
+    ControlInstance: entity work.ipbus_ctrlreg_v
+    --==============================--
+    generic map(
+        N_CTRL       => 1,
+        N_STAT       => 0
+    )
+    port map(
+        clk          => ipb_clk,
+        reset        => ipb_rst,
+        ipbus_in     => ipb_to_slaves(N_SLV_CONTROL),
+        ipbus_out    => ipb_from_slaves(N_SLV_CONTROL),
+        -- d         => link_aggregator_status_registers,
+        q            => control_registers
+    );
+
+    --==============================--
+    channel_select: entity work.ipbus_dc_fabric_sel
+    --==============================--
+    generic map(
+        SEL_WIDTH       => 7
+    )
+    port map(
+        clk             => ipb_clk,
+        rst             => ipb_rst,
+        sel             => channel_sel(0)(6 downto 0),
+        ipb_in          => ipb_to_slaves(N_SLV_MONITORING),
+        ipb_out         => ipb_from_slaves(N_SLV_MONITORING),
+        ipbdc_out       => ipb_chain(0),
+        ipbdc_in        => ipb_chain(8)
+    );
+
+    --==============================--
+    pInputLinkMask: process(clk_p)
+    --==============================--
+    begin
+        if rising_edge(clk_p) then
+            for i in 0 to N_LINKS - 1 loop
+                if control_registers(0)(i) = '1' then
+                    masked_links(i) <= links_in(i);
+                else
+                    masked_links(i) <= LWORD_NULL;
+                end if;
+            end loop;
+        end if;
+    end process;
+
+    --==============================--
+    gMonitoringRegisters : for i in 0 to 7 generate
+    --==============================--
+        signal ipb_to_channel   : ipb_wbus;
+        signal ipb_from_channel : ipb_rbus;
+        signal din              : ipb_reg_v(6 - 1 downto 0) := (others => (others => '0'));
+    begin
+        --==============================--
+        channel_node: entity work.ipbus_dc_node
+        --==============================--
+        generic map(
+            I_SLV       => i,
+            SEL_WIDTH   => 7,
+            PIPELINE    => false
+        )
+        port map(
+            clk         => ipb_clk,
+            rst         => ipb_rst,
+            ipb_out     => ipb_to_channel,
+            ipb_in      => ipb_from_channel,
+            ipbdc_in    => ipb_chain(i),
+            ipbdc_out   => ipb_chain(i + 1)
+        );
+
+        --==============================--
+        MProcessorMonitoringInstance: entity work.ipbus_ctrlreg_v
+        --==============================--
+        generic map(
+            N_CTRL       => 0,
+            N_STAT       => 6
+        )
+        port map(
+            clk          => ipb_clk,
+            reset        => ipb_rst,
+            ipbus_in     => ipb_to_channel,
+            ipbus_out    => ipb_from_channel,
+            d            => din
+        );
+
+        din(N_LINKS - 1 downto 0) <= mprocessor_monitoring_registers((i+1)*N_LINKS - 1 downto i*N_LINKS);
+    end generate gMonitoringRegisters;
+
+
+    --==============================--
+    LinkAggregatorInstance: entity work.LinkAggregatorCore
+    --==============================--
+    generic map (
+        N_LINKS => N_LINKS
+    )
+    port map (
+        --- Input Ports ---
+        clk_p            => clk_p,
+        reset            => control_registers(0)(N_LINKS + 1 - 1),
+        packet_start     => packet_start,
+        links_in         => masked_links,
+        --- 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
+    );
+    
+
+end Behavorial;
diff --git a/top/firmware/hdl/LinkAggregatorUncompressed.vhd b/top/firmware/hdl/LinkAggregatorUncompressed.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..ded60c3a538209065add03e305128ff5afdbbbdf
--- /dev/null
+++ b/top/firmware/hdl/LinkAggregatorUncompressed.vhd
@@ -0,0 +1,290 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+use work.emp_data_types.all;
+
+use work.ipbus.all;
+use work.ipbus_reg_types.all;
+
+entity LinkAggregator is
+  generic (
+    N_LINKS : integer
+  );
+  port (
+    --- Input Ports ---
+    clk_p              : in std_logic;
+    reset              : in std_logic;
+    packet_start       : in std_logic;
+    links_in           : in ldata(N_LINKS - 1 downto 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 ---
+    clk                : in  std_logic;
+    rst                : in  std_logic;
+    ipb_in             : in  ipb_wbus;
+    ipb_out            : out ipb_rbus;
+    non_empty_counts   : out ipb_reg_v(8*N_LINKS - 1 downto 0)
+  );
+end LinkAggregator;
+
+architecture uncompressed of LinkAggregator is
+
+    constant cFIFOWidth : integer := 64;
+
+
+    -- FIFO IP Cores
+
+    COMPONENT link_agg_single_link_fifo
+    PORT (
+        --- Input Ports ---
+        clk          : IN STD_LOGIC;
+        srst         : IN STD_LOGIC;
+        din          : IN STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
+        wr_en        : IN STD_LOGIC;
+        rd_en        : IN STD_LOGIC;
+        --- Output Ports ---
+        dout         : OUT STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
+        full         : OUT STD_LOGIC;
+        empty        : OUT STD_LOGIC;
+        almost_empty : OUT STD_LOGIC;
+        valid        : OUT STD_LOGIC;
+        data_count   : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
+        wr_rst_busy  : OUT STD_LOGIC;
+        rd_rst_busy  : OUT STD_LOGIC
+    );
+    END COMPONENT;
+    COMPONENT link_agg_single_link_fifo_fwft
+    PORT (
+        --- Input Ports ---
+        clk          : IN STD_LOGIC;
+        srst         : IN STD_LOGIC;
+        din          : IN STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
+        wr_en        : IN STD_LOGIC;
+        rd_en        : IN STD_LOGIC;
+        --- Output Ports ---
+        dout         : OUT STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
+        full         : OUT STD_LOGIC;
+        empty        : OUT STD_LOGIC;
+        almost_empty : OUT STD_LOGIC;
+        valid        : OUT STD_LOGIC;
+        data_count   : OUT STD_LOGIC_VECTOR(4 DOWNTO 0);
+        wr_rst_busy  : OUT STD_LOGIC;
+        rd_rst_busy  : OUT STD_LOGIC
+    );
+    END COMPONENT;
+    COMPONENT link_agg_all_links_fifo
+    PORT (
+        --- Input Ports ---
+        clk          : IN STD_LOGIC;
+        srst         : IN STD_LOGIC;
+        din          : IN STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
+        wr_en        : IN STD_LOGIC;
+        rd_en        : IN STD_LOGIC;
+        --- Output Ports ---
+        dout         : OUT STD_LOGIC_VECTOR(cFIFOWidth - 1 DOWNTO 0);
+        full         : OUT STD_LOGIC;
+        empty        : OUT STD_LOGIC;
+        almost_empty : OUT STD_LOGIC;
+        valid        : OUT STD_LOGIC;
+        data_count   : OUT STD_LOGIC_VECTOR(5 DOWNTO 0);
+        wr_rst_busy  : OUT STD_LOGIC;
+        rd_rst_busy  : OUT STD_LOGIC
+    );
+    END COMPONENT;
+
+    constant cBoxcarBx  : integer := 8;
+    
+    type tLinkDataArray is array(N_LINKS - 1 downto 0) of std_logic_vector(cFIFOWidth - 1 downto 0);
+    type t2DDataArray is array(cBoxcarBx - 1 downto 0) of tLinkDataArray;
+    type tEnableArray is array(cBoxcarBx - 1 downto 0) of std_logic_vector(N_LINKS - 1 downto 0);
+    
+    signal data              : t2DDataArray := (others => (others => (others => '0')));
+    signal rd_en_route_array : tEnableArray := (others => (others => '0'));
+    signal valid_route_array : tEnableArray := (others => (others => '0'));
+    signal counter           : integer      := 0;
+
+begin
+    --==============================--
+    genLinkCache : for i in N_LINKS - 1 downto 0 generate
+    --==============================--
+        signal wr_en_array_cache : std_logic_vector(cBoxcarBx - 1 downto 0) := (others => '0');
+        signal data_in           : std_logic_vector(cFIFOWidth - 1 downto 0);       
+    begin
+    
+        -- Send the data to the correct FIFO, using the Bx field of the stub
+        pRouteInputData : process(clk_p)
+        begin
+            if rising_edge(clk_p) then
+                wr_en_array_cache <= (others => '0');
+                wr_en_array_cache(to_integer(unsigned(links_in(i).data(17 downto 15)))) <= links_in(i).valid;
+                data_in <= std_logic_vector(to_unsigned(i, 4)) & links_in(i).data(cFIFOWidth - 1 - 4 downto 0);
+            end if;
+        end process;
+
+
+        --==============================--
+        genLinkBxCache : for j in cBoxcarBx - 1 downto 0 generate
+        --==============================--
+            signal dout_cache                                                                         : std_logic_vector(cFIFOWidth - 1 downto 0);
+            signal rd_en_cache, full_cache, empty_cache, valid_cache, almost_empty_cache              : std_logic                                 := '0';
+            signal count_cache                                                                        : std_logic_vector(3 downto 0);
+            
+            signal wr_en_route, rd_en_route, empty_route, full_route, valid_route, almost_empty_route : std_logic                                 := '0';
+            signal din_route, dout_route                                                              : std_logic_vector(cFIFOWidth - 1 downto 0) := (others => '0');
+            signal count_route                                                                        : std_logic_vector(4 downto 0);
+            signal route_reset                                                                        : std_logic                                 := '0';
+
+        begin
+            
+            pTransferToRoutingFIFO : process(clk_p)
+            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 empty_cache = '0' then
+                            rd_en_cache <= '1';
+                        end if;
+                    end if;
+                    if rd_en_cache = '1' then
+                        -- Use almost empty flag to avoid underflow
+                        if almost_empty_cache = '1' then
+                            rd_en_cache <= '0';
+                        end if;
+                    end if;
+                end if;
+            end process;
+            
+            -- Enable writing of routing FIFO using the validflag of the cache FIFO
+            wr_en_route <= valid_cache;
+            din_route <= dout_cache;
+            
+            SingleLinkCacheInstance : link_agg_single_link_fifo
+            PORT MAP (
+                --- Input Ports ---
+                clk          => clk_p,
+                srst         => reset,
+                din          => data_in,
+                wr_en        => wr_en_array_cache(j),
+                rd_en        => rd_en_cache,
+                --- Output Ports ---
+                dout         => dout_cache,
+                full         => full_cache,
+                empty        => empty_cache,
+                valid        => valid_cache,
+                almost_empty => almost_empty_cache,
+                data_count   => count_cache
+            );
+            SingleLinkRoutingFIFOInstance : link_agg_single_link_fifo_fwft
+            PORT MAP (
+                --- Input Ports ---
+                clk        => clk_p,
+                srst       => route_reset, -- Reset FIFO for every packet
+                din        => din_route,
+                wr_en      => wr_en_route,
+                rd_en      => rd_en_route_array(j)(i),
+                --- Output Ports ---
+                dout       => data(j)(i),
+                full       => full_route,
+                empty      => empty_route,
+                valid      => valid_route_array(j)(i),
+                data_count => count_route
+            );
+
+            route_reset <= reset or packet_start;
+                
+        end generate;
+     end generate;
+     
+     genAggregatedFIFOs : for i in 7 downto 0 generate
+        signal pointer : integer                       := 0;
+        signal din     : std_logic_vector(cFIFOWidth - 1 downto 0) := (others => '0');
+        
+        signal wr_en, rd_en, full, empty, almost_empty, valid : std_logic                     := '0';
+        signal dout                                           : std_logic_vector(cFIFOWidth - 1 downto 0) := (others => '0');
+        signal data_count                                     : std_logic_vector(5 downto 0);
+        signal all_links_reset                                : std_logic                     := '0';
+
+     begin
+        pIteratePointer : process(clk_p)
+        begin
+            if rising_edge(clk_p) then
+                -- Loop pointer over all the links
+                if pointer = N_LINKS - 1 then
+                    pointer <= 0;
+                else
+                    pointer <= pointer + 1;
+                end if;
+                -- Readout value of FIFO which is currently pointed to
+                rd_en_route_array(i) <= (others => '0');
+                rd_en_route_array(i)(pointer) <= valid_route_array(i)(pointer);
+                din <= data(i)(pointer);
+                
+                -- If counter is at the end of a packet, then start to readout the contents of the aggregated FIFOs
+                if counter = 48 then
+                    rd_en <= '1';
+                end if;
+                if rd_en = '1' then
+                    if almost_empty = '1' then
+                        rd_en <= '0';
+                    end if;
+                end if;
+
+                if valid = '1' then
+                    links_out(i).valid <= '1';
+                    links_out(i).data <= dout;
+                    links_out(i).strobe <= '1';
+                else
+                    links_out(i).valid <= '0';
+                    links_out(i).data <= (others => '0');
+                    links_out(i).strobe <= '1';
+                end if;               
+                wr_en <= valid_route_array(i)(pointer);
+            end if;
+            
+        end process;
+        
+        
+        AllLinksFIFOInstance : link_agg_all_links_fifo
+        PORT MAP (
+            --- Input Ports ---
+            clk          => clk_p,
+            srst         => all_links_reset, -- Reset FIFO on every packet
+            din          => din,
+            wr_en        => wr_en,
+            rd_en        => rd_en,
+            --- Output Ports ---
+            dout         => dout,
+            full         => full,
+            empty        => empty,
+            almost_empty => almost_empty,
+            valid        => valid,
+            data_count   => data_count
+        );
+
+        all_links_reset <= packet_start or reset;
+
+     end generate;
+     
+     pReadoutReset : process(clk_p)
+     begin
+        if rising_edge(clk_p) then
+            if packet_start = '1' then
+                counter <= 0;
+            else
+                counter <= counter + 1;
+            end if;
+            -- If counter is at the end of a packet, then start to readout the contents of the aggregated FIFOs
+            readout_reset <= '0';
+            if counter = 64 then
+                counter <= counter;
+            elsif counter = 48 then
+                readout_reset <= '1';
+            end if;
+        end if;
+    end process pReadoutReset;
+
+end uncompressed;
diff --git a/top/firmware/hdl/LinkCombiner.vhd b/top/firmware/hdl/LinkCombinerCore.vhd
similarity index 99%
rename from top/firmware/hdl/LinkCombiner.vhd
rename to top/firmware/hdl/LinkCombinerCore.vhd
index 0aea5348e383e50b16ebae8215fe3a93ececef92..fe4df5a4fd9b2800fca5d0eaecde8daf544afe8a 100644
--- a/top/firmware/hdl/LinkCombiner.vhd
+++ b/top/firmware/hdl/LinkCombinerCore.vhd
@@ -7,7 +7,7 @@ use work.gbt_module_constants.all;
 use work.dtc_link_maps.all;
 
 
-entity LinkCombiner is
+entity LinkCombinerCore is
     generic (
         N_INPUT_LINKS  : integer := 8;
         N_OUTPUT_LINKS : integer := 1
@@ -29,9 +29,9 @@ entity LinkCombiner is
         debug_super_id   : out std_logic_vector(31 downto 0);
         debug_fifo       : out std_logic_vector(31 downto 0) := (others => '0')
     );
-end LinkCombiner;
+end LinkCombinerCore;
 
-architecture Behavioral of LinkCombiner is
+architecture Behavioral of LinkCombinerCore is
 
     constant cWordWidth       : integer := 64;
     constant cOutputWordWidth : integer := 64;
diff --git a/top/firmware/hdl/LinkCombinerIPBus.vhd b/top/firmware/hdl/LinkCombinerIPBus.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..1ceb50e1d2f2b2876f663d2e44b10dfd3c3fd617
--- /dev/null
+++ b/top/firmware/hdl/LinkCombinerIPBus.vhd
@@ -0,0 +1,118 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+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.gbt_module_constants.all;
+use work.dtc_link_maps.all;
+
+
+entity LinkCombinerIPBus is
+    generic (
+        N_INPUT_LINKS  : integer := 8
+    );
+    port (
+        --- Input Ports ---
+        clk_p            : in std_logic;
+        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')));
+        lff              : in std_logic;
+        --- Ouput Ports ---
+        links_out        : out ldata(1 - 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 LinkCombinerIPBus;
+
+architecture Behavioral of LinkCombinerIPBus is
+
+    signal link_combiner_debug          : lword                               := LWORD_NULL;
+    signal link_combiner_rd_en          : std_logic_vector(0 downto 0)        := "0";
+    signal link_combiner_debug_super_id : std_logic_vector(31 downto 0);
+    signal masked_stubs                 : ldata(cNumberOfFEModules - 1 downto 0) := (others => LWORD_NULL);
+    signal masked_input          : ldata(8 - 1 downto 0)                  := (others => LWORD_NULL);
+
+    signal control_registers : ipb_reg_v(2 - 1 downto 0)  := (others => (others => '0'));
+
+begin
+
+    --==============================--
+    -- IPBus
+    --==============================--
+
+    --==============================--
+    ControlInstance: entity work.ipbus_ctrlreg_v
+    --==============================--
+    generic map(
+        N_CTRL       => 2,
+        N_STAT       => 0
+    )
+    port map(
+        clk          => ipb_clk,
+        reset        => ipb_rst,
+        ipbus_in     => ipb_in,
+        ipbus_out    => ipb_out,
+        -- d            => link_aggregator_status_registers,
+        q            => control_registers
+    );
+
+    --==============================--
+    pInputLinkMask: process(clk_p)
+    --==============================--
+    begin
+        if rising_edge(clk_p) then
+            for i in 0 to N_INPUT_LINKS - 1 loop
+                if control_registers(0)(i) = '1' then
+                    masked_input(i) <= links_in(i);
+                else
+                    masked_input(i) <= LWORD_NULL;
+                end if;
+            end loop;
+        end if;
+    end process pInputLinkMask;
+
+    --==============================--
+    pReadEnable: process(clk_p)
+    --==============================--
+    begin
+        if rising_edge(clk_p) then
+            for i in 0 downto 0 loop
+                link_combiner_rd_en(i) <= not lff and control_registers(0)(N_INPUT_LINKS + 2 - 1);
+            end loop;
+        end if;
+    end process pReadEnable;
+
+    --==============================--
+    LinkCombinerInstance : entity work.LinkCombinerCore
+    --==============================--
+    generic map (
+        N_INPUT_LINKS  => 8
+    )
+    port map (
+        --- Input Ports ---
+        clk_p            => clk_p,
+        reset            => reset,
+        output_reset     => control_registers(0)(N_INPUT_LINKS + 1 - 1),
+        output_rd_en     => link_combiner_rd_en,
+        links_in         => masked_input,
+        packet_start     => packet_start,
+        header_in        => header_in,
+        header_user_bits => control_registers(1),
+        --- Output Ports ---
+        links_out        => links_out
+        --- Debug Ports ---
+        -- debug            => link_combiner_debug,
+        -- debug_super_id   => link_combiner_debug_super_id,
+        -- debug_fifo       => link_aggregator_status_registers(2)
+    );
+
+end Behavioral;
diff --git a/top/firmware/hdl/MProcessor.vhd b/top/firmware/hdl/MProcessor.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..8f5bd62e33f16f47d2478f965e864a5047dc9c08
--- /dev/null
+++ b/top/firmware/hdl/MProcessor.vhd
@@ -0,0 +1,150 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+use work.emp_data_types.all;
+
+use work.ipbus.all;
+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.gbt_module_constants.all;
+use work.mprocessor_constants.all;
+
+
+entity MProcessor is
+    generic (
+        N_LINKS : integer
+    );
+    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'));
+        gbe_backpressure   : in  std_logic                                                        := '0';
+        --- Output Ports ---
+        link_out           : out lword                                                            := LWORD_NULL;
+        --- IPBus Ports ---
+        ipb_clk            : in  std_logic;
+        ipb_rst            : in  std_logic;
+        ipb_in             : in  ipb_wbus;
+        ipb_out            : out ipb_rbus
+    );
+end MProcessor;
+
+
+architecture Behavorial of MProcessor 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 packet_start            : std_logic                 := '0';
+    signal readout_reset           : std_logic                 := '0';
+    signal aggregated_stubs        : ldata(7 downto 0)         := (others => LWORD_NULL);
+    signal link_aggregator_input   : ldata(5 downto 0)         := (others => LWORD_NULL);
+    signal eth_link_out            : ldata(0 downto 0)         := (others => LWORD_NULL);
+
+    signal status_registers        : ipb_reg_v(1 - 1 downto 0) := (others => (others => '0'));
+    signal control_registers       : ipb_reg_v(1 - 1 downto 0) := (others => (others => '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_mprocessor(ipb_in.ipb_addr),
+        ipb_to_slaves   => ipb_to_slaves,
+        ipb_from_slaves => ipb_from_slaves
+    );
+
+    --==============================--
+    MProcessorControlInstance: 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_CSR),
+        ipbus_out => ipb_from_slaves(N_SLV_CSR),
+        d         => status_registers,
+        q         => control_registers
+    );
+
+    --==============================--
+    LinkAggregatorInstance: entity work.LinkAggregatorIPBus
+    --==============================--
+    generic map (
+        N_LINKS       => 6
+    )
+    port map (
+        --- Input Ports ---
+        clk_p         => clk_p,
+        packet_start  => packet_start,
+        links_in      => link_aggregator_input,
+        --- Output Ports ---
+        links_out     => aggregated_stubs,
+        readout_reset => readout_reset,
+        --- 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)
+    );
+
+    --==============================--
+    LinkCombinerInstance : entity work.LinkCombinerIPBus
+    --==============================--
+    generic map (
+        N_INPUT_LINKS => 8
+    )
+    port map (
+        --- Input Ports ---
+        clk_p         => clk_p,
+        reset         => readout_reset,
+        links_in      => aggregated_stubs,
+        packet_start  => packet_start,
+        header_in     => header_in,
+        lff           => gbe_backpressure,
+        --- Output Ports ---
+        links_out     => eth_link_out,
+        --- IPBus Ports ---
+        ipb_clk       => ipb_clk,
+        ipb_rst       => ipb_rst,
+        ipb_in        => ipb_to_slaves(N_SLV_LINK_COMBINER),
+        ipb_out       => ipb_from_slaves(N_SLV_LINK_COMBINER)
+    );
+
+    -- --==============================--
+    -- TrackReconstructorInstance: entity work.TrackReconstructor
+    -- --==============================--
+    -- port map(
+    --     clk_p => clk_p,
+    --     reset => readout_reset,
+    --     stubs_in => aggregated_stubs(0)
+    -- );
+
+    link_aggregator_input(N_LINKS - 1 downto 0) <= links_in;
+    link_out                                    <= eth_link_out(0);
+
+    status_registers(0)(0) <= gbe_backpressure;
+    packet_start           <= header_start_array(to_integer(unsigned(control_registers(0)(2 downto 0))))(0);
+
+end Behavorial;
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index f3205a472714bb61a134e151946996ef63a9cd21..cafdf14d4d8f2b264ffacf67a9b8094f29ac164b 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -15,32 +15,33 @@ use work.ipbus_decode_emp_payload.all;
 use work.dtc_link_maps.all;
 use work.front_end_data_types.all;
 use work.gbt_module_constants.all;
+use work.mprocessor_constants.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);
+    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);
     --- 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);
+    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);
     --- IPBus Ports ---
-    clk            : in  std_logic;
-    rst            : in  std_logic;
-    ipb_in         : in  ipb_wbus;
-    ipb_out        : out ipb_rbus;
+    clk              : in  std_logic;
+    rst              : in  std_logic;
+    ipb_in           : in  ipb_wbus;
+    ipb_out          : out ipb_rbus;
     -- KH
-    ldata_out      : out lword;
-    lff            : in std_logic
+    gbe_q            : out ldata := (others => LWORD_NULL);
+    gbe_backpressure : in  std_logic_vector(1 downto 0)
 );
 end emp_payload;
 
@@ -49,60 +50,59 @@ 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 ipb_to_slaves                : ipb_wbus_array(N_SLAVES - 1 downto 0);
+signal ipb_from_slaves              : ipb_rbus_array(N_SLAVES - 1 downto 0);
 
-signal channel_sel             : ipb_reg_v(0 downto 0);
-signal link_aggr_control       : ipb_reg_v(0 downto 0);
+signal channel_sel                  : ipb_reg_v(0 downto 0);
+signal mproc_channel_sel            : 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 ipb_chain                    : ipbdc_bus_array(cNumberOfFEModules downto 0);
+signal stubs                        : ldata(cNumberOfFEModules - 1 downto 0);
 
-signal linksout                   : ldata(cNumberOfFEModules - 1 downto 0);
-signal linkor  : lword                                    := LWORD_NULL;
+signal linksout                     : ldata(cNumberOfFEModules - 1 downto 0);
+signal linkor                       : lword                                    := LWORD_NULL;
 
 -- Histogrammer
 
-constant N_CTRL_HIST           : integer := 2;
-constant N_STAT_HIST           : integer := 2;
-
-constant bin_width             : integer := 32;
-constant input_width           : integer := 9;
-
-signal status_registers        : ipb_reg_v(N_STAT_HIST - 1 downto 0) := (others => (others => '0'));
-signal control_registers       : ipb_reg_v(N_CTRL_HIST - 1 downto 0) := (others => (others => '0'));
-signal link_aggregator_status_registers        : ipb_reg_v(4 - 1 downto 0) := (others => (others => '0'));
-signal link_aggregator_control_registers       : ipb_reg_v(4 - 1 downto 0) := (others => (others => '0'));
-
-signal trigger_window_lower    : std_logic_vector(31 downto 0)            := (others => '0');
-signal trigger_window_upper    : std_logic_vector(3 downto 0)             := (others => '0');
-signal trigger_window          : std_logic_vector(36 - 1 downto 0)        := X"0ffffffff";
-signal max_value0, max_value1  : std_logic_vector(bin_width - 1 downto 0) := (others => '0');
-signal histogram_reset         : std_logic                                := '0';
-signal hist0_stub, hist1_stub  : lword                                    := LWORD_NULL;
-signal histogram_sel           : integer                                  := 0;
-signal histogram_enable        : std_logic                                := '0';
-type tHeaderStartArray is array(cNumberOfFEModules - 1 downto 0) of std_logic_vector(1 downto 0);
-signal header_start_array      : tHeaderStartArray                        := (others => (others => '0'));
-signal aggregated_stubs        : ldata(7 downto 0)                        := (others => LWORD_NULL);
-signal eth_link_out            : ldata(0 downto 0)                        := (others => LWORD_NULL);
-signal readout_reset           : std_logic                                := '0';
-
-signal header_array            : tCICHeaderArray(cNumberOfFEModules * cNumberOfCICs - 1 downto 0) := (others => ('0', (others => '0'), (others => '0'), (others => '0')));
-
-signal link_combiner_debug          : lword                               := LWORD_NULL;
-signal link_combiner_rd_en          : std_logic_vector(0 downto 0)        := "0";
-signal link_combiner_debug_super_id : std_logic_vector(31 downto 0);
-signal masked_stubs                 : ldata(cNumberOfFEModules - 1 downto 0) := (others => LWORD_NULL);
-signal link_combiner_input          : ldata(8 - 1 downto 0)                  := (others => LWORD_NULL);
-signal packet_start                 : std_logic                              := '0';
+constant N_CTRL_HIST                : integer := 2;
+constant N_STAT_HIST                : integer := 2;
 
-begin
+constant bin_width                  : integer := 32;
+constant input_width                : integer := 9;
+
+signal status_registers             : ipb_reg_v(N_STAT_HIST - 1 downto 0) := (others => (others => '0'));
+signal control_registers            : ipb_reg_v(N_CTRL_HIST - 1 downto 0) := (others => (others => '0'));
+signal mprocessor_status_registers  : ipb_reg_v(1 - 1 downto 0)           := (others => (others => '0'));
+signal mprocessor_control_registers : ipb_reg_v(1 - 1 downto 0)           := (others => (others => '0'));
+
+signal trigger_window_lower         : std_logic_vector(31 downto 0)            := (others => '0');
+signal trigger_window_upper         : std_logic_vector(3 downto 0)             := (others => '0');
+signal trigger_window               : std_logic_vector(36 - 1 downto 0)        := X"0ffffffff";
+signal max_value0, max_value1       : std_logic_vector(bin_width - 1 downto 0) := (others => '0');
+signal histogram_reset              : std_logic                                := '0';
+signal hist0_stub, hist1_stub       : lword                                    := LWORD_NULL;
+signal histogram_sel                : integer                                  := 0;
+signal histogram_enable             : std_logic                                := '0';
+signal header_start_array           : tHeaderStartArray                        := (others => (others => '0'));
+signal aggregated_stubs             : ldata(7 downto 0)                        := (others => LWORD_NULL);
+signal eth_link_out                 : ldata(0 downto 0)                        := (others => LWORD_NULL);
+signal readout_reset                : std_logic                                := '0';
+
+signal header_array                 : tCICHeaderArray(cNumberOfFEModules * cNumberOfCICs - 1 downto 0) := (others => ('0', (others => '0'), (others => '0'), (others => '0')));
+
+signal link_combiner_debug_super_id : std_logic_vector(31 downto 0);
+signal packet_start                 : std_logic                                := '0';
 
+-- MProcessor
+constant cNumberOfMProcessors       : integer                                  := 1;
+signal mprocessor_ipb_chain         : ipbdc_bus_array(cNumberOfMProcessors downto 0);
 
+begin
+  
 --==============================--
 -- IPBus fabric
 --==============================--
@@ -125,7 +125,7 @@ port map(
 
 
 --==============================--
-channel_ctrl: entity work.ipbus_reg_v
+fe_channel_ctrl: entity work.ipbus_reg_v
 --==============================--
 generic map(
     N_REG           => 1
@@ -139,6 +139,21 @@ port map(
     qmask           => (0 => X"0000007f")
 );
 
+--==============================--
+mproc_channel_ctrl: entity work.ipbus_reg_v
+--==============================--
+generic map(
+    N_REG           => 1
+)
+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"0000007f")
+);
+
 
 --==============================--
 channel_select: entity work.ipbus_dc_fabric_sel
@@ -208,19 +223,14 @@ begin
 		ipb_out     => ipb_from_channel,
         --- Debug Ports ---
         debug_header_start => header_start_array(i),
-        debug_header_match => q(i+20).data(5 downto 4),
-        debug_aligner_state => q(i+20).data(13 downto 8)
+        debug_header_match => q(i+30).data(5 downto 4),
+        debug_aligner_state => q(i+30).data(13 downto 8)
 	);
-
-    q(i+20).valid              <= '1';
-    q(i+20).strobe             <= '1';
-    q(i+20).data(1 downto 0)   <= header_start_array(i);
-    q(i+20).data(63 downto 14) <= stubs(i).data(49 downto 0);
-
 end generate;
 
 
-linkor.data(63 downto 0) <= linksout(0).data(63 downto 0) or linksout(1).data(63 downto 0) or linksout(2).data(63 downto 0) or linksout(3).data(63 downto 0);
+linkor.data(63 downto 0) <= linksout(0).data(63 downto 0) or linksout(1).data(63 downto 0) or linksout(2).data(63 downto 0) or linksout(3).data(63 downto 0); --or linksout(4).data(63 downto 0) or linksout(5).data(63 downto 0);
+
 --==============================--
 hack: for i in 0 to cNumberOfFEModules - 1 generate
 --==============================--
@@ -263,20 +273,6 @@ histogram_sel         <= to_integer(unsigned(control_registers(1)(15 downto 5)))
 trigger_window        <= trigger_window_upper & trigger_window_lower;
 
 
---==============================--
-pRouteStubsToOutput: process(clk_p)
---==============================--
-begin
-    if rising_edge(clk_p) then
-        for i in 0 to cNumberOfFEModules - 1 loop
-            q(cDTCOutputLinkMap(i)).valid <= stubs(i).valid;
-            q(cDTCOutputLinkMap(i)).data <= stubs(i).data;
-            q(cDTCOutputLinkMap(i)).strobe <= '1';
-        end loop;
-    end if;
-end process;
-
-
 --==============================--
 pHistogram: process(clk_p)
 --==============================--
@@ -362,135 +358,71 @@ port map(
 --==============================--
 
 --==============================--
-pInputLinkMask: process(clk_p)
---==============================--
-begin
-    if rising_edge(clk_p) then
-        for i in 0 to cNumberOfFEModules - 1 loop
-            if link_aggregator_control_registers(2)(i) = '1' then
-                masked_stubs(i) <= stubs(i);
-            else
-                masked_stubs(i) <= LWORD_NULL;
-            end if;
-        end loop;
-    end if;
-end process;
-
---==============================--
-pLinkCombinerInputLinkMask: process(clk_p)
---==============================--
-begin
-    if rising_edge(clk_p) then
-        for i in 0 to 8 - 1 loop
-            if link_aggregator_control_registers(2)(cNumberOfFEModules + i) = '1' then
-                link_combiner_input(i) <= aggregated_stubs(i);
-            else
-                link_combiner_input(i) <= LWORD_NULL;
-            end if;
-        end loop;
-    end if;
-end process;
-
-
---==============================--
-LinkAggregatorInstance: entity work.LinkAggregator(compressed)
---==============================--
-generic map (
-    N_LINKS => cNumberOfFEModules
-)
-port map (
-    --- Input Ports ---
-    clk_p         => clk_p,
-    reset         => link_aggregator_control_registers(0)(0),
-    packet_start  => packet_start,
-    links_in      => masked_stubs,
-    --- Output Ports ---
-    links_out     => aggregated_stubs,
-    readout_reset => readout_reset,
-    --- Debug Ports ---
-    status_bits   => link_aggregator_status_registers(3)(15 downto 0)
-);
-
-q(31 downto 24) <= aggregated_stubs;
-
-packet_start <= header_start_array(to_integer(unsigned(link_aggregator_control_registers(2)(cNumberOfFEModules + 8 + 1 downto cNumberOfFEModules + 8))))(0);
-
---==============================--
-LinkAggregatorControlInstance: entity work.ipbus_ctrlreg_v
+mprocessor_channel_select: entity work.ipbus_dc_fabric_sel
 --==============================--
 generic map(
-    N_CTRL       => 4,
-    N_STAT       => 4
+    SEL_WIDTH       => 7
 )
 port map(
-    clk          => clk,
-    reset        => rst,
-    ipbus_in     => ipb_to_slaves(N_SLV_LINK_AGGR),
-    ipbus_out    => ipb_from_slaves(N_SLV_LINK_AGGR),
-    d            => link_aggregator_status_registers,
-    q            => link_aggregator_control_registers
-);
-
---==============================--
-LinkCombinerInstance : entity work.LinkCombiner
---==============================--
-generic map (
-    N_INPUT_LINKS  => 8,
-    N_OUTPUT_LINKS => 1
-)
-port map (
-    --- Input Ports ---
-    clk_p            => clk_p,
-    reset            => readout_reset,
-    output_reset     => link_aggregator_control_registers(1)(0),
-    output_rd_en     => link_combiner_rd_en,
-    links_in         => link_combiner_input,
-    packet_start     => packet_start,
-    header_in        => header_array,
-    header_user_bits => link_aggregator_control_registers(3),
-    --- Output Ports ---
-    links_out        => eth_link_out,
-    --- Debug Ports ---
-    debug            => link_combiner_debug,
-    debug_super_id   => link_combiner_debug_super_id,
-    debug_fifo       => link_aggregator_status_registers(2)
+    clk             => clk,
+    rst             => rst,
+    sel             => mproc_channel_sel(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)
 );
 
-q(32).valid  <= eth_link_out(0).valid;
-q(32).strobe <= '1';
-q(32).start  <= '0';
-q(32).data   <= eth_link_out(0).data;
-q(33)        <= link_combiner_debug;
-
-link_aggregator_status_registers(0) <= link_combiner_debug_super_id;
-link_aggregator_status_registers(1)(0) <= lff;
+genMProcessors : for i in 0 to cNumberOfMProcessors - 1 generate
 
+    signal ipb_to_channel        : ipb_wbus;
+    signal ipb_from_channel      : ipb_rbus;
+    constant cNumberofInputLinks : integer := 4;
 
-pLinkCombinerReadEnable: process(clk_p)
 begin
-    if rising_edge(clk_p) then
-        for i in 0 downto 0 loop
-            link_combiner_rd_en(i) <= not lff and link_aggregator_control_registers(1)(1);
-        end loop;
-    end if;
-end process pLinkCombinerReadEnable;
-
-ldata_out <= eth_link_out(0);
 
--- --==============================--
--- TrackReconstructorInstance: entity work.TrackReconstructor
--- --==============================--
--- port map(
---     clk_p => clk_p,
---     reset => readout_reset,
---     stubs_in => aggregated_stubs(0)
--- );
+    --==============================--
+    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
+    )
+    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 => header_start_array,
+        gbe_backpressure   => gbe_backpressure(i),
+        --- Output Ports ---
+        link_out           => gbe_q(i),
+        --- IPBus Ports ---
+        ipb_clk            => clk,
+        ipb_rst            => rst,
+        ipb_in             => ipb_to_channel,
+        ipb_out            => ipb_from_channel
+    );
+end generate genMProcessors;
 
 bc0     <= '0';
 gpio    <= (others => '0');
 gpio_en <= (others => '0');
 
-
-
 end rtl;
diff --git a/top/firmware/hdl/emp_project_decl.vhd b/top/firmware/hdl/emp_project_decl.vhd
index 6dbcdbab3e4ef3de4eca7f4df7bf5764de343ee6..fdc5575eec30b6c0d471caf07825f2de0b2bb1be 100644
--- a/top/firmware/hdl/emp_project_decl.vhd
+++ b/top/firmware/hdl/emp_project_decl.vhd
@@ -35,8 +35,8 @@ package emp_project_decl is
 --    0  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 225 -- Right Column
 --    1  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 226
     2  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 227
-    3  => (no_mgt, buf, no_fmt, buf, no_mgt),   --Bank 228
---    4  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 229
+    3  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 228
+    4  => (no_mgt, buf, no_fmt, buf, no_mgt),   --Bank 229
     5  => (no_mgt, buf, no_fmt, buf, no_mgt),   --Bank 230
     6  => (no_mgt, buf, no_fmt, buf, no_mgt),   --Bank 231
     7  => (no_mgt, buf, no_fmt, buf, no_mgt),   --Bank 232
@@ -59,12 +59,14 @@ package emp_project_decl is
   -- 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), 1=>(false, true, 0, false), 2=>(false, true, 0, false), 3=>(false, true, 0, false)),
+    3 => ( 0=>(false, true, 0, false), 1=>(false, true, 0, false), 2=>(false, true, 0, false), 3=>(false, true, 0, false)),
     others => kDummyRegionDataFramer
   );
 
   -- for lpgbt
   constant REGION_LPGBT_CONF : region_lpgbt_conf_array_t := (
     2  => (FEC5, DATARATE_5G12, PCS),
+    3  => (FEC5, DATARATE_5G12, PCS),
     others => kDummyRegionLpgbt
   );
 
diff --git a/top/firmware/hdl/ipbus_decode_emp_payload.vhd b/top/firmware/hdl/ipbus_decode_emp_payload.vhd
index fa879a32616a73b16afe62ff224cc3d40b8227e5..67da9d568ed2cbb86910acca8e505f877e48cb53 100644
--- a/top/firmware/hdl/ipbus_decode_emp_payload.vhd
+++ b/top/firmware/hdl/ipbus_decode_emp_payload.vhd
@@ -1,7 +1,10 @@
--- 
+-- Address decode logic for ipbus fabric
+--
+-- This file has been AUTOGENERATED from the address table - do not hand edit
+--
 -- We assume the synthesis tool is clever enough to recognise exclusive conditions
 -- in the if statement.
--- 
+--
 -- Dave Newbold, February 2011
 
 library IEEE;
@@ -14,17 +17,18 @@ package ipbus_decode_emp_payload is
   subtype ipbus_sel_t is std_logic_vector(IPBUS_SEL_WIDTH - 1 downto 0);
   function ipbus_sel_emp_payload(addr : in std_logic_vector(31 downto 0)) return ipbus_sel_t;
 
--- START automatically generated VHDL (Mon Oct 11 10:15:52 2021)
+-- START automatically generated VHDL (Thu Sep  1 14:33:48 2022)
   constant N_SLV_FE_CTRL: integer := 0;
   constant N_SLV_CSR: integer := 1;
   constant N_SLV_FE_CHAN: integer := 2;
-  constant N_SLV_LINK_AGGR: integer := 3;
-  constant N_SLV_MEM1: integer := 4;
-  constant N_SLV_MEM2: integer := 5;
-  constant N_SLAVES: integer := 6;
+  constant N_SLV_MPROC_CTRL: integer := 3;
+  constant N_SLV_MPROCESSOR: integer := 4;
+  constant N_SLV_MEM1: integer := 5;
+  constant N_SLV_MEM2: integer := 6;
+  constant N_SLAVES: integer := 7;
 -- END automatically generated VHDL
 
-    
+
 end ipbus_decode_emp_payload;
 
 package body ipbus_decode_emp_payload is
@@ -33,19 +37,21 @@ package body ipbus_decode_emp_payload is
     variable sel: ipbus_sel_t;
   begin
 
--- START automatically generated VHDL (Mon Oct 11 10:15:52 2021)
-    if    std_match(addr, "------------------00----00---0--") then
-      sel := ipbus_sel_t(to_unsigned(N_SLV_FE_CTRL, IPBUS_SEL_WIDTH)); -- fe_ctrl / base 0x00000000 / mask 0x000030c4
-    elsif std_match(addr, "------------------00----00---1--") then
-      sel := ipbus_sel_t(to_unsigned(N_SLV_CSR, IPBUS_SEL_WIDTH)); -- csr / base 0x00000004 / mask 0x000030c4
-    elsif std_match(addr, "------------------00----01------") then
-      sel := ipbus_sel_t(to_unsigned(N_SLV_FE_CHAN, IPBUS_SEL_WIDTH)); -- fe_chan / base 0x00000040 / mask 0x000030c0
-    elsif std_match(addr, "------------------00----10------") then
-      sel := ipbus_sel_t(to_unsigned(N_SLV_LINK_AGGR, IPBUS_SEL_WIDTH)); -- link_aggr / base 0x00000080 / mask 0x000030c0
-    elsif std_match(addr, "------------------01------------") then
-      sel := ipbus_sel_t(to_unsigned(N_SLV_MEM1, IPBUS_SEL_WIDTH)); -- mem1 / base 0x00001000 / mask 0x00003000
-    elsif std_match(addr, "------------------10------------") then
-      sel := ipbus_sel_t(to_unsigned(N_SLV_MEM2, IPBUS_SEL_WIDTH)); -- mem2 / base 0x00002000 / mask 0x00003000
+-- START automatically generated VHDL (Thu Sep  1 14:33:48 2022)
+    if    std_match(addr, "------------------00--0000000000") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_FE_CTRL, IPBUS_SEL_WIDTH)); -- fe_ctrl / base 0x00000000 / mask 0x000033ff
+    elsif std_match(addr, "------------------00--00000001--") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_CSR, IPBUS_SEL_WIDTH)); -- csr / base 0x00000004 / mask 0x000033fc
+    elsif std_match(addr, "------------------00--0001------") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_FE_CHAN, IPBUS_SEL_WIDTH)); -- fe_chan / base 0x00000040 / mask 0x000033c0
+    elsif std_match(addr, "------------------00--0111111111") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_MPROC_CTRL, IPBUS_SEL_WIDTH)); -- mproc_ctrl / base 0x000001ff / mask 0x000033ff
+    elsif std_match(addr, "------------------00--100-------") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_MPROCESSOR, IPBUS_SEL_WIDTH)); -- mprocessor / base 0x00000200 / mask 0x00003380
+    elsif std_match(addr, "------------------01--0---------") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_MEM1, IPBUS_SEL_WIDTH)); -- mem1 / base 0x00001000 / mask 0x00003200
+    elsif std_match(addr, "------------------10--0---------") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_MEM2, IPBUS_SEL_WIDTH)); -- mem2 / base 0x00002000 / mask 0x00003200
 -- END automatically generated VHDL
 
     else
diff --git a/top/firmware/hdl/ipbus_decode_link_aggregator.vhd b/top/firmware/hdl/ipbus_decode_link_aggregator.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..f7f0f178ea0cd7089fdd2a2965ca4e618e03e1d5
--- /dev/null
+++ b/top/firmware/hdl/ipbus_decode_link_aggregator.vhd
@@ -0,0 +1,53 @@
+-- Address decode logic for ipbus fabric
+--
+-- This file has been AUTOGENERATED from the address table - do not hand edit
+--
+-- We assume the synthesis tool is clever enough to recognise exclusive conditions
+-- in the if statement.
+--
+-- Dave Newbold, February 2011
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use ieee.numeric_std.all;
+
+package ipbus_decode_link_aggregator is
+
+  constant IPBUS_SEL_WIDTH: positive := 2;
+  subtype ipbus_sel_t is std_logic_vector(IPBUS_SEL_WIDTH - 1 downto 0);
+  function ipbus_sel_link_aggregator(addr : in std_logic_vector(31 downto 0)) return ipbus_sel_t;
+
+-- START automatically generated VHDL (Fri Aug 26 18:31:19 2022)
+  constant N_SLV_CHAN_SEL: integer := 0;
+  constant N_SLV_CONTROL: integer := 1;
+  constant N_SLV_MONITORING: integer := 2;
+  constant N_SLAVES: integer := 3;
+-- END automatically generated VHDL
+
+
+end ipbus_decode_link_aggregator;
+
+package body ipbus_decode_link_aggregator is
+
+  function ipbus_sel_link_aggregator(addr : in std_logic_vector(31 downto 0)) return ipbus_sel_t is
+    variable sel: ipbus_sel_t;
+  begin
+
+-- START automatically generated VHDL (Fri Aug 26 18:31:19 2022)
+    if    std_match(addr, "----------------------------0--0") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_CHAN_SEL, IPBUS_SEL_WIDTH)); -- chan_sel / base 0x00000000 / mask 0x00000009
+    elsif std_match(addr, "----------------------------0--1") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_CONTROL, IPBUS_SEL_WIDTH)); -- control / base 0x00000001 / mask 0x00000009
+    elsif std_match(addr, "----------------------------1---") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_MONITORING, IPBUS_SEL_WIDTH)); -- monitoring / base 0x00000008 / mask 0x00000008
+-- END automatically generated VHDL
+
+    else
+        sel := ipbus_sel_t(to_unsigned(N_SLAVES, IPBUS_SEL_WIDTH));
+    end if;
+
+    return sel;
+
+  end function ipbus_sel_link_aggregator;
+
+end ipbus_decode_link_aggregator;
diff --git a/top/firmware/hdl/ipbus_decode_mprocessor.vhd b/top/firmware/hdl/ipbus_decode_mprocessor.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..1f97d1fac6f828b144c74d8d1cd4f4f5da6ba904
--- /dev/null
+++ b/top/firmware/hdl/ipbus_decode_mprocessor.vhd
@@ -0,0 +1,53 @@
+-- Address decode logic for ipbus fabric
+--
+-- This file has been AUTOGENERATED from the address table - do not hand edit
+--
+-- We assume the synthesis tool is clever enough to recognise exclusive conditions
+-- in the if statement.
+--
+-- Dave Newbold, February 2011
+
+library IEEE;
+use IEEE.STD_LOGIC_1164.all;
+use ieee.numeric_std.all;
+
+package ipbus_decode_mprocessor is
+
+  constant IPBUS_SEL_WIDTH: positive := 2;
+  subtype ipbus_sel_t is std_logic_vector(IPBUS_SEL_WIDTH - 1 downto 0);
+  function ipbus_sel_mprocessor(addr : in std_logic_vector(31 downto 0)) return ipbus_sel_t;
+
+-- START automatically generated VHDL (Fri Aug 26 18:31:27 2022)
+  constant N_SLV_LINK_AGGREGATOR: integer := 0;
+  constant N_SLV_LINK_COMBINER: integer := 1;
+  constant N_SLV_CSR: integer := 2;
+  constant N_SLAVES: integer := 3;
+-- END automatically generated VHDL
+
+
+end ipbus_decode_mprocessor;
+
+package body ipbus_decode_mprocessor is
+
+  function ipbus_sel_mprocessor(addr : in std_logic_vector(31 downto 0)) return ipbus_sel_t is
+    variable sel: ipbus_sel_t;
+  begin
+
+-- START automatically generated VHDL (Fri Aug 26 18:31:27 2022)
+    if    std_match(addr, "--------------------------0-----") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_LINK_AGGREGATOR, IPBUS_SEL_WIDTH)); -- link_aggregator / base 0x00000000 / mask 0x00000020
+    elsif std_match(addr, "--------------------------1---0-") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_LINK_COMBINER, IPBUS_SEL_WIDTH)); -- link_combiner / base 0x00000020 / mask 0x00000022
+    elsif std_match(addr, "--------------------------1---1-") then
+      sel := ipbus_sel_t(to_unsigned(N_SLV_CSR, IPBUS_SEL_WIDTH)); -- csr / base 0x00000022 / mask 0x00000022
+-- END automatically generated VHDL
+
+    else
+        sel := ipbus_sel_t(to_unsigned(N_SLAVES, IPBUS_SEL_WIDTH));
+    end if;
+
+    return sel;
+
+  end function ipbus_sel_mprocessor;
+
+end ipbus_decode_mprocessor;
diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index aa5099fe77b2b8f5ac4cc9fccbfafc9980d18a52..d0ca6517cd88b2c93ed21c23763bf86053a0588d 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -10,5 +10,5 @@ package dtc_link_maps is
     constant cDTCInputLinkMap     : tDTCInputLinkMap := (8, 9, 10, 11);
 
     type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
-    constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (12, 13, 14, 15);
+    constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (16, 17, 18, 19);
 end package dtc_link_maps;
diff --git a/top/firmware/hdl/mprocessor_constants.vhd b/top/firmware/hdl/mprocessor_constants.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..90f2f75fb2499e65ab77d2c5c22bf05e87624425
--- /dev/null
+++ b/top/firmware/hdl/mprocessor_constants.vhd
@@ -0,0 +1,11 @@
+library IEEE;
+use IEEE.STD_LOGIC_1164.ALL;
+use IEEE.NUMERIC_STD.ALL;
+
+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);
+    
+end package mprocessor_constants;
\ No newline at end of file