diff --git a/.gitignore b/.gitignore
index 1e69f92bfa0862eeb16acb5d1cc7d7bdd063c61e..ffc95991b922acef816f69f76308baed70369227 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,4 +39,6 @@ Pcie40Applications/pcie40_miniPod
 Pcie40Applications/pcie40_send_ul
 *.d
 **/pcie40_reload.out
-
+Pcie40Applications/regconfig
+Pcie40Applications/statlink
+Pcie40Applications/timediff
diff --git a/Pcie40Applications/Makefile b/Pcie40Applications/Makefile
index ee95ed5c34e361f2275290cbf83d2d3bd0bd9a76..c0ecff2f5f96d9c84f03653fb78be73b94fdb1e1 100644
--- a/Pcie40Applications/Makefile
+++ b/Pcie40Applications/Makefile
@@ -100,6 +100,24 @@ PCIE40_MINIPOD_CXXFLAGS =$(CFLAGS) -I$(TOP) -I$(TOP)/../Pcie40Driver -I$(TOP)/..
 PCIE40_MINIPOD_INSTALL =$(PREFIX)/bin
 PCIE40_MINIPOD_LDFLAGS = -L../Pcie40Libraries/lib -lpcie40 -L../Pcie40DriverLibraries/ -lpcie40driver_ecs
 
+REGCONFIG :=regconfig
+REGCONFIG_OBJS =regconfig.o
+REGCONFIG_CXXFLAGS =$(CFLAGS) -I$(TOP) -I$(TOP)/../Pcie40Libraries
+REGCONFIG_INSTALL =$(PREFIX)/bin
+REGCONFIG_LDFLAGS = -L../Pcie40Libraries/lib -lpcie40 -L../Pcie40DriverLibraries/ -lpcie40driver_ecs
+
+STATLINK :=statlink
+STATLINK_OBJS =statlink.o
+STATLINK_CXXFLAGS =$(CFLAGS) -I$(TOP) -I$(TOP)/../Pcie40Libraries
+STATLINK_INSTALL =$(PREFIX)/bin
+STATLINK_LDFLAGS = -L../Pcie40Libraries/lib -lpcie40 -L../Pcie40DriverLibraries/ -lpcie40driver_ecs
+
+TIMEDIFF :=timediff
+TIMEDIFF_OBJS =timediff.o
+TIMEDIFF_CXXFLAGS =$(CFLAGS) -I$(TOP) -I$(TOP)/../Pcie40Libraries 
+TIMEDIFF_INSTALL =$(PREFIX)/bin
+TIMEDIFF_LDFLAGS = -L../Pcie40Libraries/lib -lpcie40 -L../Pcie40DriverLibraries/ -lpcie40driver_ecs -lrt
+
 VPATH :=$(TOP)
 
 include $(TOP)/rules.mk
@@ -118,6 +136,9 @@ $(eval $(call ODIR_template,PCIE40_ULRESET))
 $(eval $(call ODIR_template,PCIE40_DMA_CHECK))
 $(eval $(call ODIR_template,PCIE40_READFPGAVERSION))
 $(eval $(call ODIR_template,PCIE40_MINIPOD))
+$(eval $(call ODIR_template,REGCONFIG))
+$(eval $(call ODIR_template,STATLINK))
+$(eval $(call ODIR_template,TIMEDIFF))
 $(eval $(call COPY_template,SCRIPTS,755))
 $(eval $(call LINK_template,PCIE40_RELOAD))
 $(eval $(call ODIR_template,PCIE40_RELOAD_SUID))
