From dd2c23d4cd977fc3da4ba8e9901316a229ee0a0a Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Tue, 18 Jul 2023 18:13:48 +0200
Subject: [PATCH 001/109] Initial commit

---
 dependencies.yml                 |  2 +-
 top/firmware/cfg/top.dep         |  4 ++--
 top/firmware/hdl/emp_payload.vhd |  6 +++---
 top/firmware/hdl/link_maps.vhd   | 30 +++++++++++++++++++++++++++---
 4 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/dependencies.yml b/dependencies.yml
index 0cbe131c..169f1b66 100644
--- a/dependencies.yml
+++ b/dependencies.yml
@@ -45,7 +45,7 @@ sources:
         url: https://gitlab.cern.ch/gbtsc-fpga-support/gbt-sc.git
 
     dtc:
-        branch: master
+        branch: feature/heterogeneous-dtc
         url: https://gitlab.cern.ch/cms-tracker-phase2-data-processing/BE_firmware/dtc.git
 
     dtc-stub-processing:
diff --git a/top/firmware/cfg/top.dep b/top/firmware/cfg/top.dep
index 2b37dc34..2a604b26 100644
--- a/top/firmware/cfg/top.dep
+++ b/top/firmware/cfg/top.dep
@@ -1,6 +1,6 @@
 include -c histogram:top histogram.dep
-include -c dtc:dtc-fe/2S/5G-FEC12 module.dep
-include -c dtc:dtc-fe/2S/5G-FEC12 framer.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
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 9830d592..41590672 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -205,17 +205,17 @@ begin
         LinkInterfaceInstance : entity work.LinkInterface
         --==============================--
         generic map (
-            module_type => "2S"
+            module_type => cDTCInputLinkMap(i).module_type
         )
         port map (
             --- Input Ports ---
             clk_p               => clk_p,
             clk40               => clk40,
-            link_in             => d(cDTCInputLinkMap(i)),
+            link_in             => d(cDTCInputLinkMap(i).index),
             daq_read            => daq_read(i),
             global_fcmd         => global_fcmd,
             --- Output Ports ---
-            link_out            => q(cDTCInputLinkMap(i)),
+            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),
diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index d0ca6517..711c7cec 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -1,14 +1,38 @@
 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 := 4;
     constant cNumberOfOutputLinks : integer := 4;
 
-    type tDTCInputLinkMap is array(0 to cNumberOfFEModules - 1) of integer;
-    constant cDTCInputLinkMap     : tDTCInputLinkMap := (8, 9, 10, 11);
+    type tDTCInputLinkMap is array(0 to cNumberOfFEModules - 1) of tDTCInputLinkConfig;
+    constant cDTCInputLinkMap     : tDTCInputLinkMap := (
+        0 => (8,  "2S", "CIC2"),
+        1 => (9,  "2S", "CIC2"),
+        2 => (10, "2S", "CIC2"),
+        3 => (11, "2S", "CIC2")
+    );
 
     type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
-    constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (16, 17, 18, 19);
+    constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (
+        16, 17, 18, 19
+    );
+
+    function selectModuleTypeFromChannel(channel : in integer) return string;
 end package dtc_link_maps;
+
+package body dtc_link_maps is
+
+    function selectModuleTypeFromChannel(channel : in integer) return string is
+    begin
+        for i in 0 to cDTCInputLinkMap'length - 1 loop
+            if cDTCInputLinkMap(i).index = channel then
+                return cDTCInputLinkMap(i).module_type;
+            end if;
+        end loop;
+    end selectModuleTypeFromChannel;
+
+end package body dtc_link_maps;
-- 
GitLab


From 800420cb0a28780f9585c657972cc72f21ce896a Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Tue, 18 Jul 2023 19:23:11 +0200
Subject: [PATCH 002/109] Removed unnecessary includes

---
 common/firmware/hdl/LinkCombinerCore.vhd  | 3 ---
 common/firmware/hdl/LinkCombinerIPBus.vhd | 3 ---
 common/firmware/hdl/MProcessor.vhd        | 3 ---
 top/firmware/hdl/emp_payload.vhd          | 1 -
 4 files changed, 10 deletions(-)

diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index 54a09f1e..c1c845c8 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -2,10 +2,7 @@ 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.gbt_module_constants.all;
 use work.dtc_link_maps.all;
-use work.dtc_data_types.all;
 use work.dtc_constants.all;
 
 
diff --git a/common/firmware/hdl/LinkCombinerIPBus.vhd b/common/firmware/hdl/LinkCombinerIPBus.vhd
index 18a08325..e3d76a66 100644
--- a/common/firmware/hdl/LinkCombinerIPBus.vhd
+++ b/common/firmware/hdl/LinkCombinerIPBus.vhd
@@ -6,10 +6,7 @@ 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;
-use work.dtc_data_types.all;
 use work.dtc_constants.all;
 
 
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 27f71765..5f507a93 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -9,10 +9,7 @@ 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;
-use work.dtc_data_types.all;
 use work.dtc_constants.all;
 
 
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 41590672..17325913 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -14,7 +14,6 @@ use work.emp_slink_types.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;
 use work.dtc_constants.all;
 use work.dtc_data_types.all;
-- 
GitLab


From b850e1c3316f54cbd49618f78cc6b43262665f82 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Tue, 18 Jul 2023 20:50:23 +0200
Subject: [PATCH 003/109] Reincluded library

---
 common/firmware/hdl/LinkCombinerCore.vhd  | 1 +
 common/firmware/hdl/LinkCombinerIPBus.vhd | 1 +
 common/firmware/hdl/MProcessor.vhd        | 1 +
 3 files changed, 3 insertions(+)

diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index c1c845c8..0a217957 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -4,6 +4,7 @@ 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;
 
 
 entity LinkCombinerCore is
diff --git a/common/firmware/hdl/LinkCombinerIPBus.vhd b/common/firmware/hdl/LinkCombinerIPBus.vhd
index e3d76a66..c8136716 100644
--- a/common/firmware/hdl/LinkCombinerIPBus.vhd
+++ b/common/firmware/hdl/LinkCombinerIPBus.vhd
@@ -8,6 +8,7 @@ use work.ipbus_reg_types.all;
 
 use work.dtc_link_maps.all;
 use work.dtc_constants.all;
+use work.dtc_data_types.all;
 
 
 entity LinkCombinerIPBus is
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 5f507a93..29ee4cce 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -11,6 +11,7 @@ use work.ipbus_decode_mprocessor.all;
 use work.dtc_link_maps.all;
 use work.mprocessor_constants.all;
 use work.dtc_constants.all;
+use work.dtc_data_types.all;
 
 
 entity MProcessor is
-- 
GitLab


From e812a616cf95bc40d1224fb91c9b3a925d597cea Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Tue, 18 Jul 2023 21:03:24 +0200
Subject: [PATCH 004/109] Fixed error

---
 top/firmware/hdl/emp_payload.vhd | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 17325913..20aecfaa 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -287,8 +287,8 @@ begin
     begin
         if rising_edge(clk_p) then
             for i in 0 to cNumberOfOutputLinks - 1 loop
-                q(cDTCOutputLinkMap(i)).valid  <= d(cDTCInputLinkMap(i)).valid;
-                q(cDTCOutputLinkMap(i)).data   <= d(cDTCInputLinkMap(i)).data;
+                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;
         end if;
-- 
GitLab


From c7821632b8a0b9314b73effb9da0251a28c30b5d Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Tue, 18 Jul 2023 22:58:15 +0200
Subject: [PATCH 005/109] Added data rate

---
 top/firmware/hdl/emp_payload.vhd |  3 ++-
 top/firmware/hdl/link_maps.vhd   | 20 ++++++++++++++++----
 2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 20aecfaa..ec50cba8 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -204,7 +204,8 @@ begin
         LinkInterfaceInstance : entity work.LinkInterface
         --==============================--
         generic map (
-            module_type => cDTCInputLinkMap(i).module_type
+            module_type => cDTCInputLinkMap(i).module_type,
+            data_rate   => cDTCInputLinkMap(i).data_rate
         )
         port map (
             --- Input Ports ---
diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index 711c7cec..1490a95c 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -10,10 +10,10 @@ package dtc_link_maps is
 
     type tDTCInputLinkMap is array(0 to cNumberOfFEModules - 1) of tDTCInputLinkConfig;
     constant cDTCInputLinkMap     : tDTCInputLinkMap := (
-        0 => (8,  "2S", "CIC2"),
-        1 => (9,  "2S", "CIC2"),
-        2 => (10, "2S", "CIC2"),
-        3 => (11, "2S", "CIC2")
+        0 => (8,  "2S", 5, "CIC2"),
+        1 => (9,  "2S", 5, "CIC2"),
+        2 => (10, "2S", 5, "CIC2"),
+        3 => (11, "2S", 5, "CIC2")
     );
 
     type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
@@ -22,6 +22,7 @@ package dtc_link_maps is
     );
 
     function selectModuleTypeFromChannel(channel : in integer) return string;
+    function selectDataRateFromChannel(channel : in integer) return integer;
 end package dtc_link_maps;
 
 package body dtc_link_maps is
@@ -35,4 +36,15 @@ package body dtc_link_maps is
         end loop;
     end selectModuleTypeFromChannel;
 
+    function selectDataRateFromChannel(channel : in integer) return integer is
+        variable data_rate : integer;
+    begin
+        for i in 0 to cDTCInputLinkMap'length - 1 loop
+            if cDTCInputLinkMap(i).index = channel then
+                data_rate := cDTCInputLinkMap(i).data_rate;
+            end if;
+        end loop;
+        return data_rate;
+    end selectDataRateFromChannel;
+
 end package body dtc_link_maps;
-- 
GitLab


From 726b708d4fb4167bfd7e133c37701ed479974fc6 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Wed, 19 Jul 2023 06:23:47 +0200
Subject: [PATCH 006/109] Updated link maps

---
 top/firmware/hdl/link_maps.vhd | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index 1490a95c..aa1f7b58 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -28,12 +28,14 @@ end package dtc_link_maps;
 package body dtc_link_maps is
 
     function selectModuleTypeFromChannel(channel : in integer) return string is
+        variable module_type : string(1 to 2);
     begin
         for i in 0 to cDTCInputLinkMap'length - 1 loop
             if cDTCInputLinkMap(i).index = channel then
-                return cDTCInputLinkMap(i).module_type;
+                module_type := cDTCInputLinkMap(i).module_type;
             end if;
         end loop;
+        return module_type;
     end selectModuleTypeFromChannel;
 
     function selectDataRateFromChannel(channel : in integer) return integer is
-- 
GitLab


From c8926374c5356e749329dd728661780d865993e6 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Wed, 19 Jul 2023 07:03:11 +0200
Subject: [PATCH 007/109] Commented out unused links

---
 top/firmware/hdl/emp_project_decl.vhd | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/top/firmware/hdl/emp_project_decl.vhd b/top/firmware/hdl/emp_project_decl.vhd
index c4e9c7c1..cb139412 100644
--- a/top/firmware/hdl/emp_project_decl.vhd
+++ b/top/firmware/hdl/emp_project_decl.vhd
@@ -37,7 +37,7 @@ 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  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 228
+    -- 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
@@ -61,14 +61,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, 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)),
     others => kDummyRegionDataFramer
   );
 
   -- for lpgbt
   constant REGION_LPGBT_CONF : region_lpgbt_conf_array_t := (
     2  => (FEC5, DATARATE_5G12, PCS),
-    3  => (FEC5, DATARATE_5G12, PCS),
+    -- 3  => (FEC5, DATARATE_5G12, PCS),
     others => kDummyRegionLpgbt
   );
 
-- 
GitLab


From 98db268cbc425cbea73ae7ebb15f9d9dc5676ad5 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Wed, 19 Jul 2023 08:36:43 +0200
Subject: [PATCH 008/109] Removed functions from link maps

---
 top/firmware/hdl/link_maps.vhd | 29 +----------------------------
 1 file changed, 1 insertion(+), 28 deletions(-)

diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index aa1f7b58..1c6e5aea 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -20,33 +20,6 @@ package dtc_link_maps is
     constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (
         16, 17, 18, 19
     );
-
-    function selectModuleTypeFromChannel(channel : in integer) return string;
-    function selectDataRateFromChannel(channel : in integer) return integer;
+    
 end package dtc_link_maps;
 
-package body dtc_link_maps is
-
-    function selectModuleTypeFromChannel(channel : in integer) return string is
-        variable module_type : string(1 to 2);
-    begin
-        for i in 0 to cDTCInputLinkMap'length - 1 loop
-            if cDTCInputLinkMap(i).index = channel then
-                module_type := cDTCInputLinkMap(i).module_type;
-            end if;
-        end loop;
-        return module_type;
-    end selectModuleTypeFromChannel;
-
-    function selectDataRateFromChannel(channel : in integer) return integer is
-        variable data_rate : integer;
-    begin
-        for i in 0 to cDTCInputLinkMap'length - 1 loop
-            if cDTCInputLinkMap(i).index = channel then
-                data_rate := cDTCInputLinkMap(i).data_rate;
-            end if;
-        end loop;
-        return data_rate;
-    end selectDataRateFromChannel;
-
-end package body dtc_link_maps;
-- 
GitLab


From b749ab796dbe16141af87e550503d24dd72412bb Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Wed, 19 Jul 2023 13:16:57 +0200
Subject: [PATCH 009/109] Updated link maps

---
 top/firmware/hdl/link_maps.vhd | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index 1c6e5aea..e400497d 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -12,14 +12,14 @@ package dtc_link_maps is
     constant cDTCInputLinkMap     : tDTCInputLinkMap := (
         0 => (8,  "2S", 5, "CIC2"),
         1 => (9,  "2S", 5, "CIC2"),
-        2 => (10, "2S", 5, "CIC2"),
-        3 => (11, "2S", 5, "CIC2")
+        -- 2 => (10, "2S", 5, "CIC2"),
+        2 => (11, "2S", 5, "CIC2")
     );
 
     type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
     constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (
         16, 17, 18, 19
     );
-    
+
 end package dtc_link_maps;
 
-- 
GitLab


From f7f1596e73c18e37da7ffa59d6b4ad2b4e6d5483 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Wed, 19 Jul 2023 13:22:47 +0200
Subject: [PATCH 010/109] Corrected number of links

---
 top/firmware/hdl/link_maps.vhd | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index e400497d..94784865 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -5,8 +5,8 @@ use work.dtc_link_maps_func.all;
 
 package dtc_link_maps is
 
-    constant cNumberOfFEModules   : integer := 4;
-    constant cNumberOfOutputLinks : integer := 4;
+    constant cNumberOfFEModules   : integer := 3;
+    constant cNumberOfOutputLinks : integer := 3;
 
     type tDTCInputLinkMap is array(0 to cNumberOfFEModules - 1) of tDTCInputLinkConfig;
     constant cDTCInputLinkMap     : tDTCInputLinkMap := (
@@ -18,7 +18,7 @@ package dtc_link_maps is
 
     type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
     constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (
-        16, 17, 18, 19
+        16, 17, 18
     );
 
 end package dtc_link_maps;
-- 
GitLab


From 18785b91b841fc1fc3e556d0b98c6cc8f63a713b Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Wed, 19 Jul 2023 13:41:21 +0200
Subject: [PATCH 011/109] Added cic type in payload

---
 top/firmware/hdl/emp_payload.vhd | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index ec50cba8..755e52af 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -205,7 +205,8 @@ begin
         --==============================--
         generic map (
             module_type => cDTCInputLinkMap(i).module_type,
-            data_rate   => cDTCInputLinkMap(i).data_rate
+            data_rate   => cDTCInputLinkMap(i).data_rate,
+            cic_type   => cDTCInputLinkMap(i).cic_type
         )
         port map (
             --- Input Ports ---
-- 
GitLab


From 9de7be230ba04a74591310129c33791916280cc9 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Wed, 19 Jul 2023 13:55:18 +0200
Subject: [PATCH 012/109] Removed hard-coded constants

---
 top/firmware/hdl/emp_payload.vhd | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 755e52af..1134b68d 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -206,7 +206,7 @@ begin
         generic map (
             module_type => cDTCInputLinkMap(i).module_type,
             data_rate   => cDTCInputLinkMap(i).data_rate,
-            cic_type   => cDTCInputLinkMap(i).cic_type
+            cic_type    => cDTCInputLinkMap(i).cic_type
         )
         port map (
             --- Input Ports ---
@@ -302,14 +302,14 @@ begin
     LinkMonitorInterfaceInstance : entity work.LinkMonitorInterface
     --==============================--
     generic map (
-        N_LINKS => 4
+        N_LINKS => cNumberOfFEModules
     )
     port map (
         --- Input Ports ---
         clk_p => clk_p,
-        stubs => stubs(3 downto 0),
-        headers => header_array(7 downto 0),
-        header_start => header_start_array(7 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,
@@ -346,7 +346,7 @@ begin
 
         signal ipb_to_channel        : ipb_wbus;
         signal ipb_from_channel      : ipb_rbus;
-        constant cNumberofInputLinks : integer := 4;
+        constant cNumberofInputLinks : integer := cNumberOfFEModules;
 
     begin
 
-- 
GitLab


From 30355ec960b750e6d9ae18c99af2cb72d37bb84e Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Wed, 2 Aug 2023 14:54:39 +0200
Subject: [PATCH 013/109] Update file link_maps.vhd

---
 top/firmware/hdl/link_maps.vhd | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index 94784865..6fcd7880 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -5,20 +5,20 @@ use work.dtc_link_maps_func.all;
 
 package dtc_link_maps is
 
-    constant cNumberOfFEModules   : integer := 3;
-    constant cNumberOfOutputLinks : integer := 3;
+    constant cNumberOfFEModules   : integer := 4;
+    constant cNumberOfOutputLinks : integer := 4;
 
     type tDTCInputLinkMap is array(0 to cNumberOfFEModules - 1) of tDTCInputLinkConfig;
     constant cDTCInputLinkMap     : tDTCInputLinkMap := (
         0 => (8,  "2S", 5, "CIC2"),
         1 => (9,  "2S", 5, "CIC2"),
-        -- 2 => (10, "2S", 5, "CIC2"),
+        2 => (10, "2S", 5, "CIC2"),
         2 => (11, "2S", 5, "CIC2")
     );
 
     type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
     constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (
-        16, 17, 18
+        16, 17, 18, 19
     );
 
 end package dtc_link_maps;
-- 
GitLab


From d0693cea0b3b23a7a6ad228aac6757c1ef315904 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Wed, 2 Aug 2023 15:17:45 +0200
Subject: [PATCH 014/109] Update file link_maps.vhd

---
 top/firmware/hdl/link_maps.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index 6fcd7880..ee8248ca 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -13,7 +13,7 @@ package dtc_link_maps is
         0 => (8,  "2S", 5, "CIC2"),
         1 => (9,  "2S", 5, "CIC2"),
         2 => (10, "2S", 5, "CIC2"),
-        2 => (11, "2S", 5, "CIC2")
+        3 => (11, "2S", 5, "CIC2")
     );
 
     type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
-- 
GitLab


From e3d8fc37e03d96b1bb7bb6a10b784cc4299c1412 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Thu, 3 Aug 2023 11:05:09 +0200
Subject: [PATCH 015/109] Added constant in line with DTC

---
 top/addr_table/emp_payload.xml   |  5 +++--
 top/firmware/hdl/emp_payload.vhd | 23 +++++++++++++----------
 2 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index f37df612..0eb42100 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -1,7 +1,8 @@
 <node description="Payload ipbus registers and RAM" fwinfo="endpoint">
 
-    <node id="fe" address="0x0000" description="FE channel select" fwinfo="endpoint;width=0">
-        <node id="chan_sel" mask="0x7f"/>
+    <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"/>
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 1134b68d..6cdb337d 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -58,7 +58,8 @@ 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 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_channel_sel            : ipb_reg_v(0 downto 0);
     signal link_aggr_control            : ipb_reg_v(0 downto 0);
 
@@ -136,21 +137,23 @@ begin
     );
 
     --==============================--
-    channel_select : entity work.ipbus_dc_fabric_sel
+    channel_ctrl : entity work.ipbus_ctrlreg_v
     --==============================--
-    generic map (
-        SEL_WIDTH => 7
+    generic map(
+        N_CTRL    => 1,
+        N_STAT    => 1
     )
     port map (
         clk       => clk,
-        rst       => rst,
-        sel       => channel_sel(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)
+        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));
+
     --==============================--
     mproc_channel_ctrl: entity work.ipbus_reg_v
     --==============================--
-- 
GitLab


From b4b618ff1087bf011c5a0cb77951b4006e51c168 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Thu, 3 Aug 2023 11:19:28 +0200
Subject: [PATCH 016/109] Fixed syntax error

---
 top/firmware/hdl/emp_payload.vhd | 33 ++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 6cdb337d..72982d69 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -122,22 +122,7 @@ begin
         );
 
     --==============================--
-    fe_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_FE),
-        ipbus_out => ipb_from_slaves(N_SLV_FE),
-        q         => channel_sel,
-        qmask     => (0 => X"0000007f")
-    );
-
-    --==============================--
-    channel_ctrl : entity work.ipbus_ctrlreg_v
+    fe_channel_ctrl : entity work.ipbus_ctrlreg_v
     --==============================--
     generic map(
         N_CTRL    => 1,
@@ -154,6 +139,22 @@ begin
 
     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_channel_ctrl: entity work.ipbus_reg_v
     --==============================--
-- 
GitLab


From 9d35a53dc6f0ad2c26fb164a67cb68bb5f91fffb Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 15 Aug 2023 17:55:27 +0200
Subject: [PATCH 017/109] Update file LinkCombinerCore.vhd

---
 common/firmware/hdl/LinkCombinerCore.vhd | 55 ++++++++++++------------
 1 file changed, 28 insertions(+), 27 deletions(-)

diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index 0a217957..ba692877 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -5,6 +5,7 @@ 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;
 
 
 entity LinkCombinerCore is
@@ -87,7 +88,12 @@ 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_links_valid                                              : std_logic_vector(N_INPUT_LINKS - 1 downto 0)       := (others => '0');
+    signal all_input_links_valid                                          : std_logic                                          := '0';
+    signal all_input_links_valid_previous                                 : std_logic                                          := '0';
+    signal start_output                                                   : std_logic                                          := '0';
+    
     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');
@@ -113,7 +119,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');
 
@@ -124,6 +129,7 @@ architecture Behavioral of LinkCombinerCore is
 
 begin
 
+
     --==============================--
     genInputLinkBuffers : for i in 0 to N_INPUT_LINKS - 1 generate
     --==============================--
@@ -132,6 +138,8 @@ begin
         signal wr_en : std_logic                                 := '0';
     begin
     
+        input_links_valid(i) <= links_in(i).valid;
+    
         --==============================--
         InputLinkBufferInstance : link_agg_all_links_fifo
         --==============================--
@@ -246,13 +254,21 @@ begin
     --==============================--
     begin
         if rising_edge(clk_p) then
-            if packet_start = '1' then
+            if start_output = '1' then
                 input_data_valid <= '1';
             else
                 if reset = '1' then
                     input_data_valid <= '0';
                 end if;
             end if;
+            
+            all_input_links_valid <= and_reduce(input_links_valid);
+            all_input_links_valid_previous <= all_input_links_valid;
+            if all_input_links_valid = '0' and all_input_links_valid_previous = '1' then
+                start_output <= '1';
+            else
+                start_output <= '0';
+            end if;
         end if;
     end process pValidDataChecker;
     
@@ -266,7 +282,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
@@ -284,14 +300,16 @@ begin
                     end if;
                 end if;
             else
+                output_pointer <= 0;
+                next_pointer_location := 0;
                 input_rd_en_array(output_pointer) <= '0';
             end if;
             
             -- Packet control bits logic
-            if packet_start = '1' then
+            if start_output = '1' then
                 counter <= 0;
             else
-                if counter < 4 then
+                if counter < 3 then
                     counter <= counter + 1;
                 else
                     counter <= counter;
@@ -299,7 +317,7 @@ 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);
+            output_wr_en   <= input_valid_array(output_pointer_buffered) and (not reset);
             
             
             if reset = '1' then
@@ -323,22 +341,11 @@ begin
                 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_din_buf(11 downto 0) <= bcid_sr(bcid_sr'high);
+                output_din_buf(19 downto 12) <= std_logic_vector(packet_stub_count_previous);
                 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 <= (others => '0');
-                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;
             
@@ -349,7 +356,6 @@ begin
     --==============================--
     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
@@ -357,11 +363,6 @@ begin
                 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
-- 
GitLab


From afb6779ca67ad6842b8e0bae9f1ac59cc85cfb3b Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Mon, 28 Aug 2023 21:24:42 +0200
Subject: [PATCH 018/109] Increased number of modules to 12

---
 top/firmware/hdl/emp_payload.vhd      | 17 ++++++----
 top/firmware/hdl/emp_project_decl.vhd | 47 +++++++++++++++++++--------
 top/firmware/hdl/link_maps.vhd        | 24 +++++++++-----
 3 files changed, 59 insertions(+), 29 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 72982d69..541076f8 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -69,14 +69,14 @@ 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;
+    constant cNumberOfMProcessors                  : integer                                  := 2;
     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';
@@ -139,6 +139,7 @@ begin
 
     fe_status_registers(0) <= std_logic_vector(to_unsigned(cNumberOfFEModules, 32));
 
+
     --==============================--
     channel_select : entity work.ipbus_dc_fabric_sel
     --==============================--
@@ -297,6 +298,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;
 
@@ -382,7 +385,7 @@ begin
             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),
             gbe_backpressure   => gbe_backpressure(i),
             srst               => srst,
             --- Output Ports ---
@@ -441,10 +444,10 @@ begin
     ttc_resync_reset <= mproc_channel_sel(0)(8);
     srst <= mproc_channel_sel(0)(7) or ttc_oc0;
 
-    q(20).valid  <= '1';
-    q(20).data   <= "0000" & std_logic_vector(bunch_counter) & "0000000000000000" & std_logic_vector(orbit_counter);
-    q(20).start  <= '1';
-    q(20).strobe <= '1';
+    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';
 
 
 
diff --git a/top/firmware/hdl/emp_project_decl.vhd b/top/firmware/hdl/emp_project_decl.vhd
index cb139412..971319c1 100644
--- a/top/firmware/hdl/emp_project_decl.vhd
+++ b/top/firmware/hdl/emp_project_decl.vhd
@@ -35,12 +35,12 @@ package emp_project_decl is
   -- mgt -> buf -> fmt -> (algo) -> (fmt) -> buf -> mgt -> clk -> altclk
   constant REGION_CONF : region_conf_array_t := (
 --    0  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 225 -- Right Column
---    1  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 226
+    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  => (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
+    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
@@ -50,9 +50,9 @@ package emp_project_decl is
     --11     => (gty25, buf, no_fmt, buf, gty25),
     --12     => (gty25, buf, no_fmt, buf, gty25),
 -- KH used for gbe
---    13 => (gty25, buf, no_fmt, buf, gty25),   --Bank 131
---    14 => (gty25, buf, no_fmt, buf, gty25),   --Bank 130
---    15 => (gty25, buf, no_fmt, buf, gty25),   --Bank 129
+    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
@@ -60,15 +60,36 @@ 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, 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)),
+--    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)),
+    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),
+--    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
   );
 
