diff --git a/README.md b/README.md
index ea7de569576fe94857bdfa92ebdbf76ec53d4a8a..c003e0ff5d8b3e080e9acb4a2817059c331b58d8 100644
--- a/README.md
+++ b/README.md
@@ -774,7 +774,7 @@ $ git checkout SCALP-USER-v0.5.1
 **For the design with the NoC Scalp :**
 
 ```
-$ git checkout SCALP-ROUTER-v0.1
+$ git checkout SCALP_ROUTER_SLOW-v0.2
 ```
 
 **If you have not gone through the scalp\_safe\_petalinux firmware creation section, please go to section [Copy Scalp board files](#copy-scalp-board-files).**
@@ -821,7 +821,7 @@ $ git checkout SCALP-USER-v0.5.1
 **For the design with the NoC Scalp :**
 
 ```
-$ git checkout SCALP-ROUTER-v0.1
+$ git checkout SCALP_ROUTER_SLOW-v0.2
 ```
 
 ### Create a new Scalp User Petalinux project from a BSP
@@ -1628,3 +1628,167 @@ $ petalinux-package --bsp -p /home/jo/Documents/Projets/Hepia/scalp_project/scal
     };
 };
 ```
+
+### Scalp library header
+
+```cpp
+#ifndef __SCALP_HH__
+#define __SCALP_HH__
+
+#include <cstdint>
+#include <cstddef>
+#include <atomic>
+
+#define SCALP_ROUTER_UIO_DEV   "/dev/uio0"
+#define SCALP_ROUTER_MMAP_SIZE 0x1000
+#define SCALP_HDR_SIZE         3
+#define SCALP_MAX_SP_SIZE      64
+#define SCALP_TX_FIFO_SIZE     1024
+
+using namespace std;
+
+namespace libscalp
+{
+    struct scalp_noc_regs
+    {
+    public :
+        std::atomic<uint32_t> wr_data;
+        std::atomic<uint32_t> rd_data;
+        // Same register, but different access
+        std::atomic<uint32_t> ctrl;
+        std::atomic<uint32_t> set_ctrl;
+        std::atomic<uint32_t> clr_ctrl;
+        //
+        std::atomic<uint32_t> status;
+        std::atomic<uint32_t> txwr_datacnt;
+        std::atomic<uint32_t> txrd_datacnt;
+        std::atomic<uint32_t> rxwr_datacnt;
+        std::atomic<uint32_t> rxrd_datacnt;
+        std::atomic<uint32_t> loc_netaddr;
+    };
+
+    enum ctrl_reg_fields
+    {
+        E_WR_VALID       = 0x1,
+        E_WR_LAST        = 0x2,
+        E_WR_READY       = 0x4,
+        E_WR_NEXT        = 0x8,
+        E_RESET_ALL_FIFO = 0x10,
+        E_WR_H0          = 0x20,
+        E_WR_H1          = 0x40,
+        E_WR_H2          = 0x80,
+        E_WR_PLD         = 0x100,
+        E_WR_NEW_PACKET  = 0x200,
+        E_RD_NEXT        = 0x400,
+        E_RD_NEW_PACKET  = 0x800
+    };
+
+    enum status_reg_fields
+    {
+        E_RD_VALID     = 0x1,
+        E_RD_LAST      = 0x2,
+        E_TX_PROG_FULL = 0x4,
+        E_RX_PROG_FULL = 0x8,
+        E_RD_WAIT_NEXT = 0x10
+    };
+    
+    class uio
+    {
+    private :
+        int32_t _uiofd;
+
+    public :
+        explicit uio(const char * dev);
+        ~uio();
+        void unmask_interrupt();
+        void wait_interrupt(uint32_t timeout_ms);
+        friend class uio_mmap;        
+    };
+
+    class uio_mmap
+    {
+    private :
+        size_t _size;
+        void * _ptr;
+
+    public :
+        uio_mmap(const uio &u, uint32_t index, size_t size);
+        uio_mmap(uio *u, uint32_t index, size_t size);
+        ~uio_mmap();
+        size_t size() const { return _size; }
+        void *get_ptr() const { return _ptr; }        
+    };
+
+    void *   scalp_noc_init          (const char *dev, void **devuio, void **mmap_regs);
+    bool     scalp_noc_set_locaddr   (void *regs, uint32_t x, uint32_t y, uint32_t z);
+    uint32_t scalp_noc_get_locaddr   (void *regs);
+    void     scalp_noc_free          (void *devuio, void *mmap_regs);
+    bool     scalp_noc_data_is_valid (void *regs, bool new_packet);
+    uint32_t scalp_noc_read_data     (void *regs, bool *is_last, bool new_packet, bool *nodata);
+    uint32_t scalp_noc_read_packet   (void *regs, uint32_t *scalp_packet, bool blocking);
+    bool     scalp_noc_ready_for_data(void *regs, bool new_packet);
+    bool     scalp_noc_write_data    (void *regs, uint32_t data,  bool is_last, bool new_packet);
+    bool     scalp_noc_write_packet  (void *regs, uint32_t *scalp_packet, uint32_t size);
+    uint32_t scalp_noc_create_packet (void *regs, uint32_t x, uint32_t y, uint32_t z, uint32_t *payload, uint32_t payload_size, uint32_t *packet);
+};
+
+extern "C"
+{
+    void * sn_init(const char *dev, void **devuio, void **mmap_regs)
+    {
+        return libscalp::scalp_noc_init(dev, devuio, mmap_regs);
+    }
+
+    uint32_t sn_set_locaddr(void *regs, uint32_t x, uint32_t y, uint32_t z)
+    {
+        return (uint32_t)(libscalp::scalp_noc_set_locaddr(regs, x, y, z));
+    }
+
+    uint32_t sn_get_locaddr(void *regs)
+    {
+        return libscalp::scalp_noc_get_locaddr(regs);
+    }
+
+    void sn_free(void *devuio, void *mmap_regs)
+    {
+        return libscalp::scalp_noc_free(devuio, mmap_regs);
+    }
+
+    uint32_t sn_data_is_valid(void *regs, bool new_packet)
+    {
+        return (uint32_t)(libscalp::scalp_noc_data_is_valid(regs, new_packet));
+    }
+
+    uint32_t sn_read_data(void *regs, bool *is_last, bool new_packet, bool *nodata)
+    {
+        return libscalp::scalp_noc_read_data(regs, is_last, new_packet, nodata);
+    }
+
+    uint32_t sn_read_packet(void *regs, uint32_t *scalp_packet, bool blocking)
+    {
+        return libscalp::scalp_noc_read_packet(regs, scalp_packet, blocking);
+    }
+
+    uint32_t sn_ready_for_data(void *regs, bool new_packet)
+    {
+        return (uint32_t)(libscalp::scalp_noc_ready_for_data(regs, new_packet));
+    }
+
+    uint32_t sn_write_data(void *regs, uint32_t data,  bool is_last, bool new_packet)
+    {
+        return (uint32_t)(libscalp::scalp_noc_write_data(regs, data, is_last, new_packet));
+    }
+
+    uint32_t sn_write_packet(void *regs, uint32_t *scalp_packet, uint32_t size)
+    {
+        return (uint32_t)(libscalp::scalp_noc_write_packet(regs, scalp_packet, size));
+    }
+
+    uint32_t sn_create_packet(void *regs, uint32_t x, uint32_t y, uint32_t z, uint32_t *payload, uint32_t payload_size, uint32_t *packet)
+    {
+        return (uint32_t)(libscalp::scalp_noc_create_packet(regs, x, y , z, payload, payload_size, packet));
+    }
+}
+
+#endif
+```