diff --git a/Pcie40Applications/regconfig.cpp b/Pcie40Applications/regconfig.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..882860ee456bc610dc82f8eabe4b4486472935aa
--- /dev/null
+++ b/Pcie40Applications/regconfig.cpp
@@ -0,0 +1,384 @@
+
+/*-------------------------------------------------------------------------------*\
+  regconfig: From PCIe40 board to access register of FEE through belle2link
+
+  Qi-Dong Zhou, KEK 
+
+  2020.03.06  0.01 first version based on reghs.c
+
+\*--------------------------------------------------------------------------------*/
+#define VERSION 01
+#define MOD_DATE 20200420
+
+#include "pcie40_b2slc.h"
+#include "pcie40_reg.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <vector>
+
+extern "C" int  ecs_open(int dev, int bar);
+extern "C" void ecs_close(int dev, int bar);
+//#define PCIE_DEV     0
+#define MAX_NUM_CH   48
+#define MAX_SLOT     3
+#define SLC_BAR      2
+
+// parse 
+int dev_slot         = 0; // default device slot number, If use multiple PCIe40 on a server, change it with --dev xx option
+int ch               = -1;
+unsigned int addr    = 0;
+unsigned int data    = 0;
+char *filename;
+char *operation;
+
+//Flag for switch slc access method
+bool USE_FEE8        = false;
+bool USE_FEE32       = false;
+bool READ_ONLY       = false;
+bool WRITE           = false;
+bool STREAM          = false;
+bool STREAM_ARICH    = false;
+bool OP_FLAG         = false;
+
+/* 0 parameter */
+#define PCIE40_NOP      0x100
+#define PCIE40_LINK     0x101
+#define PCIE40_CHECKFEE 0x102
+#define PCIE40_TRGOFF   0x104
+#define PCIE40_TRGON    0x105
+
+/* 0 parameter (obsolete, unused) */
+#define PCIE40_TTTRG    0x106
+#define PCIE40_DUMTRG   0x107
+
+/* 0 parameter (CDC special) */
+#define PCIE40_SUPMODE  0x108
+#define PCIE40_RAWMODE  0x109
+
+/* 1 parameter */
+#define PCIE40_STREAM   0x200
+
+/* 1 parameter (CDC special) */
+#define PCIE40_PDSTLALL 0x201
+#define PCIE40_ADCTH    0x202
+#define PCIE40_TDCTH    0x203
+#define PCIE40_DELAY    0x204
+#define PCIE40_WINDOW   0x205
+
+/* 2 parameters */
+#define PCIE40_FEE8     0x300
+#define PCIE40_FEE32    0x301
+
+/* 2 parameters (CDC special) */
+#define PCIE40_PDSTL    0x302
+
+/* defined address */
+#define REG_FEEHWTYPE   0x0
+#define REG_FEESERIAL   0x0
+#define REG_FEEFWTYPE   0x0
+#define REG_FEEFWVER    0x0
+
+
+std::vector<std::string> splitpath(const std::string str, const char del) {
+  int first = 0;
+  int last = str.find_first_of(del);
+ 
+  std::vector<std::string> result;
+ 
+  while (first < str.size()) {
+    std::string subStr(str, first, last - first);
+ 
+    result.push_back(subStr);
+ 
+    first = last + 1;
+    last = str.find_first_of(del, first);
+ 
+    if (last == std::string::npos) {
+            last = str.size();
+    }
+  }
+  return result;
+}
+
+void argument(int argc, char **argv){
+  char *ARGV0 = argv[0]; 	
+  for(int i=1;i<argc;i++){
+    std::string ss = argv[i];
+    if(ss=="--dev"){
+      dev_slot = atoi(argv[++i]);
+      if( dev_slot<0 || dev_slot >= MAX_SLOT){
+	fprintf(stderr, "Invalid device slot %d, Valid slot [0, %d]\n", dev_slot, MAX_SLOT);
+      }
+    }
+    if(ss=="--ch"){
+      ch = atoi(argv[++i]);
+      if( ch<0 || ch >= MAX_NUM_CH){
+	fprintf(stderr, "Invalid channel ID %d, Valid ID [0, %d]\n", ch, MAX_NUM_CH);
+      }
+    }
+    if(ss=="--fee8"){
+      USE_FEE8 = true;
+    } 
+    if(ss=="--fee32"){
+      USE_FEE32 = true;
+    } 
+    if(ss=="-r" || ss=="--read"){
+      READ_ONLY = true;
+      addr = strtoul(argv[++i], 0, 16);
+    } 
+    if(ss=="-w" || ss=="--write"){
+      WRITE = true;
+      addr = strtoul(argv[++i], 0, 16);
+      data = strtoul(argv[++i], 0, 16);
+      //printf("add = %02x  data = %08x\n", addr, data);
+    } 
+    if(ss=="--stream"){
+      STREAM = true;
+      filename = argv[++i];
+      std::string file_str = filename;
+      char delims = '.'; 
+      std::vector<std::string> path = splitpath(file_str, delims);
+      if(path.back() == "bin" || path.back() == "bit"){
+	STREAM_ARICH = true;
+      }
+      //std::cout << path.back() << std::endl;
+      
+    } 
+    if(ss=="--op"){
+      OP_FLAG = true;
+      operation = argv[++i];
+      addr = strtoul(argv[++i], 0, 16);
+      data = strtoul(argv[++i], 0, 16);
+    }
+    if(ss=="-h" || ss=="-help"){
+      fprintf(stderr, "%s version %d.%02d date %d\n"
+            , ARGV0, VERSION/100, VERSION%100, MOD_DATE);
+      fprintf(stderr,  "usage: %s --ch 0 --fee32 -w 0x12 0x0\n"
+                       "       --dev   xx              #device slot number which installed PCIe40\n" 
+                       "       --ch    xx              #link channel number\n" 
+                       "       --fee8 or --fee32       #use A7D8 or A16D32 for access register\n"
+                       "       -r xx or -w xx xx       #read or write register with address xx[hex] or data xx[hex]\n\n"
+	               "       %s --ch 0 --stream /path/firmware.bit\n"
+                       "       --stream /path/filename #streaming a file by using stream file method\n\n"
+	      , ARGV0, ARGV0);
+      return;
+    }
+  }
+}
+
+/* ---------------------------------------------------------------------- *\
+   hsreg
+\* ---------------------------------------------------------------------- */
+int
+hsreg(const char *name)
+{
+  static struct { char *name; int adrs; } regs[] = {
+    { "link",     PCIE40_LINK } ,
+    { "checkfee", PCIE40_CHECKFEE },
+    
+    { "trghold",  PCIE40_TRGOFF },
+    { "trigger",  PCIE40_TRGON },
+    { "realtrg",  PCIE40_TTTRG },
+    { "simtrg" ,  PCIE40_DUMTRG },
+    { "simple",   PCIE40_SUPMODE },
+    { "verbose",  PCIE40_RAWMODE },
+    
+    { "supmode",  PCIE40_SUPMODE },
+    { "rawmode",  PCIE40_RAWMODE },
+    
+    { "pdstl",    PCIE40_PDSTL },
+    { "pdstlall", PCIE40_PDSTLALL },
+    { "adcth",    PCIE40_ADCTH },
+    { "tdcth",    PCIE40_TDCTH },
+    { "delay",    PCIE40_DELAY },
+    { "window",   PCIE40_WINDOW },
+
+    { "stat",     PCIE40REGL_STAT },
+  };
+  int i;
+
+  if (isdigit(name[0])) {
+    return strtoul(name, 0, 16);
+  }
+
+  for (i = 0; i<sizeof(regs)/sizeof(regs[0]); i++) {
+    if (strcmp(regs[i].name, name) == 0) {
+      return regs[i].adrs;
+    }
+  }
+    
+  i = strtoul(name, 0, 16);
+  return (i > 0 && i < 0x100) ? i : -1;
+}
+
+/* ---------------------------------------------------------------------- *\
+   pcie40_op
+\* ---------------------------------------------------------------------- */
+int
+pcie40_op(int dev, int ch, int op_addr, int addr, int data)
+{
+  int i;
+  const char *feetype;
+  int cmd = 0;
+  int cmd_cdc = 0;
+  
+  switch (op_addr) {
+  case PCIE40_LINK:    cmd = 0x01; break;
+  case PCIE40_TRGOFF:  cmd = 0x03; break;
+  case PCIE40_TRGON:   cmd = 0x04; break;
+  case PCIE40_SUPMODE: cmd_cdc = 0x07; break; /* suppress mode */
+  case PCIE40_RAWMODE: cmd_cdc = 0x08; break; /* raw mode */
+  }
+
+  if (op_addr == PCIE40_CHECKFEE) {
+    int ret;
+    int hwtype;
+    int serial;
+    int fwtype;
+    int fwver;
+    static const char *feetype[] = {
+      "UNDEF", "SVD", "CDC", "BPID", "EPID", "ECL", "EECL", "KLM", "EKLM",
+      "TRG", "UNKNOWN-10", "UNKNOWN-11",
+      "UNKNOWN-12", "UNKNOWN-13", "DEMO", "TEST" };
+    static const char *demotype[] = {
+      "UNDEF", "HSLB-B2L", "SP605-B2L", "ML605-B2L", "AC701-B2L" };
+    static const char *trgtype[] = {
+      "TRGMERGER", /* = 0 */
+      "TRGTSF",    /* = 1 */
+      "TRG2D",     /* = 2 */
+      "TRG3D",     /* = 3 */
+      "TRGNN",     /* = 4 */
+      "TRGEVTT",   /* = 5 */
+      "TRGGRL",    /* = 6 */
+      "TRGGDL",    /* = 7 */
+      "TRGETM",    /* = 8 */
+      "TRGTOP",    /* = 9 */
+      "TRGKLM",    /* = 10 */
+    };
+
+    if (!pcie40_b2l_status(dev_slot, ch)) {
+      printf("Failed: b2l is down\n");
+      return -1;
+    }
+    hwtype = pcie40_readfee8(dev, ch, REG_FEEHWTYPE);
+    serial = pcie40_readfee8(dev, ch, REG_FEESERIAL);
+    fwtype = pcie40_readfee8(dev, ch, REG_FEEFWTYPE);
+    fwver  = pcie40_readfee8(dev, ch, REG_FEEFWVER);
+
+    serial |= (hwtype & 0xf) << 8;
+    fwver  |= (fwtype & 0xf) << 8;
+    hwtype = (hwtype >> 4) & 0xf;
+    fwtype = (fwtype >> 4) & 0xf;
+
+    if (hwtype == 14 && fwtype > 0 && fwtype <= 4) {
+      printf("FEE type %s serial %d version %d at PCIE40_LINK-%d\n",
+	     demotype[fwtype], serial, fwver, ch);
+    } else if (hwtype == 9 && fwtype >= 0 && fwtype <= 10) {
+      printf("FEE type %s serial %d version %d at PCIE40_LINK-%d\n",
+	     trgtype[fwtype], serial, fwver, ch);
+    } else {
+      printf("FEE type %s serial %d firmware %d version %d at PCIE40_LINK-%d\n",
+	     feetype[hwtype], serial, fwtype, fwver, ch);
+    }
+  } else if (cmd) {
+    pcie40_writefee8(dev, ch, PCIE40REG_FEECONT, cmd);
+    
+  } else if (cmd_cdc) {
+    pcie40_writefee8(dev, ch, PCIE40REG_CDCCONT, cmd_cdc);
+  }else if (op_addr == PCIE40_PDSTL) {
+    if (addr <= 0 || addr > 48) {
+      printf("pedestal channel %d out of range [1,48]\n", addr);
+      return -1;
+    }
+    pcie40_writefee8(dev, ch, PCIE40REG_PDSTLMIN + (addr-1)*2+0, (data>>0) & 0xff);
+    pcie40_writefee8(dev, ch, PCIE40REG_PDSTLMIN + (addr-1)*2+1, (data>>8) & 0xff);
+  } else if (op_addr == PCIE40_PDSTLALL) {
+    for (i=1; i<=48; i++) {
+      pcie40_writefee8(dev, ch, PCIE40REG_PDSTLMIN + (i-1)*2+0, (addr>>0) & 0xff);
+      pcie40_writefee8(dev, ch, PCIE40REG_PDSTLMIN + (i-1)*2+1, (addr>>8) & 0xff);
+    }
+
+  } else if (op_addr == PCIE40_ADCTH || op_addr == PCIE40_TDCTH) {
+    int adr = (op_addr == PCIE40_ADCTH) ? PCIE40REG_ADCTH : PCIE40REG_TDCTH;
+    
+    if (addr != -1) {
+      pcie40_writefee8(dev, ch, adr + 0, (addr>>0) & 0xff);
+      pcie40_writefee8(dev, ch, adr + 1, (addr>>8) & 0xff);
+    } else {
+      printf("reg%02x = %02x%02x\n", adr,
+             pcie40_readfee8(dev, ch, adr + 1) & 0xff,
+             pcie40_readfee8(dev, ch, adr + 0) & 0xff);
+    }
+
+  }else if (op_addr == PCIE40_WINDOW || op_addr == PCIE40_DELAY) {
+    int adr = (op_addr == PCIE40_WINDOW) ? PCIE40REG_WINDOW : PCIE40REG_DELAY;
+    
+    if (addr != -1) {
+      pcie40_writefee8(dev, ch, adr, addr & 0xff);
+    } else {
+      printf("reg%02x = %02x\n", adr, pcie40_readfee8(dev, ch, adr));
+    }
+    
+  } else {
+
+    printf("undefined action %x\n", op_addr);
+    return -1;
+    
+  }
+  return 0;
+}
+
+int main(int argc, char** argv){
+  
+  // parse arguments
+  argument(argc, argv);
+
+  // open pcie40 device driver for current process
+  ecs_open( dev_slot , SLC_BAR );
+
+  int result = -1;
+
+  if(USE_FEE8 && READ_ONLY){
+    result = pcie40_readfee8( dev_slot , ch , addr );
+    printf("reg%04x = %08x\n", addr, result);
+  }else if(USE_FEE8 && WRITE){
+    result = pcie40_writefee8( dev_slot , ch , addr, data );
+    if(result == 0)
+      printf("Write 0x%04x to register 0x%04x\n", data, addr);
+    else
+      printf("ERROR: Failed to write 0x%04x to register 0x%04x\n", data, addr);
+  }else if(USE_FEE32 && READ_ONLY){
+    result = pcie40_readfee32( dev_slot , ch , addr );
+    printf("reg%04x = %08x\n", addr, result);
+  }else if(USE_FEE32 && WRITE){
+    result = pcie40_writefee32( dev_slot , ch , addr, data );
+    if(result == 0)
+      printf("Write 0x%08x to register 0x%04x\n", data, addr);
+    else
+      printf("ERROR: Failed to write 0x%08x to register %04x\n", data, addr);
+  }else if(STREAM){
+    if(STREAM_ARICH)
+      result = pcie40_writestream_arich( dev_slot , ch , filename ) ;
+    else
+      result = pcie40_writestream_klm( dev_slot , ch , filename ) ;
+    if(result == 0)
+      std::cerr<<"Succeed streaming file: " << filename << std::endl;
+    else
+      std::cerr<<"ERROR: Failed streaming file: " << filename << std::endl;
+  } 
+
+  //This is only frame for register operation in the furture
+  if(OP_FLAG){
+    unsigned int op_addr = hsreg( operation );
+      pcie40_op(dev_slot, ch, op_addr, addr, data);
+  }
+
+  // close pcie40 device driver for current process
+  ecs_close( dev_slot , SLC_BAR) ;
+
+  return 0 ;
+}
+
+
diff --git a/Pcie40Applications/rules.mk b/Pcie40Applications/rules.mk
index 38479046d3cd79a07122c28c8f4eeee3fdf8d870..a8cd3a880a0a25ef17e1ed4179dd48f62db4d731 100644
--- a/Pcie40Applications/rules.mk
+++ b/Pcie40Applications/rules.mk
@@ -2,8 +2,8 @@ BUILD_PREFIX ?=
 LIBDIR_SUFFIX ?=64
 FLEX ?=flex
 LFLAGS ?=