@@ -79,7 +100,7 @@ package emp_project_decl is
   );
 
   constant ETH10G_CONF : eth10g_conf_array_t := (
-    0 => (10, "0011", (x"000000000000", x"000000000000", x"aabbccddef53", x"aabbccddef54"))
+    0 => (10, "1111", (x"aabbccddef51", x"aabbccddef52", x"aabbccddef53", x"aabbccddef54"))
   );
 
 
diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index ee8248ca..2c90f179 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -5,21 +5,27 @@ use work.dtc_link_maps_func.all;
 
 package dtc_link_maps is
 
-    constant cNumberOfFEModules   : integer := 4;
-    constant cNumberOfOutputLinks : integer := 4;
+    constant cNumberOfFEModules   : integer := 12;
+    constant cNumberOfOutputLinks : integer := 12;
 
     type tDTCInputLinkMap is array(0 to cNumberOfFEModules - 1) of tDTCInputLinkConfig;
     constant cDTCInputLinkMap     : tDTCInputLinkMap := (
-        0 => (8,  "2S", 5, "CIC2"),
-        1 => (9,  "2S", 5, "CIC2"),
-        2 => (10, "2S", 5, "CIC2"),
-        3 => (11, "2S", 5, "CIC2")
+        0 => (16, "2S", 5, "CIC2"),
+        1 => (17, "2S", 5, "CIC2"),
+        2 => (18, "2S", 5, "CIC2"),
+        3 => (19, "2S", 5, "CIC2"),
+        0 => (20, "2S", 5, "CIC2"),
+        1 => (21, "2S", 5, "CIC2"),
+        2 => (22, "2S", 5, "CIC2"),
+        3 => (23, "2S", 5, "CIC2"),
+        0 => (24, "2S", 5, "CIC2"),
+        1 => (25, "2S", 5, "CIC2"),
+        2 => (26, "2S", 5, "CIC2"),
+        3 => (27, "2S", 5, "CIC2")
     );
 
     type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
-    constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (
-        16, 17, 18, 19
-    );
+    constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39);
 
 end package dtc_link_maps;
 
-- 
GitLab


From 3d35318d6b4c2c0d873375b1fcca1801f9fa3611 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 09:54:12 +0200
Subject: [PATCH 019/109] Update file link_maps.vhd

---
 top/firmware/hdl/link_maps.vhd | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index 2c90f179..5f03fe20 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -10,18 +10,18 @@ package dtc_link_maps is
 
     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"),
-        0 => (20, "2S", 5, "CIC2"),
-        1 => (21, "2S", 5, "CIC2"),
-        2 => (22, "2S", 5, "CIC2"),
-        3 => (23, "2S", 5, "CIC2"),
-        0 => (24, "2S", 5, "CIC2"),
-        1 => (25, "2S", 5, "CIC2"),
-        2 => (26, "2S", 5, "CIC2"),
-        3 => (27, "2S", 5, "CIC2")
+        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 tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
-- 
GitLab


From 976c998f8bf5045d4aa023953775df2a842563ac Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 10:43:50 +0200
Subject: [PATCH 020/109] Update file emp_payload.vhd

---
 top/firmware/hdl/emp_payload.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 541076f8..88b0d618 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -353,7 +353,7 @@ begin
 
         signal ipb_to_channel        : ipb_wbus;
         signal ipb_from_channel      : ipb_rbus;
-        constant cNumberofInputLinks : integer := cNumberOfFEModules;
+        constant cNumberofInputLinks : integer := 6;
 
     begin
 
-- 
GitLab


From 5b8ffa31378b3354236644df3a3718d9f8f82221 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 12:48:10 +0200
Subject: [PATCH 021/109] Update file LinkAggregatorCore.vhd

---
 common/firmware/hdl/LinkAggregatorCore.vhd | 32 ++++++++--------------
 1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index de44256f..5b82488f 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -1,6 +1,7 @@
 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.ipbus.all;
@@ -131,7 +132,8 @@ architecture compressed of LinkAggregatorCore is
     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;
@@ -195,7 +197,7 @@ 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 
@@ -303,7 +305,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 +345,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
@@ -371,7 +368,6 @@ begin
                     links_out(i).data  <= (others => '0');
                 end if;               
                 links_out(i).strobe <= '1';
-
             end if;
             
         end process pIteratePointer;
@@ -425,11 +421,10 @@ begin
             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,19 +437,14 @@ 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;
-- 
GitLab


From 6bcec346a041097904b65d7ab51f82e680787209 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 14:16:06 +0200
Subject: [PATCH 022/109] Add latch on packet_start to help timing

---
 common/firmware/hdl/LinkAggregatorCore.vhd | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index 5b82488f..42d42f8f 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -127,6 +127,8 @@ architecture compressed of LinkAggregatorCore is
         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;
@@ -140,6 +142,8 @@ architecture compressed of LinkAggregatorCore is
 
 begin
 
+    packet_start_buffered <= packet_start;
+
     --==============================--
     genLinkCache : for i in N_LINKS - 1 downto 0 generate
     -- Generator to produce the caching and routing FIFOs for each link
@@ -186,7 +190,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;
@@ -217,7 +221,7 @@ begin
             --==============================--
             begin
                 if rising_edge(clk_p) then
-                    if packet_start = '1' then
+                    if packet_start_buffered = '1' then
                         if unsigned(count_cache) >= trigger_threshold then
                             bx_valid_array(N_LINKS*j + i) <= '1';
                         else
@@ -274,8 +278,8 @@ begin
                 data_count => count_route
             );
 
-            -- Combine the IPBus 'reset' with the 'packet_start' signal to generate the reset signal for the routing FIFO.
-            route_reset <= reset or packet_start;
+            -- Combine the IPBus 'reset' with the 'packet_start_buffered' signal to generate the reset signal for the routing FIFO.
+            route_reset <= reset or packet_start_buffered;
                 
         end generate genLinkBxCache;
 
@@ -394,7 +398,7 @@ begin
             data_count   => data_count
         );
 
-        all_links_reset <= reset or packet_start;
+        all_links_reset <= reset or packet_start_buffered;
 
     end generate;
 
@@ -404,7 +408,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
-- 
GitLab


From 4234075b26a37b27e9d0af293635180dcf9f3df3 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 15:23:47 +0200
Subject: [PATCH 023/109] Update file emp_payload.vhd

---
 top/firmware/hdl/emp_payload.vhd | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 88b0d618..cfc5b221 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -400,6 +400,8 @@ begin
 
 
     gbe_q <= eth_link_out;
+    q(5) <= eth_link_out(0);
+    q(6) <= eth_link_out(1);
 
     
     --==============================--
-- 
GitLab


From 2312af032058c0a9b1740f07c31e9485b2cde39a Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 15:29:04 +0200
Subject: [PATCH 024/109] Update file LinkAggregatorCore.vhd

---
 common/firmware/hdl/LinkAggregatorCore.vhd | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index 42d42f8f..ad9f1d4a 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -142,7 +142,14 @@ architecture compressed of LinkAggregatorCore is
 
 begin
 
-    packet_start_buffered <= packet_start;
+    --==============================--
+    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
-- 
GitLab


From 74580161597bc2963372e547fb04d0b6ff6a6de7 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Thu, 31 Aug 2023 12:29:34 +0200
Subject: [PATCH 025/109] Reverted change that had lead to a bug in the readout

---
 common/firmware/hdl/LinkAggregatorCore.vhd  |  5 +++--
 common/firmware/hdl/LinkAggregatorIPBus.vhd |  6 ++++--
 common/firmware/hdl/LinkCombinerCore.vhd    | 17 ++---------------
 common/firmware/hdl/MProcessor.vhd          |  6 ++++--
 top/firmware/hdl/emp_payload.vhd            |  3 ++-
 5 files changed, 15 insertions(+), 22 deletions(-)

diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index ad9f1d4a..022d0d21 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -10,7 +10,8 @@ use work.ipbus_reg_types.all;
 
 entity LinkAggregatorCore is
     generic (
-        N_LINKS : integer
+        N_LINKS : integer;
+        INDEX   : integer := 0
     );
     port (
         --- Input Ports ---
@@ -169,7 +170,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;
 
diff --git a/common/firmware/hdl/LinkAggregatorIPBus.vhd b/common/firmware/hdl/LinkAggregatorIPBus.vhd
index 43b94dd0..ddf90b77 100644
--- a/common/firmware/hdl/LinkAggregatorIPBus.vhd
+++ b/common/firmware/hdl/LinkAggregatorIPBus.vhd
@@ -11,7 +11,8 @@ use work.ipbus_decode_link_aggregator.all;
 
 entity LinkAggregatorIPBus is
     generic (
-        N_LINKS : integer
+        N_LINKS : integer;
+        INDEX   : integer := 0
     );
     port (
         --- Input Ports ---
@@ -191,7 +192,8 @@ begin
     LinkAggregatorInstance: entity work.LinkAggregatorCore
     --==============================--
     generic map (
-        N_LINKS => N_LINKS
+        N_LINKS => N_LINKS,
+        INDEX   => INDEX
     )
     port map (
         --- Input Ports ---
diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index ba692877..149185a7 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -89,11 +89,6 @@ architecture Behavioral of LinkCombinerCore is
     constant cFullEmptyArray                                              : std_logic_vector(N_INPUT_LINKS - 1 downto 0)       := (others => '1');
 
     -- Signals
-    signal input_links_valid                                              : std_logic_vector(N_INPUT_LINKS - 1 downto 0)       := (others => '0');
-    signal all_input_links_valid                                          : std_logic                                          := '0';
-    signal all_input_links_valid_previous                                 : std_logic                                          := '0';
-    signal start_output                                                   : std_logic                                          := '0';
-    
     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');
@@ -254,21 +249,13 @@ begin
     --==============================--
     begin
         if rising_edge(clk_p) then
-            if start_output = '1' then
+            if packet_start = '1' then
                 input_data_valid <= '1';
             else
                 if reset = '1' then
                     input_data_valid <= '0';
                 end if;
             end if;
-            
-            all_input_links_valid <= and_reduce(input_links_valid);
-            all_input_links_valid_previous <= all_input_links_valid;
-            if all_input_links_valid = '0' and all_input_links_valid_previous = '1' then
-                start_output <= '1';
-            else
-                start_output <= '0';
-            end if;
         end if;
     end process pValidDataChecker;
     
@@ -306,7 +293,7 @@ begin
             end if;
             
             -- Packet control bits logic
-            if start_output = '1' then
+            if packet_start = '1' then
                 counter <= 0;
             else
                 if counter < 3 then
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 29ee4cce..d15baa4a 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -16,7 +16,8 @@ use work.dtc_data_types.all;
 
 entity MProcessor is
     generic (
-        N_LINKS : integer
+        N_LINKS : integer;
+        INDEX   : integer := 0
     );
     port (
         --- Input Ports ---
@@ -94,7 +95,8 @@ begin
     LinkAggregatorInstance: entity work.LinkAggregatorIPBus
     --==============================--
     generic map (
-        N_LINKS       => N_LINKS
+        N_LINKS       => N_LINKS,
+        INDEX         => INDEX
     )
     port map (
         --- Input Ports ---
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index cfc5b221..413cdb06 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -378,7 +378,8 @@ begin
         MProcessorInstance: entity work.MProcessor
         --==============================--
         generic map(
-            N_LINKS => cNumberofInputLinks
+            N_LINKS => cNumberofInputLinks,
+            INDEX   => i
         )
         port map(
             --- Input Ports ---
-- 
GitLab


From a697f897c27acfcf9478d86351f8b17c303c8b4e Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Thu, 31 Aug 2023 13:18:58 +0200
Subject: [PATCH 026/109] Update file LinkCombinerCore.vhd

---
 common/firmware/hdl/LinkCombinerCore.vhd | 2 --
 1 file changed, 2 deletions(-)

diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index 149185a7..9d4f7a3f 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -133,8 +133,6 @@ begin
         signal wr_en : std_logic                                 := '0';
     begin
     
-        input_links_valid(i) <= links_in(i).valid;
-    
         --==============================--
         InputLinkBufferInstance : link_agg_all_links_fifo
         --==============================--
-- 
GitLab


From 9a75997fb9a450dbb29e2ef021a6141c47b9148f Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Fri, 1 Sep 2023 15:56:40 +0200
Subject: [PATCH 027/109] Added debug packet size signal

---
 common/firmware/hdl/LinkCombinerCore.vhd  | 8 +++++++-
 common/firmware/hdl/LinkCombinerIPBus.vhd | 7 ++++---
 common/firmware/hdl/MProcessor.vhd        | 5 ++++-
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index 9d4f7a3f..deb58e18 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -27,7 +27,8 @@ entity LinkCombinerCore is
         --- 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;
 
@@ -194,6 +195,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';
@@ -213,6 +216,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);
diff --git a/common/firmware/hdl/LinkCombinerIPBus.vhd b/common/firmware/hdl/LinkCombinerIPBus.vhd
index c8136716..7abbaee7 100644
--- a/common/firmware/hdl/LinkCombinerIPBus.vhd
+++ b/common/firmware/hdl/LinkCombinerIPBus.vhd
@@ -32,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;
 
@@ -114,8 +115,8 @@ begin
         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 d15baa4a..e7e777d1 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -53,6 +53,8 @@ architecture Behavorial of MProcessor is
 
     signal super_id                : std_logic_vector(31 downto 0) := (others => '0');
 
+    signal debug_packet_size       : lword := LWORD_NULL;
+
 begin
 
     --==============================--
@@ -136,7 +138,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
     );
 
     -- --==============================--
-- 
GitLab


From 5e130b92407b135d5e30970a383b87f639039c22 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 09:15:49 +0200
Subject: [PATCH 028/109] Added histogram to LinkCOmbiner in mprocessor

---
 common/addr_table/mprocessor.xml   | 11 ++++--
 common/firmware/hdl/MProcessor.vhd | 57 +++++++++++++++++++++++++++---
 top/addr_table/emp_payload.xml     | 13 ++++---
 3 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 3075dce5..5a7b8c56 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -10,9 +10,14 @@
         <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=3">
         <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="lff" address="0x3" mask="0x0001"/>
+        <node id="super_id" address="0x4"/>
+        <node id="occupancy_max_value0" address="0x5"/>
     </node>
+
+    <node id="occupancy_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
 </node>
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index e7e777d1..d4971a96 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -48,12 +48,19 @@ 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(3 - 1 downto 0)   := (others => (others => '0'));
+    signal control_registers       : ipb_reg_v(3 - 1 downto 0)   := (others => (others => '0'));
 
     signal super_id                : std_logic_vector(31 downto 0) := (others => '0');
 
-    signal debug_packet_size       : lword := LWORD_NULL;
+    signal debug_packet_size         : lword                             := LWORD_NULL;
+    signal occupancy_max_value       : std_logic_vector(32 - 1 downto 0) := (others => '0');
+    signal occupancy_histogram_reset : std_logic                         := '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";
+
 
 begin
 
@@ -81,8 +88,8 @@ begin
     MProcessorControlInstance: entity work.ipbus_ctrlreg_v
     --==============================--
     generic map(
-        N_CTRL    => 1,
-        N_STAT    => 2
+        N_CTRL    => 3,
+        N_STAT    => 3
     )
     port map(
         clk       => ipb_clk,
@@ -157,4 +164,44 @@ begin
     status_registers(1)    <= super_id;
     packet_start           <= header_start_array(to_integer(unsigned(control_registers(0)(2 downto 0))))(0);
 
+
+    --==============================--
+    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             => clk,
+        rst             => 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/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index 0eb42100..4e5e68e3 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -7,17 +7,16 @@
 
     <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="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=10"/>
+    <node id="mproc_ctrl" address="0x4ffff" 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="be_daq" address="0x40000000" module="file://dtc_data_aggregator.xml" fwinfo="endpoint;width=30"/>
 </node>
-- 
GitLab


From 0821c61fc8d2e4ca6e6fe834fa31fcf2714baad6 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 09:24:08 +0200
Subject: [PATCH 029/109] Updated payload width

---
 top/addr_table/emp_payload.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index 4e5e68e3..2c038e0c 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -11,7 +11,7 @@
 
     <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=10"/>
+    <node id="mprocessor" address="0x40000" description="MProcessor control and status" module="file://mprocessor.xml" fwinfo="endpoint;width=12"/>
     <node id="mproc_ctrl" address="0x4ffff" description="MProcessor channel control" fwinfo="endpoint;width=0">
         <node id="chan_sel" mask="0x7f"/>
         <node id="srst"     mask="0x80"/>
-- 
GitLab


From f1f0cba8119fb2b728c9424c1d20cc38bdc98aa3 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 09:38:02 +0200
Subject: [PATCH 030/109] Fixed signal name error

---
 common/firmware/hdl/MProcessor.vhd | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index d4971a96..6526cac7 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -181,8 +181,8 @@ begin
         --- Output Ports ---
         max_bin_value   => occupancy_max_value,
         --- IPBus Ports ---
-        clk             => clk,
-        rst             => rst,
+        clk             => ipb_clk,
+        rst             => ipb_rst,
         ipb_in          => ipb_to_slaves(N_SLV_OCCUPANCY_MEM),
         ipb_out         => ipb_from_slaves(N_SLV_OCCUPANCY_MEM)
     );
-- 
GitLab


From 0814a600153a79c73f30ea44016f7b72d0e5b17e Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 12:44:32 +0200
Subject: [PATCH 031/109] Fixed address numbering

---
 common/addr_table/mprocessor.xml   | 10 +++++-----
 common/firmware/hdl/MProcessor.vhd |  9 +++++----
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 5a7b8c56..9a988f46 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -12,11 +12,11 @@
     
     <node id="csr" address="0x30" description="MProcessor control and status" fwinfo="endpoint;width=3">
         <node id="header_start_select" address="0x0" mask="0x7"/>
-        <node id="occupancy_windowL" address="0x1"/>
-        <node id="occupancy_windowH" address="0x2" mask="0x000f"/>
-        <node id="lff" address="0x3" mask="0x0001"/>
-        <node id="super_id" address="0x4"/>
-        <node id="occupancy_max_value0" address="0x5"/>
+        <node id="occupancy_windowL"   address="0x1"/>
+        <node id="occupancy_windowH"   address="0x2" mask="0x000f"/>
+        <node id="lff"                 address="0x4" mask="0x0001"/>
+        <node id="super_id"            address="0x5"/>
+        <node id="occupancy_max_value" address="0x6"/>
     </node>
 
     <node id="occupancy_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 6526cac7..4455cea1 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -53,13 +53,13 @@ architecture Behavorial of MProcessor is
 
     signal super_id                : std_logic_vector(31 downto 0) := (others => '0');
 
-    signal debug_packet_size         : lword                             := LWORD_NULL;
-    signal occupancy_max_value       : std_logic_vector(32 - 1 downto 0) := (others => '0');
-    signal occupancy_histogram_reset : std_logic                         := '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;
+
 
 
 begin
@@ -201,6 +201,7 @@ begin
     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;
 
 
-- 
GitLab


From 2e0ecdbdecbadcecd2d80b630e08683184e9fcb7 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Sat, 2 Sep 2023 15:17:10 +0200
Subject: [PATCH 032/109] Added global header block

---
 common/firmware/cfg/module.dep                |   1 +
 common/firmware/hdl/LinkCombinerCore.vhd      |  48 +-------
 common/firmware/hdl/LinkCombinerIPBus.vhd     |   5 +-
 common/firmware/hdl/MProcessor.vhd            |   9 +-
 .../firmware/hdl/PayloadHeaderGenerator.vhd   | 107 ++++++++++++++++++
 common/firmware/hdl/mprocessor_constants.vhd  |   1 +
 top/firmware/hdl/emp_payload.vhd              |  24 +++-
 7 files changed, 143 insertions(+), 52 deletions(-)
 create mode 100644 common/firmware/hdl/PayloadHeaderGenerator.vhd

diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index f8a06571..d9a3da95 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -10,6 +10,7 @@ src LinkAggregatorIPBus.vhd
 src LinkCombinerCore.vhd
 src LinkCombinerIPBus.vhd
 src --vhdl2008 TrackReconstructor.vhd
+src PayloadHeaderGenerator.vhd
 
 src ipbus_decode_link_aggregator.vhd
 src ipbus_decode_mprocessor.vhd
diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index deb58e18..89aa7012 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -20,8 +20,7 @@ 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 ---
@@ -310,30 +309,12 @@ begin
             output_din     <= input_dout_array(output_pointer_buffered);
             output_wr_en   <= input_valid_array(output_pointer_buffered) and (not reset);
             
-            
-            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;
-            
             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);
+                output_wr_en_buf <= '1';
+                output_din_buf   <= payload_header(63 downto 0);
             elsif counter = 2 then
                 output_din_buf <= (others => '0');
-                output_din_buf(11 downto 0) <= bcid_sr(bcid_sr'high);
-                output_din_buf(19 downto 12) <= std_logic_vector(packet_stub_count_previous);
+                output_din_buf(19 downto 0) <= payload_header(83 downto 64);
                 output_wr_en_buf <= '1';
             else
                 output_wr_en_buf  <= output_wr_en and (not reset);
@@ -343,27 +324,6 @@ begin
         end if;
     end process pCombineBuffers;
 
-
-    --==============================--
-    pBufferHeader: process(clk_p)
-    --==============================--
-        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
-                    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
     --==============================--
diff --git a/common/firmware/hdl/LinkCombinerIPBus.vhd b/common/firmware/hdl/LinkCombinerIPBus.vhd
index 7abbaee7..47ce1078 100644
--- a/common/firmware/hdl/LinkCombinerIPBus.vhd
+++ b/common/firmware/hdl/LinkCombinerIPBus.vhd
@@ -21,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 ---
@@ -109,8 +109,7 @@ 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 ---
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 4455cea1..d8a4465b 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -23,8 +23,8 @@ entity MProcessor is
         --- 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 ---
@@ -33,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;
 
@@ -134,7 +136,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 ---
@@ -163,6 +165,7 @@ begin
     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;
 
 
     --==============================--
diff --git a/common/firmware/hdl/PayloadHeaderGenerator.vhd b/common/firmware/hdl/PayloadHeaderGenerator.vhd
new file mode 100644
index 00000000..f4c17c98
--- /dev/null
+++ b/common/firmware/hdl/PayloadHeaderGenerator.vhd
@@ -0,0 +1,107 @@
+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'))
+    );
+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 2 - 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;
+
+        header_out(i)(75 downto 0) <= header_word(75 downto 0);
+    end generate ; -- genOutput
+    
+
+end Behavioral;
diff --git a/common/firmware/hdl/mprocessor_constants.vhd b/common/firmware/hdl/mprocessor_constants.vhd
index 367eb099..00f1e166 100644
--- a/common/firmware/hdl/mprocessor_constants.vhd
+++ b/common/firmware/hdl/mprocessor_constants.vhd
@@ -7,6 +7,7 @@ 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(2 - 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;
     
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 413cdb06..e034ed59 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -84,6 +84,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
@@ -385,8 +387,8 @@ begin
             --- 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_buffered),
+            payload_header     => payload_headers(i),
             gbe_backpressure   => gbe_backpressure(i),
             srst               => srst,
             --- Output Ports ---
@@ -395,10 +397,28 @@ 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 => x"d451d007",
+        --- Ouput Ports ---
+        header_out => payload_headers
+    );
+    
+
 
     gbe_q <= eth_link_out;
     q(5) <= eth_link_out(0);
-- 
GitLab


From 719287a88e36ed2e12ebb070e865c760b2262296 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 18:15:17 +0200
Subject: [PATCH 033/109] Small changes to header generator

---
 common/firmware/hdl/PayloadHeaderGenerator.vhd | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/common/firmware/hdl/PayloadHeaderGenerator.vhd b/common/firmware/hdl/PayloadHeaderGenerator.vhd
index f4c17c98..bcea3449 100644
--- a/common/firmware/hdl/PayloadHeaderGenerator.vhd
+++ b/common/firmware/hdl/PayloadHeaderGenerator.vhd
@@ -19,7 +19,9 @@ entity PayloadHeaderGenerator is
         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'))
+        header_out : out tPayloadHeaderArray := (others => (others => '0'));
+        --- Debug Ports ---
+        super_id : out std_logic_vector(31 downto 0) := (others => '0')
     );
 end PayloadHeaderGenerator;
 
@@ -57,8 +59,8 @@ begin
                     end if;
                 end if;
                 
-                header_word <= (others => '0');
-                header_word(31 downto 0) <= std_logic_vector(super_id);
+                -- 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;
@@ -100,7 +102,6 @@ begin
             end if;
         end process pCountStubs;
 
-        header_out(i)(75 downto 0) <= header_word(75 downto 0);
     end generate ; -- genOutput
     
 
-- 
GitLab


From 521e78fa565240a0875ff131522acb0768155339 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 18:26:22 +0200
Subject: [PATCH 034/109] Fixed signal naming

---
 common/firmware/hdl/PayloadHeaderGenerator.vhd | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/common/firmware/hdl/PayloadHeaderGenerator.vhd b/common/firmware/hdl/PayloadHeaderGenerator.vhd
index bcea3449..f5db1659 100644
--- a/common/firmware/hdl/PayloadHeaderGenerator.vhd
+++ b/common/firmware/hdl/PayloadHeaderGenerator.vhd
@@ -21,7 +21,7 @@ entity PayloadHeaderGenerator is
         --- Ouput Ports ---
         header_out : out tPayloadHeaderArray := (others => (others => '0'));
         --- Debug Ports ---
-        super_id : out std_logic_vector(31 downto 0) := (others => '0')
+        debug_super_id : out std_logic_vector(31 downto 0) := (others => '0')
     );
 end PayloadHeaderGenerator;
 
@@ -104,5 +104,6 @@ begin
 
     end generate ; -- genOutput
     
+    debug_super_id <= super_id;
 
 end Behavioral;
-- 
GitLab


From 6b482f50c1fb954a9996469ce1482923102bad9b Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 18:41:43 +0200
Subject: [PATCH 035/109] Fixed type

---
 common/firmware/hdl/PayloadHeaderGenerator.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/firmware/hdl/PayloadHeaderGenerator.vhd b/common/firmware/hdl/PayloadHeaderGenerator.vhd
index f5db1659..c36d580d 100644
--- a/common/firmware/hdl/PayloadHeaderGenerator.vhd
+++ b/common/firmware/hdl/PayloadHeaderGenerator.vhd
@@ -104,6 +104,6 @@ begin
 
     end generate ; -- genOutput
     
-    debug_super_id <= super_id;
+    debug_super_id <= std_logic_vector(super_id);
 
 end Behavioral;
-- 
GitLab


From 076e9dbf7ee75fad14329fa4e9ab18540716a960 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 18:53:13 +0200
Subject: [PATCH 036/109] Added super ID monitoring

---
 common/firmware/hdl/LinkCombinerCore.vhd | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index 89aa7012..66086644 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -327,7 +327,7 @@ begin
     --==============================--
     -- 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));
@@ -337,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;
-- 
GitLab


From 4dd40b0fd19267eb760088851f4136c811f82c2f Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sun, 3 Sep 2023 12:07:03 +0200
Subject: [PATCH 037/109] Added register for user bits

---
 top/addr_table/emp_payload.xml   | 11 +++++++----
 top/firmware/hdl/emp_payload.vhd | 18 +++++++++---------
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index 2c038e0c..04a81aba 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -12,10 +12,13 @@
     <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=12"/>
-    <node id="mproc_ctrl" address="0x4ffff" 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 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"/>
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index e034ed59..68d7fe62 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -60,7 +60,8 @@ architecture rtl of emp_payload is
 
     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 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);
 
 
@@ -159,18 +160,17 @@ 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
     );
 
 
@@ -341,7 +341,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),
@@ -413,7 +413,7 @@ begin
         readout_reset => readout_reset(0),
         header_start => header_start_array_buffered(0),
         module_header_in => header_array,
-        user_bits => x"d451d007",
+        user_bits => mproc_control_registers(1),
         --- Ouput Ports ---
         header_out => payload_headers
     );
@@ -464,8 +464,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(4).valid  <= '1';
     q(4).data   <= "0000" & std_logic_vector(bunch_counter) & "0000000000000000" & std_logic_vector(orbit_counter);
-- 
GitLab


From 092d3e0c3f756dffb7116827a7a24e6a8491f657 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Mon, 4 Sep 2023 19:00:46 +0200
Subject: [PATCH 038/109] Added configurable threshold for each input link

---
 common/addr_table/link_aggregator.xml         | 23 +++++++++++++++----
 common/firmware/cfg/module.dep                |  1 +
 common/firmware/hdl/LinkAggregatorCore.vhd    |  8 ++++---
 common/firmware/hdl/LinkAggregatorIPBus.vhd   | 19 +++++++++++----
 common/firmware/hdl/mprocessor_data_types.vhd | 15 ++++++++++++
 5 files changed, 55 insertions(+), 11 deletions(-)
 create mode 100644 common/firmware/hdl/mprocessor_data_types.vhd

diff --git a/common/addr_table/link_aggregator.xml b/common/addr_table/link_aggregator.xml
index ce2c7280..1026d7a3 100644
--- a/common/addr_table/link_aggregator.xml
+++ b/common/addr_table/link_aggregator.xml
@@ -1,9 +1,24 @@
 <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"/>
diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index d9a3da95..7975c1d2 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -10,6 +10,7 @@ src LinkAggregatorIPBus.vhd
 src LinkCombinerCore.vhd
 src LinkCombinerIPBus.vhd
 src --vhdl2008 TrackReconstructor.vhd
+src mprocessor_data_types.vhd
 src PayloadHeaderGenerator.vhd
 
 src ipbus_decode_link_aggregator.vhd
diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index 022d0d21..c6544ff8 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -6,6 +6,7 @@ use work.emp_data_types.all;
 
 use work.ipbus.all;
 use work.ipbus_reg_types.all;
+use work.mprocessor_data_types.all;
 
 
 entity LinkAggregatorCore is
@@ -19,7 +20,8 @@ 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);
@@ -230,7 +232,7 @@ begin
             begin
                 if rising_edge(clk_p) then
                     if packet_start_buffered = '1' then
-                        if unsigned(count_cache) >= trigger_threshold 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';
@@ -295,7 +297,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;
diff --git a/common/firmware/hdl/LinkAggregatorIPBus.vhd b/common/firmware/hdl/LinkAggregatorIPBus.vhd
index ddf90b77..4f1664f1 100644
--- a/common/firmware/hdl/LinkAggregatorIPBus.vhd
+++ b/common/firmware/hdl/LinkAggregatorIPBus.vhd
@@ -5,6 +5,7 @@ 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;
 
@@ -40,12 +41,14 @@ 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 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);
 
 begin
 
@@ -87,7 +90,7 @@ begin
     ControlInstance: entity work.ipbus_ctrlreg_v
     --==============================--
     generic map(
-        N_CTRL       => 1,
+        N_CTRL       => 2,
         N_STAT       => 0
     )
     port map(
@@ -188,6 +191,13 @@ 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
     --==============================--
@@ -198,10 +208,11 @@ begin
     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,
diff --git a/common/firmware/hdl/mprocessor_data_types.vhd b/common/firmware/hdl/mprocessor_data_types.vhd
new file mode 100644
index 00000000..b08d9986
--- /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
-- 
GitLab


From 7601199e62528472f2bedb7001e81a2191350b72 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Mon, 4 Sep 2023 20:22:06 +0200
Subject: [PATCH 039/109] Removed L1DataAggregator

---
 top/firmware/hdl/emp_payload.vhd | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 68d7fe62..cb8df549 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -273,22 +273,22 @@ begin
     -- L1 Data Aggregator
     --==============================--
 
-    --==============================--
-    L1DataAggregator : entity work.L1DataAggregator
-    --==============================--
-    port map (
-        --- Input Ports ---
-        clk_p   => clk_p,
-        daq_in  => daq_data,
-        empty   => daq_empty,
-        --- 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)
-    );
+    -- --==============================--
+    -- L1DataAggregator : entity work.L1DataAggregator
+    -- --==============================--
+    -- port map (
+    --     --- Input Ports ---
+    --     clk_p   => clk_p,
+    --     daq_in  => daq_data,
+    --     empty   => daq_empty,
+    --     --- 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
-- 
GitLab


From 30118f7c532b8bad805316c1eee83ee7b9e44fde Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Tue, 5 Sep 2023 15:01:56 +0200
Subject: [PATCH 040/109] Re instated Aggregatpr

---
 top/firmware/hdl/emp_payload.vhd | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index cb8df549..68d7fe62 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -273,22 +273,22 @@ begin
     -- L1 Data Aggregator
     --==============================--
 
-    -- --==============================--
-    -- L1DataAggregator : entity work.L1DataAggregator
-    -- --==============================--
-    -- port map (
-    --     --- Input Ports ---
-    --     clk_p   => clk_p,
-    --     daq_in  => daq_data,
-    --     empty   => daq_empty,
-    --     --- 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)
-    -- );
+    --==============================--
+    L1DataAggregator : entity work.L1DataAggregator
+    --==============================--
+    port map (
+        --- Input Ports ---
+        clk_p   => clk_p,
+        daq_in  => daq_data,
+        empty   => daq_empty,
+        --- 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
-- 
GitLab


From a792416de717dc318a26fa43582e8ee1d581a147 Mon Sep 17 00:00:00 2001
From: Kirika Uchida <kirika.uchida@cern.ch>
Date: Tue, 5 Sep 2023 15:10:44 +0200
Subject: [PATCH 041/109] ecal data processor

---
 common/addr_table/eprocessor.xml              |  18 +
 common/firmware/cfg/module.dep                |  16 +-
 common/firmware/cgn/ecal_data_ram.xci         | 281 +++++++++++
 common/firmware/cgn/ecal_trig_ram.xci         | 281 +++++++++++
 common/firmware/hdl/EcalDataAggregator.vhd    | 107 ++++
 common/firmware/hdl/EcalDataDecoder.vhd       |  54 ++
 common/firmware/hdl/EcalDataFilter.vhd        | 123 +++++
 common/firmware/hdl/EcalDataMonitor.vhd       |  52 ++
 common/firmware/hdl/EcalDataProcessor.vhd     | 460 ++++++++++++++++++
 common/firmware/hdl/EcalLinkInterface.vhd     |  42 ++
 .../hdl/EcalZeroSuppressionFilter.vhd         | 421 ++++++++++++++++
 common/firmware/hdl/ecal_zsf_type_pckg.vhd    |  10 +
 common/firmware/hdl/fixed_pkg_2008.vhd        |   0
 common/firmware/hdl/mprocessor_constants.vhd  |  10 +-
 top/addr_table/emp_payload.xml                |   2 +
 top/firmware/cfg/top.dep                      |   2 +-
 top/firmware/hdl/emp_payload.vhd              |  55 ++-
 top/firmware/hdl/link_maps.vhd                |  10 +-
 18 files changed, 1937 insertions(+), 7 deletions(-)
 create mode 100644 common/addr_table/eprocessor.xml
 create mode 100644 common/firmware/cgn/ecal_data_ram.xci
 create mode 100644 common/firmware/cgn/ecal_trig_ram.xci
 create mode 100644 common/firmware/hdl/EcalDataAggregator.vhd
 create mode 100644 common/firmware/hdl/EcalDataDecoder.vhd
 create mode 100644 common/firmware/hdl/EcalDataFilter.vhd
 create mode 100644 common/firmware/hdl/EcalDataMonitor.vhd
 create mode 100644 common/firmware/hdl/EcalDataProcessor.vhd
 create mode 100644 common/firmware/hdl/EcalLinkInterface.vhd
 create mode 100644 common/firmware/hdl/EcalZeroSuppressionFilter.vhd
 create mode 100644 common/firmware/hdl/ecal_zsf_type_pckg.vhd
 mode change 100755 => 100644 common/firmware/hdl/fixed_pkg_2008.vhd

diff --git a/common/addr_table/eprocessor.xml b/common/addr_table/eprocessor.xml
new file mode 100644
index 00000000..ad686de3
--- /dev/null
+++ b/common/addr_table/eprocessor.xml
@@ -0,0 +1,18 @@
+<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>
+  </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="zs_sc" address="0x1" mode="block" size="32" description="zs filter registers"/>
+  </node>
+    <node id="mon" address="0x80" description="Ecal data monitoring" fwinfo="endpoint;width=2"/>
+</node>
diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index 7975c1d2..2846b5c3 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 ecal_zsf_type_pckg.vhd
 
 src MProcessor.vhd
 src LinkAggregatorCore.vhd
@@ -13,10 +14,20 @@ src --vhdl2008 TrackReconstructor.vhd
 src mprocessor_data_types.vhd
 src PayloadHeaderGenerator.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_link_aggregator.vhd
 src ipbus_decode_mprocessor.vhd
+src ipbus_decode_eprocessor.vhd
 
 addrtab -t mprocessor.xml
+addrtab -t eprocessor.xml
 addrtab -t link_aggregator.xml
 
 # IP Cores
@@ -30,4 +41,7 @@ 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
+
+src --cd ../cgn ecal_data_ram.xci
+src --cd ../cgn ecal_trig_ram.xci
diff --git a/common/firmware/cgn/ecal_data_ram.xci b/common/firmware/cgn/ecal_data_ram.xci
new file mode 100644
index 00000000..91e6aca6
--- /dev/null
+++ b/common/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/common/firmware/cgn/ecal_trig_ram.xci b/common/firmware/cgn/ecal_trig_ram.xci
new file mode 100644
index 00000000..efccb825
--- /dev/null
+++ b/common/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/common/firmware/hdl/EcalDataAggregator.vhd b/common/firmware/hdl/EcalDataAggregator.vhd
new file mode 100644
index 00000000..65ee6c27
--- /dev/null
+++ b/common/firmware/hdl/EcalDataAggregator.vhd
@@ -0,0 +1,107 @@
+-------------------------------------------------------------
+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 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;
+                           
+          -- capturing frames
+          data_out_start <= '0';
+          data_out_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 <= ecal_data_p;
+               data_out_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 <= ecal_data_p;
+                data_out_start <= '1'; 
+                last_valid_bcid <= bcid_p(0);
+              else
+                sync <= '0';
+              end if;
+            else 
+               timer := timer + 1;
+               if timer = 7 then
+                 data_out_last <= '1';
+               end if;
+            end if;
+          end if;
+
+        end if;
+    end process;
+
+end rtl;
+
diff --git a/common/firmware/hdl/EcalDataDecoder.vhd b/common/firmware/hdl/EcalDataDecoder.vhd
new file mode 100644
index 00000000..d5f3ee31
--- /dev/null
+++ b/common/firmware/hdl/EcalDataDecoder.vhd
@@ -0,0 +1,54 @@
+-------------------------------------------------------------
+-- 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;
+begin
+
+  decoder: process (clk_p)
+
+  begin
+    if rising_edge(clk_p) then
+       
+        for j in 0 to 1 loop
+            for i in 0 to 6 loop 
+                elink_data(j*7+i) <= elink_data(j*7+i)(6 downto 0) & data_in.data(j*32+i);
+            end loop;
+        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/common/firmware/hdl/EcalDataFilter.vhd b/common/firmware/hdl/EcalDataFilter.vhd
new file mode 100644
index 00000000..0754a9f6
--- /dev/null
+++ b/common/firmware/hdl/EcalDataFilter.vhd
@@ -0,0 +1,123 @@
+-------------------------------------------------------------
+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_valid    : 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 data_meta         : std_logic_vector(28 * 16 -1 downto 0);
+  signal data_sync         : 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);
+  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     <= trig_sync    when bypass_s = '0' else x"c0000001";
+
+  data_meta   <= data_in   when rising_edge(clk40);
+  data_sync   <= data_meta when rising_edge(clk40);
+  
+  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');
+   elsif rising_edge(clk40) then
+     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_sync,
+    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/common/firmware/hdl/EcalDataMonitor.vhd b/common/firmware/hdl/EcalDataMonitor.vhd
new file mode 100644
index 00000000..17abd38d
--- /dev/null
+++ b/common/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/common/firmware/hdl/EcalDataProcessor.vhd b/common/firmware/hdl/EcalDataProcessor.vhd
new file mode 100644
index 00000000..64c1eb69
--- /dev/null
+++ b/common/firmware/hdl/EcalDataProcessor.vhd
@@ -0,0 +1,460 @@
+-------------------------------------------------------------
+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_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)(9) <= data_ready_i;
+  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_valid      => 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)
+  begin
+        if reset = '1' then
+          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 =>
+              if data_out_s.start = '1' then
+                data_out(0).start <= data_out_s.start;
+                data_out(0).valid <= data_out_s.valid;
+                ostate <= wait_last;
+              end if;
+            when wait_last =>
+                data_out(0).valid <= data_out_s.valid;
+                if data_out_s.last = '1' then
+                  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));
+              trig_ram_dina  <= trig;
+            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;
+            end if;
+
+            data_out_s.valid <= trig_ram_doutb(0) and data_ram_doutb(bit_valid);           
+            data_out_s.start <= trig_ram_doutb(31) and data_ram_doutb(bit_start) and gbe_backpressure;
+            data_out_s.last  <= trig_ram_doutb(30) and data_ram_doutb(bit_last);
+            data_out_s.strobe <= trig_ram_doutb(30) and data_ram_doutb(bit_last);         
+          end if;
+          
+          -- 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;
+            
+          -- data to write                   
+          data_ram_addra <= std_logic_vector(to_unsigned(d_waddr, 9));
+          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
+            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
+              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
+          
+        end if;   
+    end process;
+    
+end rtl;
diff --git a/common/firmware/hdl/EcalLinkInterface.vhd b/common/firmware/hdl/EcalLinkInterface.vhd
new file mode 100644
index 00000000..3d5f84fa
--- /dev/null
+++ b/common/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/common/firmware/hdl/EcalZeroSuppressionFilter.vhd b/common/firmware/hdl/EcalZeroSuppressionFilter.vhd
new file mode 100644
index 00000000..dd5b23ce
--- /dev/null
+++ b/common/firmware/hdl/EcalZeroSuppressionFilter.vhd
@@ -0,0 +1,421 @@
+----------------------------------------------------------------------------------
+-- 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) 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/common/firmware/hdl/ecal_zsf_type_pckg.vhd b/common/firmware/hdl/ecal_zsf_type_pckg.vhd
new file mode 100644
index 00000000..536ad276
--- /dev/null
+++ b/common/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/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 00f1e166..d1d91efe 100644
--- a/common/firmware/hdl/mprocessor_constants.vhd
+++ b/common/firmware/hdl/mprocessor_constants.vhd
@@ -10,6 +10,14 @@ package mprocessor_constants is
     type tPayloadHeaderArray is array(2 - 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;
 
@@ -30,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/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index 04a81aba..88bd97a3 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -7,6 +7,8 @@
 
     <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"/>
diff --git a/top/firmware/cfg/top.dep b/top/firmware/cfg/top.dep
index 2a604b26..0f54808f 100644
--- a/top/firmware/cfg/top.dep
+++ b/top/firmware/cfg/top.dep
@@ -28,4 +28,4 @@ src link_maps.vhd
 
 src ipbus_decode_emp_payload.vhd
 
-addrtab -t emp_payload.xml
\ No newline at end of file
+addrtab -t emp_payload.xml
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index cb8df549..12472e21 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -102,6 +102,13 @@ architecture rtl of emp_payload is
     signal tcds_fcmd                  : tFastCommand;
 
 
+    -- Ecal
+
+    signal ecal_link_data             : tDaqEcalLinkDataArray;
+    signal ecal_data                  : ldata(cNumberOfEcalOutputLinks - 1 downto 0);
+
+
+
 begin
 
   
@@ -174,9 +181,6 @@ begin
     );
 
 
-    
-
-
     --==============================--
     -- FE data extraction and monitoring
     --==============================--
@@ -328,6 +332,51 @@ begin
 
 
 
+    --==============================--
+    -- 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
     --==============================--
diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index 5f03fe20..215bf5a3 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -7,7 +7,9 @@ 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"),
@@ -24,6 +26,12 @@ package dtc_link_maps is
         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);
 
-- 
GitLab


From 43d71ad9b1fcfc03ce00e16c8ad4bf06e7eb452d Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 5 Sep 2023 17:44:29 +0200
Subject: [PATCH 042/109] Update file README.md

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index aea2de9c..2a46eb3c 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
-- 
GitLab


From 34d60bde173cb41be5f6f65b4596a47af9080089 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sat, 9 Sep 2023 19:04:43 +0200
Subject: [PATCH 043/109] Added tracking event rate monitor

---
 common/addr_table/link_aggregator.xml       |  1 +
 common/firmware/cfg/module.dep              |  1 +
 common/firmware/hdl/LinkAggregatorCore.vhd  | 50 ++++++++++++++++++---
 common/firmware/hdl/LinkAggregatorIPBus.vhd | 10 +++--
 common/firmware/hdl/tracking_constants.vhd  | 11 +++++
 5 files changed, 65 insertions(+), 8 deletions(-)
 create mode 100644 common/firmware/hdl/tracking_constants.vhd

diff --git a/common/addr_table/link_aggregator.xml b/common/addr_table/link_aggregator.xml
index 1026d7a3..1d4ee0bb 100644
--- a/common/addr_table/link_aggregator.xml
+++ b/common/addr_table/link_aggregator.xml
@@ -22,6 +22,7 @@
     </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/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index 2846b5c3..2036591c 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -4,6 +4,7 @@ src fixed_pkg_2008.vhd
 
 src mprocessor_constants.vhd
 src ecal_zsf_type_pckg.vhd
+src tracking_constants.vhd
 
 src MProcessor.vhd
 src LinkAggregatorCore.vhd
diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index c6544ff8..4456b4d3 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -3,6 +3,7 @@ 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;
@@ -28,7 +29,7 @@ entity LinkAggregatorCore is
         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')
         non_empty_counts   : out ipb_reg_v(8*N_LINKS - 1 downto 0);
         bx_valid_count_out : out ipb_reg_v(0 downto 0)
     );
@@ -129,7 +130,7 @@ 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');
@@ -142,6 +143,13 @@ architecture compressed of LinkAggregatorCore is
     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 track_stubs : tTrackStubs := (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
 
@@ -215,7 +223,7 @@ begin
                     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
@@ -241,6 +249,23 @@ 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;
@@ -429,9 +454,9 @@ begin
             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';
+                readout_reset_signal <= '1';
             else
-                readout_reset <= '0';
+                readout_reset_signal <= '0';
             end if;
         end if;
     end process pReadoutReset;
@@ -463,6 +488,20 @@ begin
             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' and event_valid_for_tracking = '1' then
+                tracking_event_count <= tracking_event_count + 1;
+            end if;
+        end if;
+    end process pExtractTrackingEvent;
+    
+    readout_reset <= readout_reset_signal;
 
     --==============================--
     -- Debug
@@ -479,5 +518,6 @@ 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);
 
 end compressed;
diff --git a/common/firmware/hdl/LinkAggregatorIPBus.vhd b/common/firmware/hdl/LinkAggregatorIPBus.vhd
index 4f1664f1..4ff1f48d 100644
--- a/common/firmware/hdl/LinkAggregatorIPBus.vhd
+++ b/common/firmware/hdl/LinkAggregatorIPBus.vhd
@@ -43,13 +43,15 @@ architecture Behavorial of LinkAggregatorIPBus is
     -- signal link_aggregator_status_registers : ipb_reg_v(4 - 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
 
     --==============================--
@@ -107,7 +109,7 @@ begin
     --==============================--
     generic map(
         N_CTRL       => 0,
-        N_STAT       => 1
+        N_STAT       => 2
     )
     port map(
         clk          => ipb_clk,
@@ -219,9 +221,11 @@ begin
         --- 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
     );
     
     rate_monitoring_registers(0) <= bx_valid_count(0);
+    rate_monitoring_registers(1) <= tracking_event_count;
 
 end Behavorial;
diff --git a/common/firmware/hdl/tracking_constants.vhd b/common/firmware/hdl/tracking_constants.vhd
new file mode 100644
index 00000000..121f21cf
--- /dev/null
+++ b/common/firmware/hdl/tracking_constants.vhd
@@ -0,0 +1,11 @@
+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;
+    
+end package tracking_constants;
\ No newline at end of file
-- 
GitLab


From 06c36925bc54117e1f1a7aab5ef3babbea6cd51d Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sat, 9 Sep 2023 19:21:51 +0200
Subject: [PATCH 044/109] Fixed syntax error

---
 common/firmware/hdl/LinkAggregatorCore.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index 4456b4d3..b80a640a 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -29,7 +29,7 @@ entity LinkAggregatorCore is
         readout_reset      : out std_logic := '0';
         --- Debug Ports ---
         status_bits        : out std_logic_vector(15 downto 0);
-        debug_tracking_event_count : out std_logic_vector(31 downto 0) := (others => '0')
+        debug_tracking_event_count : out std_logic_vector(31 downto 0) := (others => '0');
         non_empty_counts   : out ipb_reg_v(8*N_LINKS - 1 downto 0);
         bx_valid_count_out : out ipb_reg_v(0 downto 0)
     );
-- 
GitLab


From 23e9d36ed99300592d6f472e390c54969df15a0d Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 00:42:04 +0200
Subject: [PATCH 045/109] Added extra debug signals to Aggregator

---
 common/firmware/cfg/module.dep             |  1 +
 common/firmware/hdl/LinkAggregatorCore.vhd | 42 +++++++++-----
 common/firmware/hdl/TrackFinder.vhd        | 65 ++++++++++++++++++++++
 common/firmware/hdl/tracking_constants.vhd | 57 ++++++++++++++++++-
 4 files changed, 151 insertions(+), 14 deletions(-)
 create mode 100644 common/firmware/hdl/TrackFinder.vhd

diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index 2036591c..9c4f36cf 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -14,6 +14,7 @@ src LinkCombinerIPBus.vhd
 src --vhdl2008 TrackReconstructor.vhd
 src mprocessor_data_types.vhd
 src PayloadHeaderGenerator.vhd
+src TrackFinder.vhd
 
 src EcalLinkInterface.vhd 
 src EcalDataDecoder.vhd 
diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index b80a640a..8bfa4f07 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -30,6 +30,7 @@ entity LinkAggregatorCore is
         --- Debug Ports ---
         status_bits        : out std_logic_vector(15 downto 0);
         debug_tracking_event_count : out std_logic_vector(31 downto 0) := (others => '0');
+        debug_tracking_stubs_out : out ldata(5 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)
     );
@@ -145,8 +146,10 @@ architecture compressed of LinkAggregatorCore is
     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 : tTrackStubs := (others => LWORD_NULL);
+    signal track_stubs : ldata(5 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');
@@ -270,8 +273,8 @@ begin
             -- 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;
             
             
             --==============================--
@@ -313,7 +316,7 @@ begin
                 data_count => count_route
             );
 
-            -- Combine the IPBus 'reset' with the 'packet_start_buffered' signal to generate the reset signal for the routing FIFO.
+            -- Combine the IPBus 'reset' with the 'packet_start' signal to generate the reset signal for the routing FIFO.
             route_reset <= reset or packet_start_buffered;
                 
         end generate genLinkBxCache;
@@ -400,13 +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;
@@ -453,7 +456,7 @@ 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
+            if counter = 49 then
                 readout_reset_signal <= '1';
             else
                 readout_reset_signal <= '0';
@@ -489,19 +492,31 @@ begin
         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' and event_valid_for_tracking = '1' then
-                tracking_event_count <= tracking_event_count + 1;
+            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 5 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
@@ -519,5 +534,6 @@ begin
     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/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
new file mode 100644
index 00000000..32e63137
--- /dev/null
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -0,0 +1,65 @@
+----------------------------------------------------------------------------------
+-- 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;
+
+entity TrackFinder is
+    port (
+        clk_p : in STD_LOGIC;
+        stubs_in : in ldata(5 downto 0) := (others => LWORD_NULL);
+        header_start : in std_logic
+    );
+end TrackFinder;
+
+architecture Behavioral of TrackFinder is
+
+    signal stub_array : tDecodedStubArray := (others => cNullDecodedStub);
+    signal valid_event_array : std_logic_vector(5 downto 0);
+    signal valid_event : std_logic := '0';
+
+begin
+
+    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;
+        end if;
+    end process pMain;
+
+end Behavioral;
diff --git a/common/firmware/hdl/tracking_constants.vhd b/common/firmware/hdl/tracking_constants.vhd
index 121f21cf..32964941 100644
--- a/common/firmware/hdl/tracking_constants.vhd
+++ b/common/firmware/hdl/tracking_constants.vhd
@@ -8,4 +8,59 @@ package tracking_constants is
     
     type tTrackStubs is array (0 to 5) of lword;
     
-end package tracking_constants;
\ No newline at end of file
+    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;
-- 
GitLab


From bddfbfa00db30e6a53124b0e9de53d8da178a73e Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 09:44:46 +0200
Subject: [PATCH 046/109] Added localx histogram

---
 common/addr_table/mprocessor.xml            | 12 +++--
 common/firmware/hdl/LinkAggregatorIPBus.vhd |  4 +-
 common/firmware/hdl/MProcessor.vhd          | 55 +++++++++++++++------
 common/firmware/hdl/TrackFinder.vhd         | 54 +++++++++++++++++++-
 top/addr_table/emp_payload.xml              |  2 +-
 5 files changed, 106 insertions(+), 21 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 9a988f46..5d54a3c0 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -10,14 +10,18 @@
         <node id="header_user_bits" address="0x1"/>
     </node>
     
-    <node id="csr" address="0x30" description="MProcessor control and status" fwinfo="endpoint;width=3">
+    <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="occupancy_windowL"   address="0x1"/>
         <node id="occupancy_windowH"   address="0x2" mask="0x000f"/>
-        <node id="lff"                 address="0x4" mask="0x0001"/>
-        <node id="super_id"            address="0x5"/>
-        <node id="occupancy_max_value" address="0x6"/>
+        <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="tracking_localx_mem" address="0x1000" size="0x1000" mode="incremental" fwinfo="endpoint;width=12"/>
 </node>
diff --git a/common/firmware/hdl/LinkAggregatorIPBus.vhd b/common/firmware/hdl/LinkAggregatorIPBus.vhd
index 4ff1f48d..1445c4ea 100644
--- a/common/firmware/hdl/LinkAggregatorIPBus.vhd
+++ b/common/firmware/hdl/LinkAggregatorIPBus.vhd
@@ -24,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(5 downto 0) := (others => LWORD_NULL);
         --- IPBus Ports ---
         ipb_clk            : in  std_logic;
         ipb_rst            : in  std_logic;