-CFLAGS +=-Wall -g -O3
-CXXFLAGS +=-Wall -g -O3
+CFLAGS +=-Wall -g -O3 
+CXXFLAGS +=-Wall -g -O3 
 DOCRA ?=docra
 ASCIIDOCTOR ?=asciidoctor
 
diff --git a/Pcie40Applications/statlink.cpp b/Pcie40Applications/statlink.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2c60e53cc37f0b8c5a6be53e2940a8519afd48e5
--- /dev/null
+++ b/Pcie40Applications/statlink.cpp
@@ -0,0 +1,298 @@
+
+/*-------------------------------------------------------------------------------*\
+  regconfig: Monitoring the status of PCIe40 board and belle2links
+
+  Qi-Dong Zhou, KEK 
+
+  2020.04.28  0.01 first version based on staths.c
+
+\*--------------------------------------------------------------------------------*/
+#define VERSION 01
+#define MOD_DATE 20200428
+
+#include "pcie40_b2slc.h"
+#include "pcie40_reg.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iostream>
+#include <vector>
+#include <bitset>
+
+extern "C" int  ecs_open(int dev, int bar);
+extern "C" void ecs_close(int dev, int bar);
+//#define PCIE_DEV     0
+#define MAX_NUM_CH   48
+#define MAX_SLOT     3
+#define SLC_BAR      2
+
+#ifndef D
+#define D(a,b,c) (((a)>>(c))&((1<<((b)+1-(c)))-1))
+#define B(a,b)   D(a,b,b)
+#define Bs(a,b,s)   (B(a,b)?(s):"")
+#define Ds(a,b,c,s)   (D(a,b,c)?(s):"")
+#endif
+
+// parse 
+int dev_slot         = 0; // default device slot number, for use multiple PCIe40 on a server,--dev xx option
+int ch               = -1;
+std::bitset<48> link_mask; 
+//Flag for switch slc access method
+
+void argument(int argc, char **argv){
+  char *ARGV0 = argv[0];
+  std::bitset<48> en_link;
+  if(argc == 1){
+    link_mask.set();
+    std::cout<<std::hex<<link_mask<<std::endl;
+  }
+
+  for(int i=1;i<argc;i++){
+    std::string ss = argv[i];
+    if(ss=="--dev"){
+      dev_slot = atoi(argv[++i]);
+      if( dev_slot<0 || dev_slot >= MAX_SLOT){
+	fprintf(stderr, "Invalid device slot %d, Valid slot [0, %d]\n", dev_slot, MAX_SLOT);
+      }
+    }
+    if(ss=="--ch"){
+      for(int j = i+1; j<argc; j++){
+	ch = atoi(argv[j]);
+	if( ch<0 || ch >= MAX_NUM_CH){
+	  fprintf(stderr, "Invalid channel ID %d, Valid ID [0, %d]\n", ch, MAX_NUM_CH);
+	}
+	en_link.reset();
+	en_link.set(ch, true);
+	link_mask = link_mask | en_link;
+	//std::cout <<i << " " << j <<" "<< ch <<" "<<std::hex<< en_link <<" "<<std::hex<<link_mask<< std::endl;
+	
+      }
+    }
+    if(ss=="-h" || ss=="-help"){
+      fprintf(stderr, "%s version %d.%02d date %d\n"
+            , ARGV0, VERSION/100, VERSION%100, MOD_DATE);
+      fprintf(stderr,  "usage: %s --ch 0 \n"
+                       "       --dev   xx              #device slot number which installed PCIe40\n" 
+	               "       --ch    xx  xx ...      #link channel number\n" 
+                       , ARGV0); 
+      return;
+    }
+  }
+}
+
+
+/* ---------------------------------------------------------------------- *\
+ *    statpcie40
+\* ---------------------------------------------------------------------- */
+int
+statpice40(pcie40reg_t pcie40reg)
+{
+  pcie40reg_t *pcie = &pcie40reg;
+  memset(pcie, 0, sizeof(*pcie));
+  int pcie40_sta = pcie40_status(dev_slot);
+  int pcie40_fwver = 0;
+  printf("PCIE40 firmware version %d.%02d\n",pcie40_fwver / 100,  pcie40_fwver % 100);
+  printf("memory: %s | ttd: %s |  ttd clk: %s | run=: %d | trg: %d \n", 
+	 B(pcie40_sta, 8)?"FULL":"OK",
+	 B(pcie40_sta, 12)?"UP":"DOWN",
+	 B(pcie40_sta, 11)?"UP":"DOWN",
+	 pcie40_run_number(dev_slot),
+	 D(pcie40_sta, 28, 17));
+  printf("rxlink: %s | txlink: %s | txlink: %s | rxdisp: %s | rxdata: %s\n", 
+	 B(pcie40_sta, 0)?"READY":"NOT READY",
+	 B(pcie40_sta, 1)?"READY":"NOT READY",
+	 B(pcie40_sta, 2)?"SYNCED":"NOT SYNCED",
+	 B(pcie40_sta, 3)?"ERROR":"OK",
+	 B(pcie40_sta, 4)?"ERROR":"OK");
+
+  return 0;
+}
+
+
+
+/* ---------------------------------------------------------------------- *\
+ *    getfee
+\* ---------------------------------------------------------------------- */
+int
+getfee( pcie40reg_t *pcie40p)
+{
+  int i;
+  const char *feetype;
+
+  int ret;
+  int hwtype;
+  int serial;
+  int fwtype;
+  int fwver;
+
+  hwtype = pcie40_readfee8(dev_slot, ch, PCIE40REG_FEEHWTYPE);
+  serial = pcie40_readfee8(dev_slot, ch, PCIE40REG_FEESERIAL);
+  fwtype = pcie40_readfee8(dev_slot, ch, PCIE40REG_FEEFWTYPE);
+  fwver  = pcie40_readfee8(dev_slot, ch, PCIE40REG_FEEFWVER);
+
+  pcie40p->feeser = (serial | (hwtype << 8)) & 0xfff;
+  pcie40p->feever = (fwver  | (fwtype << 8)) & 0xfff;
+  pcie40p->feehw  = (hwtype >> 4) & 0x0f;
+  pcie40p->feefw  = (fwtype >> 4) & 0x0f;
+  
+  pcie40p->feecrce = pcie40_readfee8(dev_slot, ch, PCIE40REG_CRCERR);
+
+  return 0;
+}
+
+
+/* ---------------------------------------------------------------------- *\
+ *    readregs
+\* ---------------------------------------------------------------------- */
+int
+readregs(std::bitset<48> link_mask, pcie40reg_t pcie40reg[])
+{
+  int i;
+  int o_readonly = 1;
+  int notfound = 1;
+
+  // for (i=0; i<48; i++) {
+    pcie40reg_t *pcie = &pcie40reg[i];
+    memset(pcie, 0, sizeof(*pcie));
+  //   if (!link_mask[i]) continue;
+    
+      pcie->xbusy   = pcie40_readfee32(dev_slot, ch, PCIE40REG_CCLK);
+      pcie->conf    = pcie40_readfee32(dev_slot, ch, PCIE40REG_CONF);
+
+      pcie->pcie40ver  = pcie40_readfee32(dev_slot, ch, PCIE40REGL_VER);      /* 81 */
+      pcie->rxdata     = pcie40_readfee32(dev_slot, ch, PCIE40REGL_RXDATA);   /* 84 */
+      pcie->eventsz    = pcie40_readfee32(dev_slot, ch, PCIE40REGL_EVENTSZ);  /* 85 */
+      pcie->nevent     = pcie40_readfee32(dev_slot, ch, PCIE40REGL_NEVENT);   /* 86 */
+      pcie->nkbyte     = pcie40_readfee32(dev_slot, ch, PCIE40REGL_NKBYTE);   /* 87 */
+      pcie->nword      = pcie40_readfee32(dev_slot, ch, PCIE40REGL_NWORD);    /* 88 */
+      pcie->vetoset    = pcie40_readfee32(dev_slot, ch, PCIE40REGL_VETOSET);  /* 89 */
+      pcie->vetocnt    = pcie40_readfee32(dev_slot, ch, PCIE40REGL_VETOCNT);  /* 8a */
+      pcie->vetobuf[0] = pcie40_readfee32(dev_slot, ch, PCIE40REGL_VETOBUF0); /* 8b */
+      pcie->vetobuf[1] = pcie40_readfee32(dev_slot, ch, PCIE40REGL_VETOBUF1); /* 8c */
+      
+      pcie->feeser = 0xffff;
+      pcie->feever = 0xffff;
+      if ( pcie40_b2l_status(dev_slot, i) ) {
+	getfee(pcie);
+      }
+            
+  // }
+  return notfound;
+}
+
+/* ---------------------------------------------------------------------- *\
+ *    statlink
+\* ---------------------------------------------------------------------- */
+int
+statlink(std::bitset<48> link_mask, pcie40reg_t pcie40reg[])
+{
+  int i;
+  int first = 1;
+  int quiet = 1;
+
+  for (i=0; i<48; i++) {
+    pcie40reg_t *pcie = &pcie40reg[i];
+    double total;
+    char prompt[128];
+    
+    if (!link_mask[i]) continue;
+
+    quiet = 0;
+    if (! first) printf("\n");
+    first =0;
+    
+    sprintf(prompt, "(%02d)    ", i);
+    
+    if ( !pcie40_b2l_status(dev_slot, i) ) {
+      printf("b2link is down\n");
+    } else if (pcie->feeser & 0x8000) {
+      printf("fee info is not available\n");
+    } else {
+      printf("%s serial %d version %d\n",
+	     feename(pcie->feehw, pcie->feefw), pcie->feeser, pcie->feever);
+    }
+    
+    printf("%s", prompt);
+    printf("b2l=%s (rx=%s tx=%s rxsta=%s txsta=%s mask=%s)\n",
+	   pcie40_b2l_status(dev_slot, i)?"UP":"DOWN",
+	   pcie40_b2l_rxstatus(dev_slot, i)?"UP":"DOWN",
+	   pcie40_b2l_txstatus(dev_slot, i)?"UP":"DOWN",
+	   pcie40_b2l_rxready(dev_slot, i)?"READY":"NOT READY",
+	   pcie40_b2l_txready(dev_slot, i)?"READY":"NOT READY",
+	   pcie40_b2l_mask(dev_slot, i)?"UNMASK":"MASK");
+
+    printf("%s", prompt);
+           
+    printf("%s", prompt);
+    printf("rxdata=%04x rxlinkdown=%d rxcrcerr=%d feecrcerr=%d\n",
+           D(pcie->rxdata,15,0), D(pcie->rxdata,31,24), D(pcie->rxdata,23,16),
+           pcie->feecrce);
+    printf("%s", prompt);
+    total = (pcie->nkbyte * 256.0 + (pcie->nword & 0xff)) * 4.0;
+    printf("event=%d total=%1.0fkB", pcie->nevent, total / 1000);
+    if (pcie->nevent) {
+      double avg = total / pcie->nevent;
+      printf(" (avg=%1.0fB", avg);
+      if (D(pcie->eventsz,31,16) == 0xffff) {
+        printf(" last=oflow");
+      } else {
+        printf(" last=%dB", D(pcie->eventsz,31,16)*4);
+      }
+      if (D(pcie->eventsz,15,0) == 0xffff) {
+        printf(" max=oflow)");
+      } else {
+        printf(" max=%dB)", D(pcie->eventsz,15,0)*4);
+      }
+    }
+    printf("\n");
+
+    printf("%s", prompt);
+    if ((pcie->vetoset & 3) == 0) {
+      printf("no b2link error correction");
+    } else if (pcie->vetocnt == 0) {
+      printf("no b2link error");
+    } else {
+      printf("b2link error %d(%c) %d(%c) %c%02x %c%02x %c%02x %c%02x %c%02x %c%02x",
+             D(pcie->vetocnt,31,16),
+             B(pcie->vetoset,1) ? 'i' : '-',
+             D(pcie->vetocnt,15,0),
+             B(pcie->vetoset,0) ? 'd' : '-',
+             B(pcie->vetobuf[0],25)?'K':'D', D(pcie->vetobuf[0],15,8),
+             B(pcie->vetobuf[0],24)?'K':'D', D(pcie->vetobuf[0],7,0),
+             B(pcie->vetobuf[0],21)?'K':'D', D(pcie->vetobuf[1],31,24),
+             B(pcie->vetobuf[0],20)?'K':'D', D(pcie->vetobuf[1],23,16),
+             B(pcie->vetobuf[0],17)?'K':'D', D(pcie->vetobuf[1],15,8),
+             B(pcie->vetobuf[0],16)?'K':'D', D(pcie->vetobuf[1],7,0));
+    }
+    printf("\n");
+  }
+
+  if (quiet) {
+    printf("no PCIE40 was found.\n");
+  }
+}
+
+
+int main(int argc, char** argv){
+  
+  // parse arguments
+  argument(argc, argv);
+
+  pcie40reg_t pcie40;
+  pcie40reg_t pcie40reg[48];
+
+  // open pcie40 device driver for current process
+  ecs_open( dev_slot , SLC_BAR );
+
+  printf("statlink version %d (%d) / ", VERSION, MOD_DATE);
+  statpice40(pcie40);	
+  readregs(link_mask, pcie40reg);
+  statlink(link_mask, pcie40reg);
+
+  // close pcie40 device driver for current process
+  ecs_close( dev_slot , SLC_BAR) ;
+
+  return 0 ;
+}
+
+
diff --git a/Pcie40Applications/timediff.cpp b/Pcie40Applications/timediff.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4b8b61dc40aa912f4dd31457e1a5b29beeabb7a1
--- /dev/null
+++ b/Pcie40Applications/timediff.cpp
@@ -0,0 +1,100 @@
+#include <iostream>
+#include <ctime>
+#include <string>
+#include <stdlib.h>
+#include <unistd.h>
+#include <memory.h>
+#include <stdexcept>
+#include <string.h>
+#include <cstdio>
+
+#include "pcie40_b2slc.h"
+extern "C" int  ecs_open(int dev, int bar);
+extern "C" void ecs_close(int dev, int bar);
+/*
+std::string exec(const char* cmd) {
+    char buffer[128];
+    std::string result = "";
+    FILE* pipe = popen(cmd, "r");
+    if (!pipe) throw std::runtime_error("popen() failed!");
+    try {
+        while (fgets(buffer, sizeof buffer, pipe) != NULL) {
+            result += buffer;
+        }
+    } catch (...) {
+        pclose(pipe);
+        throw;
+    }
+    pclose(pipe);
+    return result;
+}
+*/
+int main(int argc, char **argv) {
+
+  int ch = -1;
+  int addr = 0;		
+  int data = 0;
+  int loops = 0;  
+  bool WRITE_FLAG = false;
+  bool READ_FLAG = false;
+  bool HSLB_FLAG = false;
+
+  for(int i=1; i<argc; i++){
+    std::string ss = argv[i];
+    if(ss=="--ch"){
+      ch = atoi(argv[++i]);
+    }
+    if(ss=="-w" || ss=="--write"){
+      WRITE_FLAG = true; 
+      addr = strtoul(argv[++i], 0, 16);
+      data = strtoul(argv[++i], 0, 16);
+    }
+    if(ss=="-r" || ss=="--read"){
+      READ_FLAG = true;
+      addr = strtoul(argv[++i], 0, 16);
+    }
+    if(ss=="-l" || ss=="--loop"){
+      loops = atoi(argv[++i]);
+    }
+    if(ss=="--hslb"){
+      HSLB_FLAG = true;
+    }
+  }
+
+  struct timespec ts;
+  struct timespec ts1;
+  // Success: Returns 0
+  //   // Failure: Returns -1
+  //     // First arg: CLOCK_REALTIME, CLOCL_MONOTONIC, etc.
+  int ret = clock_gettime(CLOCK_REALTIME, &ts);
+  int result;
+  int valp;
+  ecs_open( 0 , 2 );
+  for(int i=0; i<loops; i++){
+    if(HSLB_FLAG){
+      //int result = system("./reghsx -c fee32 0x12");
+      //int result = readfee32(0, ch, addr, &valp);
+      //std::cout << valp << std::endl;
+    }else{
+      if(WRITE_FLAG){
+        result = pcie40_writefee32( 0 , ch , addr, data) ;
+      }else if (READ_FLAG){
+        result = pcie40_readfee32( 0 , ch , addr) ;
+      }
+    }
+    //usleep(1000);
+  }
+  ecs_close( 0 , 2 ) ;
+
+  //usleep(1e6);
+
+  int ret1 = clock_gettime(CLOCK_REALTIME, &ts1);
+
+  if(ret == 0 && ret1 == 0){
+    std::cout << "Processing time in Seconds       : " << ts1.tv_sec - ts.tv_sec  << std::endl
+              << "Processing time in Nano seconds  : " << ts1.tv_nsec - ts.tv_nsec << std::endl;
+  }else{
+    std::cout << "Failed clock_gettime()" << std::endl;
+  }
+  return 0;
+}
diff --git a/Pcie40Libraries/Makefile b/Pcie40Libraries/Makefile
index 8969d645969d3af8b3adff0ce4c61ab5a52264fa..b5c09f013f7f4d15ac7dd560582750b52ba222d9 100644
--- a/Pcie40Libraries/Makefile
+++ b/Pcie40Libraries/Makefile
@@ -29,7 +29,7 @@ LTC2990_SRC=
 LTC2990_OBJ=$(LTC2990_SRC:$(SRC_DIR)$(LTC2990_DIR)%.c=$(OBJ_DIR)%.o)
 
 # Belle II specific libraries (slow control, ECS, ...) 