@@ -222,7 +223,8 @@ begin
         -- status_bits      => link_aggregator_status_registers(3)(15 downto 0),
         non_empty_counts => mprocessor_monitoring_registers,
         bx_valid_count_out => bx_valid_count,
-        debug_tracking_event_count => tracking_event_count
+        debug_tracking_event_count => tracking_event_count,
+        debug_tracking_stubs_out => tracking_stubs
     );
     
     rate_monitoring_registers(0) <= bx_valid_count(0);
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index d8a4465b..6e1be92d 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -50,8 +50,8 @@ 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(3 - 1 downto 0)   := (others => (others => '0'));
-    signal control_registers       : ipb_reg_v(3 - 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');
 
@@ -62,7 +62,11 @@ architecture Behavorial of MProcessor is
     signal occupancy_histogram_reset                  : std_logic                                := '0';
     signal debug_packet_size                          : lword                                    := LWORD_NULL;
 
-
+    signal tracking_stubs : ldata(5 downto 0) := (others => 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');
 
 begin
 
@@ -90,8 +94,8 @@ begin
     MProcessorControlInstance: entity work.ipbus_ctrlreg_v
     --==============================--
     generic map(
-        N_CTRL    => 3,
-        N_STAT    => 3
+        N_CTRL    => 5,
+        N_STAT    => 4
     )
     port map(
         clk       => ipb_clk,
@@ -111,17 +115,18 @@ begin
     )
     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)
     );
 
     --==============================--
@@ -160,6 +165,24 @@ 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,
+        localx_trigger_window => localx_trigger_window,
+        --- Output Ports ---
+        localx_max_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)
+    );
+
     link_aggregator_input(N_LINKS - 1 downto 0) <= links_in;
 
     status_registers(0)(0) <= gbe_backpressure;
@@ -204,8 +227,12 @@ begin
     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;
+    localx_trigger_window_lower <= control_registers(3);
+    localx_trigger_window_upper <= control_registers(4)(3 downto 0);
+    localx_trigger_window       <= localx_trigger_window_upper & localx_trigger_window_lower;
 
     status_registers(2)(32 - 1 downto 0) <= occupancy_max_value;
+    status_registers(3)(32 - 1 downto 0) <= localx_max_value;
 
 
 end Behavorial;
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 32e63137..374ad69f 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -31,7 +31,14 @@ entity TrackFinder is
     port (
         clk_p : in STD_LOGIC;
         stubs_in : in ldata(5 downto 0) := (others => LWORD_NULL);
-        header_start : in std_logic
+        header_start : in std_logic;
+        localx_trigger_window : std_logic_vector(36 - 1 downto 0) := X"0ffffffff";
+        localx_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0')
+        --- IPBus Ports ---
+        ipb_clk            : in  std_logic;
+        ipb_rst            : in  std_logic;
+        ipb_in             : in  ipb_wbus;
+        ipb_out            : out ipb_rbus;
     );
 end TrackFinder;
 
@@ -41,6 +48,9 @@ architecture Behavioral of TrackFinder is
     signal valid_event_array : std_logic_vector(5 downto 0);
     signal valid_event : std_logic := '0';
 
+    signal histogram_input : lword := LWORD_NULL;
+    signal localx_histogram_reset : std_logic := '0';
+
 begin
 
     genValidEventArray: for i in 0 to 5 generate
@@ -59,7 +69,49 @@ begin
                     end if;
                 end loop;
             end if;
+            valid_event <= and_reduce(valid_event_array) and headder_start;
+
+            if valid_event then
+                histogram_input.valid <= '1';
+                histogram_input.data(11 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 12));
+            else
+                histogram_input <= LWORD_NULL;
+            end if;
         end if;
     end process pMain;
 
+
+    --==============================--
+    LocalXHistogramInstance : entity work.IPBusHistogram
+    --==============================--
+    generic map (
+        input_width => 12,
+        bin_width   => 32,
+        data_offset => 0
+    )
+    port map (
+        --- Input Ports ---
+        clk_p           => clk_p,
+        data_in         => 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_in,
+        ipb_out         => ipb_out
+    );
+
+    --==============================--
+    LocalXHistogramResetter : entity work.HistogramResetter
+    --==============================--
+    port map (
+        --- Input Ports ---
+        clk_p           => clk_p,
+        trigger_window  => localx_trigger_window,
+        --- Output Ports ---
+        histogram_reset => localx_histogram_reset
+    );
+
 end Behavioral;
diff --git a/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index 88bd97a3..65601aff 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -13,7 +13,7 @@
 
     <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=12"/>
+    <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"/>
-- 
GitLab


From 8db46df38756554d8c3203cee93a9d457c02b7e1 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 09:56:05 +0200
Subject: [PATCH 047/109] Fixed syntax error

---
 common/firmware/hdl/TrackFinder.vhd | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 374ad69f..132f7dbe 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -33,12 +33,12 @@ entity TrackFinder is
         stubs_in : in ldata(5 downto 0) := (others => LWORD_NULL);
         header_start : in std_logic;
         localx_trigger_window : std_logic_vector(36 - 1 downto 0) := X"0ffffffff";
-        localx_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0')
+        localx_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0');
         --- IPBus Ports ---
         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
     );
 end TrackFinder;
 
-- 
GitLab


From 3b202eba432b2790ccaf5a818c4c82c05f9e0b23 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 10:06:33 +0200
Subject: [PATCH 048/109] Added IPBus headers

---
 common/firmware/hdl/TrackFinder.vhd | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 132f7dbe..7c066adb 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -27,6 +27,9 @@ 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;
+
 entity TrackFinder is
     port (
         clk_p : in STD_LOGIC;
-- 
GitLab


From e49dba0726af0d7bb17d0b7a9de08caf4b5a3be4 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 10:16:49 +0200
Subject: [PATCH 049/109] Fixed syntax error

---
 common/firmware/hdl/TrackFinder.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 7c066adb..e11a074e 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -72,7 +72,7 @@ begin
                     end if;
                 end loop;
             end if;
-            valid_event <= and_reduce(valid_event_array) and headder_start;
+            valid_event <= and_reduce(valid_event_array) and header_start;
 
             if valid_event then
                 histogram_input.valid <= '1';
-- 
GitLab


From 35b029e861e85c47a30b475c15f18e25ffdfd33b Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 10:35:05 +0200
Subject: [PATCH 050/109] Fixed bug

---
 common/firmware/hdl/TrackFinder.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index e11a074e..da246eb0 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -74,7 +74,7 @@ begin
             end if;
             valid_event <= and_reduce(valid_event_array) and header_start;
 
-            if valid_event then
+            if valid_event = '1' then
                 histogram_input.valid <= '1';
                 histogram_input.data(11 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 12));
             else
-- 
GitLab


From f65e9694360f0363230fbb05bd690c47265a819b Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 10:49:46 +0200
Subject: [PATCH 051/109] Reduced histogram size

---
 common/addr_table/mprocessor.xml    | 2 +-
 common/firmware/hdl/TrackFinder.vhd | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 5d54a3c0..3ee488e1 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -23,5 +23,5 @@
     </node>
 
     <node id="occupancy_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
-    <node id="tracking_localx_mem" address="0x1000" size="0x1000" mode="incremental" fwinfo="endpoint;width=12"/>
+    <node id="tracking_localx_mem" address="0x500" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
 </node>
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index da246eb0..09979882 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -35,8 +35,8 @@ entity TrackFinder is
         clk_p : in STD_LOGIC;
         stubs_in : in ldata(5 downto 0) := (others => LWORD_NULL);
         header_start : in std_logic;
-        localx_trigger_window : std_logic_vector(36 - 1 downto 0) := X"0ffffffff";
-        localx_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0');
+        localx_trigger_window : in std_logic_vector(36 - 1 downto 0) := X"0ffffffff";
+        localx_max_value :  out std_logic_vector(32 - 1 downto 0) := (others => '0');
         --- IPBus Ports ---
         ipb_clk            : in  std_logic;
         ipb_rst            : in  std_logic;
@@ -88,9 +88,9 @@ begin
     LocalXHistogramInstance : entity work.IPBusHistogram
     --==============================--
     generic map (
-        input_width => 12,
+        input_width => 8,
         bin_width   => 32,
-        data_offset => 0
+        data_offset => 4
     )
     port map (
         --- Input Ports ---
-- 
GitLab


From 7f679e3845cd221e228f530e472f33cd05870b63 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 11:00:51 +0200
Subject: [PATCH 052/109] Restructured IPBus

---
 common/addr_table/mprocessor.xml    |  3 +-
 common/addr_table/track_finder.xml  |  9 ++++
 common/firmware/cfg/module.dep      |  1 +
 common/firmware/hdl/MProcessor.vhd  | 16 ++-----
 common/firmware/hdl/TrackFinder.vhd | 66 ++++++++++++++++++++++++++---
 5 files changed, 75 insertions(+), 20 deletions(-)
 create mode 100644 common/addr_table/track_finder.xml

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 3ee488e1..744de77b 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -23,5 +23,6 @@
     </node>
 
     <node id="occupancy_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
-    <node id="tracking_localx_mem" address="0x500" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
+
+    <node id="track_finder" address="0x600" module="file://track_finder.xml" fwinfo="endpoint;width=9"/>
 </node>
diff --git a/common/addr_table/track_finder.xml b/common/addr_table/track_finder.xml
new file mode 100644
index 00000000..dd4150f0
--- /dev/null
+++ b/common/addr_table/track_finder.xml
@@ -0,0 +1,9 @@
+<node description="TrackFinder Control and Status" fwinfo="endpoint">
+    <node id="csr" address="0x00" description="TrackFinder control and status" fwinfo="endpoint;width=2">
+        <node id="localx_windowL"      address="0x0"/>
+        <node id="localx_windowH"      address="0x1" mask="0x000f"/>
+        <node id="localx_max_value"    address="0x2"/>
+    </node>
+
+    <node id="tracking_localx_mem" address="0x100" 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 9c4f36cf..735abc14 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -31,6 +31,7 @@ src ipbus_decode_eprocessor.vhd
 addrtab -t mprocessor.xml
 addrtab -t eprocessor.xml
 addrtab -t link_aggregator.xml
+addrtab -t track_finder.xml
 
 # IP Cores
 src --cd ../cgn link_agg_single_link_fifo.xci
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 6e1be92d..aef64452 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -63,10 +63,6 @@ architecture Behavorial of MProcessor is
     signal debug_packet_size                          : lword                                    := LWORD_NULL;
 
     signal tracking_stubs : ldata(5 downto 0) := (others => 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');
 
 begin
 
@@ -177,10 +173,10 @@ begin
         --- Output Ports ---
         localx_max_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)
+        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;
@@ -227,12 +223,8 @@ begin
     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;
-    localx_trigger_window_lower <= control_registers(3);
-    localx_trigger_window_upper <= control_registers(4)(3 downto 0);
-    localx_trigger_window       <= localx_trigger_window_upper & localx_trigger_window_lower;
 
     status_registers(2)(32 - 1 downto 0) <= occupancy_max_value;
-    status_registers(3)(32 - 1 downto 0) <= localx_max_value;
 
 
 end Behavorial;
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 09979882..efa96bc2 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -29,14 +29,14 @@ 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);
+        clk_p        : in STD_LOGIC;
+        stubs_in     : in ldata(5 downto 0) := (others => LWORD_NULL);
         header_start : in std_logic;
-        localx_trigger_window : in std_logic_vector(36 - 1 downto 0) := X"0ffffffff";
-        localx_max_value :  out std_logic_vector(32 - 1 downto 0) := (others => '0');
         --- IPBus Ports ---
         ipb_clk            : in  std_logic;
         ipb_rst            : in  std_logic;
@@ -47,21 +47,67 @@ 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(1 - 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 histogram_input : lword := LWORD_NULL;
-    signal localx_histogram_reset : std_logic := '0';
+    
+    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';
 
 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    => 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
+    );
+
+    --==============================--
     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
@@ -102,8 +148,8 @@ begin
         --- IPBus Ports ---
         clk             => ipb_clk,
         rst             => ipb_rst,
-        ipb_in          => ipb_in,
-        ipb_out         => ipb_out
+        ipbus_in  => ipb_to_slaves(N_SLV_TRACKING_LOCALX_MEM),
+        ipbus_out => ipb_from_slaves(N_SLV_TRACKING_LOCALX_MEM)
     );
 
     --==============================--
@@ -117,4 +163,10 @@ begin
         histogram_reset => localx_histogram_reset
     );
 
+    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;
+
 end Behavioral;
-- 
GitLab


From 5c80c50c9e3542f9a86ff3e65e87aed38e484a10 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 11:12:40 +0200
Subject: [PATCH 053/109] Added missing src

---
 common/firmware/cfg/module.dep | 1 +
 1 file changed, 1 insertion(+)

diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index 735abc14..804dc871 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -27,6 +27,7 @@ src EcalDataMonitor.vhd
 src ipbus_decode_link_aggregator.vhd
 src ipbus_decode_mprocessor.vhd
 src ipbus_decode_eprocessor.vhd
+src ipbus_decode_track_finder.vhd
 
 addrtab -t mprocessor.xml
 addrtab -t eprocessor.xml
-- 
GitLab


From 758d134a6184deb219d45cc69dd2874589300420 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 11:24:50 +0200
Subject: [PATCH 054/109] Added second histogram

---
 common/addr_table/mprocessor.xml    |  2 +-
 common/addr_table/track_finder.xml  |  2 +
 common/firmware/hdl/TrackFinder.vhd | 84 +++++++++++++++++++++++++----
 3 files changed, 76 insertions(+), 12 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 744de77b..21272a11 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -24,5 +24,5 @@
 
     <node id="occupancy_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
 
-    <node id="track_finder" address="0x600" module="file://track_finder.xml" fwinfo="endpoint;width=9"/>
+    <node id="track_finder" address="0x800" module="file://track_finder.xml" fwinfo="endpoint;width=10"/>
 </node>
diff --git a/common/addr_table/track_finder.xml b/common/addr_table/track_finder.xml
index dd4150f0..83efe87c 100644
--- a/common/addr_table/track_finder.xml
+++ b/common/addr_table/track_finder.xml
@@ -3,7 +3,9 @@
         <node id="localx_windowL"      address="0x0"/>
         <node id="localx_windowH"      address="0x1" mask="0x000f"/>
         <node id="localx_max_value"    address="0x2"/>
+        <node id="deltax_max_value"    address="0x3"/>
     </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>
\ No newline at end of file
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index efa96bc2..8a8e27cf 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -50,14 +50,18 @@ 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(1 - 1 downto 0)   := (others => (others => '0'));
+    signal status_registers        : ipb_reg_v(2 - 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 stub_array        : tDecodedStubArray := (others => cNullDecodedStub);
     signal valid_event_array : std_logic_vector(5 downto 0);
-    signal valid_event : std_logic := '0';
+    signal valid_event       : std_logic := '0';
 
-    signal histogram_input : lword := LWORD_NULL;
+    signal counter     : integer := 0;
+    signal track_delta : integer := 0;
+
+    signal localx_histogram_input : lword := LWORD_NULL;
+    signal deltax_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');
@@ -65,6 +69,8 @@ architecture Behavioral of TrackFinder is
     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');
+
 begin
 
     --==============================--
@@ -87,7 +93,7 @@ begin
     --==============================--
     generic map(
         N_CTRL    => 2,
-        N_STAT    => 1
+        N_STAT    => 2
     )
     port map(
         clk       => ipb_clk,
@@ -121,14 +127,47 @@ begin
             valid_event <= and_reduce(valid_event_array) and header_start;
 
             if valid_event = '1' then
-                histogram_input.valid <= '1';
-                histogram_input.data(11 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 12));
+                track_delta <= stub_array(4).localx - stub_array(0).localx + 1;
+            end if;
+            if counter = 1 then
+                if (track_delta > -127) and (track_delta < 127) then
+                    deltax_histogram_input.valid <= '1';
+                    deltax_histogram_input.data(7 downto 0) <= std_logic_vector(to_unsigned(track_delta + 128, 8));
+                else
+                    deltax_histogram_input <= LWORD_NULL;
+                end if;
             else
-                histogram_input <= LWORD_NULL;
+                deltax_histogram_input <= LWORD_NULL;
+            end if;
+
+            if valid_event = '1' then
+                localx_histogram_input.valid <= '1';
+                localx_histogram_input.data(11 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 12));
+            else
+                localx_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
@@ -141,15 +180,15 @@ begin
     port map (
         --- Input Ports ---
         clk_p           => clk_p,
-        data_in         => histogram_input,
+        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,
-        ipbus_in  => ipb_to_slaves(N_SLV_TRACKING_LOCALX_MEM),
-        ipbus_out => ipb_from_slaves(N_SLV_TRACKING_LOCALX_MEM)
+        ipb_in          => ipb_to_slaves(N_SLV_TRACKING_LOCALX_MEM),
+        ipb_out         => ipb_from_slaves(N_SLV_TRACKING_LOCALX_MEM)
     );
 
     --==============================--
@@ -163,10 +202,33 @@ begin
         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)
+    );
+
     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;
 
 end Behavioral;
-- 
GitLab


From b2e2ff9f9a84ad9642c2560c088dec838943b511 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 11:35:52 +0200
Subject: [PATCH 055/109] Removed ports

---
 common/firmware/hdl/MProcessor.vhd | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index aef64452..5fdfe885 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -169,9 +169,6 @@ begin
         clk_p => clk_p,
         stubs_in => tracking_stubs,
         header_start => packet_start,
-        localx_trigger_window => localx_trigger_window,
-        --- Output Ports ---
-        localx_max_value => localx_max_value,
         --- IPBus Ports ---
         ipb_clk             => ipb_clk,
         ipb_rst             => ipb_rst,
-- 
GitLab


From 3af184ec2c03467c025832cb4053813686ce8904 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 16:35:16 +0200
Subject: [PATCH 056/109] Updated offset

---
 common/firmware/hdl/MProcessor.vhd  | 4 ++--
 common/firmware/hdl/TrackFinder.vhd | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 5fdfe885..9ccd7790 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -172,8 +172,8 @@ begin
         --- 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)
+        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;
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 8a8e27cf..ac06ff40 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -142,7 +142,7 @@ begin
 
             if valid_event = '1' then
                 localx_histogram_input.valid <= '1';
-                localx_histogram_input.data(11 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 12));
+                localx_histogram_input.data(10 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 11));
             else
                 localx_histogram_input <= LWORD_NULL;
             end if;
@@ -175,7 +175,7 @@ begin
     generic map (
         input_width => 8,
         bin_width   => 32,
-        data_offset => 4
+        data_offset => 3
     )
     port map (
         --- Input Ports ---
-- 
GitLab


From 168920e0bdea0182bf1451b8c05fa6f9ce5783c2 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 16:47:04 +0200
Subject: [PATCH 057/109] Added histograms for Y axis

---
 common/addr_table/mprocessor.xml    |  2 +-
 common/addr_table/track_finder.xml  | 10 ++--
 common/firmware/hdl/TrackFinder.vhd | 82 ++++++++++++++++++++++++++---
 3 files changed, 83 insertions(+), 11 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 21272a11..b25246c8 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -24,5 +24,5 @@
 
     <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=10"/>
+    <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
index 83efe87c..176246e6 100644
--- a/common/addr_table/track_finder.xml
+++ b/common/addr_table/track_finder.xml
@@ -1,11 +1,15 @@
 <node description="TrackFinder Control and Status" fwinfo="endpoint">
-    <node id="csr" address="0x00" description="TrackFinder control and status" fwinfo="endpoint;width=2">
+    <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="0x2"/>
-        <node id="deltax_max_value"    address="0x3"/>
+        <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_localx_mem" address="0x300" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
+    <node id="tracking_deltax_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
 </node>
\ No newline at end of file
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index ac06ff40..80d98294 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -50,18 +50,21 @@ 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(2 - 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(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 : integer := 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');
@@ -70,6 +73,8 @@ architecture Behavioral of TrackFinder is
     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
 
@@ -93,7 +98,7 @@ begin
     --==============================--
     generic map(
         N_CTRL    => 2,
-        N_STAT    => 2
+        N_STAT    => 4
     )
     port map(
         clk       => ipb_clk,
@@ -127,12 +132,12 @@ begin
             valid_event <= and_reduce(valid_event_array) and header_start;
 
             if valid_event = '1' then
-                track_delta <= stub_array(4).localx - stub_array(0).localx + 1;
+                track_delta_x <= stub_array(4).localx - stub_array(0).localx + 1;
             end if;
             if counter = 1 then
-                if (track_delta > -127) and (track_delta < 127) 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 + 128, 8));
+                    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;
@@ -140,11 +145,28 @@ begin
                 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;
@@ -224,11 +246,57 @@ begin
         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)
+    );
+
+    --==============================--
+    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         => 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;
-- 
GitLab


From a3b247091b8d12f88dd7a9cc6c114c89152212df Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 17:20:27 +0200
Subject: [PATCH 058/109] Fixed naming

---
 common/addr_table/track_finder.xml  | 4 ++--
 common/firmware/hdl/TrackFinder.vhd | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/common/addr_table/track_finder.xml b/common/addr_table/track_finder.xml
index 176246e6..cbe8cca8 100644
--- a/common/addr_table/track_finder.xml
+++ b/common/addr_table/track_finder.xml
@@ -10,6 +10,6 @@
 
     <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_localx_mem" address="0x300" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
-    <node id="tracking_deltax_mem" address="0x400" 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/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 80d98294..36a7c9cf 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -269,7 +269,7 @@ begin
     );
 
     --==============================--
-    DeltaXHistogramInstance : entity work.IPBusHistogram
+    DeltaYHistogramInstance : entity work.IPBusHistogram
     --==============================--
     generic map (
         input_width => 8,
-- 
GitLab


From c7edb209e515e9545389272aa853642ed960046d Mon Sep 17 00:00:00 2001
From: Kirika Uchida <kirika.uchida@cern.ch>
Date: Sun, 10 Sep 2023 18:07:19 +0200
Subject: [PATCH 059/109] Revert "added a buffer at ZSF"

---
 common/addr_table/eprocessor.xml              |   9 +-
 common/firmware/cfg/module.dep                |   1 +
 common/firmware/hdl/EcalDataAggregator.vhd    |  23 +++-
 common/firmware/hdl/EcalDataDecoder.vhd       |  12 +-
 common/firmware/hdl/EcalDataFilter.vhd        |  53 +++++--
 common/firmware/hdl/EcalDataProcessor.vhd     | 130 +++++++++++-------
 .../hdl/EcalZeroSuppressionFilter.vhd         |   8 +-
 .../firmware/ucf/eprocessor_constraints.tcl   |   4 +
 top/firmware/hdl/emp_payload.vhd              |   2 +-
 top/firmware/hdl/emp_project_decl.vhd         |  12 +-
 10 files changed, 168 insertions(+), 86 deletions(-)
 create mode 100644 common/firmware/ucf/eprocessor_constraints.tcl

diff --git a/common/addr_table/eprocessor.xml b/common/addr_table/eprocessor.xml
index ad686de3..4d191f63 100644
--- a/common/addr_table/eprocessor.xml
+++ b/common/addr_table/eprocessor.xml
@@ -1,18 +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="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="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 id="mon" address="0x80" description="Ecal data monitoring" fwinfo="endpoint;width=2"/>
 </node>
diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index 804dc871..7c3a1915 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -34,6 +34,7 @@ addrtab -t eprocessor.xml
 addrtab -t link_aggregator.xml
 addrtab -t track_finder.xml
 
+
 # IP Cores
 src --cd ../cgn link_agg_single_link_fifo.xci
 setup -f --cd ../cgn link_agg_single_link_fifo.tcl
diff --git a/common/firmware/hdl/EcalDataAggregator.vhd b/common/firmware/hdl/EcalDataAggregator.vhd
index 65ee6c27..a6c216db 100644
--- a/common/firmware/hdl/EcalDataAggregator.vhd
+++ b/common/firmware/hdl/EcalDataAggregator.vhd
@@ -28,6 +28,10 @@ architecture rtl of EcalDataAggregator is
   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);
@@ -67,14 +71,19 @@ begin
             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_start <= '0';
-          data_out_last <= '0';
+          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 <= ecal_data_p;
-               data_out_start <= '1';
+               data_out_s <= ecal_data_p;
+               data_out_s_start <= '1';
                last_valid_bcid <= bcid_p(0);
                sync <= '1';
              elsif timer = 7 then
@@ -86,8 +95,8 @@ begin
             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 <= ecal_data_p;
-                data_out_start <= '1'; 
+                data_out_s <= ecal_data_p;
+                data_out_s_start <= '1'; 
                 last_valid_bcid <= bcid_p(0);
               else
                 sync <= '0';
@@ -95,7 +104,7 @@ begin
             else 
                timer := timer + 1;
                if timer = 7 then
-                 data_out_last <= '1';
+                 data_out_s_last <= '1';
                end if;
             end if;
           end if;
diff --git a/common/firmware/hdl/EcalDataDecoder.vhd b/common/firmware/hdl/EcalDataDecoder.vhd
index d5f3ee31..680001ec 100644
--- a/common/firmware/hdl/EcalDataDecoder.vhd
+++ b/common/firmware/hdl/EcalDataDecoder.vhd
@@ -25,6 +25,10 @@ architecture rtl of EcalDataDecoder is
       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)
@@ -32,11 +36,9 @@ begin
   begin
     if rising_edge(clk_p) then
        
-        for j in 0 to 1 loop
-            for i in 0 to 6 loop 
-                elink_data(j*7+i) <= elink_data(j*7+i)(6 downto 0) & data_in.data(j*32+i);
-            end loop;
-        end loop;
+	    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;
 
diff --git a/common/firmware/hdl/EcalDataFilter.vhd b/common/firmware/hdl/EcalDataFilter.vhd
index 0754a9f6..12471a16 100644
--- a/common/firmware/hdl/EcalDataFilter.vhd
+++ b/common/firmware/hdl/EcalDataFilter.vhd
@@ -16,7 +16,7 @@ port (
         clk_p            : in  std_logic;
         clk40            : in  std_logic;
         reset            : in  std_logic;
-        data_in_valid    : 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);
@@ -35,9 +35,11 @@ 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_meta         : std_logic_vector(28 * 16 -1 downto 0);
-  signal data_sync         : std_logic_vector(28 * 16 -1 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);
@@ -73,24 +75,55 @@ begin
   );
 
   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     <= trig_sync    when bypass_s = '0' else x"c0000001";
+  trig_o     <= trig40       when bypass_s = '0' else b_trg & b_trg & "00" & x"000000" & "000" & b_trg;
 
-  data_meta   <= data_in   when rising_edge(clk40);
-  data_sync   <= data_meta when rising_edge(clk40);
-  
-  trig_meta    <= trig40    when rising_edge(clk_p);
-  trig_sync    <= trig_meta when rising_edge(clk_p);
+  -- 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;
@@ -112,7 +145,7 @@ begin
   port map (
     clk                => clk40,
     rst                => reset,
-    lpgbt_payload_i    => data_sync,
+    lpgbt_payload_i    => data_s,
     sc_regs_i          => zs_sc_regs,
     valid_o            => zs_valid,
     all_valids_o       => zs_all_valids,
diff --git a/common/firmware/hdl/EcalDataProcessor.vhd b/common/firmware/hdl/EcalDataProcessor.vhd
index 64c1eb69..bebd5bc5 100644
--- a/common/firmware/hdl/EcalDataProcessor.vhd
+++ b/common/firmware/hdl/EcalDataProcessor.vhd
@@ -62,6 +62,7 @@ architecture rtl of EcalDataProcessor is
   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);
@@ -115,10 +116,11 @@ begin
   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)(9) <= data_ready_i;
-  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)(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);
@@ -144,7 +146,7 @@ begin
     clk_p              => clk_p,
     clk40              => clk40,
     reset              => reset,
-    data_in_valid      => data_start,
+    data_in_start      => data_start,
     data_in            => data,
     trig_o_lat         => trig_lat,
     trig_o             => trig,
@@ -201,8 +203,11 @@ begin
   ); 
   
   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';
@@ -218,14 +223,30 @@ begin
           data_out(0).strobe <= '0';
           case ostate is
             when wait_start =>
-              if data_out_s.start = '1' then
+							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;
-                if data_out_s.last = '1' then
+								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 
@@ -329,7 +350,6 @@ begin
             if t_waddr_valid then
               trig_ram_wea   <= '1';
               trig_ram_addra <= std_logic_vector(to_unsigned(t_waddr,6));
-              trig_ram_dina  <= trig;
             end if;
           end if;  
  
@@ -344,15 +364,58 @@ begin
             
             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;
+              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;
-
-            data_out_s.valid <= trig_ram_doutb(0) and data_ram_doutb(bit_valid);           
-            data_out_s.start <= trig_ram_doutb(31) and data_ram_doutb(bit_start) and gbe_backpressure;
-            data_out_s.last  <= trig_ram_doutb(30) and data_ram_doutb(bit_last);
-            data_out_s.strobe <= trig_ram_doutb(30) and data_ram_doutb(bit_last);         
           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
@@ -415,45 +478,6 @@ begin
             g_timer := g_timer + 1;
           end if;
             
-          -- data to write                   
-          data_ram_addra <= std_logic_vector(to_unsigned(d_waddr, 9));
-          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
-            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
-              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
-          
         end if;   
     end process;
     
diff --git a/common/firmware/hdl/EcalZeroSuppressionFilter.vhd b/common/firmware/hdl/EcalZeroSuppressionFilter.vhd
index dd5b23ce..ed8dde99 100644
--- a/common/firmware/hdl/EcalZeroSuppressionFilter.vhd
+++ b/common/firmware/hdl/EcalZeroSuppressionFilter.vhd
@@ -359,10 +359,12 @@ p_SM_com_comb:process(State_com, trg, Cnt_com) is
           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) 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
+          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);                 
diff --git a/common/firmware/ucf/eprocessor_constraints.tcl b/common/firmware/ucf/eprocessor_constraints.tcl
new file mode 100644
index 00000000..ee205f25
--- /dev/null
+++ b/common/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/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index badc237e..f022b583 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -469,7 +469,7 @@ begin
     
 
 
-    gbe_q <= eth_link_out;
+    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);
 
diff --git a/top/firmware/hdl/emp_project_decl.vhd b/top/firmware/hdl/emp_project_decl.vhd
index 971319c1..d704bc63 100644
--- a/top/firmware/hdl/emp_project_decl.vhd
+++ b/top/firmware/hdl/emp_project_decl.vhd
@@ -34,9 +34,9 @@ package emp_project_decl is
 
   -- mgt -> buf -> fmt -> (algo) -> (fmt) -> buf -> mgt -> clk -> altclk
   constant REGION_CONF : region_conf_array_t := (
---    0  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 225 -- Right Column
+  --  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
+  --  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
@@ -62,6 +62,12 @@ package emp_project_decl is
   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),
@@ -86,7 +92,7 @@ package emp_project_decl is
   -- for lpgbt
   constant REGION_LPGBT_CONF : region_lpgbt_conf_array_t := (
 --    2  => (FEC5, DATARATE_5G12, PCS),
---    3  => (FEC5, DATARATE_5G12, PCS),
+    3  => (FEC5, DATARATE_5G12, PCS),
     4  => (FEC5, DATARATE_5G12, PCS),
     5  => (FEC5, DATARATE_5G12, PCS),
     6  => (FEC5, DATARATE_5G12, PCS),
-- 
GitLab


From 93a07bc4871e888acd58ffa8b67baf55f78c458b Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Thu, 14 Sep 2023 08:56:30 +0200
Subject: [PATCH 060/109] Update file emp_payload.vhd

---
 top/firmware/hdl/emp_payload.vhd | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index f022b583..69d7278f 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -94,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
@@ -277,14 +279,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 ---
-- 
GitLab


From ac6b1f27b5065c590935355048697c189e2dfb72 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Fri, 26 Apr 2024 13:10:29 +0200
Subject: [PATCH 061/109] Moved top files to muone algorithm

---
 .gitlab-ci.yml                                    | 4 ++--
 top/{ => muone}/addr_table/emp_payload.xml        | 0
 top/{ => muone}/firmware/cfg/top.dep              | 0
 top/{ => muone}/firmware/hdl/emp_payload.vhd      | 0
 top/{ => muone}/firmware/hdl/emp_project_decl.vhd | 0
 top/{ => muone}/firmware/hdl/link_maps.vhd        | 0
 6 files changed, 2 insertions(+), 2 deletions(-)
 rename top/{ => muone}/addr_table/emp_payload.xml (100%)
 rename top/{ => muone}/firmware/cfg/top.dep (100%)
 rename top/{ => muone}/firmware/hdl/emp_payload.vhd (100%)
 rename top/{ => muone}/firmware/hdl/emp_project_decl.vhd (100%)
 rename top/{ => muone}/firmware/hdl/link_maps.vhd (100%)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8fe1eba7..9d6acdb2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,9 +3,9 @@ include:
     file: "/ci/templates/vivado-jobs.yml"
 
 variables:
-  VIVADO_VER: "2022.2"
+  VIVADO_VER: "2023.2"
   PROJECT_DEPFILE: top.dep
-  PROJECT_ALGORITHM: top
+  PROJECT_ALGORITHM: top/muone
   PROJECT_NAME: mprocessor
   EMPHUB_TAG: $CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA
   IPBB_VER: "dev-2021j-v1.2"
diff --git a/top/addr_table/emp_payload.xml b/top/muone/addr_table/emp_payload.xml
similarity index 100%
rename from top/addr_table/emp_payload.xml
rename to top/muone/addr_table/emp_payload.xml
diff --git a/top/firmware/cfg/top.dep b/top/muone/firmware/cfg/top.dep
similarity index 100%
rename from top/firmware/cfg/top.dep
rename to top/muone/firmware/cfg/top.dep
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/muone/firmware/hdl/emp_payload.vhd
similarity index 100%
rename from top/firmware/hdl/emp_payload.vhd
rename to top/muone/firmware/hdl/emp_payload.vhd
diff --git a/top/firmware/hdl/emp_project_decl.vhd b/top/muone/firmware/hdl/emp_project_decl.vhd
similarity index 100%
rename from top/firmware/hdl/emp_project_decl.vhd
rename to top/muone/firmware/hdl/emp_project_decl.vhd
diff --git a/top/firmware/hdl/link_maps.vhd b/top/muone/firmware/hdl/link_maps.vhd
similarity index 100%
rename from top/firmware/hdl/link_maps.vhd
rename to top/muone/firmware/hdl/link_maps.vhd
-- 
GitLab


From a62ae7c7a8a940f2e456df970245875bbd0458ff Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Wed, 2 Aug 2023 14:54:39 +0200
Subject: [PATCH 062/109] Update file link_maps.vhd

---
 top/firmware/hdl/link_maps.vhd | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index 94784865..6fcd7880 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -5,20 +5,20 @@ use work.dtc_link_maps_func.all;
 
 package dtc_link_maps is
 
-    constant cNumberOfFEModules   : integer := 3;
-    constant cNumberOfOutputLinks : integer := 3;
+    constant cNumberOfFEModules   : integer := 4;
+    constant cNumberOfOutputLinks : integer := 4;
 
     type tDTCInputLinkMap is array(0 to cNumberOfFEModules - 1) of tDTCInputLinkConfig;
     constant cDTCInputLinkMap     : tDTCInputLinkMap := (
         0 => (8,  "2S", 5, "CIC2"),
         1 => (9,  "2S", 5, "CIC2"),
-        -- 2 => (10, "2S", 5, "CIC2"),
+        2 => (10, "2S", 5, "CIC2"),
         2 => (11, "2S", 5, "CIC2")
     );
 
     type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
     constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (
-        16, 17, 18
+        16, 17, 18, 19
     );
 
 end package dtc_link_maps;
-- 
GitLab


From 8e2ab4b8e3fada7d20c3afbaab9428b27b8d9193 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Wed, 2 Aug 2023 15:17:45 +0200
Subject: [PATCH 063/109] Update file link_maps.vhd

---
 top/firmware/hdl/link_maps.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index 6fcd7880..ee8248ca 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -13,7 +13,7 @@ package dtc_link_maps is
         0 => (8,  "2S", 5, "CIC2"),
         1 => (9,  "2S", 5, "CIC2"),
         2 => (10, "2S", 5, "CIC2"),
-        2 => (11, "2S", 5, "CIC2")
+        3 => (11, "2S", 5, "CIC2")
     );
 
     type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
-- 
GitLab


From 88e829062da3bb0b1042d53ffbea6394a2ca5c88 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Thu, 3 Aug 2023 11:19:28 +0200
Subject: [PATCH 064/109] Fixed syntax error

---
 top/firmware/hdl/emp_payload.vhd | 33 ++++++++++++++++----------------
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 6cdb337d..72982d69 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -122,22 +122,7 @@ begin
         );
 
     --==============================--
-    fe_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_FE),
-        ipbus_out => ipb_from_slaves(N_SLV_FE),
-        q         => channel_sel,
-        qmask     => (0 => X"0000007f")
-    );
-
-    --==============================--
-    channel_ctrl : entity work.ipbus_ctrlreg_v
+    fe_channel_ctrl : entity work.ipbus_ctrlreg_v
     --==============================--
     generic map(
         N_CTRL    => 1,
@@ -154,6 +139,22 @@ begin
 
     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_channel_ctrl: entity work.ipbus_reg_v
     --==============================--
-- 
GitLab


From 0a2fc774e178aa617cf99d9804e326056f0575d9 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Mon, 28 Aug 2023 21:24:42 +0200
Subject: [PATCH 065/109] Increased number of modules to 12

---
 top/firmware/hdl/emp_payload.vhd      | 17 ++++++----
 top/firmware/hdl/emp_project_decl.vhd | 47 +++++++++++++++++++--------
 top/firmware/hdl/link_maps.vhd        | 24 +++++++++-----
 3 files changed, 59 insertions(+), 29 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 72982d69..541076f8 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -69,14 +69,14 @@ 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;
+    constant cNumberOfMProcessors                  : integer                                  := 2;
     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';
@@ -139,6 +139,7 @@ begin
 
     fe_status_registers(0) <= std_logic_vector(to_unsigned(cNumberOfFEModules, 32));
 
+
     --==============================--
     channel_select : entity work.ipbus_dc_fabric_sel
     --==============================--
@@ -297,6 +298,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;
 
@@ -382,7 +385,7 @@ begin
             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),
             gbe_backpressure   => gbe_backpressure(i),
             srst               => srst,
             --- Output Ports ---
@@ -441,10 +444,10 @@ begin
     ttc_resync_reset <= mproc_channel_sel(0)(8);
     srst <= mproc_channel_sel(0)(7) or ttc_oc0;
 
-    q(20).valid  <= '1';
-    q(20).data   <= "0000" & std_logic_vector(bunch_counter) & "0000000000000000" & std_logic_vector(orbit_counter);
-    q(20).start  <= '1';
-    q(20).strobe <= '1';
+    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';
 
 
 
diff --git a/top/firmware/hdl/emp_project_decl.vhd b/top/firmware/hdl/emp_project_decl.vhd
index cb139412..971319c1 100644
--- a/top/firmware/hdl/emp_project_decl.vhd
+++ b/top/firmware/hdl/emp_project_decl.vhd
@@ -35,12 +35,12 @@ package emp_project_decl is
   -- mgt -> buf -> fmt -> (algo) -> (fmt) -> buf -> mgt -> clk -> altclk
   constant REGION_CONF : region_conf_array_t := (
 --    0  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 225 -- Right Column
---    1  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 226
+    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  => (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
+    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
@@ -50,9 +50,9 @@ package emp_project_decl is
     --11     => (gty25, buf, no_fmt, buf, gty25),
     --12     => (gty25, buf, no_fmt, buf, gty25),
 -- KH used for gbe
---    13 => (gty25, buf, no_fmt, buf, gty25),   --Bank 131
---    14 => (gty25, buf, no_fmt, buf, gty25),   --Bank 130
---    15 => (gty25, buf, no_fmt, buf, gty25),   --Bank 129
+    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
@@ -60,15 +60,36 @@ 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, 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)),
+--    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)),
+    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),
+--    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
   );
 
@@ -79,7 +100,7 @@ package emp_project_decl is
   );
 
   constant ETH10G_CONF : eth10g_conf_array_t := (
-    0 => (10, "0011", (x"000000000000", x"000000000000", x"aabbccddef53", x"aabbccddef54"))
+    0 => (10, "1111", (x"aabbccddef51", x"aabbccddef52", x"aabbccddef53", x"aabbccddef54"))
   );
 
 
diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index ee8248ca..2c90f179 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -5,21 +5,27 @@ use work.dtc_link_maps_func.all;
 
 package dtc_link_maps is
 
-    constant cNumberOfFEModules   : integer := 4;
-    constant cNumberOfOutputLinks : integer := 4;
+    constant cNumberOfFEModules   : integer := 12;
+    constant cNumberOfOutputLinks : integer := 12;
 
     type tDTCInputLinkMap is array(0 to cNumberOfFEModules - 1) of tDTCInputLinkConfig;
     constant cDTCInputLinkMap     : tDTCInputLinkMap := (
-        0 => (8,  "2S", 5, "CIC2"),
-        1 => (9,  "2S", 5, "CIC2"),
-        2 => (10, "2S", 5, "CIC2"),
-        3 => (11, "2S", 5, "CIC2")
+        0 => (16, "2S", 5, "CIC2"),
+        1 => (17, "2S", 5, "CIC2"),
+        2 => (18, "2S", 5, "CIC2"),
+        3 => (19, "2S", 5, "CIC2"),
+        0 => (20, "2S", 5, "CIC2"),
+        1 => (21, "2S", 5, "CIC2"),
+        2 => (22, "2S", 5, "CIC2"),
+        3 => (23, "2S", 5, "CIC2"),
+        0 => (24, "2S", 5, "CIC2"),
+        1 => (25, "2S", 5, "CIC2"),
+        2 => (26, "2S", 5, "CIC2"),
+        3 => (27, "2S", 5, "CIC2")
     );
 
     type tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
-    constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (
-        16, 17, 18, 19
-    );
+    constant cDTCOutputLinkMap    : tDTCOutputLinkMap := (28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39);
 
 end package dtc_link_maps;
 
-- 
GitLab


From d9370bb48f37e98d22d4f9d1c045b983367476fb Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 09:54:12 +0200
Subject: [PATCH 066/109] Update file link_maps.vhd

---
 top/firmware/hdl/link_maps.vhd | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index 2c90f179..5f03fe20 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -10,18 +10,18 @@ package dtc_link_maps is
 
     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"),
-        0 => (20, "2S", 5, "CIC2"),
-        1 => (21, "2S", 5, "CIC2"),
-        2 => (22, "2S", 5, "CIC2"),
-        3 => (23, "2S", 5, "CIC2"),
-        0 => (24, "2S", 5, "CIC2"),
-        1 => (25, "2S", 5, "CIC2"),
-        2 => (26, "2S", 5, "CIC2"),
-        3 => (27, "2S", 5, "CIC2")
+        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 tDTCOutputLinkMap is array(0 to cNumberOfOutputLinks - 1) of integer;
-- 
GitLab


From f669d32dc31493a12fb2fa717be8fe6375d1b00f Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 10:43:50 +0200
Subject: [PATCH 067/109] Update file emp_payload.vhd

---
 top/firmware/hdl/emp_payload.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 541076f8..88b0d618 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -353,7 +353,7 @@ begin
 
         signal ipb_to_channel        : ipb_wbus;
         signal ipb_from_channel      : ipb_rbus;
-        constant cNumberofInputLinks : integer := cNumberOfFEModules;
+        constant cNumberofInputLinks : integer := 6;
 
     begin
 
-- 
GitLab


From 8051e7e5be303d8debbddae1bccf8280e6afee29 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 12:48:10 +0200
Subject: [PATCH 068/109] Update file LinkAggregatorCore.vhd

---
 common/firmware/hdl/LinkAggregatorCore.vhd | 32 ++++++++--------------
 1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index de44256f..5b82488f 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -1,6 +1,7 @@
 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.ipbus.all;
@@ -131,7 +132,8 @@ architecture compressed of LinkAggregatorCore is
     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;
@@ -195,7 +197,7 @@ 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 
@@ -303,7 +305,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 +345,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
@@ -371,7 +368,6 @@ begin
                     links_out(i).data  <= (others => '0');
                 end if;               
                 links_out(i).strobe <= '1';
-
             end if;
             
         end process pIteratePointer;
@@ -425,11 +421,10 @@ begin
             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,19 +437,14 @@ 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;
-- 
GitLab


From cb0b8b2c7ce6c65a2d4805f0854515c164a55cc2 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 14:16:06 +0200
Subject: [PATCH 069/109] Add latch on packet_start to help timing

---
 common/firmware/hdl/LinkAggregatorCore.vhd | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index 5b82488f..42d42f8f 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -127,6 +127,8 @@ architecture compressed of LinkAggregatorCore is
         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;
@@ -140,6 +142,8 @@ architecture compressed of LinkAggregatorCore is
 
 begin
 
+    packet_start_buffered <= packet_start;
+
     --==============================--
     genLinkCache : for i in N_LINKS - 1 downto 0 generate
     -- Generator to produce the caching and routing FIFOs for each link
@@ -186,7 +190,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;
@@ -217,7 +221,7 @@ begin
             --==============================--
             begin
                 if rising_edge(clk_p) then
-                    if packet_start = '1' then
+                    if packet_start_buffered = '1' then
                         if unsigned(count_cache) >= trigger_threshold then
                             bx_valid_array(N_LINKS*j + i) <= '1';
                         else
@@ -274,8 +278,8 @@ begin
                 data_count => count_route
             );
 
-            -- Combine the IPBus 'reset' with the 'packet_start' signal to generate the reset signal for the routing FIFO.
-            route_reset <= reset or packet_start;
+            -- Combine the IPBus 'reset' with the 'packet_start_buffered' signal to generate the reset signal for the routing FIFO.
+            route_reset <= reset or packet_start_buffered;
                 
         end generate genLinkBxCache;
 
@@ -394,7 +398,7 @@ begin
             data_count   => data_count
         );
 
-        all_links_reset <= reset or packet_start;
+        all_links_reset <= reset or packet_start_buffered;
 
     end generate;
 
@@ -404,7 +408,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
-- 
GitLab


From 30ecb65f496a2462a7a4eff82e3306ac33a9a49c Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 15:23:47 +0200
Subject: [PATCH 070/109] Update file emp_payload.vhd

---
 top/firmware/hdl/emp_payload.vhd | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 88b0d618..cfc5b221 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -400,6 +400,8 @@ begin
 
 
     gbe_q <= eth_link_out;
+    q(5) <= eth_link_out(0);
+    q(6) <= eth_link_out(1);
 
     
     --==============================--
-- 
GitLab


From b15037937099cc88e3fe1f73535c0e1bab09bc74 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 29 Aug 2023 15:29:04 +0200
Subject: [PATCH 071/109] Update file LinkAggregatorCore.vhd

---
 common/firmware/hdl/LinkAggregatorCore.vhd | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index 42d42f8f..ad9f1d4a 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -142,7 +142,14 @@ architecture compressed of LinkAggregatorCore is
 
 begin
 
-    packet_start_buffered <= packet_start;
+    --==============================--
+    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
-- 
GitLab


From 878f80e031e4491b9d42d373e6fc3f2919b71b03 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 15 Aug 2023 17:55:27 +0200
Subject: [PATCH 072/109] Update file LinkCombinerCore.vhd

---
 common/firmware/hdl/LinkCombinerCore.vhd | 55 ++++++++++++------------
 1 file changed, 28 insertions(+), 27 deletions(-)

diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index 0a217957..ba692877 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -5,6 +5,7 @@ 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;
 
 
 entity LinkCombinerCore is
@@ -87,7 +88,12 @@ 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_links_valid                                              : std_logic_vector(N_INPUT_LINKS - 1 downto 0)       := (others => '0');
+    signal all_input_links_valid                                          : std_logic                                          := '0';
+    signal all_input_links_valid_previous                                 : std_logic                                          := '0';
+    signal start_output                                                   : std_logic                                          := '0';
+    
     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');
@@ -113,7 +119,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');
 
@@ -124,6 +129,7 @@ architecture Behavioral of LinkCombinerCore is
 
 begin
 
+
     --==============================--
     genInputLinkBuffers : for i in 0 to N_INPUT_LINKS - 1 generate
     --==============================--
@@ -132,6 +138,8 @@ begin
         signal wr_en : std_logic                                 := '0';
     begin
     
+        input_links_valid(i) <= links_in(i).valid;
+    
         --==============================--
         InputLinkBufferInstance : link_agg_all_links_fifo
         --==============================--
@@ -246,13 +254,21 @@ begin
     --==============================--
     begin
         if rising_edge(clk_p) then
-            if packet_start = '1' then
+            if start_output = '1' then
                 input_data_valid <= '1';
             else
                 if reset = '1' then
                     input_data_valid <= '0';
                 end if;
             end if;
+            
+            all_input_links_valid <= and_reduce(input_links_valid);
+            all_input_links_valid_previous <= all_input_links_valid;
+            if all_input_links_valid = '0' and all_input_links_valid_previous = '1' then
+                start_output <= '1';
+            else
+                start_output <= '0';
+            end if;
         end if;
     end process pValidDataChecker;
     
@@ -266,7 +282,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
@@ -284,14 +300,16 @@ begin
                     end if;
                 end if;
             else
+                output_pointer <= 0;
+                next_pointer_location := 0;
                 input_rd_en_array(output_pointer) <= '0';
             end if;
             
             -- Packet control bits logic
-            if packet_start = '1' then
+            if start_output = '1' then
                 counter <= 0;
             else
-                if counter < 4 then
+                if counter < 3 then
                     counter <= counter + 1;
                 else
                     counter <= counter;
@@ -299,7 +317,7 @@ 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);
+            output_wr_en   <= input_valid_array(output_pointer_buffered) and (not reset);
             
             
             if reset = '1' then