-B2LIB_SRC= pcie40_b2slc.cpp pcie40_b2ecs.c pcie40_b2dma.c
+B2LIB_SRC= pcie40_b2slc.cpp pcie40_reg.cpp pcie40_b2ecs.c pcie40_b2dma.c
 B2LIB_OBJ=$(B2LIB_SRC:%.c=$(OBJ_DIR)%.o)
 
 # static libraries
diff --git a/Pcie40Libraries/pcie40_reg.cpp b/Pcie40Libraries/pcie40_reg.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..160b06be34ca7b21728c0e4b737550b5d3656c97
--- /dev/null
+++ b/Pcie40Libraries/pcie40_reg.cpp
@@ -0,0 +1,115 @@
+#include "pcie40_reg.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <vector>
+#include <string.h>
+
+// ===== 
+// CALL C functions
+// =====
+
+#ifndef D
+#define D(a,b,c) (((a)>>(c))&((1<<((b)+1-(c)))-1))
+#define B(a,b)   D(a,b,b)
+#define Bs(a,b,s)   (B(a,b)?(s):"")
+#define Ds(a,b,c,s)   (D(a,b,c)?(s):"")
+#endif
+
+extern "C" int      ecs_write(int dev, int bar, unsigned add, int val); 
+extern "C" unsigned ecs_read(int dev, int bar, unsigned add) ; 
+
+int pcie40_status(int dev){
+  int ret = -1;
+  ret = ecs_read(dev, SLC_BAR,  SLC_PCIE40_STATUS);
+  return ret;
+}
+
+int pcie40_run_number(int dev){
+  int ret = -1;
+  ret = ecs_read(dev, SLC_BAR,  SLC_RUM_NUMBER);
+  return (ret & 0xFF00) >> 8 | (ret & 0x00FF) << 8;
+}
+
+int pcie40_trgtag_number(int dev){
+  int ret = -1;
+  ret = ecs_read(dev, SLC_BAR,  SLC_TRGTAG_NUMBER);
+  return ret;
+}
+
+
+//----------------------------------------------
+// Belle2link dedicated
+//----------------------------------------------
+int pcie40_b2l_status(int dev, int ch){
+  int ret = -1;
+  if(ch >= 0 && ch <=23)
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_STATUS1);
+  else if (ch >= 24 && ch <= 47 )
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_STATUS2);
+  
+  return ( ( ret & ( 1 << ( SLC_BASE_BIT + ch ) ) ) 
+           >> ( SLC_BASE_BIT + ch ));
+}
+
+int pcie40_b2l_mask(int dev, int ch){
+  int ret = -1;
+  if(ch >= 0 && ch <=23)
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_MASK1);
+  else if (ch >= 24 && ch <= 47 )
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_MASK2);
+  
+  return ( ( ret & ( 1 << ( SLC_BASE_BIT + ch ) ) ) 
+           >> ( SLC_BASE_BIT + ch ));
+}
+
+int pcie40_b2l_txstatus(int dev, int ch){
+  int ret = -1;
+  if(ch >= 0 && ch <=23)
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_TX_STATUS1);
+  else if (ch >= 24 && ch <= 47 )
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_TX_STATUS2);
+  
+  return ( ( ret & ( 1 << ( SLC_BASE_BIT + ch ) ) ) 
+           >> ( SLC_BASE_BIT + ch ));
+}
+
+int pcie40_b2l_rxstatus(int dev, int ch){
+  int ret = -1;
+  if(ch >= 0 && ch <=23)
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_RX_STATUS1);
+  else if (ch >= 24 && ch <= 47 )
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_RX_STATUS2);
+  
+  return ( ( ret & ( 1 << ( SLC_BASE_BIT + ch ) ) ) 
+           >> ( SLC_BASE_BIT + ch ));
+}
+
+int pcie40_b2l_txready(int dev, int ch){
+  int ret = -1;
+  if(ch >= 0 && ch <=23)
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_TX_READY1);
+  else if (ch >= 24 && ch <= 47 )
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_TX_READY2);
+  
+  return ( ( ret & ( 1 << ( SLC_BASE_BIT + ch ) ) ) 
+           >> ( SLC_BASE_BIT + ch ));
+}
+
+int pcie40_b2l_rxready(int dev, int ch){
+  int ret = -1;
+  if(ch >= 0 && ch <=23)
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_RX_READY1);
+  else if (ch >= 24 && ch <= 47 )
+    ret = ecs_read(dev, SLC_BAR,  SLC_B2LINK_RX_READY2);
+  
+  return ( ( ret & ( 1 << ( SLC_BASE_BIT + ch ) ) ) 
+           >> ( SLC_BASE_BIT + ch ));
+}
+
+
+
+
+
+
+
+
diff --git a/Pcie40Libraries/pcie40_reg.h b/Pcie40Libraries/pcie40_reg.h
new file mode 100644
index 0000000000000000000000000000000000000000..83228501ea403e3a1faea53574a015cdc556c405
--- /dev/null
+++ b/Pcie40Libraries/pcie40_reg.h
@@ -0,0 +1,280 @@
+/*
+  hsreg.h
+
+  PCIE40 registers
+
+
+*/
+
+#ifndef __PICE40REG_H__
+#define __PICE40REG_H__
+
+#include <stdint.h>
+#include <stdio.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+#if defined(__dummy_close_bracket_to_cheat_emacs_auto_indent)
+}
+#endif
+
+#define SLC_BAR 2
+
+#define SLC_BASE_BIT 0
+#define SLC_B2LINK_RX_READY1   0x000500E0  // link in the ready state for rxdata, channel 0-23, 1 bit pre channel
+#define SLC_B2LINK_RX_READY2   0x00050100  // link in the ready state for rxdata, channel 0-23, 1 bit pre channel
+#define SLC_B2LINK_TX_READY1   0x00050120  // link in the ready state for txdata, channel 0-23, 1 bit pre channel
+#define SLC_B2LINK_TX_READY2   0x00050140  // link in the ready state for txdata, channel 0-23, 1 bit pre channel
+#define SLC_B2LINK_RX_STATUS1  0x00050160  // link in the ready state for txdata, channel 0-23, 1 bit pre channel
+#define SLC_B2LINK_RX_STATUS2  0x00050180  // link in the ready state for txdata, channel 0-23, 1 bit pre channel
+#define SLC_B2LINK_TX_STATUS1  0x000501A0  // link in the ready state for txdata, channel 0-23, 1 bit pre channel
+#define SLC_B2LINK_TX_STATUS2  0x000501C0  // link in the ready state for txdata, channel 0-23, 1 bit pre channel
+#define SLC_B2LINK_STATUS1     0x000501E0  // link up/down channel 0-23, 1 bit pre channel
+#define SLC_B2LINK_STATUS2     0x00050200  // link up/down channel 24-47, 1 bit pre channel
+#define SLC_B2LINK_MASK1       0x00050520  // link up/down channel 0-23, 1 bit pre channel
+#define SLC_B2LINK_MASK2       0x00050540  // link up/down channel 24-47, 1 bit pre channel
+#define SLC_RFIFO_STATUS       0x00060010
+
+
+#define SLC_PCIE40_STATUS      0x00050000 
+#define SLC_RUM_NUMBER         0x00050020
+#define SLC_TRGTAG_NUMBER      0x00050040
+
+int pcie40_b2l_status(int dev, int ch);
+int pcie40_b2l_txstatus(int dev, int ch);
+int pcie40_b2l_rxstatus(int dev, int ch);
+int pcie40_b2l_txready(int dev, int ch);
+int pcie40_b2l_rxready(int dev, int ch);
+int pcie40_b2l_mask(int dev, int ch);
+int pcie40_status(int dev);
+int pcie40_run_number(int dev);
+int pcie40_trgtag_number(int dev);
+
+
+
+
+/* FEE registers as implemented in belle2link_cdc */
+
+#define PCIE40REG_SERIAL    0x00
+#define PCIE40REG_PDSTL     0x01 /* 0x01 .. 0x60 for 48 ch (x2) */
+#define PCIE40REG_PDSTLMIN  0x01
+#define PCIE40REG_PDSTLMAX  0x60
+#define PCIE40REG_ADCTH     0x61 /* same as lower 8 bit of ADC threshold setting */
+#define PCIE40REG_ADCL      0x61
+#define PCIE40REG_ADCH      0x62
+#define PCIE40REG_WINDOW    0x63
+#define PCIE40REG_DELAY     0x64
+#define PCIE40REG_TDCTH     0x65 /* same as lower 8 bit of DAC setting for TDC */
+#define PCIE40REG_DACL      0x65
+#define PCIE40REG_DACH      0x66
+#define PCIE40REG_CDCCONT   0x67 /* part of b2ldo (FEE_CONTROL) moved from 0x69 */
+
+/* FEE registers for Belle2link internal use */
+
+#define PCIE40REG_CRCERR    0x68
+#define PCIE40REG_FEECONT   0x69
+#define PCIE40REG_D32A      0x6a
+#define PCIE40REG_D32B      0x6b
+#define PCIE40REG_D32C      0x6c
+#define PCIE40REG_D32D      0x6d
+
+/* HSLB registers in addition to predefined FINESSE registers */
+
+#define PCIE40REG_D32       0x6e
+#define PCIE40REG_A32       0x6f
+#define PCIE40REG_STAT      0x72   /* b2ldo (STATUS) */
+
+#define PCIE40REG_CCLK      0x74   /* cpld */
+#define PCIE40REG_CONF      0x75   /* cpld */
+#define PCIE40REG_CPLDVER   0x76   /* cpld */
+#define PCIE40REG_FEEHWTYPE 0x77
+#define PCIE40REG_FEESERIAL 0x78
+#define PCIE40REG_FEEFWTYPE 0x79
+#define PCIE40REG_FEEFWVER  0x7a
+
+#define B2LFEE_UNDEF   0
+#define B2LFEE_SVD     1
+#define B2LFEE_CDC     2
+#define B2LFEE_BPID    3
+#define B2LFEE_EPID    4
+#define B2LFEE_ECL     5
+#define B2LFEE_KLM     6
+#define B2LFEE_TRG     7
+#define B2LFEE_TEST    15
+
+
+/* HSLB 32-bit register extension */
+
+#define PCIE40REGL_ID      0x80
+#define PCIE40REGL_VER     0x81
+#define PCIE40REGL_RESET   0x82
+#define PCIE40REGL_STAT    0x83
+/*
+  -- input
+  stal(16#81#)    <= x"0000" & std_logic_vector(to_unsigned(VERSION, 16));
+
+  stal(16#83#)(0) <= not linkup;
+  stal(16#83#)(1) <= disable;
+  stal(16#83#)(2) <= led3;  -- FFUL
+  stal(16#83#)(3) <= led4;  -- LinkError
+  stal(16#83#)(4) <= led5;  -- NWFF
+  stal(16#83#)(5) <= sta_bad127;
+  stal(16#83#)(6) <= not plllk;
+  stal(16#83#)(7) <= not stapll2;
+  stal(16#83#)(11 downto  8) <= stateff;
+  stal(16#83#)(15 downto 12) <= staterx;
+  stal(16#83#)(19 downto 16) <= statepr;
+  stal(16#83#)(23 downto 20) <= statept;
+  stal(16#83#)(28 downto 24) <= statetx;
+  stal(16#83#)(29) <= not stapll;
+  stal(16#83#)(30) <= not fwenb;
+  stal(16#83#)(31) <= stalinkdown;
+
+  stal(16#84#) <= cntlinkdown(7 downto 0) & cntcrcerr(7 downto 0) & rxdata;
+  stal(16#85#) <= cnt_evtsz & cnt_maxsz;
+  stal(16#86#) <= cnt_event;  -- number of events into copper fifo
+  stal(16#87#) <= cnt_sec127;
+
+  stal(16#88#) <= cnt_nword(39 downto 8);
+
+  stal(16#89#)(31 downto 28) <= cnt_oflow;
+  stal(16#89#)(27 downto 24) <= cnt_badalign;
+  stal(16#89#)(23 downto 20) <= cnt_realign;
+  stal(16#89#)(19) <= badalign;
+  stal(16#89#)(18) <= rxrealign;
+  stal(16#89#)(17) <= not rxaligned;
+  stal(16#89#)(16) <= not led6;  -- sta_rxbyteisaligned
+  stal(16#89#)(15 downto  8) <= cnt_fwclk;
+  stal(16#89#)(7  downto  0) <= cnt_nword(7 downto 0);
+
+  stal(16#8c#)(31 downto 16) <= cntvetoidle;
+  stal(16#8c#)(15 downto 0)  <= cntvetodata;
+  stal(16#8d#)(25 downto 24) <= bufvetodown(53 downto 52);
+  stal(16#8d#)(21 downto 20) <= bufvetodown(51 downto 50);
+  stal(16#8d#)(17 downto 16) <= bufvetodown(49 downto 48);
+  stal(16#8d#)(15 downto 0)  <= bufvetodown(47 downto 32);
+  stal(16#8e#)(31 downto 0)  <= bufvetodown(31 downto  0);
+
+  stal(16#8f#) <= dbg;
+
+  -- output
+  setrunreset  <= regl(16#82#)(0);
+  b2lreset     <= regl(16#82#)(4);
+  txreset      <= regl(16#82#)(8);
+  gtpreset     <= regl(16#82#)(12);
+  clrpll       <= regl(16#82#)(16);
+  clrpll2      <= regl(16#82#)(20);
+  usebadidle   <= regl(16#8b#)(1);
+  usebaddata   <= regl(16#8b#)(0);
+*/
+#define PCIE40REGL_RXDATA  0x84  /* stal(16#84#) <= cntcrcerr & rxdata; */
+#define PCIE40REGL_EVENTSZ 0x85
+#define PCIE40REGL_NEVENT  0x86
+#define PCIE40REGL_UPTIME  0x87
+#define PCIE40REGL_NKBYTE  0x88
+#define PCIE40REGL_NWORD   0x89
+#define PCIE40REGL_VETOSET 0x8b
+#define PCIE40REGL_VETOCNT 0x8c
+#define PCIE40REGL_VETOBUF0 0x8d
+#define PCIE40REGL_VETOBUF1 0x8e
+#define PCIE40REGL_CNTFF00     0x95 /* new in hslb055 */
+#define PCIE40REGL_CNTDATAPKT  0x96 /* new in hslb055 */
+#define PCIE40REGL_CNTDATAWORD 0x97 /* new in hslb055 */
+
+static const int hsreg_revision = 1;
+
+struct pcie40reg {
+  uint32_t  stat;    /* 72 */
+  uint8_t  csr;     /* 73 */
+  uint8_t  xbusy;   /* 74 */
+  uint8_t  conf;    /* 75 */
+  uint8_t  feehw;   /* 77 >> 4 */
+  uint8_t  feefw;   /* 79 >> 4 */
+  uint8_t  feecrce; /* 68 */
+  uint16_t feeser;  /* 78 | ((77 & f) << 8) */
+  uint16_t feever;  /* 7a | ((79 & f) << 8) */
+  uint32_t pcie40id;  /* 80 */
+  uint32_t pcie40ver; /* 81 */
+  uint32_t pcie40rst; /* 82 */
+  uint32_t pcie40sta; /* 83 */
+  uint32_t rxdata;  /* 84 */
+  uint32_t eventsz; /* 85 */
+  uint32_t nevent;  /* 86 */
+  uint32_t uptime;  /* 87 */
+  uint32_t nkbyte;  /* 88 */
+  uint32_t nword;   /* 89 */
+  uint32_t vetoset; /* 8b */
+  uint32_t vetocnt; /* 8c */
+  uint32_t vetobuf[2]; /* 8d, 8e */
+  uint32_t cntff00;     /* 95 */
+  uint32_t cntdatapkt;  /* 96 */
+  uint32_t cntdataword; /* 97 */
+};
+
+typedef struct pcie40reg pcie40reg_t;
+
+
+int pcie40reg_read(int fd /* 0-3 */, pcie40reg_t*);
+int pcie40reg_getfee(int fd /* 0-3 */, pcie40reg_t*);
+
+/* ---------------------------------------------------------------------- *\
+ *    feename
+ *    
+\* ---------------------------------------------------------------------- */
+const char *
+feename(int hwtype, int fwtype)
+{
+  static const char *feetype[] = {
+    "UNDEF", "SVD", "CDC", "TOP", "ARI", "ECL", "EECL", "KLM", "EKLM",
+    "TRG", "FEE10", "FEE11", "FEE12", "FEE13", "DEMO", "TEST" };
+  static const char *demotype[] = {
+    "UNDEF", "HSLB-B2L", "SP605-B2L", "ML605-B2L", "AC701-B2L" };
+  static const char *trgtype[] = {
+    "TRGMERGER", /* = 0 */
+    "TRGTSF",    /* = 1 */
+    "TRG2D",     /* = 2 */
+    "TRG3D",     /* = 3 */
+    "TRGNN",     /* = 4 */
+    "TRGEVTT",   /* = 5 */
+    "TRGGRL",    /* = 6 */
+    "TRGGDL",    /* = 7 */
+    "TRGETM",    /* = 8 */
+    "TRGTOP",    /* = 9 */
+    "TRGKLM",    /* = 10 */
+  };
+
+  hwtype &= 0x0f;
+  fwtype  %= 16;
+
+  if (hwtype == 14 && fwtype > 0 && fwtype <= 4) {
+    return demotype[fwtype];
+  } else if (hwtype == 9 && fwtype >= 0 && fwtype <= 10) {
+    return trgtype[fwtype];
+  } else {
+    int i;
+    static int ringi = 0;
+    static int ringval[32];
+    static char ringbuf[32][20];
+    for (i=0; i<32; i++) {
+      if (ringval[i] == 0x100 + (hwtype<<4) + fwtype) break;
+    }
+    if (i == 32) {
+      i = ringi;
+      ringval[i] = 0x100 + (hwtype<<4) + fwtype;
+      sprintf(ringbuf[i], "%s", feetype[hwtype]);
+      ringi = (ringi + 1) % 32;
+    }
+    return ringbuf[i];
+  }
+}
+
+#if defined(__dummy_open_bracket_to_cheat_emacs_auto_indent)
+__dummy_open_bracket_to_cheat_emacs_auto_indent {
+#endif
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __PCIE40REG_H__ */
+