@@ -323,22 +341,11 @@ begin
                 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_din_buf(11 downto 0) <= bcid_sr(bcid_sr'high);
+                output_din_buf(19 downto 12) <= std_logic_vector(packet_stub_count_previous);
                 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 <= (others => '0');
-                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;
             
@@ -349,7 +356,6 @@ begin
     --==============================--
     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
@@ -357,11 +363,6 @@ begin
                 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
-- 
GitLab


From db10e228ad0261aaeb457b9d2b80a4c5d8d6325c Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Thu, 31 Aug 2023 12:29:34 +0200
Subject: [PATCH 073/109] Reverted change that had lead to a bug in the readout

---
 common/firmware/hdl/LinkAggregatorCore.vhd  |  5 +++--
 common/firmware/hdl/LinkAggregatorIPBus.vhd |  6 ++++--
 common/firmware/hdl/LinkCombinerCore.vhd    | 17 ++---------------
 common/firmware/hdl/MProcessor.vhd          |  6 ++++--
 top/firmware/hdl/emp_payload.vhd            |  3 ++-
 5 files changed, 15 insertions(+), 22 deletions(-)

diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index ad9f1d4a..022d0d21 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -10,7 +10,8 @@ use work.ipbus_reg_types.all;
 
 entity LinkAggregatorCore is
     generic (
-        N_LINKS : integer
+        N_LINKS : integer;
+        INDEX   : integer := 0
     );
     port (
         --- Input Ports ---
@@ -169,7 +170,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;
 
diff --git a/common/firmware/hdl/LinkAggregatorIPBus.vhd b/common/firmware/hdl/LinkAggregatorIPBus.vhd
index 43b94dd0..ddf90b77 100644
--- a/common/firmware/hdl/LinkAggregatorIPBus.vhd
+++ b/common/firmware/hdl/LinkAggregatorIPBus.vhd
@@ -11,7 +11,8 @@ use work.ipbus_decode_link_aggregator.all;
 
 entity LinkAggregatorIPBus is
     generic (
-        N_LINKS : integer
+        N_LINKS : integer;
+        INDEX   : integer := 0
     );
     port (
         --- Input Ports ---
@@ -191,7 +192,8 @@ begin
     LinkAggregatorInstance: entity work.LinkAggregatorCore
     --==============================--
     generic map (
-        N_LINKS => N_LINKS
+        N_LINKS => N_LINKS,
+        INDEX   => INDEX
     )
     port map (
         --- Input Ports ---
diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index ba692877..149185a7 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -89,11 +89,6 @@ architecture Behavioral of LinkCombinerCore is
     constant cFullEmptyArray                                              : std_logic_vector(N_INPUT_LINKS - 1 downto 0)       := (others => '1');
 
     -- Signals
-    signal input_links_valid                                              : std_logic_vector(N_INPUT_LINKS - 1 downto 0)       := (others => '0');
-    signal all_input_links_valid                                          : std_logic                                          := '0';
-    signal all_input_links_valid_previous                                 : std_logic                                          := '0';
-    signal start_output                                                   : std_logic                                          := '0';
-    
     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');
@@ -254,21 +249,13 @@ begin
     --==============================--
     begin
         if rising_edge(clk_p) then
-            if start_output = '1' then
+            if packet_start = '1' then
                 input_data_valid <= '1';
             else
                 if reset = '1' then
                     input_data_valid <= '0';
                 end if;
             end if;
-            
-            all_input_links_valid <= and_reduce(input_links_valid);
-            all_input_links_valid_previous <= all_input_links_valid;
-            if all_input_links_valid = '0' and all_input_links_valid_previous = '1' then
-                start_output <= '1';
-            else
-                start_output <= '0';
-            end if;
         end if;
     end process pValidDataChecker;
     
@@ -306,7 +293,7 @@ begin
             end if;
             
             -- Packet control bits logic
-            if start_output = '1' then
+            if packet_start = '1' then
                 counter <= 0;
             else
                 if counter < 3 then
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 29ee4cce..d15baa4a 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -16,7 +16,8 @@ use work.dtc_data_types.all;
 
 entity MProcessor is
     generic (
-        N_LINKS : integer
+        N_LINKS : integer;
+        INDEX   : integer := 0
     );
     port (
         --- Input Ports ---
@@ -94,7 +95,8 @@ begin
     LinkAggregatorInstance: entity work.LinkAggregatorIPBus
     --==============================--
     generic map (
-        N_LINKS       => N_LINKS
+        N_LINKS       => N_LINKS,
+        INDEX         => INDEX
     )
     port map (
         --- Input Ports ---
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index cfc5b221..413cdb06 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -378,7 +378,8 @@ begin
         MProcessorInstance: entity work.MProcessor
         --==============================--
         generic map(
-            N_LINKS => cNumberofInputLinks
+            N_LINKS => cNumberofInputLinks,
+            INDEX   => i
         )
         port map(
             --- Input Ports ---
-- 
GitLab


From e205b39cfdb1ec7e32596fac95ce17924edc1278 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Thu, 31 Aug 2023 13:18:58 +0200
Subject: [PATCH 074/109] Update file LinkCombinerCore.vhd

---
 common/firmware/hdl/LinkCombinerCore.vhd | 2 --
 1 file changed, 2 deletions(-)

diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index 149185a7..9d4f7a3f 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -133,8 +133,6 @@ begin
         signal wr_en : std_logic                                 := '0';
     begin
     
-        input_links_valid(i) <= links_in(i).valid;
-    
         --==============================--
         InputLinkBufferInstance : link_agg_all_links_fifo
         --==============================--
-- 
GitLab


From efc41242266de278d0dc6d3aef93191d528a1682 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Fri, 1 Sep 2023 15:56:40 +0200
Subject: [PATCH 075/109] Added debug packet size signal

---
 common/firmware/hdl/LinkCombinerCore.vhd  | 8 +++++++-
 common/firmware/hdl/LinkCombinerIPBus.vhd | 7 ++++---
 common/firmware/hdl/MProcessor.vhd        | 5 ++++-
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index 9d4f7a3f..deb58e18 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -27,7 +27,8 @@ entity LinkCombinerCore is
         --- 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;
 
@@ -194,6 +195,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';
@@ -213,6 +216,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);
diff --git a/common/firmware/hdl/LinkCombinerIPBus.vhd b/common/firmware/hdl/LinkCombinerIPBus.vhd
index c8136716..7abbaee7 100644
--- a/common/firmware/hdl/LinkCombinerIPBus.vhd
+++ b/common/firmware/hdl/LinkCombinerIPBus.vhd
@@ -32,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;
 
@@ -114,8 +115,8 @@ begin
         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 d15baa4a..e7e777d1 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -53,6 +53,8 @@ architecture Behavorial of MProcessor is
 
     signal super_id                : std_logic_vector(31 downto 0) := (others => '0');
 
+    signal debug_packet_size       : lword := LWORD_NULL;
+
 begin
 
     --==============================--
@@ -136,7 +138,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
     );
 
     -- --==============================--
-- 
GitLab


From 3104bc111372d3c9b813e615f48c4a3a374d98ac Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 09:15:49 +0200
Subject: [PATCH 076/109] Added histogram to LinkCOmbiner in mprocessor

---
 common/addr_table/mprocessor.xml   | 11 ++++--
 common/firmware/hdl/MProcessor.vhd | 57 +++++++++++++++++++++++++++---
 top/addr_table/emp_payload.xml     | 13 ++++---
 3 files changed, 66 insertions(+), 15 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 3075dce5..5a7b8c56 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -10,9 +10,14 @@
         <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=3">
         <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="lff" address="0x3" mask="0x0001"/>
+        <node id="super_id" address="0x4"/>
+        <node id="occupancy_max_value0" address="0x5"/>
     </node>
+
+    <node id="occupancy_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
 </node>
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index e7e777d1..d4971a96 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -48,12 +48,19 @@ 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(3 - 1 downto 0)   := (others => (others => '0'));
+    signal control_registers       : ipb_reg_v(3 - 1 downto 0)   := (others => (others => '0'));
 
     signal super_id                : std_logic_vector(31 downto 0) := (others => '0');
 
-    signal debug_packet_size       : lword := LWORD_NULL;
+    signal debug_packet_size         : lword                             := LWORD_NULL;
+    signal occupancy_max_value       : std_logic_vector(32 - 1 downto 0) := (others => '0');
+    signal occupancy_histogram_reset : std_logic                         := '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";
+
 
 begin
 
@@ -81,8 +88,8 @@ begin
     MProcessorControlInstance: entity work.ipbus_ctrlreg_v
     --==============================--
     generic map(
-        N_CTRL    => 1,
-        N_STAT    => 2
+        N_CTRL    => 3,
+        N_STAT    => 3
     )
     port map(
         clk       => ipb_clk,
@@ -157,4 +164,44 @@ begin
     status_registers(1)    <= super_id;
     packet_start           <= header_start_array(to_integer(unsigned(control_registers(0)(2 downto 0))))(0);
 
+
+    --==============================--
+    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             => clk,
+        rst             => 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/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index 0eb42100..4e5e68e3 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -7,17 +7,16 @@
 
     <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="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=10"/>
+    <node id="mproc_ctrl" address="0x4ffff" 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="be_daq" address="0x40000000" module="file://dtc_data_aggregator.xml" fwinfo="endpoint;width=30"/>
 </node>
-- 
GitLab


From e06c5df559250121e5aab2998af9473c65dc55d6 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 09:24:08 +0200
Subject: [PATCH 077/109] Updated payload width

---
 top/addr_table/emp_payload.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index 4e5e68e3..2c038e0c 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -11,7 +11,7 @@
 
     <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=10"/>
+    <node id="mprocessor" address="0x40000" description="MProcessor control and status" module="file://mprocessor.xml" fwinfo="endpoint;width=12"/>
     <node id="mproc_ctrl" address="0x4ffff" description="MProcessor channel control" fwinfo="endpoint;width=0">
         <node id="chan_sel" mask="0x7f"/>
         <node id="srst"     mask="0x80"/>
-- 
GitLab


From 9341d223927aa409acec157a50d2ae76c797c38f Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 09:38:02 +0200
Subject: [PATCH 078/109] Fixed signal name error

---
 common/firmware/hdl/MProcessor.vhd | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index d4971a96..6526cac7 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -181,8 +181,8 @@ begin
         --- Output Ports ---
         max_bin_value   => occupancy_max_value,
         --- IPBus Ports ---
-        clk             => clk,
-        rst             => rst,
+        clk             => ipb_clk,
+        rst             => ipb_rst,
         ipb_in          => ipb_to_slaves(N_SLV_OCCUPANCY_MEM),
         ipb_out         => ipb_from_slaves(N_SLV_OCCUPANCY_MEM)
     );
-- 
GitLab


From 919792b7da78ad2d3a7808cb6de42880300ad988 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 12:44:32 +0200
Subject: [PATCH 079/109] Fixed address numbering

---
 common/addr_table/mprocessor.xml   | 10 +++++-----
 common/firmware/hdl/MProcessor.vhd |  9 +++++----
 2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 5a7b8c56..9a988f46 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -12,11 +12,11 @@
     
     <node id="csr" address="0x30" description="MProcessor control and status" fwinfo="endpoint;width=3">
         <node id="header_start_select" address="0x0" mask="0x7"/>
-        <node id="occupancy_windowL" address="0x1"/>
-        <node id="occupancy_windowH" address="0x2" mask="0x000f"/>
-        <node id="lff" address="0x3" mask="0x0001"/>
-        <node id="super_id" address="0x4"/>
-        <node id="occupancy_max_value0" address="0x5"/>
+        <node id="occupancy_windowL"   address="0x1"/>
+        <node id="occupancy_windowH"   address="0x2" mask="0x000f"/>
+        <node id="lff"                 address="0x4" mask="0x0001"/>
+        <node id="super_id"            address="0x5"/>
+        <node id="occupancy_max_value" address="0x6"/>
     </node>
 
     <node id="occupancy_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 6526cac7..4455cea1 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -53,13 +53,13 @@ architecture Behavorial of MProcessor is
 
     signal super_id                : std_logic_vector(31 downto 0) := (others => '0');
 
-    signal debug_packet_size         : lword                             := LWORD_NULL;
-    signal occupancy_max_value       : std_logic_vector(32 - 1 downto 0) := (others => '0');
-    signal occupancy_histogram_reset : std_logic                         := '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;
+
 
 
 begin
@@ -201,6 +201,7 @@ begin
     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;
 
 
-- 
GitLab


From 9931284bf7224eecee7e8dc5d5565c827d4c0b84 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Sat, 2 Sep 2023 15:17:10 +0200
Subject: [PATCH 080/109] Added global header block

---
 common/firmware/cfg/module.dep                |   1 +
 common/firmware/hdl/LinkCombinerCore.vhd      |  48 +-------
 common/firmware/hdl/LinkCombinerIPBus.vhd     |   5 +-
 common/firmware/hdl/MProcessor.vhd            |   9 +-
 .../firmware/hdl/PayloadHeaderGenerator.vhd   | 107 ++++++++++++++++++
 common/firmware/hdl/mprocessor_constants.vhd  |   1 +
 top/firmware/hdl/emp_payload.vhd              |  24 +++-
 7 files changed, 143 insertions(+), 52 deletions(-)
 create mode 100644 common/firmware/hdl/PayloadHeaderGenerator.vhd

diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index f8a06571..d9a3da95 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -10,6 +10,7 @@ src LinkAggregatorIPBus.vhd
 src LinkCombinerCore.vhd
 src LinkCombinerIPBus.vhd
 src --vhdl2008 TrackReconstructor.vhd
+src PayloadHeaderGenerator.vhd
 
 src ipbus_decode_link_aggregator.vhd
 src ipbus_decode_mprocessor.vhd
diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index deb58e18..89aa7012 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -20,8 +20,7 @@ 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 ---
@@ -310,30 +309,12 @@ begin
             output_din     <= input_dout_array(output_pointer_buffered);
             output_wr_en   <= input_valid_array(output_pointer_buffered) and (not reset);
             
-            
-            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;
-            
             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);
+                output_wr_en_buf <= '1';
+                output_din_buf   <= payload_header(63 downto 0);
             elsif counter = 2 then
                 output_din_buf <= (others => '0');
-                output_din_buf(11 downto 0) <= bcid_sr(bcid_sr'high);
-                output_din_buf(19 downto 12) <= std_logic_vector(packet_stub_count_previous);
+                output_din_buf(19 downto 0) <= payload_header(83 downto 64);
                 output_wr_en_buf <= '1';
             else
                 output_wr_en_buf  <= output_wr_en and (not reset);
@@ -343,27 +324,6 @@ begin
         end if;
     end process pCombineBuffers;
 
-
-    --==============================--
-    pBufferHeader: process(clk_p)
-    --==============================--
-        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
-                    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
     --==============================--
diff --git a/common/firmware/hdl/LinkCombinerIPBus.vhd b/common/firmware/hdl/LinkCombinerIPBus.vhd
index 7abbaee7..47ce1078 100644
--- a/common/firmware/hdl/LinkCombinerIPBus.vhd
+++ b/common/firmware/hdl/LinkCombinerIPBus.vhd
@@ -21,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 ---
@@ -109,8 +109,7 @@ 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 ---
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 4455cea1..d8a4465b 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -23,8 +23,8 @@ entity MProcessor is
         --- 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 ---
@@ -33,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;
 
@@ -134,7 +136,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 ---
@@ -163,6 +165,7 @@ begin
     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;
 
 
     --==============================--
diff --git a/common/firmware/hdl/PayloadHeaderGenerator.vhd b/common/firmware/hdl/PayloadHeaderGenerator.vhd
new file mode 100644
index 00000000..f4c17c98
--- /dev/null
+++ b/common/firmware/hdl/PayloadHeaderGenerator.vhd
@@ -0,0 +1,107 @@
+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'))
+    );
+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 2 - 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;
+
+        header_out(i)(75 downto 0) <= header_word(75 downto 0);
+    end generate ; -- genOutput
+    
+
+end Behavioral;
diff --git a/common/firmware/hdl/mprocessor_constants.vhd b/common/firmware/hdl/mprocessor_constants.vhd
index 367eb099..00f1e166 100644
--- a/common/firmware/hdl/mprocessor_constants.vhd
+++ b/common/firmware/hdl/mprocessor_constants.vhd
@@ -7,6 +7,7 @@ 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(2 - 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;
     
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 413cdb06..e034ed59 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -84,6 +84,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
@@ -385,8 +387,8 @@ begin
             --- 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_buffered),
+            payload_header     => payload_headers(i),
             gbe_backpressure   => gbe_backpressure(i),
             srst               => srst,
             --- Output Ports ---
@@ -395,10 +397,28 @@ 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 => x"d451d007",
+        --- Ouput Ports ---
+        header_out => payload_headers
+    );
+    
+
 
     gbe_q <= eth_link_out;
     q(5) <= eth_link_out(0);
-- 
GitLab


From 91361e58ef3adc48e1b3c08888d195c4af138942 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 18:15:17 +0200
Subject: [PATCH 081/109] Small changes to header generator

---
 common/firmware/hdl/PayloadHeaderGenerator.vhd | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/common/firmware/hdl/PayloadHeaderGenerator.vhd b/common/firmware/hdl/PayloadHeaderGenerator.vhd
index f4c17c98..bcea3449 100644
--- a/common/firmware/hdl/PayloadHeaderGenerator.vhd
+++ b/common/firmware/hdl/PayloadHeaderGenerator.vhd
@@ -19,7 +19,9 @@ entity PayloadHeaderGenerator is
         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'))
+        header_out : out tPayloadHeaderArray := (others => (others => '0'));
+        --- Debug Ports ---
+        super_id : out std_logic_vector(31 downto 0) := (others => '0')
     );
 end PayloadHeaderGenerator;
 
@@ -57,8 +59,8 @@ begin
                     end if;
                 end if;
                 
-                header_word <= (others => '0');
-                header_word(31 downto 0) <= std_logic_vector(super_id);
+                -- 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;
@@ -100,7 +102,6 @@ begin
             end if;
         end process pCountStubs;
 
-        header_out(i)(75 downto 0) <= header_word(75 downto 0);
     end generate ; -- genOutput
     
 
-- 
GitLab


From fc50716e732e7d8715bd7bde00b33a3f6b600d68 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 18:26:22 +0200
Subject: [PATCH 082/109] Fixed signal naming

---
 common/firmware/hdl/PayloadHeaderGenerator.vhd | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/common/firmware/hdl/PayloadHeaderGenerator.vhd b/common/firmware/hdl/PayloadHeaderGenerator.vhd
index bcea3449..f5db1659 100644
--- a/common/firmware/hdl/PayloadHeaderGenerator.vhd
+++ b/common/firmware/hdl/PayloadHeaderGenerator.vhd
@@ -21,7 +21,7 @@ entity PayloadHeaderGenerator is
         --- Ouput Ports ---
         header_out : out tPayloadHeaderArray := (others => (others => '0'));
         --- Debug Ports ---
-        super_id : out std_logic_vector(31 downto 0) := (others => '0')
+        debug_super_id : out std_logic_vector(31 downto 0) := (others => '0')
     );
 end PayloadHeaderGenerator;
 
@@ -104,5 +104,6 @@ begin
 
     end generate ; -- genOutput
     
+    debug_super_id <= super_id;
 
 end Behavioral;
-- 
GitLab


From 722119f434b715e637207e8897fac2b08fd2e0b2 Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 18:41:43 +0200
Subject: [PATCH 083/109] Fixed type

---
 common/firmware/hdl/PayloadHeaderGenerator.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/firmware/hdl/PayloadHeaderGenerator.vhd b/common/firmware/hdl/PayloadHeaderGenerator.vhd
index f5db1659..c36d580d 100644
--- a/common/firmware/hdl/PayloadHeaderGenerator.vhd
+++ b/common/firmware/hdl/PayloadHeaderGenerator.vhd
@@ -104,6 +104,6 @@ begin
 
     end generate ; -- genOutput
     
-    debug_super_id <= super_id;
+    debug_super_id <= std_logic_vector(super_id);
 
 end Behavioral;
-- 
GitLab


From 64042f1ae06907ab7066b19de700a328eb6e800f Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sat, 2 Sep 2023 18:53:13 +0200
Subject: [PATCH 084/109] Added super ID monitoring

---
 common/firmware/hdl/LinkCombinerCore.vhd | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/firmware/hdl/LinkCombinerCore.vhd b/common/firmware/hdl/LinkCombinerCore.vhd
index 89aa7012..66086644 100644
--- a/common/firmware/hdl/LinkCombinerCore.vhd
+++ b/common/firmware/hdl/LinkCombinerCore.vhd
@@ -327,7 +327,7 @@ begin
     --==============================--
     -- 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));
@@ -337,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;
-- 
GitLab


From 60a0dc2efb8ef5b79c2cd190473f88a3686ab90d Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Sun, 3 Sep 2023 12:07:03 +0200
Subject: [PATCH 085/109] Added register for user bits

---
 top/addr_table/emp_payload.xml   | 11 +++++++----
 top/firmware/hdl/emp_payload.vhd | 18 +++++++++---------
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index 2c038e0c..04a81aba 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -12,10 +12,13 @@
     <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=12"/>
-    <node id="mproc_ctrl" address="0x4ffff" 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 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"/>
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index e034ed59..68d7fe62 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -60,7 +60,8 @@ architecture rtl of emp_payload is
 
     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 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);
 
 
@@ -159,18 +160,17 @@ 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
     );
 
 
@@ -341,7 +341,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),
@@ -413,7 +413,7 @@ begin
         readout_reset => readout_reset(0),
         header_start => header_start_array_buffered(0),
         module_header_in => header_array,
-        user_bits => x"d451d007",
+        user_bits => mproc_control_registers(1),
         --- Ouput Ports ---
         header_out => payload_headers
     );
@@ -464,8 +464,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(4).valid  <= '1';
     q(4).data   <= "0000" & std_logic_vector(bunch_counter) & "0000000000000000" & std_logic_vector(orbit_counter);
-- 
GitLab


From d9365d57c6f894cd158593d1795272a05ebbc2e8 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Mon, 4 Sep 2023 19:00:46 +0200
Subject: [PATCH 086/109] Added configurable threshold for each input link

---
 common/addr_table/link_aggregator.xml         | 23 +++++++++++++++----
 common/firmware/cfg/module.dep                |  1 +
 common/firmware/hdl/LinkAggregatorCore.vhd    |  8 ++++---
 common/firmware/hdl/LinkAggregatorIPBus.vhd   | 19 +++++++++++----
 common/firmware/hdl/mprocessor_data_types.vhd | 15 ++++++++++++
 5 files changed, 55 insertions(+), 11 deletions(-)
 create mode 100644 common/firmware/hdl/mprocessor_data_types.vhd

diff --git a/common/addr_table/link_aggregator.xml b/common/addr_table/link_aggregator.xml
index ce2c7280..1026d7a3 100644
--- a/common/addr_table/link_aggregator.xml
+++ b/common/addr_table/link_aggregator.xml
@@ -1,9 +1,24 @@
 <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"/>
diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index d9a3da95..7975c1d2 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -10,6 +10,7 @@ src LinkAggregatorIPBus.vhd
 src LinkCombinerCore.vhd
 src LinkCombinerIPBus.vhd
 src --vhdl2008 TrackReconstructor.vhd
+src mprocessor_data_types.vhd
 src PayloadHeaderGenerator.vhd
 
 src ipbus_decode_link_aggregator.vhd
diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index 022d0d21..c6544ff8 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -6,6 +6,7 @@ use work.emp_data_types.all;
 
 use work.ipbus.all;
 use work.ipbus_reg_types.all;
+use work.mprocessor_data_types.all;
 
 
 entity LinkAggregatorCore is
@@ -19,7 +20,8 @@ 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);
@@ -230,7 +232,7 @@ begin
             begin
                 if rising_edge(clk_p) then
                     if packet_start_buffered = '1' then
-                        if unsigned(count_cache) >= trigger_threshold 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';
@@ -295,7 +297,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;
diff --git a/common/firmware/hdl/LinkAggregatorIPBus.vhd b/common/firmware/hdl/LinkAggregatorIPBus.vhd
index ddf90b77..4f1664f1 100644
--- a/common/firmware/hdl/LinkAggregatorIPBus.vhd
+++ b/common/firmware/hdl/LinkAggregatorIPBus.vhd
@@ -5,6 +5,7 @@ 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;
 
@@ -40,12 +41,14 @@ 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 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);
 
 begin
 
@@ -87,7 +90,7 @@ begin
     ControlInstance: entity work.ipbus_ctrlreg_v
     --==============================--
     generic map(
-        N_CTRL       => 1,
+        N_CTRL       => 2,
         N_STAT       => 0
     )
     port map(
@@ -188,6 +191,13 @@ 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
     --==============================--
@@ -198,10 +208,11 @@ begin
     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,
diff --git a/common/firmware/hdl/mprocessor_data_types.vhd b/common/firmware/hdl/mprocessor_data_types.vhd
new file mode 100644
index 00000000..b08d9986
--- /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
-- 
GitLab


From 249b3c20c07527a7b20a14778938e230a85c5ada Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Mon, 4 Sep 2023 20:22:06 +0200
Subject: [PATCH 087/109] Removed L1DataAggregator

---
 top/firmware/hdl/emp_payload.vhd | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 68d7fe62..cb8df549 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -273,22 +273,22 @@ begin
     -- L1 Data Aggregator
     --==============================--
 
-    --==============================--
-    L1DataAggregator : entity work.L1DataAggregator
-    --==============================--
-    port map (
-        --- Input Ports ---
-        clk_p   => clk_p,
-        daq_in  => daq_data,
-        empty   => daq_empty,
-        --- 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)
-    );
+    -- --==============================--
+    -- L1DataAggregator : entity work.L1DataAggregator
+    -- --==============================--
+    -- port map (
+    --     --- Input Ports ---
+    --     clk_p   => clk_p,
+    --     daq_in  => daq_data,
+    --     empty   => daq_empty,
+    --     --- 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
-- 
GitLab


From 2d7dd4f0792bedf2550f569d5692b5a8cf48e91d Mon Sep 17 00:00:00 2001
From: David Monk <dmonk@cern.ch>
Date: Tue, 5 Sep 2023 15:01:56 +0200
Subject: [PATCH 088/109] Re instated Aggregatpr

---
 top/firmware/hdl/emp_payload.vhd | 32 ++++++++++++++++----------------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index cb8df549..68d7fe62 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -273,22 +273,22 @@ begin
     -- L1 Data Aggregator
     --==============================--
 
-    -- --==============================--
-    -- L1DataAggregator : entity work.L1DataAggregator
-    -- --==============================--
-    -- port map (
-    --     --- Input Ports ---
-    --     clk_p   => clk_p,
-    --     daq_in  => daq_data,
-    --     empty   => daq_empty,
-    --     --- 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)
-    -- );
+    --==============================--
+    L1DataAggregator : entity work.L1DataAggregator
+    --==============================--
+    port map (
+        --- Input Ports ---
+        clk_p   => clk_p,
+        daq_in  => daq_data,
+        empty   => daq_empty,
+        --- 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
-- 
GitLab


From 3813c56087b24a367d5ef3940a63646d28d6f76b Mon Sep 17 00:00:00 2001
From: Kirika Uchida <kirika.uchida@cern.ch>
Date: Tue, 5 Sep 2023 15:10:44 +0200
Subject: [PATCH 089/109] ecal data processor

---
 common/addr_table/eprocessor.xml              |  18 +
 common/firmware/cfg/module.dep                |  16 +-
 common/firmware/cgn/ecal_data_ram.xci         | 281 +++++++++++
 common/firmware/cgn/ecal_trig_ram.xci         | 281 +++++++++++
 common/firmware/hdl/EcalDataAggregator.vhd    | 107 ++++
 common/firmware/hdl/EcalDataDecoder.vhd       |  54 ++
 common/firmware/hdl/EcalDataFilter.vhd        | 123 +++++
 common/firmware/hdl/EcalDataMonitor.vhd       |  52 ++
 common/firmware/hdl/EcalDataProcessor.vhd     | 460 ++++++++++++++++++
 common/firmware/hdl/EcalLinkInterface.vhd     |  42 ++
 .../hdl/EcalZeroSuppressionFilter.vhd         | 421 ++++++++++++++++
 common/firmware/hdl/ecal_zsf_type_pckg.vhd    |  10 +
 common/firmware/hdl/fixed_pkg_2008.vhd        |   0
 common/firmware/hdl/mprocessor_constants.vhd  |  10 +-
 top/addr_table/emp_payload.xml                |   2 +
 top/firmware/cfg/top.dep                      |   2 +-
 top/firmware/hdl/emp_payload.vhd              |  55 ++-
 top/firmware/hdl/link_maps.vhd                |  10 +-
 18 files changed, 1937 insertions(+), 7 deletions(-)
 create mode 100644 common/addr_table/eprocessor.xml
 create mode 100644 common/firmware/cgn/ecal_data_ram.xci
 create mode 100644 common/firmware/cgn/ecal_trig_ram.xci
 create mode 100644 common/firmware/hdl/EcalDataAggregator.vhd
 create mode 100644 common/firmware/hdl/EcalDataDecoder.vhd
 create mode 100644 common/firmware/hdl/EcalDataFilter.vhd
 create mode 100644 common/firmware/hdl/EcalDataMonitor.vhd
 create mode 100644 common/firmware/hdl/EcalDataProcessor.vhd
 create mode 100644 common/firmware/hdl/EcalLinkInterface.vhd
 create mode 100644 common/firmware/hdl/EcalZeroSuppressionFilter.vhd
 create mode 100644 common/firmware/hdl/ecal_zsf_type_pckg.vhd
 mode change 100755 => 100644 common/firmware/hdl/fixed_pkg_2008.vhd

diff --git a/common/addr_table/eprocessor.xml b/common/addr_table/eprocessor.xml
new file mode 100644
index 00000000..ad686de3
--- /dev/null
+++ b/common/addr_table/eprocessor.xml
@@ -0,0 +1,18 @@
+<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>
+  </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="zs_sc" address="0x1" mode="block" size="32" description="zs filter registers"/>
+  </node>
+    <node id="mon" address="0x80" description="Ecal data monitoring" fwinfo="endpoint;width=2"/>
+</node>
diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index 7975c1d2..2846b5c3 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 ecal_zsf_type_pckg.vhd
 
 src MProcessor.vhd
 src LinkAggregatorCore.vhd
@@ -13,10 +14,20 @@ src --vhdl2008 TrackReconstructor.vhd
 src mprocessor_data_types.vhd
 src PayloadHeaderGenerator.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_link_aggregator.vhd
 src ipbus_decode_mprocessor.vhd
+src ipbus_decode_eprocessor.vhd
 
 addrtab -t mprocessor.xml
+addrtab -t eprocessor.xml
 addrtab -t link_aggregator.xml
 
 # IP Cores
@@ -30,4 +41,7 @@ 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
+
+src --cd ../cgn ecal_data_ram.xci
+src --cd ../cgn ecal_trig_ram.xci
diff --git a/common/firmware/cgn/ecal_data_ram.xci b/common/firmware/cgn/ecal_data_ram.xci
new file mode 100644
index 00000000..91e6aca6
--- /dev/null
+++ b/common/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/common/firmware/cgn/ecal_trig_ram.xci b/common/firmware/cgn/ecal_trig_ram.xci
new file mode 100644
index 00000000..efccb825
--- /dev/null
+++ b/common/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/common/firmware/hdl/EcalDataAggregator.vhd b/common/firmware/hdl/EcalDataAggregator.vhd
new file mode 100644
index 00000000..65ee6c27
--- /dev/null
+++ b/common/firmware/hdl/EcalDataAggregator.vhd
@@ -0,0 +1,107 @@
+-------------------------------------------------------------
+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 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;
+                           
+          -- capturing frames
+          data_out_start <= '0';
+          data_out_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 <= ecal_data_p;
+               data_out_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 <= ecal_data_p;
+                data_out_start <= '1'; 
+                last_valid_bcid <= bcid_p(0);
+              else
+                sync <= '0';
+              end if;
+            else 
+               timer := timer + 1;
+               if timer = 7 then
+                 data_out_last <= '1';
+               end if;
+            end if;
+          end if;
+
+        end if;
+    end process;
+
+end rtl;
+
diff --git a/common/firmware/hdl/EcalDataDecoder.vhd b/common/firmware/hdl/EcalDataDecoder.vhd
new file mode 100644
index 00000000..d5f3ee31
--- /dev/null
+++ b/common/firmware/hdl/EcalDataDecoder.vhd
@@ -0,0 +1,54 @@
+-------------------------------------------------------------
+-- 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;
+begin
+
+  decoder: process (clk_p)
+
+  begin
+    if rising_edge(clk_p) then
+       
+        for j in 0 to 1 loop
+            for i in 0 to 6 loop 
+                elink_data(j*7+i) <= elink_data(j*7+i)(6 downto 0) & data_in.data(j*32+i);
+            end loop;
+        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/common/firmware/hdl/EcalDataFilter.vhd b/common/firmware/hdl/EcalDataFilter.vhd
new file mode 100644
index 00000000..0754a9f6
--- /dev/null
+++ b/common/firmware/hdl/EcalDataFilter.vhd
@@ -0,0 +1,123 @@
+-------------------------------------------------------------
+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_valid    : 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 data_meta         : std_logic_vector(28 * 16 -1 downto 0);
+  signal data_sync         : 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);
+  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     <= trig_sync    when bypass_s = '0' else x"c0000001";
+
+  data_meta   <= data_in   when rising_edge(clk40);
+  data_sync   <= data_meta when rising_edge(clk40);
+  
+  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');
+   elsif rising_edge(clk40) then
+     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_sync,
+    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/common/firmware/hdl/EcalDataMonitor.vhd b/common/firmware/hdl/EcalDataMonitor.vhd
new file mode 100644
index 00000000..17abd38d
--- /dev/null
+++ b/common/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/common/firmware/hdl/EcalDataProcessor.vhd b/common/firmware/hdl/EcalDataProcessor.vhd
new file mode 100644
index 00000000..64c1eb69
--- /dev/null
+++ b/common/firmware/hdl/EcalDataProcessor.vhd
@@ -0,0 +1,460 @@
+-------------------------------------------------------------
+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_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)(9) <= data_ready_i;
+  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_valid      => 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)
+  begin
+        if reset = '1' then
+          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 =>
+              if data_out_s.start = '1' then
+                data_out(0).start <= data_out_s.start;
+                data_out(0).valid <= data_out_s.valid;
+                ostate <= wait_last;
+              end if;
+            when wait_last =>
+                data_out(0).valid <= data_out_s.valid;
+                if data_out_s.last = '1' then
+                  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));
+              trig_ram_dina  <= trig;
+            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;
+            end if;
+
+            data_out_s.valid <= trig_ram_doutb(0) and data_ram_doutb(bit_valid);           
+            data_out_s.start <= trig_ram_doutb(31) and data_ram_doutb(bit_start) and gbe_backpressure;
+            data_out_s.last  <= trig_ram_doutb(30) and data_ram_doutb(bit_last);
+            data_out_s.strobe <= trig_ram_doutb(30) and data_ram_doutb(bit_last);         
+          end if;
+          
+          -- 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;
+            
+          -- data to write                   
+          data_ram_addra <= std_logic_vector(to_unsigned(d_waddr, 9));
+          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
+            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
+              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
+          
+        end if;   
+    end process;
+    
+end rtl;
diff --git a/common/firmware/hdl/EcalLinkInterface.vhd b/common/firmware/hdl/EcalLinkInterface.vhd
new file mode 100644
index 00000000..3d5f84fa
--- /dev/null
+++ b/common/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/common/firmware/hdl/EcalZeroSuppressionFilter.vhd b/common/firmware/hdl/EcalZeroSuppressionFilter.vhd
new file mode 100644
index 00000000..dd5b23ce
--- /dev/null
+++ b/common/firmware/hdl/EcalZeroSuppressionFilter.vhd
@@ -0,0 +1,421 @@
+----------------------------------------------------------------------------------
+-- 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) 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/common/firmware/hdl/ecal_zsf_type_pckg.vhd b/common/firmware/hdl/ecal_zsf_type_pckg.vhd
new file mode 100644
index 00000000..536ad276
--- /dev/null
+++ b/common/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/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 00f1e166..d1d91efe 100644
--- a/common/firmware/hdl/mprocessor_constants.vhd
+++ b/common/firmware/hdl/mprocessor_constants.vhd
@@ -10,6 +10,14 @@ package mprocessor_constants is
     type tPayloadHeaderArray is array(2 - 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;
 
@@ -30,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/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index 04a81aba..88bd97a3 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -7,6 +7,8 @@
 
     <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"/>
diff --git a/top/firmware/cfg/top.dep b/top/firmware/cfg/top.dep
index 2a604b26..0f54808f 100644
--- a/top/firmware/cfg/top.dep
+++ b/top/firmware/cfg/top.dep
@@ -28,4 +28,4 @@ src link_maps.vhd
 
 src ipbus_decode_emp_payload.vhd
 
-addrtab -t emp_payload.xml
\ No newline at end of file
+addrtab -t emp_payload.xml
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index 68d7fe62..badc237e 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -102,6 +102,13 @@ architecture rtl of emp_payload is
     signal tcds_fcmd                  : tFastCommand;
 
 
+    -- Ecal
+
+    signal ecal_link_data             : tDaqEcalLinkDataArray;
+    signal ecal_data                  : ldata(cNumberOfEcalOutputLinks - 1 downto 0);
+
+
+
 begin
 
   
@@ -174,9 +181,6 @@ begin
     );
 
 
-    
-
-
     --==============================--
     -- FE data extraction and monitoring
     --==============================--
@@ -328,6 +332,51 @@ begin
 
 
 
+    --==============================--
+    -- 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
     --==============================--
diff --git a/top/firmware/hdl/link_maps.vhd b/top/firmware/hdl/link_maps.vhd
index 5f03fe20..215bf5a3 100644
--- a/top/firmware/hdl/link_maps.vhd
+++ b/top/firmware/hdl/link_maps.vhd
@@ -7,7 +7,9 @@ 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"),
@@ -24,6 +26,12 @@ package dtc_link_maps is
         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);
 
-- 
GitLab


From ed5133586ab62171b6df9b803938a14f6cc3ce84 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Tue, 5 Sep 2023 17:44:29 +0200
Subject: [PATCH 090/109] Update file README.md

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index aea2de9c..2a46eb3c 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
-- 
GitLab


From 2bae08ad9fdebdf9c7313a99d4d91bf7a01876d2 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sat, 9 Sep 2023 19:04:43 +0200
Subject: [PATCH 091/109] Added tracking event rate monitor

---
 common/addr_table/link_aggregator.xml       |  1 +
 common/firmware/cfg/module.dep              |  1 +
 common/firmware/hdl/LinkAggregatorCore.vhd  | 50 ++++++++++++++++++---
 common/firmware/hdl/LinkAggregatorIPBus.vhd | 10 +++--
 common/firmware/hdl/tracking_constants.vhd  | 11 +++++
 5 files changed, 65 insertions(+), 8 deletions(-)
 create mode 100644 common/firmware/hdl/tracking_constants.vhd

diff --git a/common/addr_table/link_aggregator.xml b/common/addr_table/link_aggregator.xml
index 1026d7a3..1d4ee0bb 100644
--- a/common/addr_table/link_aggregator.xml
+++ b/common/addr_table/link_aggregator.xml
@@ -22,6 +22,7 @@
     </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/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index 2846b5c3..2036591c 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -4,6 +4,7 @@ src fixed_pkg_2008.vhd
 
 src mprocessor_constants.vhd
 src ecal_zsf_type_pckg.vhd
+src tracking_constants.vhd
 
 src MProcessor.vhd
 src LinkAggregatorCore.vhd
diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index c6544ff8..4456b4d3 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -3,6 +3,7 @@ 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;
@@ -28,7 +29,7 @@ entity LinkAggregatorCore is
         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')
         non_empty_counts   : out ipb_reg_v(8*N_LINKS - 1 downto 0);
         bx_valid_count_out : out ipb_reg_v(0 downto 0)
     );
@@ -129,7 +130,7 @@ 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');
@@ -142,6 +143,13 @@ architecture compressed of LinkAggregatorCore is
     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 track_stubs : tTrackStubs := (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
 
@@ -215,7 +223,7 @@ begin
                     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
@@ -241,6 +249,23 @@ 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;
@@ -429,9 +454,9 @@ begin
             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';
+                readout_reset_signal <= '1';
             else
-                readout_reset <= '0';
+                readout_reset_signal <= '0';
             end if;
         end if;
     end process pReadoutReset;
@@ -463,6 +488,20 @@ begin
             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' and event_valid_for_tracking = '1' then
+                tracking_event_count <= tracking_event_count + 1;
+            end if;
+        end if;
+    end process pExtractTrackingEvent;
+    
+    readout_reset <= readout_reset_signal;
 
     --==============================--
     -- Debug
@@ -479,5 +518,6 @@ 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);
 
 end compressed;
diff --git a/common/firmware/hdl/LinkAggregatorIPBus.vhd b/common/firmware/hdl/LinkAggregatorIPBus.vhd
index 4f1664f1..4ff1f48d 100644
--- a/common/firmware/hdl/LinkAggregatorIPBus.vhd
+++ b/common/firmware/hdl/LinkAggregatorIPBus.vhd
@@ -43,13 +43,15 @@ architecture Behavorial of LinkAggregatorIPBus is
     -- signal link_aggregator_status_registers : ipb_reg_v(4 - 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
 
     --==============================--
@@ -107,7 +109,7 @@ begin
     --==============================--
     generic map(
         N_CTRL       => 0,
-        N_STAT       => 1
+        N_STAT       => 2
     )
     port map(
         clk          => ipb_clk,
@@ -219,9 +221,11 @@ begin
         --- 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
     );
     
     rate_monitoring_registers(0) <= bx_valid_count(0);
+    rate_monitoring_registers(1) <= tracking_event_count;
 
 end Behavorial;
diff --git a/common/firmware/hdl/tracking_constants.vhd b/common/firmware/hdl/tracking_constants.vhd
new file mode 100644
index 00000000..121f21cf
--- /dev/null
+++ b/common/firmware/hdl/tracking_constants.vhd
@@ -0,0 +1,11 @@
+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;
+    
+end package tracking_constants;
\ No newline at end of file
-- 
GitLab


From febe02c842ddbfa2723a38a2dbfcd5bf596e7b8a Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sat, 9 Sep 2023 19:21:51 +0200
Subject: [PATCH 092/109] Fixed syntax error

---
 common/firmware/hdl/LinkAggregatorCore.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index 4456b4d3..b80a640a 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -29,7 +29,7 @@ entity LinkAggregatorCore is
         readout_reset      : out std_logic := '0';
         --- Debug Ports ---
         status_bits        : out std_logic_vector(15 downto 0);
-        debug_tracking_event_count : out std_logic_vector(31 downto 0) := (others => '0')
+        debug_tracking_event_count : out std_logic_vector(31 downto 0) := (others => '0');
         non_empty_counts   : out ipb_reg_v(8*N_LINKS - 1 downto 0);
         bx_valid_count_out : out ipb_reg_v(0 downto 0)
     );
-- 
GitLab


From c935189466e2c38bf0759f49bf92eea6ae4dc796 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 00:42:04 +0200
Subject: [PATCH 093/109] Added extra debug signals to Aggregator

---
 common/firmware/cfg/module.dep             |  1 +
 common/firmware/hdl/LinkAggregatorCore.vhd | 42 +++++++++-----
 common/firmware/hdl/TrackFinder.vhd        | 65 ++++++++++++++++++++++
 common/firmware/hdl/tracking_constants.vhd | 57 ++++++++++++++++++-
 4 files changed, 151 insertions(+), 14 deletions(-)
 create mode 100644 common/firmware/hdl/TrackFinder.vhd

diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index 2036591c..9c4f36cf 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -14,6 +14,7 @@ src LinkCombinerIPBus.vhd
 src --vhdl2008 TrackReconstructor.vhd
 src mprocessor_data_types.vhd
 src PayloadHeaderGenerator.vhd
+src TrackFinder.vhd
 
 src EcalLinkInterface.vhd 
 src EcalDataDecoder.vhd 
diff --git a/common/firmware/hdl/LinkAggregatorCore.vhd b/common/firmware/hdl/LinkAggregatorCore.vhd
index b80a640a..8bfa4f07 100644
--- a/common/firmware/hdl/LinkAggregatorCore.vhd
+++ b/common/firmware/hdl/LinkAggregatorCore.vhd
@@ -30,6 +30,7 @@ entity LinkAggregatorCore is
         --- Debug Ports ---
         status_bits        : out std_logic_vector(15 downto 0);
         debug_tracking_event_count : out std_logic_vector(31 downto 0) := (others => '0');
+        debug_tracking_stubs_out : out ldata(5 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)
     );
@@ -145,8 +146,10 @@ architecture compressed of LinkAggregatorCore is
     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 : tTrackStubs := (others => LWORD_NULL);
+    signal track_stubs : ldata(5 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');
@@ -270,8 +273,8 @@ begin
             -- 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;
             
             
             --==============================--
@@ -313,7 +316,7 @@ begin
                 data_count => count_route
             );
 
-            -- Combine the IPBus 'reset' with the 'packet_start_buffered' signal to generate the reset signal for the routing FIFO.
+            -- Combine the IPBus 'reset' with the 'packet_start' signal to generate the reset signal for the routing FIFO.
             route_reset <= reset or packet_start_buffered;
                 
         end generate genLinkBxCache;
@@ -400,13 +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;
@@ -453,7 +456,7 @@ 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
+            if counter = 49 then
                 readout_reset_signal <= '1';
             else
                 readout_reset_signal <= '0';
@@ -489,19 +492,31 @@ begin
         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' and event_valid_for_tracking = '1' then
-                tracking_event_count <= tracking_event_count + 1;
+            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 5 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
@@ -519,5 +534,6 @@ begin
     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/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
new file mode 100644
index 00000000..32e63137
--- /dev/null
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -0,0 +1,65 @@
+----------------------------------------------------------------------------------
+-- 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;
+
+entity TrackFinder is
+    port (
+        clk_p : in STD_LOGIC;
+        stubs_in : in ldata(5 downto 0) := (others => LWORD_NULL);
+        header_start : in std_logic
+    );
+end TrackFinder;
+
+architecture Behavioral of TrackFinder is
+
+    signal stub_array : tDecodedStubArray := (others => cNullDecodedStub);
+    signal valid_event_array : std_logic_vector(5 downto 0);
+    signal valid_event : std_logic := '0';
+
+begin
+
+    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;
+        end if;
+    end process pMain;
+
+end Behavioral;
diff --git a/common/firmware/hdl/tracking_constants.vhd b/common/firmware/hdl/tracking_constants.vhd
index 121f21cf..32964941 100644
--- a/common/firmware/hdl/tracking_constants.vhd
+++ b/common/firmware/hdl/tracking_constants.vhd
@@ -8,4 +8,59 @@ package tracking_constants is
     
     type tTrackStubs is array (0 to 5) of lword;
     
-end package tracking_constants;
\ No newline at end of file
+    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;
-- 
GitLab


From 7ca7f417793b7e5125596d032d7e300cc36383d8 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 09:44:46 +0200
Subject: [PATCH 094/109] Added localx histogram

---
 common/addr_table/mprocessor.xml            | 12 +++--
 common/firmware/hdl/LinkAggregatorIPBus.vhd |  4 +-
 common/firmware/hdl/MProcessor.vhd          | 55 +++++++++++++++------
 common/firmware/hdl/TrackFinder.vhd         | 54 +++++++++++++++++++-
 top/addr_table/emp_payload.xml              |  2 +-
 5 files changed, 106 insertions(+), 21 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 9a988f46..5d54a3c0 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -10,14 +10,18 @@
         <node id="header_user_bits" address="0x1"/>
     </node>
     
-    <node id="csr" address="0x30" description="MProcessor control and status" fwinfo="endpoint;width=3">
+    <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="occupancy_windowL"   address="0x1"/>
         <node id="occupancy_windowH"   address="0x2" mask="0x000f"/>
-        <node id="lff"                 address="0x4" mask="0x0001"/>
-        <node id="super_id"            address="0x5"/>
-        <node id="occupancy_max_value" address="0x6"/>
+        <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="tracking_localx_mem" address="0x1000" size="0x1000" mode="incremental" fwinfo="endpoint;width=12"/>
 </node>
diff --git a/common/firmware/hdl/LinkAggregatorIPBus.vhd b/common/firmware/hdl/LinkAggregatorIPBus.vhd
index 4ff1f48d..1445c4ea 100644
--- a/common/firmware/hdl/LinkAggregatorIPBus.vhd
+++ b/common/firmware/hdl/LinkAggregatorIPBus.vhd
@@ -24,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(5 downto 0) := (others => LWORD_NULL);
         --- IPBus Ports ---
         ipb_clk            : in  std_logic;
         ipb_rst            : in  std_logic;
@@ -222,7 +223,8 @@ begin
         -- status_bits      => link_aggregator_status_registers(3)(15 downto 0),
         non_empty_counts => mprocessor_monitoring_registers,
         bx_valid_count_out => bx_valid_count,
-        debug_tracking_event_count => tracking_event_count
+        debug_tracking_event_count => tracking_event_count,
+        debug_tracking_stubs_out => tracking_stubs
     );
     
     rate_monitoring_registers(0) <= bx_valid_count(0);
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index d8a4465b..6e1be92d 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -50,8 +50,8 @@ 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(3 - 1 downto 0)   := (others => (others => '0'));
-    signal control_registers       : ipb_reg_v(3 - 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');
 
@@ -62,7 +62,11 @@ architecture Behavorial of MProcessor is
     signal occupancy_histogram_reset                  : std_logic                                := '0';
     signal debug_packet_size                          : lword                                    := LWORD_NULL;
 
-
+    signal tracking_stubs : ldata(5 downto 0) := (others => 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');
 
 begin
 
@@ -90,8 +94,8 @@ begin
     MProcessorControlInstance: entity work.ipbus_ctrlreg_v
     --==============================--
     generic map(
-        N_CTRL    => 3,
-        N_STAT    => 3
+        N_CTRL    => 5,
+        N_STAT    => 4
     )
     port map(
         clk       => ipb_clk,
@@ -111,17 +115,18 @@ begin
     )
     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)
     );
 
     --==============================--
@@ -160,6 +165,24 @@ 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,
+        localx_trigger_window => localx_trigger_window,
+        --- Output Ports ---
+        localx_max_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)
+    );
+
     link_aggregator_input(N_LINKS - 1 downto 0) <= links_in;
 
     status_registers(0)(0) <= gbe_backpressure;
@@ -204,8 +227,12 @@ begin
     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;
+    localx_trigger_window_lower <= control_registers(3);
+    localx_trigger_window_upper <= control_registers(4)(3 downto 0);
+    localx_trigger_window       <= localx_trigger_window_upper & localx_trigger_window_lower;
 
     status_registers(2)(32 - 1 downto 0) <= occupancy_max_value;
+    status_registers(3)(32 - 1 downto 0) <= localx_max_value;
 
 
 end Behavorial;
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 32e63137..374ad69f 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -31,7 +31,14 @@ entity TrackFinder is
     port (
         clk_p : in STD_LOGIC;
         stubs_in : in ldata(5 downto 0) := (others => LWORD_NULL);
-        header_start : in std_logic
+        header_start : in std_logic;
+        localx_trigger_window : std_logic_vector(36 - 1 downto 0) := X"0ffffffff";
+        localx_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0')
+        --- IPBus Ports ---
+        ipb_clk            : in  std_logic;
+        ipb_rst            : in  std_logic;
+        ipb_in             : in  ipb_wbus;
+        ipb_out            : out ipb_rbus;
     );
 end TrackFinder;
 
@@ -41,6 +48,9 @@ architecture Behavioral of TrackFinder is
     signal valid_event_array : std_logic_vector(5 downto 0);
     signal valid_event : std_logic := '0';
 
+    signal histogram_input : lword := LWORD_NULL;
+    signal localx_histogram_reset : std_logic := '0';
+
 begin
 
     genValidEventArray: for i in 0 to 5 generate
@@ -59,7 +69,49 @@ begin
                     end if;
                 end loop;
             end if;
+            valid_event <= and_reduce(valid_event_array) and headder_start;
+
+            if valid_event then
+                histogram_input.valid <= '1';
+                histogram_input.data(11 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 12));
+            else
+                histogram_input <= LWORD_NULL;
+            end if;
         end if;
     end process pMain;
 
+
+    --==============================--
+    LocalXHistogramInstance : entity work.IPBusHistogram
+    --==============================--
+    generic map (
+        input_width => 12,
+        bin_width   => 32,
+        data_offset => 0
+    )
+    port map (
+        --- Input Ports ---
+        clk_p           => clk_p,
+        data_in         => 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_in,
+        ipb_out         => ipb_out
+    );
+
+    --==============================--
+    LocalXHistogramResetter : entity work.HistogramResetter
+    --==============================--
+    port map (
+        --- Input Ports ---
+        clk_p           => clk_p,
+        trigger_window  => localx_trigger_window,
+        --- Output Ports ---
+        histogram_reset => localx_histogram_reset
+    );
+
 end Behavioral;
diff --git a/top/addr_table/emp_payload.xml b/top/addr_table/emp_payload.xml
index 88bd97a3..65601aff 100644
--- a/top/addr_table/emp_payload.xml
+++ b/top/addr_table/emp_payload.xml
@@ -13,7 +13,7 @@
 
     <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=12"/>
+    <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"/>
-- 
GitLab


From 9e644ac0fa5f2da8fb5dee6aac044a586182704c Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 09:56:05 +0200
Subject: [PATCH 095/109] Fixed syntax error

---
 common/firmware/hdl/TrackFinder.vhd | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 374ad69f..132f7dbe 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -33,12 +33,12 @@ entity TrackFinder is
         stubs_in : in ldata(5 downto 0) := (others => LWORD_NULL);
         header_start : in std_logic;
         localx_trigger_window : std_logic_vector(36 - 1 downto 0) := X"0ffffffff";
-        localx_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0')
+        localx_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0');
         --- IPBus Ports ---
         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
     );
 end TrackFinder;
 
-- 
GitLab


From 896b7134a2ab61a33285d10cc10222294f77c233 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 10:06:33 +0200
Subject: [PATCH 096/109] Added IPBus headers

---
 common/firmware/hdl/TrackFinder.vhd | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 132f7dbe..7c066adb 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -27,6 +27,9 @@ 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;
+
 entity TrackFinder is
     port (
         clk_p : in STD_LOGIC;
-- 
GitLab


From 76c36aacb6c4ee2dda1fa3831ce1cae57fd8efdf Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 10:16:49 +0200
Subject: [PATCH 097/109] Fixed syntax error

---
 common/firmware/hdl/TrackFinder.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 7c066adb..e11a074e 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -72,7 +72,7 @@ begin
                     end if;
                 end loop;
             end if;
-            valid_event <= and_reduce(valid_event_array) and headder_start;
+            valid_event <= and_reduce(valid_event_array) and header_start;
 
             if valid_event then
                 histogram_input.valid <= '1';
-- 
GitLab


From 37d16edcee35b81aaf7936ded4e3ac6daaea057d Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 10:35:05 +0200
Subject: [PATCH 098/109] Fixed bug

---
 common/firmware/hdl/TrackFinder.vhd | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index e11a074e..da246eb0 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -74,7 +74,7 @@ begin
             end if;
             valid_event <= and_reduce(valid_event_array) and header_start;
 
-            if valid_event then
+            if valid_event = '1' then
                 histogram_input.valid <= '1';
                 histogram_input.data(11 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 12));
             else
-- 
GitLab


From b00ae84a04d191b032f2df90270e66bf5db7001b Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 10:49:46 +0200
Subject: [PATCH 099/109] Reduced histogram size

---
 common/addr_table/mprocessor.xml    | 2 +-
 common/firmware/hdl/TrackFinder.vhd | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 5d54a3c0..3ee488e1 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -23,5 +23,5 @@
     </node>
 
     <node id="occupancy_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
-    <node id="tracking_localx_mem" address="0x1000" size="0x1000" mode="incremental" fwinfo="endpoint;width=12"/>
+    <node id="tracking_localx_mem" address="0x500" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
 </node>
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index da246eb0..09979882 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -35,8 +35,8 @@ entity TrackFinder is
         clk_p : in STD_LOGIC;
         stubs_in : in ldata(5 downto 0) := (others => LWORD_NULL);
         header_start : in std_logic;
-        localx_trigger_window : std_logic_vector(36 - 1 downto 0) := X"0ffffffff";
-        localx_max_value : std_logic_vector(32 - 1 downto 0) := (others => '0');
+        localx_trigger_window : in std_logic_vector(36 - 1 downto 0) := X"0ffffffff";
+        localx_max_value :  out std_logic_vector(32 - 1 downto 0) := (others => '0');
         --- IPBus Ports ---
         ipb_clk            : in  std_logic;
         ipb_rst            : in  std_logic;
@@ -88,9 +88,9 @@ begin
     LocalXHistogramInstance : entity work.IPBusHistogram
     --==============================--
     generic map (
-        input_width => 12,
+        input_width => 8,
         bin_width   => 32,
-        data_offset => 0
+        data_offset => 4
     )
     port map (
         --- Input Ports ---
-- 
GitLab


From b0f195a749748a9a78f35c76338da57f91791e7d Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 11:00:51 +0200
Subject: [PATCH 100/109] Restructured IPBus

---
 common/addr_table/mprocessor.xml    |  3 +-
 common/addr_table/track_finder.xml  |  9 ++++
 common/firmware/cfg/module.dep      |  1 +
 common/firmware/hdl/MProcessor.vhd  | 16 ++-----
 common/firmware/hdl/TrackFinder.vhd | 66 ++++++++++++++++++++++++++---
 5 files changed, 75 insertions(+), 20 deletions(-)
 create mode 100644 common/addr_table/track_finder.xml

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 3ee488e1..744de77b 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -23,5 +23,6 @@
     </node>
 
     <node id="occupancy_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
-    <node id="tracking_localx_mem" address="0x500" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
+
+    <node id="track_finder" address="0x600" module="file://track_finder.xml" fwinfo="endpoint;width=9"/>
 </node>
diff --git a/common/addr_table/track_finder.xml b/common/addr_table/track_finder.xml
new file mode 100644
index 00000000..dd4150f0
--- /dev/null
+++ b/common/addr_table/track_finder.xml
@@ -0,0 +1,9 @@
+<node description="TrackFinder Control and Status" fwinfo="endpoint">
+    <node id="csr" address="0x00" description="TrackFinder control and status" fwinfo="endpoint;width=2">
+        <node id="localx_windowL"      address="0x0"/>
+        <node id="localx_windowH"      address="0x1" mask="0x000f"/>
+        <node id="localx_max_value"    address="0x2"/>
+    </node>
+
+    <node id="tracking_localx_mem" address="0x100" 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 9c4f36cf..735abc14 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -31,6 +31,7 @@ src ipbus_decode_eprocessor.vhd
 addrtab -t mprocessor.xml
 addrtab -t eprocessor.xml
 addrtab -t link_aggregator.xml
+addrtab -t track_finder.xml
 
 # IP Cores
 src --cd ../cgn link_agg_single_link_fifo.xci
diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 6e1be92d..aef64452 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -63,10 +63,6 @@ architecture Behavorial of MProcessor is
     signal debug_packet_size                          : lword                                    := LWORD_NULL;
 
     signal tracking_stubs : ldata(5 downto 0) := (others => 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');
 
 begin
 
@@ -177,10 +173,10 @@ begin
         --- Output Ports ---
         localx_max_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)
+        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;
@@ -227,12 +223,8 @@ begin
     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;
-    localx_trigger_window_lower <= control_registers(3);
-    localx_trigger_window_upper <= control_registers(4)(3 downto 0);
-    localx_trigger_window       <= localx_trigger_window_upper & localx_trigger_window_lower;
 
     status_registers(2)(32 - 1 downto 0) <= occupancy_max_value;
-    status_registers(3)(32 - 1 downto 0) <= localx_max_value;
 
 
 end Behavorial;
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 09979882..efa96bc2 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -29,14 +29,14 @@ 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);
+        clk_p        : in STD_LOGIC;
+        stubs_in     : in ldata(5 downto 0) := (others => LWORD_NULL);
         header_start : in std_logic;
-        localx_trigger_window : in std_logic_vector(36 - 1 downto 0) := X"0ffffffff";
-        localx_max_value :  out std_logic_vector(32 - 1 downto 0) := (others => '0');
         --- IPBus Ports ---
         ipb_clk            : in  std_logic;
         ipb_rst            : in  std_logic;
@@ -47,21 +47,67 @@ 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(1 - 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 histogram_input : lword := LWORD_NULL;
-    signal localx_histogram_reset : std_logic := '0';
+    
+    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';
 
 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    => 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
+    );
+
+    --==============================--
     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
@@ -102,8 +148,8 @@ begin
         --- IPBus Ports ---
         clk             => ipb_clk,
         rst             => ipb_rst,
-        ipb_in          => ipb_in,
-        ipb_out         => ipb_out
+        ipbus_in  => ipb_to_slaves(N_SLV_TRACKING_LOCALX_MEM),
+        ipbus_out => ipb_from_slaves(N_SLV_TRACKING_LOCALX_MEM)
     );
 
     --==============================--
@@ -117,4 +163,10 @@ begin
         histogram_reset => localx_histogram_reset
     );
 
+    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;
+
 end Behavioral;
-- 
GitLab


From 246db658488ef1d318e0db444e43acb37b8db445 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 11:12:40 +0200
Subject: [PATCH 101/109] Added missing src

---
 common/firmware/cfg/module.dep | 1 +
 1 file changed, 1 insertion(+)

diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index 735abc14..804dc871 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -27,6 +27,7 @@ src EcalDataMonitor.vhd
 src ipbus_decode_link_aggregator.vhd
 src ipbus_decode_mprocessor.vhd
 src ipbus_decode_eprocessor.vhd
+src ipbus_decode_track_finder.vhd
 
 addrtab -t mprocessor.xml
 addrtab -t eprocessor.xml
-- 
GitLab


From f3f90a9e68d6b1481914ec932643abd5fa049450 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 11:24:50 +0200
Subject: [PATCH 102/109] Added second histogram

---
 common/addr_table/mprocessor.xml    |  2 +-
 common/addr_table/track_finder.xml  |  2 +
 common/firmware/hdl/TrackFinder.vhd | 84 +++++++++++++++++++++++++----
 3 files changed, 76 insertions(+), 12 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 744de77b..21272a11 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -24,5 +24,5 @@
 
     <node id="occupancy_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
 
-    <node id="track_finder" address="0x600" module="file://track_finder.xml" fwinfo="endpoint;width=9"/>
+    <node id="track_finder" address="0x800" module="file://track_finder.xml" fwinfo="endpoint;width=10"/>
 </node>
diff --git a/common/addr_table/track_finder.xml b/common/addr_table/track_finder.xml
index dd4150f0..83efe87c 100644
--- a/common/addr_table/track_finder.xml
+++ b/common/addr_table/track_finder.xml
@@ -3,7 +3,9 @@
         <node id="localx_windowL"      address="0x0"/>
         <node id="localx_windowH"      address="0x1" mask="0x000f"/>
         <node id="localx_max_value"    address="0x2"/>
+        <node id="deltax_max_value"    address="0x3"/>
     </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>
\ No newline at end of file
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index efa96bc2..8a8e27cf 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -50,14 +50,18 @@ 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(1 - 1 downto 0)   := (others => (others => '0'));
+    signal status_registers        : ipb_reg_v(2 - 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 stub_array        : tDecodedStubArray := (others => cNullDecodedStub);
     signal valid_event_array : std_logic_vector(5 downto 0);
-    signal valid_event : std_logic := '0';
+    signal valid_event       : std_logic := '0';
 
-    signal histogram_input : lword := LWORD_NULL;
+    signal counter     : integer := 0;
+    signal track_delta : integer := 0;
+
+    signal localx_histogram_input : lword := LWORD_NULL;
+    signal deltax_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');
@@ -65,6 +69,8 @@ architecture Behavioral of TrackFinder is
     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');
+
 begin
 
     --==============================--
@@ -87,7 +93,7 @@ begin
     --==============================--
     generic map(
         N_CTRL    => 2,
-        N_STAT    => 1
+        N_STAT    => 2
     )
     port map(
         clk       => ipb_clk,
@@ -121,14 +127,47 @@ begin
             valid_event <= and_reduce(valid_event_array) and header_start;
 
             if valid_event = '1' then
-                histogram_input.valid <= '1';
-                histogram_input.data(11 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 12));
+                track_delta <= stub_array(4).localx - stub_array(0).localx + 1;
+            end if;
+            if counter = 1 then
+                if (track_delta > -127) and (track_delta < 127) then
+                    deltax_histogram_input.valid <= '1';
+                    deltax_histogram_input.data(7 downto 0) <= std_logic_vector(to_unsigned(track_delta + 128, 8));
+                else
+                    deltax_histogram_input <= LWORD_NULL;
+                end if;
             else
-                histogram_input <= LWORD_NULL;
+                deltax_histogram_input <= LWORD_NULL;
+            end if;
+
+            if valid_event = '1' then
+                localx_histogram_input.valid <= '1';
+                localx_histogram_input.data(11 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 12));
+            else
+                localx_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
@@ -141,15 +180,15 @@ begin
     port map (
         --- Input Ports ---
         clk_p           => clk_p,
-        data_in         => histogram_input,
+        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,
-        ipbus_in  => ipb_to_slaves(N_SLV_TRACKING_LOCALX_MEM),
-        ipbus_out => ipb_from_slaves(N_SLV_TRACKING_LOCALX_MEM)
+        ipb_in          => ipb_to_slaves(N_SLV_TRACKING_LOCALX_MEM),
+        ipb_out         => ipb_from_slaves(N_SLV_TRACKING_LOCALX_MEM)
     );
 
     --==============================--
@@ -163,10 +202,33 @@ begin
         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)
+    );
+
     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;
 
 end Behavioral;
-- 
GitLab


From baa1655f62f6ea11a579b3fd6e30e124587c92fe Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 11:35:52 +0200
Subject: [PATCH 103/109] Removed ports

---
 common/firmware/hdl/MProcessor.vhd | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index aef64452..5fdfe885 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -169,9 +169,6 @@ begin
         clk_p => clk_p,
         stubs_in => tracking_stubs,
         header_start => packet_start,
-        localx_trigger_window => localx_trigger_window,
-        --- Output Ports ---
-        localx_max_value => localx_max_value,
         --- IPBus Ports ---
         ipb_clk             => ipb_clk,
         ipb_rst             => ipb_rst,
-- 
GitLab


From 7cf77e5dd5b12b94d5aca2a36c55ed9d4edb12f3 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 16:35:16 +0200
Subject: [PATCH 104/109] Updated offset

---
 common/firmware/hdl/MProcessor.vhd  | 4 ++--
 common/firmware/hdl/TrackFinder.vhd | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/common/firmware/hdl/MProcessor.vhd b/common/firmware/hdl/MProcessor.vhd
index 5fdfe885..9ccd7790 100644
--- a/common/firmware/hdl/MProcessor.vhd
+++ b/common/firmware/hdl/MProcessor.vhd
@@ -172,8 +172,8 @@ begin
         --- 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)
+        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;
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 8a8e27cf..ac06ff40 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -142,7 +142,7 @@ begin
 
             if valid_event = '1' then
                 localx_histogram_input.valid <= '1';
-                localx_histogram_input.data(11 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 12));
+                localx_histogram_input.data(10 downto 0) <= std_logic_vector(to_unsigned(stub_array(0).localx, 11));
             else
                 localx_histogram_input <= LWORD_NULL;
             end if;
@@ -175,7 +175,7 @@ begin
     generic map (
         input_width => 8,
         bin_width   => 32,
-        data_offset => 4
+        data_offset => 3
     )
     port map (
         --- Input Ports ---
-- 
GitLab


From ec9d2ecff135b472ec134b50a75fe35454aadf6c Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 16:47:04 +0200
Subject: [PATCH 105/109] Added histograms for Y axis

---
 common/addr_table/mprocessor.xml    |  2 +-
 common/addr_table/track_finder.xml  | 10 ++--
 common/firmware/hdl/TrackFinder.vhd | 82 ++++++++++++++++++++++++++---
 3 files changed, 83 insertions(+), 11 deletions(-)

diff --git a/common/addr_table/mprocessor.xml b/common/addr_table/mprocessor.xml
index 21272a11..b25246c8 100644
--- a/common/addr_table/mprocessor.xml
+++ b/common/addr_table/mprocessor.xml
@@ -24,5 +24,5 @@
 
     <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=10"/>
+    <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
index 83efe87c..176246e6 100644
--- a/common/addr_table/track_finder.xml
+++ b/common/addr_table/track_finder.xml
@@ -1,11 +1,15 @@
 <node description="TrackFinder Control and Status" fwinfo="endpoint">
-    <node id="csr" address="0x00" description="TrackFinder control and status" fwinfo="endpoint;width=2">
+    <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="0x2"/>
-        <node id="deltax_max_value"    address="0x3"/>
+        <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_localx_mem" address="0x300" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
+    <node id="tracking_deltax_mem" address="0x400" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
 </node>
\ No newline at end of file
diff --git a/common/firmware/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index ac06ff40..80d98294 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -50,18 +50,21 @@ 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(2 - 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(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 : integer := 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');
@@ -70,6 +73,8 @@ architecture Behavioral of TrackFinder is
     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
 
@@ -93,7 +98,7 @@ begin
     --==============================--
     generic map(
         N_CTRL    => 2,
-        N_STAT    => 2
+        N_STAT    => 4
     )
     port map(
         clk       => ipb_clk,
@@ -127,12 +132,12 @@ begin
             valid_event <= and_reduce(valid_event_array) and header_start;
 
             if valid_event = '1' then
-                track_delta <= stub_array(4).localx - stub_array(0).localx + 1;
+                track_delta_x <= stub_array(4).localx - stub_array(0).localx + 1;
             end if;
             if counter = 1 then
-                if (track_delta > -127) and (track_delta < 127) 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 + 128, 8));
+                    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;
@@ -140,11 +145,28 @@ begin
                 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;
@@ -224,11 +246,57 @@ begin
         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)
+    );
+
+    --==============================--
+    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         => 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;
-- 
GitLab


From edd6f815ab8074eec13e9a9f1b1f8adcc4b5c27b Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Sun, 10 Sep 2023 17:20:27 +0200
Subject: [PATCH 106/109] Fixed naming

---
 common/addr_table/track_finder.xml  | 4 ++--
 common/firmware/hdl/TrackFinder.vhd | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/common/addr_table/track_finder.xml b/common/addr_table/track_finder.xml
index 176246e6..cbe8cca8 100644
--- a/common/addr_table/track_finder.xml
+++ b/common/addr_table/track_finder.xml
@@ -10,6 +10,6 @@
 
     <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_localx_mem" address="0x300" size="0x100" mode="incremental" fwinfo="endpoint;width=8"/>
-    <node id="tracking_deltax_mem" address="0x400" 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/hdl/TrackFinder.vhd b/common/firmware/hdl/TrackFinder.vhd
index 80d98294..36a7c9cf 100644
--- a/common/firmware/hdl/TrackFinder.vhd
+++ b/common/firmware/hdl/TrackFinder.vhd
@@ -269,7 +269,7 @@ begin
     );
 
     --==============================--
-    DeltaXHistogramInstance : entity work.IPBusHistogram
+    DeltaYHistogramInstance : entity work.IPBusHistogram
     --==============================--
     generic map (
         input_width => 8,
-- 
GitLab


From c61f0c4862e1677e1593c25aebdabe154e2a524c Mon Sep 17 00:00:00 2001
From: Kirika Uchida <kirika.uchida@cern.ch>
Date: Sun, 10 Sep 2023 18:07:19 +0200
Subject: [PATCH 107/109] Revert "added a buffer at ZSF"

---
 common/addr_table/eprocessor.xml              |   9 +-
 common/firmware/cfg/module.dep                |   1 +
 common/firmware/hdl/EcalDataAggregator.vhd    |  23 +++-
 common/firmware/hdl/EcalDataDecoder.vhd       |  12 +-
 common/firmware/hdl/EcalDataFilter.vhd        |  53 +++++--
 common/firmware/hdl/EcalDataProcessor.vhd     | 130 +++++++++++-------
 .../hdl/EcalZeroSuppressionFilter.vhd         |   8 +-
 .../firmware/ucf/eprocessor_constraints.tcl   |   4 +
 top/firmware/hdl/emp_payload.vhd              |   2 +-
 top/firmware/hdl/emp_project_decl.vhd         |  12 +-
 10 files changed, 168 insertions(+), 86 deletions(-)
 create mode 100644 common/firmware/ucf/eprocessor_constraints.tcl

diff --git a/common/addr_table/eprocessor.xml b/common/addr_table/eprocessor.xml
index ad686de3..4d191f63 100644
--- a/common/addr_table/eprocessor.xml
+++ b/common/addr_table/eprocessor.xml
@@ -1,18 +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="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="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 id="mon" address="0x80" description="Ecal data monitoring" fwinfo="endpoint;width=2"/>
 </node>
diff --git a/common/firmware/cfg/module.dep b/common/firmware/cfg/module.dep
index 804dc871..7c3a1915 100644
--- a/common/firmware/cfg/module.dep
+++ b/common/firmware/cfg/module.dep
@@ -34,6 +34,7 @@ addrtab -t eprocessor.xml
 addrtab -t link_aggregator.xml
 addrtab -t track_finder.xml
 
+
 # IP Cores
 src --cd ../cgn link_agg_single_link_fifo.xci
 setup -f --cd ../cgn link_agg_single_link_fifo.tcl
diff --git a/common/firmware/hdl/EcalDataAggregator.vhd b/common/firmware/hdl/EcalDataAggregator.vhd
index 65ee6c27..a6c216db 100644
--- a/common/firmware/hdl/EcalDataAggregator.vhd
+++ b/common/firmware/hdl/EcalDataAggregator.vhd
@@ -28,6 +28,10 @@ architecture rtl of EcalDataAggregator is
   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);
@@ -67,14 +71,19 @@ begin
             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_start <= '0';
-          data_out_last <= '0';
+          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 <= ecal_data_p;
-               data_out_start <= '1';
+               data_out_s <= ecal_data_p;
+               data_out_s_start <= '1';
                last_valid_bcid <= bcid_p(0);
                sync <= '1';
              elsif timer = 7 then
@@ -86,8 +95,8 @@ begin
             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 <= ecal_data_p;
-                data_out_start <= '1'; 
+                data_out_s <= ecal_data_p;
+                data_out_s_start <= '1'; 
                 last_valid_bcid <= bcid_p(0);
               else
                 sync <= '0';
@@ -95,7 +104,7 @@ begin
             else 
                timer := timer + 1;
                if timer = 7 then
-                 data_out_last <= '1';
+                 data_out_s_last <= '1';
                end if;
             end if;
           end if;
diff --git a/common/firmware/hdl/EcalDataDecoder.vhd b/common/firmware/hdl/EcalDataDecoder.vhd
index d5f3ee31..680001ec 100644
--- a/common/firmware/hdl/EcalDataDecoder.vhd
+++ b/common/firmware/hdl/EcalDataDecoder.vhd
@@ -25,6 +25,10 @@ architecture rtl of EcalDataDecoder is
       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)
@@ -32,11 +36,9 @@ begin
   begin
     if rising_edge(clk_p) then
        
-        for j in 0 to 1 loop
-            for i in 0 to 6 loop 
-                elink_data(j*7+i) <= elink_data(j*7+i)(6 downto 0) & data_in.data(j*32+i);
-            end loop;
-        end loop;
+	    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;
 
diff --git a/common/firmware/hdl/EcalDataFilter.vhd b/common/firmware/hdl/EcalDataFilter.vhd
index 0754a9f6..12471a16 100644
--- a/common/firmware/hdl/EcalDataFilter.vhd
+++ b/common/firmware/hdl/EcalDataFilter.vhd
@@ -16,7 +16,7 @@ port (
         clk_p            : in  std_logic;
         clk40            : in  std_logic;
         reset            : in  std_logic;
-        data_in_valid    : 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);
@@ -35,9 +35,11 @@ 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_meta         : std_logic_vector(28 * 16 -1 downto 0);
-  signal data_sync         : std_logic_vector(28 * 16 -1 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);
@@ -73,24 +75,55 @@ begin
   );
 
   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     <= trig_sync    when bypass_s = '0' else x"c0000001";
+  trig_o     <= trig40       when bypass_s = '0' else b_trg & b_trg & "00" & x"000000" & "000" & b_trg;
 
-  data_meta   <= data_in   when rising_edge(clk40);
-  data_sync   <= data_meta when rising_edge(clk40);
-  
-  trig_meta    <= trig40    when rising_edge(clk_p);
-  trig_sync    <= trig_meta when rising_edge(clk_p);
+  -- 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;
@@ -112,7 +145,7 @@ begin
   port map (
     clk                => clk40,
     rst                => reset,
-    lpgbt_payload_i    => data_sync,
+    lpgbt_payload_i    => data_s,
     sc_regs_i          => zs_sc_regs,
     valid_o            => zs_valid,
     all_valids_o       => zs_all_valids,
diff --git a/common/firmware/hdl/EcalDataProcessor.vhd b/common/firmware/hdl/EcalDataProcessor.vhd
index 64c1eb69..bebd5bc5 100644
--- a/common/firmware/hdl/EcalDataProcessor.vhd
+++ b/common/firmware/hdl/EcalDataProcessor.vhd
@@ -62,6 +62,7 @@ architecture rtl of EcalDataProcessor is
   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);
@@ -115,10 +116,11 @@ begin
   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)(9) <= data_ready_i;
-  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)(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);
@@ -144,7 +146,7 @@ begin
     clk_p              => clk_p,
     clk40              => clk40,
     reset              => reset,
-    data_in_valid      => data_start,
+    data_in_start      => data_start,
     data_in            => data,
     trig_o_lat         => trig_lat,
     trig_o             => trig,
@@ -201,8 +203,11 @@ begin
   ); 
   
   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';
@@ -218,14 +223,30 @@ begin
           data_out(0).strobe <= '0';
           case ostate is
             when wait_start =>
-              if data_out_s.start = '1' then
+							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;
-                if data_out_s.last = '1' then
+								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 
@@ -329,7 +350,6 @@ begin
             if t_waddr_valid then
               trig_ram_wea   <= '1';
               trig_ram_addra <= std_logic_vector(to_unsigned(t_waddr,6));
-              trig_ram_dina  <= trig;
             end if;
           end if;  
  
@@ -344,15 +364,58 @@ begin
             
             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;
+              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;
-
-            data_out_s.valid <= trig_ram_doutb(0) and data_ram_doutb(bit_valid);           
-            data_out_s.start <= trig_ram_doutb(31) and data_ram_doutb(bit_start) and gbe_backpressure;
-            data_out_s.last  <= trig_ram_doutb(30) and data_ram_doutb(bit_last);
-            data_out_s.strobe <= trig_ram_doutb(30) and data_ram_doutb(bit_last);         
           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
@@ -415,45 +478,6 @@ begin
             g_timer := g_timer + 1;
           end if;
             
-          -- data to write                   
-          data_ram_addra <= std_logic_vector(to_unsigned(d_waddr, 9));
-          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
-            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
-              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
-          
         end if;   
     end process;
     
diff --git a/common/firmware/hdl/EcalZeroSuppressionFilter.vhd b/common/firmware/hdl/EcalZeroSuppressionFilter.vhd
index dd5b23ce..ed8dde99 100644
--- a/common/firmware/hdl/EcalZeroSuppressionFilter.vhd
+++ b/common/firmware/hdl/EcalZeroSuppressionFilter.vhd
@@ -359,10 +359,12 @@ p_SM_com_comb:process(State_com, trg, Cnt_com) is
           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) 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
+          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);                 
diff --git a/common/firmware/ucf/eprocessor_constraints.tcl b/common/firmware/ucf/eprocessor_constraints.tcl
new file mode 100644
index 00000000..ee205f25
--- /dev/null
+++ b/common/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/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index badc237e..f022b583 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -469,7 +469,7 @@ begin
     
 
 
-    gbe_q <= eth_link_out;
+    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);
 
diff --git a/top/firmware/hdl/emp_project_decl.vhd b/top/firmware/hdl/emp_project_decl.vhd
index 971319c1..d704bc63 100644
--- a/top/firmware/hdl/emp_project_decl.vhd
+++ b/top/firmware/hdl/emp_project_decl.vhd
@@ -34,9 +34,9 @@ package emp_project_decl is
 
   -- mgt -> buf -> fmt -> (algo) -> (fmt) -> buf -> mgt -> clk -> altclk
   constant REGION_CONF : region_conf_array_t := (
---    0  => (lpgbt, buf, no_fmt, buf, lpgbt),   --Bank 225 -- Right Column
+  --  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
+  --  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
@@ -62,6 +62,12 @@ package emp_project_decl is
   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),
@@ -86,7 +92,7 @@ package emp_project_decl is
   -- for lpgbt
   constant REGION_LPGBT_CONF : region_lpgbt_conf_array_t := (
 --    2  => (FEC5, DATARATE_5G12, PCS),
---    3  => (FEC5, DATARATE_5G12, PCS),
+    3  => (FEC5, DATARATE_5G12, PCS),
     4  => (FEC5, DATARATE_5G12, PCS),
     5  => (FEC5, DATARATE_5G12, PCS),
     6  => (FEC5, DATARATE_5G12, PCS),
-- 
GitLab


From b901da5115587f91da6ed494fd0039356fba2474 Mon Sep 17 00:00:00 2001
From: David Gabriel Monk <david.gabriel.monk@cern.ch>
Date: Thu, 14 Sep 2023 08:56:30 +0200
Subject: [PATCH 108/109] Update file emp_payload.vhd

---
 top/firmware/hdl/emp_payload.vhd | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/top/firmware/hdl/emp_payload.vhd b/top/firmware/hdl/emp_payload.vhd
index f022b583..69d7278f 100644
--- a/top/firmware/hdl/emp_payload.vhd
+++ b/top/firmware/hdl/emp_payload.vhd
@@ -94,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
@@ -277,14 +279,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 ---
-- 
GitLab


From 0ce9da46588e5ec3d618ef7a42985ba32c0392b2 Mon Sep 17 00:00:00 2001
From: David Monk <david.gabriel.monk@cern.ch>
Date: Fri, 26 Apr 2024 13:10:29 +0200
Subject: [PATCH 109/109] Moved top files to muone algorithm

---
 .gitlab-ci.yml                                    | 4 ++--
 top/{ => muone}/addr_table/emp_payload.xml        | 0
 top/{ => muone}/firmware/cfg/top.dep              | 0
 top/{ => muone}/firmware/hdl/emp_payload.vhd      | 0
 top/{ => muone}/firmware/hdl/emp_project_decl.vhd | 0
 top/{ => muone}/firmware/hdl/link_maps.vhd        | 0
 6 files changed, 2 insertions(+), 2 deletions(-)
 rename top/{ => muone}/addr_table/emp_payload.xml (100%)
 rename top/{ => muone}/firmware/cfg/top.dep (100%)
 rename top/{ => muone}/firmware/hdl/emp_payload.vhd (100%)
 rename top/{ => muone}/firmware/hdl/emp_project_decl.vhd (100%)
 rename top/{ => muone}/firmware/hdl/link_maps.vhd (100%)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 8fe1eba7..9d6acdb2 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,9 +3,9 @@ include:
     file: "/ci/templates/vivado-jobs.yml"
 
 variables:
-  VIVADO_VER: "2022.2"
+  VIVADO_VER: "2023.2"
   PROJECT_DEPFILE: top.dep
-  PROJECT_ALGORITHM: top
+  PROJECT_ALGORITHM: top/muone
   PROJECT_NAME: mprocessor
   EMPHUB_TAG: $CI_COMMIT_REF_NAME-$CI_COMMIT_SHORT_SHA
   IPBB_VER: "dev-2021j-v1.2"
diff --git a/top/addr_table/emp_payload.xml b/top/muone/addr_table/emp_payload.xml
similarity index 100%
rename from top/addr_table/emp_payload.xml
rename to top/muone/addr_table/emp_payload.xml
diff --git a/top/firmware/cfg/top.dep b/top/muone/firmware/cfg/top.dep
similarity index 100%
rename from top/firmware/cfg/top.dep
rename to top/muone/firmware/cfg/top.dep
diff --git a/top/firmware/hdl/emp_payload.vhd b/top/muone/firmware/hdl/emp_payload.vhd
similarity index 100%
rename from top/firmware/hdl/emp_payload.vhd
rename to top/muone/firmware/hdl/emp_payload.vhd
diff --git a/top/firmware/hdl/emp_project_decl.vhd b/top/muone/firmware/hdl/emp_project_decl.vhd
similarity index 100%
rename from top/firmware/hdl/emp_project_decl.vhd
rename to top/muone/firmware/hdl/emp_project_decl.vhd
diff --git a/top/firmware/hdl/link_maps.vhd b/top/muone/firmware/hdl/link_maps.vhd
similarity index 100%
rename from top/firmware/hdl/link_maps.vhd
rename to top/muone/firmware/hdl/link_maps.vhd
-- 
GitLab