diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..ad5aa25c4c6130a4233814c024830d556532a1d6
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+The LAGO ECOSYSTEM
+Copyright (C) 2018-Today, The LAGO Project, [lagoproject.org](http://lagoproject.org)
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..005f254443719ae452bc86d5c8f5aca3c5b32d5c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,202 @@
+# 'make' builds everything
+# 'make clean' deletes everything except source files and Makefile
+#
+# You need to set NAME, PART and PROC for your project.
+# NAME is the base name for most of the generated files.
+
+# solves problem with awk while building linux kernel
+# solution taken from http://www.googoolia.com/wp/2015/04/21/awk-symbol-lookup-error-awk-undefined-symbol-mpfr_z_sub/
+LD_LIBRARY_PATH =
+
+NAME = led_blinker
+PART = xc7z010clg400-1
+PROC = ps7_cortexa9_0
+
+CORES = axi_axis_reader_v1_0 \
+				axi_axis_writer_v1_0 \
+				axi_bram_reader_v1_0 \
+				axi_cfg_register_v1_0 \
+				axi_sts_register_v1_0 \
+				axi_time_trig_gen_v1_0 \
+				axis_avgr16bits_v1_0 \
+				axis_avgr32bits_v1_0 \
+				axis_avgr_v1_0 \
+				axis_bram_reader_v1_0 \
+				axis_bram_writer_v1_0 \
+				axis_constant_v1_0 \
+				axis_counter_v1_0 \
+				axis_dc_removal_v1_0 \
+				axis_decimator_v1_0 \
+				axis_fifo_v1_0 \
+				axis_generator_v1_0 \
+				axis_gpio_reader_i_v1_0 \
+				axis_gpio_reader_v1_0 \
+				axis_histogram_v1_0 \
+				axis_histogram_v1_1 \
+				axis_interpolator_v1_0 \
+				axis_lago_trigger_v1_0 \
+				axis_lago_trigger_v1_1 \
+				axis_lago_trigger_v1_2 \
+				axis_lago_trigger_v1_3 \
+				axis_lfsr_v1_0 \
+				axis_lpf_v1_0 \
+				axis_packetizer_v1_0 \
+				axis_ram_writer_v1_0 \
+				axis_rp_adc_v1_0 \
+				axis_rp_adc_v3_0 \
+				axis_rp_dac_v1_0 \
+				axis_rp_dac_v2_0 \
+				axis_tlast_gen_v1_0 \
+				axis_trigger_v1_0 \
+				axis_validator_v1_0 \
+				axis_variable_v1_0 \
+				axis_zero_crossing_det_v1_0 \
+				axis_zeroer_v1_0 \
+				bram_counter_v1_0 \
+				bram_selector_v1_0 \
+				dc_removal_v1_0 \
+				dna_reader_v1_0 \
+				int_counter_v1_0 \
+				port_selector_v1_0 \
+				port_slicer_v1_0 \
+				pps_gen_v1_0 \
+				pps_gen_v1_1 \
+				pwm_gen_v1_0 \
+				ramp_gen_v1_0 \
+				selector_v1_0 \
+				time_trig_gen_v1_0 
+
+VIVADO = vivado -nolog -nojournal -mode batch
+XSCT = xsct
+RM = rm -rf
+
+UBOOT_TAG = 2021.04
+LINUX_TAG = 5.10
+DTREE_TAG = xilinx-v2020.2
+
+UBOOT_DIR = tmp/u-boot-$(UBOOT_TAG)
+LINUX_DIR = tmp/linux-$(LINUX_TAG)
+DTREE_DIR = tmp/device-tree-xlnx-$(DTREE_TAG)
+
+UBOOT_TAR = tmp/u-boot-$(UBOOT_TAG).tar.bz2
+LINUX_TAR = tmp/linux-$(LINUX_TAG).tar.xz
+DTREE_TAR = tmp/device-tree-xlnx-$(DTREE_TAG).tar.gz
+
+UBOOT_URL = https://ftp.denx.de/pub/u-boot/u-boot-$(UBOOT_TAG).tar.bz2
+LINUX_URL = https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-$(LINUX_TAG).107.tar.xz
+DTREE_URL = https://github.com/Xilinx/device-tree-xlnx/archive/$(DTREE_TAG).tar.gz
+
+RTL8188_TAR = tmp/rtl8188eu-v5.2.2.4.tar.gz
+RTL8188_URL = https://github.com/lwfinger/rtl8188eu/archive/v5.2.2.4.tar.gz
+
+RTL8192_TAR = tmp/rtl8192cu-fixes-master.tar.gz
+RTL8192_URL = https://github.com/pvaret/rtl8192cu-fixes/archive/master.tar.gz
+
+.PRECIOUS: tmp/cores/% tmp/%.xpr tmp/%.xsa tmp/%.bit tmp/%.fsbl/executable.elf tmp/%.tree/system-top.dts
+
+all: tmp/$(NAME).bit boot.bin uImage devicetree.dtb
+
+cores: $(addprefix tmp/cores/, $(CORES))
+
+xpr: tmp/$(NAME).xpr
+
+bit: tmp/$(NAME).bit
+
+$(UBOOT_TAR):
+	mkdir -p $(@D)
+	curl -L $(UBOOT_URL) -o $@
+
+$(LINUX_TAR):
+	mkdir -p $(@D)
+	curl -L $(LINUX_URL) -o $@
+
+$(DTREE_TAR):
+	mkdir -p $(@D)
+	curl -L $(DTREE_URL) -o $@
+
+$(RTL8188_TAR):
+	mkdir -p $(@D)
+	curl -L $(RTL8188_URL) -o $@
+
+$(RTL8192_TAR):
+	mkdir -p $(@D)
+	curl -L $(RTL8192_URL) -o $@
+
+$(UBOOT_DIR): $(UBOOT_TAR)
+	mkdir -p $@
+	tar -jxf $< --strip-components=1 --directory=$@
+	patch -d tmp -p 0 < patches/u-boot-$(UBOOT_TAG).patch
+	cp patches/zynq_red_pitaya_defconfig $@/configs
+	cp patches/zynq-red-pitaya.dts $@/arch/arm/dts
+
+$(LINUX_DIR): $(LINUX_TAR) $(RTL8188_TAR) $(RTL8192_TAR)
+	mkdir -p $@
+	tar -Jxf $< --strip-components=1 --directory=$@
+	mkdir -p $@/drivers/net/wireless/realtek/rtl8188eu
+	mkdir -p $@/drivers/net/wireless/realtek/rtl8192cu
+	tar -zxf $(RTL8188_TAR) --strip-components=1 --directory=$@/drivers/net/wireless/realtek/rtl8188eu
+	tar -zxf $(RTL8192_TAR) --strip-components=1 --directory=$@/drivers/net/wireless/realtek/rtl8192cu
+	patch -d tmp -p 0 < patches/linux-$(LINUX_TAG).patch
+	cp patches/zynq_ocm.c $@/arch/arm/mach-zynq
+	cp patches/cma.c $@/drivers/char
+	cp patches/xilinx_devcfg.c $@/drivers/char
+	cp patches/xilinx_zynq_defconfig $@/arch/arm/configs
+
+$(DTREE_DIR): $(DTREE_TAR)
+	mkdir -p $@
+	tar -zxf $< --strip-components=1 --directory=$@
+
+uImage: $(LINUX_DIR)
+	make -C $< mrproper
+	make -C $< ARCH=arm xilinx_zynq_defconfig
+	make -C $< ARCH=arm -j $(shell nproc 2> /dev/null || echo 1) \
+	  CROSS_COMPILE=arm-linux-gnueabihf- UIMAGE_LOADADDR=0x8000 \
+	  uImage modules
+	cp $</arch/arm/boot/uImage $@
+
+$(UBOOT_DIR)/u-boot.bin: $(UBOOT_DIR)
+	mkdir -p $(@D)
+	make -C $< mrproper
+	make -C $< ARCH=arm zynq_red_pitaya_defconfig
+	make -C $< ARCH=arm -j $(shell nproc 2> /dev/null || echo 1) \
+	  CROSS_COMPILE=arm-linux-gnueabihf- all
+
+boot.bin: tmp/$(NAME).fsbl/executable.elf $(UBOOT_DIR)/u-boot.bin
+	echo "img:{[bootloader] tmp/$(NAME).fsbl/executable.elf [load=0x4000000,startup=0x4000000] $(UBOOT_DIR)/u-boot.bin}" > tmp/boot.bif
+	bootgen -image tmp/boot.bif -w -o i $@
+
+devicetree.dtb: uImage tmp/$(NAME).tree/system-top.dts
+	$(LINUX_DIR)/scripts/dtc/dtc -I dts -O dtb -o devicetree.dtb \
+	  -i tmp/$(NAME).tree tmp/$(NAME).tree/system-top.dts
+
+tmp/cores/%: cores/%/core_config.tcl cores/%/*.vhd
+	mkdir -p $(@D)
+	$(VIVADO) -source scripts/core.tcl -tclargs $* $(PART)
+
+tmp/%.xpr: projects/% $(addprefix tmp/cores/, $(CORES))
+	mkdir -p $(@D)
+	$(VIVADO) -source scripts/project.tcl -tclargs $* $(PART)
+
+tmp/%.xsa: tmp/%.xpr
+	mkdir -p $(@D)
+	$(VIVADO) -source scripts/hwdef.tcl -tclargs $*
+
+tmp/%.bit: tmp/%.xpr
+	mkdir -p $(@D)
+	$(VIVADO) -source scripts/bitstream.tcl -tclargs $*
+
+tmp/%.fsbl/executable.elf: tmp/%.xsa
+	mkdir -p $(@D)
+	$(XSCT) scripts/fsbl.tcl $* $(PROC)
+
+tmp/%.tree/system-top.dts: tmp/%.xsa $(DTREE_DIR)
+	mkdir -p $(@D)
+	$(XSCT) scripts/devicetree.tcl $* $(PROC) $(DTREE_DIR)
+	sed -i 's|#include|/include/|' $@
+	patch -d $(@D) < patches/devicetree.patch
+
+clean:
+	$(RM) uImage boot.bin devicetree.dtb tmp
+	$(RM) .Xil usage_statistics_webtalk.html usage_statistics_webtalk.xml
+	$(RM) vivado*.jou vivado*.log
+	$(RM) webtalk*.jou webtalk*.log
diff --git a/TODO.md b/TODO.md
new file mode 100644
index 0000000000000000000000000000000000000000..c0f38923ed15c9400f1dc6bc50eccf353717ac69
--- /dev/null
+++ b/TODO.md
@@ -0,0 +1,51 @@
+FPGA:
+- replace undocumented system bus with AXI4 Lite
+- move CPU accessible registers out from processing modules
+- separate the code into smaller modules connected over AXI4-Stream
+- rethink generator and osciloscope SW interface sequences
+- sestructure registers into a hierarchy
+- generalize trigger modes
+- write configurable PLL
+- write streaming benches
+- Scope:
+  - use DMA from Xilinx
+  - continuous mode
+  - trigger mode
+- add configurable PLL
+
+Linux:
+- upgrade to 3.19, there are Ethernet and USB driver issues
+- write IIO drivers
+- rethink user management and security
+
+Bazaar:
+- review the Nginx current patch, try to remove it and instead update the config file
+- update Nginx to newer version
+- update Buildroot to newer version
+- use API to get Zynq DNA (there are 2 instances)
+
+API:
+- move type definitins (structures, constants) to header files
+- remove middle API layer
+- avoid using read modify write access to registers
+
+Applications:
+- remove library sources from GIT, use sources from Buildroot instead
+- replace kiss FFT with NE10 library
+- replace libjpeg with turbo-jpeg from Buildroot
+
+SCPI:
+- migrate to latest upstream
+- push our patches upstream
+
+
+TODO
+
+* Fix bugs.
+* Decrease the amount of duplicated code and move common components
+  to shared.
+* Bring OS & ecosystem sources together as they compose one package.
+* Comment the code extensively in Doxygen style. Provide Doxygen
+  documentation.
+* Simplify Test/monitor.
+
diff --git a/apps/rp_bmp180/Makefile b/apps/rp_bmp180/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..c7bf5a39a8cb5960855936bb10794b1d28ca02aa
--- /dev/null
+++ b/apps/rp_bmp180/Makefile
@@ -0,0 +1,9 @@
+
+SENSOR=bmp180
+
+all:
+	gcc -Wall -c $(SENSOR).c -o $(SENSOR).o -lm
+	gcc -Wall $(SENSOR).o test.c -o test -lm
+
+clean:
+	rm *.o > /dev/null 2>&1 &
diff --git a/apps/rp_bmp180/bmp180.c b/apps/rp_bmp180/bmp180.c
new file mode 100644
index 0000000000000000000000000000000000000000..8b08e4006ba97725fc980e21da87e3110e7bab90
--- /dev/null
+++ b/apps/rp_bmp180/bmp180.c
@@ -0,0 +1,558 @@
+/**
+ * $Id: $
+ *
+ * @brief A C driver for BMP180 sesor
+ *
+ * @Author L. Horacio Arnaldi <lharnaldi@gmail.com>
+ * @date  01.04.2016
+ *
+ * (c) LabDPR  http://labdpr.cab.cnea.gov.ar
+ *
+ * This part of code is written in C programming language.
+ * Please visit http://en.wikipedia.org/wiki/C_(programming_language)
+ * for more details on the language used herein.
+ */
+ 
+#ifndef __BMP180__
+#define __BMP180__
+#include <stdint.h>
+#include "bmp180.h"
+#include <string.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <linux/i2c-dev.h>
+#include <time.h>
+#include <math.h>
+#endif
+
+
+/* 
+ * AC register
+ */
+#define BMP180_REG_AC1_H 0xAA
+#define BMP180_REG_AC2_H 0xAC
+#define BMP180_REG_AC3_H 0xAE
+#define BMP180_REG_AC4_H 0xB0
+#define BMP180_REG_AC5_H 0xB2
+#define BMP180_REG_AC6_H 0xB4
+
+/* 
+ * B1 register
+ */
+#define BMP180_REG_B1_H 0xB6
+
+/* 
+ * B2 register
+ */
+#define BMP180_REG_B2_H 0xB8
+
+/* 
+ * MB register
+ */
+#define BMP180_REG_MB_H 0xBA
+
+/* 
+ * MC register
+ */
+#define BMP180_REG_MC_H 0xBC
+
+/* 
+ * MD register
+ */
+#define BMP180_REG_MD_H 0xBE
+
+/* 
+ * AC register
+ */
+#define BMP180_CTRL 0xF4
+
+/* 
+ * Temperature register
+ */
+#define BMP180_REG_TMP 0xF6
+
+/* 
+ * Pressure register
+ */
+#define BMP180_REG_PRE 0xF6
+
+/*
+ * Temperature read command
+ */
+#define BMP180_TMP_READ_CMD 0x2E
+
+/*
+ *  Waiting time in us for reading temperature values
+ */
+#define BMP180_TMP_READ_WAIT_US 5000
+
+/*
+ * Pressure oversampling modes
+ */
+#define BMP180_PRE_OSS0 0 // ultra low power
+#define BMP180_PRE_OSS1 1 // standard
+#define BMP180_PRE_OSS2 2 // high resolution
+#define BMP180_PRE_OSS3 3 // ultra high resoultion
+
+/*
+ * Pressure read commands
+ */
+#define BMP180_PRE_OSS0_CMD 0x34
+#define BMP180_PRE_OSS1_CMD 0x74
+#define BMP180_PRE_OSS2_CMD 0xB4
+#define BMP180_PRE_OSS3_CMD 0xF4
+
+/* 
+ * Waiting times in us for reading pressure values
+ */
+#define BMP180_PRE_OSS0_WAIT_US 5000
+#define BMP180_PRE_OSS1_WAIT_US 8000
+#define BMP180_PRE_OSS2_WAIT_US 14000
+#define BMP180_PRE_OSS3_WAIT_US 26000
+
+/*
+ * Average sea-level pressure in hPa
+ */
+#define BMP180_SEA_LEVEL 1013.25
+
+
+/*
+ * Define debug function.
+ */
+
+//#define __BMP180_DEBUG__
+#ifdef __BMP180_DEBUG__
+#define DEBUG(...)	printf(__VA_ARGS__)
+#else
+#define DEBUG(...)
+#endif
+
+
+/*
+ * Shortcut to cast void pointer to a bmp180_t pointer
+ */
+#define TO_BMP(x)	(bmp180_t*) x
+
+
+
+/*
+ * Basic structure for the bmp180 sensor
+ */
+typedef struct {
+	/* file descriptor */
+	int file;
+
+	/* i2c device address */
+	int address;
+	
+	/* BMP180 oversampling mode */
+	int oss;
+	
+	/* i2c device file path */
+	char *i2c_device;
+	
+	/* Eprom values */
+	int32_t ac1;
+	int32_t ac2;
+	int32_t ac3;
+	int32_t ac4;
+	int32_t ac5;
+	int32_t ac6;
+	int32_t b1;
+	int32_t b2;
+	int32_t mb;
+	int32_t mc;
+	int32_t md;
+} bmp180_t;
+
+
+/*
+ * Lookup table for BMP180 register addresses
+ */
+int32_t bmp180_register_table[11][2] = {
+		{BMP180_REG_AC1_H, 1},
+		{BMP180_REG_AC2_H, 1},
+		{BMP180_REG_AC3_H, 1},
+		{BMP180_REG_AC4_H, 0},
+		{BMP180_REG_AC5_H, 0},
+		{BMP180_REG_AC6_H, 0},
+		{BMP180_REG_B1_H, 1},
+		{BMP180_REG_B2_H, 1},
+		{BMP180_REG_MB_H, 1},
+		{BMP180_REG_MC_H, 1},
+		{BMP180_REG_MD_H, 1}
+};
+
+
+/*
+ * Prototypes for helper functions
+ */
+int bmp180_set_addr(void *_bmp);
+void bmp180_read_eprom_reg(void *_bmp, int32_t *_data, uint8_t reg, int32_t sign);
+void bmp180_read_eprom(void *_bmp);
+int32_t bmp180_read_raw_pressure(void *_bmp, uint8_t oss);
+int32_t bmp180_read_raw_temperature(void *_bmp);
+void bmp180_init_error_cleanup(void *_bmp);
+
+
+/*
+ * Implemetation of the helper functions
+ */
+
+
+/*
+ * Sets the address for the i2c device file.
+ * 
+ * @param bmp180 sensor
+ */
+int bmp180_set_addr(void *_bmp) {
+	bmp180_t* bmp = TO_BMP(_bmp);
+	int error;
+
+	if((error = ioctl(bmp->file, I2C_SLAVE, bmp->address)) < 0) {
+		DEBUG("error: ioctl() failed\n");
+	}
+
+	return error;
+}
+
+
+
+/*
+ * Frees allocated memory in the init function.
+ * 
+ * @param bmp180 sensor
+ */
+void bmp180_init_error_cleanup(void *_bmp) {
+	bmp180_t* bmp = TO_BMP(_bmp);
+	
+	if(bmp->i2c_device != NULL) {
+		free(bmp->i2c_device);
+		bmp->i2c_device = NULL;
+	}
+	
+	free(bmp);
+	bmp = NULL;
+}
+
+
+
+/*
+ * Reads a single calibration coefficient from the BMP180 eprom.
+ * 
+ * @param bmp180 sensor
+ */
+void bmp180_read_eprom_reg(void *_bmp, int32_t *_store, uint8_t reg, int32_t sign) {
+	bmp180_t *bmp = TO_BMP(_bmp);
+	int32_t data = i2c_smbus_read_word_data(bmp->file, reg) & 0xFFFF;
+	
+	// i2c_smbus_read_word_data assumes little endian 
+	// but ARM uses big endian. Thus the ordering of the bytes is reversed.
+	// data = 	 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15   bit position
+	//          |      lsb      |          msb        |  
+	
+	//                 msb           +     lsb
+	*_store = ((data << 8) & 0xFF00) + (data >> 8);
+	
+	if(sign && (*_store > 32767)) {
+		*_store -= 65536;
+	}
+}
+
+
+/*
+ * Reads the eprom of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ */
+void bmp180_read_eprom(void *_bmp) {
+	bmp180_t *bmp = TO_BMP(_bmp);	
+	
+	int32_t *bmp180_register_addr[11] = {
+		&bmp->ac1, &bmp->ac2, &bmp->ac3, &bmp->ac4, &bmp->ac5, &bmp->ac6,
+		&bmp->b1, &bmp->b2, &bmp->mb, &bmp->mc, &bmp->md
+	};
+	
+	uint8_t sign, reg;
+	int32_t *data;
+	int i;
+	for(i = 0; i < 11; i++) {
+		reg = (uint8_t) bmp180_register_table[i][0];
+		sign = (uint8_t) bmp180_register_table[i][1];
+		data = bmp180_register_addr[i];
+		bmp180_read_eprom_reg(_bmp, data, reg, sign);
+	}
+}
+
+
+/*
+ * Returns the raw measured temperature value of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ */
+int32_t bmp180_read_raw_temperature(void *_bmp) {
+	bmp180_t* bmp = TO_BMP(_bmp);
+	i2c_smbus_write_byte_data(bmp->file, BMP180_CTRL, BMP180_TMP_READ_CMD);
+
+	usleep(BMP180_TMP_READ_WAIT_US);
+	int32_t data = i2c_smbus_read_word_data(bmp->file, BMP180_REG_TMP) & 0xFFFF;
+	
+	data = ((data << 8) & 0xFF00) + (data >> 8);
+	
+	return data;
+}
+
+
+/*
+ * Returns the raw measured pressure value of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ */
+int32_t bmp180_read_raw_pressure(void *_bmp, uint8_t oss) {
+	bmp180_t* bmp = TO_BMP(_bmp);
+	uint16_t wait;
+	uint8_t cmd;
+	
+	switch(oss) {
+		case BMP180_PRE_OSS1:
+			wait = BMP180_PRE_OSS1_WAIT_US; cmd = BMP180_PRE_OSS1_CMD;
+			break;
+		
+		case BMP180_PRE_OSS2:
+			wait = BMP180_PRE_OSS2_WAIT_US; cmd = BMP180_PRE_OSS2_CMD;
+			break;
+		
+		case BMP180_PRE_OSS3:
+			wait = BMP180_PRE_OSS3_WAIT_US; cmd = BMP180_PRE_OSS3_CMD;
+			break;
+		
+		case BMP180_PRE_OSS0:
+		default:
+			wait = BMP180_PRE_OSS0_WAIT_US; cmd = BMP180_PRE_OSS0_CMD;
+			break;
+	}
+	
+	i2c_smbus_write_byte_data(bmp->file, BMP180_CTRL, cmd);
+
+	usleep(wait);
+	
+	int32_t msb, lsb, xlsb, data;
+	msb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE) & 0xFF;
+	lsb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE+1) & 0xFF;
+	xlsb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE+2) & 0xFF;
+	
+	data = ((msb << 16)  + (lsb << 8)  + xlsb) >> (8 - bmp->oss);
+	
+	return data;
+}
+
+/*
+ * Implementation of the interface functions
+ */
+
+/**
+ * Dumps the eprom values of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ * @param bmp180 eprom struct
+ */
+void bmp180_dump_eprom(void *_bmp, bmp180_eprom_t *eprom) {
+	bmp180_t *bmp = TO_BMP(_bmp);
+	eprom->ac1 = bmp->ac1;
+	eprom->ac2 = bmp->ac2;
+	eprom->ac3 = bmp->ac3;
+	eprom->ac4 = bmp->ac4;
+	eprom->ac5 = bmp->ac5;
+	eprom->ac6 = bmp->ac6;
+	eprom->b1 = bmp->b1;
+	eprom->b2 = bmp->b2;
+	eprom->mb = bmp->mb;
+	eprom->mc = bmp->mc;
+	eprom->md = bmp->md;
+}
+
+
+/**
+ * Creates a BMP180 sensor object.
+ *
+ * @param i2c device address
+ * @param i2c device file path
+ * @return bmp180 sensor
+ */
+void *bmp180_init(int address, const char* i2c_device_filepath) {
+	DEBUG("device: init using address %#x and i2cbus %s\n", address, i2c_device_filepath);
+	
+	// setup BMP180
+	void *_bmp = malloc(sizeof(bmp180_t));
+	if(_bmp == NULL)  {
+		DEBUG("error: malloc returns NULL pointer\n");
+		return NULL;
+	}
+
+	bmp180_t *bmp = TO_BMP(_bmp);
+	bmp->address = address;
+
+	// setup i2c device path
+	bmp->i2c_device = (char*) malloc(strlen(i2c_device_filepath) * sizeof(char));
+	if(bmp->i2c_device == NULL) {
+		DEBUG("error: malloc returns NULL pointer!\n");
+		bmp180_init_error_cleanup(bmp);
+		return NULL;
+	}
+
+	// copy string
+	strcpy(bmp->i2c_device, i2c_device_filepath);
+	
+	// open i2c device
+	int file;
+	if((file = open(bmp->i2c_device, O_RDWR)) < 0) {
+		DEBUG("error: %s open() failed\n", bmp->i2c_device);
+		bmp180_init_error_cleanup(bmp);
+		return NULL;
+	}
+	bmp->file = file;
+
+	// set i2c device address
+	if(bmp180_set_addr(_bmp) < 0) {
+		bmp180_init_error_cleanup(bmp);
+		return NULL;
+	}
+
+	// setup i2c device
+	bmp180_read_eprom(_bmp);
+	bmp->oss = 0;
+	
+	DEBUG("device: open ok\n");
+
+	return _bmp;
+}
+
+
+/**
+ * Closes a BMP180 object.
+ * 
+ * @param bmp180 sensor
+ */
+void bmp180_close(void *_bmp) {
+	if(_bmp == NULL) {
+		return;
+	}
+	
+	DEBUG("close bmp180 device\n");
+	bmp180_t *bmp = TO_BMP(_bmp);
+	
+	if(close(bmp->file) < 0) {
+		DEBUG("error: %s close() failed\n", bmp->i2c_device);
+	}
+	
+	free(bmp->i2c_device); // free string
+	bmp->i2c_device = NULL;
+	free(bmp); // free bmp structure
+	_bmp = NULL;
+} 
+
+
+/**
+ * Returns the measured temperature in celsius.
+ * 
+ * @param bmp180 sensor
+ * @return temperature
+ */
+float bmp180_temperature(void *_bmp) {
+	bmp180_t* bmp = TO_BMP(_bmp);
+	long UT, X1, X2, B5;
+	float T;
+	
+	UT = bmp180_read_raw_temperature(_bmp);
+	
+	DEBUG("UT=%lu\n",UT);
+	
+	X1 = ((UT - bmp->ac6) * bmp->ac5) >> 15;
+	X2 = (bmp->mc << 11) / (X1 + bmp->md);
+	B5 = X1 + X2;
+	T = ((B5 + 8) >> 4) / 10.0;
+	
+	return T;
+}
+
+
+/**
+ * Returns the measured pressure in pascal.
+ * 
+ * @param bmp180 sensor
+ * @return pressure
+ */
+long bmp180_pressure(void *_bmp) {
+	bmp180_t* bmp = TO_BMP(_bmp);
+	long UT, UP, B6, B5, X1, X2, X3, B3, p;
+	unsigned long B4, B7;
+	
+	UT = bmp180_read_raw_temperature(_bmp);
+	UP = bmp180_read_raw_pressure(_bmp, bmp->oss);
+	
+	X1 = ((UT - bmp->ac6) * bmp->ac5) >> 15;
+	X2 = (bmp->mc << 11) / (X1 + bmp->md);
+	
+	B5 = X1 + X2;
+	
+	B6 = B5 - 4000;
+	
+	X1 = (bmp->b2 * (B6 * B6) >> 12) >> 11;
+	X2 = (bmp->ac2 * B6) >> 11;
+	X3 = X1 + X2;
+	
+	B3 = ((((bmp->ac1 * 4) + X3) << bmp->oss) + 2) / 4;
+	X1 = (bmp->ac3 * B6) >> 13;
+	X2 = (bmp->b1 * ((B6 * B6) >> 12)) >> 16;
+	X3 = ((X1 + X2) + 2) >> 2;
+	
+	
+	B4 = bmp->ac4 * (unsigned long)(X3 + 32768) >> 15;
+	B7 = ((unsigned long) UP - B3) * (50000 >> bmp->oss);
+	
+	if(B7 < 0x80000000) {
+		p = (B7 * 2) / B4;
+	} else {
+		p = (B7 / B4) * 2;
+	}
+	
+	X1 = (p >> 8) * (p >> 8);
+	X1 = (X1 * 3038) >> 16;
+	X2 = (-7357 * p) >> 16;
+	p = p + ((X1 + X2 + 3791) >> 4);
+	
+	return p;
+}
+
+
+/**
+ * Returns altitude in meters based on the measured pressure 
+ * and temperature of this sensor.
+ * 
+ * @param bmp180 sensor
+ * @return altitude
+ */
+float bmp180_altitude(void *_bmp) {
+	float p, alt;
+	p = bmp180_pressure(_bmp);
+	alt = 44330 * (1 - pow(( (p/100) / BMP180_SEA_LEVEL),1/5.255));
+	
+	return alt;
+}
+
+
+/**
+ * Sets the oversampling setting for this sensor.
+ * 
+ * @param bmp180 sensor
+ * @param oversampling mode
+ */
+void bmp180_set_oss(void *_bmp, int oss) {
+	bmp180_t* bmp = TO_BMP(_bmp);
+	bmp->oss = oss;
+}
+
diff --git a/apps/rp_bmp180/bmp180.h b/apps/rp_bmp180/bmp180.h
new file mode 100644
index 0000000000000000000000000000000000000000..3cf73df53144f426df96afd23b5d8d714d3bc3aa
--- /dev/null
+++ b/apps/rp_bmp180/bmp180.h
@@ -0,0 +1,53 @@
+/**
+ * $Id: $
+ *
+ * @brief A C driver for BMP180 sesor
+ *
+ * @Author L. Horacio Arnaldi <lharnaldi@gmail.com>
+ * @date  01.04.2016
+ *
+ * (c) LabDPR  http://labdpr.cab.cnea.gov.ar
+ *
+ * This part of code is written in C programming language.
+ * Please visit http://en.wikipedia.org/wiki/C_(programming_language)
+ * for more details on the language used herein.
+ */
+ 
+/*
+ * pressure oversampling modes
+ */
+#define BMP180_PRE_OSS0 0 // ultra low power
+#define BMP180_PRE_OSS1 1 // standard
+#define BMP180_PRE_OSS2 2 // high resolution
+#define BMP180_PRE_OSS3 3 // ultra high resoultion
+
+
+typedef struct {
+	/* Eprom values */
+	int ac1;
+	int ac2;
+	int ac3;
+	int ac4;
+	int ac5;
+	int ac6;
+	int b1;
+	int b2;
+	int mb;
+	int mc;
+	int md;
+} bmp180_eprom_t;
+
+void *bmp180_init(int address, const char* i2c_device_filepath);
+
+void bmp180_close(void *_bmp);
+
+long bmp180_pressure(void *_bmp);
+
+void bmp180_set_oss(void *_bmp, int oss);
+
+float bmp180_temperature(void *_bmp);
+
+float bmp180_altitude(void *_bmp);
+
+void bmp180_dump_eprom(void *_bmp, bmp180_eprom_t *eprom);
+
diff --git a/apps/rp_bmp180/test.c b/apps/rp_bmp180/test.c
new file mode 100644
index 0000000000000000000000000000000000000000..1f0d851f328cf812040eae892d35a846cbabef7d
--- /dev/null
+++ b/apps/rp_bmp180/test.c
@@ -0,0 +1,31 @@
+#include "bmp180.h"
+#include <unistd.h>
+#include <stdio.h>
+
+int main(int argc, char **argv){
+	char *i2c_device = "/dev/i2c-0";
+	int address = 0x77;
+	
+	void *bmp = bmp180_init(address, i2c_device);
+	
+	bmp180_eprom_t eprom;
+	bmp180_dump_eprom(bmp, &eprom);
+	
+	
+	bmp180_set_oss(bmp, 1);
+	
+	if(bmp != NULL){
+		int i;
+		for(i = 0; i < 10; i++) {
+			float t = bmp180_temperature(bmp);
+			long p = bmp180_pressure(bmp);
+			float alt = bmp180_altitude(bmp);
+			printf("Temperature = %.1f, Pressure = %lu, Altitude= %.1f\n", t, p, alt);
+			usleep(2 * 1000 * 1000);
+		}
+	
+		bmp180_close(bmp);
+	}
+	
+	return 0;
+}
diff --git a/apps/rp_tinygps/Makefile b/apps/rp_tinygps/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d2810b15dc3a4307964739789881e69fab69ce2c
--- /dev/null
+++ b/apps/rp_tinygps/Makefile
@@ -0,0 +1,14 @@
+CC=gcc
+FLAGS=-Wall -O3
+
+####
+PROG=rp_gps
+EXTRA=tinygps.c
+
+all: $(PROG)
+
+$(PROG): $(PROG).c $(EXTRA) 
+	$(CC) $(FLAGS) -o $(PROG) $(PROG).c $(EXTRA) -lm 
+
+clean:
+	rm -f $(PROG)
diff --git a/apps/rp_tinygps/rp_gps.c b/apps/rp_tinygps/rp_gps.c
new file mode 100644
index 0000000000000000000000000000000000000000..d736afae47723110a49794e7287046528eeaf6fa
--- /dev/null
+++ b/apps/rp_tinygps/rp_gps.c
@@ -0,0 +1,105 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "tinygps.h"
+
+#define BAUDRATE B9600  // Configuración UART para GPS - Velocidad
+#define FALSE 0
+#define TRUE 1
+#define VERSION "0.1"
+
+/*GPS*/
+long alt; // Variable donde se guardara la altitud
+long satellites;
+float flat, flon; // Variables donde se guardarán la latitud y longitud
+unsigned long age, fage;
+int fyear;
+byte fmes, fdia, fhora, fminutos, fs, fhs; // variables para la hora y fecha
+int newdata = 0;
+int res, fd;
+int count=0, aux;
+char buf[255];
+struct termios newtio;
+struct sigaction saio;
+int res, fd;
+int wait_flag=TRUE;
+char devicename[80] = "/dev/ttyPS1";   // Nombre del dispositivo GPS para UART
+int i; // Variable utilizada para los lazos FOR
+
+void signal_handler_IO (int status)
+{
+wait_flag = FALSE;
+}
+
+
+int main(void) {
+
+	// Abir la comunicacion UART para el GPS
+
+	fd = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK);
+
+	if (fd < 0)
+	{
+		perror(devicename);
+		exit(1);
+	}
+
+	//Se installa el serial handler para el GPS
+	saio.sa_handler = signal_handler_IO;
+	sigemptyset(&saio.sa_mask);   //saio.sa_mask = 0;
+	saio.sa_flags = 0;
+	saio.sa_restorer = NULL;
+	sigaction(SIGIO,&saio,NULL);
+
+	fcntl(fd, F_SETOWN, getpid());
+	fcntl(fd, F_SETFL, FASYNC);
+	newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
+	newtio.c_iflag = IGNPAR;
+	newtio.c_oflag = 0;
+	newtio.c_lflag = 0;
+	newtio.c_cc[VMIN]=1;
+	newtio.c_cc[VTIME]=0;
+	tcflush(fd, TCIFLUSH);
+	tcsetattr(fd,TCSANOW,&newtio);
+	//
+	count=0;
+	aux = 0;
+
+	while (count != 2 && aux < 10 )//Si no se recibe una señal valida del GPS en este lapso el programa contnua
+	{
+		usleep (10);
+
+		aux++;
+		res = read(fd,buf,255);
+		if (res > 0)
+		{
+			for (i=0; i < res; i++)  //Lee todos los caracteres del string
+			{
+				if(gps_encode(buf[i]))
+					newdata = 1;
+			}
+
+			if (newdata)
+			{
+				alt = gps_f_altitude();
+				satellites = gps_satellites();
+				gps_crack_datetime(&fyear, &fmes, &fdia, &fhora, &fminutos, &fs, &fhs, &fage);
+				if (fhora < 5)
+				{
+					fhora = 24 + fhora;
+					fdia = fdia -1;
+				}
+
+				gps_f_get_position(&flat, &flon, &age);
+				newdata = 0;
+				count++;
+			}
+		}
+        printf("# ------------------------------\n# Fecha:%d/%d/%d \n# Hora:%d:%d:%d:%d \n# Latitud= %f \n# Longitud= %f \n# Altitud: %lum\n# Satélites: %lu\n# -------------------------------\n",fyear, fmes, fdia, fhora-5, fminutos, fs, fhs, flat, flon, alt, satellites);
+
+	}
+
+	close(fd);
+
+
+}
+
diff --git a/apps/rp_tinygps/tinygps.c b/apps/rp_tinygps/tinygps.c
new file mode 100644
index 0000000000000000000000000000000000000000..842ec36abc879b69a08c2ceb34b8777eafc79a60
--- /dev/null
+++ b/apps/rp_tinygps/tinygps.c
@@ -0,0 +1,464 @@
+
+#include "tinygps.h"
+
+// properties
+unsigned long _time, _new_time;
+unsigned long _date, _new_date;
+long _latitude, _new_latitude;
+long _longitude, _new_longitude;
+long _altitude, _new_altitude;
+unsigned long  _speed, _new_speed;
+unsigned long  _course, _new_course;
+unsigned long  _hdop, _new_hdop;
+unsigned short _numsats, _new_numsats;
+
+unsigned long _last_time_fix, _new_time_fix;
+unsigned long _last_position_fix, _new_position_fix;
+
+// parsing state variables
+byte _parity;
+bool _is_checksum_term;
+char _term[15];
+byte _sentence_type;
+byte _term_number = 0;
+byte _term_offset = 0;
+bool _is_gps_data_good;
+
+#ifndef GPS_NO_STATS
+  // statistics
+unsigned long _encoded_characters;
+unsigned short _good_sentences;
+unsigned short _failed_checksum;
+unsigned short _passed_checksum;
+#endif
+
+//
+// public methods
+//
+
+// verify is character is a digit
+bool gpsisdigit(char c) { return c >= '0' && c <= '9'; }
+
+// signed altitude in centimeters (from GPGGA sentence)
+inline long altitude() { return _altitude; }
+
+// course in last full GPRMC sentence in 100th of a degree
+inline unsigned long course() { return _course; }
+
+// speed in last full GPRMC sentence in 100ths of a knot
+inline unsigned long speed() { return _speed; }
+
+// satellites used in last full GPGGA sentence
+unsigned short gps_satellites() { return _numsats; }
+
+// horizontal dilution of precision in 100ths
+inline unsigned long gps_hdop() { return _hdop; }
+
+
+clock_t uptime()
+{
+	return clock() / (CLOCKS_PER_SEC / 1000);
+}
+
+float radians(float deg)
+{
+	return deg * (PI/180);
+}
+
+float degrees(float rad)
+{
+	return rad * (180/PI);
+}
+
+bool gps_encode(char c)
+{
+  bool valid_sentence = false;
+
+#ifndef GPS_NO_STATS
+  _encoded_characters++;
+#endif
+  switch(c)
+  {
+  case ',': // term terminators
+    _parity ^= c;
+  case '\r':
+  case '\n':
+  case '*':
+    if (_term_offset < sizeof(_term))
+    {
+      _term[_term_offset] = 0;
+      valid_sentence = gps_term_complete();
+    }
+    ++_term_number;
+    _term_offset = 0;
+    _is_checksum_term = c == '*';
+    return valid_sentence;
+
+  case '$': // sentence begin
+    _term_number = 0;
+    _term_offset = 0;
+    _parity = 0;
+    _sentence_type = GPS_SENTENCE_OTHER;
+    _is_checksum_term = false;
+    _is_gps_data_good = false;
+    return valid_sentence;
+  }
+
+  // ordinary characters
+  if (_term_offset < sizeof(_term) - 1)
+    _term[_term_offset++] = c;
+  if (!_is_checksum_term)
+    _parity ^= c;
+
+  return valid_sentence;
+}
+
+#ifndef GPS_NO_STATS
+void gps_stats(unsigned long *chars, unsigned short *sentences, unsigned short *failed_cs)
+{
+  if (chars)
+	*chars = _encoded_characters;
+  if (sentences)
+	*sentences = _good_sentences;
+  if (failed_cs)
+	*failed_cs = _failed_checksum;
+}
+#endif
+
+/*
+ * internal utilities
+*/
+
+int from_hex(char a) 
+{
+  if (a >= 'A' && a <= 'F')
+    return a - 'A' + 10;
+  else if (a >= 'a' && a <= 'f')
+    return a - 'a' + 10;
+  else
+    return a - '0';
+}
+
+unsigned long gps_parse_decimal()
+{
+  char *p;
+  bool isneg;
+  unsigned long ret;
+
+  p = _term;
+  isneg = (*p == '-');
+  if (isneg)
+	++p;
+
+  ret = 100UL * gpsatol(p);
+
+  while (gpsisdigit(*p))
+	++p;
+
+  if (*p == '.')
+  {
+    if (gpsisdigit(p[1]))
+    {
+      ret += 10 * (p[1] - '0');
+      if (gpsisdigit(p[2]))
+        ret += p[2] - '0';
+    }
+  }
+  return isneg ? -ret : ret;
+}
+
+unsigned long gps_parse_degrees()
+{
+  char *p;
+  unsigned long left;
+  unsigned long tenk_minutes;
+
+  left = gpsatol(_term);
+  tenk_minutes = (left % 100UL) * 10000UL;
+
+  for (p=_term; gpsisdigit(*p); ++p);
+
+  if (*p == '.')
+  {
+    unsigned long mult = 1000;
+    while (gpsisdigit(*++p))
+    {
+      tenk_minutes += mult * (*p - '0');
+      mult /= 10;
+    }
+  }
+  return (left / 100) * 100000 + tenk_minutes / 6;
+}
+
+#define COMBINE(sentence_type, term_number) (((unsigned)(sentence_type) << 5) | term_number)
+
+/* Processes a just-completed term
+ * Returns true if new sentence has just passed checksum test and is validated
+ */
+bool gps_term_complete()
+{
+  if (_is_checksum_term)
+  {
+    byte checksum;
+    checksum = 16 * from_hex(_term[0]) + from_hex(_term[1]);
+    if (checksum == _parity)
+    {
+      if (_is_gps_data_good)
+      {
+#ifndef GPS_NO_STATS
+        ++_good_sentences;
+#endif
+        _last_time_fix = _new_time_fix;
+        _last_position_fix = _new_position_fix;
+
+        switch(_sentence_type)
+        {
+        case GPS_SENTENCE_GPRMC:
+          _time      = _new_time;
+          _date      = _new_date;
+          _latitude  = _new_latitude;
+          _longitude = _new_longitude;
+          _speed     = _new_speed;
+          _course    = _new_course;
+          break;
+        case GPS_SENTENCE_GPGGA:
+          _altitude  = _new_altitude;
+          _time      = _new_time;
+          _latitude  = _new_latitude;
+          _longitude = _new_longitude;
+          _numsats   = _new_numsats;
+          _hdop      = _new_hdop;
+          break;
+        }
+
+        return true;
+      }
+    }
+
+#ifndef GPS_NO_STATS
+    else
+      ++_failed_checksum;
+#endif
+    return false;
+  }
+
+  // the first term determines the sentence type
+  if (_term_number == 0)
+  {
+    if (!gpsstrcmp(_term, GPRMC_TERM))
+      _sentence_type = GPS_SENTENCE_GPRMC;
+    else if (!gpsstrcmp(_term, GPGGA_TERM))
+      _sentence_type = GPS_SENTENCE_GPGGA;
+    else
+      _sentence_type = GPS_SENTENCE_OTHER;
+    return false;
+  }
+
+  if (_sentence_type != GPS_SENTENCE_OTHER && _term[0])
+    switch(COMBINE(_sentence_type, _term_number))
+  {
+    case COMBINE(GPS_SENTENCE_GPRMC, 1): // Time in both sentences
+    case COMBINE(GPS_SENTENCE_GPGGA, 1):
+      _new_time = gps_parse_decimal();
+      _new_time_fix = uptime();
+      break;
+    case COMBINE(GPS_SENTENCE_GPRMC, 2): // GPRMC validity
+      _is_gps_data_good = (_term[0] == 'A');
+      break;
+    case COMBINE(GPS_SENTENCE_GPRMC, 3): // Latitude
+    case COMBINE(GPS_SENTENCE_GPGGA, 2):
+      _new_latitude = gps_parse_degrees();
+      _new_position_fix = uptime();
+      break;
+    case COMBINE(GPS_SENTENCE_GPRMC, 4): // N/S
+    case COMBINE(GPS_SENTENCE_GPGGA, 3):
+      if (_term[0] == 'S')
+        _new_latitude = -_new_latitude;
+      break;
+    case COMBINE(GPS_SENTENCE_GPRMC, 5): // Longitude
+    case COMBINE(GPS_SENTENCE_GPGGA, 4):
+      _new_longitude = gps_parse_degrees();
+      break;
+    case COMBINE(GPS_SENTENCE_GPRMC, 6): // E/W
+    case COMBINE(GPS_SENTENCE_GPGGA, 5):
+      if (_term[0] == 'W')
+        _new_longitude = -_new_longitude;
+      break;
+    case COMBINE(GPS_SENTENCE_GPRMC, 7): // Speed (GPRMC)
+      _new_speed = gps_parse_decimal();
+      break;
+    case COMBINE(GPS_SENTENCE_GPRMC, 8): // Course (GPRMC)
+      _new_course = gps_parse_decimal();
+      break;
+    case COMBINE(GPS_SENTENCE_GPRMC, 9): // Date (GPRMC)
+      _new_date = gpsatol(_term);
+      break;
+    case COMBINE(GPS_SENTENCE_GPGGA, 6): // Fix data (GPGGA)
+      _is_gps_data_good = (_term[0] > '0');
+      break;
+    case COMBINE(GPS_SENTENCE_GPGGA, 7): // Satellites used (GPGGA)
+      _new_numsats = (unsigned char)atoi(_term);
+      break;
+    case COMBINE(GPS_SENTENCE_GPGGA, 8): // HDOP
+      _new_hdop = gps_parse_decimal();
+      break;
+    case COMBINE(GPS_SENTENCE_GPGGA, 9): // Altitude (GPGGA)
+      _new_altitude = gps_parse_decimal();
+      break;
+  }
+
+  return false;
+}
+
+long gpsatol(const char *str)
+{
+  long ret = 0;
+  while (gpsisdigit(*str))
+    ret = 10 * ret + *str++ - '0';
+  return ret;
+}
+
+int gpsstrcmp(const char *str1, const char *str2)
+{
+  while (*str1 && *str1 == *str2)
+    ++str1, ++str2;
+  return *str1;
+}
+
+/* static */
+float gps_distance_between (float lat1, float long1, float lat2, float long2) 
+{
+  // returns distance in meters between two positions, both specified 
+  // as signed decimal-degrees latitude and longitude. Uses great-circle 
+  // distance computation for hypothetical sphere of radius 6372795 meters.
+  // Because Earth is no exact sphere, rounding errors may be up to 0.5%.
+  // Courtesy of Maarten Lamers
+  float delta = radians(long1-long2);
+  float sdlong = (float)sin(delta);
+  float cdlong = (float)cos(delta);
+  lat1 = radians(lat1);
+  lat2 = radians(lat2);
+  float slat1 = sin(lat1);
+  float clat1 = cos(lat1);
+  float slat2 = sin(lat2);
+  float clat2 = cos(lat2);
+  delta = (clat1 * slat2) - (slat1 * clat2 * cdlong); 
+  delta = sq(delta); 
+  delta += sq(clat2 * sdlong); 
+  delta = sqrt(delta); 
+  float denom = (slat1 * slat2) + (clat1 * clat2 * cdlong); 
+  delta = atan2(delta, denom); 
+  return delta * 6372795; 
+}
+
+float gps_course_to (float lat1, float long1, float lat2, float long2) 
+{
+  // returns course in degrees (North=0, West=270) from position 1 to position 2,
+  // both specified as signed decimal-degrees latitude and longitude.
+  // Because Earth is no exact sphere, calculated course may be off by a tiny fraction.
+  // Courtesy of Maarten Lamers
+  float dlon = radians(long2-long1);
+  lat1 = radians(lat1);
+  lat2 = radians(lat2);
+  float a1 = sin(dlon) * cos(lat2);
+  float a2 = sin(lat1) * cos(lat2) * cos(dlon);
+  a2 = cos(lat1) * sin(lat2) - a2;
+  a2 = atan2(a1, a2);
+  if (a2 < 0.0)
+  {
+    a2 += TWO_PI;
+  }
+  return degrees(a2);
+}
+
+const char *gps_cardinal (float course)
+{
+  static const char* directions[] = {"N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"};
+
+  int direction = (int)((course + 11.25f) / 22.5f);
+  return directions[direction % 16];
+}
+
+// lat/long in hundred thousandths of a degree and age of fix in milliseconds
+void gps_get_position(long *latitude, long *longitude, unsigned long *fix_age)
+{
+  if (latitude)
+	*latitude = _latitude;
+  if (longitude)
+	*longitude = _longitude;
+  if (fix_age)
+	*fix_age = (_last_position_fix == GPS_INVALID_FIX_TIME) ? 
+		GPS_INVALID_AGE : uptime() - _last_position_fix;
+}
+
+// date as ddmmyy, time as hhmmsscc, and age in milliseconds
+void gps_get_datetime(unsigned long *date, unsigned long *time, unsigned long *age)
+{
+  if (date)
+	*date = _date;
+  if (time)
+	*time = _time;
+  if (age)
+	*age = _last_time_fix == GPS_INVALID_FIX_TIME ? 
+		GPS_INVALID_AGE : uptime() - _last_time_fix;
+}
+
+void gps_f_get_position(float *latitude, float *longitude, unsigned long *fix_age)
+{
+  long lat, lon;
+  gps_get_position(&lat, &lon, fix_age);
+  *latitude = lat == GPS_INVALID_ANGLE ? GPS_INVALID_F_ANGLE : (lat / 100000.0);
+  *longitude = lat == GPS_INVALID_ANGLE ? GPS_INVALID_F_ANGLE : (lon / 100000.0);
+}
+
+void gps_crack_datetime(int *year, byte *month, byte *day, 
+  byte *hour, byte *minute, byte *second, byte *hundredths, unsigned long *age)
+{
+  unsigned long date, time;
+  gps_get_datetime(&date, &time, age);
+  if (year) 
+  {
+    *year = date % 100;
+    *year += *year > 80 ? 1900 : 2000;
+  }
+  if (month) *month = (date / 100) % 100;
+  if (day) *day = date / 10000;
+  if (hour) *hour = time / 1000000;
+  if (minute) *minute = (time / 10000) % 100;
+  if (second) *second = (time / 100) % 100;
+  if (hundredths) *hundredths = time % 100;
+}
+
+float gps_f_altitude()    
+{
+  return _altitude == GPS_INVALID_ALTITUDE ? GPS_INVALID_F_ALTITUDE : _altitude / 100.0;
+}
+
+float gps_f_course()
+{
+  return _course == GPS_INVALID_ANGLE ? GPS_INVALID_F_ANGLE : _course / 100.0;
+}
+
+float gps_f_speed_knots() 
+{
+  return _speed == GPS_INVALID_SPEED ? GPS_INVALID_F_SPEED : _speed / 100.0;
+}
+
+float gps_f_speed_mph()   
+{ 
+  float sk = gps_f_speed_knots();
+  return sk == GPS_INVALID_F_SPEED ? GPS_INVALID_F_SPEED : GPS_MPH_PER_KNOT * gps_f_speed_knots(); 
+}
+
+float gps_f_speed_mps()   
+{ 
+  float sk = gps_f_speed_knots();
+  return sk == GPS_INVALID_F_SPEED ? GPS_INVALID_F_SPEED : GPS_MPS_PER_KNOT * gps_f_speed_knots(); 
+}
+
+float gps_f_speed_kmph()  
+{ 
+  float sk = gps_f_speed_knots();
+  return sk == GPS_INVALID_F_SPEED ? GPS_INVALID_F_SPEED : GPS_KMPH_PER_KNOT * gps_f_speed_knots(); 
+}
+
diff --git a/apps/rp_tinygps/tinygps.h b/apps/rp_tinygps/tinygps.h
new file mode 100644
index 0000000000000000000000000000000000000000..93e863ce5a1e8f7cf83cd0163c38812612ef61f7
--- /dev/null
+++ b/apps/rp_tinygps/tinygps.h
@@ -0,0 +1,110 @@
+#ifndef tinygps_h
+#define tinygps_h
+
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+#include <termios.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/signal.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sys/sendfile.h>
+#include <sys/stat.h>
+
+
+//typedef char bool;
+typedef unsigned char byte;
+#define false 0
+#define true 1
+
+#define PI 3.14159265
+#define TWO_PI 2*PI
+
+#define sq(x) ((x)*(x))
+
+#define GPRMC_TERM   "GPRMC"
+#define GPGGA_TERM   "GPGGA"
+
+#define GPS_INVALID_F_ANGLE 1000.0
+#define GPS_INVALID_F_ALTITUDE 1000000.0
+#define GPS_INVALID_F_SPEED -1.0
+
+
+#define GPS_VERSION 12 // software version of this library
+#define GPS_MPH_PER_KNOT 1.15077945
+#define GPS_MPS_PER_KNOT 0.51444444
+#define GPS_KMPH_PER_KNOT 1.852
+#define GPS_MILES_PER_METER 0.00062137112
+#define GPS_KM_PER_METER 0.001
+// #define GPS_NO_STATS
+
+  enum {
+    GPS_INVALID_AGE = 0xFFFFFFFF,
+    GPS_INVALID_ANGLE = 999999999, 
+    GPS_INVALID_ALTITUDE = 999999999,
+    GPS_INVALID_DATE = 0,
+    GPS_INVALID_TIME = 0xFFFFFFFF,
+    GPS_INVALID_SPEED = 999999999, 
+    GPS_INVALID_FIX_TIME = 0xFFFFFFFF,
+    GPS_INVALID_SATELLITES = 0xFF,
+    GPS_INVALID_HDOP = 0xFFFFFFFF
+  };
+
+  // process one character received from GPS
+  bool encode(char c);
+
+  // lat/long in hundred thousandths of a degree and age of fix in milliseconds
+  void gps_get_position(long *latitude, long *longitude, unsigned long *fix_age);
+
+  // date as ddmmyy, time as hhmmsscc, and age in milliseconds
+  void gps_get_datetime(unsigned long *date, unsigned long *time, unsigned long *age);
+
+  void gps_f_get_position(float *latitude, float *longitude, unsigned long *fix_age);
+  void gps_crack_datetime(int *year, byte *month, byte *day, 
+    byte *hour, byte *minute, byte *second, byte *hundredths, unsigned long *fix_age);
+  float gps_f_altitude();
+  unsigned short gps_satellites();
+  float gps_f_course();
+  float gps_f_speed_knots();
+  float gps_f_speed_mph();
+  float gps_f_speed_mps();
+  float gps_f_speed_kmph();
+
+  static int library_version() { return GPS_VERSION; }
+
+  static float gps_distance_between (float lat1, float long1, float lat2, float long2);
+  static float gps_course_to (float lat1, float long1, float lat2, float long2);
+  static const char *gps_cardinal(float course);
+
+#ifndef GPS_NO_STATS
+  void gps_stats(unsigned long *chars, unsigned short *good_sentences, unsigned short *failed_cs);
+#endif
+
+  enum {
+	GPS_SENTENCE_GPGGA,
+	GPS_SENTENCE_GPRMC,
+	GPS_SENTENCE_OTHER
+  };
+
+  // internal utilities
+  int from_hex(char a);
+  unsigned long gps_parse_decimal();
+  unsigned long gps_parse_degrees();
+  bool gps_term_complete();
+  bool gpsisdigit(char c);
+  long gpsatol(const char *str);
+  int gpsstrcmp(const char *str1, const char *str2);
+// Cabeceras funciones
+void signal_handler_IO (int status);
+
+#endif
diff --git a/apps/rp_venusGPS/Makefile b/apps/rp_venusGPS/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..7268416d2a155349485255054649dfa5f6d447d2
--- /dev/null
+++ b/apps/rp_venusGPS/Makefile
@@ -0,0 +1,14 @@
+CC=gcc
+FLAGS=-Wall -O3
+
+####
+PROG=gpsLogger
+EXTRA=nmea_rp.c uart_rp.c gps_rp.c
+
+all: $(PROG)
+
+$(PROG): $(PROG).c $(EXTRA) 
+	$(CC) $(FLAGS) -o $(PROG) $(PROG).c $(EXTRA) -lm 
+
+clean:
+	rm -f $(PROG)
diff --git a/apps/rp_venusGPS/gpsLogger.c b/apps/rp_venusGPS/gpsLogger.c
new file mode 100644
index 0000000000000000000000000000000000000000..2bfe2d16c9cc670c083dd70499dea4937277795f
--- /dev/null
+++ b/apps/rp_venusGPS/gpsLogger.c
@@ -0,0 +1,19 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "gps_rp.h"
+
+int main(void) {
+    // Open
+    gps_init();
+
+    loc_t data;
+
+    while (1) {
+        gps_location(&data);
+
+        printf("%lf %lf %02d:%02d:%02d %02d/%02d/%04d\n", data.latitude, data.longitude, data.D.hour, data.D.minute, data.D.second, data.D.day, data.D.month,data.D.year);
+    }
+
+    return EXIT_SUCCESS;
+}
+
diff --git a/apps/rp_venusGPS/gps_rp.c b/apps/rp_venusGPS/gps_rp.c
new file mode 100644
index 0000000000000000000000000000000000000000..dfb8b16a95c6e71cde2b7fc4ab974069e774fd22
--- /dev/null
+++ b/apps/rp_venusGPS/gps_rp.c
@@ -0,0 +1,147 @@
+/*
+ * @brief This is a simple application for testing UART communication with a GPS
+ * connected to a RedPitaya
+ *
+ * @Author L. Horacio Arnaldi <lharnaldi@gmail.com>
+ *
+ * (c) LabDPR  http://labdpr.cab.cnea.gov.ar
+ *
+ * This part of code is written in C programming language.
+ * Please visit http://en.wikipedia.org/wiki/C_(programming_language)
+ * for more details on the language used herein.
+ */
+
+#include "gps_rp.h"
+#include "nmea_rp.h"
+#include "uart_rp.h"
+
+void gps_init(void) {
+  rp_UartInit();
+  rp_UartConfig();
+}
+
+void gps_on(void) {
+}
+
+// Compute the GPS location using decimal scale
+void gps_location(loc_t *coord) {
+  uint8_t status = _EMPTY;
+  while(status != _COMPLETED) {
+    gpgga_t gpgga;
+    gprmc_t gprmc;
+    char buffer[256];
+
+    rp_UartReadln(buffer, 256);
+    switch (rp_NmeaGetMessageType(buffer)) {
+      case NMEA_GPGGA:
+        rp_NmeaParseGpgga(buffer, &gpgga);
+
+        gps_convert_deg_to_dec(&(gpgga.latitude), gpgga.NS, &(gpgga.longitude), gpgga.EW);
+
+        coord->latitude = gpgga.latitude;
+        coord->longitude = gpgga.longitude;
+        coord->height = gpgga.height;
+
+        status |= NMEA_GPGGA;
+        break;
+      case NMEA_GPRMC:
+        rp_NmeaParseGprmc(buffer, &gprmc);
+
+        gps_convert_deg_to_dec(&(gprmc.latitude), gprmc.NS, &(gprmc.longitude), gprmc.EW);
+        coord->latitude = gprmc.latitude;
+        coord->longitude = gprmc.longitude;
+        coord->height = gprmc.height;
+        coord->speed = gprmc.speed;
+        coord->course = gprmc.course;
+        coord->D.hour = gprmc.D.hour;
+        coord->D.minute = gprmc.D.minute;
+        coord->D.second = gprmc.D.second;
+        coord->D.day = gprmc.D.day;
+        coord->D.month = gprmc.D.month;
+        coord->D.year = gprmc.D.year;
+
+
+        status |= NMEA_GPRMC;
+        break;
+    }
+  }
+}
+
+void gps_off(void) {
+  //Write off
+  rp_UartClose();
+}
+
+// Convert lat e lon to decimals (from deg)
+void gps_convert_deg_to_dec(double *latitude, char ns,  double *longitude, char we)
+{
+  double lat = (ns == 'N') ? *latitude : -1 * (*latitude);
+  double lon = (we == 'E') ? *longitude : -1 * (*longitude);
+
+  *latitude = gps_deg_dec(lat);
+  *longitude = gps_deg_dec(lon);
+}
+
+double gps_deg_dec(double deg_point)
+{
+  double ddeg;
+  double sec = modf(deg_point, &ddeg)*60;
+  int deg = (int)(ddeg/100);
+  int min = (int)(deg_point-(deg*100));
+
+  double absdlat = round(deg * 1000000.);
+  double absmlat = round(min * 1000000.);
+  double absslat = round(sec * 1000000.);
+
+  return round(absdlat + (absmlat/60) + (absslat/3600)) /1000000;
+}
+
+// GPS Parser **********************************************
+
+// Example: $GPRMC,092741.00,A,5213.13757,N,00008.23605,E,0.272,,180617,,,A*7F
+//char fmt[]="$GPRMC,dddtdd.ds,A,eeae.eeee,l,eeeae.eeee,o,jdk,c,dddy";
+//
+//int state;
+//unsigned int temp;
+//long ltmp;
+//
+//// GPS variables
+//volatile unsigned int Time, Csecs, Knots, Course, Date;
+//volatile long Lat, Long;
+//volatile boolean Fix;
+//
+//void ParseGPS (char c) {
+//  if (c == '$') { state = 0; temp = 0; ltmp = 0; }
+//  char mode = fmt[state++];
+//  // If received character matches format string, return
+//  if (mode == c) return;
+//  char d = c - '0';
+//  // Ignore extra digits of precision
+//  if (mode == ',') state--; 
+//  // d=decimal digit; j=decimal digits before decimal point
+//  else if (mode == 'd') temp = temp*10 + d;
+//  else if (mode == 'j') { if (c != '.') { temp = temp*10 + d; state--; } }
+//  // e=long decimal digit
+//  else if (mode == 'e') ltmp = (ltmp<<3) + (ltmp<<1) + d; // ltmp = ltmp*10 + d;
+//  // a=angular measure
+//  else if (mode == 'a') ltmp = (ltmp<<2) + (ltmp<<1) + d; // ltmp = ltmp*6 + d;
+//  // t=Time - hhmm
+//  else if (mode == 't') { Time = temp*10 + d; temp = 0; }
+//  // s=Centisecs
+//  else if (mode == 's') { Csecs = temp*10 + d; temp = 0; }
+//  // l=Latitude - in minutes * 1e-4
+//  else if (mode == 'l') { if (c == 'N') Lat = ltmp; else Lat = -ltmp; ltmp = 0; }
+//  // o=Longitude - in minutes * 1e-4
+//  else if (mode == 'o') { if (c == 'E') Long = ltmp; else Long = -ltmp; ltmp = 0; }
+//   // k=Speed - in knots*100
+//  else if (mode == 'k') { Knots = temp*10 + d; temp = 0; }
+//  // c=Course (Track) - in degrees*100. Allow for empty field.
+//  else if (mode == 'c') {
+//    if (c == ',') { Course = temp; temp = 0; state++; }
+//    else if (c == '.') state--;
+//    else { temp = temp*10 + d; state--; }
+//  }
+//  // y=Date - ddmm
+//  else if (mode == 'y') { Date = temp*10 + d ; Fix = 1; state = 0; }
+//  else state = 0;
+//}
diff --git a/apps/rp_venusGPS/gps_rp.h b/apps/rp_venusGPS/gps_rp.h
new file mode 100644
index 0000000000000000000000000000000000000000..42e9deadc93a7d492d533f02896c28b78822ffd4
--- /dev/null
+++ b/apps/rp_venusGPS/gps_rp.h
@@ -0,0 +1,75 @@
+/**
+ * $Id: $
+ *
+ * @brief GPS stuffs module.
+ *
+ * @Author L. Horacio Arnaldi <lharnaldi@gmail.com>
+ *
+ * (c) LabDPR  http://labdpr.cab.cnea.gov.ar
+ *
+ * This part of code is written in C programming language.
+ * Please visit http://en.wikipedia.org/wiki/C_(programming_language)
+ * for more details on the language used herein.
+ */
+
+#ifndef _GPS_RP_H_
+#define _GPS_RP_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+typedef struct{
+    int year;
+    int month;
+    int day;
+    int hour;
+    int minute;
+    int second;
+}DTIME;
+
+
+typedef struct location {
+    //double gtime;
+    //double latitude;
+    //double longitude;
+    //double speed;
+    //double altitude;
+    //double course;
+    double  latitude;         // longitud
+    double  longitude;        // Latitud
+    int     latitude_Degree;  // grado
+    int     latitude_Cent;    // min
+    int     latitude_Second;  // segundos
+    int     longitude_Degree; // grado
+    int     longitude_Cent;   // min
+    int     longitude_Second; // segundos
+    float   speed;            // velocidad
+    float   course;           // rumbo
+    float   height;           // altitud
+    int     satellite;
+    char    NS;
+    char    EW;
+    DTIME   D;
+} loc_t;
+
+// Initialize device
+void gps_init(void);
+// Activate device
+void gps_on(void);
+// Get the actual location
+void gps_location(loc_t *);
+
+
+// Turn off device (low-power consumption)
+void gps_off(void);
+
+// -------------------------------------------------------------------------
+// Internal functions
+// -------------------------------------------------------------------------
+
+// convert deg to decimal deg latitude, (N/S), longitude, (W/E)
+void gps_convert_deg_to_dec(double *, char, double *, char);
+double gps_deg_dec(double);
+
+#endif
diff --git a/apps/rp_venusGPS/nmea_rp.c b/apps/rp_venusGPS/nmea_rp.c
new file mode 100644
index 0000000000000000000000000000000000000000..814f0436bbc980e668656eac10154e886d410635
--- /dev/null
+++ b/apps/rp_venusGPS/nmea_rp.c
@@ -0,0 +1,221 @@
+/*
+ * @brief This is a simple parser programm for NMEA messages
+ *
+ * @Author L. Horacio Arnaldi <lharnaldi@gmail.com>
+ *
+ * (c) LabDPR  http://labdpr.cab.cnea.gov.ar
+ *
+ * This part of code is written in C programming language.
+ * Please visit http://en.wikipedia.org/wiki/C_(programming_language)
+ * for more details on the language used herein.
+ */
+
+#include "nmea_rp.h"
+
+int rp_GetComma(char num, char* line){
+	char *ptr = line;
+	int count = 0;
+	while ((count != num) && ((ptr = strstr(ptr, ",")) != NULL)) {
+		ptr += 1;
+		count++;
+	}
+	return ptr-line;
+}
+
+int rp_NmeaParseGprmc(char *nmea, gprmc_t *GPS){
+	uint8_t ch, status, tmp;
+	float lati_cent_tmp, lati_second_tmp;
+	float long_cent_tmp, long_second_tmp;
+	float speed_tmp=0;
+	char *buf = nmea;
+	ch = buf[5];
+	status = buf[rp_GetComma(2, buf)];
+
+	GPS->NS = buf[rp_GetComma(4, buf)];
+	GPS->EW = buf[rp_GetComma(6, buf)];
+
+	//GPS->latitude = Get_Double_Number(&buf[rp_GetComma(3, buf)]);
+	//GPS->longitude = Get_Double_Number(&buf[rp_GetComma(5, buf)]);
+
+	GPS->latitude_Degree = (int)GPS->latitude / 100; // Latitud separada
+	lati_cent_tmp = (GPS->latitude - GPS->latitude_Degree * 100);
+	GPS->latitude_Cent = (int)lati_cent_tmp;
+	lati_second_tmp = (lati_cent_tmp - GPS->latitude_Cent) * 60;
+	GPS->latitude_Second = (int)lati_second_tmp;
+
+	GPS->longitude_Degree = (int)GPS->longitude / 100; // Longitud separada
+	long_cent_tmp = (GPS->longitude - GPS->longitude_Degree * 100);
+	GPS->longitude_Cent = (int)long_cent_tmp;
+	long_second_tmp = (long_cent_tmp - GPS->longitude_Cent) * 60;
+	GPS->longitude_Second = (int)long_second_tmp;
+
+	//speed_tmp = Get_Float_Number(&buf[rp_GetComma(7, buf)]); // Velocidad (unidad: milla náutica / hora)
+	GPS->speed = speed_tmp * 1.85; //1Millas náuticas =1.85Kilómetros
+	//GPS->direction = Get_Float_Number(&buf[rp_GetComma(8, buf)]); // ángulo
+
+	GPS->D.hour = (buf[7] - '0') * 10 + (buf[8] - '0'); // Tiempo
+	GPS->D.minute = (buf[9] - '0') * 10 + (buf[10] - '0');
+	GPS->D.second = (buf[11] - '0') * 10 + (buf[12] - '0');
+	tmp = rp_GetComma(9, buf);
+	GPS->D.day = (buf[tmp + 0] - '0') * 10 + (buf[tmp + 1] - '0'); // fecha
+	GPS->D.month = (buf[tmp + 2] - '0') * 10 + (buf[tmp + 3] - '0');
+	GPS->D.year = (buf[tmp + 4] - '0') * 10 + (buf[tmp + 5] - '0') + 2000;
+
+	//UTC2BTC(&GPS->D);
+
+	return 1;
+	//}
+	//}
+
+	//return 0;
+	}
+
+void rp_NmeaParseGpgga(char *nmea, gpgga_t *loc){
+	char *ptr = nmea;
+
+	ptr = strchr(ptr, ',')+1; //skip time -> not valid now
+	//loc->gtime = atof(ptr);
+
+	ptr = strchr(ptr, ',')+1;
+	loc->latitude = atof(ptr);
+
+	ptr = strchr(ptr, ',')+1;
+	switch (ptr[0]) {
+		case 'N':
+			loc->NS = 'N';
+			break;
+		case 'S':
+			loc->NS = 'S';
+			break;
+		case ',':
+			loc->NS = '\0';
+			break;
+	}
+
+	ptr = strchr(ptr, ',')+1;
+	loc->longitude = atof(ptr);
+
+	ptr = strchr(ptr, ',')+1;
+	switch (ptr[0]) {
+		case 'W':
+			loc->EW = 'W';
+			break;
+		case 'E':
+			loc->EW = 'E';
+			break;
+		case ',':
+			loc->EW = '\0';
+			break;
+	}
+
+	ptr = strchr(ptr, ',')+1;
+	loc->quality = (uint8_t)atoi(ptr);
+
+	ptr = strchr(ptr, ',')+1;
+	loc->satellites = (uint8_t)atoi(ptr);
+
+	ptr = strchr(ptr, ',')+1;
+
+	ptr = strchr(ptr, ',')+1;
+	loc->height = atof(ptr);
+}
+
+/*
+   void rp_NmeaParseGprmc(char *nmea, gprmc_t *loc){
+   char *ptr = nmea;
+
+//			GPS->D.hour = (buf[7] - '0') * 10 + (buf[8] - '0'); // Tiempo
+//			GPS->D.minute = (buf[9] - '0') * 10 + (buf[10] - '0');
+//			GPS->D.second = (buf[11] - '0') * 10 + (buf[12] - '0');
+//			tmp = rp_GetComma(9, buf);
+//			GPS->D.day = (buf[tmp + 0] - '0') * 10 + (buf[tmp + 1] - '0'); // fecha
+//			GPS->D.month = (buf[tmp + 2] - '0') * 10 + (buf[tmp + 3] - '0');
+//			GPS->D.year = (buf[tmp + 4] - '0') * 10 + (buf[tmp + 5] - '0') + 2000;
+ptr = strchr(ptr, ',')+1; //skip time
+//loc->gtime = atof(ptr);
+loc->D.hour = *(ptr-'0')*10 + *(ptr+1 - '0'); //(buf[7] - '0') * 10 + (buf[8] - '0'); // Tiempo
+loc->D.minute = *(ptr+2 - '0')*10 + *(ptr+3 - '0'); //(buf[9] - '0') * 10 + (buf[10] - '0');
+loc->D.second = *(ptr+4 - '0')*10 + *(ptr+5 - '0'); //(buf[11] - '0') * 10 + (buf[12] - '0');
+ptr = strchr(ptr, ',')+1; //skip status
+
+ptr = strchr(ptr, ',')+1;
+loc->latitude = atof(ptr);
+
+ptr = strchr(ptr, ',')+1;
+switch (ptr[0]) {
+case 'N':
+loc->NS = 'N';
+break;
+case 'S':
+loc->NS = 'S';
+break;
+case ',':
+loc->NS = '\0';
+break;
+}
+
+ptr = strchr(ptr, ',')+1;
+loc->longitude = atof(ptr);
+
+ptr = strchr(ptr, ',')+1;
+switch (ptr[0]) {
+case 'W':
+loc->EW = 'W';
+break;
+case 'E':
+loc->EW = 'E';
+break;
+case ',':
+loc->EW = '\0';
+break;
+}
+
+ptr = strchr(ptr, ',')+1;
+loc->speed = atof(ptr);
+
+ptr = strchr(ptr, ',')+1;
+loc->course = atof(ptr);
+}*/
+
+/**
+ * Get the message type (GPGGA, GPRMC, etc..)
+ *
+ * This function filters out also wrong packages (invalid checksum)
+ *
+ * @param message The NMEA message
+ * @return The type of message if it is valid
+ */
+uint8_t rp_NmeaGetMessageType(const char *message){
+	uint8_t checksum = 0;
+	if ((checksum = rp_NmeaValidChecksum(message)) != _EMPTY) {
+		return checksum;
+	}
+
+	if (strstr(message, NMEA_GPGGA_STR) != NULL) {
+		return NMEA_GPGGA;
+	}
+
+	if (strstr(message, NMEA_GPRMC_STR) != NULL) {
+		return NMEA_GPRMC;
+	}
+
+	return NMEA_UNKNOWN;
+}
+
+uint8_t rp_NmeaValidChecksum(const char *message) {
+	uint8_t checksum= (uint8_t)strtol(strchr(message, '*')+1, NULL, 16);
+
+	char p;
+	uint8_t sum = 0;
+	++message;
+	while ((p = *message++) != '*') {
+		sum ^= p;
+	}
+
+	if (sum != checksum) {
+		return NMEA_CHECKSUM_ERR;
+	}
+
+	return _EMPTY;
+}
+
diff --git a/apps/rp_venusGPS/nmea_rp.h b/apps/rp_venusGPS/nmea_rp.h
new file mode 100644
index 0000000000000000000000000000000000000000..5838b08e5e57762592b3955315df628c5e564fad
--- /dev/null
+++ b/apps/rp_venusGPS/nmea_rp.h
@@ -0,0 +1,104 @@
+/**
+ * $Id: $
+ *
+ * @brief GPS NMEA messages parser.
+ *
+ * @Author L. Horacio Arnaldi <lharnaldi@gmail.com>
+ *
+ * (c) LabDPR  http://labdpr.cab.cnea.gov.ar
+ *
+ * This part of code is written in C programming language.
+ * Please visit http://en.wikipedia.org/wiki/C_(programming_language)
+ * for more details on the language used herein.
+ */
+
+#ifndef _NMEA_RP_H_
+#define _NMEA_RP_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+#include <math.h>
+
+#define _EMPTY 0x00
+#define NMEA_GPRMC 0x01
+#define NMEA_GPRMC_STR "$GPRMC"
+#define NMEA_GPGGA 0x02
+#define NMEA_GPGGA_STR "$GPGGA"
+#define NMEA_UNKNOWN 0x00
+#define _COMPLETED 0x03
+
+#define NMEA_CHECKSUM_ERR 0x80
+#define NMEA_MESSAGE_ERR 0xC0
+
+typedef struct{
+    int year; 
+    int month; 
+    int day;
+    int hour;
+    int minute;
+    int second;
+}DATE_TIME;
+
+//typedef struct gdata{
+//    double  latitude;         // longitud
+//    double  longitude;        // Latitud
+//    int     latitude_Degree;  // grado
+//    int     latitude_Cent;    // min
+//    int     latitude_Second;  // segundos
+//    int     longitude_Degree; // grado
+//    int     longitude_Cent;   // min
+//    int     longitude_Second; // segundos
+//    float   speed;            // velocidad
+//    float   direction;        // rumbo
+//    float   height;           // altitud
+//    int     satellite;
+//    uint8_t NS;
+//    uint8_t EW;
+//    DATE_TIME D;
+//}GPS_INFO;
+
+typedef struct gpgga {
+    double gtime;
+    double latitude;
+    double longitude;
+    uint8_t quality;
+    uint8_t satellites;
+    float   height;           // altitud
+    char    NS;
+    char    EW;
+} gpgga_t;
+
+typedef struct gprmc {
+    //double gtime;
+    //double latitude;
+    //char lat;
+    //double longitude;
+    //char lon;
+    //double speed;
+    //double course;
+    double  latitude;         // longitud
+    double  longitude;        // Latitud
+    int     latitude_Degree;  // grado
+    int     latitude_Cent;    // min
+    int     latitude_Second;  // segundos
+    int     longitude_Degree; // grado
+    int     longitude_Cent;   // min
+    int     longitude_Second; // segundos
+    float   speed;            // velocidad
+    float   course;           // rumbo
+    float   height;           // altitud
+    int     satellite;
+    char    NS;
+    char    EW;
+    DATE_TIME D;
+} gprmc_t;
+
+uint8_t rp_NmeaGetMessageType(const char *);
+uint8_t rp_NmeaValidChecksum(const char *);
+void rp_NmeaParseGpgga(char *, gpgga_t *);
+int rp_NmeaParseGprmc(char *, gprmc_t *);
+
+#endif
+
diff --git a/apps/rp_venusGPS/uart_rp.c b/apps/rp_venusGPS/uart_rp.c
new file mode 100644
index 0000000000000000000000000000000000000000..51e04f610fdb5b75aa480ff3417944990f78667b
--- /dev/null
+++ b/apps/rp_venusGPS/uart_rp.c
@@ -0,0 +1,92 @@
+/*
+ * @brief This is a simple application for testing UART 
+ * communication with a GPS connected to a RedPitaya
+ *
+ * @Author L. Horacio Arnaldi <lharnaldi@gmail.com>
+ *
+ * (c) LabDPR  http://labdpr.cab.cnea.gov.ar
+ *
+ * This part of code is written in C programming language.
+ * Please visit http://en.wikipedia.org/wiki/C_(programming_language)
+ * for more details on the language used herein.
+ */
+
+#include "uart_rp.h"
+
+/* File descriptor definition */
+int uart_fd = -1;
+
+int rp_UartInit(void)
+{
+	uart_fd = open(PORTNAME, O_RDWR | O_NOCTTY | O_NDELAY);
+
+  if(uart_fd == -1){
+    fprintf(stderr, "Failed to open uart.\n");
+    return -1;
+  }
+	return 0;
+}
+
+void rp_UartConfig(void)
+{
+    struct termios options;
+    tcgetattr(uart_fd, &options);
+		/*Configure the UART
+			see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html */
+    options.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
+    options.c_iflag = IGNPAR;
+    options.c_oflag = 0;
+    options.c_lflag = 0;
+		/* Setting attributes */
+    tcflush(uart_fd, TCIFLUSH);
+    tcsetattr(uart_fd, TCSANOW, &options);
+}
+
+int rp_UartPrintln(const char *line, int len)
+{
+    if (uart_fd != -1) {
+        char *cpstr = (char *)malloc((len+1) * sizeof(char));
+        strcpy(cpstr, line);
+        cpstr[len-1] = '\r';
+        cpstr[len] = '\n';
+
+        int count = write(uart_fd, cpstr, len+1);
+        if (count < 0) {
+					fprintf(stderr, "UART TX error.\n");
+					return -1;
+        }
+        free(cpstr);
+    }
+	return 0;
+}
+
+/* Read a line from UART */
+int rp_UartReadln(char *buffer, int len)
+{
+	char c;
+	char *b = buffer;
+	int rx_length = -1;
+
+	while(1) {
+		rx_length = read(uart_fd, (void*)(&c), 1);
+		
+		if (rx_length <= 0) {
+			//wait for messages
+			 sleep(1);
+		} else {
+		  	if (c == '\n') {
+		    	*b++ = '\0';
+		      break;
+		    }
+		    *b++ = c;
+		}
+	}
+	return 0;
+}
+
+void rp_UartClose(void)
+{
+	tcflush(uart_fd, TCIFLUSH);
+	close(uart_fd);
+}
+
diff --git a/apps/rp_venusGPS/uart_rp.h b/apps/rp_venusGPS/uart_rp.h
new file mode 100644
index 0000000000000000000000000000000000000000..b7098cfd0e8538c78fc8832b664a02b85d09ead5
--- /dev/null
+++ b/apps/rp_venusGPS/uart_rp.h
@@ -0,0 +1,40 @@
+/**
+ * $Id: $
+ *
+ * @brief UART communication module for the STEMLab RedPitaya board (tested with
+ * the 14-bit version).
+ *
+ * @Author L. Horacio Arnaldi <lharnaldi@gmail.com>
+ *
+ * (c) LabDPR  http://labdpr.cab.cnea.gov.ar
+ *
+ * This part of code is written in C programming language.
+ * Please visit http://en.wikipedia.org/wiki/C_(programming_language)
+ * for more details on the language used herein.
+ */
+
+#ifndef _UART_RP_H_
+#define _UART_RP_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include <inttypes.h>
+
+//Default name for UART port in E2 expansion conector
+#ifndef PORTNAME
+#define PORTNAME "/dev/ttyPS1"
+#endif
+
+int rp_UartInit(void);
+void rp_UartConfig(void);
+int rp_UartPrintln(const char *, int);
+int rp_UartReadln(char *, int);
+void rp_UartClose(void);
+
+#endif
diff --git a/cfg/clocks.xdc b/cfg/clocks.xdc
new file mode 100644
index 0000000000000000000000000000000000000000..d2cfe3fa18e4254f16df57408a4b52d741536646
--- /dev/null
+++ b/cfg/clocks.xdc
@@ -0,0 +1,2 @@
+set_input_delay -max 1.000 -clock adc_clk_p_i [get_ports adc_dat_a_i[*]]
+set_input_delay -max 1.000 -clock adc_clk_p_i [get_ports adc_dat_b_i[*]]
diff --git a/cfg/ports.tcl b/cfg/ports.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..9a7319b7deecba98b061108ee491d363e2912a1b
--- /dev/null
+++ b/cfg/ports.tcl
@@ -0,0 +1,43 @@
+
+### ADC
+
+create_bd_port -dir I -from 15 -to 0 adc_dat_a_i
+create_bd_port -dir I -from 15 -to 0 adc_dat_b_i
+
+create_bd_port -dir I adc_clk_p_i
+create_bd_port -dir I adc_clk_n_i
+
+create_bd_port -dir O adc_enc_p_o
+create_bd_port -dir O adc_enc_n_o
+
+create_bd_port -dir O adc_csn_o
+
+### DAC
+
+create_bd_port -dir O -from 13 -to 0 dac_dat_o
+
+create_bd_port -dir O dac_clk_o
+create_bd_port -dir O dac_rst_o
+create_bd_port -dir O dac_sel_o
+create_bd_port -dir O dac_wrt_o
+
+### PWM
+
+create_bd_port -dir O -from 3 -to 0 dac_pwm_o
+
+### XADC
+
+create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_analog_io_rtl:1.0 Vp_Vn
+create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_analog_io_rtl:1.0 Vaux0
+create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_analog_io_rtl:1.0 Vaux1
+create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_analog_io_rtl:1.0 Vaux9
+create_bd_intf_port -mode Slave -vlnv xilinx.com:interface:diff_analog_io_rtl:1.0 Vaux8
+
+### Expansion connector
+
+create_bd_port -dir IO -from 7 -to 0 exp_p_tri_io
+create_bd_port -dir IO -from 7 -to 0 exp_n_tri_io
+
+### LED
+
+create_bd_port -dir O -from 7 -to 0 led_o
diff --git a/cfg/ports.xdc b/cfg/ports.xdc
new file mode 100644
index 0000000000000000000000000000000000000000..f0703c590182c7be868b4345f6b68c9497b10c91
--- /dev/null
+++ b/cfg/ports.xdc
@@ -0,0 +1,208 @@
+
+# set_property CFGBVS VCCO [current_design]
+# set_property CONFIG_VOLTAGE 3.3 [current_design]
+
+### ADC
+
+# data
+
+set_property IOSTANDARD LVCMOS18 [get_ports {adc_dat_a_i[*]}]
+set_property IOB TRUE [get_ports {adc_dat_a_i[*]}]
+
+set_property PACKAGE_PIN V17 [get_ports {adc_dat_a_i[0]}]
+set_property PACKAGE_PIN U17 [get_ports {adc_dat_a_i[1]}]
+set_property PACKAGE_PIN Y17 [get_ports {adc_dat_a_i[2]}]
+set_property PACKAGE_PIN W16 [get_ports {adc_dat_a_i[3]}]
+set_property PACKAGE_PIN Y16 [get_ports {adc_dat_a_i[4]}]
+set_property PACKAGE_PIN W15 [get_ports {adc_dat_a_i[5]}]
+set_property PACKAGE_PIN W14 [get_ports {adc_dat_a_i[6]}]
+set_property PACKAGE_PIN Y14 [get_ports {adc_dat_a_i[7]}]
+set_property PACKAGE_PIN W13 [get_ports {adc_dat_a_i[8]}]
+set_property PACKAGE_PIN V12 [get_ports {adc_dat_a_i[9]}]
+set_property PACKAGE_PIN V13 [get_ports {adc_dat_a_i[10]}]
+set_property PACKAGE_PIN T14 [get_ports {adc_dat_a_i[11]}]
+set_property PACKAGE_PIN T15 [get_ports {adc_dat_a_i[12]}]
+set_property PACKAGE_PIN V15 [get_ports {adc_dat_a_i[13]}]
+set_property PACKAGE_PIN T16 [get_ports {adc_dat_a_i[14]}]
+set_property PACKAGE_PIN V16 [get_ports {adc_dat_a_i[15]}]
+
+set_property IOSTANDARD LVCMOS18 [get_ports {adc_dat_b_i[*]}]
+set_property IOB TRUE [get_ports {adc_dat_b_i[*]}]
+
+set_property PACKAGE_PIN T17 [get_ports {adc_dat_b_i[0]}]
+set_property PACKAGE_PIN R16 [get_ports {adc_dat_b_i[1]}]
+set_property PACKAGE_PIN R18 [get_ports {adc_dat_b_i[2]}]
+set_property PACKAGE_PIN P16 [get_ports {adc_dat_b_i[3]}]
+set_property PACKAGE_PIN P18 [get_ports {adc_dat_b_i[4]}]
+set_property PACKAGE_PIN N17 [get_ports {adc_dat_b_i[5]}]
+set_property PACKAGE_PIN R19 [get_ports {adc_dat_b_i[6]}]
+set_property PACKAGE_PIN T20 [get_ports {adc_dat_b_i[7]}]
+set_property PACKAGE_PIN T19 [get_ports {adc_dat_b_i[8]}]
+set_property PACKAGE_PIN U20 [get_ports {adc_dat_b_i[9]}]
+set_property PACKAGE_PIN V20 [get_ports {adc_dat_b_i[10]}]
+set_property PACKAGE_PIN W20 [get_ports {adc_dat_b_i[11]}]
+set_property PACKAGE_PIN W19 [get_ports {adc_dat_b_i[12]}]
+set_property PACKAGE_PIN Y19 [get_ports {adc_dat_b_i[13]}]
+set_property PACKAGE_PIN W18 [get_ports {adc_dat_b_i[14]}]
+set_property PACKAGE_PIN Y18 [get_ports {adc_dat_b_i[15]}]
+
+# clock input
+
+set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports adc_clk_p_i]
+set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports adc_clk_n_i]
+set_property PACKAGE_PIN U18 [get_ports adc_clk_p_i]
+set_property PACKAGE_PIN U19 [get_ports adc_clk_n_i]
+
+# clock output
+
+set_property IOSTANDARD LVCMOS18 [get_ports adc_enc_p_o]
+set_property IOSTANDARD LVCMOS18 [get_ports adc_enc_n_o]
+
+set_property SLEW FAST [get_ports adc_enc_p_o]
+set_property SLEW FAST [get_ports adc_enc_n_o]
+
+set_property DRIVE 8 [get_ports adc_enc_p_o]
+set_property DRIVE 8 [get_ports adc_enc_n_o]
+
+set_property PACKAGE_PIN N20 [get_ports adc_enc_p_o]
+set_property PACKAGE_PIN P20 [get_ports adc_enc_n_o]
+
+# clock duty cycle stabilizer (CSn)
+
+set_property IOSTANDARD LVCMOS18 [get_ports adc_csn_o]
+set_property PACKAGE_PIN V18 [get_ports adc_csn_o]
+set_property SLEW FAST [get_ports adc_csn_o]
+set_property DRIVE 8 [get_ports adc_csn_o]
+
+### DAC
+
+# data
+
+set_property IOSTANDARD LVCMOS33 [get_ports {dac_dat_o[*]}]
+set_property SLEW SLOW [get_ports {dac_dat_o[*]}]
+set_property DRIVE 4 [get_ports {dac_dat_o[*]}]
+# set_property IOB TRUE [get_ports {dac_dat_o[*]}]
+
+set_property PACKAGE_PIN M19 [get_ports {dac_dat_o[0]}]
+set_property PACKAGE_PIN M20 [get_ports {dac_dat_o[1]}]
+set_property PACKAGE_PIN L19 [get_ports {dac_dat_o[2]}]
+set_property PACKAGE_PIN L20 [get_ports {dac_dat_o[3]}]
+set_property PACKAGE_PIN K19 [get_ports {dac_dat_o[4]}]
+set_property PACKAGE_PIN J19 [get_ports {dac_dat_o[5]}]
+set_property PACKAGE_PIN J20 [get_ports {dac_dat_o[6]}]
+set_property PACKAGE_PIN H20 [get_ports {dac_dat_o[7]}]
+set_property PACKAGE_PIN G19 [get_ports {dac_dat_o[8]}]
+set_property PACKAGE_PIN G20 [get_ports {dac_dat_o[9]}]
+set_property PACKAGE_PIN F19 [get_ports {dac_dat_o[10]}]
+set_property PACKAGE_PIN F20 [get_ports {dac_dat_o[11]}]
+set_property PACKAGE_PIN D20 [get_ports {dac_dat_o[12]}]
+set_property PACKAGE_PIN D19 [get_ports {dac_dat_o[13]}]
+
+# control
+
+set_property IOSTANDARD LVCMOS33 [get_ports dac_*_o]
+set_property SLEW FAST [get_ports dac_*_o]
+set_property DRIVE 8 [get_ports dac_*_o]
+# set_property IOB TRUE [get_ports {dac_*_o}]
+
+set_property PACKAGE_PIN M17 [get_ports dac_wrt_o]
+set_property PACKAGE_PIN N16 [get_ports dac_sel_o]
+set_property PACKAGE_PIN M18 [get_ports dac_clk_o]
+set_property PACKAGE_PIN N15 [get_ports dac_rst_o]
+
+### PWM
+
+set_property IOSTANDARD LVCMOS18 [get_ports {dac_pwm_o[*]}]
+set_property SLEW FAST [get_ports {dac_pwm_o[*]}]
+set_property DRIVE 12 [get_ports {dac_pwm_o[*]}]
+# set_property IOB TRUE [get_ports {dac_pwm_o[*]}]
+
+set_property PACKAGE_PIN T10 [get_ports {dac_pwm_o[0]}]
+set_property PACKAGE_PIN T11 [get_ports {dac_pwm_o[1]}]
+set_property PACKAGE_PIN P15 [get_ports {dac_pwm_o[2]}]
+set_property PACKAGE_PIN U13 [get_ports {dac_pwm_o[3]}]
+
+### XADC
+
+set_property IOSTANDARD LVCMOS33 [get_ports Vp_Vn_v_p]
+set_property IOSTANDARD LVCMOS33 [get_ports Vp_Vn_v_n]
+set_property IOSTANDARD LVCMOS33 [get_ports Vaux0_v_p]
+set_property IOSTANDARD LVCMOS33 [get_ports Vaux0_v_n]
+set_property IOSTANDARD LVCMOS33 [get_ports Vaux1_v_p]
+set_property IOSTANDARD LVCMOS33 [get_ports Vaux1_v_n]
+set_property IOSTANDARD LVCMOS33 [get_ports Vaux8_v_p]
+set_property IOSTANDARD LVCMOS33 [get_ports Vaux8_v_n]
+set_property IOSTANDARD LVCMOS33 [get_ports Vaux9_v_p]
+set_property IOSTANDARD LVCMOS33 [get_ports Vaux9_v_n]
+
+set_property PACKAGE_PIN K9  [get_ports Vp_Vn_v_p]
+set_property PACKAGE_PIN L10 [get_ports Vp_Vn_v_n]
+set_property PACKAGE_PIN C20 [get_ports Vaux0_v_p]
+set_property PACKAGE_PIN B20 [get_ports Vaux0_v_n]
+set_property PACKAGE_PIN E17 [get_ports Vaux1_v_p]
+set_property PACKAGE_PIN D18 [get_ports Vaux1_v_n]
+set_property PACKAGE_PIN B19 [get_ports Vaux8_v_p]
+set_property PACKAGE_PIN A20 [get_ports Vaux8_v_n]
+set_property PACKAGE_PIN E18 [get_ports Vaux9_v_p]
+set_property PACKAGE_PIN E19 [get_ports Vaux9_v_n]
+
+### Expansion connector
+
+set_property IOSTANDARD LVCMOS33 [get_ports {exp_p_tri_io[*]}]
+set_property IOSTANDARD LVCMOS33 [get_ports {exp_n_tri_io[*]}]
+set_property SLEW FAST [get_ports {exp_p_tri_io[*]}]
+set_property SLEW FAST [get_ports {exp_n_tri_io[*]}]
+set_property DRIVE 8 [get_ports {exp_p_tri_io[*]}]
+set_property DRIVE 8 [get_ports {exp_n_tri_io[*]}]
+
+set_property PACKAGE_PIN G17 [get_ports {exp_p_tri_io[0]}]
+set_property PACKAGE_PIN G18 [get_ports {exp_n_tri_io[0]}]
+set_property PACKAGE_PIN H16 [get_ports {exp_p_tri_io[1]}]
+set_property PACKAGE_PIN H17 [get_ports {exp_n_tri_io[1]}]
+set_property PACKAGE_PIN J18 [get_ports {exp_p_tri_io[2]}]
+set_property PACKAGE_PIN H18 [get_ports {exp_n_tri_io[2]}]
+set_property PACKAGE_PIN K17 [get_ports {exp_p_tri_io[3]}]
+set_property PACKAGE_PIN K18 [get_ports {exp_n_tri_io[3]}]
+set_property PACKAGE_PIN L14 [get_ports {exp_p_tri_io[4]}]
+set_property PACKAGE_PIN L15 [get_ports {exp_n_tri_io[4]}]
+set_property PACKAGE_PIN L16 [get_ports {exp_p_tri_io[5]}]
+set_property PACKAGE_PIN L17 [get_ports {exp_n_tri_io[5]}]
+set_property PACKAGE_PIN K16 [get_ports {exp_p_tri_io[6]}]
+set_property PACKAGE_PIN J16 [get_ports {exp_n_tri_io[6]}]
+set_property PACKAGE_PIN M14 [get_ports {exp_p_tri_io[7]}]
+set_property PACKAGE_PIN M15 [get_ports {exp_n_tri_io[7]}]
+
+### SATA connector
+
+set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports daisy_p_o[*]]
+set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports daisy_n_o[*]]
+
+set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports daisy_p_i[*]]
+set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports daisy_n_i[*]]
+
+set_property PACKAGE_PIN T12 [get_ports {daisy_p_o[0]}]
+set_property PACKAGE_PIN U12 [get_ports {daisy_n_o[0]}]
+
+set_property PACKAGE_PIN U14 [get_ports {daisy_p_o[1]}]
+set_property PACKAGE_PIN U15 [get_ports {daisy_n_o[1]}]
+
+set_property PACKAGE_PIN P14 [get_ports {daisy_p_i[0]}]
+set_property PACKAGE_PIN R14 [get_ports {daisy_n_i[0]}]
+
+set_property PACKAGE_PIN N18 [get_ports {daisy_p_i[1]}]
+set_property PACKAGE_PIN P19 [get_ports {daisy_n_i[1]}]
+
+### LED
+
+set_property IOSTANDARD LVCMOS33 [get_ports {led_o[*]}]
+set_property SLEW SLOW [get_ports {led_o[*]}]
+set_property DRIVE 4 [get_ports {led_o[*]}]
+
+set_property PACKAGE_PIN F16 [get_ports {led_o[0]}]
+set_property PACKAGE_PIN F17 [get_ports {led_o[1]}]
+set_property PACKAGE_PIN G15 [get_ports {led_o[2]}]
+set_property PACKAGE_PIN H15 [get_ports {led_o[3]}]
+set_property PACKAGE_PIN K14 [get_ports {led_o[4]}]
+set_property PACKAGE_PIN G14 [get_ports {led_o[5]}]
+set_property PACKAGE_PIN J15 [get_ports {led_o[6]}]
+set_property PACKAGE_PIN J14 [get_ports {led_o[7]}]
diff --git a/cfg/red_pitaya.xml b/cfg/red_pitaya.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c48ea199e6e360542bdb68aed65988593206e6c5
--- /dev/null
+++ b/cfg/red_pitaya.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE project PUBLIC "project" "project.dtd" >
+<project version="1.0" >
+  <set param="PCW::ENET0::PERIPHERAL::ENABLE" value="1" />
+  <set param="PCW::ENET0::GRP_MDIO::ENABLE" value="1" />
+  <set param="PCW::ENET0::ENET0::IO" value="MIO 16 .. 27" />
+  <set param="PCW::ENET0::GRP_MDIO::IO" value="MIO 52 .. 53" />
+  <set param="PCW::GPIO::PERIPHERAL::ENABLE" value="1" />
+  <set param="PCW::GPIO::MIO_GPIO::ENABLE" value="1" />
+  <set param="PCW::GPIO::EMIO_GPIO::ENABLE" value="1" />
+  <set param="PCW::I2C0::PERIPHERAL::ENABLE" value="1" />
+  <set param="PCW::I2C0::I2C0::IO" value="MIO 50 .. 51" />
+  <set param="PCW::UART0::PERIPHERAL::ENABLE" value="1" />
+  <set param="PCW::UART0::UART0::IO" value="MIO 14 .. 15" />
+  <set param="PCW::UART1::PERIPHERAL::ENABLE" value="1" />
+  <set param="PCW::UART1::UART1::IO" value="MIO 8 .. 9" />
+  <set param="PCW::USB0::PERIPHERAL::ENABLE" value="1" />
+  <set param="PCW::USB0::RESET::ENABLE" value="1" />
+  <set param="PCW::USB0::RESET::IO" value="MIO 48" />
+  <set param="PCW::SD0::PERIPHERAL::ENABLE" value="1" />
+  <set param="PCW::SD0::SD0::IO" value="MIO 40 .. 45" />
+  <set param="PCW::SD0::GRP_CD::ENABLE" value="1" />
+  <set param="PCW::SD0::GRP_WP::ENABLE" value="1" />
+  <set param="PCW::SD0::GRP_CD::IO" value="MIO 46" />
+  <set param="PCW::SD0::GRP_WP::IO" value="MIO 47" />
+  <set param="PCW::SPI0::PERIPHERAL::ENABLE" value="1" />
+  <set param="PCW::SPI1::PERIPHERAL::ENABLE" value="1" />
+  <set param="PCW::SPI1::SPI1::IO" value="MIO 10 .. 15" />
+  <set param="PCW::PRESET::BANK0::VOLTAGE" value="LVCMOS 3.3V" />
+  <set param="PCW::PRESET::BANK1::VOLTAGE" value="LVCMOS 2.5V" />
+  <set param="PCW::UIPARAM::DDR::PARTNO" value="MT41J256M16 RE-125" />
+  <set param="PCW::UIPARAM::DDR::BUS_WIDTH" value="16 Bit" />
+  <set param="PCW::MIO::MIO[0]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[16]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[16]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[17]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[17]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[18]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[18]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[19]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[19]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[20]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[20]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[21]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[21]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[22]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[22]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[23]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[23]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[24]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[24]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[25]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[25]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[26]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[26]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[27]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[27]::PULLUP" value="disabled" />
+  <set param="PCW::MIO::MIO[28]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[29]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[30]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[31]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[32]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[33]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[34]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[35]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[36]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[37]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[38]::SLEW" value="fast" />
+  <set param="PCW::MIO::MIO[39]::SLEW" value="fast" />
+</project>
diff --git a/contributors.txt b/contributors.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0b2c3be1019bfde5a9640ac8e26fbcb3d5b487df
--- /dev/null
+++ b/contributors.txt
@@ -0,0 +1 @@
+L. Horacio Arnaldi <lharnaldi@gmail.com>
diff --git a/cores/axi_axis_reader_v1_0/axi_axis_reader.vhd b/cores/axi_axis_reader_v1_0/axi_axis_reader.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..74611165f93bf8364fd9ba9d6d71f6b3e6a5680d
--- /dev/null
+++ b/cores/axi_axis_reader_v1_0/axi_axis_reader.vhd
@@ -0,0 +1,77 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axi_axis_reader is
+  generic (
+    AXI_DATA_WIDTH : natural  := 32;
+    AXI_ADDR_WIDTH : natural  := 32
+);
+port (
+  -- System signals
+  aclk          : in std_logic;
+  aresetn       : in std_logic;
+  
+  -- Slave side
+  s_axi_awaddr 	: in  std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Write address
+  s_axi_awvalid	: in  std_logic; 			            -- AXI4-Lite slave: Write address valid
+  s_axi_awready	: out std_logic; 			            -- AXI4-Lite slave: Write address ready
+  s_axi_wdata	: in  std_logic_vector(AXI_DATA_WIDTH-1 downto 0);  -- AXI4-Lite slave: Write data
+  s_axi_wvalid	: in  std_logic;  				    -- AXI4-Lite slave: Write data valid
+  s_axi_wready	: out std_logic;  				    -- AXI4-Lite slave: Write data ready
+  s_axi_bresp	: out std_logic_vector(1 downto 0);   		    -- AXI4-Lite slave: Write response
+  s_axi_bvalid	: out std_logic;  				    -- AXI4-Lite slave: Write response valid
+  s_axi_bready	: in  std_logic;  				    -- AXI4-Lite slave: Write response ready
+  s_axi_araddr	: in  std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Read address
+  s_axi_arvalid	: in  std_logic; 				    -- AXI4-Lite slave: Read address valid
+  s_axi_arready	: out std_logic; 				    -- AXI4-Lite slave: Read address ready
+  s_axi_rdata	: out std_logic_vector(AXI_DATA_WIDTH-1 downto 0);  -- AXI4-Lite slave: Read data
+  s_axi_rresp	: out std_logic_vector(1 downto 0);   	            -- AXI4-Lite slave: Read data response
+  s_axi_rvalid	: out std_logic;  				    -- AXI4-Lite slave: Read data valid
+  s_axi_rready	: in  std_logic;  				    -- AXI4-Lite slave: Read data ready
+  
+  -- Slave side
+  s_axis_tready : out std_logic;
+  s_axis_tdata  : in std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+  s_axis_tvalid : in std_logic
+);
+end axi_axis_reader;
+
+architecture rtl of axi_axis_reader is
+
+signal int_rvalid_reg, int_rvalid_next : std_logic;
+signal int_rdata_reg, int_rdata_next : std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+
+begin
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then 
+    if (aresetn = '0') then
+      int_rvalid_reg <= '0';
+      int_rdata_reg <= (others => '0');
+    else
+      int_rvalid_reg <= int_rvalid_next;
+      int_rdata_reg <= int_rdata_next;
+    end if;
+    end if;
+  end process;
+  
+  int_rvalid_next <= '1' when (s_axi_arvalid = '1') else 
+                     '0' when (s_axi_rready = '1') and (int_rvalid_reg = '1') else
+                     int_rvalid_reg;  
+  
+  int_rdata_next <= s_axis_tdata when (s_axi_arvalid = '1') and (s_axis_tvalid = '1') else
+                    (others => '0') when (s_axi_arvalid = '1') and (s_axis_tvalid = '0') else
+                    int_rdata_reg;
+
+  s_axi_rresp <= (others => '0');
+  
+  s_axi_arready <= '1';
+  s_axi_rdata <= int_rdata_reg;
+  s_axi_rvalid <= int_rvalid_reg;
+  
+  s_axis_tready <= s_axi_rready and int_rvalid_reg;
+
+end rtl;
diff --git a/cores/axi_axis_reader_v1_0/core_config.tcl b/cores/axi_axis_reader_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..7b45e229ae664ae6794177679250bd90a5a8dfc4
--- /dev/null
+++ b/cores/axi_axis_reader_v1_0/core_config.tcl
@@ -0,0 +1,21 @@
+set display_name {AXI AXI4-Stream Reader}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXI_DATA_WIDTH {AXI DATA WIDTH} {Width of the AXI data bus.}
+core_parameter AXI_ADDR_WIDTH {AXI ADDR WIDTH} {Width of the AXI address bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axi]
+set_property NAME S_AXI $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS:S_AXI $parameter
diff --git a/cores/axi_axis_writer_v1_0/axi_axis_writer.vhd b/cores/axi_axis_writer_v1_0/axi_axis_writer.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..f7d0a31447673dfd8d027168eb416d0a4710036c
--- /dev/null
+++ b/cores/axi_axis_writer_v1_0/axi_axis_writer.vhd
@@ -0,0 +1,72 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axi_axis_writer is
+  generic (
+    AXI_DATA_WIDTH : natural  := 32;
+    AXI_ADDR_WIDTH : natural  := 32
+);
+port (
+  -- System signals
+  aclk : in std_logic;
+  aresetn : in std_logic;
+  
+  -- Slave side
+  s_axi_awaddr 	: in 	std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Write address
+  s_axi_awvalid	: in 	std_logic; 			              -- AXI4-Lite slave: Write address valid
+  s_axi_awready	: out std_logic; 			              -- AXI4-Lite slave: Write address ready
+  s_axi_wdata	: in 	std_logic_vector(AXI_DATA_WIDTH-1 downto 0);  -- AXI4-Lite slave: Write data
+  s_axi_wvalid	: in 	std_logic;  				      -- AXI4-Lite slave: Write data valid
+  s_axi_wready	: out std_logic;  				      -- AXI4-Lite slave: Write data ready
+  s_axi_bresp	: out std_logic_vector(1 downto 0);   		      -- AXI4-Lite slave: Write response
+  s_axi_bvalid	: out std_logic;  				      -- AXI4-Lite slave: Write response valid
+  s_axi_bready	: in 	std_logic;  				      -- AXI4-Lite slave: Write response ready
+  s_axi_araddr	: in 	std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Read address
+  s_axi_arvalid	: in 	std_logic; 				      -- AXI4-Lite slave: Read address valid
+  s_axi_arready	: out std_logic; 				      -- AXI4-Lite slave: Read address ready
+  s_axi_rdata	: out std_logic_vector(AXI_DATA_WIDTH-1 downto 0);    -- AXI4-Lite slave: Read data
+  s_axi_rresp	: out	std_logic_vector(1 downto 0);   	      -- AXI4-Lite slave: Read data response
+  s_axi_rvalid	: in 	std_logic;  				      -- AXI4-Lite slave: Read data valid
+  s_axi_rready	: in 	std_logic;  				      -- AXI4-Lite slave: Read data ready
+  
+  -- Master side
+  m_axis_tdata	: out std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+  m_axis_tvalid	: out std_logic
+);
+end axi_axis_writer;
+
+architecture rtl of axi_axis_writer is
+
+signal int_ready_reg, int_ready_next : std_logic;
+signal int_valid_reg, int_valid_next : std_logic;
+signal int_tdata_reg, int_tdata_next : std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+
+begin
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then 
+    if (aresetn = '0') then
+    	int_valid_reg <= '0';
+    else
+    	int_valid_reg <= int_valid_next;
+    end if;
+    end if;
+  end process;
+  
+  int_valid_next <= '1' when (s_axi_wvalid = '1') else 
+                    '0' when (s_axi_bready = '1') and (int_valid_reg = '1') else
+                    int_valid_reg;  
+  
+  s_axi_bresp <= (others => '0');
+  
+  s_axi_awready <= '1';
+  s_axi_wready <= '1';
+  s_axi_bvalid <= int_valid_reg;
+  
+  m_axis_tdata <= s_axi_wdata;
+  m_axis_tvalid <= s_axi_wvalid;
+  
+end rtl;
diff --git a/cores/axi_axis_writer_v1_0/core_config.tcl b/cores/axi_axis_writer_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..01731b3d2855dc09e2e64cab6b1a42453bd05049
--- /dev/null
+++ b/cores/axi_axis_writer_v1_0/core_config.tcl
@@ -0,0 +1,21 @@
+set display_name {AXI AXI4-Stream Writer}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXI_DATA_WIDTH {AXI DATA WIDTH} {Width of the AXI data bus.}
+core_parameter AXI_ADDR_WIDTH {AXI ADDR WIDTH} {Width of the AXI address bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axi]
+set_property NAME S_AXI $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXI $parameter
diff --git a/cores/axi_bram_reader_v1_0/axi_bram_reader.vhd b/cores/axi_bram_reader_v1_0/axi_bram_reader.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..c3e9ec57f5d40a578401d4300e76387620d9f36e
--- /dev/null
+++ b/cores/axi_bram_reader_v1_0/axi_bram_reader.vhd
@@ -0,0 +1,89 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axi_bram_reader is
+  generic (
+            AXI_DATA_WIDTH    : natural := 32;
+            AXI_ADDR_WIDTH    : natural := 16;
+            BRAM_ADDR_WIDTH   : natural := 10;
+            BRAM_DATA_WIDTH   : natural := 32
+          );
+  port (
+         -- System signals
+         aclk             : in std_logic;
+         aresetn          : in std_logic;
+
+         -- Slave side
+         s_axi_awaddr  : in  std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Write address
+         s_axi_awvalid : in  std_logic;                                    -- AXI4-Lite slave: Write address valid
+         s_axi_awready : out std_logic;                                    -- AXI4-Lite slave: Write address ready
+         s_axi_wdata   : in  std_logic_vector(AXI_DATA_WIDTH-1 downto 0);  -- AXI4-Lite slave: Write data
+         s_axi_wvalid  : in  std_logic;                                    -- AXI4-Lite slave: Write data valid
+         s_axi_wready  : out std_logic;                                    -- AXI4-Lite slave: Write data ready
+         s_axi_bresp   : out std_logic_vector(1 downto 0);                 -- AXI4-Lite slave: Write response
+         s_axi_bvalid  : out std_logic;                                    -- AXI4-Lite slave: Write response valid
+         s_axi_bready  : in  std_logic;                                    -- AXI4-Lite slave: Write response ready
+         s_axi_araddr  : in  std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Read address
+         s_axi_arvalid : in  std_logic;                                    -- AXI4-Lite slave: Read address valid
+         s_axi_arready : out std_logic;                                    -- AXI4-Lite slave: Read address ready
+         s_axi_rdata   : out std_logic_vector(AXI_DATA_WIDTH-1 downto 0);  -- AXI4-Lite slave: Read data
+         s_axi_rresp   : out std_logic_vector(1 downto 0);                 -- AXI4-Lite slave: Read data response
+         s_axi_rvalid  : out std_logic;                                    -- AXI4-Lite slave: Read data valid
+         s_axi_rready  : in  std_logic;                                    -- AXI4-Lite slave: Read data ready
+
+         -- BRAM port
+         bram_porta_clk : out std_logic;  
+         bram_porta_rst : out std_logic;
+         bram_porta_addr: out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+         bram_porta_rddata : in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0)
+       );
+end axi_bram_reader;
+
+architecture rtl of axi_bram_reader is
+
+  function clogb2 (value: natural) return natural is
+  variable temp    : natural := value;
+  variable ret_val : natural := 1;
+  begin
+    while temp > 1 loop
+      ret_val := ret_val + 1;
+      temp    := temp / 2;
+    end loop;
+    return ret_val;
+  end function;
+
+  constant ADDR_LSB : natural := clogb2((AXI_DATA_WIDTH/8) - 1);
+
+  signal int_rvalid_reg, int_rvalid_next : std_logic;
+
+begin
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn = '0') then
+        int_rvalid_reg <= '0';
+      else
+        int_rvalid_reg <= int_rvalid_next;
+      end if;
+    end if;
+  end process;
+
+  -- Next state logic
+  int_rvalid_next <= '1' when (s_axi_arvalid = '1') else
+                     '0' when (s_axi_rready = '1' and int_rvalid_reg = '1') else
+                     int_rvalid_reg;
+
+  s_axi_rresp <= (others => '0');
+
+  s_axi_arready <= '1';
+  s_axi_rdata <= bram_porta_rddata;
+  s_axi_rvalid <= int_rvalid_reg;
+
+  bram_porta_clk <= aclk;
+  bram_porta_rst <= not aresetn;
+  bram_porta_addr <= s_axi_araddr(ADDR_LSB+BRAM_ADDR_WIDTH-1 downto ADDR_LSB);
+
+end rtl;
diff --git a/cores/axi_bram_reader_v1_0/core_config.tcl b/cores/axi_bram_reader_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..4834efb9f01acd55f9a0922f26840603e61292e7
--- /dev/null
+++ b/cores/axi_bram_reader_v1_0/core_config.tcl
@@ -0,0 +1,36 @@
+set display_name {AXI Block RAM Reader}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXI_DATA_WIDTH {AXI DATA WIDTH} {Width of the AXI data bus.}
+core_parameter AXI_ADDR_WIDTH {AXI ADDR WIDTH} {Width of the AXI address bus.}
+core_parameter BRAM_DATA_WIDTH {BRAM DATA WIDTH} {Width of the BRAM data port.}
+core_parameter BRAM_ADDR_WIDTH {BRAM ADDR WIDTH} {Width of the BRAM address port.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axi]
+set_property NAME S_AXI $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXI $parameter
+
+set bus [ipx::add_bus_interface BRAM_PORTA $core]
+set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus
+set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus
+set_property INTERFACE_MODE master $bus
+foreach {logical physical} {
+  RST  bram_porta_rst
+  CLK  bram_porta_clk
+  ADDR bram_porta_addr
+  DOUT bram_porta_rddata
+} {
+  set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus]
+}
+
+set bus [ipx::get_bus_interfaces bram_porta_clk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE BRAM_PORTA $parameter
diff --git a/cores/axi_cfg_register_v1_0/axi_cfg_register.vhd b/cores/axi_cfg_register_v1_0/axi_cfg_register.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..0dad943ebfdc5146027895c886f3554f5fd883de
--- /dev/null
+++ b/cores/axi_cfg_register_v1_0/axi_cfg_register.vhd
@@ -0,0 +1,146 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity axi_cfg_register is
+  generic (
+  CFG_DATA_WIDTH : natural := 1024;
+  AXI_DATA_WIDTH : natural := 32;
+  AXI_ADDR_WIDTH : natural := 32
+);
+port (
+  -- System signals
+  aclk           : in std_logic;
+  aresetn        : in std_logic;
+
+	-- Configuration bits
+  cfg_data       : out std_logic_vector(CFG_DATA_WIDTH-1 downto 0);
+
+  -- Slave side
+  s_axi_awaddr   : in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Write address
+  s_axi_awvalid  : in std_logic;                                    -- AXI4-Lite slave: Write address valid
+  s_axi_awready  : out std_logic;                                   -- AXI4-Lite slave: Write address ready
+  s_axi_wdata    : in std_logic_vector(AXI_DATA_WIDTH-1 downto 0);  -- AXI4-Lite slave: Write data
+  s_axi_wstrb    : in std_logic_vector(AXI_DATA_WIDTH/8-1 downto 0);-- AXI4-Lite slave: Write strobe
+  s_axi_wvalid   : in std_logic;                                    -- AXI4-Lite slave: Write data valid
+  s_axi_wready   : out std_logic;                                   -- AXI4-Lite slave: Write data ready
+  s_axi_bresp    : out std_logic_vector(1 downto 0);                -- AXI4-Lite slave: Write response
+  s_axi_bvalid   : out std_logic;                                   -- AXI4-Lite slave: Write response valid
+  s_axi_bready   : in std_logic;                                    -- AXI4-Lite slave: Write response ready
+  s_axi_araddr   : in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Read address
+  s_axi_arvalid  : in std_logic;                                    -- AXI4-Lite slave: Read address valid
+  s_axi_arready  : out std_logic;                                   -- AXI4-Lite slave: Read address ready
+  s_axi_rdata    : out std_logic_vector(AXI_DATA_WIDTH-1 downto 0); -- AXI4-Lite slave: Read data
+  s_axi_rresp    : out std_logic_vector(1 downto 0);                -- AXI4-Lite slave: Read data response
+  s_axi_rvalid   : out std_logic;                                   -- AXI4-Lite slave: Read data valid
+  s_axi_rready   : in std_logic                                     -- AXI4-Lite slave: Read data ready
+);
+end axi_cfg_register;
+
+architecture rtl of axi_cfg_register is
+
+function clogb2 (value: natural) return natural is
+    variable temp    : natural := value;
+    variable ret_val : natural := 1; 
+  begin					
+    while temp > 1 loop
+      ret_val := ret_val + 1;
+      temp    := temp / 2;     
+    end loop;
+  	
+    return ret_val;
+  end function;
+
+function sel(cond: boolean; if_true, if_false: natural) return natural is 
+    begin 
+        if (cond = true) then 
+            return(if_true); 
+        else 
+            return(if_false); 
+        end if; 
+    end function; 
+
+  constant ADDR_LSB : natural := clogb2(AXI_DATA_WIDTH/8 - 1);
+  constant CFG_SIZE : natural := CFG_DATA_WIDTH/AXI_DATA_WIDTH;
+  constant CFG_WIDTH : natural := sel((CFG_SIZE > 1), clogb2(CFG_SIZE-1), 1);
+
+  signal int_bvalid_reg, int_bvalid_next: std_logic;
+
+  signal int_rvalid_reg, int_rvalid_next: std_logic;
+  signal int_rdata_reg, int_rdata_next: std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+
+  type int_data_mux_t is array (CFG_SIZE-1 downto 0) of std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+  signal int_data_mux: int_data_mux_t;	
+	
+  signal int_data_wire   : std_logic_vector(CFG_DATA_WIDTH-1 downto 0);
+  signal int_ce_wire     : std_logic_vector(CFG_SIZE-1 downto 0);
+  signal int_wvalid_wire : std_logic;
+  type tmp_s1_t is array (CFG_SIZE-1 downto 0) of std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+  signal tmp_s1  : tmp_s1_t;--std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+  signal reset_s : std_logic;
+
+begin
+
+  int_wvalid_wire <= s_axi_awvalid and s_axi_wvalid;
+
+  WORDS: for j in 0 to CFG_SIZE-1 generate 
+    int_data_mux(j) <= int_data_wire(j*AXI_DATA_WIDTH+AXI_DATA_WIDTH-1 downto j*AXI_DATA_WIDTH);
+    int_ce_wire(j)  <= '1' when (int_wvalid_wire = '1') and (unsigned(s_axi_awaddr(ADDR_LSB+CFG_WIDTH-1 downto ADDR_LSB)) = j) else '0';
+    BITS: for k in 0 to AXI_DATA_WIDTH-1 generate
+      tmp_s1(j)(k) <= int_ce_wire(j) and s_axi_wstrb(k/8);
+      FDRE_inst: FDRE 
+       generic map( INIT => '0')
+       port map (
+         Q => int_data_wire(j*AXI_DATA_WIDTH + k),
+         C => aclk,
+         CE => tmp_s1(j)(k),
+         R => reset_s,
+         D => s_axi_wdata(k)
+       );
+    end generate;
+  end generate;
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+    if(aresetn = '0') then
+      reset_s <= '1';
+      int_bvalid_reg <= '0';
+      int_rvalid_reg <= '0';
+      int_rdata_reg <= (others => '0');
+    else 
+      reset_s <= '0';
+      int_bvalid_reg <= int_bvalid_next;
+      int_rvalid_reg <= int_rvalid_next;
+      int_rdata_reg <= int_rdata_next;
+    end if;
+    end if;
+  end process;
+
+  int_bvalid_next <= '1' when (int_wvalid_wire = '1') else
+                     '0' when (s_axi_bready = '1') and (int_bvalid_reg = '1') else
+                     int_bvalid_reg;
+
+  int_rvalid_next <= '1' when (s_axi_arvalid = '1') else
+                     '0' when (s_axi_rready = '1') and (int_rvalid_reg = '1') else
+                     int_rvalid_reg;
+
+  int_rdata_next <= int_data_mux(to_integer(unsigned(s_axi_araddr(ADDR_LSB+CFG_WIDTH-1 downto ADDR_LSB)))) when (s_axi_arvalid = '1') else
+                    int_rdata_reg;
+
+  cfg_data <= int_data_wire;
+  s_axi_bresp <= (others => '0');
+  s_axi_rresp <= (others => '0');
+
+  s_axi_awready <= int_wvalid_wire;
+  s_axi_wready <= int_wvalid_wire;
+  s_axi_bvalid <= int_bvalid_reg;
+  s_axi_arready <= '1';
+  s_axi_rdata <= int_rdata_reg;
+  s_axi_rvalid <= int_rvalid_reg;
+
+end rtl;
diff --git a/cores/axi_cfg_register_v1_0/core_config.tcl b/cores/axi_cfg_register_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..694510dd3720c3096341d4bfb0451a5b2da20f42
--- /dev/null
+++ b/cores/axi_cfg_register_v1_0/core_config.tcl
@@ -0,0 +1,18 @@
+set display_name {AXI Configuration Register}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXI_DATA_WIDTH {AXI DATA WIDTH} {Width of the AXI data bus.}
+core_parameter AXI_ADDR_WIDTH {AXI ADDR WIDTH} {Width of the AXI address bus.}
+core_parameter CFG_DATA_WIDTH {CFG DATA WIDTH} {Width of the configuration data.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axi]
+set_property NAME S_AXI $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXI $parameter
diff --git a/cores/axi_sts_register_v1_0/axi_sts_register.vhd b/cores/axi_sts_register_v1_0/axi_sts_register.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..347df1ca4590bd2617ceb3f76d152a5f9cdd31fa
--- /dev/null
+++ b/cores/axi_sts_register_v1_0/axi_sts_register.vhd
@@ -0,0 +1,108 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity axi_sts_register is
+  generic (
+  STS_DATA_WIDTH : integer := 1024;
+  AXI_DATA_WIDTH : integer := 32;
+  AXI_ADDR_WIDTH: integer := 32
+);
+port (
+  -- System signals
+  aclk: in std_logic;
+  aresetn : in std_logic;
+
+  -- Status bits
+  sts_data : in std_logic_vector(STS_DATA_WIDTH-1 downto 0);
+
+  -- Slave side
+  s_axi_awaddr: in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Write address
+  s_axi_awvalid: in std_logic;                                   -- AXI4-Lite slave: Write address valid
+  s_axi_awready: out std_logic;                                  -- AXI4-Lite slave: Write address ready
+  s_axi_wdata: in std_logic_vector(AXI_DATA_WIDTH-1 downto 0);   -- AXI4-Lite slave: Write data
+  s_axi_wvalid: in std_logic;                                    -- AXI4-Lite slave: Write data valid
+  s_axi_wready: out std_logic;                                   -- AXI4-Lite slave: Write data ready
+  s_axi_bresp: out std_logic_vector(1 downto 0);                 -- AXI4-Lite slave: Write response
+  s_axi_bvalid: out std_logic;                                   -- AXI4-Lite slave: Write response valid
+  s_axi_bready: in std_logic;                                    -- AXI4-Lite slave: Write response ready
+  s_axi_araddr: in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Read address
+  s_axi_arvalid: in std_logic;                                   -- AXI4-Lite slave: Read address valid
+  s_axi_arready: out std_logic;                                  -- AXI4-Lite slave: Read address ready
+  s_axi_rdata: out std_logic_vector(AXI_DATA_WIDTH-1 downto 0);  -- AXI4-Lite slave: Read data
+  s_axi_rresp: out std_logic_vector(1 downto 0);                 -- AXI4-Lite slave: Read data response
+  s_axi_rvalid: out std_logic;                                   -- AXI4-Lite slave: Read data valid
+  s_axi_rready: in std_logic                                     -- AXI4-Lite slave: Read data ready
+);
+end axi_sts_register;
+
+architecture rtl of axi_sts_register is
+
+function clogb2 (value: natural) return integer is
+    variable temp    : integer := value;
+    variable ret_val : integer := 1; 
+  begin					
+    while temp > 1 loop
+      ret_val := ret_val + 1;
+      temp    := temp / 2;     
+    end loop;
+  	
+    return ret_val;
+  end function;
+
+function sel(cond: boolean; if_true, if_false: integer) return integer is 
+    begin 
+        if (cond = true) then 
+            return(if_true); 
+        else 
+            return(if_false); 
+        end if; 
+    end function; 
+
+  constant ADDR_LSB : integer := clogb2(AXI_DATA_WIDTH/8 - 1);
+  constant STS_SIZE : integer := STS_DATA_WIDTH/AXI_DATA_WIDTH;
+  constant STS_WIDTH : integer := sel((STS_SIZE > 1), clogb2(STS_SIZE-1), 1);
+
+  signal int_rvalid_reg, int_rvalid_next: std_logic;
+  signal int_rdata_reg, int_rdata_next: std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+
+  type int_data_mux_t is array (STS_SIZE-1 downto 0) of std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+  signal int_data_mux: int_data_mux_t;	
+
+begin
+
+  WORDS: for j in 0 to STS_SIZE-1 generate 
+     int_data_mux(j) <= sts_data(j*AXI_DATA_WIDTH+AXI_DATA_WIDTH-1 downto j*AXI_DATA_WIDTH);
+  end generate;
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+    if(aresetn = '0') then
+      int_rvalid_reg <= '0';
+      int_rdata_reg <= (others => '0');
+    else
+      int_rvalid_reg <= int_rvalid_next;
+      int_rdata_reg <= int_rdata_next;
+    end if;
+    end if;
+  end process;
+
+  int_rvalid_next <= '1' when (s_axi_arvalid = '1') else
+                     '0' when (s_axi_rready = '1') and (int_rvalid_reg = '1') else
+                     int_rvalid_reg;
+
+  int_rdata_next <= int_data_mux(to_integer(unsigned(s_axi_araddr(ADDR_LSB+STS_WIDTH-1 downto ADDR_LSB)))) when (s_axi_arvalid = '1') else
+                    int_rdata_reg;
+
+  s_axi_rresp <= (others => '0');
+
+  s_axi_arready <= '1';
+  s_axi_rdata <= int_rdata_reg;
+  s_axi_rvalid <= int_rvalid_reg;
+
+end rtl;
diff --git a/cores/axi_sts_register_v1_0/core_config.tcl b/cores/axi_sts_register_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..048310cd9bcb8abb4565fe3c816d0c7e8e62412d
--- /dev/null
+++ b/cores/axi_sts_register_v1_0/core_config.tcl
@@ -0,0 +1,18 @@
+set display_name {AXI Status Register}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXI_DATA_WIDTH {AXI DATA WIDTH} {Width of the AXI data bus.}
+core_parameter AXI_ADDR_WIDTH {AXI ADDR WIDTH} {Width of the AXI address bus.}
+core_parameter STS_DATA_WIDTH {STS DATA WIDTH} {Width of the status data.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axi]
+set_property NAME S_AXI $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXI $parameter
diff --git a/cores/axi_time_trig_gen_v1_0/axi_cfg_register.vhd b/cores/axi_time_trig_gen_v1_0/axi_cfg_register.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..b87919211c45eb512ac9b8cb89cb0d9546239824
--- /dev/null
+++ b/cores/axi_time_trig_gen_v1_0/axi_cfg_register.vhd
@@ -0,0 +1,146 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity axi_cfg_register is
+  generic (
+  CFG_DATA_WIDTH : natural := 1024;
+  AXI_DATA_WIDTH : natural := 32;
+  AXI_ADDR_WIDTH : natural := 32
+);
+port (
+  -- System signals
+  s_axi_aclk     : in std_logic;
+  s_axi_aresetn  : in std_logic;
+
+	-- Configuration bits
+  cfg_data       : out std_logic_vector(CFG_DATA_WIDTH-1 downto 0);
+
+  -- Slave side
+  s_axi_awaddr   : in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Write address
+  s_axi_awvalid  : in std_logic;                                    -- AXI4-Lite slave: Write address valid
+  s_axi_awready  : out std_logic;                                   -- AXI4-Lite slave: Write address ready
+  s_axi_wdata    : in std_logic_vector(AXI_DATA_WIDTH-1 downto 0);  -- AXI4-Lite slave: Write data
+  s_axi_wstrb    : in std_logic_vector(AXI_DATA_WIDTH/8-1 downto 0);-- AXI4-Lite slave: Write strobe
+  s_axi_wvalid   : in std_logic;                                    -- AXI4-Lite slave: Write data valid
+  s_axi_wready   : out std_logic;                                   -- AXI4-Lite slave: Write data ready
+  s_axi_bresp    : out std_logic_vector(1 downto 0);                -- AXI4-Lite slave: Write response
+  s_axi_bvalid   : out std_logic;                                   -- AXI4-Lite slave: Write response valid
+  s_axi_bready   : in std_logic;                                    -- AXI4-Lite slave: Write response ready
+  s_axi_araddr   : in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  -- AXI4-Lite slave: Read address
+  s_axi_arvalid  : in std_logic;                                    -- AXI4-Lite slave: Read address valid
+  s_axi_arready  : out std_logic;                                   -- AXI4-Lite slave: Read address ready
+  s_axi_rdata    : out std_logic_vector(AXI_DATA_WIDTH-1 downto 0); -- AXI4-Lite slave: Read data
+  s_axi_rresp    : out std_logic_vector(1 downto 0);                -- AXI4-Lite slave: Read data response
+  s_axi_rvalid   : out std_logic;                                   -- AXI4-Lite slave: Read data valid
+  s_axi_rready   : in std_logic                                     -- AXI4-Lite slave: Read data ready
+);
+end axi_cfg_register;
+
+architecture rtl of axi_cfg_register is
+
+function clogb2 (value: natural) return natural is
+    variable temp    : natural := value;
+    variable ret_val : natural := 1; 
+  begin					
+    while temp > 1 loop
+      ret_val := ret_val + 1;
+      temp    := temp / 2;     
+    end loop;
+  	
+    return ret_val;
+  end function;
+
+function sel(cond: boolean; if_true, if_false: natural) return natural is 
+    begin 
+        if (cond = true) then 
+            return(if_true); 
+        else 
+            return(if_false); 
+        end if; 
+    end function; 
+
+  constant ADDR_LSB : natural := clogb2(AXI_DATA_WIDTH/8 - 1);
+  constant CFG_SIZE : natural := CFG_DATA_WIDTH/AXI_DATA_WIDTH;
+  constant CFG_WIDTH : natural := sel((CFG_SIZE > 1), clogb2(CFG_SIZE-1), 1);
+
+  signal int_bvalid_reg, int_bvalid_next: std_logic;
+
+  signal int_rvalid_reg, int_rvalid_next: std_logic;
+  signal int_rdata_reg, int_rdata_next: std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+
+  type int_data_mux_t is array (CFG_SIZE-1 downto 0) of std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+  signal int_data_mux: int_data_mux_t;	
+	
+  signal int_data_wire   : std_logic_vector(CFG_DATA_WIDTH-1 downto 0);
+  signal int_ce_wire     : std_logic_vector(CFG_SIZE-1 downto 0);
+  signal int_wvalid_wire : std_logic;
+  type tmp_s1_t is array (CFG_SIZE-1 downto 0) of std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+  signal tmp_s1  : tmp_s1_t;--std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+  signal reset_s : std_logic;
+
+begin
+
+  int_wvalid_wire <= s_axi_awvalid and s_axi_wvalid;
+
+  WORDS: for j in 0 to CFG_SIZE-1 generate 
+    int_data_mux(j) <= int_data_wire(j*AXI_DATA_WIDTH+AXI_DATA_WIDTH-1 downto j*AXI_DATA_WIDTH);
+    int_ce_wire(j)  <= '1' when (int_wvalid_wire = '1') and (unsigned(s_axi_awaddr(ADDR_LSB+CFG_WIDTH-1 downto ADDR_LSB)) = j) else '0';
+    BITS: for k in 0 to AXI_DATA_WIDTH-1 generate
+      tmp_s1(j)(k) <= int_ce_wire(j) and s_axi_wstrb(k/8);
+      FDRE_inst: FDRE 
+       generic map( INIT => '0')
+       port map (
+         Q => int_data_wire(j*AXI_DATA_WIDTH + k),
+         C => s_axi_aclk,
+         CE => tmp_s1(j)(k),
+         R => reset_s,
+         D => s_axi_wdata(k)
+       );
+    end generate;
+  end generate;
+
+  process(s_axi_aclk)
+  begin
+    if rising_edge(s_axi_aclk) then
+    if(s_axi_aresetn = '0') then
+      reset_s <= '1';
+      int_bvalid_reg <= '0';
+      int_rvalid_reg <= '0';
+      int_rdata_reg <= (others => '0');
+    else 
+      reset_s <= '0';
+      int_bvalid_reg <= int_bvalid_next;
+      int_rvalid_reg <= int_rvalid_next;
+      int_rdata_reg <= int_rdata_next;
+    end if;
+    end if;
+  end process;
+
+  int_bvalid_next <= '1' when (int_wvalid_wire = '1') else
+                     '0' when (s_axi_bready = '1') and (int_bvalid_reg = '1') else
+                     int_bvalid_reg;
+
+  int_rvalid_next <= '1' when (s_axi_arvalid = '1') else
+                     '0' when (s_axi_rready = '1') and (int_rvalid_reg = '1') else
+                     int_rvalid_reg;
+
+  int_rdata_next <= int_data_mux(to_integer(unsigned(s_axi_araddr(ADDR_LSB+CFG_WIDTH-1 downto ADDR_LSB)))) when (s_axi_arvalid = '1') else
+                    int_rdata_reg;
+
+  cfg_data <= int_data_wire;
+  s_axi_bresp <= (others => '0');
+  s_axi_rresp <= (others => '0');
+
+  s_axi_awready <= int_wvalid_wire;
+  s_axi_wready <= int_wvalid_wire;
+  s_axi_bvalid <= int_bvalid_reg;
+  s_axi_arready <= '1';
+  s_axi_rdata <= int_rdata_reg;
+  s_axi_rvalid <= int_rvalid_reg;
+
+end rtl;
diff --git a/cores/axi_time_trig_gen_v1_0/axi_time_trig_gen.vhd b/cores/axi_time_trig_gen_v1_0/axi_time_trig_gen.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..00c91799a7e0fe0f39693aefc709523632c16a6d
--- /dev/null
+++ b/cores/axi_time_trig_gen_v1_0/axi_time_trig_gen.vhd
@@ -0,0 +1,125 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axi_time_trig_gen is
+  generic (
+            CFG_DATA_WIDTH  : natural := 64;
+            AXI_DATA_WIDTH  : natural := 32;
+            AXI_ADDR_WIDTH  : natural := 32
+          );
+  port (
+         -- AXI INTERFACE CFG REGISTER
+         s_axi_aclk     : in std_logic;
+         s_axi_aresetn  : in std_logic;
+         s_axi_awaddr   : in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);  
+         s_axi_awvalid  : in std_logic;                                   
+         s_axi_awready  : out std_logic;                                 
+         s_axi_wdata    : in std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+         s_axi_wstrb    : in std_logic_vector(AXI_DATA_WIDTH/8-1 downto 0);
+         s_axi_wvalid   : in std_logic;                                   
+         s_axi_wready   : out std_logic;                                 
+         s_axi_bresp    : out std_logic_vector(1 downto 0);             
+         s_axi_bvalid   : out std_logic;                               
+         s_axi_bready   : in std_logic;                               
+         s_axi_araddr   : in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);
+         s_axi_arvalid  : in std_logic;                                  
+         s_axi_arready  : out std_logic;                                
+         s_axi_rdata    : out std_logic_vector(AXI_DATA_WIDTH-1 downto 0); 
+         s_axi_rresp    : out std_logic_vector(1 downto 0);               
+         s_axi_rvalid   : out std_logic;                                 
+         s_axi_rready   : in std_logic;                
+
+         data_clk       : in std_logic;
+         trig_o         : out std_logic
+    );
+end axi_time_trig_gen;
+
+architecture rtl of axi_time_trig_gen is
+
+  signal cntr_reg, cntr_next : std_logic_vector(CFG_DATA_WIDTH-1 downto 0);
+  signal trig_reg, trig_next : std_logic;
+  signal comp_reg, comp_next : std_logic;
+  signal cfg_data_s          : std_logic_vector(CFG_DATA_WIDTH-1 downto 0);
+  signal cfg_data_s_sync     : std_logic_vector(CFG_DATA_WIDTH-1 downto 0);
+  signal cfg_data_comp       : std_logic_vector(32-1 downto 0);
+  signal rstn_s              : std_logic;
+
+begin
+
+  --AXI interface cfg register
+  cfg_i : entity work.axi_cfg_register
+  generic map(
+               CFG_DATA_WIDTH => CFG_DATA_WIDTH,
+               AXI_DATA_WIDTH => AXI_DATA_WIDTH,
+               AXI_ADDR_WIDTH => AXI_ADDR_WIDTH
+             )
+  port map(
+            s_axi_aclk    => s_axi_aclk,   
+            s_axi_aresetn => s_axi_aresetn,
+            s_axi_awaddr  => s_axi_awaddr, 
+            s_axi_awvalid => s_axi_awvalid,
+            s_axi_awready => s_axi_awready,
+            s_axi_wdata   => s_axi_wdata,  
+            s_axi_wstrb   => s_axi_wstrb,  
+            s_axi_wvalid  => s_axi_wvalid, 
+            s_axi_wready  => s_axi_wready, 
+            s_axi_bresp   => s_axi_bresp,  
+            s_axi_bvalid  => s_axi_bvalid, 
+            s_axi_bready  => s_axi_bready, 
+            s_axi_araddr  => s_axi_araddr, 
+            s_axi_arvalid => s_axi_arvalid,
+            s_axi_arready => s_axi_arready,
+            s_axi_rdata   => s_axi_rdata,  
+            s_axi_rresp   => s_axi_rresp,  
+            s_axi_rvalid  => s_axi_rvalid, 
+            s_axi_rready  => s_axi_rready, 
+            cfg_data      => cfg_data_s
+          );
+
+  -- synchronizer 0 from PS to PL clk -> PL
+  sync0_i: entity work.shift_register
+  generic map(
+           SR_WIDTH => CFG_DATA_WIDTH,
+           SR_DEPTH => 2
+         )
+  port map
+  (
+         aclk    => data_clk,
+         aresetn => '1',
+         en      => '1',
+         data_i  => cfg_data_s,
+         data_o  => cfg_data_s_sync
+         );
+
+  rstn_s        <= cfg_data_s_sync(32);
+  cfg_data_comp <= cfg_data_s_sync(31 downto 0);
+
+ process(data_clk)
+  begin
+    if rising_edge(data_clk) then
+      if (rstn_s = '0') then
+        cntr_reg <= (others => '0');
+        trig_reg <= '0';
+        comp_reg <= '0';
+      else
+        cntr_reg <= cntr_next;
+        trig_reg <= trig_next;
+        comp_reg <= comp_next;
+      end if;
+    end if;
+  end process;
+  
+  comp_next <= '0' when (unsigned(cntr_reg) = unsigned(cfg_data_comp)-1) else 
+               '1';
+
+  cntr_next <= std_logic_vector(unsigned(cntr_reg) + 1) when (comp_reg = '1') else
+               (others => '0') when (comp_reg = '0') else --reset
+               cntr_reg;
+
+  trig_next <= '1' when (unsigned(cntr_reg) = unsigned(cfg_data_comp)-1) else 
+               '0';
+ 
+  trig_o    <= trig_reg;
+
+end rtl;
diff --git a/cores/axi_time_trig_gen_v1_0/core_config.tcl b/cores/axi_time_trig_gen_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..78ba88feccef5433d5073e923283d40f6447a1fe
--- /dev/null
+++ b/cores/axi_time_trig_gen_v1_0/core_config.tcl
@@ -0,0 +1,18 @@
+set display_name {AXI Time Trigger Generator}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXI_DATA_WIDTH {AXI DATA WIDTH} {Width of the AXI data bus.}
+core_parameter AXI_ADDR_WIDTH {AXI ADDR WIDTH} {Width of the AXI address bus.}
+core_parameter CFG_DATA_WIDTH {CFG DATA WIDTH} {Width of the configuration data.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axi]
+set_property NAME S_AXI $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces s_axi_aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXI $parameter
diff --git a/cores/axi_time_trig_gen_v1_0/shift_reg.vhd b/cores/axi_time_trig_gen_v1_0/shift_reg.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..39f9b35e69ecab2fd2b35f8152b258c7dd3426cd
--- /dev/null
+++ b/cores/axi_time_trig_gen_v1_0/shift_reg.vhd
@@ -0,0 +1,40 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity shift_register is
+  generic( 
+           SR_WIDTH: integer := 32;
+           SR_DEPTH: integer := 2
+         );
+  port ( 
+         aclk   : in  std_logic;
+         aresetn: in  std_logic;
+         en     : in  std_logic;
+         data_i : in  std_logic_vector(SR_WIDTH-1 downto 0);
+         data_o : out std_logic_vector(SR_WIDTH-1 downto 0));
+end shift_register;
+
+architecture rtl of shift_register is
+  type fifo_t is array (SR_DEPTH-1 downto 0) of std_logic_vector(SR_WIDTH-1 downto 0);
+  signal fifo_s: fifo_t := (others =>(others => '0'));
+
+begin
+  shift: process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if aresetn = '0' then
+        fifo_s <= (others => (others => '0'));
+      else
+        if en = '1' then
+          fifo_s(0) <= data_i;
+          for i in 0 to SR_DEPTH-2 loop
+            fifo_s(i+1) <= fifo_s(i);
+          end loop;
+        end if;
+      end if;
+    end if;
+  end process;
+  data_o <= fifo_s(SR_DEPTH-1);
+
+end rtl;
diff --git a/cores/axis_avgr16bits_v1_0/asym_ram_sdp_write_wider.vhd b/cores/axis_avgr16bits_v1_0/asym_ram_sdp_write_wider.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..9292f4dd36155f80b9fb244c4a971629804e1328
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/asym_ram_sdp_write_wider.vhd
@@ -0,0 +1,110 @@
+-- Asymmetric port RAM
+-- Write Wider than Read
+-- modified from asym_ram_sdp_write_wider.vhd
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity asym_ram_sdp_write_wider is
+  generic(
+           WIDTHA     : integer := 4;
+           SIZEA      : integer := 1024;
+           ADDRWIDTHA : integer := 10;
+           WIDTHB     : integer := 16;
+           SIZEB      : integer := 256;
+           ADDRWIDTHB : integer := 8
+         );
+
+  port(
+        clkA  : in  std_logic;
+        rstA  : in  std_logic;
+        enA   : in  std_logic;
+        addrA : in  std_logic_vector(ADDRWIDTHA - 1 downto 0);
+        doA   : out std_logic_vector(WIDTHA - 1 downto 0);
+        clkB  : in  std_logic;
+        --rstB  : in  std_logic;
+        --enB   : in  std_logic;
+        weB   : in  std_logic;
+        addrB : in  std_logic_vector(ADDRWIDTHB - 1 downto 0);
+        diB   : in  std_logic_vector(WIDTHB - 1 downto 0)
+      );
+
+end asym_ram_sdp_write_wider;
+
+architecture behavioral of asym_ram_sdp_write_wider is
+  function max(L, R : INTEGER) return INTEGER is
+  begin
+    if L > R then
+      return L;
+    else
+      return R;
+    end if;
+  end;
+
+  function min(L, R : INTEGER) return INTEGER is
+  begin
+    if L < R then
+      return L;
+    else
+      return R;
+    end if;
+  end;
+
+  function log2(val : INTEGER) return natural is
+    variable res : natural;
+  begin
+    for i in 0 to 31 loop
+      if (val <= (2 ** i)) then
+        res := i;
+        exit;
+      end if;
+    end loop;
+    return res;
+  end function Log2;
+
+  constant minWIDTH : integer := min(WIDTHA, WIDTHB);
+  constant maxWIDTH : integer := max(WIDTHA, WIDTHB);
+  constant maxSIZE  : integer := max(SIZEA, SIZEB);
+  constant RATIO    : integer := maxWIDTH / minWIDTH;
+
+  -- An asymmetric RAM is modeled in a similar way as a symmetric RAM, with an
+  -- array of array object. Its aspect ratio corresponds to the port with the
+  -- lower data width (larger depth)
+  type ramType is array (0 to maxSIZE - 1) of std_logic_vector(minWIDTH - 1 downto 0);
+
+  signal my_ram : ramType := (others => (others => '0'));
+
+  signal a_reg, a_next  : std_logic_vector(WIDTHA - 1 downto 0) := (others => '0');
+
+begin
+
+  -- read process
+  process(clkA)
+  begin
+    if rising_edge(clkA) then
+      if rstA = '1' then
+        a_reg <= (others => '0');
+      else
+        a_reg <= a_next;
+      end if;
+    end if;
+  end process;
+  --next state logic
+  a_next <= my_ram(to_integer(unsigned(addrA))) when enA = '1' else a_reg;
+  doA <= a_reg;
+
+  -- Write process
+  process(clkB)
+  begin
+    if rising_edge(clkB) then
+      for i in 0 to RATIO - 1 loop
+          if weB = '1' then
+            my_ram(to_integer(unsigned(addrB) & to_unsigned(i, log2(RATIO)))) <= diB((i + 1) * minWIDTH - 1 downto i * minWIDTH);
+          end if;
+      end loop;
+    end if;
+  end process;
+
+end behavioral;
diff --git a/cores/axis_avgr16bits_v1_0/avg_ntoone.vhd b/cores/axis_avgr16bits_v1_0/avg_ntoone.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..9fe4e5aeab0aa5216150a4b83b0d94057becb682
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/avg_ntoone.vhd
@@ -0,0 +1,253 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity avg_ntoone is
+  generic (
+            I_DWIDTH   : natural := 128; -- ADC data width x8
+            O_DWIDTH   : natural := 16;  -- AXI data width
+            ADC_DWIDTH : natural := 16;  -- ADC data width
+            MEM_AWIDTH : natural := 10;  --
+            MEM_DEPTH  : natural := 1024 -- Max 2**16
+          );
+  port (
+         -- Averager specific ports
+         start_i        : in std_logic;
+         send_i         : in std_logic;
+         trig_i         : in std_logic;
+         done_o         : out std_logic;
+         --state_mon      : out std_logic_vector(3 downto 0);
+         --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW
+         en_i           : in std_logic;
+         naverages_i    : in std_logic_vector(O_DWIDTH-1 downto 0);
+         nsamples_i     : in std_logic_vector(O_DWIDTH-1 downto 0);
+
+         --avg_o          : out std_logic_vector(O_DWIDTH-1 downto 0);
+
+         s_axis_cfg_aclk    : in std_logic;
+         s_axis_cfg_aresetn : in std_logic;
+
+         -- Slave side
+         s_axis_aclk    : in std_logic;
+         s_axis_aresetn : in std_logic;
+         s_axis_tready  : out std_logic;
+         s_axis_tvalid  : in std_logic;
+         s_axis_tdata   : in std_logic_vector(I_DWIDTH-1 downto 0);
+
+         -- Master side
+         m_axis_aclk    : in std_logic;
+         m_axis_aresetn : in std_logic;
+         m_axis_tready  : in std_logic;
+         m_axis_tdata   : out std_logic_vector(O_DWIDTH-1 downto 0);
+         m_axis_tvalid  : out std_logic;
+         m_axis_tlast   : out std_logic;
+         m_axis_tkeep   : out std_logic_vector(2-1 downto 0)
+       );
+end avg_ntoone;
+
+architecture rtl of avg_ntoone is
+
+  function log2c(n: integer) return integer is
+    variable m, p: integer;
+  begin
+    m := 0;
+    p := 1;
+    while p < n loop
+      m := m + 1;
+      p := p * 2;
+    end loop;
+    return m;
+  end log2c;
+
+  constant RATIO : natural := I_DWIDTH/ADC_DWIDTH;
+
+  type state_t is (
+  ST_IDLE,
+  ST_WAIT_TRIG,
+  ST_AVG_N1,
+  ST_WRITE_AVG,
+  ST_FINISH
+);
+signal state_reg, state_next      : state_t;
+
+signal tdp_wea     : std_logic;
+signal tdp_addra_reg, tdp_addra_next : unsigned(MEM_AWIDTH-1 downto 0);
+signal tdp_dia     : std_logic_vector(ADC_DWIDTH-1 downto 0);
+signal tdp_doa     : std_logic_vector(ADC_DWIDTH-1 downto 0);
+signal data_reg, data_next       : std_logic_vector(I_DWIDTH-1 downto 0);
+signal samples_reg, samples_next : unsigned(ADC_DWIDTH-1 downto 0);
+
+signal done_s, tready_s : std_logic;
+signal avg_reg, avg_next: unsigned(ADC_DWIDTH-1 downto 0);
+signal restart_s, restart_os : std_logic;
+
+signal bram_clk  : std_logic;
+signal bram_rst  : std_logic;
+signal bram_en   : std_logic;
+signal bram_addr : std_logic_vector(MEM_AWIDTH-1 downto 0);
+signal bram_rddata : std_logic_vector(O_DWIDTH-1 downto 0);
+
+begin
+
+  s_axis_tready <= tready_s;
+  --avg_o         <= std_logic_vector(avg_reg);
+  done_o        <= done_s;
+
+  -- TDP RAM
+  tdp_ram_i : entity work.tdp_ram_pip
+  generic map(
+               AWIDTH       => MEM_AWIDTH,
+               DWIDTH       => ADC_DWIDTH
+             )
+  port map(
+            clka  => s_axis_aclk,
+            wea   => tdp_wea,
+            addra => std_logic_vector(tdp_addra_reg),
+            dia   => tdp_dia,
+
+            clkb  => bram_clk,
+            rstb  => bram_rst,
+            enb   => bram_en,
+            addrb => bram_addr,
+            dob   => bram_rddata
+          );
+
+  process(s_axis_aclk)
+  begin
+    if rising_edge(s_axis_aclk) then
+      if (s_axis_aresetn = '0') then
+        state_reg     <= ST_IDLE;
+        tdp_addra_reg <= (others => '0');
+        data_reg      <= (others => '0');
+        samples_reg   <= (others => '0');
+        avg_reg       <= (others => '0');
+      else
+        state_reg     <= state_next;
+        tdp_addra_reg <= tdp_addra_next;
+        data_reg      <= data_next;
+        samples_reg   <= samples_next;
+        avg_reg       <= avg_next;
+      end if;
+    end if;
+  end process;
+
+  --Next state logic
+  process(state_reg, en_i, start_i, trig_i, nsamples_i,
+    naverages_i, tdp_addra_reg, tdp_dia, data_reg, samples_reg,
+    s_axis_tvalid, s_axis_tdata, avg_reg, m_axis_tready, restart_os)
+    variable dinbv : std_logic_vector(ADC_DWIDTH-1 downto 0);
+  begin
+    state_next    <= state_reg;
+    tdp_wea       <= '0';
+    tdp_addra_next<= tdp_addra_reg;
+    data_next     <= data_reg;
+    samples_next  <= samples_reg;
+    tdp_dia       <= (others => '0'); 
+    tready_s      <= '0';
+    avg_next      <= avg_reg;
+    done_s        <= '0';
+
+    case state_reg is
+      when ST_IDLE => -- Start
+        --state_mon      <= "0000"; --state mon
+        samples_next   <= (others => '0');
+        tdp_addra_next <= (others => '0');
+        avg_next       <= (others => '0');
+        data_next      <= (others => '0');
+        if en_i = '1' and start_i = '1' then
+          state_next  <= ST_WAIT_TRIG;
+        else
+          state_next  <= ST_IDLE;
+        end if;
+
+      when ST_WAIT_TRIG => -- Wait for trigger
+        --state_mon <= "0001"; --state mon
+        if(trig_i = '1') then
+          state_next    <= ST_AVG_N1;
+        else
+          state_next <= ST_WAIT_TRIG;
+        end if;
+
+      when ST_AVG_N1 => 
+        --state_mon <= "0010"; 
+        if (s_axis_tvalid = '1') then
+        tready_s <= '1';
+        samples_next <= samples_reg + 1;
+        ASSIGN_N: for I in 0 to RATIO-1 loop
+          data_next(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-(I+1)*ADC_DWIDTH) <=
+          std_logic_vector(signed(data_reg(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-(I+1)*ADC_DWIDTH)) +
+          resize(signed(s_axis_tdata(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-((I+1)*ADC_DWIDTH)+4)),ADC_DWIDTH));
+        end loop;
+        if(samples_reg = (unsigned(nsamples_i)/RATIO)-1) then
+          samples_next <= (others => '0');
+          state_next  <= ST_WRITE_AVG;
+        end if;
+      end if;
+
+      when ST_WRITE_AVG => 
+        --state_mon <= "0011"; 
+        dinbv := (others => '0');
+        ASSIGN_AVG1: for K in 0 to RATIO-1 loop
+          dinbv := std_logic_vector(signed(dinbv) + signed(data_reg(I_DWIDTH-1-K*ADC_DWIDTH downto I_DWIDTH-(K+1)*ADC_DWIDTH)));
+        end loop;
+        tdp_dia <= dinbv;
+        tdp_wea <= '1';
+        data_next <= (others => '0');
+        tdp_addra_next <= tdp_addra_reg + 1;
+        avg_next <= avg_reg + 1;
+        if (avg_reg = unsigned(naverages_i)-1) then
+          state_next <= ST_FINISH;
+        else
+          state_next <= ST_WAIT_TRIG;
+        end if;
+
+      when ST_FINISH => 
+        --state_mon <= "0100"; 
+        done_s    <= '1';
+        if restart_os = '1' then
+          state_next <= ST_IDLE;
+        end if;
+
+    end case;
+  end process;
+
+  --lets synchronize the restart signal
+  os_restart_nt: entity work.edge_det
+  port map(
+            aclk     => s_axis_aclk,
+            aresetn  => s_axis_aresetn,
+            sig_i    => restart_s,
+            sig_o    => restart_os
+          );
+
+  reader_i: entity work.bram_reader 
+  generic map(
+               MEM_DEPTH   => MEM_DEPTH,
+               MEM_AWIDTH  => MEM_AWIDTH,
+               AXIS_DWIDTH => O_DWIDTH
+             )
+  port map(
+
+            cfg_data_i     => naverages_i,
+            --sts_data_o     => open,
+            done_i         => done_s,
+            send_i         => send_i,
+            restart_o      => restart_s,
+
+         -- Master side
+            aclk           => m_axis_aclk,
+            aresetn        => m_axis_aresetn,
+            m_axis_tready  => m_axis_tready,
+            m_axis_tdata   => m_axis_tdata,
+            m_axis_tvalid  => m_axis_tvalid,
+            m_axis_tlast   => m_axis_tlast, 
+            m_axis_tkeep   => m_axis_tkeep, 
+         -- BRAM port
+            bram_clk       => bram_clk,   
+            bram_rst       => bram_rst,
+            bram_en        => bram_en,
+            bram_addr      => bram_addr,
+            bram_rddata    => bram_rddata
+          );
+
+end rtl;
diff --git a/cores/axis_avgr16bits_v1_0/avg_scope.vhd b/cores/axis_avgr16bits_v1_0/avg_scope.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..3ff46ca0aac0b7b1515fab3deaf62cf696d7e96a
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/avg_scope.vhd
@@ -0,0 +1,362 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity avg_scope is
+  generic (
+            I_DWIDTH   : natural := 128; -- ADC data width x8
+            O_DWIDTH   : natural := 16;  -- AXI data width
+            ADC_DWIDTH : natural := 16;  -- ADC data width
+            MEM_AWIDTH : natural := 10;  --
+            MEM_DEPTH  : natural := 1024 -- Max 2**16
+          );
+  port (
+         -- Averager specific ports
+         start_i        : in std_logic;
+         send_i         : in std_logic;
+         trig_i         : in std_logic;
+         done_o         : out std_logic;
+         --state_mon      : out std_logic_vector(3 downto 0);
+         --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW
+         en_i           : in std_logic;
+         naverages_i    : in std_logic_vector(O_DWIDTH-1 downto 0);
+         nsamples_i     : in std_logic_vector(O_DWIDTH-1 downto 0);
+
+         --bram_en_o      : out std_logic;
+         --bram_addr_o    : out std_logic_vector(MEM_AWIDTH-1 downto 0);
+         --bram_rddata_o  : out std_logic_vector(O_DWIDTH-1 downto 0);
+         --bram_en_oo      : out std_logic;
+         --bram_addr_oo    : out std_logic_vector(MEM_AWIDTH-1 downto 0);
+         --bram_rddata_oo  : out std_logic_vector(O_DWIDTH-1 downto 0);
+         --avg_o          : out std_logic_vector(O_DWIDTH-1 downto 0);
+
+         --tdp_addra_o    : out std_logic_vector(11-1 downto 0);
+         --tdp_addrb_o    : out std_logic_vector(11-1 downto 0);
+
+         s_axis_cfg_aclk    : in std_logic;
+         s_axis_cfg_aresetn : in std_logic;
+
+         -- Slave side
+         s_axis_aclk    : in std_logic;
+         s_axis_aresetn : in std_logic;
+         s_axis_tready  : out std_logic;
+         s_axis_tvalid  : in std_logic;
+         s_axis_tdata   : in std_logic_vector(I_DWIDTH-1 downto 0);
+
+         -- Master side
+         m_axis_aclk    : in std_logic;
+         m_axis_aresetn : in std_logic;
+         m_axis_tready  : in std_logic;
+         m_axis_tdata   : out std_logic_vector(O_DWIDTH-1 downto 0);
+         m_axis_tvalid  : out std_logic;
+         m_axis_tlast   : out std_logic;
+         m_axis_tkeep   : out std_logic_vector(2-1 downto 0)
+       );
+end avg_scope;
+
+architecture rtl of avg_scope is
+
+  function log2c(n: integer) return integer is
+    variable m, p: integer;
+  begin
+    m := 0;
+    p := 1;
+    while p < n loop
+      m := m + 1;
+      p := p * 2;
+    end loop;
+    return m;
+  end log2c;
+
+  constant RATIO : natural := I_DWIDTH/ADC_DWIDTH;
+
+  type state_t is (
+  ST_IDLE,
+  ST_WAIT_TRIG,
+  ST_EN_TDPB,
+  ST_AVG_SCOPE,
+  ST_FINISH,
+  ST_WR_ZEROS
+);
+signal state_reg, state_next      : state_t;
+--signal state_mon_reg, state_mon_next : std_logic_vector(3 downto 0);
+
+signal rstb_s   : std_logic;
+signal tdp_wea  : std_logic;
+signal tdp_addra_reg, tdp_addra_next : unsigned(log2c(MEM_DEPTH/RATIO)-1 downto 0);
+signal tdp_dia     : std_logic_vector(I_DWIDTH-1 downto 0);
+signal tdp_enb  : std_logic;
+signal tdp_addrb_reg, tdp_addrb_next : unsigned(log2c(MEM_DEPTH/RATIO)-1 downto 0);
+signal tdp_doa, tdp_dob              : std_logic_vector(I_DWIDTH-1 downto 0);
+signal addrb_s                       : std_logic_vector(log2c(MEM_DEPTH/RATIO)-1 downto 0);
+
+signal asy_rsta  : std_logic;
+signal asy_ena   : std_logic;
+signal asy_enb   : std_logic;
+signal asy_web   : std_logic;
+signal asy_doa   : std_logic_vector(ADC_DWIDTH-1 downto 0);
+
+signal done_s, tready_s : std_logic;
+signal avg_reg, avg_next: unsigned(ADC_DWIDTH-1 downto 0);
+signal restart_s, restart_os : std_logic;
+
+signal bram_clk  : std_logic;
+signal bram_rst  : std_logic;
+signal bram_en   : std_logic;
+signal bram_addr : std_logic_vector(MEM_AWIDTH-1 downto 0);
+signal bram_rddata : std_logic_vector(O_DWIDTH-1 downto 0);
+
+begin
+
+  --state_mon <= state_mon_reg;
+  --tdp_addra_o <= std_logic_vector(tdp_addra_reg);
+  --tdp_addrb_o <= std_logic_vector(tdp_addrb_reg);
+
+  s_axis_tready <= tready_s;
+  --avg_o         <= std_logic_vector(avg_reg);
+  done_o <= done_s;
+
+  -- TDP RAM
+  tdp_ram_i : entity work.tdp_ram_pip
+  generic map(
+               AWIDTH       => log2c(MEM_DEPTH/RATIO),
+               DWIDTH       => I_DWIDTH
+             )
+  port map(
+            clka  => s_axis_aclk,
+            --rsta  => rsta_s,
+            wea   => tdp_wea,
+            addra => std_logic_vector(tdp_addra_reg),
+            dia   => tdp_dia,
+
+            clkb  => s_axis_aclk,
+            rstb  => rstb_s,
+            enb   => tdp_enb, --'1',
+            addrb => std_logic_vector(tdp_addrb_reg),
+            dob   => tdp_dob
+          );
+
+  -- ASYMMETRIC RAM
+  -- Port A -> AXI IF
+  -- Port B -> same as WIDER BRAM
+  asy_ram_i : entity work.asym_ram_sdp_write_wider
+  generic map
+  (
+    WIDTHA      => ADC_DWIDTH,
+    SIZEA       => MEM_DEPTH,
+    ADDRWIDTHA  => MEM_AWIDTH,
+    WIDTHB      => I_DWIDTH,
+    SIZEB       => (MEM_DEPTH/RATIO),
+    ADDRWIDTHB  => log2c(MEM_DEPTH/RATIO)
+  )
+  port map
+  (
+    clkA        => bram_clk,
+    rstA        => bram_rst,
+    enA         => bram_en, 
+    addrA       => bram_addr, 
+    doA         => bram_rddata, 
+
+    --portB same as portA in tdp_ram
+    clkB        => s_axis_aclk,
+    weB         => tdp_wea,
+    addrB       => std_logic_vector(tdp_addra_reg),
+    diB         => tdp_dia
+  );
+
+  --debug signals
+  --lets synchronize the en signal
+  --sync_bram_en: entity work.sync
+  --port map(
+  --          aclk     => s_axis_aclk,
+  --          aresetn  => s_axis_aresetn,
+  --          in_async => bram_en,
+  --          out_sync => bram_en_o
+  --        );
+  --bram_en_oo <= bram_en;
+
+  --lets synchronize the addr signal
+  --sync_bram_addr: entity work.n_sync
+  --generic map(
+  --             N => MEM_AWIDTH
+  --           )
+  --port map(
+  --          aclk     => s_axis_aclk,
+  --          aresetn  => s_axis_aresetn,
+  --          in_async => bram_addr,
+  --          out_sync => bram_addr_o
+  --        );
+  --bram_addr_oo <= bram_addr;
+
+  ----lets synchronize the en signal
+  --sync_bram_rddata: entity work.n_sync
+  --generic map(
+  --             N => O_DWIDTH
+  --           )
+  --port map(
+  --          aclk     => s_axis_aclk,
+  --          aresetn  => s_axis_aresetn,
+  --          in_async => bram_rddata,
+  --          out_sync => bram_rddata_o
+  --        );
+  --bram_rddata_oo <= bram_rddata;
+
+  process(s_axis_aclk)
+  begin
+    if rising_edge(s_axis_aclk) then
+      if (s_axis_aresetn = '0') then
+        state_reg     <= ST_IDLE;
+        --state_mon_reg <= (others => '0');
+        tdp_addra_reg <= (others => '0');
+        tdp_addrb_reg <= (others => '0');
+        avg_reg       <= (others => '0');
+      else
+        state_reg     <= state_next;
+        --state_mon_reg <= state_mon_next;
+        tdp_addra_reg <= tdp_addra_next;
+        tdp_addrb_reg <= tdp_addrb_next;
+        avg_reg       <= avg_next;
+      end if;
+    end if;
+  end process;
+
+  --tdp_addra_next <= tdp_addrb_reg;
+
+  --Next state logic
+  --process(state_reg, state_mon_reg, en_i, start_i, trig_i, nsamples_i, naverages_i,
+  process(state_reg, en_i, start_i, trig_i, nsamples_i, naverages_i,
+    tdp_addra_reg, tdp_addrb_reg, tdp_dia, tdp_dob, s_axis_tvalid, s_axis_tdata,
+    avg_reg, m_axis_tready, restart_os)
+  begin
+    state_next    <= state_reg;
+    --state_mon_next<= state_mon_reg;
+    rstb_s        <= '0';
+    tdp_wea       <= '0';
+    tdp_addra_next<= tdp_addra_reg;
+    tdp_dia       <= (others => '0'); 
+    tdp_enb       <= '0';
+    tdp_addrb_next<= tdp_addrb_reg;
+    asy_rsta      <= '1';
+    asy_ena       <= '0';
+    tready_s      <= '0';
+    avg_next      <= avg_reg;
+    done_s        <= '0';
+
+    case state_reg is
+      when ST_IDLE => -- Start
+        rstb_s         <= '1';
+        tdp_addra_next <= (others => '0');
+        tdp_addrb_next <= (others => '0');
+        avg_next       <= (others => '0');
+        if en_i = '1' and start_i = '1' then
+          state_next  <= ST_WAIT_TRIG;
+          --state_mon_next <= "0001"; 
+        else
+          state_next  <= ST_IDLE;
+          --state_mon_next <= (others => '0'); 
+        end if;
+
+      when ST_WAIT_TRIG => -- Wait for trigger
+        if(trig_i = '1') then
+          state_next  <= ST_EN_TDPB;
+          --state_mon_next <= "0010"; 
+        else
+          state_next <= ST_WAIT_TRIG;
+          --state_mon_next <= "0001"; 
+        end if;
+
+      when ST_EN_TDPB =>
+        if (s_axis_tvalid = '1') then
+          tdp_enb        <= '1';
+          tdp_addrb_next <= tdp_addrb_reg + 1;
+          state_next     <= ST_AVG_SCOPE;
+          --state_mon_next <= "0011"; 
+        end if;
+
+      when ST_AVG_SCOPE => -- Measure
+        if (s_axis_tvalid = '1') then
+          tready_s <= '1';
+          tdp_enb  <= '1';
+          tdp_wea  <= '1';
+          tdp_addra_next <= tdp_addra_reg + 1;
+          tdp_addrb_next <= tdp_addrb_reg + 1;
+          ASSIGN_G1: for I in 0 to RATIO-1 loop
+            tdp_dia(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-(I+1)*ADC_DWIDTH) <=
+            std_logic_vector(signed(tdp_dob(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-(I+1)*ADC_DWIDTH)) +
+            resize(signed(s_axis_tdata(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-((I+1)*ADC_DWIDTH)+4)),ADC_DWIDTH));
+          end loop;
+          if(tdp_addra_reg = (unsigned(nsamples_i)/RATIO)-1) then
+            tdp_addra_next <= (others => '0');
+            tdp_addrb_next <= (others => '0');
+            avg_next <= avg_reg + 1;
+            if (avg_reg = unsigned(naverages_i)-1) then
+              state_next  <= ST_FINISH;
+              --state_mon_next <= "0100"; 
+            else
+              state_next  <= ST_WAIT_TRIG;
+              --state_mon_next <= "0001"; 
+            end if;
+          end if;
+        else 
+          state_next <= ST_AVG_SCOPE;
+          --state_mon_next <= "0011"; 
+        end if;
+
+      when ST_FINISH => 
+        done_s    <= '1';
+        if restart_os = '1' then
+          state_next <= ST_WR_ZEROS;
+          --state_mon_next <= "0101";
+        end if;
+
+      when ST_WR_ZEROS => 
+        tdp_wea   <= '1';
+        tdp_addra_next <= tdp_addra_reg + 1; 
+        if (tdp_addra_reg = (unsigned(nsamples_i)/RATIO)-1) then
+          state_next <= ST_IDLE;
+          --state_mon_next <= (others => '0');
+        end if;
+
+    end case;
+  end process;
+
+  --lets synchronize the restart signal
+  os_restart_as: entity work.edge_det
+  port map(
+            aclk     => s_axis_aclk,
+            aresetn  => s_axis_aresetn,
+            sig_i    => restart_s,
+            sig_o    => restart_os
+          );
+
+  reader_i: entity work.bram_reader 
+  generic map(
+            MEM_DEPTH   => MEM_DEPTH,
+            MEM_AWIDTH  => MEM_AWIDTH,
+            AXIS_DWIDTH => O_DWIDTH
+          )
+  port map(
+
+         cfg_data_i     => nsamples_i,
+         --sts_data_o     => open,
+         done_i         => done_s,
+         send_i         => send_i, 
+         restart_o      => restart_s,
+
+         -- Master side
+         aclk           => m_axis_aclk,
+         aresetn        => m_axis_aresetn,
+         m_axis_tready  => m_axis_tready,
+         m_axis_tdata   => m_axis_tdata,
+         m_axis_tvalid  => m_axis_tvalid,
+         m_axis_tlast   => m_axis_tlast, 
+         m_axis_tkeep   => m_axis_tkeep, 
+          -- BRAM port
+         bram_clk       => bram_clk,   
+         bram_rst       => bram_rst,
+         bram_en        => bram_en,
+         bram_addr      => bram_addr,
+         bram_rddata    => bram_rddata
+       );
+
+end rtl;
diff --git a/cores/axis_avgr16bits_v1_0/axis_averager.vhd b/cores/axis_avgr16bits_v1_0/axis_averager.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..142e4b2bef6b148501be60c37dca7154c69ee7c9
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/axis_averager.vhd
@@ -0,0 +1,312 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_averager is
+  generic (
+            S_AXIS_DWIDTH : natural := 128; -- AXIS itf data width
+            M_AXIS_DWIDTH : natural := 16;  -- AXI itf data width
+            ADC_DWIDTH    : natural := 16;  -- ADC data width
+            MEM_AWIDTH    : natural := 10;  -- MEM addr width
+            MEM_DEPTH     : natural := 1024 --Max 2**16
+          );
+  port ( 
+         start_i           : in std_logic;
+         trig_i            : in std_logic;
+         send_i            : in std_logic;
+         done_o            : out std_logic;
+
+         --start_o           : out std_logic;
+         --trig_o            : out std_logic;
+         --mode_o            : out std_logic;
+
+         --avg_scope (as) debug signals
+         --as_state_mon_o    : out std_logic_vector(4-1 downto 0);
+         --as_avg_o          : out std_logic_vector(16-1 downto 0);
+
+         --ntoone (nt) debug signals
+         --nt_state_mon_o    : out std_logic_vector(4-1 downto 0);
+         --nt_avg_o          : out std_logic_vector(16-1 downto 0);
+
+         --en_o              : out std_logic;
+         --nsamples_o        : out std_logic_vector(16-1 downto 0);
+         --naverages_o       : out std_logic_vector(16-1 downto 0);
+         --tdp_addra_o       : out std_logic_vector(11-1 downto 0);
+         --tdp_addrb_o       : out std_logic_vector(11-1 downto 0);
+         --bram_en_o         : out std_logic;
+         --bram_addr_o       : out std_logic_vector(MEM_AWIDTH-1 downto 0);
+         --bram_rddata_o     : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0);
+         --bram_en_oo         : out std_logic;
+         --bram_addr_oo       : out std_logic_vector(MEM_AWIDTH-1 downto 0);
+         --bram_rddata_oo     : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0);
+
+         -- Slave config side
+         s_axis_cfg_aclk   : in std_logic;
+         s_axis_cfg_aresetn: in std_logic;
+         s_axis_cfg_reg_i  : in std_logic_vector(80-1 downto 0);
+
+         -- Slave data interface
+         s_axis_aclk       : in std_logic;
+         s_axis_aresetn    : in std_logic;
+         s_axis_tready     : out std_logic;
+         s_axis_tvalid     : in std_logic;
+         s_axis_tdata      : in std_logic_vector(S_AXIS_DWIDTH-1 downto 0);
+
+         -- Master data interface
+         m_axis_aclk       : in std_logic;
+         m_axis_aresetn    : in std_logic;
+         m_axis_tready     : in std_logic;
+         m_axis_tvalid     : out std_logic;
+         m_axis_tlast      : out std_logic;
+         m_axis_tkeep      : out std_logic_vector(2-1 downto 0);
+         m_axis_tdata      : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0)
+       );
+end axis_averager;
+
+architecture rtl of axis_averager is
+
+  signal en_as, en_nt          : std_logic;
+  signal mode_s, mode_sm       : std_logic;
+  signal done_s, as_done, nt_done   : std_logic;
+  signal start_sync, trig_sync : std_logic;
+  signal start_os, trig_os, send_os : std_logic;
+  signal nsamples_s, naverages_s    : std_logic_vector(M_AXIS_DWIDTH-1 downto 0);
+
+  --Register cfg/sts
+  signal s_axis_cfg_reg_sync   : std_logic_vector(80-1 downto 0);
+  signal m_axis_cfg_reg_sync   : std_logic_vector(80-1 downto 0);
+  signal m0_axis_aclk, m1_axis_aclk       : std_logic;
+  signal m0_axis_aresetn, m1_axis_aresetn : std_logic;
+  signal m0_axis_tdata, m1_axis_tdata     : std_logic_vector(S_AXIS_DWIDTH-1 downto 0);
+  signal m0_axis_tvalid, m1_axis_tvalid   : std_logic;
+  signal m0_axis_tready, m1_axis_tready   : std_logic;
+
+  signal m00_axis_aclk, m11_axis_aclk       : std_logic;
+  signal m00_axis_aresetn, m11_axis_aresetn : std_logic;
+  signal m00_axis_tdata, m11_axis_tdata     : std_logic_vector(M_AXIS_DWIDTH-1 downto 0);
+  signal m00_axis_tvalid, m11_axis_tvalid   : std_logic;
+  signal m00_axis_tready, m11_axis_tready   : std_logic;
+  signal m00_axis_tlast, m11_axis_tlast     : std_logic;
+  signal m00_axis_tkeep, m11_axis_tkeep     : std_logic_vector(2-1 downto 0);
+
+begin
+
+  --lets synchronize the cfg word
+  sync_cfg_s: entity work.n_sync
+  generic map(N => 80
+             )
+  port map(
+            aclk     => s_axis_aclk,
+            aresetn  => s_axis_aresetn,
+            in_async => s_axis_cfg_reg_i,
+            out_sync => s_axis_cfg_reg_sync
+          );
+
+  mode_s      <= s_axis_cfg_reg_sync(64-1); 
+  naverages_s <= s_axis_cfg_reg_sync(48-1 downto 32);
+  nsamples_s  <= s_axis_cfg_reg_sync(16-1 downto 0);
+
+  --mode_s      <= s_axis_cfg_reg_sync(32); 
+  --naverages_s <= s_axis_cfg_reg_sync(32-1 downto 16);
+  --nsamples_s  <= s_axis_cfg_reg_sync(16-1 downto 0);
+
+  --signals for debug
+  --mode_o      <= s_axis_cfg_reg_sync(64-1); 
+  --naverages_o <= s_axis_cfg_reg_sync(48-1 downto 32);
+  --nsamples_o  <= s_axis_cfg_reg_sync(16-1 downto 0);
+  en_as       <= not mode_s;
+  en_nt       <= mode_s;
+  
+  --en_o <= en_as;
+
+  os_start: entity work.edge_det
+  port map(
+            aclk     => s_axis_aclk,
+            aresetn  => s_axis_aresetn,
+            sig_i    => start_i,
+            sig_o    => start_os
+          );
+  --start_o <= start_os;
+
+  --lets synchronize the send signal
+  sync_send_m: entity work.edge_det
+  port map(
+            aclk     => m_axis_aclk,
+            aresetn  => m_axis_aresetn,
+            sig_i    => send_i,
+            sig_o    => send_os
+          );
+
+  os_trig: entity work.edge_det
+  port map(
+            aclk     => s_axis_aclk,
+            aresetn  => s_axis_aresetn,
+            sig_i    => trig_i,
+            sig_o    => trig_os
+          );
+  --trig_o <= trig_os;
+
+  --lets synchronize the cfg word
+  --sync_cfg_m: entity work.n_sync
+  --generic map(N => 80
+  --           )
+  --port map(
+  --          aclk     => m_axis_aclk,
+  --          aresetn  => m_axis_aresetn,
+  --          in_async => s_axis_cfg_reg_i,
+  --          out_sync => m_axis_cfg_reg_sync
+  --        );
+  ----mode_sm      <= m_axis_cfg_reg_sync(32-1); 
+  --mode_sm      <= m_axis_cfg_reg_sync(64-1); 
+
+  --Select the data input
+  sig_sel_i: entity work.axis_signal_selector 
+  generic map(
+               AXIS_DWIDTH => S_AXIS_DWIDTH
+             )
+  port map(
+            sel            => mode_s,
+            s_axis_aclk    => s_axis_aclk,
+            s_axis_aresetn => s_axis_aresetn,
+            s_axis_tdata   => s_axis_tdata,
+            s_axis_tvalid  => s_axis_tvalid,
+            s_axis_tready  => s_axis_tready,
+            
+            m0_axis_aclk   => m0_axis_aclk,
+            m0_axis_aresetn=> m0_axis_aresetn,
+            m0_axis_tdata  => m0_axis_tdata,
+            m0_axis_tvalid => m0_axis_tvalid,
+            m0_axis_tready => m0_axis_tready,
+
+            m1_axis_aclk   => m1_axis_aclk,
+            m1_axis_aresetn=> m1_axis_aresetn,
+            m1_axis_tdata  => m1_axis_tdata,
+            m1_axis_tvalid => m1_axis_tvalid,
+            m1_axis_tready => m1_axis_tready
+);
+
+  --Averager scope
+  avg_scope_i: entity work.avg_scope 
+  generic map(
+               I_DWIDTH   => S_AXIS_DWIDTH,
+               O_DWIDTH   => M_AXIS_DWIDTH,
+               ADC_DWIDTH => ADC_DWIDTH,
+               MEM_AWIDTH => MEM_AWIDTH,
+               MEM_DEPTH  => MEM_DEPTH
+             )
+  port map(
+            start_i        => start_os,
+            send_i         => send_os,
+            trig_i         => trig_os,
+            done_o         => as_done,
+            --state_mon      => as_state_mon_o,
+            en_i           => en_as,
+            naverages_i    => naverages_s,
+            nsamples_i     => nsamples_s,
+            --bram_en_o      => bram_en_o,
+            --bram_addr_o    => bram_addr_o,
+            --bram_rddata_o  => bram_rddata_o,
+            --bram_en_oo      => bram_en_oo,
+            --bram_addr_oo    => bram_addr_oo,
+            --bram_rddata_oo  => bram_rddata_oo,
+
+            --avg_o          => as_avg_o,
+
+            --tdp_addra_o    => tdp_addra_o,
+            --tdp_addrb_o    => tdp_addrb_o,
+
+            s_axis_cfg_aclk=> s_axis_cfg_aclk,
+            s_axis_cfg_aresetn => s_axis_cfg_aresetn,
+
+            s_axis_aclk    => m0_axis_aclk,
+            s_axis_aresetn => m0_axis_aresetn,
+            s_axis_tready  => m0_axis_tready,
+            s_axis_tvalid  => m0_axis_tvalid,
+            s_axis_tdata   => m0_axis_tdata,
+
+            m_axis_aclk    => m_axis_aclk,
+            m_axis_aresetn => m_axis_aresetn,
+            m_axis_tready  => m00_axis_tready,
+            m_axis_tdata   => m00_axis_tdata,
+            m_axis_tvalid  => m00_axis_tvalid,
+            m_axis_tlast   => m00_axis_tlast,
+            m_axis_tkeep   => m00_axis_tkeep
+          );
+
+  --Averager N to One
+  avg_ntoone_i: entity work.avg_ntoone 
+  generic map(
+               I_DWIDTH   => S_AXIS_DWIDTH,
+               O_DWIDTH   => M_AXIS_DWIDTH,
+               ADC_DWIDTH => ADC_DWIDTH,
+               MEM_AWIDTH => MEM_AWIDTH,
+               MEM_DEPTH  => MEM_DEPTH
+             )
+  port map(
+            start_i        => start_os,
+            send_i         => send_os,
+            trig_i         => trig_os,
+            done_o         => nt_done,
+            --state_mon      => nt_state_mon_o,
+            en_i           => en_nt,
+            naverages_i    => naverages_s,
+            nsamples_i     => nsamples_s,
+            --avg_o          => nt_avg_o,
+
+            s_axis_cfg_aclk=> s_axis_cfg_aclk,
+            s_axis_cfg_aresetn => s_axis_cfg_aresetn,
+
+            s_axis_aclk    => m1_axis_aclk,
+            s_axis_aresetn => m1_axis_aresetn,
+            s_axis_tready  => m1_axis_tready,
+            s_axis_tvalid  => m1_axis_tvalid,
+            s_axis_tdata   => m1_axis_tdata,
+
+            m_axis_aclk    => m_axis_aclk,
+            m_axis_aresetn => m_axis_aresetn,
+            m_axis_tready  => m11_axis_tready,
+            m_axis_tdata   => m11_axis_tdata,
+            m_axis_tvalid  => m11_axis_tvalid,
+            m_axis_tlast   => m11_axis_tlast,
+            m_axis_tkeep   => m11_axis_tkeep
+          );
+
+  done_s <= nt_done when (mode_s = '1') else as_done;
+  --lets synchronize the done signal
+  sync_done: entity work.sync
+  port map(
+            aclk     => s_axis_cfg_aclk,
+            aresetn  => s_axis_cfg_aresetn,
+            in_async => done_s,
+            out_sync => done_o
+          );
+
+  --Mux the output data
+  sig_mux_i: entity work.axis_signal_mux 
+  generic map(
+               AXIS_DWIDTH => M_AXIS_DWIDTH
+             )
+  port map(
+            sel            => mode_s, --m,
+
+            s0_axis_tdata   => m00_axis_tdata,
+            s0_axis_tvalid  => m00_axis_tvalid,
+            s0_axis_tready  => m00_axis_tready,
+            s0_axis_tlast   => m00_axis_tlast,
+            s0_axis_tkeep   => m00_axis_tkeep,
+
+            s1_axis_tdata   => m11_axis_tdata,
+            s1_axis_tvalid  => m11_axis_tvalid,
+            s1_axis_tready  => m11_axis_tready,
+            s1_axis_tlast   => m11_axis_tlast,
+            s1_axis_tkeep   => m11_axis_tkeep,
+
+            m_axis_tdata   => m_axis_tdata,
+            m_axis_tvalid  => m_axis_tvalid,
+            m_axis_tready  => m_axis_tready,
+            m_axis_tlast   => m_axis_tlast,
+            m_axis_tkeep   => m_axis_tkeep
+
+);
+
+end rtl;
diff --git a/cores/axis_avgr16bits_v1_0/axis_signal_mux.vhd b/cores/axis_avgr16bits_v1_0/axis_signal_mux.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..5ce086372aa15faae2c96292b910aeaa5e484c33
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/axis_signal_mux.vhd
@@ -0,0 +1,43 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_signal_mux is
+generic (
+      AXIS_DWIDTH : natural := 32
+);
+port (
+  sel               : in std_logic;
+
+  s0_axis_tdata     : in std_logic_vector(AXIS_DWIDTH-1 downto 0);        
+  s0_axis_tvalid    : in std_logic;                               
+  s0_axis_tready    : out std_logic;                               
+  s0_axis_tlast     : in std_logic;                               
+  s0_axis_tkeep     : in std_logic_vector(2-1 downto 0);        
+
+  s1_axis_tdata     : in std_logic_vector(AXIS_DWIDTH-1 downto 0);  
+  s1_axis_tvalid    : in std_logic;                         
+  s1_axis_tready    : out std_logic;                         
+  s1_axis_tlast     : in std_logic;                               
+  s1_axis_tkeep     : in std_logic_vector(2-1 downto 0);        
+
+  m_axis_tdata      : out std_logic_vector(AXIS_DWIDTH-1 downto 0);  
+  m_axis_tvalid     : out std_logic;                         
+  m_axis_tlast      : out std_logic;                               
+  m_axis_tkeep      : out std_logic_vector(2-1 downto 0);        
+  m_axis_tready     : in std_logic                         
+);
+end axis_signal_mux;
+
+architecture rtl of axis_signal_mux is
+begin
+
+  s0_axis_tready <= m_axis_tready when sel = '0' else '0';
+  s1_axis_tready <= m_axis_tready when sel = '1' else '0';
+
+  m_axis_tdata  <= s0_axis_tdata when sel = '0' else s1_axis_tdata;
+  m_axis_tvalid <= s0_axis_tvalid when sel = '0' else s1_axis_tvalid;
+  m_axis_tlast  <= s0_axis_tlast when sel = '0' else s1_axis_tlast;
+  m_axis_tkeep  <= s0_axis_tkeep when sel = '0' else s1_axis_tkeep;
+
+end rtl;
diff --git a/cores/axis_avgr16bits_v1_0/axis_signal_selector.vhd b/cores/axis_avgr16bits_v1_0/axis_signal_selector.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a9bda66e8dbd75041603249a57a6a14b220183d3
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/axis_signal_selector.vhd
@@ -0,0 +1,48 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_signal_selector is
+generic (
+      AXIS_DWIDTH : natural := 32
+);
+port (
+  sel                : in std_logic;
+  -- System signals
+  s_axis_aclk        : in std_logic;
+  s_axis_aresetn     : in std_logic;
+  s_axis_tdata       : in std_logic_vector(AXIS_DWIDTH-1 downto 0);        
+  s_axis_tvalid      : in std_logic;                               
+  s_axis_tready      : out std_logic;                               
+
+  m0_axis_aclk       : out std_logic;
+  m0_axis_aresetn    : out std_logic;
+  m0_axis_tdata      : out std_logic_vector(AXIS_DWIDTH-1 downto 0);  
+  m0_axis_tvalid     : out std_logic;                         
+  m0_axis_tready     : in std_logic;                         
+
+  m1_axis_aclk       : out std_logic;
+  m1_axis_aresetn    : out std_logic;
+  m1_axis_tdata      : out std_logic_vector(AXIS_DWIDTH-1 downto 0);  
+  m1_axis_tvalid     : out std_logic;                         
+  m1_axis_tready     : in std_logic                         
+);
+end axis_signal_selector;
+
+architecture rtl of axis_signal_selector is
+begin
+  m0_axis_aclk    <= s_axis_aclk; 
+  m0_axis_aresetn <= s_axis_aresetn; 
+
+  m1_axis_aclk    <= s_axis_aclk; 
+  m1_axis_aresetn <= s_axis_aresetn; 
+
+  s_axis_tready <= m0_axis_tready when sel = '0' else m1_axis_tready;
+
+  m0_axis_tvalid <= s_axis_tvalid when sel = '0' else '0';
+  m0_axis_tdata  <= s_axis_tdata when sel = '0' else (others => '0');
+
+  m1_axis_tvalid <= s_axis_tvalid when sel = '1' else '0';
+  m1_axis_tdata  <= s_axis_tdata when sel = '1' else (others => '0');
+
+end rtl;
diff --git a/cores/axis_avgr16bits_v1_0/bram_reader.vhd b/cores/axis_avgr16bits_v1_0/bram_reader.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..78184ad12c5051ef9c088a0a9cdf748d2895d8e8
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/bram_reader.vhd
@@ -0,0 +1,150 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity bram_reader is
+  generic (
+            MEM_DEPTH   : natural := 1024;
+            MEM_AWIDTH  : natural := 10;
+            AXIS_DWIDTH : natural := 16
+          );
+  port (
+         -- System signals
+         aclk           : in std_logic;
+         aresetn        : in std_logic;
+
+         cfg_data_i     : in std_logic_vector(AXIS_DWIDTH-1 downto 0);
+         --sts_data_o     : out std_logic_vector(AXIS_DWIDTH-1 downto 0);
+         done_i         : in std_logic;
+         send_i         : in std_logic;
+         restart_o      : out std_logic;
+
+         -- Master side
+         m_axis_tready  : in std_logic;
+         m_axis_tdata   : out std_logic_vector(AXIS_DWIDTH-1 downto 0);
+         m_axis_tvalid  : out std_logic;
+         m_axis_tlast   : out std_logic;
+         m_axis_tkeep   : out std_logic_vector(2-1 downto 0);
+
+         -- BRAM port
+         bram_clk       : out std_logic;
+         bram_rst       : out std_logic;
+         bram_en        : out std_logic;
+         bram_addr      : out std_logic_vector(MEM_AWIDTH-1 downto 0);
+         bram_rddata    : in std_logic_vector(AXIS_DWIDTH-1 downto 0)
+       );
+end bram_reader;
+
+architecture rtl of bram_reader is
+
+  type state_t is (
+  ST_IDLE,
+  ST_EN_BRAM,
+  ST_SEND_DATA,
+  ST_TLAST,
+  ST_FINISH
+);
+signal state_reg, state_next   : state_t;
+
+signal addr_reg, addr_next     : unsigned(MEM_AWIDTH-1 downto 0);
+signal tlast_s, rst_s, en_s    : std_logic;
+signal tvalid_s                : std_logic;
+signal restart_s               : std_logic;
+signal tkeep_s                 : std_logic_vector(2-1 downto 0);
+--signal bram_st_mon             : std_logic_vector(4-1 downto 0);
+
+begin
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if aresetn = '0' then
+        state_reg  <= ST_IDLE;
+        addr_reg   <= (others => '0');
+      else 
+        state_reg  <= state_next;
+        addr_reg   <= addr_next;
+      end if;
+    end if;
+  end process;
+
+  --Next state logic
+  process(state_reg, addr_reg, done_i, send_i, m_axis_tready,
+    cfg_data_i)
+  begin
+    state_next   <= state_reg;
+    addr_next    <= addr_reg;
+    tvalid_s     <= '0';
+    tlast_s      <= '0';
+    restart_s    <= '0';
+    en_s         <= '0';
+    rst_s        <= '0';
+    tkeep_s      <= (others => '0');
+
+    case state_reg is
+      when ST_IDLE => 
+        --bram_st_mon <= "0000"; --state mon
+        rst_s       <= '1';
+        addr_next  <= (others => '0');
+        if (done_i = '1') and (send_i = '1') then
+            state_next  <= ST_EN_BRAM;
+        else
+          state_next  <= ST_IDLE;
+        end if;
+
+      when ST_EN_BRAM =>
+        --bram_st_mon <= "0001"; --state mon
+        if m_axis_tready = '1' then
+          en_s <= '1';
+          addr_next <= addr_reg + 1;
+          state_next  <= ST_SEND_DATA;
+        else
+          state_next <= ST_EN_BRAM;
+        end if;
+
+      when ST_SEND_DATA =>
+        --bram_st_mon <= "0010"; --state mon
+        tvalid_s <= '1';
+        tkeep_s  <= (others => '1');
+        if m_axis_tready = '1' then
+          en_s     <= '1';
+          addr_next <= addr_reg + 1;
+          if (addr_reg = unsigned(cfg_data_i)-1) then
+            --addr_next <= (others => '0');
+            state_next <= ST_TLAST;
+          else
+            state_next <= ST_SEND_DATA;
+          end if;
+        else 
+          state_next <= ST_SEND_DATA;
+        end if;
+
+      when ST_TLAST =>
+        --bram_st_mon <= "0011";
+        tvalid_s <= '1';
+        tkeep_s  <= (others => '1');
+        tlast_s <= '1';
+        state_next <= ST_FINISH;
+
+      when ST_FINISH =>
+        --bram_st_mon <= "0100"; --state mon
+        restart_s <= '1';
+        state_next <= ST_IDLE;
+
+    end case;
+  end process;
+
+  --sts_data_o <= std_logic_vector(resize(addr_reg,AXIS_DWIDTH));
+
+  m_axis_tdata  <= bram_rddata;
+  m_axis_tvalid <= tvalid_s;
+  m_axis_tlast  <= tlast_s;
+  m_axis_tkeep  <= tkeep_s;
+
+  bram_clk <= aclk;
+  bram_rst <= rst_s;
+  bram_en  <= en_s;
+  bram_addr <= std_logic_vector(addr_reg);
+  restart_o <= restart_s; 
+
+end rtl;
diff --git a/cores/axis_avgr16bits_v1_0/core_config.tcl b/cores/axis_avgr16bits_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..500dabacf61d4a472a4520845e1094de6f2a3724
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/core_config.tcl
@@ -0,0 +1,29 @@
+set display_name {AXI4-Stream Averager 16 bits v1.0}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter S_AXIS_DWIDTH {S_AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter M_AXIS_DWIDTH {M_AXIS TDATA WIDTH} {Width of the M_AXI data bus.}
+core_parameter ADC_DWIDTH {ADC DATA WIDTH} {Width of the ADC data.}
+core_parameter MEM_AWIDTH {MEMORY ADDR WIDTH} {Address width of the data memory.}
+core_parameter MEM_DEPTH {MEMORY DEPTH} {Depth of the data memory.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces s_axis_aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS $parameter
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces m_axis_aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS $parameter
+
diff --git a/cores/axis_avgr16bits_v1_0/edge_det.vhd b/cores/axis_avgr16bits_v1_0/edge_det.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..11dfb19e15f76895c353a79309729f16aa8c4609
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/edge_det.vhd
@@ -0,0 +1,58 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity edge_det is
+  port(
+        aclk   : in std_logic;
+        aresetn: in std_logic;
+        sig_i  : in std_logic;
+        sig_o  : out std_logic
+      );
+end edge_det;
+
+architecture rtl of edge_det is
+  type state_t is (zero, edge, one);
+  signal state_reg, state_next: state_t;
+begin
+   -- state register
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn='0') then
+        state_reg <= zero;
+      else
+        state_reg <= state_next;
+      end if;
+    end if;
+  end process;
+
+   -- next-state logic
+  process(state_reg, sig_i)
+  begin
+    case state_reg is
+      when zero=>
+        if sig_i = '1' then
+          state_next <= edge;
+        else
+          state_next <= zero;
+        end if;
+      when edge =>
+        if sig_i = '1' then
+          state_next <= one;
+        else
+          state_next <= zero;
+        end if;
+      when one =>
+        if sig_i = '1' then
+          state_next <= one;
+        else
+          state_next <= zero;
+        end if;
+    end case;
+  end process;
+
+   -- Moore output logic
+  sig_o <= '1' when state_reg=edge else
+           '0';
+
+end rtl;
diff --git a/cores/axis_avgr16bits_v1_0/n_sync.vhd b/cores/axis_avgr16bits_v1_0/n_sync.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..1a92e1d9063bda1af8dd5ab5bf4738ec802fec89
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/n_sync.vhd
@@ -0,0 +1,46 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity n_sync is
+  generic(
+           N : natural
+         );
+  port(
+        aclk     : in std_logic;
+        aresetn  : in std_logic;
+        in_async : in std_logic_vector(N-1 downto 0);
+        out_sync : out std_logic_vector(N-1 downto 0)
+      );
+end n_sync;
+
+architecture two_ff_arch of n_sync is
+  signal meta_reg, meta_next  : std_logic_vector(N-1 downto 0);
+  signal sync_reg, sync_next: std_logic_vector(N-1 downto 0);
+
+  attribute ASYNC_REG : string;
+  attribute ASYNC_REG of meta_reg: signal is "TRUE";
+  attribute ASYNC_REG of sync_reg: signal is "TRUE";
+
+begin
+
+  -- two registers
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn='0') then
+        meta_reg <= (others=>'0');
+        sync_reg <= (others=>'0');
+      else
+        meta_reg <= meta_next;
+        sync_reg <= sync_next;
+      end if;
+    end if;
+  end process;
+
+  -- next-state logic
+  meta_next <= in_async;
+  sync_next <= meta_reg;
+  -- output
+  out_sync <= sync_reg;
+
+end two_ff_arch;
diff --git a/cores/axis_avgr16bits_v1_0/sync.vhd b/cores/axis_avgr16bits_v1_0/sync.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..492bcf687e2f451fc1ca74e627086b861f6dad6f
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/sync.vhd
@@ -0,0 +1,43 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+--synchronizer
+entity sync is
+  port(
+        aclk     : in std_logic;
+        aresetn  : in std_logic;
+        in_async : in std_logic;
+        out_sync : out std_logic
+      );
+end sync;
+
+architecture two_ff_arch of sync is
+  signal meta_reg, meta_next : std_logic;
+  signal sync_reg, sync_next: std_logic;
+
+  attribute ASYNC_REG : string;
+  attribute ASYNC_REG of meta_reg: signal is "TRUE";
+  attribute ASYNC_REG of sync_reg: signal is "TRUE";
+begin
+
+  -- two registers
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn='0') then
+        meta_reg <= '0';
+        sync_reg <= '0';
+      else
+        meta_reg <= meta_next;
+        sync_reg <= sync_next;
+      end if;
+    end if;
+  end process;
+
+  -- next-state logic
+  meta_next <= in_async;
+  sync_next <= meta_reg;
+  -- output
+  out_sync <= sync_reg;
+
+end two_ff_arch;
diff --git a/cores/axis_avgr16bits_v1_0/tdp_ram_pip.vhd b/cores/axis_avgr16bits_v1_0/tdp_ram_pip.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..712f43ace738fbbfaaa30aa94a6c03ed6c521997
--- /dev/null
+++ b/cores/axis_avgr16bits_v1_0/tdp_ram_pip.vhd
@@ -0,0 +1,86 @@
+-- Block RAM with Optional Output Registers
+-- File: modified from rams_pipeline.vhd
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity tdp_ram_pip is
+  generic (
+            AWIDTH       : integer := 16;
+            DWIDTH       : integer := 16
+          );
+  port(
+        clka  : in  std_logic;
+        --rsta  : in  std_logic;
+        --ena   : in  std_logic;
+        wea   : in  std_logic;
+        addra : in  std_logic_vector(AWIDTH-1 downto 0);
+        dia   : in  std_logic_vector(DWIDTH-1 downto 0);
+        --doa   : out std_logic_vector(DWIDTH-1 downto 0);
+        clkb  : in  std_logic;
+        rstb  : in  std_logic;
+        enb   : in  std_logic;
+        --web   : in  std_logic;
+        addrb : in  std_logic_vector(AWIDTH-1 downto 0);
+        --dib   : in  std_logic_vector(DWIDTH-1 downto 0);
+        dob   : out std_logic_vector(DWIDTH-1 downto 0)
+      );
+end tdp_ram_pip;
+
+architecture rtl of tdp_ram_pip is
+  type ram_t is array (0 to 2**AWIDTH-1) of std_logic_vector(DWIDTH-1 downto 0);
+  signal ram : ram_t := (others => (others => '0')); 
+  signal a_reg, a_next : std_logic_vector(DWIDTH-1 downto 0);
+  signal b_reg, b_next : std_logic_vector(DWIDTH-1 downto 0);
+
+begin
+
+  process(clka)
+  begin
+    if rising_edge(clka) then
+      if wea = '1' then
+        ram(to_integer(unsigned(addra))) <= dia;
+      end if;
+    --do1 <= ram(to_integer(unsigned(addra)));
+    end if;
+  end process;
+
+  --process(clka)
+  --begin
+  --  if rising_edge(clka) then
+  --    if rsta = '1' then
+  --      a_reg <= (others => '0');
+  --    else
+  --      a_reg <= a_next;
+  --    end if;
+  --  end if;
+  --end process;
+  ----next state logic
+  --a_next <= ram(to_integer(unsigned(addra))) when ena = '1' else a_reg;
+  --doa <= a_reg;
+
+  --process(clkb)
+  --begin
+  --  if rising_edge(clkb) then
+  --    if web = '1' then
+  --      ram(to_integer(unsigned(addrb))) <= dib;
+  --    end if;
+  --  --do2 <= ram(to_integer(unsigned(addrb)));
+  --  end if;
+  --end process;
+
+  process(clkb)
+  begin
+    if rising_edge(clkb) then
+      if rstb = '1' then
+        b_reg <= (others => '0');
+      else
+        b_reg <= b_next;
+      end if;
+    end if;
+  end process;
+  --next state logic
+  b_next <= ram(to_integer(unsigned(addrb))) when enb = '1' else b_reg;
+  dob <= b_reg;
+
+end rtl;
diff --git a/cores/axis_avgr32bits_v1_0/avg_ntoone.vhd b/cores/axis_avgr32bits_v1_0/avg_ntoone.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..7546098a20a63695a5759737f360493efcec64df
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/avg_ntoone.vhd
@@ -0,0 +1,255 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity avg_ntoone is
+  generic (
+            I_DWIDTH   : natural := 128; -- ADC data width x8
+            O_DWIDTH   : natural := 32;  -- AXI data width
+            ADC_DWIDTH : natural := 16;  -- ADC data width
+            MEM_AWIDTH : natural := 10;  --
+            MEM_DEPTH  : natural := 1024 -- Max 2**16
+          );
+  port (
+         -- Averager specific ports
+         start_i        : in std_logic;
+         send_i         : in std_logic;
+         trig_i         : in std_logic;
+         done_o         : out std_logic;
+         --state_mon      : out std_logic_vector(3 downto 0);
+         --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW
+         en_i           : in std_logic;
+         naverages_i    : in std_logic_vector(ADC_DWIDTH-1 downto 0);
+         nsamples_i     : in std_logic_vector(ADC_DWIDTH-1 downto 0);
+
+         --avg_o          : out std_logic_vector(O_DWIDTH-1 downto 0);
+
+         s_axis_cfg_aclk    : in std_logic;
+         s_axis_cfg_aresetn : in std_logic;
+
+         -- Slave side
+         s_axis_aclk    : in std_logic;
+         s_axis_aresetn : in std_logic;
+         s_axis_tready  : out std_logic;
+         s_axis_tvalid  : in std_logic;
+         s_axis_tdata   : in std_logic_vector(I_DWIDTH-1 downto 0);
+
+         -- Master side
+         m_axis_aclk    : in std_logic;
+         m_axis_aresetn : in std_logic;
+         m_axis_tready  : in std_logic;
+         m_axis_tdata   : out std_logic_vector(O_DWIDTH-1 downto 0);
+         m_axis_tvalid  : out std_logic;
+         m_axis_tlast   : out std_logic;
+         m_axis_tkeep   : out std_logic_vector(4-1 downto 0)
+       );
+end avg_ntoone;
+
+architecture rtl of avg_ntoone is
+
+  function log2c(n: integer) return integer is
+    variable m, p: integer;
+  begin
+    m := 0;
+    p := 1;
+    while p < n loop
+      m := m + 1;
+      p := p * 2;
+    end loop;
+    return m;
+  end log2c;
+
+  constant RATIO : natural := I_DWIDTH/ADC_DWIDTH;
+
+  type state_t is (
+  ST_IDLE,
+  ST_WAIT_TRIG,
+  ST_AVG_N1,
+  ST_WRITE_AVG,
+  ST_FINISH
+);
+signal state_reg, state_next      : state_t;
+
+signal tdp_wea     : std_logic;
+signal tdp_addra_reg, tdp_addra_next : unsigned(MEM_AWIDTH-1 downto 0);
+signal tdp_dia     : std_logic_vector(O_DWIDTH-1 downto 0);
+signal tdp_doa     : std_logic_vector(O_DWIDTH-1 downto 0);
+signal data_reg, data_next       : std_logic_vector(2*I_DWIDTH-1 downto 0);
+signal samples_reg, samples_next : unsigned(ADC_DWIDTH-1 downto 0);
+
+signal done_s, tready_s : std_logic;
+signal avg_reg, avg_next       : unsigned(ADC_DWIDTH-1 downto 0);
+signal restart_s, restart_os   : std_logic;
+
+signal bram_clk  : std_logic;
+signal bram_rst  : std_logic;
+signal bram_en   : std_logic;
+signal bram_addr : std_logic_vector(MEM_AWIDTH-1 downto 0);
+signal bram_rddata : std_logic_vector(O_DWIDTH-1 downto 0);
+signal naverages_b : std_logic_vector(O_DWIDTH-1 downto 0);
+
+begin
+
+  s_axis_tready <= tready_s;
+  --avg_o         <= std_logic_vector(avg_reg);
+  done_o        <= done_s;
+
+  -- TDP RAM
+  tdp_ram_i : entity work.tdp_ram_pip
+  generic map(
+               AWIDTH       => MEM_AWIDTH,
+               DWIDTH       => O_DWIDTH
+             )
+  port map(
+            clka  => s_axis_aclk,
+            wea   => tdp_wea,
+            addra => std_logic_vector(tdp_addra_reg),
+            dia   => tdp_dia,
+
+            clkb  => bram_clk,
+            rstb  => bram_rst,
+            enb   => bram_en,
+            addrb => bram_addr,
+            dob   => bram_rddata
+          );
+
+  process(s_axis_aclk)
+  begin
+    if rising_edge(s_axis_aclk) then
+      if (s_axis_aresetn = '0') then
+        state_reg     <= ST_IDLE;
+        tdp_addra_reg <= (others => '0');
+        data_reg      <= (others => '0');
+        samples_reg   <= (others => '0');
+        avg_reg       <= (others => '0');
+      else
+        state_reg     <= state_next;
+        tdp_addra_reg <= tdp_addra_next;
+        data_reg      <= data_next;
+        samples_reg   <= samples_next;
+        avg_reg       <= avg_next;
+      end if;
+    end if;
+  end process;
+
+  --Next state logic
+  process(state_reg, en_i, start_i, trig_i, nsamples_i,
+    naverages_i, tdp_addra_reg, tdp_dia, data_reg, samples_reg,
+    s_axis_tvalid, s_axis_tdata, avg_reg, m_axis_tready, restart_os)
+    variable dinbv : std_logic_vector(O_DWIDTH-1 downto 0);
+  begin
+    state_next    <= state_reg;
+    tdp_wea       <= '0';
+    tdp_addra_next<= tdp_addra_reg;
+    data_next     <= data_reg;
+    samples_next  <= samples_reg;
+    tdp_dia       <= (others => '0'); 
+    tready_s      <= '0';
+    avg_next      <= avg_reg;
+    done_s        <= '0';
+
+    case state_reg is
+      when ST_IDLE => -- Start
+        --state_mon      <= "0000"; --state mon
+        samples_next   <= (others => '0');
+        tdp_addra_next <= (others => '0');
+        avg_next       <= (others => '0');
+        data_next      <= (others => '0');
+        if en_i = '1' and start_i = '1' then
+          state_next  <= ST_WAIT_TRIG;
+        else
+          state_next  <= ST_IDLE;
+        end if;
+
+      when ST_WAIT_TRIG => -- Wait for trigger
+        --state_mon <= "0001"; --state mon
+        if(trig_i = '1') then
+          state_next    <= ST_AVG_N1;
+        else
+          state_next <= ST_WAIT_TRIG;
+        end if;
+
+      when ST_AVG_N1 => 
+        --state_mon <= "0010"; 
+        if (s_axis_tvalid = '1') then
+        tready_s <= '1';
+        samples_next <= samples_reg + 1;
+        ASSIGN_N: for I in 0 to RATIO-1 loop
+          data_next(2*I_DWIDTH-1-I*O_DWIDTH downto 2*I_DWIDTH-(I+1)*O_DWIDTH) <=
+          std_logic_vector(signed(data_reg(2*I_DWIDTH-1-I*O_DWIDTH downto 2*I_DWIDTH-(I+1)*O_DWIDTH)) +
+          resize(signed(s_axis_tdata(I_DWIDTH-1-I*ADC_DWIDTH downto I_DWIDTH-((I+1)*ADC_DWIDTH))),O_DWIDTH));
+        end loop;
+        if(samples_reg = (unsigned(nsamples_i)/RATIO)-1) then
+          samples_next <= (others => '0');
+          state_next  <= ST_WRITE_AVG;
+        end if;
+      end if;
+
+      when ST_WRITE_AVG => 
+        --state_mon <= "0011"; 
+        dinbv := (others => '0');
+        ASSIGN_AVG1: for K in 0 to RATIO-1 loop
+          dinbv := std_logic_vector(signed(dinbv) + signed(data_reg(2*I_DWIDTH-1-K*O_DWIDTH downto 2*I_DWIDTH-(K+1)*O_DWIDTH)));
+        end loop;
+        tdp_dia <= dinbv;
+        tdp_wea <= '1';
+        data_next <= (others => '0');
+        tdp_addra_next <= tdp_addra_reg + 1;
+        avg_next <= avg_reg + 1;
+        if (avg_reg = unsigned(naverages_i)-1) then
+          state_next <= ST_FINISH;
+        else
+          state_next <= ST_WAIT_TRIG;
+        end if;
+
+      when ST_FINISH => 
+        --state_mon <= "0100"; 
+        done_s    <= '1';
+        if restart_os = '1' then
+          state_next <= ST_IDLE;
+        end if;
+
+    end case;
+  end process;
+
+  --lets synchronize the restart signal
+  os_restart_nt: entity work.edge_det
+  port map(
+            aclk     => s_axis_aclk,
+            aresetn  => s_axis_aresetn,
+            sig_i    => restart_s,
+            sig_o    => restart_os
+          );
+
+  naverages_b <= (31 downto 16 => '0') & naverages_i;
+  reader_i: entity work.bram_reader_nt 
+  generic map(
+               MEM_DEPTH   => MEM_DEPTH,
+               MEM_AWIDTH  => MEM_AWIDTH,
+               AXIS_DWIDTH => O_DWIDTH
+             )
+  port map(
+
+            cfg_data_i     => naverages_s,
+            --sts_data_o     => open,
+            done_i         => done_s,
+            send_i         => send_i,
+            restart_o      => restart_s,
+
+         -- Master side
+            aclk           => m_axis_aclk,
+            aresetn        => m_axis_aresetn,
+            m_axis_tready  => m_axis_tready,
+            m_axis_tdata   => m_axis_tdata,
+            m_axis_tvalid  => m_axis_tvalid,
+            m_axis_tlast   => m_axis_tlast, 
+            m_axis_tkeep   => m_axis_tkeep, 
+         -- BRAM port
+            bram_clk       => bram_clk,   
+            bram_rst       => bram_rst,
+            bram_en        => bram_en,
+            bram_addr      => bram_addr,
+            bram_rddata    => bram_rddata
+          );
+
+end rtl;
diff --git a/cores/axis_avgr32bits_v1_0/avg_scope.vhd b/cores/axis_avgr32bits_v1_0/avg_scope.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..ec3809a5a5b4151e89d35f5f5ab52b00501a2b52
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/avg_scope.vhd
@@ -0,0 +1,318 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity avg_scope is
+  generic (
+            I_DWIDTH   : natural := 128; -- ADC data width x8
+            O_DWIDTH   : natural := 32;  -- AXI data width
+            ADC_DWIDTH : natural := 16;  -- ADC data width
+            MEM_AWIDTH : natural := 10;  --
+            MEM_DEPTH  : natural := 1024 -- Max 2**16
+          );
+  port (
+         -- Averager specific ports
+         start_i        : in std_logic;
+         send_i         : in std_logic;
+         trig_i         : in std_logic;
+         done_o         : out std_logic;
+         --state_mon      : out std_logic_vector(3 downto 0);
+         --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW
+         en_i           : in std_logic;
+         naverages_i    : in std_logic_vector(ADC_DWIDTH-1 downto 0);
+         nsamples_i     : in std_logic_vector(ADC_DWIDTH-1 downto 0);
+         --avg_o          : out std_logic_vector(16-1 downto 0);
+
+         s_axis_cfg_aclk    : in std_logic;
+         s_axis_cfg_aresetn : in std_logic;
+
+         -- Slave side
+         s_axis_aclk    : in std_logic;
+         s_axis_aresetn : in std_logic;
+         s_axis_tready  : out std_logic;
+         s_axis_tvalid  : in std_logic;
+         s_axis_tdata   : in std_logic_vector(I_DWIDTH-1 downto 0);
+
+         -- Master side
+         m_axis_aclk    : in std_logic;
+         m_axis_aresetn : in std_logic;
+         m_axis_tready  : in std_logic;
+         m_axis_tdata   : out std_logic_vector(O_DWIDTH-1 downto 0);
+         m_axis_tvalid  : out std_logic;
+         m_axis_tlast   : out std_logic;
+         m_axis_tkeep   : out std_logic_vector(4-1 downto 0)
+       );
+end avg_scope;
+
+architecture rtl of avg_scope is
+
+  function log2c(n: integer) return integer is
+    variable m, p: integer;
+  begin
+    m := 0;
+    p := 1;
+    while p < n loop
+      m := m + 1;
+      p := p * 2;
+    end loop;
+    return m;
+  end log2c;
+
+  constant RATIO : natural := I_DWIDTH/ADC_DWIDTH;
+
+  type state_t is (
+  ST_IDLE,
+  ST_WAIT_TRIG,
+  ST_EN_TDPB,
+  ST_AVG_SCOPE,
+  ST_FINISH,
+  ST_WR_ZEROS
+);
+signal state_reg, state_next      : state_t;
+
+signal rstb_s   : std_logic;
+signal tdp_wea  : std_logic;
+signal tdp_addra_reg, tdp_addra_next : unsigned(MEM_AWIDTH-1 downto 0);
+signal tdp_enb  : std_logic;
+signal tdp_addrb_reg, tdp_addrb_next : unsigned(MEM_AWIDTH-1 downto 0);
+signal addrb_s                       : std_logic_vector(MEM_AWIDTH-1 downto 0);
+
+
+signal done_s, tready_s : std_logic;
+signal avg_reg, avg_next       : unsigned(ADC_DWIDTH-1 downto 0);
+signal en_s, restart_s         : std_logic;
+signal start_sync, trig_sync, send_sync, restart_sync  : std_logic;
+
+signal bram_clk  : std_logic;
+signal bram_rst  : std_logic;
+signal bram_en   : std_logic;
+signal bram_addr : std_logic_vector(MEM_AWIDTH-1 downto 0);
+signal bram_rddata : std_logic_vector(2*I_DWIDTH-1 downto 0);
+
+type vect_t is array (0 to RATIO-1) of std_logic_vector(O_DWIDTH-1 downto 0);
+signal in_reg, in_next : vect_t;
+signal tdp_dia, tdp_doa, tdp_dob, bram_rddata_s : vect_t;
+signal tvalid_reg, tvalid_next : std_logic;
+signal reader_cfg              : std_logic_vector(16-1 downto 0);
+
+begin
+
+  --en_s <= not cfg_data_i(32); --mode=0 enables this block
+  --naverages_s <= cfg_data_i(32-1 downto 16);
+  --nsamples_s <= cfg_data_i(16-1 downto 0);
+
+  s_axis_tready <= tready_s;
+  --avg_o         <= std_logic_vector(avg_reg);
+  done_o <= done_s;
+
+  -- TDP RAM
+  -- input assignment 
+  process(s_axis_tvalid, s_axis_tdata)
+  begin
+    if (s_axis_tvalid = '1') then
+      for k in 0 to RATIO-1  loop
+        in_next(k) <= std_logic_vector(resize(signed(s_axis_tdata(I_DWIDTH-1-k*ADC_DWIDTH downto I_DWIDTH-(k+1)*ADC_DWIDTH)),O_DWIDTH));
+      end loop;
+    else
+      for k in 0 to RATIO-1 loop
+        in_next(k) <= in_reg(k);
+      end loop;
+    end if;
+  end process;
+
+  BRAM_CALC_inst: for j in 0 to RATIO-1 generate
+  tdp_ram_i : entity work.tdp_ram_pip
+  generic map(
+               AWIDTH       => MEM_AWIDTH, 
+               DWIDTH       => O_DWIDTH
+             )
+  port map(
+            clka  => s_axis_aclk,
+            --rsta  => rsta_s,
+            wea   => tdp_wea,
+            addra => std_logic_vector(tdp_addra_reg),
+            dia   => tdp_dia(j),
+
+            clkb  => s_axis_aclk,
+            rstb  => rstb_s,
+            enb   => tdp_enb, --'1',
+            addrb => std_logic_vector(tdp_addrb_reg),
+            dob   => tdp_dob(j)
+          );
+end generate;
+
+  BRAM_OUT_inst: for j in 0 to RATIO-1 generate
+  tdp_ram_i : entity work.tdp_ram_pip
+  generic map(
+               AWIDTH       => MEM_AWIDTH, 
+               DWIDTH       => O_DWIDTH
+             )
+  port map(
+            clka  => s_axis_aclk,
+            wea   => tdp_wea,
+            addra => std_logic_vector(tdp_addra_reg),
+            dia   => tdp_dia(j),
+
+            clkb  => bram_clk,   
+            rstb  => bram_rst,  
+            enb   => bram_en,  
+            addrb => bram_addr, 
+            dob   => bram_rddata_s(j)
+          );
+end generate;
+
+process(bram_rddata_s)
+begin
+  for k in 0 to RATIO-1 loop
+    bram_rddata(2*I_DWIDTH-1-k*O_DWIDTH downto 2*I_DWIDTH-(k+1)*O_DWIDTH) <= bram_rddata_s(RATIO-1-k);
+  end loop;
+end process;
+
+  process(s_axis_aclk)
+  begin
+    if rising_edge(s_axis_aclk) then
+      if (s_axis_aresetn = '0') then
+        state_reg     <= ST_IDLE;
+        in_reg        <= (others => (others => '0'));
+        tvalid_reg    <= '0';
+        tdp_addra_reg <= (others => '0');
+        tdp_addrb_reg <= (others => '0');
+        avg_reg       <= (others => '0');
+      else
+        state_reg     <= state_next;
+        in_reg        <= in_next;
+        tvalid_reg    <= tvalid_next;
+        tdp_addra_reg <= tdp_addra_next;
+        tdp_addrb_reg <= tdp_addrb_next;
+        avg_reg       <= avg_next;
+      end if;
+    end if;
+  end process;
+
+  tvalid_next <= s_axis_tvalid; -- one clk delay
+
+  --Next state logic
+  process(state_reg, en_i, start_i, trig_i, nsamples_i, naverages_i, 
+    tdp_addra_reg, tdp_addrb_reg, tdp_dia, tvalid_reg, 
+    avg_reg, m_axis_tready, restart_os)
+  begin
+    state_next    <= state_reg;
+    rstb_s        <= '0';
+    tdp_wea       <= '0';
+    tdp_addra_next<= tdp_addra_reg;
+    tdp_dia       <= (others => (others => '0')); 
+    tdp_enb       <= '0';
+    tdp_addrb_next<= tdp_addrb_reg;
+    tready_s      <= '0';
+    avg_next      <= avg_reg;
+    done_s        <= '0';
+
+    case state_reg is
+      when ST_IDLE => -- Start
+        rstb_s         <= '1';
+        tdp_addra_next <= (others => '0');
+        tdp_addrb_next <= (others => '0');
+        avg_next       <= (others => '0');
+        if en_i = '1' and start_i = '1' then
+          state_next  <= ST_WAIT_TRIG;
+        else
+          state_next  <= ST_IDLE;
+        end if;
+
+      when ST_WAIT_TRIG => -- Wait for trigger
+        if(trig_i = '1') then
+          state_next  <= ST_EN_TDPB;
+        else
+          state_next <= ST_WAIT_TRIG;
+        end if;
+
+      when ST_EN_TDPB =>
+        if (tvalid_reg = '1') then
+          tdp_enb        <= '1';
+          tdp_addrb_next <= tdp_addrb_reg + 1;
+          state_next     <= ST_AVG_SCOPE;
+        end if;
+
+      when ST_AVG_SCOPE => -- Measure
+        if (tvalid_reg = '1') then
+          tready_s <= '1';
+          tdp_enb  <= '1';
+          tdp_wea  <= '1';
+          tdp_addra_next <= tdp_addra_reg + 1;
+          tdp_addrb_next <= tdp_addrb_reg + 1;
+          ASSIGN_G1: for I in 0 to RATIO-1 loop
+            tdp_dia(I) <= std_logic_vector(signed(tdp_dob(I)) + signed(in_reg(I)));
+          end loop;
+          if(tdp_addra_reg = (unsigned(nsamples_i)/RATIO)-1) then
+            tdp_addra_next <= (others => '0');
+            tdp_addrb_next <= (others => '0');
+            avg_next <= avg_reg + 1;
+            if (avg_reg = unsigned(naverages_i)-1) then
+              state_next  <= ST_FINISH;
+            else
+              state_next  <= ST_WAIT_TRIG;
+            end if;
+          end if;
+        else 
+          state_next <= ST_AVG_SCOPE;
+        end if;
+
+      when ST_FINISH => 
+        done_s    <= '1';
+        if restart_os = '1' then
+          state_next <= ST_WR_ZEROS;
+        end if;
+
+      when ST_WR_ZEROS => 
+        state_mon <= "0101";
+        tdp_wea   <= '1';
+        tdp_addra_next <= tdp_addra_reg + 1; 
+        if (tdp_addra_reg = (unsigned(nsamples_i)/RATIO)-1) then
+          state_next <= ST_IDLE;
+        end if;
+
+    end case;
+  end process;
+
+  --lets synchronize the restart signal
+  os_restart_as: entity work.edge_det
+  port map(
+            aclk     => s_axis_aclk,
+            aresetn  => s_axis_aresetn,
+            sig_i    => restart_s,
+            sig_o    => restart_os
+          );
+
+  reader_cfg <= std_logic_vector(unsigned(nsamples_i)/RATIO);
+  reader_i: entity work.bram_reader 
+  generic map(
+            MEM_DEPTH   => MEM_DEPTH,
+            MEM_AWIDTH  => MEM_AWIDTH,
+            DRATIO      => RATIO,
+            AXIS_DWIDTH => O_DWIDTH
+          )
+  port map(
+
+         cfg_data_i     => reader_cfg, --nsamples_s,
+         --sts_data_o     => open,
+         done_i         => done_s,
+         send_i         => send_i, 
+         restart_o      => restart_s,
+
+         -- Master side
+         aclk           => m_axis_aclk,
+         aresetn        => m_axis_aresetn,
+         m_axis_tready  => m_axis_tready,
+         m_axis_tdata   => m_axis_tdata,
+         m_axis_tvalid  => m_axis_tvalid,
+         m_axis_tlast   => m_axis_tlast, 
+         m_axis_tkeep   => m_axis_tkeep, 
+          -- BRAM port
+         bram_clk       => bram_clk,   
+         bram_rst       => bram_rst,
+         bram_en        => bram_en,
+         bram_addr      => bram_addr,
+         bram_rddata    => bram_rddata
+       );
+
+end rtl;
diff --git a/cores/axis_avgr32bits_v1_0/axis_averager.vhd b/cores/axis_avgr32bits_v1_0/axis_averager.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..f0f1bc955de15cdd3152df04014969f015dc4428
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/axis_averager.vhd
@@ -0,0 +1,311 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_averager is
+  generic (
+            S_AXIS_DWIDTH : natural := 128; -- AXIS itf data width
+            M_AXIS_DWIDTH : natural := 32;  -- AXI itf data width
+            ADC_DWIDTH    : natural := 16;  -- ADC data width
+            MEM_AWIDTH    : natural := 10;  -- MEM addr width
+            MEM_DEPTH     : natural := 1024 --Max 2**16
+          );
+  port ( 
+         start_i           : in std_logic;
+         trig_i            : in std_logic;
+         send_i            : in std_logic;
+         done_o            : out std_logic;
+
+         --start_o           : out std_logic;
+         --trig_o            : out std_logic;
+         --mode_o            : out std_logic;
+
+         --avg_scope (as) debug signals
+         --as_state_mon_o    : out std_logic_vector(4-1 downto 0);
+         --as_avg_o          : out std_logic_vector(16-1 downto 0);
+
+         --ntoone (nt) debug signals
+         --nt_state_mon_o    : out std_logic_vector(4-1 downto 0);
+         --nt_avg_o          : out std_logic_vector(16-1 downto 0);
+
+         --en_o              : out std_logic;
+         --nsamples_o        : out std_logic_vector(16-1 downto 0);
+         --naverages_o       : out std_logic_vector(16-1 downto 0);
+         --tdp_addra_o       : out std_logic_vector(11-1 downto 0);
+         --tdp_addrb_o       : out std_logic_vector(11-1 downto 0);
+         --bram_en_o         : out std_logic;
+         --bram_addr_o       : out std_logic_vector(MEM_AWIDTH-1 downto 0);
+         --bram_rddata_o     : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0);
+         --bram_en_oo         : out std_logic;
+         --bram_addr_oo       : out std_logic_vector(MEM_AWIDTH-1 downto 0);
+         --bram_rddata_oo     : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0);
+
+         -- Slave config side
+         s_axis_cfg_aclk   : in std_logic;
+         s_axis_cfg_aresetn: in std_logic;
+         s_axis_cfg_reg_i  : in std_logic_vector(80-1 downto 0);
+
+         -- Slave data interface
+         s_axis_aclk       : in std_logic;
+         s_axis_aresetn    : in std_logic;
+         s_axis_tready     : out std_logic;
+         s_axis_tvalid     : in std_logic;
+         s_axis_tdata      : in std_logic_vector(S_AXIS_DWIDTH-1 downto 0);
+
+         -- Master data interface
+         m_axis_aclk       : in std_logic;
+         m_axis_aresetn    : in std_logic;
+         m_axis_tready     : in std_logic;
+         m_axis_tvalid     : out std_logic;
+         m_axis_tlast      : out std_logic;
+         m_axis_tkeep      : out std_logic_vector(4-1 downto 0);
+         m_axis_tdata      : out std_logic_vector(M_AXIS_DWIDTH-1 downto 0)
+       );
+end axis_averager;
+
+architecture rtl of axis_averager is
+
+  signal en_as, en_nt          : std_logic;
+  signal mode_s, mode_sm       : std_logic;
+  signal done_s, as_done, nt_done   : std_logic;
+  signal start_sync, trig_sync : std_logic;
+  signal start_os, trig_os, send_os : std_logic;
+  signal nsamples_s, naverages_s    : std_logic_vector(ADC_DWIDTH-1 downto 0);
+
+  --Register cfg/sts
+  signal s_axis_cfg_reg_sync   : std_logic_vector(80-1 downto 0);
+  signal m_axis_cfg_reg_sync   : std_logic_vector(80-1 downto 0);
+  signal m0_axis_aclk, m1_axis_aclk       : std_logic;
+  signal m0_axis_aresetn, m1_axis_aresetn : std_logic;
+  signal m0_axis_tdata, m1_axis_tdata     : std_logic_vector(S_AXIS_DWIDTH-1 downto 0);
+  signal m0_axis_tvalid, m1_axis_tvalid   : std_logic;
+  signal m0_axis_tready, m1_axis_tready   : std_logic;
+
+  signal m00_axis_aclk, m11_axis_aclk       : std_logic;
+  signal m00_axis_aresetn, m11_axis_aresetn : std_logic;
+  signal m00_axis_tdata, m11_axis_tdata     : std_logic_vector(M_AXIS_DWIDTH-1 downto 0);
+  signal m00_axis_tvalid, m11_axis_tvalid   : std_logic;
+  signal m00_axis_tready, m11_axis_tready   : std_logic;
+  signal m00_axis_tlast, m11_axis_tlast     : std_logic;
+  signal m00_axis_tkeep, m11_axis_tkeep     : std_logic_vector(4-1 downto 0);
+
+begin
+
+  --lets synchronize the cfg word
+  sync_cfg_s: entity work.n_sync
+  generic map(N => 80
+             )
+  port map(
+            aclk     => s_axis_aclk,
+            aresetn  => s_axis_aresetn,
+            in_async => s_axis_cfg_reg_i,
+            out_sync => s_axis_cfg_reg_sync
+          );
+
+  --mode_s      <= s_axis_cfg_reg_sync(64-1); 
+  --naverages_s <= s_axis_cfg_reg_sync(48-1 downto 32);
+  --nsamples_s  <= s_axis_cfg_reg_sync(16-1 downto 0);
+  mode_s      <= s_axis_cfg_reg_sync(32); 
+  naverages_s <= s_axis_cfg_reg_sync(32-1 downto 16);
+  nsamples_s  <= s_axis_cfg_reg_sync(16-1 downto 0);
+
+  --signals for debug
+  --mode_o      <= s_axis_cfg_reg_sync(64-1); 
+  --naverages_o <= s_axis_cfg_reg_sync(48-1 downto 32);
+  --nsamples_o  <= s_axis_cfg_reg_sync(16-1 downto 0);
+  en_as       <= not mode_s;
+  en_nt       <= mode_s;
+  
+  --en_o <= en_as;
+
+  os_start: entity work.edge_det
+  port map(
+            aclk     => s_axis_aclk,
+            aresetn  => s_axis_aresetn,
+            sig_i    => start_i,
+            sig_o    => start_os
+          );
+  --start_o <= start_os;
+
+  --lets synchronize the send signal
+  sync_send_m: entity work.edge_det
+  port map(
+            aclk     => m_axis_aclk,
+            aresetn  => m_axis_aresetn,
+            sig_i    => send_i,
+            sig_o    => send_os
+          );
+
+  os_trig: entity work.edge_det
+  port map(
+            aclk     => s_axis_aclk,
+            aresetn  => s_axis_aresetn,
+            sig_i    => trig_i,
+            sig_o    => trig_os
+          );
+  --trig_o <= trig_os;
+
+  --lets synchronize the cfg word
+  --sync_cfg_m: entity work.n_sync
+  --generic map(N => 80
+  --           )
+  --port map(
+  --          aclk     => m_axis_aclk,
+  --          aresetn  => m_axis_aresetn,
+  --          in_async => s_axis_cfg_reg_i,
+  --          out_sync => m_axis_cfg_reg_sync
+  --        );
+  ----mode_sm      <= m_axis_cfg_reg_sync(32-1); 
+  --mode_sm      <= m_axis_cfg_reg_sync(64-1); 
+
+  --Select the data input
+  sig_sel_i: entity work.axis_signal_selector 
+  generic map(
+               AXIS_DWIDTH => S_AXIS_DWIDTH
+             )
+  port map(
+            sel            => mode_s,
+            s_axis_aclk    => s_axis_aclk,
+            s_axis_aresetn => s_axis_aresetn,
+            s_axis_tdata   => s_axis_tdata,
+            s_axis_tvalid  => s_axis_tvalid,
+            s_axis_tready  => s_axis_tready,
+            
+            m0_axis_aclk   => m0_axis_aclk,
+            m0_axis_aresetn=> m0_axis_aresetn,
+            m0_axis_tdata  => m0_axis_tdata,
+            m0_axis_tvalid => m0_axis_tvalid,
+            m0_axis_tready => m0_axis_tready,
+
+            m1_axis_aclk   => m1_axis_aclk,
+            m1_axis_aresetn=> m1_axis_aresetn,
+            m1_axis_tdata  => m1_axis_tdata,
+            m1_axis_tvalid => m1_axis_tvalid,
+            m1_axis_tready => m1_axis_tready
+);
+
+  --Averager scope
+  avg_scope_i: entity work.avg_scope 
+  generic map(
+               I_DWIDTH   => S_AXIS_DWIDTH,
+               O_DWIDTH   => M_AXIS_DWIDTH,
+               ADC_DWIDTH => ADC_DWIDTH,
+               MEM_AWIDTH => MEM_AWIDTH,
+               MEM_DEPTH  => MEM_DEPTH
+             )
+  port map(
+            start_i        => start_os,
+            send_i         => send_os,
+            trig_i         => trig_os,
+            done_o         => as_done,
+            --state_mon      => as_state_mon_o,
+            en_i           => en_as,
+            naverages_i    => naverages_s,
+            nsamples_i     => nsamples_s,
+            --bram_en_o      => bram_en_o,
+            --bram_addr_o    => bram_addr_o,
+            --bram_rddata_o  => bram_rddata_o,
+            --bram_en_oo      => bram_en_oo,
+            --bram_addr_oo    => bram_addr_oo,
+            --bram_rddata_oo  => bram_rddata_oo,
+
+            --avg_o          => as_avg_o,
+
+            --tdp_addra_o    => tdp_addra_o,
+            --tdp_addrb_o    => tdp_addrb_o,
+
+            s_axis_cfg_aclk=> s_axis_cfg_aclk,
+            s_axis_cfg_aresetn => s_axis_cfg_aresetn,
+
+            s_axis_aclk    => m0_axis_aclk,
+            s_axis_aresetn => m0_axis_aresetn,
+            s_axis_tready  => m0_axis_tready,
+            s_axis_tvalid  => m0_axis_tvalid,
+            s_axis_tdata   => m0_axis_tdata,
+
+            m_axis_aclk    => m_axis_aclk,
+            m_axis_aresetn => m_axis_aresetn,
+            m_axis_tready  => m00_axis_tready,
+            m_axis_tdata   => m00_axis_tdata,
+            m_axis_tvalid  => m00_axis_tvalid,
+            m_axis_tlast   => m00_axis_tlast,
+            m_axis_tkeep   => m00_axis_tkeep
+          );
+
+  --Averager N to One
+  avg_ntoone_i: entity work.avg_ntoone 
+  generic map(
+               I_DWIDTH   => S_AXIS_DWIDTH,
+               O_DWIDTH   => M_AXIS_DWIDTH,
+               ADC_DWIDTH => ADC_DWIDTH,
+               MEM_AWIDTH => MEM_AWIDTH,
+               MEM_DEPTH  => MEM_DEPTH
+             )
+  port map(
+            start_i        => start_os,
+            send_i         => send_os,
+            trig_i         => trig_os,
+            done_o         => nt_done,
+            --state_mon      => nt_state_mon_o,
+            en_i           => en_nt,
+            naverages_i    => naverages_s,
+            nsamples_i     => nsamples_s,
+            --avg_o          => nt_avg_o,
+
+            s_axis_cfg_aclk=> s_axis_cfg_aclk,
+            s_axis_cfg_aresetn => s_axis_cfg_aresetn,
+
+            s_axis_aclk    => m1_axis_aclk,
+            s_axis_aresetn => m1_axis_aresetn,
+            s_axis_tready  => m1_axis_tready,
+            s_axis_tvalid  => m1_axis_tvalid,
+            s_axis_tdata   => m1_axis_tdata,
+
+            m_axis_aclk    => m_axis_aclk,
+            m_axis_aresetn => m_axis_aresetn,
+            m_axis_tready  => m11_axis_tready,
+            m_axis_tdata   => m11_axis_tdata,
+            m_axis_tvalid  => m11_axis_tvalid,
+            m_axis_tlast   => m11_axis_tlast,
+            m_axis_tkeep   => m11_axis_tkeep
+          );
+
+  done_s <= nt_done when (mode_s = '1') else as_done;
+  --lets synchronize the done signal
+  sync_done: entity work.sync
+  port map(
+            aclk     => s_axis_cfg_aclk,
+            aresetn  => s_axis_cfg_aresetn,
+            in_async => done_s,
+            out_sync => done_o
+          );
+
+  --Mux the output data
+  sig_mux_i: entity work.axis_signal_mux 
+  generic map(
+               AXIS_DWIDTH => M_AXIS_DWIDTH
+             )
+  port map(
+            sel            => mode_s, --m,
+
+            s0_axis_tdata   => m00_axis_tdata,
+            s0_axis_tvalid  => m00_axis_tvalid,
+            s0_axis_tready  => m00_axis_tready,
+            s0_axis_tlast   => m00_axis_tlast,
+            s0_axis_tkeep   => m00_axis_tkeep,
+
+            s1_axis_tdata   => m11_axis_tdata,
+            s1_axis_tvalid  => m11_axis_tvalid,
+            s1_axis_tready  => m11_axis_tready,
+            s1_axis_tlast   => m11_axis_tlast,
+            s1_axis_tkeep   => m11_axis_tkeep,
+
+            m_axis_tdata   => m_axis_tdata,
+            m_axis_tvalid  => m_axis_tvalid,
+            m_axis_tready  => m_axis_tready,
+            m_axis_tlast   => m_axis_tlast,
+            m_axis_tkeep   => m_axis_tkeep
+
+);
+
+end rtl;
diff --git a/cores/axis_avgr32bits_v1_0/axis_signal_mux.vhd b/cores/axis_avgr32bits_v1_0/axis_signal_mux.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..79f91ecc8046551fdfd4b7567fad12944c21049a
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/axis_signal_mux.vhd
@@ -0,0 +1,43 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_signal_mux is
+generic (
+      AXIS_DWIDTH : natural := 32
+);
+port (
+  sel               : in std_logic;
+
+  s0_axis_tdata     : in std_logic_vector(AXIS_DWIDTH-1 downto 0);        
+  s0_axis_tvalid    : in std_logic;                               
+  s0_axis_tready    : out std_logic;                               
+  s0_axis_tlast     : in std_logic;                               
+  s0_axis_tkeep     : in std_logic_vector(4-1 downto 0);        
+
+  s1_axis_tdata     : in std_logic_vector(AXIS_DWIDTH-1 downto 0);  
+  s1_axis_tvalid    : in std_logic;                         
+  s1_axis_tready    : out std_logic;                         
+  s1_axis_tlast     : in std_logic;                               
+  s1_axis_tkeep     : in std_logic_vector(4-1 downto 0);        
+
+  m_axis_tdata      : out std_logic_vector(AXIS_DWIDTH-1 downto 0);  
+  m_axis_tvalid     : out std_logic;                         
+  m_axis_tlast      : out std_logic;                               
+  m_axis_tkeep      : out std_logic_vector(4-1 downto 0);        
+  m_axis_tready     : in std_logic                         
+);
+end axis_signal_mux;
+
+architecture rtl of axis_signal_mux is
+begin
+
+  s0_axis_tready <= m_axis_tready when sel = '0' else '0';
+  s1_axis_tready <= m_axis_tready when sel = '1' else '0';
+
+  m_axis_tdata  <= s0_axis_tdata when sel = '0' else s1_axis_tdata;
+  m_axis_tvalid <= s0_axis_tvalid when sel = '0' else s1_axis_tvalid;
+  m_axis_tlast  <= s0_axis_tlast when sel = '0' else s1_axis_tlast;
+  m_axis_tkeep  <= s0_axis_tkeep when sel = '0' else s1_axis_tkeep;
+
+end rtl;
diff --git a/cores/axis_avgr32bits_v1_0/axis_signal_selector.vhd b/cores/axis_avgr32bits_v1_0/axis_signal_selector.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a9bda66e8dbd75041603249a57a6a14b220183d3
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/axis_signal_selector.vhd
@@ -0,0 +1,48 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_signal_selector is
+generic (
+      AXIS_DWIDTH : natural := 32
+);
+port (
+  sel                : in std_logic;
+  -- System signals
+  s_axis_aclk        : in std_logic;
+  s_axis_aresetn     : in std_logic;
+  s_axis_tdata       : in std_logic_vector(AXIS_DWIDTH-1 downto 0);        
+  s_axis_tvalid      : in std_logic;                               
+  s_axis_tready      : out std_logic;                               
+
+  m0_axis_aclk       : out std_logic;
+  m0_axis_aresetn    : out std_logic;
+  m0_axis_tdata      : out std_logic_vector(AXIS_DWIDTH-1 downto 0);  
+  m0_axis_tvalid     : out std_logic;                         
+  m0_axis_tready     : in std_logic;                         
+
+  m1_axis_aclk       : out std_logic;
+  m1_axis_aresetn    : out std_logic;
+  m1_axis_tdata      : out std_logic_vector(AXIS_DWIDTH-1 downto 0);  
+  m1_axis_tvalid     : out std_logic;                         
+  m1_axis_tready     : in std_logic                         
+);
+end axis_signal_selector;
+
+architecture rtl of axis_signal_selector is
+begin
+  m0_axis_aclk    <= s_axis_aclk; 
+  m0_axis_aresetn <= s_axis_aresetn; 
+
+  m1_axis_aclk    <= s_axis_aclk; 
+  m1_axis_aresetn <= s_axis_aresetn; 
+
+  s_axis_tready <= m0_axis_tready when sel = '0' else m1_axis_tready;
+
+  m0_axis_tvalid <= s_axis_tvalid when sel = '0' else '0';
+  m0_axis_tdata  <= s_axis_tdata when sel = '0' else (others => '0');
+
+  m1_axis_tvalid <= s_axis_tvalid when sel = '1' else '0';
+  m1_axis_tdata  <= s_axis_tdata when sel = '1' else (others => '0');
+
+end rtl;
diff --git a/cores/axis_avgr32bits_v1_0/bram_reader.vhd b/cores/axis_avgr32bits_v1_0/bram_reader.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..9bd369d8b48a8f9199154b51ea7e5600f5d4f94f
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/bram_reader.vhd
@@ -0,0 +1,184 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity bram_reader is
+  generic (
+            MEM_DEPTH   : natural := 1024;
+            MEM_AWIDTH  : natural := 10;
+            DRATIO      : natural := 8;
+            AXIS_DWIDTH : natural := 32
+          );
+  port (
+         -- System signals
+         aclk           : in std_logic;
+         aresetn        : in std_logic;
+
+         cfg_data_i     : in std_logic_vector(16-1 downto 0);
+         --sts_data_o     : out std_logic_vector(AXIS_DWIDTH-1 downto 0);
+         done_i         : in std_logic;
+         send_i         : in std_logic;
+         restart_o      : out std_logic;
+
+         -- Master side
+         m_axis_tready  : in std_logic;
+         m_axis_tdata   : out std_logic_vector(AXIS_DWIDTH-1 downto 0);
+         m_axis_tvalid  : out std_logic;
+         m_axis_tlast   : out std_logic;
+         m_axis_tkeep   : out std_logic_vector(4-1 downto 0);
+
+         -- BRAM port
+         bram_clk       : out std_logic;
+         bram_rst       : out std_logic;
+         bram_en        : out std_logic;
+         bram_addr      : out std_logic_vector(MEM_AWIDTH-1 downto 0);
+         bram_rddata    : in std_logic_vector((DRATIO*AXIS_DWIDTH)-1 downto 0)
+       );
+end bram_reader;
+
+architecture rtl of bram_reader is
+
+  type state_t is (
+  ST_IDLE,
+  ST_EN_BRAM,
+  ST_LOAD_DATA,
+  ST_SEND_DATA,
+  --ST_TLAST,
+  ST_FINISH
+);
+signal state_reg, state_next   : state_t;
+
+signal addr_reg, addr_next     : unsigned(MEM_AWIDTH-1 downto 0);
+signal tlast_s, rst_s, en_s    : std_logic;
+signal tvalid_s                : std_logic;
+signal restart_s               : std_logic;
+signal tkeep_s                 : std_logic_vector(4-1 downto 0);
+--signal bram_st_mon             : std_logic_vector(4-1 downto 0);
+signal load_s                  : std_logic;
+signal cntr_reg, cntr_next     : unsigned(DRATIO-1 downto 0); --4 should be enough
+
+begin
+
+  sh_reg_i : entity work.shift_reg_vect
+  generic map(
+               DWIDTH => 32,
+               DRATIO => 8
+             )
+  port map(
+            aclk   => aclk,
+            --serin  => (others => '0'),
+            load   => load_s,
+            parin  => bram_rddata,
+            serout => m_axis_tdata
+          );
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if aresetn = '0' then
+        state_reg  <= ST_IDLE;
+        addr_reg   <= (others => '0');
+        cntr_reg   <= (others => '0');
+      else 
+        state_reg  <= state_next;
+        addr_reg   <= addr_next;
+        cntr_reg   <= cntr_next;
+      end if;
+    end if;
+  end process;
+
+  --Next state logic
+  process(state_reg, addr_reg, cntr_reg, done_i, send_i, m_axis_tready,
+    cfg_data_i)
+  begin
+    state_next   <= state_reg;
+    addr_next    <= addr_reg;
+    cntr_next    <= cntr_reg;
+    tvalid_s     <= '0';
+    tlast_s      <= '0';
+    restart_s    <= '0';
+    en_s         <= '0';
+    rst_s        <= '0';
+    load_s       <= '0';
+    tkeep_s      <= (others => '0');
+
+    case state_reg is
+      when ST_IDLE => 
+        --bram_st_mon <= "0000"; --state mon
+        rst_s       <= '1';
+        addr_next  <= (others => '0');
+        if (done_i = '1') and (send_i = '1') then
+          state_next  <= ST_EN_BRAM;
+        else
+          state_next  <= ST_IDLE;
+        end if;
+
+      when ST_EN_BRAM =>
+        --bram_st_mon <= "0001"; --state mon
+        if m_axis_tready = '1' then
+          en_s <= '1';
+          addr_next <= addr_reg + 1;
+          state_next  <= ST_LOAD_DATA;
+        else
+          state_next <= ST_EN_BRAM;
+        end if;
+
+      when ST_LOAD_DATA =>
+        en_s <= '1';
+        load_s <= '1';
+        state_next  <= ST_SEND_DATA;
+
+      when ST_SEND_DATA =>
+        --bram_st_mon <= "0010"; --state mon
+        tvalid_s <= '1';
+        tkeep_s  <= (others => '1');
+        if m_axis_tready = '1' then
+          cntr_next <= cntr_reg + 1;
+          if (cntr_reg = DRATIO-1) then
+            addr_next <= addr_reg + 1;
+            if (addr_reg = unsigned(cfg_data_i)) then
+              addr_next <= (others => '0');
+              tlast_s <= '1';
+              cntr_next <= (others => '0');
+              state_next <= ST_FINISH;
+            else
+              en_s <= '1';
+              load_s <= '1';
+              cntr_next <= (others => '0');
+              state_next <= ST_SEND_DATA;
+            end if;
+          else 
+            state_next <= ST_SEND_DATA;
+          end if;
+        else 
+          state_next <= ST_SEND_DATA;
+        end if;
+
+    --when ST_TLAST =>
+    --  bram_st_mon <= "0011";
+    --  tvalid_s <= '1';
+    --  tlast_s <= '1';
+    --  state_next <= ST_FINISH;
+
+      when ST_FINISH =>
+        --bram_st_mon <= "0011"; --state mon
+        restart_s <= '1';
+        state_next <= ST_IDLE;
+
+    end case;
+  end process;
+
+  --sts_data_o <= std_logic_vector(resize(addr_reg,AXIS_DWIDTH));
+
+--m_axis_tdata  <= bram_rddata;
+  m_axis_tvalid <= tvalid_s;
+  m_axis_tlast  <= tlast_s;
+  m_axis_tkeep  <= tkeep_s;
+
+  bram_clk <= aclk;
+  bram_rst <= rst_s;
+  bram_en  <= en_s;
+  bram_addr <= std_logic_vector(addr_reg);
+  restart_o <= restart_s; 
+
+end rtl;
diff --git a/cores/axis_avgr32bits_v1_0/bram_reader_nt.vhd b/cores/axis_avgr32bits_v1_0/bram_reader_nt.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..60c09f41ce85ad497c45dcebd0b251c830bbc071
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/bram_reader_nt.vhd
@@ -0,0 +1,149 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity bram_reader_nt is
+  generic (
+            MEM_DEPTH   : natural := 1024;
+            MEM_AWIDTH  : natural := 10;
+            AXIS_DWIDTH : natural := 16
+          );
+  port (
+         -- System signals
+         aclk           : in std_logic;
+         aresetn        : in std_logic;
+
+         cfg_data_i     : in std_logic_vector(16-1 downto 0);
+         sts_data_o     : out std_logic_vector(16-1 downto 0);
+         done_i         : in std_logic;
+         send_i         : in std_logic;
+         restart_o      : out std_logic;
+
+         -- Master side
+         m_axis_tready  : in std_logic;
+         m_axis_tdata   : out std_logic_vector(AXIS_DWIDTH-1 downto 0);
+         m_axis_tvalid  : out std_logic;
+         m_axis_tlast   : out std_logic;
+         m_axis_tkeep   : out std_logic_vector(4-1 downto 0);
+
+         -- BRAM port
+         bram_clk       : out std_logic;
+         bram_rst       : out std_logic;
+         bram_en        : out std_logic;
+         bram_addr      : out std_logic_vector(MEM_AWIDTH-1 downto 0);
+         bram_rddata    : in std_logic_vector(AXIS_DWIDTH-1 downto 0)
+       );
+end bram_reader_nt;
+
+architecture rtl of bram_reader_nt is
+
+  type state_t is (
+  ST_IDLE,
+  ST_EN_BRAM,
+  ST_SEND_DATA,
+  ST_TLAST,
+  ST_FINISH
+);
+signal state_reg, state_next   : state_t;
+
+signal addr_reg, addr_next     : unsigned(MEM_AWIDTH-1 downto 0);
+signal tlast_s, rst_s, en_s    : std_logic;
+signal tvalid_s                : std_logic;
+signal restart_s               : std_logic;
+signal tkeep_s                 : std_logic_vector(4-1 downto 0);
+signal bram_st_mon             : std_logic_vector(4-1 downto 0);
+
+begin
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if aresetn = '0' then
+        state_reg  <= ST_IDLE;
+        addr_reg   <= (others => '0');
+      else 
+        state_reg  <= state_next;
+        addr_reg   <= addr_next;
+      end if;
+    end if;
+  end process;
+
+  --Next state logic
+  process(state_reg, addr_reg, done_i, send_i, m_axis_tready,
+    cfg_data_i)
+  begin
+    state_next   <= state_reg;
+    addr_next    <= addr_reg;
+    tvalid_s     <= '0';
+    tlast_s      <= '0';
+    restart_s    <= '0';
+    en_s         <= '0';
+    rst_s        <= '0';
+    tkeep_s      <= (others => '0');
+
+    case state_reg is
+      when ST_IDLE => 
+        bram_st_mon <= "0000"; --state mon
+        rst_s       <= '1';
+        addr_next  <= (others => '0');
+        if (done_i = '1') and (send_i = '1') then
+            state_next  <= ST_EN_BRAM;
+        else
+          state_next  <= ST_IDLE;
+        end if;
+
+      when ST_EN_BRAM =>
+        bram_st_mon <= "0001"; --state mon
+        if m_axis_tready = '1' then
+          en_s <= '1';
+          addr_next <= addr_reg + 1;
+          state_next  <= ST_SEND_DATA;
+        else
+          state_next <= ST_EN_BRAM;
+        end if;
+
+      when ST_SEND_DATA =>
+        bram_st_mon <= "0010"; --state mon
+        tvalid_s <= '1';
+        tkeep_s  <= (others => '1');
+        if m_axis_tready = '1' then
+          en_s     <= '1';
+          addr_next <= addr_reg + 1;
+          if (addr_reg = unsigned(cfg_data_i)-1) then
+            addr_next <= (others => '0');
+            state_next <= ST_TLAST;
+          else
+            state_next <= ST_SEND_DATA;
+          end if;
+        else 
+          state_next <= ST_SEND_DATA;
+        end if;
+
+      when ST_TLAST =>
+        bram_st_mon <= "0011";
+        tvalid_s <= '1';
+        tlast_s <= '1';
+        state_next <= ST_FINISH;
+
+      when ST_FINISH =>
+        bram_st_mon <= "0100"; --state mon
+        restart_s <= '1';
+        state_next <= ST_IDLE;
+
+    end case;
+  end process;
+
+  sts_data_o <= std_logic_vector(resize(addr_reg,16));
+
+  m_axis_tdata  <= bram_rddata;
+  m_axis_tvalid <= tvalid_s;
+  m_axis_tlast  <= tlast_s;
+  m_axis_tkeep  <= tkeep_s;
+
+  bram_clk <= aclk;
+  bram_rst <= rst_s;
+  bram_en  <= en_s;
+  bram_addr <= std_logic_vector(addr_reg);
+  restart_o <= restart_s; 
+
+end rtl;
diff --git a/cores/axis_avgr32bits_v1_0/core_config.tcl b/cores/axis_avgr32bits_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..18531b2557d0d9efb7c7e0e1265db5457ed9a8bb
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/core_config.tcl
@@ -0,0 +1,29 @@
+set display_name {AXI4-Stream Averager 32 bits v1.0}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter S_AXIS_DWIDTH {S_AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter M_AXIS_DWIDTH {M_AXIS TDATA WIDTH} {Width of the M_AXI data bus.}
+core_parameter ADC_DWIDTH {ADC DATA WIDTH} {Width of the ADC data.}
+core_parameter MEM_AWIDTH {MEMORY ADDR WIDTH} {Address width of the data memory.}
+core_parameter MEM_DEPTH {MEMORY DEPTH} {Depth of the data memory.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces s_axis_aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS $parameter
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces m_axis_aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS $parameter
+
diff --git a/cores/axis_avgr32bits_v1_0/edge_det.vhd b/cores/axis_avgr32bits_v1_0/edge_det.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..11dfb19e15f76895c353a79309729f16aa8c4609
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/edge_det.vhd
@@ -0,0 +1,58 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity edge_det is
+  port(
+        aclk   : in std_logic;
+        aresetn: in std_logic;
+        sig_i  : in std_logic;
+        sig_o  : out std_logic
+      );
+end edge_det;
+
+architecture rtl of edge_det is
+  type state_t is (zero, edge, one);
+  signal state_reg, state_next: state_t;
+begin
+   -- state register
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn='0') then
+        state_reg <= zero;
+      else
+        state_reg <= state_next;
+      end if;
+    end if;
+  end process;
+
+   -- next-state logic
+  process(state_reg, sig_i)
+  begin
+    case state_reg is
+      when zero=>
+        if sig_i = '1' then
+          state_next <= edge;
+        else
+          state_next <= zero;
+        end if;
+      when edge =>
+        if sig_i = '1' then
+          state_next <= one;
+        else
+          state_next <= zero;
+        end if;
+      when one =>
+        if sig_i = '1' then
+          state_next <= one;
+        else
+          state_next <= zero;
+        end if;
+    end case;
+  end process;
+
+   -- Moore output logic
+  sig_o <= '1' when state_reg=edge else
+           '0';
+
+end rtl;
diff --git a/cores/axis_avgr32bits_v1_0/n_sync.vhd b/cores/axis_avgr32bits_v1_0/n_sync.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..1a92e1d9063bda1af8dd5ab5bf4738ec802fec89
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/n_sync.vhd
@@ -0,0 +1,46 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity n_sync is
+  generic(
+           N : natural
+         );
+  port(
+        aclk     : in std_logic;
+        aresetn  : in std_logic;
+        in_async : in std_logic_vector(N-1 downto 0);
+        out_sync : out std_logic_vector(N-1 downto 0)
+      );
+end n_sync;
+
+architecture two_ff_arch of n_sync is
+  signal meta_reg, meta_next  : std_logic_vector(N-1 downto 0);
+  signal sync_reg, sync_next: std_logic_vector(N-1 downto 0);
+
+  attribute ASYNC_REG : string;
+  attribute ASYNC_REG of meta_reg: signal is "TRUE";
+  attribute ASYNC_REG of sync_reg: signal is "TRUE";
+
+begin
+
+  -- two registers
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn='0') then
+        meta_reg <= (others=>'0');
+        sync_reg <= (others=>'0');
+      else
+        meta_reg <= meta_next;
+        sync_reg <= sync_next;
+      end if;
+    end if;
+  end process;
+
+  -- next-state logic
+  meta_next <= in_async;
+  sync_next <= meta_reg;
+  -- output
+  out_sync <= sync_reg;
+
+end two_ff_arch;
diff --git a/cores/axis_avgr32bits_v1_0/sync.vhd b/cores/axis_avgr32bits_v1_0/sync.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..492bcf687e2f451fc1ca74e627086b861f6dad6f
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/sync.vhd
@@ -0,0 +1,43 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+--synchronizer
+entity sync is
+  port(
+        aclk     : in std_logic;
+        aresetn  : in std_logic;
+        in_async : in std_logic;
+        out_sync : out std_logic
+      );
+end sync;
+
+architecture two_ff_arch of sync is
+  signal meta_reg, meta_next : std_logic;
+  signal sync_reg, sync_next: std_logic;
+
+  attribute ASYNC_REG : string;
+  attribute ASYNC_REG of meta_reg: signal is "TRUE";
+  attribute ASYNC_REG of sync_reg: signal is "TRUE";
+begin
+
+  -- two registers
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn='0') then
+        meta_reg <= '0';
+        sync_reg <= '0';
+      else
+        meta_reg <= meta_next;
+        sync_reg <= sync_next;
+      end if;
+    end if;
+  end process;
+
+  -- next-state logic
+  meta_next <= in_async;
+  sync_next <= meta_reg;
+  -- output
+  out_sync <= sync_reg;
+
+end two_ff_arch;
diff --git a/cores/axis_avgr32bits_v1_0/tdp_ram_pip.vhd b/cores/axis_avgr32bits_v1_0/tdp_ram_pip.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..712f43ace738fbbfaaa30aa94a6c03ed6c521997
--- /dev/null
+++ b/cores/axis_avgr32bits_v1_0/tdp_ram_pip.vhd
@@ -0,0 +1,86 @@
+-- Block RAM with Optional Output Registers
+-- File: modified from rams_pipeline.vhd
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity tdp_ram_pip is
+  generic (
+            AWIDTH       : integer := 16;
+            DWIDTH       : integer := 16
+          );
+  port(
+        clka  : in  std_logic;
+        --rsta  : in  std_logic;
+        --ena   : in  std_logic;
+        wea   : in  std_logic;
+        addra : in  std_logic_vector(AWIDTH-1 downto 0);
+        dia   : in  std_logic_vector(DWIDTH-1 downto 0);
+        --doa   : out std_logic_vector(DWIDTH-1 downto 0);
+        clkb  : in  std_logic;
+        rstb  : in  std_logic;
+        enb   : in  std_logic;
+        --web   : in  std_logic;
+        addrb : in  std_logic_vector(AWIDTH-1 downto 0);
+        --dib   : in  std_logic_vector(DWIDTH-1 downto 0);
+        dob   : out std_logic_vector(DWIDTH-1 downto 0)
+      );
+end tdp_ram_pip;
+
+architecture rtl of tdp_ram_pip is
+  type ram_t is array (0 to 2**AWIDTH-1) of std_logic_vector(DWIDTH-1 downto 0);
+  signal ram : ram_t := (others => (others => '0')); 
+  signal a_reg, a_next : std_logic_vector(DWIDTH-1 downto 0);
+  signal b_reg, b_next : std_logic_vector(DWIDTH-1 downto 0);
+
+begin
+
+  process(clka)
+  begin
+    if rising_edge(clka) then
+      if wea = '1' then
+        ram(to_integer(unsigned(addra))) <= dia;
+      end if;
+    --do1 <= ram(to_integer(unsigned(addra)));
+    end if;
+  end process;
+
+  --process(clka)
+  --begin
+  --  if rising_edge(clka) then
+  --    if rsta = '1' then
+  --      a_reg <= (others => '0');
+  --    else
+  --      a_reg <= a_next;
+  --    end if;
+  --  end if;
+  --end process;
+  ----next state logic
+  --a_next <= ram(to_integer(unsigned(addra))) when ena = '1' else a_reg;
+  --doa <= a_reg;
+
+  --process(clkb)
+  --begin
+  --  if rising_edge(clkb) then
+  --    if web = '1' then
+  --      ram(to_integer(unsigned(addrb))) <= dib;
+  --    end if;
+  --  --do2 <= ram(to_integer(unsigned(addrb)));
+  --  end if;
+  --end process;
+
+  process(clkb)
+  begin
+    if rising_edge(clkb) then
+      if rstb = '1' then
+        b_reg <= (others => '0');
+      else
+        b_reg <= b_next;
+      end if;
+    end if;
+  end process;
+  --next state logic
+  b_next <= ram(to_integer(unsigned(addrb))) when enb = '1' else b_reg;
+  dob <= b_reg;
+
+end rtl;
diff --git a/cores/axis_avgr_v1_0/asym_ram_tdp.vhd b/cores/axis_avgr_v1_0/asym_ram_tdp.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..cd074ff366ddf984b9bff4f4a0eec32ded2086b1
--- /dev/null
+++ b/cores/axis_avgr_v1_0/asym_ram_tdp.vhd
@@ -0,0 +1,115 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity asym_ram_tdp is
+  generic (
+            WIDTHA      : integer   := 4;
+            --SIZEA       : integer   := 1024;
+            ADDRWIDTHA  : integer   := 10;
+            WIDTHB      : integer   := 16;
+            --SIZEB       : integer   := 256;
+            ADDRWIDTHB  : integer   := 8 
+          );
+  port (
+         clka        : in  std_logic;
+         clkb        : in  std_logic;
+         ena         : in  std_logic;
+         enb         : in  std_logic;
+         wea         : in  std_logic;
+         web         : in  std_logic;
+         addra       : in  std_logic_vector(ADDRWIDTHA-1 downto 0);
+         addrb       : in  std_logic_vector(ADDRWIDTHB-1 downto 0);
+         dia         : in  std_logic_vector(WIDTHA-1 downto 0);
+         dib         : in  std_logic_vector(WIDTHB-1 downto 0);
+         doa         : out std_logic_vector(WIDTHA-1 downto 0);
+         dob         : out std_logic_vector(WIDTHB-1 downto 0)
+       );
+end asym_ram_tdp;
+
+
+architecture asym_ram_tdp_arc of asym_ram_tdp is
+
+  function max(L, R: INTEGER) return INTEGER is
+  begin
+    if L > R then
+      return L;
+    else
+      return R;
+    end if;
+  end;
+
+  function min(L, R: INTEGER) return INTEGER is
+  begin
+    if L < R then
+      return L;
+    else
+      return R;
+    end if;
+  end;
+
+  function log2 (val: INTEGER) return natural is
+    variable res : natural;
+  begin
+    for i in 0 to 31 loop
+      if (val <= (2**i)) then
+        res := i;
+        exit;
+      end if;
+    end loop;
+    return res;
+  end function log2;
+
+  constant SIZEA    : integer := 2**ADDRWIDTHA;
+  constant SIZEB    : integer := 2**ADDRWIDTHB;
+  constant minWIDTH : integer := min(WIDTHA,WIDTHB);
+  constant maxWIDTH : integer := max(WIDTHA,WIDTHB);
+  constant maxSIZE  : integer := max(SIZEA,SIZEB);
+  constant RATIO    : integer := maxWIDTH / minWIDTH;
+
+  -- An asymmetric RAM is modeled in a similar way as a symmetric RAM, with an
+  -- array of array object. Its aspect ratio corresponds to the port with the lower
+  -- data width (larger depth).
+  type ramType is array (0 to maxSIZE-1) of std_logic_vector(minWIDTH-1 downto 0);
+
+  shared variable ram : ramType := (others => (others => '0'));
+
+  signal readA  : std_logic_vector(WIDTHA-1 downto 0):= (others => '0');
+  signal readB  : std_logic_vector(WIDTHB-1 downto 0):= (others => '0');
+  signal regA   : std_logic_vector(WIDTHA-1 downto 0):= (others => '0');
+  signal regB   : std_logic_vector(WIDTHB-1 downto 0):= (others => '0');
+
+begin
+
+  process (clka)
+  begin
+    if rising_edge(clka) then
+      if ena = '1' then
+        readA <= ram(to_integer(unsigned(addra)));
+        if wea = '1' then 
+          ram(to_integer(unsigned(addra))) := dia;
+        end if;
+      end if;
+      regA <= readA;
+    end if;
+  end process;
+
+  process (clkb)
+  begin
+    if rising_edge(clkb) then
+      for i in 0 to RATIO-1 loop
+        if enb = '1' then
+          readB((i+1)*minWIDTH-1 downto i*minWIDTH) <= ram(to_integer(unsigned(addrb) & to_unsigned(i,log2(RATIO))));
+          if web = '1' then
+            ram(to_integer(unsigned(addrb) & to_unsigned(i,log2(RATIO)))) := dib((i+1)*minWIDTH-1 downto i*minWIDTH);
+          end if;              
+        end if;
+      end loop;
+      regB <= readB;
+    end if;
+  end process;
+
+  doa <= regA;
+  dob <= regB;
+
+end asym_ram_tdp_arc;
diff --git a/cores/axis_avgr_v1_0/averager.vhd b/cores/axis_avgr_v1_0/averager.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..14987334ba1bca9520ee23ca033afc56a4cb5b24
--- /dev/null
+++ b/cores/axis_avgr_v1_0/averager.vhd
@@ -0,0 +1,330 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity averager is
+  generic (
+            IN_DATA_WIDTH  : natural := 128; -- ADC data width x8
+            OUT_DATA_WIDTH : natural := 32;  -- AXI data width
+            ADC_DATA_WIDTH : natural := 16;  -- ADC data width
+            MEM_DEPTH      : natural := 10   -- Max 2**16
+          );
+  port ( 
+         -- System signals
+         aclk              : in std_logic;
+         aresetn           : in std_logic;
+
+         -- Averager specific ports
+         start             : in std_logic;
+         restart           : in std_logic;
+         mode              : in std_logic; --0- (default) avg scope, 1-avg nsamples to one value
+         trig_i            : in std_logic;
+         --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW
+         nsamples          : in std_logic_vector(32-1 downto 0); 
+         naverages         : in std_logic_vector(32-1 downto 0);
+         done              : out std_logic;
+         averages_out      : out std_logic_vector(32-1 downto 0);
+         -- BRAM PORTA. Reading port
+         bram_porta_clk    : in std_logic;
+         --bram_porta_rst    : in std_logic;
+         bram_porta_wrdata : in std_logic_vector(OUT_DATA_WIDTH-1 downto 0);
+         bram_porta_we     : in std_logic;
+         bram_porta_addr   : in std_logic_vector(OUT_DATA_WIDTH-1 downto 0);
+         bram_porta_rddata : out std_logic_vector(OUT_DATA_WIDTH-1 downto 0);
+
+         -- Slave side     
+         s_axis_tready     : out std_logic;
+         s_axis_tvalid     : in std_logic;
+         s_axis_tdata      : in std_logic_vector(IN_DATA_WIDTH-1 downto 0)
+       );
+end averager;
+
+architecture rtl of averager is
+
+  function log2c(n: integer) return integer is
+    variable m, p: integer;
+  begin
+    m := 0;
+    p := 1;
+    while p < n loop
+      m := m + 1;
+      p := p * 2;
+    end loop;
+    return m;
+  end log2c;
+
+  constant RATIO          : natural := IN_DATA_WIDTH/ADC_DATA_WIDTH;
+  constant MEM_ADDR_WIDTH : natural := log2c(MEM_DEPTH);
+
+  type state_t is (
+--  ST_WRITE_ZEROS, 
+  ST_IDLE, 
+  ST_WRITE_ZEROS, 
+  ST_WAIT_TRIG, 
+  ST_AVG_SCOPE,
+  ST_AVG_N1,
+  ST_WRITE_AVG,
+  ST_FINISH 
+);
+signal state_reg, state_next      : state_t;
+
+signal addr_reg, addr_next        : std_logic_vector(log2c(MEM_DEPTH/RATIO)-1 downto 0);
+signal addr_dly_reg, addr_dly_next: std_logic_vector(log2c(MEM_DEPTH/RATIO)-1 downto 0);
+signal data_reg, data_next        : std_logic_vector(IN_DATA_WIDTH-1 downto 0);
+signal tready_reg, tready_next    : std_logic;
+
+signal averages_reg, averages_next: std_logic_vector(32-1 downto 0);
+signal done_reg, done_next        : std_logic;
+signal dout_b_s                   : std_logic_vector(IN_DATA_WIDTH-1 downto 0);
+signal addr_s                     : std_logic_vector(log2c(MEM_DEPTH)-1 downto 0);
+signal brama_clk, bramb_clk       : std_logic;  
+--signal brama_rst, bramb_rst       : std_logic;  
+signal bramb_out                  : std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+signal dinb_reg, dinb_next        : std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+signal addrb_s                    : std_logic_vector(log2c(MEM_DEPTH)-1 downto 0);
+signal wren_reg, wren_next        : std_logic;  
+signal wrenb_reg, wrenb_next      : std_logic;  
+signal web                        : std_logic;
+
+begin
+
+  BUFGMUX_inst: BUFGMUX
+  port map (
+             O  => brama_clk,      -- 1-bit output: Clock output
+             I0 => aclk,           -- 1-bit input: Clock input (S=0)
+             I1 => bram_porta_clk, -- 1-bit input: Clock input (S=1)
+             S  => done_reg    -- 1-bit input: Clock select
+           );
+
+  s_axis_tready     <= tready_reg;
+  done              <= done_reg;
+  averages_out      <= averages_reg;
+  addr_dly_next     <= addr_reg;
+  addr_s            <= std_logic_vector(resize(unsigned(unsigned(bram_porta_addr)-1),addrb_s'length)) when (done_reg = '1') else 
+                       std_logic_vector(resize(unsigned(unsigned(averages_reg)-1),addrb_s'length));
+  web               <= wren_reg when (mode = '0') else '0';
+  --bram_porta_rddata <= std_logic_vector(resize(unsigned(bramb_out),bram_porta_rddata'length)) when (done_reg = '1') else (others => '0');
+  bram_porta_rddata <= std_logic_vector(resize(signed(bramb_out),bram_porta_rddata'length));
+  --  brama_rst         <= bram_porta_rst when (done_reg = '1') and (mode = '0') else
+  --                       aresetn;
+
+  -- DP RAM
+  tdp_ram_i : entity work.tdp_bram
+  generic map(
+               AWIDTH       => log2c(MEM_DEPTH/RATIO),
+               DWIDTH       => IN_DATA_WIDTH
+             )
+  port map(
+            clka    => aclk,
+            clkb    => aclk,
+            ena     => '1',
+            enb     => '1',
+            wea     => wren_reg,
+            web     => '0',
+            addra   => addr_dly_reg,
+            addrb   => addr_reg,
+            dia     => data_reg,
+            dib     => (others => '0'),
+            doa     => open,
+            dob     => dout_b_s
+          );
+
+  -- ASYMMETRIC RAM
+  -- Port A -> AXI IF
+  -- Port B -> same as WIDER BRAM
+  ram_asy : entity work.asym_ram_tdp
+  generic map
+  (
+    WIDTHA      => ADC_DATA_WIDTH, 
+    ADDRWIDTHA  => log2c(MEM_DEPTH),
+    WIDTHB      => IN_DATA_WIDTH,
+    ADDRWIDTHB  => log2c(MEM_DEPTH/RATIO)
+  )
+  port map
+  (
+    --portA same as op_ram
+    clka        => brama_clk,
+    ena         => '1',
+    wea         => wrenb_reg,
+    addra       => addr_s,
+    dia         => dinb_reg,
+    doa         => bramb_out,
+
+    --portB same as portA in dp_ram
+    clkb        => aclk, --brama_clk,
+    enb         => '1',
+    web         => web, --wren_reg,
+    addrb       => addr_dly_reg,
+    dib         => data_reg,
+    dob         => open
+  );
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn = '0') then
+        state_reg    <= ST_IDLE;
+        --state_reg    <= ST_WRITE_ZEROS;
+        addr_reg     <= (others => '0');
+        addr_dly_reg <= (others => '0');
+        data_reg     <= (others => '0');
+        averages_reg <= (others => '0');
+        dinb_reg     <= (others => '0');
+        tready_reg   <= '0';
+        done_reg     <= '0';
+        wren_reg     <= '0';
+        wrenb_reg    <= '0';
+      else
+        state_reg    <= state_next;
+        addr_reg     <= addr_next;
+        addr_dly_reg <= addr_dly_next;
+        data_reg     <= data_next;
+        dinb_reg     <= dinb_next;
+        averages_reg <= averages_next;
+        tready_reg   <= tready_next;
+        done_reg     <= done_next;
+        wren_reg     <= wren_next;
+        wrenb_reg    <= wrenb_next;
+      end if;
+    end if;
+  end process;
+
+  --Next state logic
+  process(state_reg, start, mode, trig_i, restart, nsamples, naverages, addr_reg, s_axis_tvalid)
+    variable dinbv : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
+  begin
+    state_next    <= state_reg;  
+    addr_next     <= addr_reg;
+    data_next     <= data_reg;
+    averages_next <= averages_reg;
+    wren_next     <= wren_reg; 
+    wrenb_next    <= wrenb_reg; 
+    tready_next   <= tready_reg;
+    done_next     <= done_reg;
+    dinb_next     <= dinb_reg;
+    dinbv         := (others => '0');
+
+    case state_reg is
+      --when ST_WRITE_ZEROS =>    -- Clear BRAM state one time case
+      --  wren_next     <= '1';
+      --  wrenb_next     <= '1';
+      --  addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
+      --  if(unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then 
+      --    wren_next  <= '0';
+      --    wrenb_next  <= '0';
+      --    addr_next  <= (others => '0');
+      --    state_next <= ST_IDLE;
+      --  end if;
+
+      when ST_IDLE => -- Start
+        addr_next     <= (others => '0');
+        data_next     <= (others => '0');
+        averages_next <= (others => '0');
+        wren_next     <= '0';
+        wrenb_next    <= '0';
+        tready_next   <= '0';
+        done_next     <= '0';
+        dinb_next     <= (others => '0');
+        if start = '1' then
+          state_next  <= ST_WRITE_ZEROS;
+          --state_next  <= ST_WAIT_TRIG;
+        else
+          state_next  <= ST_IDLE;
+        end if;
+
+      when ST_WRITE_ZEROS =>    -- Clear BRAM state
+        wren_next     <= '1';
+        wrenb_next     <= '1';
+        addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
+        --if(unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then 
+        if(unsigned(addr_reg) = unsigned(nsamples)/RATIO) then 
+          wren_next  <= '0';
+          wrenb_next  <= '0';
+          addr_next  <= (others => '0');
+          state_next <= ST_WAIT_TRIG;
+        end if;
+
+      when ST_WAIT_TRIG => -- Wait for trigger
+        --wrenb_next <= '0';
+        if(trig_i = '1') and (s_axis_tvalid = '1') then
+          tready_next  <= '1';
+          if (mode = '0') then
+            state_next  <= ST_AVG_SCOPE;
+          else
+            state_next    <= ST_AVG_N1;
+          end if;
+        else 
+          state_next <= ST_WAIT_TRIG;
+        end if;
+
+      when ST_AVG_SCOPE => -- Measure
+        --ASSIGN_G: for I in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop
+        ASSIGN_G: for I in 0 to RATIO-1 loop
+          data_next(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH) <= 
+          std_logic_vector(signed(dout_b_s(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)) + 
+          signed(s_axis_tdata(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)));
+        end loop;
+        wren_next    <= '1';
+        addr_next   <= std_logic_vector(unsigned(addr_reg) + 1);
+        --if (unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then
+        if (unsigned(addr_reg) = unsigned(nsamples)/RATIO) then
+          averages_next <= std_logic_vector(unsigned(averages_reg) + 1);
+          addr_next   <= (others => '0');
+          tready_next <= '0';
+          wren_next <= '0';
+          if (unsigned(averages_reg) = unsigned(naverages)-1) then
+            state_next  <= ST_FINISH;
+          else
+            state_next  <= ST_WAIT_TRIG;
+          end if;
+        end if;
+
+      when ST_AVG_N1 => -- N to 1 average
+        --ASSIGN_N: for I in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop
+        ASSIGN_N: for I in 0 to RATIO-1 loop
+          data_next(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH) <= 
+          std_logic_vector(signed(data_reg(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)) + 
+          signed(s_axis_tdata(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)));
+        end loop;
+        wren_next    <= '1';
+        addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
+        --if (unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then
+        if (unsigned(addr_reg) = unsigned(nsamples)/RATIO) then
+          averages_next <= std_logic_vector(unsigned(averages_reg) + 1);
+          addr_next   <= (others => '0');
+          tready_next <= '0';
+          wren_next <= '0';
+          --ASSIGN_AVG: for K in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop
+          ASSIGN_AVG: for K in 0 to RATIO-1 loop
+            dinbv := 
+            std_logic_vector(signed(dinbv) + signed(data_reg(IN_DATA_WIDTH-1-K*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(K+1)*ADC_DATA_WIDTH)));
+          end loop;
+          dinb_next <= dinbv;
+          wrenb_next   <= '1';
+          if (unsigned(averages_reg) = unsigned(naverages)-1) then
+            state_next  <= ST_FINISH;
+          else
+            state_next  <= ST_WRITE_AVG;
+          end if;
+        end if;
+
+      when ST_WRITE_AVG => -- write bramb
+        wrenb_next   <= '0';
+        data_next <= (others => '0');
+        state_next <= ST_WAIT_TRIG;
+
+      when ST_FINISH => -- done
+        wrenb_next <= '0';
+        done_next  <= '1';
+        if restart = '1' then
+          --wren_next <= '1';
+          --data_next <= (others => '0');
+          state_next <= ST_IDLE;
+        end if;
+    end case;
+  end process;
+
+end rtl;
diff --git a/cores/axis_avgr_v1_0/averager.vhd_bkp b/cores/axis_avgr_v1_0/averager.vhd_bkp
new file mode 100644
index 0000000000000000000000000000000000000000..14987334ba1bca9520ee23ca033afc56a4cb5b24
--- /dev/null
+++ b/cores/axis_avgr_v1_0/averager.vhd_bkp
@@ -0,0 +1,330 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity averager is
+  generic (
+            IN_DATA_WIDTH  : natural := 128; -- ADC data width x8
+            OUT_DATA_WIDTH : natural := 32;  -- AXI data width
+            ADC_DATA_WIDTH : natural := 16;  -- ADC data width
+            MEM_DEPTH      : natural := 10   -- Max 2**16
+          );
+  port ( 
+         -- System signals
+         aclk              : in std_logic;
+         aresetn           : in std_logic;
+
+         -- Averager specific ports
+         start             : in std_logic;
+         restart           : in std_logic;
+         mode              : in std_logic; --0- (default) avg scope, 1-avg nsamples to one value
+         trig_i            : in std_logic;
+         --nsamples Must be power of 2. Minimum is 8 and maximum is 2^AW
+         nsamples          : in std_logic_vector(32-1 downto 0); 
+         naverages         : in std_logic_vector(32-1 downto 0);
+         done              : out std_logic;
+         averages_out      : out std_logic_vector(32-1 downto 0);
+         -- BRAM PORTA. Reading port
+         bram_porta_clk    : in std_logic;
+         --bram_porta_rst    : in std_logic;
+         bram_porta_wrdata : in std_logic_vector(OUT_DATA_WIDTH-1 downto 0);
+         bram_porta_we     : in std_logic;
+         bram_porta_addr   : in std_logic_vector(OUT_DATA_WIDTH-1 downto 0);
+         bram_porta_rddata : out std_logic_vector(OUT_DATA_WIDTH-1 downto 0);
+
+         -- Slave side     
+         s_axis_tready     : out std_logic;
+         s_axis_tvalid     : in std_logic;
+         s_axis_tdata      : in std_logic_vector(IN_DATA_WIDTH-1 downto 0)
+       );
+end averager;
+
+architecture rtl of averager is
+
+  function log2c(n: integer) return integer is
+    variable m, p: integer;
+  begin
+    m := 0;
+    p := 1;
+    while p < n loop
+      m := m + 1;
+      p := p * 2;
+    end loop;
+    return m;
+  end log2c;
+
+  constant RATIO          : natural := IN_DATA_WIDTH/ADC_DATA_WIDTH;
+  constant MEM_ADDR_WIDTH : natural := log2c(MEM_DEPTH);
+
+  type state_t is (
+--  ST_WRITE_ZEROS, 
+  ST_IDLE, 
+  ST_WRITE_ZEROS, 
+  ST_WAIT_TRIG, 
+  ST_AVG_SCOPE,
+  ST_AVG_N1,
+  ST_WRITE_AVG,
+  ST_FINISH 
+);
+signal state_reg, state_next      : state_t;
+
+signal addr_reg, addr_next        : std_logic_vector(log2c(MEM_DEPTH/RATIO)-1 downto 0);
+signal addr_dly_reg, addr_dly_next: std_logic_vector(log2c(MEM_DEPTH/RATIO)-1 downto 0);
+signal data_reg, data_next        : std_logic_vector(IN_DATA_WIDTH-1 downto 0);
+signal tready_reg, tready_next    : std_logic;
+
+signal averages_reg, averages_next: std_logic_vector(32-1 downto 0);
+signal done_reg, done_next        : std_logic;
+signal dout_b_s                   : std_logic_vector(IN_DATA_WIDTH-1 downto 0);
+signal addr_s                     : std_logic_vector(log2c(MEM_DEPTH)-1 downto 0);
+signal brama_clk, bramb_clk       : std_logic;  
+--signal brama_rst, bramb_rst       : std_logic;  
+signal bramb_out                  : std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+signal dinb_reg, dinb_next        : std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+signal addrb_s                    : std_logic_vector(log2c(MEM_DEPTH)-1 downto 0);
+signal wren_reg, wren_next        : std_logic;  
+signal wrenb_reg, wrenb_next      : std_logic;  
+signal web                        : std_logic;
+
+begin
+
+  BUFGMUX_inst: BUFGMUX
+  port map (
+             O  => brama_clk,      -- 1-bit output: Clock output
+             I0 => aclk,           -- 1-bit input: Clock input (S=0)
+             I1 => bram_porta_clk, -- 1-bit input: Clock input (S=1)
+             S  => done_reg    -- 1-bit input: Clock select
+           );
+
+  s_axis_tready     <= tready_reg;
+  done              <= done_reg;
+  averages_out      <= averages_reg;
+  addr_dly_next     <= addr_reg;
+  addr_s            <= std_logic_vector(resize(unsigned(unsigned(bram_porta_addr)-1),addrb_s'length)) when (done_reg = '1') else 
+                       std_logic_vector(resize(unsigned(unsigned(averages_reg)-1),addrb_s'length));
+  web               <= wren_reg when (mode = '0') else '0';
+  --bram_porta_rddata <= std_logic_vector(resize(unsigned(bramb_out),bram_porta_rddata'length)) when (done_reg = '1') else (others => '0');
+  bram_porta_rddata <= std_logic_vector(resize(signed(bramb_out),bram_porta_rddata'length));
+  --  brama_rst         <= bram_porta_rst when (done_reg = '1') and (mode = '0') else
+  --                       aresetn;
+
+  -- DP RAM
+  tdp_ram_i : entity work.tdp_bram
+  generic map(
+               AWIDTH       => log2c(MEM_DEPTH/RATIO),
+               DWIDTH       => IN_DATA_WIDTH
+             )
+  port map(
+            clka    => aclk,
+            clkb    => aclk,
+            ena     => '1',
+            enb     => '1',
+            wea     => wren_reg,
+            web     => '0',
+            addra   => addr_dly_reg,
+            addrb   => addr_reg,
+            dia     => data_reg,
+            dib     => (others => '0'),
+            doa     => open,
+            dob     => dout_b_s
+          );
+
+  -- ASYMMETRIC RAM
+  -- Port A -> AXI IF
+  -- Port B -> same as WIDER BRAM
+  ram_asy : entity work.asym_ram_tdp
+  generic map
+  (
+    WIDTHA      => ADC_DATA_WIDTH, 
+    ADDRWIDTHA  => log2c(MEM_DEPTH),
+    WIDTHB      => IN_DATA_WIDTH,
+    ADDRWIDTHB  => log2c(MEM_DEPTH/RATIO)
+  )
+  port map
+  (
+    --portA same as op_ram
+    clka        => brama_clk,
+    ena         => '1',
+    wea         => wrenb_reg,
+    addra       => addr_s,
+    dia         => dinb_reg,
+    doa         => bramb_out,
+
+    --portB same as portA in dp_ram
+    clkb        => aclk, --brama_clk,
+    enb         => '1',
+    web         => web, --wren_reg,
+    addrb       => addr_dly_reg,
+    dib         => data_reg,
+    dob         => open
+  );
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn = '0') then
+        state_reg    <= ST_IDLE;
+        --state_reg    <= ST_WRITE_ZEROS;
+        addr_reg     <= (others => '0');
+        addr_dly_reg <= (others => '0');
+        data_reg     <= (others => '0');
+        averages_reg <= (others => '0');
+        dinb_reg     <= (others => '0');
+        tready_reg   <= '0';
+        done_reg     <= '0';
+        wren_reg     <= '0';
+        wrenb_reg    <= '0';
+      else
+        state_reg    <= state_next;
+        addr_reg     <= addr_next;
+        addr_dly_reg <= addr_dly_next;
+        data_reg     <= data_next;
+        dinb_reg     <= dinb_next;
+        averages_reg <= averages_next;
+        tready_reg   <= tready_next;
+        done_reg     <= done_next;
+        wren_reg     <= wren_next;
+        wrenb_reg    <= wrenb_next;
+      end if;
+    end if;
+  end process;
+
+  --Next state logic
+  process(state_reg, start, mode, trig_i, restart, nsamples, naverages, addr_reg, s_axis_tvalid)
+    variable dinbv : std_logic_vector(ADC_DATA_WIDTH-1 downto 0) := (others => '0');
+  begin
+    state_next    <= state_reg;  
+    addr_next     <= addr_reg;
+    data_next     <= data_reg;
+    averages_next <= averages_reg;
+    wren_next     <= wren_reg; 
+    wrenb_next    <= wrenb_reg; 
+    tready_next   <= tready_reg;
+    done_next     <= done_reg;
+    dinb_next     <= dinb_reg;
+    dinbv         := (others => '0');
+
+    case state_reg is
+      --when ST_WRITE_ZEROS =>    -- Clear BRAM state one time case
+      --  wren_next     <= '1';
+      --  wrenb_next     <= '1';
+      --  addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
+      --  if(unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then 
+      --    wren_next  <= '0';
+      --    wrenb_next  <= '0';
+      --    addr_next  <= (others => '0');
+      --    state_next <= ST_IDLE;
+      --  end if;
+
+      when ST_IDLE => -- Start
+        addr_next     <= (others => '0');
+        data_next     <= (others => '0');
+        averages_next <= (others => '0');
+        wren_next     <= '0';
+        wrenb_next    <= '0';
+        tready_next   <= '0';
+        done_next     <= '0';
+        dinb_next     <= (others => '0');
+        if start = '1' then
+          state_next  <= ST_WRITE_ZEROS;
+          --state_next  <= ST_WAIT_TRIG;
+        else
+          state_next  <= ST_IDLE;
+        end if;
+
+      when ST_WRITE_ZEROS =>    -- Clear BRAM state
+        wren_next     <= '1';
+        wrenb_next     <= '1';
+        addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
+        --if(unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then 
+        if(unsigned(addr_reg) = unsigned(nsamples)/RATIO) then 
+          wren_next  <= '0';
+          wrenb_next  <= '0';
+          addr_next  <= (others => '0');
+          state_next <= ST_WAIT_TRIG;
+        end if;
+
+      when ST_WAIT_TRIG => -- Wait for trigger
+        --wrenb_next <= '0';
+        if(trig_i = '1') and (s_axis_tvalid = '1') then
+          tready_next  <= '1';
+          if (mode = '0') then
+            state_next  <= ST_AVG_SCOPE;
+          else
+            state_next    <= ST_AVG_N1;
+          end if;
+        else 
+          state_next <= ST_WAIT_TRIG;
+        end if;
+
+      when ST_AVG_SCOPE => -- Measure
+        --ASSIGN_G: for I in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop
+        ASSIGN_G: for I in 0 to RATIO-1 loop
+          data_next(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH) <= 
+          std_logic_vector(signed(dout_b_s(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)) + 
+          signed(s_axis_tdata(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)));
+        end loop;
+        wren_next    <= '1';
+        addr_next   <= std_logic_vector(unsigned(addr_reg) + 1);
+        --if (unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then
+        if (unsigned(addr_reg) = unsigned(nsamples)/RATIO) then
+          averages_next <= std_logic_vector(unsigned(averages_reg) + 1);
+          addr_next   <= (others => '0');
+          tready_next <= '0';
+          wren_next <= '0';
+          if (unsigned(averages_reg) = unsigned(naverages)-1) then
+            state_next  <= ST_FINISH;
+          else
+            state_next  <= ST_WAIT_TRIG;
+          end if;
+        end if;
+
+      when ST_AVG_N1 => -- N to 1 average
+        --ASSIGN_N: for I in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop
+        ASSIGN_N: for I in 0 to RATIO-1 loop
+          data_next(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH) <= 
+          std_logic_vector(signed(data_reg(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)) + 
+          signed(s_axis_tdata(IN_DATA_WIDTH-1-I*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(I+1)*ADC_DATA_WIDTH)));
+        end loop;
+        wren_next    <= '1';
+        addr_next <= std_logic_vector(unsigned(addr_reg) + 1);
+        --if (unsigned(addr_reg) = unsigned(nsamples)/(IN_DATA_WIDTH/ADC_DATA_WIDTH)) then
+        if (unsigned(addr_reg) = unsigned(nsamples)/RATIO) then
+          averages_next <= std_logic_vector(unsigned(averages_reg) + 1);
+          addr_next   <= (others => '0');
+          tready_next <= '0';
+          wren_next <= '0';
+          --ASSIGN_AVG: for K in 0 to (IN_DATA_WIDTH/ADC_DATA_WIDTH)-1 loop
+          ASSIGN_AVG: for K in 0 to RATIO-1 loop
+            dinbv := 
+            std_logic_vector(signed(dinbv) + signed(data_reg(IN_DATA_WIDTH-1-K*ADC_DATA_WIDTH downto IN_DATA_WIDTH-(K+1)*ADC_DATA_WIDTH)));
+          end loop;
+          dinb_next <= dinbv;
+          wrenb_next   <= '1';
+          if (unsigned(averages_reg) = unsigned(naverages)-1) then
+            state_next  <= ST_FINISH;
+          else
+            state_next  <= ST_WRITE_AVG;
+          end if;
+        end if;
+
+      when ST_WRITE_AVG => -- write bramb
+        wrenb_next   <= '0';
+        data_next <= (others => '0');
+        state_next <= ST_WAIT_TRIG;
+
+      when ST_FINISH => -- done
+        wrenb_next <= '0';
+        done_next  <= '1';
+        if restart = '1' then
+          --wren_next <= '1';
+          --data_next <= (others => '0');
+          state_next <= ST_IDLE;
+        end if;
+    end case;
+  end process;
+
+end rtl;
diff --git a/cores/axis_avgr_v1_0/axis_averager.vhd b/cores/axis_avgr_v1_0/axis_averager.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..9fa7018fbc3e330c4005813a485997bd0b1f1d63
--- /dev/null
+++ b/cores/axis_avgr_v1_0/axis_averager.vhd
@@ -0,0 +1,227 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_averager is
+  generic (
+            S_AXIS_TDATA_WIDTH: natural := 128; -- AXIS itf data width
+            M_AXIS_TDATA_WIDTH: natural := 32;  -- AXI itf data width
+            ADC_DATA_WIDTH    : natural := 16;  -- ADC data width
+            MEM_DEPTH         : natural := 1024 --Max 2**16
+          );
+  port ( 
+         start             : in std_logic;
+         --restart           : in std_logic;
+         trig_i            : in std_logic;
+         send_data         : in std_logic;
+         done              : out std_logic;
+
+         -- Slave config side
+         s_axis_cfg_aclk   : in std_logic;
+         s_axis_cfg_aresetn: in std_logic;
+         s_axis_cfg_tready : out std_logic;
+         s_axis_cfg_tvalid : in std_logic;
+         s_axis_cfg_tdata  : in std_logic_vector(64-1 downto 0);
+
+         -- Slave data interface
+         s_axis_aclk       : in std_logic;
+         s_axis_aresetn    : in std_logic;
+         s_axis_tready     : out std_logic;
+         s_axis_tvalid     : in std_logic;
+         s_axis_tdata      : in std_logic_vector(S_AXIS_TDATA_WIDTH-1 downto 0);
+
+         -- Master data interface
+         m_axis_aclk       : in std_logic;
+         m_axis_aresetn    : in std_logic;
+         m_axis_tready     : in std_logic;
+         m_axis_tvalid     : out std_logic;
+         m_axis_tlast      : out std_logic;
+         m_axis_tdata      : out std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0)
+       );
+end axis_averager;
+
+architecture rtl of axis_averager is
+
+  function log2c(n: integer) return integer is
+    variable m, p: integer;
+  begin
+    m := 0;
+    p := 1;
+    while p < n loop
+      m := m + 1;
+      p := p * 2;
+    end loop;
+    return m;
+  end log2c;
+
+  constant MEM_ADDR_WIDTH : natural := log2c(MEM_DEPTH);
+
+  signal nsamples_s            : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0);
+  signal naverages_s           : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0);
+  signal averages_out_s        : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0);
+  signal done_s                : std_logic;
+  signal done_sync             : std_logic;
+  signal send_sync             : std_logic;
+  signal start_sync            : std_logic;
+--  signal restart_sync          : std_logic;
+  signal restart_s             : std_logic;
+  signal trig_en_s             : std_logic;
+  signal mode_s                : std_logic;
+
+  signal bram_porta_clk_s      : std_logic;
+--  signal bram_porta_rst_s      : std_logic;
+  signal bram_porta_wrdata_s   : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0);
+  signal bram_porta_we_s       : std_logic;
+  --signal bram_porta_addr_s   : std_logic_vector(AW-1 downto 0);
+  signal bram_porta_addr_s     : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0); --AXI itf
+  --signal bram_porta_rddata_s : std_logic_vector(DW-1 downto 0);
+  signal bram_porta_rddata_s   : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0); --AXI itf 
+
+  --Register cfg/sts
+  signal cfg_gral_reg          : std_logic_vector(64-1 downto 0);
+  signal cfg_gral_reg_sync     : std_logic_vector(64-1 downto 0);
+--  signal sts_avg_reg           : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0);
+--  signal sts_avg_reg_sync      : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0);
+  signal rd_cfg_word           : std_logic_vector(M_AXIS_TDATA_WIDTH-1 downto 0);
+
+begin
+
+  --done <= done_s;
+
+  --lets synchronize the start signal
+  sync_start: entity work.sync
+  port map(
+            clk      => s_axis_aclk,
+            reset    => s_axis_aresetn,
+            in_async => start,
+            out_sync => start_sync
+          );
+
+  --lets synchronize the restart signal
+--  sync_restart: entity work.sync
+--  port map(
+--            clk      => s_axis_aclk,
+--            reset    => s_axis_aresetn,
+--            in_async => restart,
+--            out_sync => restart_sync
+--          );
+
+  --lets synchronize the done signal
+  sync_done: entity work.sync
+  port map(
+            clk      => s_axis_cfg_aclk,
+            reset    => s_axis_cfg_aresetn,
+            in_async => done_s,
+            out_sync => done
+          );
+
+  -- synchronizer 1 
+  sync_fifo: entity work.axis_fifo
+  generic map(
+               AXIS_TDATA_WIDTH => 64,
+               FIFO_DEPTH       => 4
+             )
+  port map(
+            s_axis_aclk       => s_axis_cfg_aclk,
+            s_axis_aresetn    => s_axis_cfg_aresetn,
+            s_axis_tready     => s_axis_cfg_tready,
+            s_axis_tvalid     => s_axis_cfg_tvalid,
+            s_axis_tdata      => s_axis_cfg_tdata,
+
+            m_axis_aclk       => s_axis_aclk,
+            m_axis_aresetn    => s_axis_aresetn,
+            m_axis_tready     => '1',
+            m_axis_tvalid     => open,
+            m_axis_tdata      => cfg_gral_reg_sync
+          );
+
+  mode_s      <= cfg_gral_reg_sync(64-1); 
+  naverages_s <= '0' & cfg_gral_reg_sync(64-2 downto (64/2)); 
+  nsamples_s  <= cfg_gral_reg_sync((64/2)-1 downto 0);  
+
+  --Averager itf
+  avg_i : entity work.averager 
+  generic map(
+               IN_DATA_WIDTH  => S_AXIS_TDATA_WIDTH,
+               OUT_DATA_WIDTH => M_AXIS_TDATA_WIDTH,
+               ADC_DATA_WIDTH => ADC_DATA_WIDTH,
+               MEM_DEPTH      => MEM_DEPTH
+             )
+  port map(
+            aclk              => s_axis_aclk,
+            aresetn           => s_axis_aresetn,
+            start             => start_sync,
+            restart           => restart_s,
+            mode              => mode_s, --0- (default) avg scope, 1-avg nsamples to one value
+            trig_i            => trig_i,
+            nsamples          => nsamples_s,
+            naverages         => naverages_s,
+            done              => done_s,
+            averages_out      => averages_out_s,
+
+            bram_porta_clk    => bram_porta_clk_s,
+            --bram_porta_rst    => bram_porta_rst_s,
+            bram_porta_wrdata => (others => '0'),
+            bram_porta_we     => '0',
+            bram_porta_addr   => bram_porta_addr_s,
+            bram_porta_rddata => bram_porta_rddata_s, 
+
+            s_axis_tready     => s_axis_tready,
+            s_axis_tvalid     => s_axis_tvalid,
+            s_axis_tdata      => s_axis_tdata
+          );
+
+  -- determine how many data we need to read from m_axis
+  -- it depends of the working MODE
+  -- MODE=0 (averaging scope mode) -> so we need to read NSAMPLES samples
+  -- MODE=1 (nsamples mode)        -> so we need to read NAVERAGES samples
+  rd_cfg_word <= nsamples_s when (mode_s = '0') else 
+                 naverages_s;
+
+  --lets synchronize the done signal
+  sync_mdone: entity work.sync
+  port map(
+            clk      => m_axis_aclk,
+            reset    => m_axis_aresetn,
+            in_async => done_s,
+            out_sync => done_sync
+          );
+
+  --lets synchronize the send_data signal
+  sync_send: entity work.sync
+  port map(
+            clk      => m_axis_aclk,
+            reset    => m_axis_aresetn,
+            in_async => send_data,
+            out_sync => send_sync
+          );
+
+  --AXIS interface bram reader avg scope and nsamples modes
+  axis_bram_itf: entity work.axis_bram_reader
+  generic map(
+               BRAM_DEPTH       => MEM_DEPTH,
+               BRAM_DATA_WIDTH  => M_AXIS_TDATA_WIDTH,
+               AXIS_TDATA_WIDTH => M_AXIS_TDATA_WIDTH
+             )
+  port map(
+            aclk            => m_axis_aclk,
+            aresetn         => m_axis_aresetn,
+
+            cfg_data        => rd_cfg_word,
+            sts_data        => open,
+            done            => done_sync,
+            send            => send_sync,
+            restart_o       => restart_s,
+
+            m_axis_tready     => m_axis_tready,
+            m_axis_tdata      => m_axis_tdata,
+            m_axis_tvalid     => m_axis_tvalid,
+            m_axis_tlast      => m_axis_tlast,
+
+            bram_porta_clk    => bram_porta_clk_s,
+           -- bram_porta_rst    => bram_porta_rst_s, 
+            bram_porta_addr   => bram_porta_addr_s,
+            bram_porta_rddata => bram_porta_rddata_s 
+          );
+
+end rtl;
diff --git a/cores/axis_avgr_v1_0/axis_bram_reader.vhd b/cores/axis_avgr_v1_0/axis_bram_reader.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..dc528ca5e946f726689ff9db94f49858e4eaa637
--- /dev/null
+++ b/cores/axis_avgr_v1_0/axis_bram_reader.vhd
@@ -0,0 +1,147 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_bram_reader is
+  generic (
+            BRAM_DEPTH        : natural := 1024;
+            BRAM_DATA_WIDTH   : natural := 32;
+            AXIS_TDATA_WIDTH  : natural := 32
+          );
+  port (
+         -- System signals
+         aclk             : in std_logic;
+         aresetn          : in std_logic;
+
+         cfg_data         : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         sts_data         : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         done             : in std_logic;
+         send             : in std_logic;
+         restart_o        : out std_logic;
+
+         -- Master side
+         m_axis_tready    : in std_logic;
+         m_axis_tdata     : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         m_axis_tvalid    : out std_logic;
+         m_axis_tlast     : out std_logic;
+
+         -- BRAM port
+         bram_porta_clk   : out std_logic;
+         --bram_porta_rst   : out std_logic;
+         bram_porta_addr  : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         bram_porta_rddata: in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0)
+       );
+end axis_bram_reader;
+
+architecture rtl of axis_bram_reader is
+
+  function log2c(n: integer) return integer is
+    variable m, p: integer;
+  begin
+    m := 0;
+    p := 1;
+    while p < n loop
+      m := m + 1;
+      p := p * 2;
+    end loop;
+    return m;
+  end log2c;
+
+  constant BRAM_ADDR_WIDTH : integer := log2c(BRAM_DEPTH);
+
+  type state_t is (
+  ST_IDLE,
+  ST_DLY1,
+  --ST_WAIT_READY,
+  ST_SEND_DATA
+);
+signal state_reg, state_next      : state_t;
+
+signal addr_reg, addr_next     : unsigned(BRAM_ADDR_WIDTH-1 downto 0);
+signal tvalid_s, tlast_s       : std_logic;
+signal tvalid_reg, tvalid_next : std_logic;
+signal tlast_reg, tlast_next : std_logic;
+
+begin
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if aresetn = '0' then
+        state_reg  <= ST_IDLE;
+        addr_reg   <= (others => '1');
+        tvalid_reg <= '0';
+        tlast_reg  <= '0';
+      else 
+        state_reg  <= state_next;
+        addr_reg   <= addr_next;
+        tvalid_reg <= tvalid_next;
+        tlast_reg  <= tlast_next;
+      end if;
+    end if;
+  end process;
+
+  --Next state logic
+  process(state_reg, addr_reg, done, send, m_axis_tready)
+  begin
+    state_next    <= state_reg;
+    addr_next     <= addr_reg;
+    --tvalid_s      <= '0';
+    tvalid_next   <= '0';
+    tlast_next    <= '0';
+    --tlast_s       <= '0';
+
+    case state_reg is
+      when ST_IDLE => 
+        if (done = '1') and (send = '1') then
+          addr_next <= addr_reg + 1;
+          state_next  <= ST_DLY1;
+        else
+          state_next  <= ST_IDLE;
+        end if;
+
+      when ST_DLY1 =>
+        addr_next <= addr_reg + 1;
+        state_next <= ST_SEND_DATA;
+        --state_next <= ST_WAIT_READY;
+
+      --when ST_WAIT_READY =>  
+      --  if m_axis_tready = '1' then
+      --    state_next <= ST_SEND_DATA;
+      --    addr_next <= addr_reg + 1;
+      --  end if;
+
+      when ST_SEND_DATA =>
+        --tvalid_s <= '1';
+        tvalid_next <= '1';
+        if m_axis_tready = '1' then
+          addr_next <= addr_reg + 1;
+          if (addr_reg = unsigned(cfg_data)) then
+            addr_next <= (others => '1');
+            state_next <= ST_IDLE;
+            --tlast_s <= '1';
+            tlast_next <= '1';
+          else
+            state_next <= ST_SEND_DATA;
+          end if;
+        else 
+          state_next <= ST_SEND_DATA;
+        end if;
+    end case;
+  end process;
+
+  sts_data <= std_logic_vector(resize(addr_reg,sts_data'length));
+
+  m_axis_tdata  <= bram_porta_rddata;
+  --m_axis_tvalid <= tvalid_s;
+  m_axis_tvalid <= tvalid_reg;
+  --m_axis_tlast  <= tlast_s;
+  m_axis_tlast  <= tlast_reg;
+
+  bram_porta_clk <= aclk;
+  --bram_porta_rst <= aresetn;
+  bram_porta_addr <= std_logic_vector(resize(addr_next,bram_porta_addr'length));
+  restart_o <= tlast_reg;
+
+end rtl;
diff --git a/cores/axis_avgr_v1_0/axis_fifo.vhd b/cores/axis_avgr_v1_0/axis_fifo.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..67d8ab63f5af8aaf5f4c24e7a04398f397f9bd2e
--- /dev/null
+++ b/cores/axis_avgr_v1_0/axis_fifo.vhd
@@ -0,0 +1,124 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_fifo is
+  generic(
+           AXIS_TDATA_WIDTH : natural := 32;
+           FIFO_DEPTH       : natural := 16
+         --           AWIDTH           : natural := 2
+         );
+  port(
+        -- Slave data interface
+        s_axis_aclk       : in std_logic;
+        s_axis_aresetn    : in std_logic;
+        s_axis_tready     : out std_logic;
+        s_axis_tvalid     : in std_logic;
+        s_axis_tdata      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+        -- Master data interface
+        m_axis_aclk       : in std_logic;
+        m_axis_aresetn    : in std_logic;
+        m_axis_tready     : in std_logic;
+        m_axis_tvalid     : out std_logic;
+        --m_axis_tlast      : out std_logic;
+        m_axis_tdata      : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0)
+      );
+end axis_fifo;
+
+architecture rtl of axis_fifo is
+  function log2c(n: integer) return integer is
+    variable m, p: integer;
+  begin
+    m := 0;
+    p := 1;
+    while p < n loop
+      m := m + 1;
+      p := p * 2;
+    end loop;
+    return m;
+  end log2c;
+
+  constant AWIDTH : natural := log2c(FIFO_DEPTH);
+
+  signal s_tready_reg, s_tready_next : std_logic;
+  signal m_tvalid_reg, m_tvalid_next : std_logic;
+  signal we_s, rd_s, full_s, empty_s : std_logic;
+  signal w_addr_s, r_addr_s          : std_logic_vector(AWIDTH-1 downto 0);
+
+begin
+
+  s_axis_tready <= s_tready_reg;
+
+  --slave port registers
+  process(s_axis_aclk)
+  begin
+    if rising_edge(s_axis_aclk) then
+      if (s_axis_aresetn = '0') then
+        s_tready_reg <= '0';
+      else
+        s_tready_reg <= s_tready_next;
+      end if;
+    end if;
+  end process;
+  --next state logic
+  s_tready_next <= '1' when (full_s = '0') else '0'; 
+  we_s          <= '1' when (full_s = '0') and (s_axis_tvalid = '1') else '0';
+
+  m_axis_tvalid <= m_tvalid_reg;
+  --master port registers
+  process(m_axis_aclk)
+  begin
+    if rising_edge(m_axis_aclk) then
+      if (m_axis_aresetn = '0') then
+        m_tvalid_reg <= '0';
+      else
+        m_tvalid_reg <= m_tvalid_next;
+      end if;
+    end if;
+  end process;
+  --next state logic
+  m_tvalid_next <= '1' when (empty_s = '0') else '0';
+  rd_s          <= '1' when (empty_s = '0') and (m_axis_tready = '1') else '0';
+
+  --port a is wr port (slave)
+  --port b is rd port (master)
+  dp_ram_i: entity work.tdp_bram 
+  generic map(
+               AWIDTH       => AWIDTH,
+               DWIDTH       => AXIS_TDATA_WIDTH
+             )
+  port map(
+            clka    => s_axis_aclk,
+            clkb    => m_axis_aclk,
+            ena     => '1',
+            enb     => '1',
+            wea     => we_s,
+            web     => '0',
+            addra   => w_addr_s,
+            addrb   => r_addr_s,
+            dia     => s_axis_tdata,
+            dib     => (others => '0'),
+            doa     => open,
+            dob     => m_axis_tdata
+          );
+
+  fifo_ctrl_i: entity work.fifo_async_ctrl
+  generic map(
+               --DEPTH => FIFO_DEPTH
+               DEPTH => AWIDTH
+             )
+  port map(
+            clkw   => s_axis_aclk,
+            resetw => s_axis_aresetn,
+            wr     => we_s,
+            full   => full_s,
+            w_addr => w_addr_s,
+            clkr   => m_axis_aclk,
+            resetr => m_axis_aresetn,
+            rd     => rd_s,
+            empty  => empty_s,
+            r_addr => r_addr_s
+          );
+
+end rtl;
diff --git a/cores/axis_avgr_v1_0/core_config.tcl b/cores/axis_avgr_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..00998784129e404d4ed943b7b91c0704b2135ae2
--- /dev/null
+++ b/cores/axis_avgr_v1_0/core_config.tcl
@@ -0,0 +1,36 @@
+set display_name {AXI4-Stream Averager v1.0}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter S_AXIS_TDATA_WIDTH {S_AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter M_AXIS_TDATA_WIDTH {M_AXIS TDATA WIDTH} {Width of the M_AXI data bus.}
+core_parameter ADC_DATA_WIDTH {ADC DATA WIDTH} {Width of the ADC data.}
+core_parameter MEM_DEPTH {MEMORY DEPTH} {Depth of the data memory.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis_cfg]
+set_property NAME S_AXIS_CFG $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces s_axis_cfg_aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS_CFG $parameter
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces s_axis_aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS $parameter
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces m_axis_aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS $parameter
+
diff --git a/cores/axis_avgr_v1_0/fifo_async_ctrl.vhd b/cores/axis_avgr_v1_0/fifo_async_ctrl.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..3f10117aa1250991485c1e464b54013afe23c421
--- /dev/null
+++ b/cores/axis_avgr_v1_0/fifo_async_ctrl.vhd
@@ -0,0 +1,81 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity fifo_async_ctrl is
+  generic(
+           DEPTH: natural := 4
+         );
+  port(
+        clkw   : in std_logic;
+        resetw : in std_logic;
+        wr     : in std_logic;
+        full   : out std_logic;
+        w_addr : out std_logic_vector (DEPTH-1 downto 0);
+        clkr   : in std_logic;
+        resetr : in std_logic;
+        rd     : in std_logic;
+        empty  : out std_logic;
+        r_addr : out std_logic_vector (DEPTH-1 downto 0)
+      );
+end fifo_async_ctrl ;
+
+architecture str_arch of fifo_async_ctrl is
+
+  signal r_ptr_in  : std_logic_vector(DEPTH downto 0);
+  signal r_ptr_out : std_logic_vector(DEPTH downto 0);
+  signal w_ptr_in  : std_logic_vector(DEPTH downto 0);
+  signal w_ptr_out : std_logic_vector(DEPTH downto 0);
+
+begin
+  read_ctrl: entity work.fifo_read_ctrl
+  generic map(
+               N=>DEPTH
+             )
+  port map (
+             clkr     => clkr, 
+             resetr   => resetr, 
+             rd       => rd,
+             w_ptr_in => w_ptr_in, 
+             empty    => empty,
+             r_ptr_out=> r_ptr_out, 
+             r_addr   => r_addr
+           );
+
+  write_ctrl: entity work.fifo_write_ctrl
+  generic map(
+               N =>DEPTH
+             )
+  port map(
+            clkw      => clkw, 
+            resetw    => resetw, 
+            wr        => wr,
+            r_ptr_in  => r_ptr_in, 
+            full      => full,
+            w_ptr_out => w_ptr_out, 
+            w_addr    => w_addr
+          );
+
+  sync_w_ptr: entity work.n_sync
+  generic map(
+               N=>DEPTH+1
+             )
+  port map(
+            clk      => clkw, 
+            reset    => resetw,
+            in_async => w_ptr_out,
+            out_sync => w_ptr_in
+          );
+
+  sync_r_ptr: entity work.n_sync
+  generic map(
+               N=>DEPTH+1
+             )
+  port map(
+            clk      => clkr, 
+            reset    => resetr,
+            in_async => r_ptr_out, 
+            out_sync => r_ptr_in
+          );
+
+end str_arch;
diff --git a/cores/axis_avgr_v1_0/fifo_read.vhd b/cores/axis_avgr_v1_0/fifo_read.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..65d0f7c5116991989cab5fb965fc8bd1a22463ae
--- /dev/null
+++ b/cores/axis_avgr_v1_0/fifo_read.vhd
@@ -0,0 +1,62 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity fifo_read_ctrl is
+  generic(
+           N: natural :=4
+         );
+  port(
+        clkr     : in std_logic;
+        resetr   : in std_logic;
+        w_ptr_in : in std_logic_vector(N downto 0);
+        rd       : in std_logic;
+        empty    : out std_logic;
+        r_ptr_out: out std_logic_vector(N downto 0);
+        r_addr   : out std_logic_vector(N-1 downto 0)
+      );
+end fifo_read_ctrl;
+
+architecture gray_arch of fifo_read_ctrl is
+  signal r_ptr_reg, r_ptr_next : std_logic_vector(N downto 0);
+  signal gray1, bin, bin1      : std_logic_vector(N downto 0);
+  signal raddr_all             : std_logic_vector(N-1 downto 0);
+  signal raddr_msb,waddr_msb   : std_logic;
+  signal empty_flag            : std_logic;
+
+begin
+
+  -- register
+  process(clkr)
+  begin
+    if rising_edge(clkr) then
+      if (resetr='0') then
+        r_ptr_reg <= (others=>'0');
+      else
+        r_ptr_reg <= r_ptr_next;
+      end if;
+    end if;
+  end process;
+
+  -- (N+1)-bit Gray counter
+  bin   <= r_ptr_reg xor ('0' & bin(N downto 1));
+  bin1  <= std_logic_vector(unsigned(bin) + 1);
+  gray1 <= bin1 xor ('0' & bin1(N downto 1));
+
+  -- update read pointer
+  r_ptr_next <= gray1 when rd='1' and empty_flag='0' else
+                r_ptr_reg;
+  -- N-bit Gray counter
+  raddr_msb <= r_ptr_reg(N) xor r_ptr_reg(N-1);
+  raddr_all <= raddr_msb & r_ptr_reg(N-2 downto 0);
+  waddr_msb <= w_ptr_in(N) xor w_ptr_in(N-1);
+  -- check for FIFO empty
+  empty_flag <= '1' when w_ptr_in(N)=r_ptr_reg(N) and
+                w_ptr_in(N-2 downto 0)=r_ptr_reg(N-2 downto 0) and
+                raddr_msb = waddr_msb else
+                '0';
+  -- output
+  r_addr <= raddr_all;
+  r_ptr_out <= r_ptr_reg;
+  empty <= empty_flag;
+end gray_arch;
diff --git a/cores/axis_avgr_v1_0/fifo_write.vhd b/cores/axis_avgr_v1_0/fifo_write.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..46d831068430c731c799590ff90ed3005f43f30b
--- /dev/null
+++ b/cores/axis_avgr_v1_0/fifo_write.vhd
@@ -0,0 +1,62 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity fifo_write_ctrl is
+  generic(
+           N : natural := 4
+         );
+  port(
+        clkw     : in std_logic;
+        resetw   : in std_logic;
+        wr       : in std_logic;
+        r_ptr_in : in std_logic_vector(N downto 0);
+        full     : out std_logic;
+        w_ptr_out: out std_logic_vector(N downto 0);
+        w_addr   : out std_logic_vector(N-1 downto 0)
+      );
+end fifo_write_ctrl;
+
+architecture gray_arch of fifo_write_ctrl is
+  signal w_ptr_reg, w_ptr_next :std_logic_vector(N downto 0);
+  signal gray1, bin, bin1      : std_logic_vector(N downto 0);
+  signal waddr_all             : std_logic_vector(N-1 downto 0);
+  signal waddr_msb, raddr_msb  : std_logic;
+  signal full_flag             : std_logic;
+
+begin
+
+  -- register
+  process(clkw)
+  begin
+    if rising_edge(clkw) then
+      if (resetw='0') then
+        w_ptr_reg <= (others=>'0');
+      else
+        w_ptr_reg <= w_ptr_next;
+      end if;
+    end if;
+  end process;
+
+  -- (N+1)-bit Gray counter
+  bin   <= w_ptr_reg xor ('0' & bin(N downto 1));
+  bin1  <= std_logic_vector(unsigned(bin) + 1);
+  gray1 <= bin1 xor ('0' & bin1(N downto 1));
+  -- update write pointer
+  w_ptr_next <= gray1 when wr='1' and full_flag='0' else
+                w_ptr_reg;
+  -- N-bit Gray counter
+  waddr_msb <=  w_ptr_reg(N) xor w_ptr_reg(N-1);
+  waddr_all <= waddr_msb & w_ptr_reg(N-2 downto 0);
+  -- check for FIFO full
+  raddr_msb <= r_ptr_in(N) xor r_ptr_in(N-1);
+  full_flag <= '1' when r_ptr_in(N) /=w_ptr_reg(N) and
+               r_ptr_in(N-2 downto 0)=w_ptr_reg(N-2 downto 0) and
+               raddr_msb = waddr_msb else
+               '0';
+  -- output
+  w_addr    <= waddr_all;
+  w_ptr_out <= w_ptr_reg;
+  full      <= full_flag;
+
+end gray_arch;
diff --git a/cores/axis_avgr_v1_0/n_sync.vhd b/cores/axis_avgr_v1_0/n_sync.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..396966990bda1fbeaefb2f267e981abc9a791f64
--- /dev/null
+++ b/cores/axis_avgr_v1_0/n_sync.vhd
@@ -0,0 +1,41 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity n_sync is
+  generic(
+           N : natural
+         );
+  port(
+        clk      : in std_logic;
+        reset    : in std_logic;
+        in_async : in std_logic_vector(N-1 downto 0);
+        out_sync : out std_logic_vector(N-1 downto 0)
+      );
+end n_sync;
+
+architecture two_ff_arch of n_sync is
+  signal meta_reg, sync_reg  : std_logic_vector(N-1 downto 0);
+  signal meta_next, sync_next: std_logic_vector(N-1 downto 0);
+begin
+
+  -- two registers
+  process(clk)
+  begin
+    if rising_edge(clk) then
+      if (reset='0') then
+        meta_reg <= (others=>'0');
+        sync_reg <= (others=>'0');
+      else
+        meta_reg <= meta_next;
+        sync_reg <= sync_next;
+      end if;
+    end if;
+  end process;
+
+  -- next-state logic
+  meta_next <= in_async;
+  sync_next <= meta_reg;
+  -- output
+  out_sync <= sync_reg;
+
+end two_ff_arch;
diff --git a/cores/axis_avgr_v1_0/sync.vhd b/cores/axis_avgr_v1_0/sync.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..ca83fec39785fa8b1af7f2c1a19ccd59cd72bc6b
--- /dev/null
+++ b/cores/axis_avgr_v1_0/sync.vhd
@@ -0,0 +1,39 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+--synchronizer
+entity sync is
+  port(
+        clk      : in std_logic;
+        reset    : in std_logic;
+        in_async : in std_logic;
+        out_sync : out std_logic
+      );
+end sync;
+
+architecture two_ff_arch of sync is
+  signal meta_reg, sync_reg  : std_logic;
+  signal meta_next, sync_next: std_logic;
+begin
+
+  -- two registers
+  process(clk)
+  begin
+    if rising_edge(clk) then
+      if (reset='0') then
+        meta_reg <= '0';
+        sync_reg <= '0';
+      else
+        meta_reg <= meta_next;
+        sync_reg <= sync_next;
+      end if;
+    end if;
+  end process;
+
+  -- next-state logic
+  meta_next <= in_async;
+  sync_next <= meta_reg;
+  -- output
+  out_sync <= sync_reg;
+
+end two_ff_arch;
diff --git a/cores/axis_avgr_v1_0/tdp_bram.vhd b/cores/axis_avgr_v1_0/tdp_bram.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..e991a176e96b2bcf8a9427470322afc612bc3e16
--- /dev/null
+++ b/cores/axis_avgr_v1_0/tdp_bram.vhd
@@ -0,0 +1,60 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity tdp_bram is
+  generic (
+            AWIDTH       : integer := 16;
+            DWIDTH       : integer := 16
+          );
+  port ( 
+         clka    : in std_logic;
+         clkb    : in std_logic;
+         ena     : in std_logic;
+         enb     : in std_logic;
+         wea     : in std_logic;
+         web     : in std_logic;
+         addra   : in std_logic_vector (AWIDTH-1 downto 0);
+         addrb   : in std_logic_vector (AWIDTH-1 downto 0);
+         dia     : in std_logic_vector (DWIDTH-1 downto 0);
+         dib     : in std_logic_vector (DWIDTH-1 downto 0);
+         doa     : out std_logic_vector (DWIDTH-1 downto 0);
+         dob     : out std_logic_vector (DWIDTH-1 downto 0)
+       );
+end tdp_bram;
+
+architecture rtl of tdp_bram is
+
+  type ram_t is array (2**AWIDTH-1 downto 0) of std_logic_vector (DWIDTH-1 downto 0);
+  shared variable ram : ram_t;
+
+begin
+
+  -- clka port.
+  process (clka)
+  begin
+    if rising_edge(clka) then
+      if (ena = '1') then
+        doa <= ram(to_integer(unsigned(addra)));
+        if (wea = '1') then
+          ram(to_integer(unsigned(addra))) := dia;
+        end if;
+      end if;
+    end if;
+  end process;
+
+  -- clkb port.
+  process (clkb)
+  begin
+    if rising_edge(clkb) then
+      if (enb = '1') then
+        dob <= ram(to_integer(unsigned(addrb)));
+        if (web = '1') then
+          ram(to_integer(unsigned(addrb))) := dib;
+        end if;
+      end if;
+    end if;
+  end process;
+
+end rtl;
+
diff --git a/cores/axis_bram_reader_v1_0/axis_bram_reader.vhd b/cores/axis_bram_reader_v1_0/axis_bram_reader.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..54ca5a94d39d0cb616aa69859c8c66db08c11ae0
--- /dev/null
+++ b/cores/axis_bram_reader_v1_0/axis_bram_reader.vhd
@@ -0,0 +1,90 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_bram_reader is
+  generic (
+            BRAM_ADDR_WIDTH   : natural := 10;
+            BRAM_DATA_WIDTH   : natural := 32;
+            AXIS_TDATA_WIDTH  : natural := 32
+          );
+  port (
+         -- System signals
+         aclk             : in std_logic;
+         aresetn          : in std_logic;
+
+         cfg_data         : in std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+         sts_data         : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+
+         -- Master side
+         m_axis_tready    : in std_logic;
+         m_axis_tdata     : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         m_axis_tvalid    : out std_logic;
+         m_axis_tlast     : out std_logic;
+
+         --m_axis_config_tready : in std_logic;
+         --m_axis_config_tvalid : out std_logic;
+
+         -- BRAM port
+         bram_porta_clk   : out std_logic;
+         bram_porta_rst   : out std_logic;
+         bram_porta_addr  : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+         bram_porta_rddata: in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0)
+       );
+end axis_bram_reader;
+
+architecture rtl of axis_bram_reader is
+
+  signal addr_reg, addr_next     : unsigned(BRAM_ADDR_WIDTH-1 downto 0);
+  signal addr_dly_reg, addr_dly_next : unsigned(BRAM_ADDR_WIDTH-1 downto 0);
+  signal tlast_reg, tlast_next   : std_logic;
+  signal comp_reg, comp_next     : std_logic;
+
+begin
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if aresetn = '0' then
+        addr_reg <= (others => '0');
+        comp_reg <= '0';
+        addr_dly_reg <= (others => '0');
+        tlast_reg <= '0';
+      else 
+        addr_reg <= addr_next;
+        comp_reg <= comp_next;
+        addr_dly_reg <= addr_dly_next;
+        tlast_reg <= tlast_next;
+      end if;
+    end if;
+  end process;
+
+  -- Next state logic
+  comp_next <= '0' when (addr_reg = unsigned(cfg_data)) else
+               '1';
+
+  tlast_next <= '1' when (addr_reg = unsigned(cfg_data)-1) else
+                '0';
+
+  addr_next <= addr_reg + 1 when (m_axis_tready = '1') and (comp_reg = '1') else
+               (others => '0') when (comp_reg = '0') else
+               addr_reg;
+
+  addr_dly_next <= addr_reg;
+
+  --tvalid_next <= '1' when (tvalid_reg = '0') and (comp_reg = '1') else 
+  --							 '0' when 
+  --							 tvalid_reg;
+
+  sts_data <= std_logic_vector(addr_dly_reg);
+
+  m_axis_tdata  <= bram_porta_rddata;
+  m_axis_tvalid <= comp_reg;
+  m_axis_tlast  <= tlast_reg;
+
+  bram_porta_clk <= aclk;
+  bram_porta_rst <= not aresetn;
+  bram_porta_addr <= std_logic_vector(addr_next);
+
+end rtl;
diff --git a/cores/axis_bram_reader_v1_0/core_config.tcl b/cores/axis_bram_reader_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..bc9d829694dda11ac02202f2f2607f7759e48942
--- /dev/null
+++ b/cores/axis_bram_reader_v1_0/core_config.tcl
@@ -0,0 +1,35 @@
+set display_name {AXI4-Stream Block RAM Reader}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+core_parameter BRAM_DATA_WIDTH {BRAM DATA WIDTH} {Width of the BRAM data port.}
+core_parameter BRAM_ADDR_WIDTH {BRAM ADDR WIDTH} {Width of the BRAM address port.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS $parameter
+
+set bus [ipx::add_bus_interface BRAM_PORTA $core]
+set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus
+set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus
+set_property INTERFACE_MODE master $bus
+foreach {logical physical} {
+  RST  bram_porta_rst
+  CLK  bram_porta_clk
+  ADDR bram_porta_addr
+  DOUT bram_porta_rddata
+} {
+  set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus]
+}
+
+set bus [ipx::get_bus_interfaces bram_porta_clk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE BRAM_PORTA $parameter
diff --git a/cores/axis_bram_writer_v1_0/axis_bram_writer.vhd b/cores/axis_bram_writer_v1_0/axis_bram_writer.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..ac290e411f2003e1b5bc5dabe32f1f08312c1e47
--- /dev/null
+++ b/cores/axis_bram_writer_v1_0/axis_bram_writer.vhd
@@ -0,0 +1,73 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_bram_writer is
+  generic (
+            BRAM_ADDR_WIDTH   : natural := 10;
+            BRAM_DATA_WIDTH   : natural := 32;
+            AXIS_TDATA_WIDTH  : natural := 32
+          );
+  port (
+         -- System signals
+         aclk             : in std_logic;
+         aresetn          : in std_logic;
+
+         sts_data         : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+
+         -- Slave side
+         s_axis_tready    : out std_logic;
+         s_axis_tdata     : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         s_axis_tvalid    : in std_logic;
+
+         -- BRAM port
+         bram_porta_clk   : out std_logic;
+         bram_porta_rst   : out std_logic;
+         bram_porta_addr  : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+         bram_porta_wrdata: out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+         bram_porta_we    : out std_logic_vector(BRAM_DATA_WIDTH/8-1 downto 0)
+       );
+end axis_bram_writer;
+
+architecture rtl of axis_bram_writer is
+  signal addr_reg, addr_next : std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+  signal enbl_reg, enbl_next : std_logic;
+  signal s_aux1              : std_logic;
+
+begin
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn = '0') then
+        addr_reg <= (others => '0');
+        enbl_reg <= '0';
+      else
+        addr_reg <= addr_next;
+        enbl_reg <= enbl_next;
+      end if;
+    end if;
+  end process;
+
+  -- Next state logic
+  enbl_next <= '1' when enbl_reg = '0' else
+               enbl_reg;
+
+  addr_next <= std_logic_vector(unsigned(addr_reg)+1) when (s_axis_tvalid = '1') and (enbl_reg = '1') else
+               addr_reg;
+
+  sts_data <= addr_reg;
+
+  s_axis_tready <= enbl_reg;
+
+  s_aux1 <= '1' when (s_axis_tvalid = '1') and (enbl_reg = '1') else 
+            '0';
+
+  bram_porta_clk    <= aclk;
+  bram_porta_rst    <= not aresetn;
+  bram_porta_addr   <= addr_reg;
+  bram_porta_wrdata <= s_axis_tdata;
+  bram_porta_we     <= ((BRAM_DATA_WIDTH/8-1) downto 0 => s_aux1); 
+
+end rtl;
diff --git a/cores/axis_bram_writer_v1_0/core_config.tcl b/cores/axis_bram_writer_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..5f6bafdb0005c70dc4f2a71478f04c5115eb6886
--- /dev/null
+++ b/cores/axis_bram_writer_v1_0/core_config.tcl
@@ -0,0 +1,36 @@
+set display_name {AXI4-Stream Block RAM Writer}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter BRAM_DATA_WIDTH {BRAM DATA WIDTH} {Width of the BRAM data port.}
+core_parameter BRAM_ADDR_WIDTH {BRAM ADDR WIDTH} {Width of the BRAM address port.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS $parameter
+
+set bus [ipx::add_bus_interface BRAM_PORTA $core]
+set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus
+set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus
+set_property INTERFACE_MODE master $bus
+foreach {logical physical} {
+  RST  bram_porta_rst
+  CLK  bram_porta_clk
+  ADDR bram_porta_addr
+  DIN  bram_porta_wrdata
+  WE   bram_porta_we
+} {
+  set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus]
+}
+
+set bus [ipx::get_bus_interfaces bram_porta_clk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE BRAM_PORTA $parameter
diff --git a/cores/axis_constant_v1_0/axis_constant.vhd b/cores/axis_constant_v1_0/axis_constant.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..96a1ab1caa42056ce6d0bd49acbf406096775890
--- /dev/null
+++ b/cores/axis_constant_v1_0/axis_constant.vhd
@@ -0,0 +1,29 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_constant is
+  generic (
+            AXIS_TDATA_WIDTH: natural := 32
+          );
+  port (
+         -- System signals
+         aclk          : in std_logic;
+
+         cfg_data      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+         -- Master side
+         m_axis_tdata  : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         m_axis_tvalid : out std_logic
+       );
+end axis_constant;
+
+architecture rtl of axis_constant is
+
+begin
+
+  m_axis_tdata <= cfg_data;
+  m_axis_tvalid <= '1';
+
+end rtl;
diff --git a/cores/axis_constant_v1_0/core_config.tcl b/cores/axis_constant_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..195c4d965be657f9594adcb208fc92b4948db595
--- /dev/null
+++ b/cores/axis_constant_v1_0/core_config.tcl
@@ -0,0 +1,16 @@
+set display_name {AXI4-Stream Constant}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS $parameter
diff --git a/cores/axis_counter_v1_0/axis_counter.vhd b/cores/axis_counter_v1_0/axis_counter.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..d13594f76966ae6a98da2092205d32693194ced5
--- /dev/null
+++ b/cores/axis_counter_v1_0/axis_counter.vhd
@@ -0,0 +1,62 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_counter is
+  generic (
+            AXIS_TDATA_WIDTH : natural := 32;
+            CNTR_WIDTH       : natural := 32
+          );
+  port (
+         -- System signals
+         aclk               : in std_logic;
+         aresetn            : in std_logic;
+
+         cfg_data           : in std_logic_vector(CNTR_WIDTH-1 downto 0);
+
+         -- Master side
+         m_axis_tdata       : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         m_axis_tlast       : out std_logic;
+         m_axis_tready      : in std_logic;
+         m_axis_tvalid      : out std_logic
+       );
+end axis_counter;
+
+architecture rtl of axis_counter is
+
+  signal cntr_reg, cntr_next   : unsigned(CNTR_WIDTH-1 downto 0);
+  signal tlast_reg, tlast_next : std_logic;
+  signal comp_reg, comp_next  : std_logic;
+
+begin
+
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+      if(aresetn = '0') then
+        cntr_reg <= (others => '0');
+        tlast_reg <= '0';
+        comp_reg <= '0';
+      else
+        cntr_reg <= cntr_next;
+        tlast_reg <= tlast_next;
+        comp_reg <= comp_next;
+      end if;
+    end if;
+  end process;
+
+  tlast_next <= '1' when (cntr_reg = unsigned(cfg_data)-2) else '0';
+
+  comp_next <= '0' when (cntr_reg = unsigned(cfg_data)-1) else '1';
+
+  cntr_next <= cntr_reg + 1 when ((comp_reg = '1') and (m_axis_tready = '1')) else
+  --cntr_next <= cntr_reg + 1 when ((comp_reg = '1') and (m_axis_tready = '1')) else
+               --(others => '0') when (comp_reg = '0') else --reset
+               cntr_reg;
+
+  m_axis_tdata <= std_logic_vector(resize(cntr_reg, m_axis_tdata'length));
+  m_axis_tlast <= tlast_reg;
+  m_axis_tvalid <= comp_reg;
+
+end rtl;
diff --git a/cores/axis_counter_v1_0/core_config.tcl b/cores/axis_counter_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..c86878a8e3a99a45bb93ae4d76662e3fc8e0b501
--- /dev/null
+++ b/cores/axis_counter_v1_0/core_config.tcl
@@ -0,0 +1,17 @@
+set display_name {AXI4-Stream Counter}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+core_parameter CNTR_WIDTH {CNTR WIDTH} {Width of the counter register.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS $parameter
diff --git a/cores/axis_dc_removal_v1_0/axis_dc_removal.vhd b/cores/axis_dc_removal_v1_0/axis_dc_removal.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..3b42e8b7ecfdaf410795a7f258544abeef327e00
--- /dev/null
+++ b/cores/axis_dc_removal_v1_0/axis_dc_removal.vhd
@@ -0,0 +1,94 @@
+-- See WP279 from Xilinx
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_dc_removal is
+  generic(
+           AXIS_TDATA_WIDTH : integer := 32
+         );
+  port (
+         aclk    : in std_logic;
+         aresetn : in std_logic;
+         k1_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+         k2_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+
+         -- Slave side
+         s_axis_tready     : out std_logic;
+         s_axis_tdata      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         s_axis_tvalid     : in std_logic;
+
+         -- Master side
+         m_axis_tready     : in std_logic;
+         m_axis_tdata      : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         m_axis_tvalid     : out std_logic
+
+       );
+end axis_dc_removal;
+
+architecture rtl of axis_dc_removal is
+
+  signal d1_reg, d1_next : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal d2_reg, d2_next : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal d3_reg, d3_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal ch1_s, ch2_s    : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal axis_tready     : std_logic;
+  signal axis_tvalid     : std_logic;
+
+begin
+
+  axis_tready <= '1'; 
+  s_axis_tready <= axis_tready; 
+  m_axis_tvalid <= axis_tvalid;
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if aresetn = '0' then
+        d1_reg <= (others => '0');     
+        d2_reg <= (others => '0');     
+        d3_reg <= (others => '0');     
+      else
+        d1_reg <= d1_next;
+        d2_reg <= d2_next;
+        d3_reg <= d3_next;
+      end if;
+    end if;
+  end process;
+
+  d1_next <= s_axis_tdata(AXIS_TDATA_WIDTH/2-1 downto 0) when
+             ((axis_tready = '1') and (s_axis_tvalid = '1')) else
+             d1_reg;
+  d2_next <= s_axis_tdata(AXIS_TDATA_WIDTH-1 downto AXIS_TDATA_WIDTH/2)
+             when ((axis_tready = '1') and (s_axis_tvalid = '1')) else
+             d2_reg;
+
+  d3_next <= ch2_s & ch1_s when ((m_axis_tready = '1') and (axis_tvalid = '1')) else 
+             d3_reg;
+
+
+  --dc removal for ch1
+  ch1_dcrm: entity work.dc_removal
+  port map(
+            aclk     => aclk,
+            aresetn  => aresetn,
+            k_i      => k1_i,
+            data_i   => d1_reg,
+            data_o   => ch1_s
+          );
+
+  --dc removal for ch2
+  ch2_dcrm: entity work.dc_removal
+  port map(
+            aclk     => aclk,
+            aresetn  => aresetn,
+            k_i      => k2_i,
+            data_i   => d2_reg,
+            data_o   => ch2_s
+          );
+
+  axis_tvalid <= '1';
+  m_axis_tdata <= d3_reg;
+
+end rtl;     
diff --git a/cores/axis_dc_removal_v1_0/core_config.tcl b/cores/axis_dc_removal_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..25887086cac98e38415ec6b0d518af91f17bd471
--- /dev/null
+++ b/cores/axis_dc_removal_v1_0/core_config.tcl
@@ -0,0 +1,21 @@
+set display_name {AXI4-Stream Digital DC Removal Circuit}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
+
diff --git a/cores/axis_dc_removal_v1_0/dc_removal.vhd b/cores/axis_dc_removal_v1_0/dc_removal.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..75c732baca78217910e768a7c3244f02417efba6
--- /dev/null
+++ b/cores/axis_dc_removal_v1_0/dc_removal.vhd
@@ -0,0 +1,92 @@
+-- See WP279 from Xilinx
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity dc_removal is
+  generic(
+           DATA_WIDTH : integer := 16
+         );
+  port (
+         aclk    : in std_logic;
+         aresetn : in std_logic;
+         k_i     : in std_logic_vector(DATA_WIDTH-1 downto 0);
+         data_i  : in std_logic_vector(DATA_WIDTH-1 downto 0);
+         data_o  : out std_logic_vector(DATA_WIDTH-1 downto 0)
+       );
+end dc_removal;
+
+architecture rtl of dc_removal is
+  signal k_reg, k_next     : std_logic_vector(DATA_WIDTH-1 downto 0);
+  signal d0_reg, d0_next   : std_logic_vector(DATA_WIDTH-1 downto 0);
+  signal d11_reg, d11_next : std_logic_vector(DATA_WIDTH-1 downto 0);
+  signal d12_reg, d12_next : std_logic_vector(DATA_WIDTH-1 downto 0);
+  signal d21_reg, d21_next : std_logic_vector(DATA_WIDTH-1 downto 0);
+  signal d22_reg, d22_next : std_logic_vector(2*DATA_WIDTH-1 downto 0);
+  signal d31_reg, d31_next : std_logic_vector(DATA_WIDTH-1 downto 0);
+  signal d32_reg, d32_next : std_logic_vector(2*DATA_WIDTH-1 downto 0);
+  signal d4_reg, d4_next   : std_logic_vector(DATA_WIDTH-1 downto 0);
+  signal mult_s            : std_logic_vector(2*DATA_WIDTH-1 downto 0);
+  signal sub_s             : std_logic_vector(DATA_WIDTH-1 downto 0);
+  signal sub2_s            : std_logic_vector(DATA_WIDTH-1 downto 0);
+  signal data_fbk          : std_logic_vector(DATA_WIDTH-1 downto 0);
+
+begin
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if aresetn = '0' then
+        k_reg   <= (others => '0');     
+        d0_reg  <= (others => '0');     
+        d11_reg <= (others => '0');     
+        d12_reg <= (others => '0');     
+        d21_reg <= (others => '0');     
+        d22_reg <= (others => '0');     
+        d31_reg <= (others => '0');     
+        d32_reg <= (others => '0');     
+        d4_reg  <= (others => '0');     
+      else
+        k_reg   <= k_next;
+        d0_reg  <= d0_next;
+        d11_reg <= d11_next;
+        d12_reg <= d12_next;
+        d21_reg <= d21_next;
+        d22_reg <= d22_next;
+        d31_reg <= d31_next;
+        d32_reg <= d32_next;
+        d4_reg  <= d4_next;
+      end if;
+    end if;
+  end process;
+
+  k_next <= k_i;
+
+  d0_next <= data_i;
+
+  d11_next <= d0_reg;
+
+  sub_s <= std_logic_vector(signed(d0_reg) - signed(data_fbk));
+
+  d12_next <= sub_s; 
+
+  d21_next <= d11_reg; 
+
+  mult_s <= std_logic_vector(signed(k_reg) * signed(d12_reg));
+
+  d22_next <= mult_s;
+
+  d31_next <= d21_reg; 
+
+  d32_next <= std_logic_vector(signed(d32_reg) + signed(d22_reg));
+
+  data_fbk <= d32_reg(2*DATA_WIDTH-1 downto DATA_WIDTH);
+
+  sub2_s <= std_logic_vector(signed(d31_reg) - signed(data_fbk));
+
+  d4_next <= sub2_s;
+
+  data_o <= d4_reg;
+
+end rtl;     
diff --git a/cores/axis_decimator_v1_0/axis_decimator.vhd b/cores/axis_decimator_v1_0/axis_decimator.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..532a52f411675b4ab8343fc7de7c533b55f4dd24
--- /dev/null
+++ b/cores/axis_decimator_v1_0/axis_decimator.vhd
@@ -0,0 +1,80 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_decimator is
+  generic (
+    AXIS_TDATA_WIDTH : natural  := 32;
+    CNTR_WIDTH       : natural  := 32
+);
+port (
+  -- System signals
+  aclk           : in std_logic;
+  aresetn        : in std_logic;
+
+  cfg_data       : in std_logic_vector(CNTR_WIDTH-1 downto 0);
+
+  -- Slave side
+  s_axis_tready  : out std_logic;
+  s_axis_tdata   : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  s_axis_tvalid  : in std_logic;
+
+  -- Master side
+  m_axis_tready  : in std_logic;
+  m_axis_tdata   : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  m_axis_tvalid  : out std_logic
+);
+end axis_decimator;
+
+architecture rtl of axis_decimator is
+
+  signal int_tdata_reg, int_tdata_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal int_cntr_reg, int_cntr_next: unsigned(CNTR_WIDTH-1 downto 0);
+  signal int_tvalid_reg, int_tvalid_next: std_logic;
+  signal int_tready_reg, int_tready_next: std_logic;
+
+  signal int_comp_wire, int_tvalid_wire: std_logic;
+
+begin
+
+  int_comp_wire <= '1' when (int_cntr_reg < unsigned(cfg_data)) else '0';
+  int_tvalid_wire <= int_tready_reg and s_axis_tvalid;
+
+  process(aclk)
+  begin
+  if (rising_edge(aclk)) then
+  if (aresetn = '0') then
+    int_tdata_reg <= (others => '0');
+    int_tvalid_reg <= '0';
+    int_tready_reg <= '0';
+    int_cntr_reg <= (others => '0');
+  else
+    int_tdata_reg <= int_tdata_next;
+    int_tvalid_reg <= int_tvalid_next;
+    int_tready_reg <= int_tready_next;
+    int_cntr_reg <= int_cntr_next;
+  end if;
+  end if;
+  end process;
+
+
+  int_tready_next <= '1' when (int_tready_reg = '0') and (int_comp_wire = '1') else
+                     int_tready_reg;
+
+  int_cntr_next <= int_cntr_reg + 1 when (int_tvalid_wire = '1') and (int_comp_wire = '1') else
+                   (others => '0') when (int_tvalid_wire = '1') and (int_comp_wire = '0') else
+                   int_cntr_reg;
+
+  int_tdata_next <= s_axis_tdata when (int_tvalid_wire = '1') and (int_comp_wire = '0') else
+                        int_tdata_reg;
+
+  int_tvalid_next <= '1' when (int_tvalid_wire = '1') and (int_comp_wire = '0') else
+                    '0' when (m_axis_tready = '1') and (int_tvalid_reg = '1') else
+                    int_tvalid_reg;
+
+  s_axis_tready <= int_tready_reg;
+  m_axis_tdata <= int_tdata_reg;
+  m_axis_tvalid <= int_tvalid_reg;
+
+end rtl;
diff --git a/cores/axis_decimator_v1_0/core_config.tcl b/cores/axis_decimator_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..f91a68253c3239bc20a0819b3205380b8197896f
--- /dev/null
+++ b/cores/axis_decimator_v1_0/core_config.tcl
@@ -0,0 +1,21 @@
+set display_name {AXI4-Stream Decimator}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS and S_AXIS data buses.}
+core_parameter CNTR_WIDTH {CNTR WIDTH} {Width of the counter register.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
diff --git a/cores/axis_fifo_v1_0/axis_fifo.vhd b/cores/axis_fifo_v1_0/axis_fifo.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..862f7a011ae375565c098db15fc1f6f725ba569b
--- /dev/null
+++ b/cores/axis_fifo_v1_0/axis_fifo.vhd
@@ -0,0 +1,124 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_fifo is
+  generic(
+           AXIS_TDATA_WIDTH : natural := 32;
+           FIFO_DEPTH       : natural := 16
+         --           AWIDTH           : natural := 2
+         );
+  port(
+        -- Slave data interface
+        s_axis_aclk       : in std_logic;
+        s_axis_aresetn    : in std_logic;
+        s_axis_tready     : out std_logic;
+        s_axis_tvalid     : in std_logic;
+        s_axis_tdata      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+        -- Master data interface
+        m_axis_aclk       : in std_logic;
+        m_axis_aresetn    : in std_logic;
+        m_axis_tready     : in std_logic;
+        m_axis_tvalid     : out std_logic;
+        --m_axis_tlast      : out std_logic;
+        m_axis_tdata      : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0)
+      );
+end axis_fifo;
+
+architecture rtl of axis_fifo is
+  function log2c(n: integer) return integer is
+    variable m, p: integer;
+  begin
+    m := 0;
+    p := 1;
+    while p < n loop
+      m := m + 1;
+      p := p * 2;
+    end loop;
+    return m;
+  end log2c;
+
+  constant AWIDTH : natural := log2c(FIFO_DEPTH);
+
+  signal s_tready_reg, s_tready_next : std_logic;
+  signal m_tvalid_reg, m_tvalid_next : std_logic;
+  signal we_s, rd_s, full_s, empty_s : std_logic;
+  signal w_addr_s, r_addr_s          : std_logic_vector(AWIDTH-1 downto 0);
+
+begin
+
+  s_axis_tready <= s_tready_reg;
+
+  --slave port registers
+  process(s_axis_aclk)
+  begin
+    if rising_edge(s_axis_aclk) then
+      if (s_axis_aresetn = '0') then
+        s_tready_reg <= '0';
+      else
+        s_tready_reg <= s_tready_next;
+      end if;
+    end if;
+  end process;
+  --next state logic
+  s_tready_next <= '1' when (full_s = '0') else '0'; 
+  we_s          <= '1' when (full_s = '0') and (s_axis_tvalid = '1') else '0';
+
+  m_axis_tvalid <= m_tvalid_reg;
+  --master port registers
+  process(m_axis_aclk)
+  begin
+    if rising_edge(m_axis_aclk) then
+      if (m_axis_aresetn = '0') then
+        m_tvalid_reg <= '0';
+      else
+        m_tvalid_reg <= m_tvalid_next;
+      end if;
+    end if;
+  end process;
+  --next state logic
+  m_tvalid_next <= '1' when (empty_s = '0') else '0';
+  rd_s          <= '1' when (empty_s = '0') and (m_axis_tready = '1') else '0';
+
+  --port a is wr port (slave)
+  --port b is rd port (master)
+  dp_ram_i: entity work.dp_ram 
+  generic map(
+               AWIDTH       => AWIDTH,
+               DWIDTH       => AXIS_TDATA_WIDTH
+             )
+  port map(
+            clka    => s_axis_aclk,
+            clkb    => m_axis_aclk,
+            ena     => '1',
+            enb     => '1',
+            wea     => we_s,
+            web     => '0',
+            addra   => w_addr_s,
+            addrb   => r_addr_s,
+            dia     => s_axis_tdata,
+            dib     => (others => '0'),
+            doa     => open,
+            dob     => m_axis_tdata
+          );
+
+  fifo_ctrl_i: entity work.fifo_async_ctrl
+  generic map(
+               --DEPTH => FIFO_DEPTH
+               DEPTH => AWIDTH
+             )
+  port map(
+            clkw   => s_axis_aclk,
+            resetw => s_axis_aresetn,
+            wr     => we_s,
+            full   => full_s,
+            w_addr => w_addr_s,
+            clkr   => m_axis_aclk,
+            resetr => m_axis_aresetn,
+            rd     => rd_s,
+            empty  => empty_s,
+            r_addr => r_addr_s
+          );
+
+end rtl;
diff --git a/cores/axis_fifo_v1_0/core_config.tcl b/cores/axis_fifo_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..416eb3b827eee953011c1a56b2cf0eedf12f697d
--- /dev/null
+++ b/cores/axis_fifo_v1_0/core_config.tcl
@@ -0,0 +1,26 @@
+set display_name {AXI4-Stream FIFO v1.0}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter FIFO_DEPTH {FIFO DEPTH} {Depth of the FIFO.}
+#core_parameter AWIDTH {ADDRESS WIDTH} {Determines the depth of the FIFO.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces s_axis_aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS $parameter
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces m_axis_aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS $parameter
diff --git a/cores/axis_fifo_v1_0/dp_bram.vhd b/cores/axis_fifo_v1_0/dp_bram.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..d483c497b763505add0b6ac983d6811fd9dac8ff
--- /dev/null
+++ b/cores/axis_fifo_v1_0/dp_bram.vhd
@@ -0,0 +1,60 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.std_logic_unsigned.all;
+
+entity dp_ram is
+  generic (
+            AWIDTH       : integer := 16;
+            DWIDTH       : integer := 16
+          );
+  port ( 
+         clka    : in std_logic;
+         clkb    : in std_logic;
+         ena     : in std_logic;
+         enb     : in std_logic;
+         wea     : in std_logic;
+         web     : in std_logic;
+         addra   : in std_logic_vector (AWIDTH-1 downto 0);
+         addrb   : in std_logic_vector (AWIDTH-1 downto 0);
+         dia     : in std_logic_vector (DWIDTH-1 downto 0);
+         dib     : in std_logic_vector (DWIDTH-1 downto 0);
+         doa     : out std_logic_vector (DWIDTH-1 downto 0);
+         dob     : out std_logic_vector (DWIDTH-1 downto 0)
+       );
+end dp_ram;
+
+architecture rtl of dp_ram is
+
+  type ram_t is array (2**AWIDTH-1 downto 0) of std_logic_vector (DWIDTH-1 downto 0);
+  shared variable ram : ram_t;
+
+begin
+
+  -- clka port.
+  process (clka)
+  begin
+    if rising_edge(clka) then
+      if (ena = '1') then
+        doa <= ram(conv_integer(addra));
+        if (wea = '1') then
+          ram(conv_integer(addra)) := dia;
+        end if;
+      end if;
+    end if;
+  end process;
+
+  -- clkb port.
+  process (clkb)
+  begin
+    if rising_edge(clkb) then
+      if (enb = '1') then
+        dob <= ram(conv_integer(addrb));
+        if (web = '1') then
+          ram(conv_integer(addrb)) := dib;
+        end if;
+      end if;
+    end if;
+  end process;
+
+end rtl;
+
diff --git a/cores/axis_fifo_v1_0/fifo_async_ctrl.vhd b/cores/axis_fifo_v1_0/fifo_async_ctrl.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..3f10117aa1250991485c1e464b54013afe23c421
--- /dev/null
+++ b/cores/axis_fifo_v1_0/fifo_async_ctrl.vhd
@@ -0,0 +1,81 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity fifo_async_ctrl is
+  generic(
+           DEPTH: natural := 4
+         );
+  port(
+        clkw   : in std_logic;
+        resetw : in std_logic;
+        wr     : in std_logic;
+        full   : out std_logic;
+        w_addr : out std_logic_vector (DEPTH-1 downto 0);
+        clkr   : in std_logic;
+        resetr : in std_logic;
+        rd     : in std_logic;
+        empty  : out std_logic;
+        r_addr : out std_logic_vector (DEPTH-1 downto 0)
+      );
+end fifo_async_ctrl ;
+
+architecture str_arch of fifo_async_ctrl is
+
+  signal r_ptr_in  : std_logic_vector(DEPTH downto 0);
+  signal r_ptr_out : std_logic_vector(DEPTH downto 0);
+  signal w_ptr_in  : std_logic_vector(DEPTH downto 0);
+  signal w_ptr_out : std_logic_vector(DEPTH downto 0);
+
+begin
+  read_ctrl: entity work.fifo_read_ctrl
+  generic map(
+               N=>DEPTH
+             )
+  port map (
+             clkr     => clkr, 
+             resetr   => resetr, 
+             rd       => rd,
+             w_ptr_in => w_ptr_in, 
+             empty    => empty,
+             r_ptr_out=> r_ptr_out, 
+             r_addr   => r_addr
+           );
+
+  write_ctrl: entity work.fifo_write_ctrl
+  generic map(
+               N =>DEPTH
+             )
+  port map(
+            clkw      => clkw, 
+            resetw    => resetw, 
+            wr        => wr,
+            r_ptr_in  => r_ptr_in, 
+            full      => full,
+            w_ptr_out => w_ptr_out, 
+            w_addr    => w_addr
+          );
+
+  sync_w_ptr: entity work.n_sync
+  generic map(
+               N=>DEPTH+1
+             )
+  port map(
+            clk      => clkw, 
+            reset    => resetw,
+            in_async => w_ptr_out,
+            out_sync => w_ptr_in
+          );
+
+  sync_r_ptr: entity work.n_sync
+  generic map(
+               N=>DEPTH+1
+             )
+  port map(
+            clk      => clkr, 
+            reset    => resetr,
+            in_async => r_ptr_out, 
+            out_sync => r_ptr_in
+          );
+
+end str_arch;
diff --git a/cores/axis_fifo_v1_0/fifo_read.vhd b/cores/axis_fifo_v1_0/fifo_read.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..65d0f7c5116991989cab5fb965fc8bd1a22463ae
--- /dev/null
+++ b/cores/axis_fifo_v1_0/fifo_read.vhd
@@ -0,0 +1,62 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity fifo_read_ctrl is
+  generic(
+           N: natural :=4
+         );
+  port(
+        clkr     : in std_logic;
+        resetr   : in std_logic;
+        w_ptr_in : in std_logic_vector(N downto 0);
+        rd       : in std_logic;
+        empty    : out std_logic;
+        r_ptr_out: out std_logic_vector(N downto 0);
+        r_addr   : out std_logic_vector(N-1 downto 0)
+      );
+end fifo_read_ctrl;
+
+architecture gray_arch of fifo_read_ctrl is
+  signal r_ptr_reg, r_ptr_next : std_logic_vector(N downto 0);
+  signal gray1, bin, bin1      : std_logic_vector(N downto 0);
+  signal raddr_all             : std_logic_vector(N-1 downto 0);
+  signal raddr_msb,waddr_msb   : std_logic;
+  signal empty_flag            : std_logic;
+
+begin
+
+  -- register
+  process(clkr)
+  begin
+    if rising_edge(clkr) then
+      if (resetr='0') then
+        r_ptr_reg <= (others=>'0');
+      else
+        r_ptr_reg <= r_ptr_next;
+      end if;
+    end if;
+  end process;
+
+  -- (N+1)-bit Gray counter
+  bin   <= r_ptr_reg xor ('0' & bin(N downto 1));
+  bin1  <= std_logic_vector(unsigned(bin) + 1);
+  gray1 <= bin1 xor ('0' & bin1(N downto 1));
+
+  -- update read pointer
+  r_ptr_next <= gray1 when rd='1' and empty_flag='0' else
+                r_ptr_reg;
+  -- N-bit Gray counter
+  raddr_msb <= r_ptr_reg(N) xor r_ptr_reg(N-1);
+  raddr_all <= raddr_msb & r_ptr_reg(N-2 downto 0);
+  waddr_msb <= w_ptr_in(N) xor w_ptr_in(N-1);
+  -- check for FIFO empty
+  empty_flag <= '1' when w_ptr_in(N)=r_ptr_reg(N) and
+                w_ptr_in(N-2 downto 0)=r_ptr_reg(N-2 downto 0) and
+                raddr_msb = waddr_msb else
+                '0';
+  -- output
+  r_addr <= raddr_all;
+  r_ptr_out <= r_ptr_reg;
+  empty <= empty_flag;
+end gray_arch;
diff --git a/cores/axis_fifo_v1_0/fifo_write.vhd b/cores/axis_fifo_v1_0/fifo_write.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..46d831068430c731c799590ff90ed3005f43f30b
--- /dev/null
+++ b/cores/axis_fifo_v1_0/fifo_write.vhd
@@ -0,0 +1,62 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity fifo_write_ctrl is
+  generic(
+           N : natural := 4
+         );
+  port(
+        clkw     : in std_logic;
+        resetw   : in std_logic;
+        wr       : in std_logic;
+        r_ptr_in : in std_logic_vector(N downto 0);
+        full     : out std_logic;
+        w_ptr_out: out std_logic_vector(N downto 0);
+        w_addr   : out std_logic_vector(N-1 downto 0)
+      );
+end fifo_write_ctrl;
+
+architecture gray_arch of fifo_write_ctrl is
+  signal w_ptr_reg, w_ptr_next :std_logic_vector(N downto 0);
+  signal gray1, bin, bin1      : std_logic_vector(N downto 0);
+  signal waddr_all             : std_logic_vector(N-1 downto 0);
+  signal waddr_msb, raddr_msb  : std_logic;
+  signal full_flag             : std_logic;
+
+begin
+
+  -- register
+  process(clkw)
+  begin
+    if rising_edge(clkw) then
+      if (resetw='0') then
+        w_ptr_reg <= (others=>'0');
+      else
+        w_ptr_reg <= w_ptr_next;
+      end if;
+    end if;
+  end process;
+
+  -- (N+1)-bit Gray counter
+  bin   <= w_ptr_reg xor ('0' & bin(N downto 1));
+  bin1  <= std_logic_vector(unsigned(bin) + 1);
+  gray1 <= bin1 xor ('0' & bin1(N downto 1));
+  -- update write pointer
+  w_ptr_next <= gray1 when wr='1' and full_flag='0' else
+                w_ptr_reg;
+  -- N-bit Gray counter
+  waddr_msb <=  w_ptr_reg(N) xor w_ptr_reg(N-1);
+  waddr_all <= waddr_msb & w_ptr_reg(N-2 downto 0);
+  -- check for FIFO full
+  raddr_msb <= r_ptr_in(N) xor r_ptr_in(N-1);
+  full_flag <= '1' when r_ptr_in(N) /=w_ptr_reg(N) and
+               r_ptr_in(N-2 downto 0)=w_ptr_reg(N-2 downto 0) and
+               raddr_msb = waddr_msb else
+               '0';
+  -- output
+  w_addr    <= waddr_all;
+  w_ptr_out <= w_ptr_reg;
+  full      <= full_flag;
+
+end gray_arch;
diff --git a/cores/axis_fifo_v1_0/n_sync.vhd b/cores/axis_fifo_v1_0/n_sync.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..396966990bda1fbeaefb2f267e981abc9a791f64
--- /dev/null
+++ b/cores/axis_fifo_v1_0/n_sync.vhd
@@ -0,0 +1,41 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+entity n_sync is
+  generic(
+           N : natural
+         );
+  port(
+        clk      : in std_logic;
+        reset    : in std_logic;
+        in_async : in std_logic_vector(N-1 downto 0);
+        out_sync : out std_logic_vector(N-1 downto 0)
+      );
+end n_sync;
+
+architecture two_ff_arch of n_sync is
+  signal meta_reg, sync_reg  : std_logic_vector(N-1 downto 0);
+  signal meta_next, sync_next: std_logic_vector(N-1 downto 0);
+begin
+
+  -- two registers
+  process(clk)
+  begin
+    if rising_edge(clk) then
+      if (reset='0') then
+        meta_reg <= (others=>'0');
+        sync_reg <= (others=>'0');
+      else
+        meta_reg <= meta_next;
+        sync_reg <= sync_next;
+      end if;
+    end if;
+  end process;
+
+  -- next-state logic
+  meta_next <= in_async;
+  sync_next <= meta_reg;
+  -- output
+  out_sync <= sync_reg;
+
+end two_ff_arch;
diff --git a/cores/axis_generator_v1_0/axis_generator.vhd b/cores/axis_generator_v1_0/axis_generator.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..8a20378cc43a43e645c8bf575bfd1816479ad614
--- /dev/null
+++ b/cores/axis_generator_v1_0/axis_generator.vhd
@@ -0,0 +1,131 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axi_stream_generator is
+  generic(
+           AXIS_TDATA_WIDTH : natural := 32
+         );
+  port 
+  (
+    -- DO NOT EDIT BELOW THIS LINE ---------------------
+    -- Bus protocol ports, do not add or delete. 
+    aclk	: in	std_logic;
+    aresetn	: in	std_logic;
+    s_axis_tready	: out	std_logic;
+    s_axis_tdata	: in	std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+    s_axis_tlast	: in	std_logic;
+    s_axis_tvalid	: in	std_logic;
+    m_axis_tvalid	: out	std_logic;
+    m_axis_tdata	: out	std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+    m_axis_tlast	: out	std_logic;
+    m_axis_tready	: in	std_logic
+  -- DO NOT EDIT ABOVE THIS LINE ---------------------
+  );
+
+--  attribute SIGIS : string; 
+--  attribute SIGIS of ACLK : signal is "Clk"; 
+
+end axi_stream_generator;
+
+------------------------------------------------------------------------------
+-- Architecture Section
+------------------------------------------------------------------------------
+
+-- In this section, we povide an example implementation of ENTITY axi_stream_generator
+-- that does the following:
+--
+-- 1. Read all inputs
+-- 2. Add each input to the contents of register 'sum' which
+--    acts as an accumulator
+-- 3. After all the inputs have been read, write out the
+--    content of 'sum' into the output stream NUMBER_OF_OUTPUT_WORDS times
+--
+-- You will need to modify this example or implement a new architecture for
+-- ENTITY axi_stream_generator to implement your coprocessor
+
+architecture EXAMPLE of axi_stream_generator is
+
+  -- Total number of input data.
+  constant NUMBER_OF_INPUT_WORDS  : natural := 8;
+
+  -- Total number of output data
+  constant NUMBER_OF_OUTPUT_WORDS : natural := 8;
+
+  type STATE_TYPE is (Idle, Read_Inputs, Write_Outputs);
+
+  signal state        : STATE_TYPE;
+
+  -- Accumulator to hold sum of inputs read at any point in time
+  signal sum          : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+  -- Counters to store the number inputs read & outputs written
+  signal nr_of_reads  : natural range 0 to NUMBER_OF_INPUT_WORDS - 1;
+  signal nr_of_writes : natural range 0 to NUMBER_OF_OUTPUT_WORDS - 1;
+
+  -- tlast signal
+  signal tlast : std_logic;
+
+begin
+  -- CAUTION:
+  -- The sequence in which data are read in and written out should be
+  -- consistent with the sequence they are written and read in the
+  -- driver's axi_stream_generator.c file
+
+  -- s_axis_tready  <= '1'   when state = Read_Inputs   else '0';
+  s_axis_tready  <= '0' when state = Write_Outputs else '1';
+  m_axis_tvalid <= '1' when state = Write_Outputs else '0';
+
+  m_axis_tdata <= sum;
+  m_axis_tlast <= tlast;
+
+  The_SW_accelerator : process (ACLK) is
+  begin  -- process The_SW_accelerator
+    if ACLK'event and ACLK = '1' then     -- Rising clock edge
+      if ARESETN = '0' then               -- Synchronous reset (active low)
+                                          -- CAUTION: make sure your reset polarity is consistent with the
+                                          -- system reset polarity
+        state        <= Idle;
+        nr_of_reads  <= 0;
+        nr_of_writes <= 0;
+        sum          <= (others => '0');
+        tlast        <= '0';
+      else
+        case state is
+          when Idle =>
+            if (s_axis_tvalid = '1') then
+              state       <= Read_Inputs;
+              nr_of_reads <= NUMBER_OF_INPUT_WORDS - 1;
+              sum         <= (others => '0');
+            end if;
+
+          when Read_Inputs =>
+            if (s_axis_tvalid = '1') then
+              -- Coprocessor function (Adding) happens here
+              sum         <= std_logic_vector(unsigned(sum) + unsigned(s_axis_tdata));
+              if (s_axis_tlast = '1') then
+                state        <= Write_Outputs;
+                nr_of_writes <= NUMBER_OF_OUTPUT_WORDS - 1;
+              else
+                nr_of_reads <= nr_of_reads - 1;
+              end if;
+            end if;
+
+          when Write_Outputs =>
+            if (m_axis_tready = '1') then
+              if (nr_of_writes = 0) then
+                state <= Idle;
+                tlast <= '0';
+              else
+                -- assert tlast on last transmitted word
+                if (nr_of_writes = 1) then
+                  tlast <= '1';
+                end if;
+                nr_of_writes <= nr_of_writes - 1;
+              end if;
+            end if;
+        end case;
+      end if;
+    end if;
+  end process The_SW_accelerator;
+end architecture EXAMPLE;
diff --git a/cores/axis_generator_v1_0/core_config.tcl b/cores/axis_generator_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..7cf6e7ea3178568977623eb8aa123f0cc5914911
--- /dev/null
+++ b/cores/axis_generator_v1_0/core_config.tcl
@@ -0,0 +1,20 @@
+set display_name {AXI4-Stream Generator v1.0}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {TDATA WIDTH} {Width of the AXIS data bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
diff --git a/cores/axis_gpio_reader_i_v1_0/axis_gpio_reader_i.vhd b/cores/axis_gpio_reader_i_v1_0/axis_gpio_reader_i.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..b97555a94e7a4a99298498df24f53175ed659e8b
--- /dev/null
+++ b/cores/axis_gpio_reader_i_v1_0/axis_gpio_reader_i.vhd
@@ -0,0 +1,52 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity axis_gpio_reader_i is
+  generic (
+  AXIS_TDATA_WIDTH: natural := 32
+);
+port (
+  -- System signals
+  aclk : in std_logic;
+
+  gpio_data : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+  -- Master side
+  m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  m_axis_tvalid : out std_logic
+);
+end axis_gpio_reader_i;
+
+architecture rtl of axis_gpio_reader_i is
+
+  type int_data_t is array (1 downto 0) of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal int_data_reg : int_data_t;
+  signal int_data_wire: std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+begin
+
+  GPIO_G: for j in 0 to AXIS_TDATA_WIDTH-1 generate
+  IBUF_int: IBUF 
+  port map(
+    O => int_data_wire(j), 
+    I => gpio_data(j) 
+    );
+  end generate;
+
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    int_data_reg(0) <= int_data_wire;
+    int_data_reg(1) <= int_data_reg(0);
+    end if;
+  end process;
+
+  m_axis_tdata <= int_data_reg(1);
+  m_axis_tvalid <= '1';
+
+end rtl;
diff --git a/cores/axis_gpio_reader_i_v1_0/core_config.tcl b/cores/axis_gpio_reader_i_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..968c5d347733e2e1f35e40ac4ebe46f8cc5ffd38
--- /dev/null
+++ b/cores/axis_gpio_reader_i_v1_0/core_config.tcl
@@ -0,0 +1,16 @@
+set display_name {AXI4-Stream GPIO Reader}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS $parameter
diff --git a/cores/axis_gpio_reader_v1_0/axis_gpio_reader.vhd b/cores/axis_gpio_reader_v1_0/axis_gpio_reader.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..9b57a63a4acc84ae751d8b310e0ffa8afacb2e54
--- /dev/null
+++ b/cores/axis_gpio_reader_v1_0/axis_gpio_reader.vhd
@@ -0,0 +1,54 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity axis_gpio_reader is
+  generic (
+            AXIS_TDATA_WIDTH: natural := 32
+          );
+  port (
+         -- System signals
+         aclk : in std_logic;
+
+         gpio_data : inout std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+         -- Master side
+         m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         m_axis_tvalid : out std_logic
+       );
+end axis_gpio_reader;
+
+architecture rtl of axis_gpio_reader is
+
+  type int_data_t is array (1 downto 0) of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal int_data_reg : int_data_t;
+  signal int_data_wire: std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+begin
+
+  GPIO_G: for j in 0 to AXIS_TDATA_WIDTH-1 generate
+    IOBUF_int: IOBUF 
+    port map(
+              O => int_data_wire(j), 
+              IO => gpio_data(j), 
+              I => '0', 
+              T => '1'
+            );
+  end generate;
+
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+      int_data_reg(0) <= int_data_wire;
+      int_data_reg(1) <= int_data_reg(0);
+    end if;
+  end process;
+
+  m_axis_tdata <= int_data_reg(1);
+  m_axis_tvalid <= '1';
+
+end rtl;
diff --git a/cores/axis_gpio_reader_v1_0/core_config.tcl b/cores/axis_gpio_reader_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..968c5d347733e2e1f35e40ac4ebe46f8cc5ffd38
--- /dev/null
+++ b/cores/axis_gpio_reader_v1_0/core_config.tcl
@@ -0,0 +1,16 @@
+set display_name {AXI4-Stream GPIO Reader}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS $parameter
diff --git a/cores/axis_histogram_v1_0/axis_histogram.vhd b/cores/axis_histogram_v1_0/axis_histogram.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..ac29bcb3b2d8badb35f13be2ebc96f0938f3c8e7
--- /dev/null
+++ b/cores/axis_histogram_v1_0/axis_histogram.vhd
@@ -0,0 +1,124 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_histogram is
+  generic (
+            AXIS_TDATA_WIDTH: natural := 16;
+            BRAM_DATA_WIDTH : natural := 32;
+            BRAM_ADDR_WIDTH : natural := 14
+          );
+  port ( 
+         -- System signals
+         aclk              : in std_logic;
+         aresetn           : in std_logic;
+
+         -- Slave side
+         s_axis_tready     : out std_logic;
+         s_axis_tvalid     : in std_logic;
+         s_axis_tdata      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+         -- BRAM port
+         bram_porta_clk    : out std_logic;
+         bram_porta_rst    : out std_logic;
+         bram_porta_addr   : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+         bram_porta_wrdata : out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+         bram_porta_rddata : in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+         bram_porta_we     : out std_logic
+       );
+end axis_histogram;
+
+architecture rtl of axis_histogram is
+
+  type state_t is (
+  ST_IDLE, 
+  ST_WRITE_ZEROS, 
+  ST_READ_ADDR, 
+  ST_DELAY1, 
+  ST_INC_DATA, 
+  ST_DELAY2
+);
+signal state_reg, state_next : state_t;
+
+signal addr_reg, addr_next     : std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+signal data_reg, data_next     : std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+signal tready_reg, tready_next : std_logic;
+signal wren_reg, wren_next     : std_logic;
+signal wren_s                  : std_logic;
+
+begin
+
+  s_axis_tready     <= tready_reg;
+
+  bram_porta_clk    <= aclk;
+  bram_porta_rst    <= not aresetn;
+  bram_porta_addr   <= addr_reg when (wren_reg = '1') else 
+                       s_axis_tdata(BRAM_ADDR_WIDTH-1 downto 0);
+  bram_porta_wrdata <= data_reg;
+  bram_porta_we     <= wren_reg;
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn = '0') then
+        state_reg  <= ST_IDLE;
+        addr_reg   <= (others => '0');
+        data_reg   <= (others => '0');
+        tready_reg <= '0';
+        wren_reg   <= '0';
+      else
+        state_reg  <= state_next;
+        addr_reg   <= addr_next;
+        data_reg   <= data_next;
+        tready_reg <= tready_next;
+        wren_reg   <= wren_next;
+      end if;
+    end if;
+  end process;
+
+  wren_s <= '1' when (bram_porta_rddata = (bram_porta_rddata'range => '1')) else 
+            '0';
+
+  --Next state logic
+  process(state_reg, addr_reg, s_axis_tvalid)
+  begin
+    state_next  <= state_reg;  
+    addr_next   <= addr_reg;
+    data_next   <= data_reg;
+    tready_next <= tready_reg;
+    wren_next   <= wren_reg;
+
+    case state_reg is
+      when ST_IDLE =>
+        addr_next     <= (others => '0');
+        data_next     <= (others => '0');
+        wren_next     <= '1';
+        state_next    <= ST_WRITE_ZEROS;
+      when ST_WRITE_ZEROS =>
+        addr_next     <= std_logic_vector(unsigned(addr_reg) + 1);
+        if (addr_reg = (addr_reg'range => '1')) then
+          tready_next <= '1';
+          wren_next   <= '0';
+          state_next  <= ST_READ_ADDR;
+        end if;
+      when ST_READ_ADDR => 
+        if (s_axis_tvalid = '1') then
+          addr_next   <= s_axis_tdata(BRAM_ADDR_WIDTH-1 downto 0);
+          tready_next <= '0';
+          state_next  <= ST_DELAY1;
+        end if;
+      when ST_DELAY1 => 
+        state_next    <= ST_INC_DATA;
+      when ST_INC_DATA => 
+        data_next     <= std_logic_vector(unsigned(bram_porta_rddata) + 1);
+        wren_next     <= not wren_s; --(and bram_porta_rddata); 
+        state_next    <= ST_DELAY2;
+      when ST_DELAY2 => 
+        tready_next   <= '1';
+        wren_next     <= '0';
+        state_next    <= ST_READ_ADDR;
+    end case;
+  end process;
+
+end rtl;
diff --git a/cores/axis_histogram_v1_0/core_config.tcl b/cores/axis_histogram_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..0a3e5e684256be8a3d6c781cc687fb5b9a3d0a55
--- /dev/null
+++ b/cores/axis_histogram_v1_0/core_config.tcl
@@ -0,0 +1,37 @@
+set display_name {AXI4-Stream Histogram}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter BRAM_DATA_WIDTH {BRAM DATA WIDTH} {Width of the BRAM data port.}
+core_parameter BRAM_ADDR_WIDTH {BRAM ADDR WIDTH} {Width of the BRAM address port.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS $parameter
+
+set bus [ipx::add_bus_interface BRAM_PORTA $core]
+set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus
+set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus
+set_property INTERFACE_MODE master $bus
+foreach {logical physical} {
+  RST  bram_porta_rst
+  CLK  bram_porta_clk
+  ADDR bram_porta_addr
+  DIN  bram_porta_wrdata
+  DOUT bram_porta_rddata
+  WE   bram_porta_we
+} {
+  set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus]
+}
+
+set bus [ipx::get_bus_interfaces bram_porta_clk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE BRAM_PORTA $parameter
diff --git a/cores/axis_histogram_v1_1/axis_histogram.vhd b/cores/axis_histogram_v1_1/axis_histogram.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..922785db34c6120ef640f0705c9f338279ed5629
--- /dev/null
+++ b/cores/axis_histogram_v1_1/axis_histogram.vhd
@@ -0,0 +1,141 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_histogram is
+  generic (
+            AXIS_TDATA_WIDTH: natural := 16;
+            BRAM_DATA_WIDTH : natural := 32;
+            BRAM_ADDR_WIDTH : natural := 14;
+            CNTR_WIDTH      : natural := 32
+          );
+  port ( 
+         -- System signals
+         aclk              : in std_logic;
+         aresetn           : in std_logic;
+
+         cfg_data          : in std_logic_vector(CNTR_WIDTH-1 downto 0);
+         sts_data          : out std_logic_vector(CNTR_WIDTH-1 downto 0);
+         
+         -- Slave side
+         s_axis_tready     : out std_logic;
+         s_axis_tvalid     : in std_logic;
+         s_axis_tdata      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+         -- BRAM port
+         bram_porta_clk    : out std_logic;
+         bram_porta_rst    : out std_logic;
+         bram_porta_addr   : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+         bram_porta_wrdata : out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+         bram_porta_rddata : in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+         bram_porta_we     : out std_logic
+       );
+end axis_histogram;
+
+architecture rtl of axis_histogram is
+
+  type state_t is (
+  ST_IDLE, 
+  ST_WRITE_ZEROS, 
+  ST_READ_ADDR, 
+  ST_DELAY1, 
+  ST_INC_DATA, 
+  ST_DELAY2
+);
+signal state_reg, state_next : state_t;
+
+signal cntr_reg, cntr_next     : unsigned(CNTR_WIDTH-1 downto 0);
+signal comp_reg, comp_next     : std_logic;
+
+signal addr_reg, addr_next     : std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+signal data_reg, data_next     : std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+signal tready_reg, tready_next : std_logic;
+signal wren_reg, wren_next     : std_logic;
+signal wren_s                  : std_logic;
+
+begin
+
+  sts_data          <= std_logic_vector(cntr_reg);
+  s_axis_tready     <= tready_reg;
+
+  bram_porta_clk    <= aclk;
+  bram_porta_rst    <= not aresetn;
+  bram_porta_addr   <= addr_reg when (wren_reg = '1') else 
+                       s_axis_tdata(BRAM_ADDR_WIDTH-1 downto 0);
+  bram_porta_wrdata <= data_reg;
+  bram_porta_we     <= wren_reg;
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn = '0') then
+        state_reg  <= ST_IDLE;
+        comp_reg   <= '0';
+        cntr_reg   <= (others => '0');
+        addr_reg   <= (others => '0');
+        data_reg   <= (others => '0');
+        tready_reg <= '0';
+        wren_reg   <= '0';
+      else
+        state_reg  <= state_next;
+        comp_reg   <= comp_next;
+        cntr_reg   <= cntr_next;
+        addr_reg   <= addr_next;
+        data_reg   <= data_next;
+        tready_reg <= tready_next;
+        wren_reg   <= wren_next;
+      end if;
+    end if;
+  end process;
+
+  comp_next <= '0' when (cntr_reg = unsigned(cfg_data)-1) else '1';
+
+  cntr_next <= cntr_reg + 1 when ((comp_reg = '1') and (tready_reg = '1')) else
+               --(others => '0') when (comp_reg = '0') else --reset
+               cntr_reg;
+  wren_s <= '1' when (bram_porta_rddata = (bram_porta_rddata'range => '1')) else 
+            '0';
+
+  --Next state logic
+  process(state_reg, addr_reg, s_axis_tvalid, comp_reg)
+  begin
+    state_next  <= state_reg;  
+    addr_next   <= addr_reg;
+    data_next   <= data_reg;
+    tready_next <= tready_reg;
+    wren_next   <= wren_reg;
+
+    case state_reg is
+      when ST_IDLE =>
+        addr_next     <= (others => '0');
+        data_next     <= (others => '0');
+        wren_next     <= '1';
+        state_next    <= ST_WRITE_ZEROS;
+      when ST_WRITE_ZEROS =>
+        addr_next     <= std_logic_vector(unsigned(addr_reg) + 1);
+        if (addr_reg = (addr_reg'range => '1')) then
+          tready_next <= '1';
+          wren_next   <= '0';
+          state_next  <= ST_READ_ADDR;
+        end if;
+      when ST_READ_ADDR => 
+        if (s_axis_tvalid = '1') and (comp_reg = '1') then
+          addr_next   <= s_axis_tdata(BRAM_ADDR_WIDTH-1 downto 0);
+          tready_next <= '0';
+          state_next  <= ST_DELAY1;
+        end if;
+      when ST_DELAY1 => 
+        state_next    <= ST_INC_DATA;
+      when ST_INC_DATA => 
+        data_next     <= std_logic_vector(unsigned(bram_porta_rddata) + 1);
+        wren_next     <= not wren_s; --(and bram_porta_rddata); 
+        state_next    <= ST_DELAY2;
+      when ST_DELAY2 => 
+        tready_next   <= '1';
+        wren_next     <= '0';
+        state_next    <= ST_READ_ADDR;
+    end case;
+  end process;
+
+end rtl;
diff --git a/cores/axis_histogram_v1_1/core_config.tcl b/cores/axis_histogram_v1_1/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..82631de8decfa0947c08b1c32872753f846060e4
--- /dev/null
+++ b/cores/axis_histogram_v1_1/core_config.tcl
@@ -0,0 +1,37 @@
+set display_name {AXI4-Stream Histogram v1.1}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter BRAM_DATA_WIDTH {BRAM DATA WIDTH} {Width of the BRAM data port.}
+core_parameter BRAM_ADDR_WIDTH {BRAM ADDR WIDTH} {Width of the BRAM address port.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS $parameter
+
+set bus [ipx::add_bus_interface BRAM_PORTA $core]
+set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus
+set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus
+set_property INTERFACE_MODE master $bus
+foreach {logical physical} {
+  RST  bram_porta_rst
+  CLK  bram_porta_clk
+  ADDR bram_porta_addr
+  DIN  bram_porta_wrdata
+  DOUT bram_porta_rddata
+  WE   bram_porta_we
+} {
+  set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus]
+}
+
+set bus [ipx::get_bus_interfaces bram_porta_clk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE BRAM_PORTA $parameter
diff --git a/cores/axis_interpolator_v1_0/axis_interpolator.vhd b/cores/axis_interpolator_v1_0/axis_interpolator.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..1e0071705fc2e3e8fca7cafb2e435cb6fc1b6b2f
--- /dev/null
+++ b/cores/axis_interpolator_v1_0/axis_interpolator.vhd
@@ -0,0 +1,68 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_interpolator is
+  generic (
+    AXIS_TDATA_WIDTH : natural  := 32;
+    CNTR_WIDTH : natural  := 32
+);
+port (
+  -- System signals
+  aclk : in std_logic;
+  aresetn : in std_logic;
+
+  cfg_data : in std_logic_vector(CNTR_WIDTH-1 downto 0);
+
+  -- Slave side
+  s_axis_tready : out std_logic;
+  s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  s_axis_tvalid : in std_logic;
+
+  -- Master side
+  m_axis_tready : in std_logic;
+  m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  m_axis_tvalid : out std_logic
+);
+end axis_interpolator;
+
+architecture rtl of axis_interpolator is
+
+  signal int_tdata_reg, int_tdata_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal int_cntr_reg, int_cntr_next: unsigned(CNTR_WIDTH-1 downto 0);
+  signal int_tvalid_reg, int_tvalid_next: std_logic;
+
+begin
+
+  process(aclk)
+  begin
+  if (rising_edge(aclk)) then
+  if (aresetn = '0') then
+    int_tdata_reg <= (others => '0');
+    int_tvalid_reg <= '0';
+    int_cntr_reg <= (others => '0');
+  else
+    int_tdata_reg <= int_tdata_next;
+    int_tvalid_reg <= int_tvalid_next;
+    int_cntr_reg <= int_cntr_next;
+  end if;
+  end if;
+  end process;
+
+  int_tdata_next <= s_axis_tdata when (s_axis_tvalid = '1') and (int_tvalid_reg = '0') else
+                        int_tdata_reg;
+
+  int_cntr_next <= int_cntr_reg + 1 when (m_axis_tready = '1') and (int_tvalid_reg = '1') and (int_cntr_reg < unsigned(cfg_data)) else
+                   (others => '0') when (m_axis_tready = '1') and (int_tvalid_reg = '1') and not(int_cntr_reg < unsigned(cfg_data)) else
+                   int_cntr_reg;
+
+  int_tvalid_next <= '1' when (s_axis_tvalid = '1') and (int_tvalid_reg = '0') else
+                    '0' when (m_axis_tready = '1') and (int_tvalid_reg = '1') and not(int_cntr_reg < unsigned(cfg_data)) else
+                    int_tvalid_reg;
+
+  s_axis_tready <= not(int_tvalid_reg);
+  m_axis_tdata <= int_tdata_reg;
+  m_axis_tvalid <= int_tvalid_reg;
+
+end rtl;
diff --git a/cores/axis_interpolator_v1_0/core_config.tcl b/cores/axis_interpolator_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..ad5d2c102a179596d353de3c445cb2a03b41a918
--- /dev/null
+++ b/cores/axis_interpolator_v1_0/core_config.tcl
@@ -0,0 +1,21 @@
+set display_name {AXI4-Stream Interpolator}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS and S_AXIS data buses.}
+core_parameter CNTR_WIDTH {CNTR WIDTH} {Width of the counter register.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
diff --git a/cores/axis_lago_trigger_v1_0/axis_lago_trigger.vhd b/cores/axis_lago_trigger_v1_0/axis_lago_trigger.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..132f961a166ecad0a898331eba4bffa8527ee4bd
--- /dev/null
+++ b/cores/axis_lago_trigger_v1_0/axis_lago_trigger.vhd
@@ -0,0 +1,417 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_lago_trigger is
+  generic (
+  AXIS_TDATA_WIDTH      : natural  := 32;
+  -- data arrays bit numbers
+  ADC_DATA_WIDTH        : natural := 14;    
+  DATA_ARRAY_LENGTH     : natural := 20;
+  METADATA_ARRAY_LENGTH : natural := 10;
+  SUBTRIG_ARRAY_LENGTH  : natural := 3
+);
+port (
+  -- System signals
+  aclk               : in std_logic;
+  aresetn            : in std_logic;
+  trig_lvl_a_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  trig_lvl_b_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  subtrig_lvl_a_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  subtrig_lvl_b_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  pps_i              : in   std_logic;
+  clk_cnt_pps_i      : in std_logic_vector(27-1 downto 0);
+--  pwr_enA            : out  std_logic;
+--  data_out           : out  std_logic_vector(2**W-1 downto 0);
+--  pfifo_status       : in   std_logic_vector(2 downto 0);
+--  ptemperatura       : in   std_logic_vector(15 downto 0);
+--  ppresion           : in   std_logic_vector(15 downto 0);
+--  phora              : in   std_logic_vector(7 downto 0);
+--  pminutos           : in   std_logic_vector(7 downto 0);
+--  psegundos          : in   std_logic_vector(7 downto 0);
+--  latitude1_port     : in   std_logic_vector(7 downto 0);
+--  latitude2_port     : in   std_logic_vector(7 downto 0);
+--  latitude3_port     : in   std_logic_vector(7 downto 0);
+--  latitude4_port     : in   std_logic_vector(7 downto 0);
+--  longitude1_port    : in   std_logic_vector(7 downto 0);
+--  longitude2_port    : in   std_logic_vector(7 downto 0);
+--  longitude3_port    : in   std_logic_vector(7 downto 0);
+--  longitude4_port    : in   std_logic_vector(7 downto 0);
+--  ellipsoid1_port    : in   std_logic_vector(7 downto 0);
+--  ellipsoid2_port    : in   std_logic_vector(7 downto 0);
+--  ellipsoid3_port    : in   std_logic_vector(7 downto 0);
+--  ellipsoid4_port    : in   std_logic_vector(7 downto 0);
+--  num_vis_sat_port   : in   std_logic_vector(7 downto 0);
+--  num_track_sat_port : in   std_logic_vector(7 downto 0);
+--  rsf_port           : in   std_logic_vector(7 downto 0)
+
+  -- Slave side
+  s_axis_tready     : out std_logic;
+  s_axis_tdata      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  s_axis_tvalid     : in std_logic;
+
+  -- Master side
+  m_axis_tready     : in std_logic;
+  m_axis_tdata      : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  m_axis_tvalid     : out std_logic
+);
+end axis_lago_trigger;
+
+architecture rtl of axis_lago_trigger is
+
+  constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH;
+
+  --ADC related signals
+  type  adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t;
+  signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t;
+
+  type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal array_pps_reg, array_pps_next : array_pps_t;
+
+  type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal array_scalers_reg, array_scalers_next : array_scalers_t;
+
+  --Trigger related signals
+  --Triggers
+  signal tr1_s, tr2_s, tr_s              : std_logic; 
+  --Sub-Triggers
+  signal subtr1_s, subtr2_s, subtr_s     : std_logic; 
+
+  signal tr_status_reg, tr_status_next   : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+  signal trig_cnt_reg, trig_cnt_next     : std_logic_vector(30-1 downto 0); 
+
+  --Charge signals
+  signal charge1_reg, charge1_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+  signal charge2_reg, charge2_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+
+  --FSM signals
+  type state_t is (ST_IDLE,
+                      ST_ATT_TR,
+                      ST_SEND_TR_STATUS,
+                      ST_SEND_CNT_STATUS,
+                      ST_ATT_SUBTR,
+                      ST_ATT_PPS);
+  signal state_reg, state_next: state_t;
+
+  signal wr_count_reg, wr_count_next : unsigned(7 downto 0);
+  signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal status : std_logic_vector(2 downto 0);
+
+  signal axis_tready_reg, axis_tready_next : std_logic;
+  signal axis_tvalid_reg, axis_tvalid_next : std_logic;
+
+  signal trig_lvl_a, trig_lvl_b       : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_dat_a, adc_dat_b         : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+
+begin
+    
+  trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+  trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+  subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+  subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+  adc_dat_a <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0);
+  adc_dat_b <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto AXIS_TDATA_WIDTH/2);
+
+  -- data registers for a second
+  process(aclk)
+  begin
+    for i in METADATA_ARRAY_LENGTH-1 downto 0 loop
+      if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        array_pps_reg(i) <= (others => '0');
+      else
+        array_pps_reg(i) <= array_pps_next(i);
+      end if;
+      end if;
+    end loop;
+  end process;
+  --next state logic
+--  array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+--  array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+--  array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & ptemperatura when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+--  array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & ppresion when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+--  array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" & phora & pminutos & psegundos when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+--  array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" & latitude1_port & latitude2_port & latitude3_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+--  array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & longitude1_port & longitude2_port & latitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+--  array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & ellipsoid1_port & longitude3_port & longitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+--  array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & ellipsoid2_port & ellipsoid3_port & ellipsoid4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+--  array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & num_track_sat_port & num_vis_sat_port & rsf_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+
+  array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF"                                   when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+  array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i                   when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+  array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+  array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+  array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+  array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+  array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+  array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+  array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+  array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+------------------------------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------------------------------
+  --data acquisition for each channel
+  process(aclk)
+  begin
+    for i in (DATA_ARRAY_LENGTH-1) downto 0 loop
+      if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        adc_dat_a_reg(i) <= (others=>'0');
+        adc_dat_b_reg(i) <= (others=>'0');
+      else
+        adc_dat_a_reg(i) <= adc_dat_a_next(i);
+        adc_dat_b_reg(i) <= adc_dat_b_next(i);
+      end if;
+      end if;
+      -- next state logic
+      if (i = (DATA_ARRAY_LENGTH-1)) then
+        adc_dat_a_next(i) <= adc_dat_a;
+        adc_dat_b_next(i) <= adc_dat_b;
+      else
+        adc_dat_a_next(i) <= adc_dat_a_reg(i+1);
+        adc_dat_b_next(i) <= adc_dat_b_reg(i+1);
+      end if;
+    end loop;
+  end process;
+
+-----------------------------------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------------------------------
+  --trigger
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      tr_status_reg  <= (others => '0');
+      cnt_status_reg <= (others => '0');
+      trig_cnt_reg   <= (others => '0');
+    else
+      tr_status_reg  <= tr_status_next;
+      cnt_status_reg <= cnt_status_next;
+      trig_cnt_reg   <= trig_cnt_next;
+    end if;
+    end if;
+  end process;
+  
+
+  -- The trigger is at  bin 4 because we loose a clock pulse in the state machine
+  -- next state logic
+  tr1_s <=  '1' when ((adc_dat_a_reg(3)(adc_dat_a_reg(3)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+                      (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (unsigned(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+            '0';
+  tr2_s <=  '1' when ((adc_dat_b_reg(3)(adc_dat_b_reg(3)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+                      (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (unsigned(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+            '0';
+
+  tr_s <= '1' when  ((tr1_s = '1') or (tr2_s = '1')) else '0';
+
+  tr_status_next <=   "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else
+                      tr_status_reg;
+  cnt_status_next <=  "10" & trig_cnt_reg when (tr_s = '1') else
+                      cnt_status_reg;
+
+  trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else
+                   trig_cnt_reg;
+
+----------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------
+  --sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      charge1_reg <= (others => '0');
+      charge2_reg <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0');
+    else
+      charge1_reg <= charge1_next;
+      charge2_reg <= charge2_next;
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1);
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2);
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3);
+    end if;
+    end if;
+  end process;
+  -- next state logic
+  subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and 
+                      unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+                      (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+                      (adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+                      unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+                    '0';
+  subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and
+                      unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+                      (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+                      (adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+                      unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+                    '0';
+  subtr_s <=  '1' when  ((subtr1_s = '1') or (subtr2_s = '1')) else '0';
+
+  charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right;
+  charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right;
+
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1);
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too
+
+----------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------
+  -- FSM controlling all
+  --================================================================
+  -- state and data registers
+  --================================================================
+  process (aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      state_reg      <= ST_IDLE;
+      wr_count_reg   <= (others => '0');
+      data_to_fifo_reg <= (others => '0');
+      axis_tvalid_reg <= '0';
+      axis_tready_reg <= '0';
+    else
+      state_reg      <= state_next;
+      wr_count_reg   <= wr_count_next;
+      data_to_fifo_reg <= data_to_fifo_next;
+      axis_tvalid_reg <= axis_tvalid_next;
+      axis_tready_reg <= axis_tready_next;
+    end if;
+    end if;
+  end process;
+  --=================================================================
+  --next-state logic & data path functional units/routing
+  --=================================================================
+  process(state_reg, status, wr_count_reg)
+  begin
+    state_next        <= state_reg;         -- default 
+    wr_count_next     <= (others => '0'); -- wr_count_reg;
+    data_to_fifo_next <= data_to_fifo_reg;  -- default 
+    axis_tvalid_next  <= '0';               -- default disable write
+    axis_tready_next  <= '1';               -- always ready
+    case state_reg is
+      when ST_IDLE =>
+        if (m_axis_tready = '1') then
+          case status is
+            when "001" | "011" | "101" | "111" => -- priority is for PPS data every second
+              state_next <= ST_ATT_PPS;
+            when "100" | "110" =>
+              state_next <= ST_ATT_TR;
+            when "010" =>
+              state_next <= ST_ATT_SUBTR;
+            when others => --"000"
+              state_next <= ST_IDLE;
+          end case;
+        else
+          state_next <= ST_IDLE;
+        end if;
+
+      --we send adc data because we have a trigger
+      when ST_ATT_TR =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          --data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0));
+          data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0);
+          --data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg);
+          if (wr_count_reg = DATA_ARRAY_LENGTH-1) then
+            state_next <= ST_SEND_TR_STATUS;
+          else
+            state_next <= ST_ATT_TR;
+          end if;
+        else
+          state_next <= ST_ATT_TR;
+        end if;
+
+      when ST_SEND_TR_STATUS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          data_to_fifo_next <= tr_status_reg;
+          --data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30));
+          state_next <= ST_SEND_CNT_STATUS;
+        else
+          state_next <= ST_SEND_TR_STATUS;
+        end if;
+
+      when ST_SEND_CNT_STATUS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          data_to_fifo_next <= cnt_status_reg;
+          --data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30));
+          state_next <= ST_IDLE;
+        else
+          state_next <= ST_SEND_CNT_STATUS;
+        end if;
+
+      when ST_ATT_SUBTR =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg));
+          if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then
+            state_next <= ST_IDLE;
+          else 
+            state_next <= ST_ATT_SUBTR;
+          end if;
+        else
+          state_next <= ST_ATT_SUBTR;
+        end if;
+
+      when ST_ATT_PPS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg));
+          if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then
+            state_next <= ST_IDLE;
+          else
+            state_next <= ST_ATT_PPS;
+          end if;
+        else
+          state_next <= ST_ATT_PPS;
+        end if;
+   end case;
+  end process;
+
+  status <= tr_s & subtr_s & pps_i;
+  s_axis_tready <= axis_tready_reg;
+  m_axis_tdata <= data_to_fifo_reg;
+  m_axis_tvalid <= axis_tvalid_reg;
+
+end architecture rtl;
+
diff --git a/cores/axis_lago_trigger_v1_0/axis_lago_trigger_v1_0.vhd b/cores/axis_lago_trigger_v1_0/axis_lago_trigger_v1_0.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..132f961a166ecad0a898331eba4bffa8527ee4bd
--- /dev/null
+++ b/cores/axis_lago_trigger_v1_0/axis_lago_trigger_v1_0.vhd
@@ -0,0 +1,417 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_lago_trigger is
+  generic (
+  AXIS_TDATA_WIDTH      : natural  := 32;
+  -- data arrays bit numbers
+  ADC_DATA_WIDTH        : natural := 14;    
+  DATA_ARRAY_LENGTH     : natural := 20;
+  METADATA_ARRAY_LENGTH : natural := 10;
+  SUBTRIG_ARRAY_LENGTH  : natural := 3
+);
+port (
+  -- System signals
+  aclk               : in std_logic;
+  aresetn            : in std_logic;
+  trig_lvl_a_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  trig_lvl_b_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  subtrig_lvl_a_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  subtrig_lvl_b_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  pps_i              : in   std_logic;
+  clk_cnt_pps_i      : in std_logic_vector(27-1 downto 0);
+--  pwr_enA            : out  std_logic;
+--  data_out           : out  std_logic_vector(2**W-1 downto 0);
+--  pfifo_status       : in   std_logic_vector(2 downto 0);
+--  ptemperatura       : in   std_logic_vector(15 downto 0);
+--  ppresion           : in   std_logic_vector(15 downto 0);
+--  phora              : in   std_logic_vector(7 downto 0);
+--  pminutos           : in   std_logic_vector(7 downto 0);
+--  psegundos          : in   std_logic_vector(7 downto 0);
+--  latitude1_port     : in   std_logic_vector(7 downto 0);
+--  latitude2_port     : in   std_logic_vector(7 downto 0);
+--  latitude3_port     : in   std_logic_vector(7 downto 0);
+--  latitude4_port     : in   std_logic_vector(7 downto 0);
+--  longitude1_port    : in   std_logic_vector(7 downto 0);
+--  longitude2_port    : in   std_logic_vector(7 downto 0);
+--  longitude3_port    : in   std_logic_vector(7 downto 0);
+--  longitude4_port    : in   std_logic_vector(7 downto 0);
+--  ellipsoid1_port    : in   std_logic_vector(7 downto 0);
+--  ellipsoid2_port    : in   std_logic_vector(7 downto 0);
+--  ellipsoid3_port    : in   std_logic_vector(7 downto 0);
+--  ellipsoid4_port    : in   std_logic_vector(7 downto 0);
+--  num_vis_sat_port   : in   std_logic_vector(7 downto 0);
+--  num_track_sat_port : in   std_logic_vector(7 downto 0);
+--  rsf_port           : in   std_logic_vector(7 downto 0)
+
+  -- Slave side
+  s_axis_tready     : out std_logic;
+  s_axis_tdata      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  s_axis_tvalid     : in std_logic;
+
+  -- Master side
+  m_axis_tready     : in std_logic;
+  m_axis_tdata      : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  m_axis_tvalid     : out std_logic
+);
+end axis_lago_trigger;
+
+architecture rtl of axis_lago_trigger is
+
+  constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH;
+
+  --ADC related signals
+  type  adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t;
+  signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t;
+
+  type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal array_pps_reg, array_pps_next : array_pps_t;
+
+  type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal array_scalers_reg, array_scalers_next : array_scalers_t;
+
+  --Trigger related signals
+  --Triggers
+  signal tr1_s, tr2_s, tr_s              : std_logic; 
+  --Sub-Triggers
+  signal subtr1_s, subtr2_s, subtr_s     : std_logic; 
+
+  signal tr_status_reg, tr_status_next   : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+  signal trig_cnt_reg, trig_cnt_next     : std_logic_vector(30-1 downto 0); 
+
+  --Charge signals
+  signal charge1_reg, charge1_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+  signal charge2_reg, charge2_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+
+  --FSM signals
+  type state_t is (ST_IDLE,
+                      ST_ATT_TR,
+                      ST_SEND_TR_STATUS,
+                      ST_SEND_CNT_STATUS,
+                      ST_ATT_SUBTR,
+                      ST_ATT_PPS);
+  signal state_reg, state_next: state_t;
+
+  signal wr_count_reg, wr_count_next : unsigned(7 downto 0);
+  signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal status : std_logic_vector(2 downto 0);
+
+  signal axis_tready_reg, axis_tready_next : std_logic;
+  signal axis_tvalid_reg, axis_tvalid_next : std_logic;
+
+  signal trig_lvl_a, trig_lvl_b       : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_dat_a, adc_dat_b         : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+
+begin
+    
+  trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+  trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+  subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+  subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+  adc_dat_a <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0);
+  adc_dat_b <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto AXIS_TDATA_WIDTH/2);
+
+  -- data registers for a second
+  process(aclk)
+  begin
+    for i in METADATA_ARRAY_LENGTH-1 downto 0 loop
+      if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        array_pps_reg(i) <= (others => '0');
+      else
+        array_pps_reg(i) <= array_pps_next(i);
+      end if;
+      end if;
+    end loop;
+  end process;
+  --next state logic
+--  array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+--  array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+--  array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & ptemperatura when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+--  array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & ppresion when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+--  array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" & phora & pminutos & psegundos when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+--  array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" & latitude1_port & latitude2_port & latitude3_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+--  array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & longitude1_port & longitude2_port & latitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+--  array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & ellipsoid1_port & longitude3_port & longitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+--  array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & ellipsoid2_port & ellipsoid3_port & ellipsoid4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+--  array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & num_track_sat_port & num_vis_sat_port & rsf_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+
+  array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF"                                   when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+  array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i                   when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+  array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+  array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+  array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+  array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+  array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+  array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+  array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+  array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+------------------------------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------------------------------
+  --data acquisition for each channel
+  process(aclk)
+  begin
+    for i in (DATA_ARRAY_LENGTH-1) downto 0 loop
+      if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        adc_dat_a_reg(i) <= (others=>'0');
+        adc_dat_b_reg(i) <= (others=>'0');
+      else
+        adc_dat_a_reg(i) <= adc_dat_a_next(i);
+        adc_dat_b_reg(i) <= adc_dat_b_next(i);
+      end if;
+      end if;
+      -- next state logic
+      if (i = (DATA_ARRAY_LENGTH-1)) then
+        adc_dat_a_next(i) <= adc_dat_a;
+        adc_dat_b_next(i) <= adc_dat_b;
+      else
+        adc_dat_a_next(i) <= adc_dat_a_reg(i+1);
+        adc_dat_b_next(i) <= adc_dat_b_reg(i+1);
+      end if;
+    end loop;
+  end process;
+
+-----------------------------------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------------------------------
+  --trigger
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      tr_status_reg  <= (others => '0');
+      cnt_status_reg <= (others => '0');
+      trig_cnt_reg   <= (others => '0');
+    else
+      tr_status_reg  <= tr_status_next;
+      cnt_status_reg <= cnt_status_next;
+      trig_cnt_reg   <= trig_cnt_next;
+    end if;
+    end if;
+  end process;
+  
+
+  -- The trigger is at  bin 4 because we loose a clock pulse in the state machine
+  -- next state logic
+  tr1_s <=  '1' when ((adc_dat_a_reg(3)(adc_dat_a_reg(3)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+                      (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (unsigned(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+            '0';
+  tr2_s <=  '1' when ((adc_dat_b_reg(3)(adc_dat_b_reg(3)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+                      (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (unsigned(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+            '0';
+
+  tr_s <= '1' when  ((tr1_s = '1') or (tr2_s = '1')) else '0';
+
+  tr_status_next <=   "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else
+                      tr_status_reg;
+  cnt_status_next <=  "10" & trig_cnt_reg when (tr_s = '1') else
+                      cnt_status_reg;
+
+  trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else
+                   trig_cnt_reg;
+
+----------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------
+  --sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      charge1_reg <= (others => '0');
+      charge2_reg <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0');
+    else
+      charge1_reg <= charge1_next;
+      charge2_reg <= charge2_next;
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1);
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2);
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3);
+    end if;
+    end if;
+  end process;
+  -- next state logic
+  subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and 
+                      unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+                      (unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+                      (adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+                      unsigned(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+                    '0';
+  subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and
+                      unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= unsigned(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+                      (unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+                      (adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+                      unsigned(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      unsigned(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < unsigned(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+                    '0';
+  subtr_s <=  '1' when  ((subtr1_s = '1') or (subtr2_s = '1')) else '0';
+
+  charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right;
+  charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right;
+
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1);
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too
+
+----------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------
+  -- FSM controlling all
+  --================================================================
+  -- state and data registers
+  --================================================================
+  process (aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      state_reg      <= ST_IDLE;
+      wr_count_reg   <= (others => '0');
+      data_to_fifo_reg <= (others => '0');
+      axis_tvalid_reg <= '0';
+      axis_tready_reg <= '0';
+    else
+      state_reg      <= state_next;
+      wr_count_reg   <= wr_count_next;
+      data_to_fifo_reg <= data_to_fifo_next;
+      axis_tvalid_reg <= axis_tvalid_next;
+      axis_tready_reg <= axis_tready_next;
+    end if;
+    end if;
+  end process;
+  --=================================================================
+  --next-state logic & data path functional units/routing
+  --=================================================================
+  process(state_reg, status, wr_count_reg)
+  begin
+    state_next        <= state_reg;         -- default 
+    wr_count_next     <= (others => '0'); -- wr_count_reg;
+    data_to_fifo_next <= data_to_fifo_reg;  -- default 
+    axis_tvalid_next  <= '0';               -- default disable write
+    axis_tready_next  <= '1';               -- always ready
+    case state_reg is
+      when ST_IDLE =>
+        if (m_axis_tready = '1') then
+          case status is
+            when "001" | "011" | "101" | "111" => -- priority is for PPS data every second
+              state_next <= ST_ATT_PPS;
+            when "100" | "110" =>
+              state_next <= ST_ATT_TR;
+            when "010" =>
+              state_next <= ST_ATT_SUBTR;
+            when others => --"000"
+              state_next <= ST_IDLE;
+          end case;
+        else
+          state_next <= ST_IDLE;
+        end if;
+
+      --we send adc data because we have a trigger
+      when ST_ATT_TR =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          --data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0));
+          data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0);
+          --data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg);
+          if (wr_count_reg = DATA_ARRAY_LENGTH-1) then
+            state_next <= ST_SEND_TR_STATUS;
+          else
+            state_next <= ST_ATT_TR;
+          end if;
+        else
+          state_next <= ST_ATT_TR;
+        end if;
+
+      when ST_SEND_TR_STATUS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          data_to_fifo_next <= tr_status_reg;
+          --data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30));
+          state_next <= ST_SEND_CNT_STATUS;
+        else
+          state_next <= ST_SEND_TR_STATUS;
+        end if;
+
+      when ST_SEND_CNT_STATUS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          data_to_fifo_next <= cnt_status_reg;
+          --data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30));
+          state_next <= ST_IDLE;
+        else
+          state_next <= ST_SEND_CNT_STATUS;
+        end if;
+
+      when ST_ATT_SUBTR =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg));
+          if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then
+            state_next <= ST_IDLE;
+          else 
+            state_next <= ST_ATT_SUBTR;
+          end if;
+        else
+          state_next <= ST_ATT_SUBTR;
+        end if;
+
+      when ST_ATT_PPS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg));
+          if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then
+            state_next <= ST_IDLE;
+          else
+            state_next <= ST_ATT_PPS;
+          end if;
+        else
+          state_next <= ST_ATT_PPS;
+        end if;
+   end case;
+  end process;
+
+  status <= tr_s & subtr_s & pps_i;
+  s_axis_tready <= axis_tready_reg;
+  m_axis_tdata <= data_to_fifo_reg;
+  m_axis_tvalid <= axis_tvalid_reg;
+
+end architecture rtl;
+
diff --git a/cores/axis_lago_trigger_v1_0/core_config.tcl b/cores/axis_lago_trigger_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..d7a1051f6b65a754c4d2de8e1cda01cc94f2f7c5
--- /dev/null
+++ b/cores/axis_lago_trigger_v1_0/core_config.tcl
@@ -0,0 +1,25 @@
+set display_name {AXI4-Stream LAGO Trigger v1r0}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter ADC_DATA_WIDTH {ADC_DATA_WIDTH} {Number of ADC data bits.}
+core_parameter DATA_ARRAY_LENGTH {DATA_ARRAY_LENGTH} {Length of the data array.}
+core_parameter METADATA_ARRAY_LENGTH {METADATA_ARRAY_LENGTH} {Length of the metadata array.}
+core_parameter SUBTRIG_ARRAY_LENGTH {SUBTRIG_ARRAY_LENGTH} {Length of the sub-trigger array.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
+
diff --git a/cores/axis_lago_trigger_v1_1/axis_lago_trigger.vhd b/cores/axis_lago_trigger_v1_1/axis_lago_trigger.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..8d357e189de86b9111e51ba258a72f7521e7b2a0
--- /dev/null
+++ b/cores/axis_lago_trigger_v1_1/axis_lago_trigger.vhd
@@ -0,0 +1,413 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_lago_trigger is
+  generic (
+  AXIS_TDATA_WIDTH      : natural  := 32;
+  -- data arrays bit numbers
+  ADC_DATA_WIDTH        : natural := 14;    
+  DATA_ARRAY_LENGTH     : natural := 20;
+  METADATA_ARRAY_LENGTH : natural := 10;
+  SUBTRIG_ARRAY_LENGTH  : natural := 3
+);
+port (
+  -- System signals
+  aclk               : in std_logic;
+  aresetn            : in std_logic;
+  trig_lvl_a_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  trig_lvl_b_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  subtrig_lvl_a_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  subtrig_lvl_b_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  pps_i              : in std_logic;
+  clk_cnt_pps_i      : in std_logic_vector(27-1 downto 0);
+  temp_i             : in std_logic_vector(24-1 downto 0);
+  pressure_i         : in std_logic_vector(24-1 downto 0);
+  time_i             : in std_logic_vector(24-1 downto 0);
+  date_i             : in std_logic_vector(24-1 downto 0);
+  latitude_i         : in std_logic_vector(24-1 downto 0);
+  longitude_i        : in std_logic_vector(24-1 downto 0);
+  altitude_i         : in std_logic_vector(24-1 downto 0);
+  satellites_i       : in std_logic_vector(24-1 downto 0);
+
+  -- Slave side
+  s_axis_tready     : out std_logic;
+  s_axis_tdata      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  s_axis_tvalid     : in std_logic;
+
+  -- Master side
+  m_axis_tready     : in std_logic;
+  m_axis_tdata      : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  m_axis_tvalid     : out std_logic
+);
+end axis_lago_trigger;
+
+architecture rtl of axis_lago_trigger is
+
+  constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH;
+
+  --ADC related signals
+  type  adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t;
+  signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t;
+
+  type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal array_pps_reg, array_pps_next : array_pps_t;
+
+  type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal array_scalers_reg, array_scalers_next : array_scalers_t;
+
+  --Trigger related signals
+  --Triggers
+  signal tr1_s, tr2_s, tr_s              : std_logic; 
+  --Sub-Triggers
+  signal subtr1_s, subtr2_s, subtr_s     : std_logic; 
+
+  signal tr_status_reg, tr_status_next   : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+  signal trig_cnt_reg, trig_cnt_next     : std_logic_vector(30-1 downto 0); 
+
+  --Charge signals
+  signal charge1_reg, charge1_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+  signal charge2_reg, charge2_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+
+  --FSM signals
+  type state_t is (ST_IDLE,
+                      ST_ATT_TR,
+                      ST_SEND_TR_STATUS,
+                      ST_SEND_CNT_STATUS,
+                      ST_ATT_SUBTR,
+                      ST_ATT_PPS);
+  signal state_reg, state_next: state_t;
+
+  signal wr_count_reg, wr_count_next : unsigned(7 downto 0);
+  signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal status : std_logic_vector(2 downto 0);
+
+  signal axis_tready_reg, axis_tready_next : std_logic;
+  signal axis_tvalid_reg, axis_tvalid_next : std_logic;
+
+  signal trig_lvl_a, trig_lvl_b       : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_dat_a, adc_dat_b         : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+
+begin
+    
+  trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+  trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+  subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+  subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+  adc_dat_a <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0);
+  adc_dat_b <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto AXIS_TDATA_WIDTH/2);
+
+  -- data registers for a second
+  process(aclk)
+  begin
+    for i in METADATA_ARRAY_LENGTH-1 downto 0 loop
+      if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        array_pps_reg(i) <= (others => '0');
+      else
+        array_pps_reg(i) <= array_pps_next(i);
+      end if;
+      end if;
+    end loop;
+  end process;
+  --next state logic
+--  array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+--  array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+--  array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & ptemperatura when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+--  array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & ppresion when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+--  array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" & phora & pminutos & psegundos when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+--  array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" & latitude1_port & latitude2_port & latitude3_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+--  array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & longitude1_port & longitude2_port & latitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+--  array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & ellipsoid1_port & longitude3_port & longitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+--  array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & ellipsoid2_port & ellipsoid3_port & ellipsoid4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+--  array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & num_track_sat_port & num_vis_sat_port & rsf_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+
+  array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF"                              when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+  array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i              when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+  array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "000" &  temp_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+  array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "000" &  pressure_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+  array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" &  time_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+  array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" &  latitude_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+  array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" &  longitude_i       when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+  array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" &  altitude_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+  array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" &  date_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+  array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" &  satellites_i      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+
+--  array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF"                                   when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+--  array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i                   when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+--  array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+--  array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+--  array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+--  array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+--  array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+--  array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+--  array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+--  array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+------------------------------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------------------------------
+  --data acquisition for each channel
+  process(aclk)
+  begin
+    for i in (DATA_ARRAY_LENGTH-1) downto 0 loop
+      if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        adc_dat_a_reg(i) <= (others=>'0');
+        adc_dat_b_reg(i) <= (others=>'0');
+      else
+        adc_dat_a_reg(i) <= adc_dat_a_next(i);
+        adc_dat_b_reg(i) <= adc_dat_b_next(i);
+      end if;
+      end if;
+      -- next state logic
+      if (i = (DATA_ARRAY_LENGTH-1)) then
+        adc_dat_a_next(i) <= adc_dat_a;
+        adc_dat_b_next(i) <= adc_dat_b;
+      else
+        adc_dat_a_next(i) <= adc_dat_a_reg(i+1);
+        adc_dat_b_next(i) <= adc_dat_b_reg(i+1);
+      end if;
+    end loop;
+  end process;
+
+-----------------------------------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------------------------------
+  --trigger
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      tr_status_reg  <= (others => '0');
+      cnt_status_reg <= (others => '0');
+      trig_cnt_reg   <= (others => '0');
+    else
+      tr_status_reg  <= tr_status_next;
+      cnt_status_reg <= cnt_status_next;
+      trig_cnt_reg   <= trig_cnt_next;
+    end if;
+    end if;
+  end process;
+  
+
+  -- The trigger is at  bin 4 because we loose a clock pulse in the state machine
+  -- next state logic
+  tr1_s <=  '1' when ((adc_dat_a_reg(3)(adc_dat_a_reg(3)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+                      (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+            '0';
+  tr2_s <=  '1' when ((adc_dat_b_reg(3)(adc_dat_b_reg(3)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+                      (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+            '0';
+
+  tr_s <= '1' when  ((tr1_s = '1') or (tr2_s = '1')) else '0';
+
+  tr_status_next <=   "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else
+                      tr_status_reg;
+  cnt_status_next <=  "10" & trig_cnt_reg when (tr_s = '1') else
+                      cnt_status_reg;
+
+  trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else
+                   trig_cnt_reg;
+
+----------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------
+  --sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      charge1_reg <= (others => '0');
+      charge2_reg <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0');
+    else
+      charge1_reg <= charge1_next;
+      charge2_reg <= charge2_next;
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1);
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2);
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3);
+    end if;
+    end if;
+  end process;
+  -- next state logic
+  subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and 
+                      signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+                      (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+                      (adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+                      signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+                    '0';
+  subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and
+                      signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+                      (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+                      (adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+                      signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+                    '0';
+  subtr_s <=  '1' when  ((subtr1_s = '1') or (subtr2_s = '1')) else '0';
+
+  charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right;
+  charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right;
+
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1);
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too
+
+----------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------
+  -- FSM controlling all
+  --================================================================
+  -- state and data registers
+  --================================================================
+  process (aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      state_reg      <= ST_IDLE;
+      wr_count_reg   <= (others => '0');
+      data_to_fifo_reg <= (others => '0');
+      axis_tvalid_reg <= '0';
+      axis_tready_reg <= '0';
+    else
+      state_reg      <= state_next;
+      wr_count_reg   <= wr_count_next;
+      data_to_fifo_reg <= data_to_fifo_next;
+      axis_tvalid_reg <= axis_tvalid_next;
+      axis_tready_reg <= axis_tready_next;
+    end if;
+    end if;
+  end process;
+  --=================================================================
+  --next-state logic & data path functional units/routing
+  --=================================================================
+  process(state_reg, status, wr_count_reg)
+  begin
+    state_next        <= state_reg;         -- default 
+    wr_count_next     <= (others => '0'); -- wr_count_reg;
+    data_to_fifo_next <= data_to_fifo_reg;  -- default 
+    axis_tvalid_next  <= '0';               -- default disable write
+    axis_tready_next  <= '1';               -- always ready
+    case state_reg is
+      when ST_IDLE =>
+        if (m_axis_tready = '1') then
+          case status is
+            when "001" | "011" | "101" | "111" => -- priority is for PPS data every second
+              state_next <= ST_ATT_PPS;
+            when "100" | "110" =>
+              state_next <= ST_ATT_TR;
+            when "010" =>
+              state_next <= ST_ATT_SUBTR;
+            when others => --"000"
+              state_next <= ST_IDLE;
+          end case;
+        else
+          state_next <= ST_IDLE;
+        end if;
+
+      --we send adc data because we have a trigger
+      when ST_ATT_TR =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          --data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0));
+          data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0);
+          --data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg);
+          if (wr_count_reg = DATA_ARRAY_LENGTH-1) then
+            state_next <= ST_SEND_TR_STATUS;
+          else
+            state_next <= ST_ATT_TR;
+          end if;
+        else
+          state_next <= ST_ATT_TR;
+        end if;
+
+      when ST_SEND_TR_STATUS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          data_to_fifo_next <= tr_status_reg;
+          --data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30));
+          state_next <= ST_SEND_CNT_STATUS;
+        else
+          state_next <= ST_SEND_TR_STATUS;
+        end if;
+
+      when ST_SEND_CNT_STATUS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          data_to_fifo_next <= cnt_status_reg;
+          --data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30));
+          state_next <= ST_IDLE;
+        else
+          state_next <= ST_SEND_CNT_STATUS;
+        end if;
+
+      when ST_ATT_SUBTR =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg));
+          if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then
+            state_next <= ST_IDLE;
+          else 
+            state_next <= ST_ATT_SUBTR;
+          end if;
+        else
+          state_next <= ST_ATT_SUBTR;
+        end if;
+
+      when ST_ATT_PPS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg));
+          if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then
+            state_next <= ST_IDLE;
+          else
+            state_next <= ST_ATT_PPS;
+          end if;
+        else
+          state_next <= ST_ATT_PPS;
+        end if;
+   end case;
+  end process;
+
+  status <= tr_s & subtr_s & pps_i;
+  s_axis_tready <= axis_tready_reg;
+  m_axis_tdata <= data_to_fifo_reg;
+  m_axis_tvalid <= axis_tvalid_reg;
+
+end architecture rtl;
+
diff --git a/cores/axis_lago_trigger_v1_1/axis_lago_trigger_v1_1.vhd b/cores/axis_lago_trigger_v1_1/axis_lago_trigger_v1_1.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..8d357e189de86b9111e51ba258a72f7521e7b2a0
--- /dev/null
+++ b/cores/axis_lago_trigger_v1_1/axis_lago_trigger_v1_1.vhd
@@ -0,0 +1,413 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_lago_trigger is
+  generic (
+  AXIS_TDATA_WIDTH      : natural  := 32;
+  -- data arrays bit numbers
+  ADC_DATA_WIDTH        : natural := 14;    
+  DATA_ARRAY_LENGTH     : natural := 20;
+  METADATA_ARRAY_LENGTH : natural := 10;
+  SUBTRIG_ARRAY_LENGTH  : natural := 3
+);
+port (
+  -- System signals
+  aclk               : in std_logic;
+  aresetn            : in std_logic;
+  trig_lvl_a_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  trig_lvl_b_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  subtrig_lvl_a_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  subtrig_lvl_b_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  pps_i              : in std_logic;
+  clk_cnt_pps_i      : in std_logic_vector(27-1 downto 0);
+  temp_i             : in std_logic_vector(24-1 downto 0);
+  pressure_i         : in std_logic_vector(24-1 downto 0);
+  time_i             : in std_logic_vector(24-1 downto 0);
+  date_i             : in std_logic_vector(24-1 downto 0);
+  latitude_i         : in std_logic_vector(24-1 downto 0);
+  longitude_i        : in std_logic_vector(24-1 downto 0);
+  altitude_i         : in std_logic_vector(24-1 downto 0);
+  satellites_i       : in std_logic_vector(24-1 downto 0);
+
+  -- Slave side
+  s_axis_tready     : out std_logic;
+  s_axis_tdata      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  s_axis_tvalid     : in std_logic;
+
+  -- Master side
+  m_axis_tready     : in std_logic;
+  m_axis_tdata      : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  m_axis_tvalid     : out std_logic
+);
+end axis_lago_trigger;
+
+architecture rtl of axis_lago_trigger is
+
+  constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH;
+
+  --ADC related signals
+  type  adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t;
+  signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t;
+
+  type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal array_pps_reg, array_pps_next : array_pps_t;
+
+  type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal array_scalers_reg, array_scalers_next : array_scalers_t;
+
+  --Trigger related signals
+  --Triggers
+  signal tr1_s, tr2_s, tr_s              : std_logic; 
+  --Sub-Triggers
+  signal subtr1_s, subtr2_s, subtr_s     : std_logic; 
+
+  signal tr_status_reg, tr_status_next   : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+  signal trig_cnt_reg, trig_cnt_next     : std_logic_vector(30-1 downto 0); 
+
+  --Charge signals
+  signal charge1_reg, charge1_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+  signal charge2_reg, charge2_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+
+  --FSM signals
+  type state_t is (ST_IDLE,
+                      ST_ATT_TR,
+                      ST_SEND_TR_STATUS,
+                      ST_SEND_CNT_STATUS,
+                      ST_ATT_SUBTR,
+                      ST_ATT_PPS);
+  signal state_reg, state_next: state_t;
+
+  signal wr_count_reg, wr_count_next : unsigned(7 downto 0);
+  signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal status : std_logic_vector(2 downto 0);
+
+  signal axis_tready_reg, axis_tready_next : std_logic;
+  signal axis_tvalid_reg, axis_tvalid_next : std_logic;
+
+  signal trig_lvl_a, trig_lvl_b       : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_dat_a, adc_dat_b         : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+
+begin
+    
+  trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+  trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+  subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+  subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+  adc_dat_a <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0);
+  adc_dat_b <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto AXIS_TDATA_WIDTH/2);
+
+  -- data registers for a second
+  process(aclk)
+  begin
+    for i in METADATA_ARRAY_LENGTH-1 downto 0 loop
+      if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        array_pps_reg(i) <= (others => '0');
+      else
+        array_pps_reg(i) <= array_pps_next(i);
+      end if;
+      end if;
+    end loop;
+  end process;
+  --next state logic
+--  array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF" when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+--  array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+--  array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & ptemperatura when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+--  array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & ppresion when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+--  array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" & phora & pminutos & psegundos when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+--  array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" & latitude1_port & latitude2_port & latitude3_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+--  array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & longitude1_port & longitude2_port & latitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+--  array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & ellipsoid1_port & longitude3_port & longitude4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+--  array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & ellipsoid2_port & ellipsoid3_port & ellipsoid4_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+--  array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & num_track_sat_port & num_vis_sat_port & rsf_port when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+
+  array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF"                              when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+  array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i              when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+  array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "000" &  temp_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+  array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "000" &  pressure_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+  array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "000" &  time_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+  array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "000" &  latitude_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+  array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" &  longitude_i       when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+  array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" &  altitude_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+  array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" &  date_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+  array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" &  satellites_i      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+
+--  array_pps_next(METADATA_ARRAY_LENGTH-10)<= x"FFFFFFFF"                                   when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+--  array_pps_next(METADATA_ARRAY_LENGTH-9)<= "11" & "000" & clk_cnt_pps_i                   when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+--  array_pps_next(METADATA_ARRAY_LENGTH-8)<= "11" & "001" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+--  array_pps_next(METADATA_ARRAY_LENGTH-7)<= "11" & "010" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+--  array_pps_next(METADATA_ARRAY_LENGTH-6)<= "11" & "011" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+--  array_pps_next(METADATA_ARRAY_LENGTH-5)<= "11" & "100" & "00000000000" & trig_lvl_a      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+--  array_pps_next(METADATA_ARRAY_LENGTH-4)<= "11" & "100" & "001" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+--  array_pps_next(METADATA_ARRAY_LENGTH-3)<= "11" & "100" & "010" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+--  array_pps_next(METADATA_ARRAY_LENGTH-2)<= "11" & "100" & "011" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+--  array_pps_next(METADATA_ARRAY_LENGTH-1)<= "11" & "100" & "100" & "00000000" & trig_lvl_a when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+------------------------------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------------------------------
+  --data acquisition for each channel
+  process(aclk)
+  begin
+    for i in (DATA_ARRAY_LENGTH-1) downto 0 loop
+      if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        adc_dat_a_reg(i) <= (others=>'0');
+        adc_dat_b_reg(i) <= (others=>'0');
+      else
+        adc_dat_a_reg(i) <= adc_dat_a_next(i);
+        adc_dat_b_reg(i) <= adc_dat_b_next(i);
+      end if;
+      end if;
+      -- next state logic
+      if (i = (DATA_ARRAY_LENGTH-1)) then
+        adc_dat_a_next(i) <= adc_dat_a;
+        adc_dat_b_next(i) <= adc_dat_b;
+      else
+        adc_dat_a_next(i) <= adc_dat_a_reg(i+1);
+        adc_dat_b_next(i) <= adc_dat_b_reg(i+1);
+      end if;
+    end loop;
+  end process;
+
+-----------------------------------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------------------------------
+  --trigger
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      tr_status_reg  <= (others => '0');
+      cnt_status_reg <= (others => '0');
+      trig_cnt_reg   <= (others => '0');
+    else
+      tr_status_reg  <= tr_status_next;
+      cnt_status_reg <= cnt_status_next;
+      trig_cnt_reg   <= trig_cnt_next;
+    end if;
+    end if;
+  end process;
+  
+
+  -- The trigger is at  bin 4 because we loose a clock pulse in the state machine
+  -- next state logic
+  tr1_s <=  '1' when ((adc_dat_a_reg(3)(adc_dat_a_reg(3)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+                      (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+            '0';
+  tr2_s <=  '1' when ((adc_dat_b_reg(3)(adc_dat_b_reg(3)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+                      (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+                      (signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+            '0';
+
+  tr_s <= '1' when  ((tr1_s = '1') or (tr2_s = '1')) else '0';
+
+  tr_status_next <=   "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else
+                      tr_status_reg;
+  cnt_status_next <=  "10" & trig_cnt_reg when (tr_s = '1') else
+                      cnt_status_reg;
+
+  trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else
+                   trig_cnt_reg;
+
+----------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------
+  --sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      charge1_reg <= (others => '0');
+      charge2_reg <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0');
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0');
+    else
+      charge1_reg <= charge1_next;
+      charge2_reg <= charge2_next;
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1);
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2);
+      array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3);
+    end if;
+    end if;
+  end process;
+  -- next state logic
+  subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and 
+                      signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+                      (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+                      (adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+                      signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+                    '0';
+  subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and
+                      signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+                      (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+                      (adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+                      signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+                      signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+                    '0';
+  subtr_s <=  '1' when  ((subtr1_s = '1') or (subtr2_s = '1')) else '0';
+
+  charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right;
+  charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right;
+
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1);
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else
+                                              array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too
+
+----------------------------------------------------------------------------------------------------------------
+
+----------------------------------------------------------------------------------------------------------------
+  -- FSM controlling all
+  --================================================================
+  -- state and data registers
+  --================================================================
+  process (aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+      state_reg      <= ST_IDLE;
+      wr_count_reg   <= (others => '0');
+      data_to_fifo_reg <= (others => '0');
+      axis_tvalid_reg <= '0';
+      axis_tready_reg <= '0';
+    else
+      state_reg      <= state_next;
+      wr_count_reg   <= wr_count_next;
+      data_to_fifo_reg <= data_to_fifo_next;
+      axis_tvalid_reg <= axis_tvalid_next;
+      axis_tready_reg <= axis_tready_next;
+    end if;
+    end if;
+  end process;
+  --=================================================================
+  --next-state logic & data path functional units/routing
+  --=================================================================
+  process(state_reg, status, wr_count_reg)
+  begin
+    state_next        <= state_reg;         -- default 
+    wr_count_next     <= (others => '0'); -- wr_count_reg;
+    data_to_fifo_next <= data_to_fifo_reg;  -- default 
+    axis_tvalid_next  <= '0';               -- default disable write
+    axis_tready_next  <= '1';               -- always ready
+    case state_reg is
+      when ST_IDLE =>
+        if (m_axis_tready = '1') then
+          case status is
+            when "001" | "011" | "101" | "111" => -- priority is for PPS data every second
+              state_next <= ST_ATT_PPS;
+            when "100" | "110" =>
+              state_next <= ST_ATT_TR;
+            when "010" =>
+              state_next <= ST_ATT_SUBTR;
+            when others => --"000"
+              state_next <= ST_IDLE;
+          end case;
+        else
+          state_next <= ST_IDLE;
+        end if;
+
+      --we send adc data because we have a trigger
+      when ST_ATT_TR =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          --data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0));
+          data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0);
+          --data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg);
+          if (wr_count_reg = DATA_ARRAY_LENGTH-1) then
+            state_next <= ST_SEND_TR_STATUS;
+          else
+            state_next <= ST_ATT_TR;
+          end if;
+        else
+          state_next <= ST_ATT_TR;
+        end if;
+
+      when ST_SEND_TR_STATUS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          data_to_fifo_next <= tr_status_reg;
+          --data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30));
+          state_next <= ST_SEND_CNT_STATUS;
+        else
+          state_next <= ST_SEND_TR_STATUS;
+        end if;
+
+      when ST_SEND_CNT_STATUS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          data_to_fifo_next <= cnt_status_reg;
+          --data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30));
+          state_next <= ST_IDLE;
+        else
+          state_next <= ST_SEND_CNT_STATUS;
+        end if;
+
+      when ST_ATT_SUBTR =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg));
+          if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then
+            state_next <= ST_IDLE;
+          else 
+            state_next <= ST_ATT_SUBTR;
+          end if;
+        else
+          state_next <= ST_ATT_SUBTR;
+        end if;
+
+      when ST_ATT_PPS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg));
+          if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then
+            state_next <= ST_IDLE;
+          else
+            state_next <= ST_ATT_PPS;
+          end if;
+        else
+          state_next <= ST_ATT_PPS;
+        end if;
+   end case;
+  end process;
+
+  status <= tr_s & subtr_s & pps_i;
+  s_axis_tready <= axis_tready_reg;
+  m_axis_tdata <= data_to_fifo_reg;
+  m_axis_tvalid <= axis_tvalid_reg;
+
+end architecture rtl;
+
diff --git a/cores/axis_lago_trigger_v1_1/core_config.tcl b/cores/axis_lago_trigger_v1_1/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..3e7f5b30643d20f5c3c64e5091dd8ed638263876
--- /dev/null
+++ b/cores/axis_lago_trigger_v1_1/core_config.tcl
@@ -0,0 +1,25 @@
+set display_name {AXI4-Stream LAGO Trigger v1r1}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter ADC_DATA_WIDTH {ADC_DATA_WIDTH} {Number of ADC data bits.}
+core_parameter DATA_ARRAY_LENGTH {DATA_ARRAY_LENGTH} {Length of the data array.}
+core_parameter METADATA_ARRAY_LENGTH {METADATA_ARRAY_LENGTH} {Length of the metadata array.}
+core_parameter SUBTRIG_ARRAY_LENGTH {SUBTRIG_ARRAY_LENGTH} {Length of the sub-trigger array.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
+
diff --git a/cores/axis_lago_trigger_v1_2/axis_lago_trigger_v1_2.vhd b/cores/axis_lago_trigger_v1_2/axis_lago_trigger_v1_2.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..b8886c080249a01c3a5a56889d60b29c9c453e9e
--- /dev/null
+++ b/cores/axis_lago_trigger_v1_2/axis_lago_trigger_v1_2.vhd
@@ -0,0 +1,472 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_lago_trigger is
+				generic (
+												AXIS_TDATA_WIDTH      : natural  := 32;
+												-- data arrays bit numbers
+												ADC_DATA_WIDTH        : natural := 14;    
+												DATA_ARRAY_LENGTH     : natural := 20;
+												METADATA_ARRAY_LENGTH : natural := 12;
+												SUBTRIG_ARRAY_LENGTH  : natural := 3
+								);
+				port (
+										 -- System signals
+										 aclk               : in std_logic;
+										 aresetn            : in std_logic;
+										 trig_lvl_a_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+										 trig_lvl_b_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+										 subtrig_lvl_a_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+										 subtrig_lvl_b_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+										 pps_i              : in std_logic;
+										 clk_cnt_pps_i      : in std_logic_vector(27-1 downto 0);
+										 temp_i             : in std_logic_vector(24-1 downto 0);
+										 pressure_i         : in std_logic_vector(24-1 downto 0);
+										 time_i             : in std_logic_vector(24-1 downto 0);
+										 date_i             : in std_logic_vector(24-1 downto 0);
+										 latitude_i         : in std_logic_vector(24-1 downto 0);
+										 longitude_i        : in std_logic_vector(24-1 downto 0);
+										 altitude_i         : in std_logic_vector(24-1 downto 0);
+										 satellites_i       : in std_logic_vector(24-1 downto 0);
+										 scaler_a_i         : in std_logic_vector(32-1 downto 0);
+										 scaler_b_i         : in std_logic_vector(32-1 downto 0);
+
+										 -- Slave side
+										 s_axis_tready     : out std_logic;
+										 s_axis_tdata      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+										 s_axis_tvalid     : in std_logic;
+
+										 -- Master side
+										 m_axis_tready     : in std_logic;
+										 m_axis_tdata      : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+										 m_axis_tvalid     : out std_logic
+						 );
+end axis_lago_trigger;
+
+architecture rtl of axis_lago_trigger is
+
+				constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH;
+
+				--ADC related signals
+				type  adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) 
+				of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+				signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t;
+				signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t;
+
+				type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) 
+				of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+				signal array_pps_reg, array_pps_next : array_pps_t;
+
+				type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) 
+				of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+				signal array_scalers_reg, array_scalers_next : array_scalers_t;
+
+				--Trigger related signals
+				--Triggers
+				signal tr1_s, tr2_s, tr_s              : std_logic; 
+				--Sub-Triggers
+				signal subtr1_s, subtr2_s, subtr_s     : std_logic; 
+
+				signal tr_status_reg, tr_status_next   : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+				signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+				signal trig_cnt_reg, trig_cnt_next     : std_logic_vector(30-1 downto 0); 
+
+				--Charge signals
+				signal charge1_reg, charge1_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+				signal charge2_reg, charge2_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+
+				--FSM signals
+				type state_t is (ST_IDLE,
+				ST_ATT_TR,
+				ST_SEND_TR_STATUS,
+				ST_SEND_CNT_STATUS,
+				ST_ATT_SUBTR,
+				ST_ATT_PPS);
+				signal state_reg, state_next: state_t;
+
+				signal wr_count_reg, wr_count_next : unsigned(7 downto 0);
+				signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+				signal status : std_logic_vector(2 downto 0);
+
+				signal axis_tready_reg, axis_tready_next : std_logic;
+				signal axis_tvalid_reg, axis_tvalid_next : std_logic;
+
+				signal trig_lvl_a, trig_lvl_b       : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+				signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+				signal adc_dat_a, adc_dat_b         : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+
+				--Trigger scaler signals
+				signal scaler_a_cnt_reg, scaler_a_cnt_next : std_logic_vector(32-1 downto 0);
+				signal scaler_b_cnt_reg, scaler_b_cnt_next : std_logic_vector(32-1 downto 0);
+				signal scaler_a_max_tick, scaler_b_max_tick: std_logic;
+
+				--Trigger scaler signals
+				signal rate_a_cnt_reg, rate_a_cnt_next : std_logic_vector(24-1 downto 0);
+				signal rate_b_cnt_reg, rate_b_cnt_next : std_logic_vector(24-1 downto 0);
+
+begin
+
+				trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+				trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+				subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+				subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+				adc_dat_a <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0);
+				adc_dat_b <= ((PADDING_WIDTH-1) downto 0 => s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) & s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto AXIS_TDATA_WIDTH/2);
+
+				-- data registers for a second
+				process(aclk)
+				begin
+								for i in METADATA_ARRAY_LENGTH-1 downto 0 loop
+												if (rising_edge(aclk)) then
+																if (aresetn = '0') then
+																				array_pps_reg(i) <= (others => '0');
+																else
+																				array_pps_reg(i) <= array_pps_next(i);
+																end if;
+												end if;
+								end loop;
+				end process;
+				--next state logic
+
+				array_pps_next(METADATA_ARRAY_LENGTH-1) <= x"FFFFFFFF"                              when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+				array_pps_next(METADATA_ARRAY_LENGTH-2) <= "1" & "1000" & clk_cnt_pps_i             when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+				array_pps_next(METADATA_ARRAY_LENGTH-3) <= "1" & "1001" & "000" & temp_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+				array_pps_next(METADATA_ARRAY_LENGTH-4) <= "1" & "1010" & "000" & pressure_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+				array_pps_next(METADATA_ARRAY_LENGTH-5) <= "1" & "1011" & "000" & time_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+				array_pps_next(METADATA_ARRAY_LENGTH-6) <= "1" & "1100" & "000" & latitude_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+				array_pps_next(METADATA_ARRAY_LENGTH-7) <= "1" & "1100" & "001" & longitude_i       when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+				array_pps_next(METADATA_ARRAY_LENGTH-8) <= "1" & "1100" & "010" & altitude_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+				array_pps_next(METADATA_ARRAY_LENGTH-9) <= "1" & "1100" & "011" & date_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+				array_pps_next(METADATA_ARRAY_LENGTH-10)<= "1" & "1100" & "100" & satellites_i      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+				array_pps_next(METADATA_ARRAY_LENGTH-11)<= "1" & "1101" & "000" & rate_a_cnt_reg    when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-11);
+				array_pps_next(METADATA_ARRAY_LENGTH-12)<= "1" & "1110" & "000" & rate_b_cnt_reg    when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-12);
+
+				------------------------------------------------------------------------------------------------------
+
+				------------------------------------------------------------------------------------------------------
+				--data acquisition for each channel
+				process(aclk)
+				begin
+								for i in (DATA_ARRAY_LENGTH-1) downto 0 loop
+												if (rising_edge(aclk)) then
+																if (aresetn = '0') then
+																				adc_dat_a_reg(i) <= (others=>'0');
+																				adc_dat_b_reg(i) <= (others=>'0');
+																else
+																				adc_dat_a_reg(i) <= adc_dat_a_next(i);
+																				adc_dat_b_reg(i) <= adc_dat_b_next(i);
+																end if;
+												end if;
+												-- next state logic
+												if (i = (DATA_ARRAY_LENGTH-1)) then
+																adc_dat_a_next(i) <= adc_dat_a;
+																adc_dat_b_next(i) <= adc_dat_b;
+												else
+																adc_dat_a_next(i) <= adc_dat_a_reg(i+1);
+																adc_dat_b_next(i) <= adc_dat_b_reg(i+1);
+												end if;
+								end loop;
+				end process;
+
+				-----------------------------------------------------------------------------------------------------
+				--rate counter
+				process(aclk)
+				begin
+								if (rising_edge(aclk)) then
+												if (aresetn = '0') then
+																rate_a_cnt_reg  <= (others => '0');
+																rate_b_cnt_reg  <= (others => '0');
+												else
+																rate_a_cnt_reg  <= rate_a_cnt_next;
+																rate_b_cnt_reg  <= rate_b_cnt_next;
+												end if;
+								end if;
+				end process;
+
+				--next state logic
+				rate_a_cnt_next <= std_logic_vector(unsigned(rate_a_cnt_reg) + 1) when scaler_a_max_tick = '1' else
+													 (others => '0') when pps_i = '1' else
+													 rate_a_cnt_reg;
+
+				rate_b_cnt_next <= std_logic_vector(unsigned(rate_b_cnt_reg) + 1) when scaler_b_max_tick = '1' else
+													 (others => '0') when pps_i = '1' else
+													 rate_b_cnt_reg;
+				-----------------------------------------------------------------------------------------------------
+				-----------------------------------------------------------------------------------------------------
+				--trigger scaler
+				process(aclk)
+				begin
+								if (rising_edge(aclk)) then
+												if (aresetn = '0') then
+																scaler_a_cnt_reg  <= (others => '0');
+																scaler_b_cnt_reg  <= (others => '0');
+												else
+																scaler_a_cnt_reg  <= scaler_a_cnt_next;
+																scaler_b_cnt_reg  <= scaler_b_cnt_next;
+												end if;
+								end if;
+				end process;
+
+				--next state logic
+				scaler_a_cnt_next <= std_logic_vector(unsigned(scaler_a_cnt_reg) + 1) when tr1_s = '1' else
+														 (others => '0') when unsigned(scaler_a_cnt_reg) = unsigned(scaler_a_i) else
+														 scaler_a_cnt_reg;
+
+				scaler_a_max_tick <= '1' when unsigned(scaler_a_cnt_reg) = unsigned(scaler_a_i) else '0';
+
+				scaler_b_cnt_next <= std_logic_vector(unsigned(scaler_b_cnt_reg) + 1) when tr2_s = '1' else
+														 (others => '0') when unsigned(scaler_b_cnt_reg) = unsigned(scaler_b_i) else
+														 scaler_b_cnt_reg;
+
+				scaler_b_max_tick <= '1' when unsigned(scaler_b_cnt_reg) = unsigned(scaler_b_i) else '0';
+				-----------------------------------------------------------------------------------------------------
+
+				-----------------------------------------------------------------------------------------------------
+				--trigger
+				process(aclk)
+				begin
+								if (rising_edge(aclk)) then
+												if (aresetn = '0') then
+																tr_status_reg  <= (others => '0');
+																cnt_status_reg <= (others => '0');
+																trig_cnt_reg   <= (others => '0');
+												else
+																tr_status_reg  <= tr_status_next;
+																cnt_status_reg <= cnt_status_next;
+																trig_cnt_reg   <= trig_cnt_next;
+												end if;
+								end if;
+				end process;
+
+
+				-- The trigger is at  bin 4 because we loose a clock pulse in the state machine
+				-- next state logic
+				tr1_s <=  '1' when ((adc_dat_a_reg(10)(adc_dat_a_reg(10)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+									(signed(adc_dat_a_reg(10)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_a_reg(9)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_a_reg(8)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_a_reg(7)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_a_reg(6)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_a_reg(5)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+									'0';
+				tr2_s <=  '1' when ((adc_dat_b_reg(10)(adc_dat_b_reg(10)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+									(signed(adc_dat_b_reg(10)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_b_reg(9)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_b_reg(8)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_b_reg(7)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_b_reg(6)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_b_reg(5)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+									(signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+									'0';
+
+				--tr_s <= '1' when  ((tr1_s = '1') or (tr2_s = '1')) else '0';
+				tr_s <= '1' when  ((scaler_a_max_tick = '1') or (scaler_b_max_tick = '1')) else '0';
+
+				tr_status_next <=   "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else
+														tr_status_reg;
+				cnt_status_next <=  "10" & trig_cnt_reg when (tr_s = '1') else
+														cnt_status_reg;
+
+				trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else
+												 trig_cnt_reg;
+
+				----------------------------------------------------------------------------------------------------------
+
+				----------------------------------------------------------------------------------------------------------
+				--sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks
+				process(aclk)
+				begin
+								if (rising_edge(aclk)) then
+												if (aresetn = '0') then
+																charge1_reg <= (others => '0');
+																charge2_reg <= (others => '0');
+																array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0');
+																array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0');
+																array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0');
+												else
+																charge1_reg <= charge1_next;
+																charge2_reg <= charge2_next;
+																array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1);
+																array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2);
+																array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3);
+												end if;
+								end if;
+				end process;
+				-- next state logic
+				subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and 
+										signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+										signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+										(signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+										(signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+										signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+										(adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+										signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+										signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+										signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+										'0';
+				subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and
+										signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+										signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+										(signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+										(signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+										signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+										(adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+										signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+										signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+										signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+										'0';
+				subtr_s <=  '1' when  ((subtr1_s = '1') or (subtr2_s = '1')) else '0';
+
+				charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right;
+				charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right;
+
+				array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else
+																											array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1);
+				array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else
+																											array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel
+				array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else
+																											array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too
+
+				----------------------------------------------------------------------------------------------------------------
+
+				----------------------------------------------------------------------------------------------------------------
+				-- FSM controlling all
+				--================================================================
+				-- state and data registers
+				--================================================================
+				process (aclk)
+				begin
+								if (rising_edge(aclk)) then
+												if (aresetn = '0') then
+																state_reg      <= ST_IDLE;
+																wr_count_reg   <= (others => '0');
+																data_to_fifo_reg <= (others => '0');
+																axis_tvalid_reg <= '0';
+																axis_tready_reg <= '0';
+												else
+																state_reg      <= state_next;
+																wr_count_reg   <= wr_count_next;
+																data_to_fifo_reg <= data_to_fifo_next;
+																axis_tvalid_reg <= axis_tvalid_next;
+																axis_tready_reg <= axis_tready_next;
+												end if;
+								end if;
+				end process;
+				--=================================================================
+				--next-state logic & data path functional units/routing
+				--=================================================================
+				process(state_reg, status, wr_count_reg)
+				begin
+								state_next        <= state_reg;         -- default 
+								wr_count_next     <= (others => '0'); -- wr_count_reg;
+								data_to_fifo_next <= data_to_fifo_reg;  -- default 
+								axis_tvalid_next  <= '0';               -- default disable write
+								axis_tready_next  <= '1';               -- always ready
+								case state_reg is
+												when ST_IDLE =>
+																if (m_axis_tready = '1') then
+																				case status is
+																								when "001" | "011" | "101" | "111" => -- priority is for PPS data every second
+																												state_next <= ST_ATT_PPS;
+																								when "100" | "110" =>
+																												state_next <= ST_ATT_TR;
+																								when "010" =>
+																												state_next <= ST_ATT_SUBTR;
+																								when others => --"000"
+																												state_next <= ST_IDLE;
+																				end case;
+																else
+																				state_next <= ST_IDLE;
+																end if;
+
+												--we send adc data because we have a trigger
+												when ST_ATT_TR =>
+																axis_tready_next <= '0';
+																axis_tvalid_next <= '1';
+																if (m_axis_tready = '1') then
+																				wr_count_next <= wr_count_reg + 1;
+																				--data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0));
+																				data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0);
+																				--data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg);
+																				if (wr_count_reg = DATA_ARRAY_LENGTH-1) then
+																								state_next <= ST_SEND_TR_STATUS;
+																				else
+																								state_next <= ST_ATT_TR;
+																				end if;
+																else
+																				state_next <= ST_ATT_TR;
+																end if;
+
+												when ST_SEND_TR_STATUS =>
+																axis_tready_next <= '0';
+																axis_tvalid_next <= '1';
+																if (m_axis_tready = '1') then
+																				data_to_fifo_next <= tr_status_reg;
+																				--data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30));
+																				state_next <= ST_SEND_CNT_STATUS;
+																else
+																				state_next <= ST_SEND_TR_STATUS;
+																end if;
+
+												when ST_SEND_CNT_STATUS =>
+																axis_tready_next <= '0';
+																axis_tvalid_next <= '1';
+																if (m_axis_tready = '1') then
+																				data_to_fifo_next <= cnt_status_reg;
+																				--data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30));
+																				state_next <= ST_IDLE;
+																else
+																				state_next <= ST_SEND_CNT_STATUS;
+																end if;
+
+												when ST_ATT_SUBTR =>
+																axis_tready_next <= '0';
+																axis_tvalid_next <= '1';
+																if (m_axis_tready = '1') then
+																				wr_count_next <= wr_count_reg + 1;
+																				data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg));
+																				if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then
+																								state_next <= ST_IDLE;
+																				else 
+																								state_next <= ST_ATT_SUBTR;
+																				end if;
+																else
+																				state_next <= ST_ATT_SUBTR;
+																end if;
+
+												when ST_ATT_PPS =>
+																axis_tready_next <= '0';
+																axis_tvalid_next <= '1';
+																if (m_axis_tready = '1') then
+																				wr_count_next <= wr_count_reg + 1;
+																				data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg));
+																				if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then
+																								state_next <= ST_IDLE;
+																				else
+																								state_next <= ST_ATT_PPS;
+																				end if;
+																else
+																				state_next <= ST_ATT_PPS;
+																end if;
+								end case;
+				end process;
+
+				status <= tr_s & subtr_s & pps_i;
+				s_axis_tready <= axis_tready_reg;
+				m_axis_tdata <= data_to_fifo_reg;
+				m_axis_tvalid <= axis_tvalid_reg;
+
+end architecture rtl;
+
diff --git a/cores/axis_lago_trigger_v1_2/core_config.tcl b/cores/axis_lago_trigger_v1_2/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..5df40a56baa54357b62b19adfe344644ac0956a9
--- /dev/null
+++ b/cores/axis_lago_trigger_v1_2/core_config.tcl
@@ -0,0 +1,25 @@
+set display_name {AXI4-Stream LAGO Trigger v1r2}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter ADC_DATA_WIDTH {ADC_DATA_WIDTH} {Number of ADC data bits.}
+core_parameter DATA_ARRAY_LENGTH {DATA_ARRAY_LENGTH} {Length of the data array.}
+core_parameter METADATA_ARRAY_LENGTH {METADATA_ARRAY_LENGTH} {Length of the metadata array.}
+core_parameter SUBTRIG_ARRAY_LENGTH {SUBTRIG_ARRAY_LENGTH} {Length of the sub-trigger array.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
+
diff --git a/cores/axis_lago_trigger_v1_3/axis_lago_trigger_v1_3.vhd b/cores/axis_lago_trigger_v1_3/axis_lago_trigger_v1_3.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..2156ece99f59a62ba14b9663a30e411af16415b3
--- /dev/null
+++ b/cores/axis_lago_trigger_v1_3/axis_lago_trigger_v1_3.vhd
@@ -0,0 +1,509 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_lago_trigger is
+  generic (
+            AXIS_TDATA_WIDTH      : natural  := 32;
+            -- data arrays bit numbers
+            ADC_DATA_WIDTH        : natural := 14;    
+            DATA_ARRAY_LENGTH     : natural := 20;
+            METADATA_ARRAY_LENGTH : natural := 12;
+            SUBTRIG_ARRAY_LENGTH  : natural := 3
+          );
+  port (
+         -- System signals
+         aclk               : in std_logic;
+         aresetn            : in std_logic;
+         trig_lvl_a_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+         trig_lvl_b_i       : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+         subtrig_lvl_a_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+         subtrig_lvl_b_i    : in std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+         pps_i              : in std_logic;
+         clk_cnt_pps_i      : in std_logic_vector(27-1 downto 0);
+         temp_i             : in std_logic_vector(24-1 downto 0);
+         pressure_i         : in std_logic_vector(24-1 downto 0);
+         time_i             : in std_logic_vector(24-1 downto 0);
+         date_i             : in std_logic_vector(24-1 downto 0);
+         latitude_i         : in std_logic_vector(24-1 downto 0);
+         longitude_i        : in std_logic_vector(24-1 downto 0);
+         altitude_i         : in std_logic_vector(24-1 downto 0);
+         satellites_i       : in std_logic_vector(24-1 downto 0);
+         scaler_a_i         : in std_logic_vector(32-1 downto 0);
+         scaler_b_i         : in std_logic_vector(32-1 downto 0);
+
+         -- Slave side
+         s_axis_tready     : out std_logic;
+         s_axis_tdata      : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         s_axis_tvalid     : in std_logic;
+
+         -- Master side
+         m_axis_tready     : in std_logic;
+         m_axis_tdata      : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         m_axis_tvalid     : out std_logic
+       );
+end axis_lago_trigger;
+
+architecture rtl of axis_lago_trigger is
+
+  constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH;
+
+  --ADC related signals
+  type  adc_data_array_t is array (DATA_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_dat_a_reg, adc_dat_a_next : adc_data_array_t;
+  signal adc_dat_b_reg, adc_dat_b_next : adc_data_array_t;
+
+  type array_pps_t is array (METADATA_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal array_pps_reg, array_pps_next : array_pps_t;
+
+  type array_scalers_t is array (SUBTRIG_ARRAY_LENGTH-1 downto 0) 
+  of std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal array_scalers_reg, array_scalers_next : array_scalers_t;
+
+  --Trigger related signals
+  --Triggers
+  signal tr1_s, tr2_s, tr_s              : std_logic; 
+  --Sub-Triggers
+  signal subtr1_s, subtr2_s, subtr_s     : std_logic; 
+
+  signal tr_status_reg, tr_status_next   : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal cnt_status_reg, cnt_status_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+  signal trig_cnt_reg, trig_cnt_next     : std_logic_vector(30-1 downto 0); 
+
+  --Charge signals
+  signal charge1_reg, charge1_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+  signal charge2_reg, charge2_next       : unsigned(ADC_DATA_WIDTH-1 downto 0);
+
+  --FSM signals
+  type state_t is (ST_IDLE,
+  ST_ATT_TR,
+  ST_SEND_TR_STATUS,
+  ST_SEND_CNT_STATUS,
+  ST_ATT_SUBTR,
+  ST_ATT_PPS);
+  signal state_reg, state_next: state_t;
+
+  signal wr_count_reg, wr_count_next : unsigned(7 downto 0);
+  signal data_to_fifo_reg, data_to_fifo_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal status : std_logic_vector(2 downto 0);
+
+  signal axis_tready_reg, axis_tready_next : std_logic;
+  signal axis_tvalid_reg, axis_tvalid_next : std_logic;
+
+  signal trig_lvl_a, trig_lvl_b       : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal subtrig_lvl_a, subtrig_lvl_b : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_dat_a, adc_dat_b         : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_reg_a, adc_next_a        : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+  signal adc_reg_b, adc_next_b        : std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+
+  --Trigger scaler signals
+  signal scaler_a_cnt_reg, scaler_a_cnt_next : std_logic_vector(32-1 downto 0);
+  signal scaler_b_cnt_reg, scaler_b_cnt_next : std_logic_vector(32-1 downto 0);
+  signal scaler_a_max_tick, scaler_b_max_tick: std_logic;
+
+  --Trigger scaler signals
+  signal rate_a_cnt_reg, rate_a_cnt_next : std_logic_vector(24-1 downto 0);
+  signal rate_b_cnt_reg, rate_b_cnt_next : std_logic_vector(24-1 downto 0);
+  signal tr11_s_dly_reg, tr11_s_dly_next : std_logic;
+  signal tr21_s_dly_reg, tr21_s_dly_next : std_logic;
+
+begin
+
+  trig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_a_i(ADC_DATA_WIDTH-1)) & trig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+  trig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => trig_lvl_b_i(ADC_DATA_WIDTH-1)) & trig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+  subtrig_lvl_a <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_a_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_a_i(ADC_DATA_WIDTH-1 downto 0);
+  subtrig_lvl_b <= ((PADDING_WIDTH-1) downto 0 => subtrig_lvl_b_i(ADC_DATA_WIDTH-1)) & subtrig_lvl_b_i(ADC_DATA_WIDTH-1 downto 0);
+
+  adc_dat_a <= adc_reg_a;
+  adc_dat_b <= adc_reg_b;
+
+  --input registers
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        adc_reg_a <= (others => '0');
+        adc_reg_b <= (others => '0');
+      else
+        adc_reg_a <= adc_next_a;
+        adc_reg_b <= adc_next_b;
+      end if;
+    end if;
+  end process;
+  --next state logic
+  adc_next_a <= ((PADDING_WIDTH-1) downto 0 =>
+                s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1)) &
+                s_axis_tdata(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0)
+              when ((axis_tready_reg = '1') and (s_axis_tvalid = '1')) else
+              adc_reg_a;
+  adc_next_b <= ((PADDING_WIDTH-1) downto 0 =>
+                s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1)) &
+                s_axis_tdata(AXIS_TDATA_WIDTH-PADDING_WIDTH-1 downto
+                AXIS_TDATA_WIDTH/2) when ((axis_tready_reg = '1') and (s_axis_tvalid = '1')) else
+                adc_reg_b;
+
+
+  -- data registers for a second
+  process(aclk)
+  begin
+    for i in METADATA_ARRAY_LENGTH-1 downto 0 loop
+      if (rising_edge(aclk)) then
+        if (aresetn = '0') then
+          array_pps_reg(i) <= (others => '0');
+        else
+          array_pps_reg(i) <= array_pps_next(i);
+        end if;
+      end if;
+    end loop;
+  end process;
+  --next state logic
+
+  array_pps_next(METADATA_ARRAY_LENGTH-1) <= x"FFFFFFFF"                              when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-1);
+  array_pps_next(METADATA_ARRAY_LENGTH-2) <= "1" & "1000" & clk_cnt_pps_i             when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-2);
+  array_pps_next(METADATA_ARRAY_LENGTH-3) <= "1" & "1001" & "000" & temp_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-3);
+  array_pps_next(METADATA_ARRAY_LENGTH-4) <= "1" & "1010" & "000" & pressure_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-4);
+  array_pps_next(METADATA_ARRAY_LENGTH-5) <= "1" & "1011" & "000" & time_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-5);
+  array_pps_next(METADATA_ARRAY_LENGTH-6) <= "1" & "1100" & "000" & latitude_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-6);
+  array_pps_next(METADATA_ARRAY_LENGTH-7) <= "1" & "1100" & "001" & longitude_i       when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-7);
+  array_pps_next(METADATA_ARRAY_LENGTH-8) <= "1" & "1100" & "010" & altitude_i        when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-8);
+  array_pps_next(METADATA_ARRAY_LENGTH-9) <= "1" & "1100" & "011" & date_i            when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-9);
+  array_pps_next(METADATA_ARRAY_LENGTH-10)<= "1" & "1100" & "100" & satellites_i      when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-10);
+  array_pps_next(METADATA_ARRAY_LENGTH-11)<= "1" & "1101" & "000" & rate_a_cnt_reg    when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-11);
+  array_pps_next(METADATA_ARRAY_LENGTH-12)<= "1" & "1110" & "000" & rate_b_cnt_reg    when (pps_i = '1') else array_pps_reg(METADATA_ARRAY_LENGTH-12);
+
+  ------------------------------------------------------------------------------------------------------
+
+  ------------------------------------------------------------------------------------------------------
+  --data acquisition for each channel
+  process(aclk)
+  begin
+    for i in (DATA_ARRAY_LENGTH-1) downto 0 loop
+      if (rising_edge(aclk)) then
+        if (aresetn = '0') then
+          adc_dat_a_reg(i) <= (others=>'0');
+          adc_dat_b_reg(i) <= (others=>'0');
+        else
+          adc_dat_a_reg(i) <= adc_dat_a_next(i);
+          adc_dat_b_reg(i) <= adc_dat_b_next(i);
+        end if;
+      end if;
+      -- next state logic
+      if (i = (DATA_ARRAY_LENGTH-1)) then
+        adc_dat_a_next(i) <= adc_dat_a;
+        adc_dat_b_next(i) <= adc_dat_b;
+      else
+        adc_dat_a_next(i) <= adc_dat_a_reg(i+1);
+        adc_dat_b_next(i) <= adc_dat_b_reg(i+1);
+      end if;
+    end loop;
+  end process;
+
+  -----------------------------------------------------------------------------------------------------
+  --rate counter
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        rate_a_cnt_reg  <= (others => '0');
+        rate_b_cnt_reg  <= (others => '0');
+      else
+        rate_a_cnt_reg  <= rate_a_cnt_next;
+        rate_b_cnt_reg  <= rate_b_cnt_next;
+      end if;
+    end if;
+  end process;
+
+  --next state logic
+  rate_a_cnt_next <= std_logic_vector(unsigned(rate_a_cnt_reg) + 1) when scaler_a_max_tick = '1' else
+                     (others => '0') when pps_i = '1' else
+                     rate_a_cnt_reg;
+
+  rate_b_cnt_next <= std_logic_vector(unsigned(rate_b_cnt_reg) + 1) when scaler_b_max_tick = '1' else
+                     (others => '0') when pps_i = '1' else
+                     rate_b_cnt_reg;
+  -----------------------------------------------------------------------------------------------------
+  -----------------------------------------------------------------------------------------------------
+  --trigger scaler
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        scaler_a_cnt_reg  <= (others => '0');
+        scaler_b_cnt_reg  <= (others => '0');
+        tr11_s_dly_reg    <= '0';
+        tr21_s_dly_reg    <= '0';
+      else
+        scaler_a_cnt_reg  <= scaler_a_cnt_next;
+        scaler_b_cnt_reg  <= scaler_b_cnt_next;
+        tr11_s_dly_reg    <= tr11_s_dly_next;
+        tr21_s_dly_reg    <= tr21_s_dly_next;
+      end if;
+    end if;
+  end process;
+
+  --next state logic
+  scaler_a_cnt_next <= std_logic_vector(unsigned(scaler_a_cnt_reg) + 1) when tr1_s = '1' else
+                       (others => '0') when unsigned(scaler_a_cnt_reg) = unsigned(scaler_a_i) else
+                       scaler_a_cnt_reg;
+  tr11_s_dly_next    <= '1' when tr1_s = '1' else '0';
+
+  scaler_a_max_tick <= '1' when unsigned(scaler_a_cnt_reg) = unsigned(scaler_a_i) else '0';
+
+  scaler_b_cnt_next <= std_logic_vector(unsigned(scaler_b_cnt_reg) + 1) when tr2_s = '1' else
+                       (others => '0') when unsigned(scaler_b_cnt_reg) = unsigned(scaler_b_i) else
+                       scaler_b_cnt_reg;
+  tr21_s_dly_next    <= '1' when tr2_s = '1' else '0';
+
+  scaler_b_max_tick <= '1' when unsigned(scaler_b_cnt_reg) = unsigned(scaler_b_i) else '0';
+  -----------------------------------------------------------------------------------------------------
+
+  -----------------------------------------------------------------------------------------------------
+  --trigger
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        tr_status_reg  <= (others => '0');
+        cnt_status_reg <= (others => '0');
+        trig_cnt_reg   <= (others => '0');
+      else
+        tr_status_reg  <= tr_status_next;
+        cnt_status_reg <= cnt_status_next;
+        trig_cnt_reg   <= trig_cnt_next;
+      end if;
+    end if;
+  end process;
+
+
+  -- The trigger is at  bin 4 because we loose a clock pulse in the state machine
+  -- next state logic
+  tr1_s <=  '1' when ((adc_dat_a_reg(10)(adc_dat_a_reg(10)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+            (signed(adc_dat_a_reg(10)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_a_reg(9)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_a_reg(8)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_a_reg(7)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_a_reg(6)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_a_reg(5)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+            '0';
+  tr2_s <=  '1' when ((adc_dat_b_reg(10)(adc_dat_b_reg(10)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+            (signed(adc_dat_b_reg(10)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_b_reg(9)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_b_reg(8)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_b_reg(7)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_b_reg(6)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_b_reg(5)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0))) and
+            (signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)))) else
+            '0';
+
+  --tr_s <= '1' when  ((tr1_s = '1') or (tr2_s = '1')) else '0';
+  tr_s <= '1' when  ((scaler_a_max_tick = '1') or (scaler_b_max_tick = '1')) else '0';
+
+  --tr_status_next <=   "010" & tr2_s & tr1_s & clk_cnt_pps_i when (tr_s = '1') else
+  tr_status_next <=   "010" & tr21_s_dly_reg & tr11_s_dly_reg & clk_cnt_pps_i when (tr_s = '1') else
+                      tr_status_reg;
+  cnt_status_next <=  "10" & trig_cnt_reg when (tr_s = '1') else
+                      cnt_status_reg;
+
+  trig_cnt_next <= std_logic_vector(unsigned(trig_cnt_reg) + 1) when (tr_s = '1') else
+                   trig_cnt_reg;
+
+  ----------------------------------------------------------------------------------------------------------
+
+  ----------------------------------------------------------------------------------------------------------
+  --sub-trigger: we test for a sub-trigger and we must not have a trigger in the next two clocks
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        charge1_reg <= (others => '0');
+        charge2_reg <= (others => '0');
+        array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= (others => '0');
+        array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= (others => '0');
+        array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= (others => '0');
+      else
+        charge1_reg <= charge1_next;
+        charge2_reg <= charge2_next;
+        array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-1);
+        array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-2);
+        array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3) <= array_scalers_next(SUBTRIG_ARRAY_LENGTH-3);
+      end if;
+    end if;
+  end process;
+  -- next state logic
+  subtr1_s <= '1' when adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = subtrig_lvl_a(subtrig_lvl_a'left) and 
+              signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+              signed(adc_dat_a_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+              (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+              (signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+              signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+              (adc_dat_a_reg(2)(adc_dat_a_reg(2)'left) = trig_lvl_a(trig_lvl_a'left)) and 
+              signed(adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+              signed(adc_dat_a_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+              signed(adc_dat_a_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_a(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+              '0';
+  subtr2_s <= '1' when adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = subtrig_lvl_b(subtrig_lvl_b'left) and
+              signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) >= signed(subtrig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+              signed(adc_dat_b_reg(1)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+              (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) or
+              (signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) = signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+              signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)))) and
+              (adc_dat_b_reg(2)(adc_dat_b_reg(2)'left) = trig_lvl_b(trig_lvl_b'left)) and 
+              signed(adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+              signed(adc_dat_b_reg(3)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) and
+              signed(adc_dat_b_reg(4)(AXIS_TDATA_WIDTH/2-2 downto 0)) < signed(trig_lvl_b(AXIS_TDATA_WIDTH/2-2 downto 0)) else
+              '0';
+  subtr_s <=  '1' when  ((subtr1_s = '1') or (subtr2_s = '1')) else '0';
+
+  charge1_next <= charge1_reg + adc_dat_a_reg'left - adc_dat_a_reg'right;
+  charge2_next <= charge2_reg + adc_dat_b_reg'left - adc_dat_b_reg'right;
+
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-1) <= "010" & subtr2_s & subtr1_s & clk_cnt_pps_i when (subtr_s = '1') else
+                                                array_scalers_reg(SUBTRIG_ARRAY_LENGTH-1);
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-2) <= "0000" & std_logic_vector(charge1_reg) & std_logic_vector(charge2_reg) when (subtr_s = '1') else
+                                                array_scalers_reg(SUBTRIG_ARRAY_LENGTH-2); --charge values per channel
+  array_scalers_next(SUBTRIG_ARRAY_LENGTH-3) <= "0000" & adc_dat_a_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) & adc_dat_b_reg(2)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1 downto 0) when (subtr_s = '1') else
+                                                array_scalers_reg(SUBTRIG_ARRAY_LENGTH-3); --we send the pulse maximum too
+
+  ----------------------------------------------------------------------------------------------------------------
+
+  ----------------------------------------------------------------------------------------------------------------
+  -- FSM controlling all
+  --================================================================
+  -- state and data registers
+  --================================================================
+  process (aclk)
+  begin
+    if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        state_reg      <= ST_IDLE;
+        wr_count_reg   <= (others => '0');
+        data_to_fifo_reg <= (others => '0');
+        axis_tvalid_reg <= '0';
+        axis_tready_reg <= '0';
+      else
+        state_reg      <= state_next;
+        wr_count_reg   <= wr_count_next;
+        data_to_fifo_reg <= data_to_fifo_next;
+        axis_tvalid_reg <= axis_tvalid_next;
+        axis_tready_reg <= axis_tready_next;
+      end if;
+    end if;
+  end process;
+  --=================================================================
+  --next-state logic & data path functional units/routing
+  --=================================================================
+  process(state_reg, status, wr_count_reg)
+  begin
+    state_next        <= state_reg;         -- default 
+    wr_count_next     <= (others => '0'); -- wr_count_reg;
+    data_to_fifo_next <= data_to_fifo_reg;  -- default 
+    axis_tvalid_next  <= '0';               -- default disable write
+    axis_tready_next  <= '1';               -- always ready
+    case state_reg is
+      when ST_IDLE =>
+        if (m_axis_tready = '1') then
+          case status is
+            when "001" | "011" | "101" | "111" => -- priority is for PPS data every second
+              state_next <= ST_ATT_PPS;
+            when "100" | "110" =>
+              state_next <= ST_ATT_TR;
+            when "010" =>
+              state_next <= ST_ATT_SUBTR;
+            when others => --"000"
+              state_next <= ST_IDLE;
+          end case;
+        else
+          state_next <= ST_IDLE;
+        end if;
+
+      --we send adc data because we have a trigger
+      when ST_ATT_TR =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          --data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0)) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & not(adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0));
+          data_to_fifo_next <= "00" & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_b_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0) & "00" & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-1) & adc_dat_a_reg(0)(AXIS_TDATA_WIDTH/2-PADDING_WIDTH-2 downto 0);
+          --data_to_fifo_next <= "00" & (29 downto 8 => '0') & std_logic_vector(wr_count_reg);
+          if (wr_count_reg = DATA_ARRAY_LENGTH-1) then
+            state_next <= ST_SEND_TR_STATUS;
+          else
+            state_next <= ST_ATT_TR;
+          end if;
+        else
+          state_next <= ST_ATT_TR;
+        end if;
+
+      when ST_SEND_TR_STATUS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          data_to_fifo_next <= tr_status_reg;
+          --data_to_fifo_next <= "01" & std_logic_vector(to_unsigned(33,30));
+          state_next <= ST_SEND_CNT_STATUS;
+        else
+          state_next <= ST_SEND_TR_STATUS;
+        end if;
+
+      when ST_SEND_CNT_STATUS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          data_to_fifo_next <= cnt_status_reg;
+          --data_to_fifo_next <= "10" & std_logic_vector(to_unsigned(55,30));
+          state_next <= ST_IDLE;
+        else
+          state_next <= ST_SEND_CNT_STATUS;
+        end if;
+
+      when ST_ATT_SUBTR =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          data_to_fifo_next <= array_scalers_reg(to_integer(wr_count_reg));
+          if (wr_count_reg = SUBTRIG_ARRAY_LENGTH-1) then
+            state_next <= ST_IDLE;
+          else 
+            state_next <= ST_ATT_SUBTR;
+          end if;
+        else
+          state_next <= ST_ATT_SUBTR;
+        end if;
+
+      when ST_ATT_PPS =>
+        axis_tready_next <= '0';
+        axis_tvalid_next <= '1';
+        if (m_axis_tready = '1') then
+          wr_count_next <= wr_count_reg + 1;
+          data_to_fifo_next <= array_pps_reg(to_integer(wr_count_reg));
+          if (wr_count_reg = METADATA_ARRAY_LENGTH-1) then
+            state_next <= ST_IDLE;
+          else
+            state_next <= ST_ATT_PPS;
+          end if;
+        else
+          state_next <= ST_ATT_PPS;
+        end if;
+    end case;
+  end process;
+
+  status <= tr_s & subtr_s & pps_i;
+  s_axis_tready <= axis_tready_reg;
+  m_axis_tdata <= data_to_fifo_reg;
+  m_axis_tvalid <= axis_tvalid_reg;
+
+end architecture rtl;
+
diff --git a/cores/axis_lago_trigger_v1_3/core_config.tcl b/cores/axis_lago_trigger_v1_3/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..725cd3a7928d6a154c809426bac7e58f4abe6648
--- /dev/null
+++ b/cores/axis_lago_trigger_v1_3/core_config.tcl
@@ -0,0 +1,25 @@
+set display_name {AXI4-Stream LAGO Trigger v1r3}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter ADC_DATA_WIDTH {ADC_DATA_WIDTH} {Number of ADC data bits.}
+core_parameter DATA_ARRAY_LENGTH {DATA_ARRAY_LENGTH} {Length of the data array.}
+core_parameter METADATA_ARRAY_LENGTH {METADATA_ARRAY_LENGTH} {Length of the metadata array.}
+core_parameter SUBTRIG_ARRAY_LENGTH {SUBTRIG_ARRAY_LENGTH} {Length of the sub-trigger array.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
+
diff --git a/cores/axis_lfsr_v1_0/axis_lfsr.vhd b/cores/axis_lfsr_v1_0/axis_lfsr.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..5e3c33ed56cad3bbc91c3c71cddfcfa2ee4e95d2
--- /dev/null
+++ b/cores/axis_lfsr_v1_0/axis_lfsr.vhd
@@ -0,0 +1,60 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_lfsr is
+  generic (
+            HAS_TREADY      : boolean := FALSE;
+            AXIS_TDATA_WIDTH: natural := 64
+          );
+  port (
+         -- System signals
+         aclk          : in std_logic;
+         aresetn       : in std_logic;
+
+         -- Master side
+         m_axis_tready : in std_logic;
+         m_axis_tvalid : out std_logic;
+         m_axis_tdata  : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0)
+       );
+end axis_lfsr;
+
+architecture rtl of axis_lfsr is
+  signal int_lfsr_reg, int_lfsr_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal int_enbl_reg, int_enbl_next : std_logic;
+  signal tmp_sig                     : std_logic;
+
+begin
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then 
+      if aresetn = '0' then
+        int_lfsr_reg <= std_logic_vector(to_unsigned(16#5#, AXIS_TDATA_WIDTH));
+        int_enbl_reg <= '0';
+      else 
+        int_lfsr_reg <= int_lfsr_next;
+        int_enbl_reg <= int_enbl_next;
+      end if;
+      end if;
+    end process;
+    
+    tmp_sig <= int_lfsr_reg(AXIS_TDATA_WIDTH-2) xnor int_lfsr_reg(AXIS_TDATA_WIDTH-3);
+
+    WITH_TREADY: if (HAS_TREADY) generate
+      int_lfsr_next <= int_lfsr_reg(AXIS_TDATA_WIDTH-2 downto 0) & tmp_sig when (int_enbl_reg = '1' and m_axis_tready = '1') else 
+                       int_lfsr_reg;
+      int_enbl_next <= '1' when (int_enbl_reg = '0') else 
+                       int_enbl_reg;
+    end generate;
+    NO_TREADY: if (not HAS_TREADY) generate
+      int_lfsr_next <= int_lfsr_reg(AXIS_TDATA_WIDTH-2 downto 0) & tmp_sig when (int_enbl_reg = '1') else 
+                       int_lfsr_reg;
+      int_enbl_next <= '1' when (int_enbl_reg = '0') else 
+                       int_enbl_reg;
+    end generate;
+
+  m_axis_tdata <= int_lfsr_reg;
+  m_axis_tvalid <= int_enbl_reg;
+end rtl;
diff --git a/cores/axis_lfsr_v1_0/core_config.tcl b/cores/axis_lfsr_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..cff097432d5aa0158cda78e2082661799f969e44
--- /dev/null
+++ b/cores/axis_lfsr_v1_0/core_config.tcl
@@ -0,0 +1,17 @@
+set display_name {AXI4-Stream Linear Feedback Shift-Register}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+core_parameter HAS_TREADY {HAS TREADY} {If TRUE, use m_axis_tready.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS $parameter
diff --git a/cores/axis_lpf_v1_0/axis_lpf.vhd b/cores/axis_lpf_v1_0/axis_lpf.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..b1484941442b228249644bb880d004dfe442e4af
--- /dev/null
+++ b/cores/axis_lpf_v1_0/axis_lpf.vhd
@@ -0,0 +1,71 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity lpf_iir is
+generic (
+  AXIS_TDATA_WIDTH: natural := 32;
+  ADC_DATA_WIDTH  : natural := 14
+);
+port(
+  aclk       : in std_logic;
+  aresetn    : in std_logic;
+  tc_i       : in std_logic_vector (AXIS_TDATA_WIDTH-1 downto 0); -- time constant: parameter equal to e^-1/d where d is number of samples time constant
+  data_o     : out std_logic_vector (AXIS_TDATA_WIDTH-1 downto 0);
+
+  -- Slave side
+  s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);  
+  s_axis_tready: out std_logic;
+  s_axis_tvalid: in std_logic; 
+
+  -- Master side
+  m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  m_axis_tready: in std_logic;
+  m_axis_tvalid: out std_logic
+
+);
+end lpf_iir;
+
+architecture rtl of lpf_iir is
+
+constant one               : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0) := "01111111111111111111111111111111";
+
+signal sig_reg, sig_next   : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+signal data_reg, data_next : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+signal mult_out            : std_logic_vector(2*AXIS_TDATA_WIDTH-1 downto 0);
+
+signal a0                  : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+signal b1                  : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+begin
+
+  process(aclk)
+  begin
+  	if(aresetn = '0') then
+  		sig_reg <= s_axis_tdata;
+      data_reg <= (others => '0');
+  	elsif rising_edge(aclk) then
+  		sig_reg <= sig_next;
+      data_reg <= data_next;
+  	end if;
+  end process;
+
+  --next state logic
+  sig_next <= s_axis_tdata;
+  s_axis_tready <= m_axis_tready;
+  m_axis_tvalid <= s_axis_tvalid;
+  
+  a0 <= std_logic_vector(signed(one) - signed(tc_i)); --  & (AXIS_TDATA_WIDTH-2 downto 0 => '1') - signed(tc_i)); 
+  b1 <= tc_i;  
+  
+  mult_out <= std_logic_vector(signed(a0)*signed(s_axis_tdata) + signed(b1)*signed(sig_reg));
+  
+  data_next <= mult_out((2*AXIS_TDATA_WIDTH)-1) & mult_out(2*AXIS_TDATA_WIDTH-2 downto 32);
+  
+  data_o <= data_reg;
+  
+  m_axis_tdata <= mult_out((2*AXIS_TDATA_WIDTH)-1) & mult_out(2*AXIS_TDATA_WIDTH-2 downto 32);
+
+end rtl;
diff --git a/cores/axis_lpf_v1_0/core_config.tcl b/cores/axis_lpf_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..1128d10e42f4631b14988ec39a088b0111159287
--- /dev/null
+++ b/cores/axis_lpf_v1_0/core_config.tcl
@@ -0,0 +1,21 @@
+set display_name {AXI4-Stream IIR Low Pass Filter}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+core_parameter ADC_DATA_WIDTH {ADC DATA WIDTH} {Width of the ADC data bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE M_AXIS:S_AXIS $parameter
diff --git a/cores/axis_packetizer_v1_0/axis_packetizer.vhd b/cores/axis_packetizer_v1_0/axis_packetizer.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..dd8e5ec29200ee684cad329b723c0b987a1b3fd1
--- /dev/null
+++ b/cores/axis_packetizer_v1_0/axis_packetizer.vhd
@@ -0,0 +1,83 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_packetizer is
+  generic (
+  AXIS_TDATA_WIDTH : natural := 32;
+  CNTR_WIDTH    : natural    := 32;
+  CONTINUOUS    : string     := "FALSE"
+);
+port (
+  -- System signals
+  aclk          : in std_logic;
+  aresetn       : in std_logic;
+
+  -- Configuration bits
+  cfg_data      : in std_logic_vector(CNTR_WIDTH-1 downto 0);
+
+  -- Slave side
+  s_axis_tready : out std_logic;
+  s_axis_tdata  : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  s_axis_tvalid : in std_logic;
+
+  --Master side
+  m_axis_tready : in std_logic;
+  m_axis_tdata  : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  m_axis_tvalid : out std_logic;
+  m_axis_tlast  : out std_logic
+);
+end axis_packetizer;
+
+architecture rtl of axis_packetizer is
+
+  signal int_cntr_reg, int_cntr_next : unsigned(CNTR_WIDTH-1 downto 0);
+  signal int_enbl_reg, int_enbl_next : std_logic;
+
+  signal int_comp_wire, int_tvalid_wire, int_tlast_wire : std_logic;
+
+begin
+
+  process(aclk)
+  begin
+  if (rising_edge(aclk)) then
+  if (aresetn = '0') then
+    int_cntr_reg <= (others => '0');
+    int_enbl_reg <= '0';
+  else
+    int_cntr_reg <= int_cntr_next;
+    int_enbl_reg <= int_enbl_next;
+  end if;
+  end if;
+  end process;
+
+  int_comp_wire   <= '1' when (int_cntr_reg < unsigned(cfg_data)) else '0';
+  int_tvalid_wire <= '1' when (int_enbl_reg = '1') and (s_axis_tvalid = '1') else '0';
+  int_tlast_wire  <= '1' when (int_comp_wire = '0') else '0';
+
+  CONTINUOUS_G: if (CONTINUOUS = "TRUE") generate
+  begin
+  int_cntr_next <= int_cntr_reg + 1 when (m_axis_tready = '1') and (int_tvalid_wire = '1') and (int_comp_wire = '1') else 
+                   (others => '0') when (m_axis_tready = '1') and (int_tvalid_wire = '1') and (int_tlast_wire = '1') else 
+		               int_cntr_reg;
+
+  int_enbl_next <= '1' when (int_enbl_reg = '0') and (int_comp_wire = '1') else int_enbl_reg;
+  end generate;
+
+  STOP_G: if (CONTINUOUS = "FALSE") generate
+  begin
+  int_cntr_next <= int_cntr_reg + 1 when (m_axis_tready = '1') and (int_tvalid_wire = '1') and (int_comp_wire = '1') else 
+                   int_cntr_reg;
+
+  int_enbl_next <= '1' when (int_enbl_reg = '0') and (int_comp_wire = '1') else 
+                   '0' when (m_axis_tready = '1') and (int_tvalid_wire = '1') and (int_tlast_wire = '1') else 
+		               int_enbl_reg;
+  end generate;
+
+  s_axis_tready <= '1' when (int_enbl_reg = '1') and (m_axis_tready = '1') else '0';
+  m_axis_tdata  <= s_axis_tdata;
+  m_axis_tvalid <= int_tvalid_wire;
+  m_axis_tlast  <= '1' when (int_enbl_reg = '1') and (int_tlast_wire = '1') else '0';
+
+end rtl;
diff --git a/cores/axis_packetizer_v1_0/core_config.tcl b/cores/axis_packetizer_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..dc6b23e2a132d91d15d2e7d34ceaec945c8ccb7b
--- /dev/null
+++ b/cores/axis_packetizer_v1_0/core_config.tcl
@@ -0,0 +1,22 @@
+set display_name {AXI4-Stream Packetizer}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS and S_AXIS data buses.}
+core_parameter CNTR_WIDTH {CNTR WIDTH} {Width of the counter register.}
+core_parameter CONTINUOUS {CONTINUOUS} {If TRUE, packetizer runs continuously.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
diff --git a/cores/axis_ram_writer_v1_0/axis_ram_writer.vhd b/cores/axis_ram_writer_v1_0/axis_ram_writer.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..8203039efbb215110f313b8050c9305722fd34e1
--- /dev/null
+++ b/cores/axis_ram_writer_v1_0/axis_ram_writer.vhd
@@ -0,0 +1,164 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity axis_ram_writer is
+  generic (
+            ADDR_WIDTH       : natural := 20;
+            AXI_ID_WIDTH     : natural := 6;
+            AXI_ADDR_WIDTH   : natural := 32;
+            AXI_DATA_WIDTH   : natural := 64;
+            AXIS_TDATA_WIDTH : natural := 64
+          );
+  port (
+         -- System signals
+         aclk             : in std_logic;
+         aresetn          : in std_logic;
+
+         -- Configuration bits
+         cfg_data         : in std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);
+         sts_data         : out std_logic_vector(ADDR_WIDTH-1 downto 0);
+
+         -- Master side
+         m_axi_awid       : out std_logic_vector(AXI_ID_WIDTH-1 downto 0);     -- AXI master: Write address ID
+         m_axi_awaddr     : out std_logic_vector(AXI_ADDR_WIDTH-1 downto 0);   -- AXI master: Write address
+         m_axi_awlen      : out std_logic_vector(3 downto 0);                  -- AXI master: Write burst length
+         m_axi_awsize     : out std_logic_vector(2 downto 0);                  -- AXI master: Write burst size
+         m_axi_awburst    : out std_logic_vector(1 downto 0);                  -- AXI master: Write burst type
+         m_axi_awcache    : out std_logic_vector(3 downto 0);                  -- AXI master: Write memory type
+         m_axi_awvalid    : out std_logic;                                     -- AXI master: Write address valid
+         m_axi_awready    : in std_logic;                                      -- AXI master: Write address ready
+         m_axi_wid        : out std_logic_vector(AXI_ID_WIDTH-1 downto 0);     -- AXI master: Write data ID
+         m_axi_wdata      : out std_logic_vector(AXI_DATA_WIDTH-1 downto 0);   -- AXI master: Write data
+         m_axi_wstrb      : out std_logic_vector(AXI_DATA_WIDTH/8-1 downto 0); -- AXI master: Write strobes
+         m_axi_wlast      : out std_logic;                                     -- AXI master: Write last
+         m_axi_wvalid     : out std_logic;                                     -- AXI master: Write valid
+         m_axi_wready     : in std_logic;                                      -- AXI master: Write ready
+         m_axi_bvalid     : in std_logic;                                      -- AXI master: Write response valid
+         m_axi_bready     : out std_logic;                                     -- AXI master: Write response ready
+
+         -- Slave side
+         s_axis_tready    : out std_logic;
+         s_axis_tdata     : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         s_axis_tvalid    : in std_logic
+       );
+end axis_ram_writer;
+
+architecture rtl of axis_ram_writer is
+
+  function clogb2 (value: natural) return natural is
+  variable temp    : natural := value;
+  variable ret_val : natural := 1;
+  begin
+    while temp > 1 loop
+      ret_val := ret_val + 1;
+      temp    := temp / 2;
+    end loop;
+    return ret_val;
+  end function;
+
+  constant ADDR_SIZE : natural := clogb2((AXI_DATA_WIDTH/8) - 1);
+
+  signal int_awvalid_reg, int_awvalid_next : std_logic;
+  signal int_wvalid_reg, int_wvalid_next   : std_logic;
+  signal int_addr_reg, int_addr_next       : unsigned(ADDR_WIDTH-1 downto 0);
+  signal int_wid_reg, int_wid_next         : unsigned(AXI_ID_WIDTH-1 downto 0);
+
+  signal int_full_wire, int_empty_wire, int_rden_wire : std_logic;
+  signal int_wlast_wire, int_tready_wire   : std_logic;
+  signal int_wdata_wire                    : std_logic_vector(AXI_DATA_WIDTH-1 downto 0);
+
+  signal tmp_s2                            : std_logic;
+  signal reset                             : std_logic;
+
+begin
+
+  int_tready_wire <= not int_full_wire;
+  int_wlast_wire <= '1' when (int_addr_reg(3 downto 0) = "1111") else '0';
+  int_rden_wire <= m_axi_wready and int_wvalid_reg;
+  tmp_s2 <= int_tready_wire and s_axis_tvalid;
+
+  reset <= not aresetn;
+
+  FIFO36E1_inst: FIFO36E1 
+  generic map(
+               FIRST_WORD_FALL_THROUGH => TRUE,
+               ALMOST_EMPTY_OFFSET => X"000F",
+               DATA_WIDTH => 72,
+               FIFO_MODE => "FIFO36_72"
+             ) 
+  port map (
+             ALMOSTEMPTY => int_empty_wire,
+             ALMOSTFULL  => open,
+             EMPTY       => open,
+             FULL        => int_full_wire,
+             DOP         => open,
+             DO          => int_wdata_wire,
+             INJECTDBITERR => '0', 
+             INJECTSBITERR => '0',
+             RDCLK       => aclk,
+             RDEN        => int_rden_wire,
+             REGCE       => '1',
+             RST         => reset,
+             RSTREG      => '0',
+             WRCLK       => aclk,
+             WREN        => tmp_s2,
+             DI          => s_axis_tdata,
+             DIP         => X"00"
+           );
+
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+      if (reset = '1') then
+        int_awvalid_reg <= '0';
+        int_wvalid_reg <= '0';
+        int_addr_reg <= (others => '0');
+        int_wid_reg <= (others => '0');
+      else
+        int_awvalid_reg <= int_awvalid_next;
+        int_wvalid_reg <= int_wvalid_next;
+        int_addr_reg <= int_addr_next;
+        int_wid_reg <= int_wid_next;
+      end if;
+    end if;
+  end process;
+
+  int_awvalid_next <= '1' when ((int_empty_wire = '0') and (int_awvalid_reg = '0') and (int_wvalid_reg = '0')) or 
+                      ((m_axi_wready = '1') and (int_wlast_wire = '1') and (int_empty_wire = '0')) else 
+                      '0' when ((m_axi_awready = '1') and (int_awvalid_reg = '1')) else
+                      int_awvalid_reg;
+
+  int_wvalid_next <= '1' when ((int_empty_wire = '0') and (int_awvalid_reg = '0') and (int_wvalid_reg = '0')) else 
+                     '0' when (m_axi_wready = '1') and (int_wlast_wire = '1') and (int_empty_wire = '1') else
+                     int_wvalid_reg;
+
+  int_addr_next <= int_addr_reg + 1 when (int_rden_wire = '1') else
+                   int_addr_reg;
+
+  int_wid_next <= int_wid_reg + 1 when (m_axi_wready = '1') and (int_wlast_wire = '1') else
+                  int_wid_reg;
+
+  sts_data      <= std_logic_vector(int_addr_reg);
+
+  m_axi_awid    <= std_logic_vector(int_wid_reg);
+  m_axi_awaddr  <= std_logic_vector(unsigned(cfg_data) + (int_addr_reg & (ADDR_SIZE-1 downto 0 => '0')));
+  m_axi_awlen   <= std_logic_vector(to_unsigned(15, m_axi_awlen'length));
+  m_axi_awsize  <= std_logic_vector(to_unsigned(ADDR_SIZE, m_axi_awsize'length));
+  m_axi_awburst <= "01";
+  m_axi_awcache <= "0011";
+  m_axi_awvalid <= int_awvalid_reg;
+  m_axi_wid     <= std_logic_vector(int_wid_reg);
+  m_axi_wdata   <= int_wdata_wire;
+  m_axi_wstrb   <= ((AXI_DATA_WIDTH/8-1) downto 0 => '1');
+  m_axi_wlast   <= int_wlast_wire;
+  m_axi_wvalid  <= int_wvalid_reg;
+  m_axi_bready  <= '1';
+
+  s_axis_tready <= int_tready_wire;
+
+end rtl;
diff --git a/cores/axis_ram_writer_v1_0/core_config.tcl b/cores/axis_ram_writer_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..ef4f457b07574795b08f2ae5cf1409e2667244f1
--- /dev/null
+++ b/cores/axis_ram_writer_v1_0/core_config.tcl
@@ -0,0 +1,28 @@
+set display_name {AXI4-Stream RAM Writer}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXI_DATA_WIDTH {AXI DATA WIDTH} {Width of the AXI data bus.}
+core_parameter AXI_ADDR_WIDTH {AXI ADDR WIDTH} {Width of the AXI address bus.}
+core_parameter AXI_ID_WIDTH {AXI ID WIDTH} {Width of the AXI ID bus.}
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter ADDR_WIDTH {ADDR WIDTH} {Width of the address.}
+
+set address [ipx::get_address_spaces m_axi -of_objects $core]
+set_property NAME M_AXI $address
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axi]
+set_property NAME M_AXI $bus
+set_property INTERFACE_MODE master $bus
+set_property MASTER_ADDRESS_SPACE_REF M_AXI $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXI:S_AXIS $parameter
diff --git a/cores/axis_rp_adc_v1_0/axis_rp_adc.vhd b/cores/axis_rp_adc_v1_0/axis_rp_adc.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..f82482587212ba79db04b7abd5bfa93268b888a9
--- /dev/null
+++ b/cores/axis_rp_adc_v1_0/axis_rp_adc.vhd
@@ -0,0 +1,57 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_rp_adc is
+  generic (
+  ADC_DATA_WIDTH : natural := 14;
+  AXIS_TDATA_WIDTH: natural := 32
+);
+port (
+  -- System signals
+  aclk : in std_logic;
+
+  -- ADC signals
+  adc_csn : out std_logic;
+  adc_dat_a : in std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+  adc_dat_b : in std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+
+  -- Master side
+  m_axis_tvalid : out std_logic;
+  m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0)
+);
+end axis_rp_adc;
+
+architecture rtl of axis_rp_adc is
+
+  constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH;
+
+  signal int_dat_a_reg : std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+  signal int_dat_b_reg : std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+  signal dat_a_tmp, dat_b_tmp : std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+
+begin
+
+  process(aclk)
+  begin
+  if rising_edge(aclk) then 
+    int_dat_a_reg <= adc_dat_a;
+    int_dat_b_reg <= adc_dat_b;
+  end if;
+  end process;
+
+  adc_csn <= '1';
+
+  m_axis_tvalid <= '1';
+
+  --Format conversion
+  dat_a_tmp(ADC_DATA_WIDTH-1) <= not int_dat_a_reg(ADC_DATA_WIDTH-1);
+  dat_a_tmp(ADC_DATA_WIDTH-2 downto 0) <=  int_dat_a_reg(ADC_DATA_WIDTH-2 downto 0);
+  dat_b_tmp(ADC_DATA_WIDTH-1) <= not int_dat_b_reg(ADC_DATA_WIDTH-1);
+  dat_b_tmp(ADC_DATA_WIDTH-2 downto 0) <=  int_dat_b_reg(ADC_DATA_WIDTH-2 downto 0);
+  
+  --padding to m_axis_tdata size
+  m_axis_tdata <= ((PADDING_WIDTH-1) downto 0 => dat_b_tmp(ADC_DATA_WIDTH-1)) & dat_b_tmp & ((PADDING_WIDTH-1) downto 0 => dat_a_tmp(ADC_DATA_WIDTH-1)) & dat_a_tmp;
+
+end rtl;
diff --git a/cores/axis_rp_adc_v1_0/core_config.tcl b/cores/axis_rp_adc_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..7b59ee3efed5d773344bb5fe2866051db7f7de42
--- /dev/null
+++ b/cores/axis_rp_adc_v1_0/core_config.tcl
@@ -0,0 +1,17 @@
+set display_name {AXI4-Stream Red Pitaya ADC v1.0}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+core_parameter ADC_DATA_WIDTH {ADC DATA WIDTH} {Width of the ADC data bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE M_AXIS $parameter
diff --git a/cores/axis_rp_adc_v3_0/axis_rp_adc.vhd b/cores/axis_rp_adc_v3_0/axis_rp_adc.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..9d80e8cf2bab177627ec4d96ee1adfe5fa88809b
--- /dev/null
+++ b/cores/axis_rp_adc_v3_0/axis_rp_adc.vhd
@@ -0,0 +1,57 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_rp_adc is
+  generic (
+  ADC_DATA_WIDTH : natural := 14;
+  AXIS_TDATA_WIDTH: natural := 32
+);
+port (
+  -- System signals
+  aclk : in std_logic;
+
+  -- ADC signals
+  adc_csn : out std_logic;
+  adc_dat_a : in std_logic_vector((AXIS_TDATA_WIDTH/2)-1 downto 0);
+  adc_dat_b : in std_logic_vector((AXIS_TDATA_WIDTH/2)-1 downto 0);
+
+  -- Master side
+  m_axis_tvalid : out std_logic;
+  m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0)
+);
+end axis_rp_adc;
+
+architecture rtl of axis_rp_adc is
+
+  constant PADDING_WIDTH : natural := AXIS_TDATA_WIDTH/2 - ADC_DATA_WIDTH;
+
+  signal int_dat_a_reg : std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+  signal int_dat_b_reg : std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+  signal dat_a_tmp, dat_b_tmp : std_logic_vector(ADC_DATA_WIDTH-1 downto 0);
+
+begin
+
+  process(aclk)
+  begin
+  if rising_edge(aclk) then 
+    int_dat_a_reg <= adc_dat_a(16-1 downto PADDING_WIDTH);
+    int_dat_b_reg <= adc_dat_b(16-1 downto PADDING_WIDTH);
+  end if;
+  end process;
+
+  adc_csn <= '1';
+
+  m_axis_tvalid <= '1';
+
+  --Format conversion
+  dat_a_tmp(ADC_DATA_WIDTH-1) <= int_dat_a_reg(ADC_DATA_WIDTH-1);
+  dat_a_tmp(ADC_DATA_WIDTH-2 downto 0) <=  not int_dat_a_reg(ADC_DATA_WIDTH-2 downto 0);
+  dat_b_tmp(ADC_DATA_WIDTH-1) <= int_dat_b_reg(ADC_DATA_WIDTH-1);
+  dat_b_tmp(ADC_DATA_WIDTH-2 downto 0) <=  not int_dat_b_reg(ADC_DATA_WIDTH-2 downto 0);
+  
+  --padding to m_axis_tdata size
+  m_axis_tdata <= ((PADDING_WIDTH-1) downto 0 => dat_b_tmp(ADC_DATA_WIDTH-1)) & dat_b_tmp & ((PADDING_WIDTH-1) downto 0 => dat_a_tmp(ADC_DATA_WIDTH-1)) & dat_a_tmp;
+
+end rtl;
diff --git a/cores/axis_rp_adc_v3_0/core_config.tcl b/cores/axis_rp_adc_v3_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..e01ad25776f5d08985e89ed780d049c99981bb10
--- /dev/null
+++ b/cores/axis_rp_adc_v3_0/core_config.tcl
@@ -0,0 +1,17 @@
+set display_name {AXI4-Stream Red Pitaya ADC v3.0}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+core_parameter ADC_DATA_WIDTH {ADC DATA WIDTH} {Width of the ADC data bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE M_AXIS $parameter
diff --git a/cores/axis_rp_dac_v1_0/axis_rp_dac.vhd b/cores/axis_rp_dac_v1_0/axis_rp_dac.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..8d08cd0a8c452ce6d47a57517a967baa92120946
--- /dev/null
+++ b/cores/axis_rp_dac_v1_0/axis_rp_dac.vhd
@@ -0,0 +1,80 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity axis_rp_dac is
+  generic (
+  DAC_DATA_WIDTH : natural := 14;
+  AXIS_TDATA_WIDTH: natural := 32
+);
+port (
+  -- PLL signals
+  aclk    : in std_logic;
+  ddr_clk : in std_logic;
+  locked  : in std_logic;
+
+  -- DAC signals
+  dac_clk : out std_logic;
+  dac_rst : out std_logic;
+  dac_sel : out std_logic;
+  dac_wrt : out std_logic;
+  dac_dat : out std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
+
+  -- Slave side
+  s_axis_tready : out std_logic;
+  s_axis_tvalid : in std_logic;
+  s_axis_tdata  : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0)
+);
+end axis_rp_dac;
+
+architecture rtl of axis_rp_dac is
+
+  signal int_dat_a_reg : std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
+  signal int_dat_b_reg : std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
+  signal int_rst_reg : std_logic;
+
+  signal int_dat_a_wire : std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
+  signal int_dat_b_wire : std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
+
+begin
+  int_dat_a_wire <= s_axis_tdata(DAC_DATA_WIDTH-1 downto 0);
+  int_dat_b_wire <= s_axis_tdata(AXIS_TDATA_WIDTH/2+DAC_DATA_WIDTH-1 downto AXIS_TDATA_WIDTH/2);
+
+  process(aclk)
+  begin
+  if rising_edge(aclk) then
+    if (locked = '0' or s_axis_tvalid = '0') then
+    int_dat_a_reg <= (others => '0');
+    int_dat_b_reg <= (others => '0');
+  else
+    int_dat_a_reg <= int_dat_a_wire(DAC_DATA_WIDTH-1) & not int_dat_a_wire(DAC_DATA_WIDTH-2 downto 0);
+    int_dat_b_reg <= int_dat_b_wire(DAC_DATA_WIDTH-1) & not int_dat_b_wire(DAC_DATA_WIDTH-2 downto 0);
+    int_rst_reg <= not locked or not s_axis_tvalid;
+  end if;
+  end if;
+  end process;
+
+  ODDR_rst: ODDR port map (Q => dac_rst, D1 => int_rst_reg, D2 => int_rst_reg, C => aclk, CE => '1', R => '0', S => '0');
+  ODDR_sel: ODDR port map (Q => dac_sel, D1 => '0', D2 => '1', C => aclk, CE => '1', R => '0', S => '0');
+  ODDR_wrt: ODDR port map (Q => dac_wrt, D1 => '0', D2 => '1', C => ddr_clk, CE => '1', R => '0', S => '0');
+  ODDR_clk: ODDR port map (Q => dac_clk, D1 => '0', D2 => '1', C => ddr_clk, CE => '1', R => '0', S => '0');
+  
+  DAC_DAT_inst: for j in 0 to DAC_DATA_WIDTH-1 generate
+  ODDR_inst: ODDR port map(
+    Q => dac_dat(j),
+    D1 => int_dat_a_reg(j),
+    D2 =>int_dat_b_reg(j),
+    C => aclk,
+    CE =>'1',
+    R => '0',
+    S => '0'
+    );
+  end generate;
+
+  s_axis_tready <= '1';
+	
+end rtl;
diff --git a/cores/axis_rp_dac_v1_0/core_config.tcl b/cores/axis_rp_dac_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..17b73fdc8b02691ff85529553472d6bfa34a7fdc
--- /dev/null
+++ b/cores/axis_rp_dac_v1_0/core_config.tcl
@@ -0,0 +1,17 @@
+set display_name {AXI4-Stream Red Pitaya DAC v1.0}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter DAC_DATA_WIDTH {DAC DATA WIDTH} {Width of the DAC data bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS $parameter
diff --git a/cores/axis_rp_dac_v2_0/axis_rp_dac.vhd b/cores/axis_rp_dac_v2_0/axis_rp_dac.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..c8975cca7fa1e47abb6b4356596e9ef5bdbefca5
--- /dev/null
+++ b/cores/axis_rp_dac_v2_0/axis_rp_dac.vhd
@@ -0,0 +1,81 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity axis_rp_dac is
+  generic (
+  DAC_DATA_WIDTH : natural := 14;
+  AXIS_TDATA_WIDTH: natural := 32
+);
+port (
+  -- PLL signals
+  aclk    : in std_logic;
+  ddr_clk : in std_logic;
+  wrt_clk : in std_logic;
+  locked  : in std_logic;
+
+  -- DAC signals
+  dac_clk : out std_logic;
+  dac_rst : out std_logic;
+  dac_sel : out std_logic;
+  dac_wrt : out std_logic;
+  dac_dat : out std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
+
+  -- Slave side
+  s_axis_tready : out std_logic;
+  s_axis_tvalid : in std_logic;
+  s_axis_tdata  : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0)
+);
+end axis_rp_dac;
+
+architecture rtl of axis_rp_dac is
+
+  signal int_dat_a_reg : std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
+  signal int_dat_b_reg : std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
+  signal int_rst_reg : std_logic;
+
+  signal int_dat_a_wire : std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
+  signal int_dat_b_wire : std_logic_vector(DAC_DATA_WIDTH-1 downto 0);
+
+begin
+  int_dat_a_wire <= s_axis_tdata(DAC_DATA_WIDTH-1 downto 0);
+  int_dat_b_wire <= s_axis_tdata(AXIS_TDATA_WIDTH/2+DAC_DATA_WIDTH-1 downto AXIS_TDATA_WIDTH/2);
+
+  process(aclk)
+  begin
+  if rising_edge(aclk) then
+    if (locked = '0' or s_axis_tvalid = '0') then
+    int_dat_a_reg <= (others => '0');
+    int_dat_b_reg <= (others => '0');
+  else
+    int_dat_a_reg <= int_dat_a_wire(DAC_DATA_WIDTH-1) & not int_dat_a_wire(DAC_DATA_WIDTH-2 downto 0);
+    int_dat_b_reg <= int_dat_b_wire(DAC_DATA_WIDTH-1) & not int_dat_b_wire(DAC_DATA_WIDTH-2 downto 0);
+    int_rst_reg <= not locked or not s_axis_tvalid;
+  end if;
+  end if;
+  end process;
+
+  ODDR_rst: ODDR port map (Q => dac_rst, D1 => int_rst_reg, D2 => int_rst_reg, C => aclk, CE => '1', R => '0', S => '0');
+  ODDR_sel: ODDR port map (Q => dac_sel, D1 => '0', D2 => '1', C => aclk, CE => '1', R => '0', S => '0');
+  ODDR_wrt: ODDR port map (Q => dac_wrt, D1 => '0', D2 => '1', C => wrt_clk, CE => '1', R => '0', S => '0');
+  ODDR_clk: ODDR port map (Q => dac_clk, D1 => '0', D2 => '1', C => ddr_clk, CE => '1', R => '0', S => '0');
+  
+  DAC_DAT_inst: for j in 0 to DAC_DATA_WIDTH-1 generate
+  ODDR_inst: ODDR port map(
+    Q => dac_dat(j),
+    D1 => int_dat_a_reg(j),
+    D2 =>int_dat_b_reg(j),
+    C => aclk,
+    CE =>'1',
+    R => '0',
+    S => '0'
+    );
+  end generate;
+
+  s_axis_tready <= '1';
+	
+end rtl;
diff --git a/cores/axis_rp_dac_v2_0/core_config.tcl b/cores/axis_rp_dac_v2_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..fac0868f6125d3f9b701571667639cedf19fc0f8
--- /dev/null
+++ b/cores/axis_rp_dac_v2_0/core_config.tcl
@@ -0,0 +1,17 @@
+set display_name {AXI4-Stream Red Pitaya DAC v2.0}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter DAC_DATA_WIDTH {DAC DATA WIDTH} {Width of the DAC data bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS $parameter
diff --git a/cores/axis_tlast_gen_v1_0/axis_tlast_gen.vhd b/cores/axis_tlast_gen_v1_0/axis_tlast_gen.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..512bf56d4e515daa445d2002b98b89946a52d065
--- /dev/null
+++ b/cores/axis_tlast_gen_v1_0/axis_tlast_gen.vhd
@@ -0,0 +1,67 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_tlast_gen is
+  generic (
+  AXIS_TDATA_WIDTH : natural := 8;
+  PKT_CNTR_BITS    : natural := 8 -- number of bits of the packet counter
+);
+port (
+  -- System signals
+  aclk          : in std_logic;
+  aresetn       : in std_logic;
+
+  -- Control signals
+  pkt_length    : in std_logic_vector((PKT_CNTR_BITS-1) downto 0);
+
+  -- Master side
+  m_axis_tvalid : out std_logic;
+  m_axis_tready : in std_logic;
+  m_axis_tlast  : out std_logic;
+  m_axis_tdata  : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+  -- Slave side
+  s_axis_tvalid : in std_logic;
+  s_axis_tready : out std_logic;
+  s_axis_tdata  : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0)
+);
+end axis_tlast_gen;
+
+architecture rtl of axis_tlast_gen is
+
+  -- Internal signals
+  signal new_sample  : std_logic;
+  signal cnt         : std_logic_vector((PKT_CNTR_BITS-1) downto 0) := (others => '0');
+  signal axis_tlast  : std_logic;
+  signal axis_tready : std_logic;
+begin
+
+  -- Pass through control signals
+  s_axis_tready <= m_axis_tready;
+  m_axis_tvalid <= s_axis_tvalid;
+  m_axis_tdata  <= s_axis_tdata;
+
+  axis_tready <= m_axis_tready;
+  -- Count samples
+  new_sample <= s_axis_tvalid and axis_tready;
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then 
+      if (aresetn = '0' or (axis_tlast = '1' and new_sample = '1')) then
+          cnt <= (others => '0');
+      else
+        if (new_sample = '1') then
+          cnt <= std_logic_vector(unsigned(cnt) + 1);
+        end if;
+      end if;
+    end if;
+  end process;
+
+  -- Generate tlast
+  axis_tlast <= '1' when (unsigned(cnt) = unsigned(unsigned(pkt_length)-1)) else '0';
+  m_axis_tlast <= axis_tlast;
+
+end rtl;
diff --git a/cores/axis_tlast_gen_v1_0/core_config.tcl b/cores/axis_tlast_gen_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..f82d26a2056a23b7abbaa3e5a8305def590ce528
--- /dev/null
+++ b/cores/axis_tlast_gen_v1_0/core_config.tcl
@@ -0,0 +1,22 @@
+set display_name {AXI4-Stream Tlast Generator}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+core_parameter PKT_CNTR_BITS    {PKT CNTR BITS} {Number of bits of the packet counter.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
+
diff --git a/cores/axis_trigger_v1_0/axis_trigger.vhd b/cores/axis_trigger_v1_0/axis_trigger.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..279b700cdaa3441e66ed84f54cc85a3c6f03a821
--- /dev/null
+++ b/cores/axis_trigger_v1_0/axis_trigger.vhd
@@ -0,0 +1,56 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_trigger is
+  generic (
+            AXIS_TDATA_WIDTH : natural := 32;
+            AXIS_TDATA_SIGNED : string := "FALSE"
+          );
+  port (
+         -- System signals
+         aclk         : in std_logic;
+
+         pol_data     : in std_logic;
+         msk_data     : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         lvl_data     : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+         trg_flag     : out std_logic;
+
+         -- Slave side
+         s_axis_tready: out std_logic;
+         s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         s_axis_tvalid: in std_logic
+       );
+end axis_trigger;
+
+architecture rtl of axis_trigger is
+
+  signal int_comp_reg : std_logic_vector(1 downto 0);
+  signal int_comp_wire: std_logic;
+
+begin
+
+  SIGNED_G: if (AXIS_TDATA_SIGNED = "TRUE") generate
+    int_comp_wire <= '1' when signed(s_axis_tdata and msk_data) >= signed(lvl_data) else '0';
+  end generate;
+
+  UNSIGNED_G: if (AXIS_TDATA_SIGNED = "FALSE") generate
+    int_comp_wire <= '1' when unsigned(s_axis_tdata and msk_data) >= unsigned(lvl_data) else '0';
+  end generate;
+
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+      if (s_axis_tvalid = '1') then
+        int_comp_reg <= int_comp_reg(0) & int_comp_wire;
+      end if;
+    end if;
+  end process;
+
+  s_axis_tready <= '1';
+
+  trg_flag <= s_axis_tvalid and (pol_data xor int_comp_reg(0)) and (pol_data xor not(int_comp_reg(1)));
+
+end rtl;
diff --git a/cores/axis_trigger_v1_0/core_config.tcl b/cores/axis_trigger_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..724c2c428a4ab9f45a8691d889b0ce48b2d8307d
--- /dev/null
+++ b/cores/axis_trigger_v1_0/core_config.tcl
@@ -0,0 +1,17 @@
+set display_name {AXI4-Stream Trigger}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the S_AXIS data bus.}
+core_parameter AXIS_TDATA_SIGNED {AXIS_TDATA_SIGNED} {If TRUE, the S_AXIS data are signed values.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE S_AXIS $parameter
diff --git a/cores/axis_validator_v1_0/axis_validator.vhd b/cores/axis_validator_v1_0/axis_validator.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..606ae7ab08f4c32fe592c410ca14256393896720
--- /dev/null
+++ b/cores/axis_validator_v1_0/axis_validator.vhd
@@ -0,0 +1,35 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_validator is
+  generic (
+            AXIS_TDATA_WIDTH  : natural := 32
+          );
+  port (
+         -- System signals
+         aclk             : in std_logic;
+         trg_flag         : in std_logic;
+
+         -- Slave side
+         s_axis_tready    : out std_logic;
+         s_axis_tdata     : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         s_axis_tvalid    : in std_logic;
+
+         -- Master side
+         m_axis_tready    : in std_logic;
+         m_axis_tdata     : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+         m_axis_tvalid    : out std_logic
+       );
+end axis_validator;
+
+architecture rtl of axis_validator is
+
+begin
+
+  s_axis_tready <= m_axis_tready;
+  m_axis_tdata  <= s_axis_tdata;
+  m_axis_tvalid <= '1' when ((s_axis_tvalid = '1') and (trg_flag = '1')) else
+                   '0';
+end rtl;
diff --git a/cores/axis_validator_v1_0/core_config.tcl b/cores/axis_validator_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..5b57b3df950ec3fc61d4b14198c746ec80a0ae8b
--- /dev/null
+++ b/cores/axis_validator_v1_0/core_config.tcl
@@ -0,0 +1,20 @@
+set display_name {AXI4-Stream Validator}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS and S_AXIS data buses.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
diff --git a/cores/axis_variable_v1_0/axis_variable.vhd b/cores/axis_variable_v1_0/axis_variable.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..b79e1dbc311d405df27e86c18e40eeadbb6fe37f
--- /dev/null
+++ b/cores/axis_variable_v1_0/axis_variable.vhd
@@ -0,0 +1,51 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_variable is
+  generic (
+  AXIS_TDATA_WIDTH: natural := 32
+);
+port (
+  -- System signals
+  aclk : in std_logic;
+  aresetn : in std_logic;
+
+  cfg_data : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+
+  -- Master side
+  m_axis_tready : in std_logic;
+  m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  m_axis_tvalid : out std_logic
+);
+end axis_variable;
+
+architecture rtl of axis_variable is
+
+  signal int_tdata_reg : std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  signal int_tvalid_reg, int_tvalid_next: std_logic;
+
+begin
+
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if(aresetn = '0') then
+      int_tdata_reg <= (others => '0');
+      int_tvalid_reg <= '0';
+    else
+      int_tdata_reg <= cfg_data;
+      int_tvalid_reg <= int_tvalid_next;
+    end if;
+    end if;
+  end process;
+
+  int_tvalid_next <= '1' when (int_tdata_reg /= cfg_data) else
+                     '0' when (m_axis_tready = '1') and (int_tvalid_reg = '1') else
+                     int_tvalid_reg;        
+
+  m_axis_tdata <= int_tdata_reg;
+  m_axis_tvalid <= int_tvalid_reg;
+
+end rtl;
diff --git a/cores/axis_variable_v1_0/core_config.tcl b/cores/axis_variable_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..70ffb5a860eb8bdd574d685dd4c4a105ae042592
--- /dev/null
+++ b/cores/axis_variable_v1_0/core_config.tcl
@@ -0,0 +1,16 @@
+set display_name {AXI4-Stream Variable}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS $parameter
diff --git a/cores/axis_zero_crossing_det_v1_0/axis_zero_crossing_det.vhd b/cores/axis_zero_crossing_det_v1_0/axis_zero_crossing_det.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..cd49b7b5ea9f7ed2a5dc17869af51572e115de14
--- /dev/null
+++ b/cores/axis_zero_crossing_det_v1_0/axis_zero_crossing_det.vhd
@@ -0,0 +1,99 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity zero_cross_det is
+generic (
+  HYST_CONST      : natural := 2048; --"00100000000000"
+  AXIS_TDATA_WIDTH: natural := 32
+);
+port (
+  aclk    : in std_logic;
+  aresetn : in std_logic;
+
+  det_a_o : out std_logic;
+  det_b_o : out std_logic;
+
+ -- Slave side
+  s_axis_tready: out std_logic;
+  s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0)
+);
+end zero_cross_det;
+
+architecture rtl of zero_cross_det is
+
+signal sig_a_reg, sig_a_next: std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+signal sig_b_reg, sig_b_next: std_logic_vector(AXIS_TDATA_WIDTH/2-1 downto 0);
+signal det_a_o_reg, det_a_o_next: std_logic;
+signal det_b_o_reg, det_b_o_next: std_logic;
+signal hyst_a_low_reg, hyst_a_low_next  : std_logic;
+signal hyst_a_high_reg, hyst_a_high_next : std_logic;
+signal hyst_b_low_reg, hyst_b_low_next  : std_logic;
+signal hyst_b_high_reg, hyst_b_high_next : std_logic;
+
+begin
+
+  process(aclk)
+  begin
+  if rising_edge(aclk) then
+    if aresetn = '0' then
+      sig_a_reg <= (others => '0');
+      det_a_o_reg <= '0';
+      hyst_a_low_reg <= '0';
+      hyst_a_high_reg <= '0';
+
+      sig_b_reg <= (others => '0');
+      det_b_o_reg <= '0';
+      hyst_b_low_reg <= '0';
+      hyst_b_high_reg <= '0';
+    else
+      sig_a_reg <= sig_a_next;
+      det_a_o_reg <= det_a_o_next;
+      hyst_a_low_reg <= hyst_a_low_next;
+      hyst_a_high_reg <= hyst_a_high_next;
+
+      sig_b_reg <= sig_b_next;
+      det_b_o_reg <= det_b_o_next;
+      hyst_b_low_reg <= hyst_b_low_next;
+      hyst_b_high_reg <= hyst_b_high_next;
+    end if;
+  end if;
+  end process;
+
+  --Next state logic
+  sig_a_next <= s_axis_tdata(AXIS_TDATA_WIDTH/2-1 downto 0);
+  
+  det_a_o_next <= '1' when (sig_a_reg(sig_a_reg'left) = '1' and sig_a_next(sig_a_next'left) = '0' and hyst_a_low_reg = '1') else
+                '0' when (sig_a_reg(sig_a_reg'left) = '0' and sig_a_next(sig_a_next'left) = '1' and hyst_a_high_reg = '1') else
+                det_a_o_reg;
+  
+  hyst_a_low_next  <= '1' when (signed(sig_a_next) < (to_signed(-HYST_CONST, AXIS_TDATA_WIDTH/2))) else 
+                    '0' when (sig_a_reg(sig_a_reg'left) = '1' and sig_a_next(sig_a_next'left) = '0' and hyst_a_low_reg = '1') else
+                    hyst_a_low_reg;
+  
+  hyst_a_high_next <= '1' when (signed(sig_a_next) > (to_signed(HYST_CONST, AXIS_TDATA_WIDTH/2))) else
+                    '0' when (sig_a_reg(sig_a_reg'left) = '0' and sig_a_next(sig_a_next'left) = '1' and hyst_a_high_reg = '1') else
+                    hyst_a_high_reg;
+  
+  det_a_o <= det_a_o_reg;
+  
+  sig_b_next <= s_axis_tdata(AXIS_TDATA_WIDTH-1 downto AXIS_TDATA_WIDTH/2);
+  
+  det_b_o_next <= '1' when (sig_b_reg(sig_b_reg'left) = '1' and sig_b_next(sig_b_next'left) = '0' and hyst_b_low_reg = '1') else
+                '0' when (sig_b_reg(sig_b_reg'left) = '0' and sig_b_next(sig_b_next'left) = '1' and hyst_b_high_reg = '1') else
+                det_b_o_reg;
+  
+  hyst_b_low_next  <= '1' when (signed(sig_b_next) < (to_signed(-HYST_CONST, AXIS_TDATA_WIDTH/2))) else 
+                    '0' when (sig_b_reg(sig_b_reg'left) = '1' and sig_b_next(sig_b_next'left) = '0' and hyst_b_low_reg = '1') else
+                    hyst_b_low_reg;
+  
+  hyst_b_high_next <= '1' when (signed(sig_b_next) > (to_signed(HYST_CONST, AXIS_TDATA_WIDTH/2))) else
+                    '0' when (sig_b_reg(sig_b_reg'left) = '0' and sig_b_next(sig_b_next'left) = '1' and hyst_b_high_reg = '1') else
+                    hyst_b_high_reg;
+  
+  det_b_o <= det_b_o_reg;
+
+
+  s_axis_tready <= '1';
+
+end rtl;
diff --git a/cores/axis_zero_crossing_det_v1_0/core_config.tcl b/cores/axis_zero_crossing_det_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..ebd926fca81801ba96ca83b9af28d30ef1234bcc
--- /dev/null
+++ b/cores/axis_zero_crossing_det_v1_0/core_config.tcl
@@ -0,0 +1,17 @@
+set display_name {AXI4-Stream Zero Crossing Detector}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS data bus.}
+core_parameter HYST_CONST {HYSTERISIS CONSTANT} {Hysterisis constant.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE S_AXIS $parameter
diff --git a/cores/axis_zeroer_v1_0/axis_zeroer.vhd b/cores/axis_zeroer_v1_0/axis_zeroer.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..01f42c0f4f99b00ba987dc57eb11ab70747c2aa7
--- /dev/null
+++ b/cores/axis_zeroer_v1_0/axis_zeroer.vhd
@@ -0,0 +1,34 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_zeroer is
+  generic (
+    AXIS_TDATA_WIDTH: natural := 32
+);
+port (
+  -- System signals
+  aclk : in std_logic;
+
+  -- Slave side
+  s_axis_tready: out std_logic;
+  s_axis_tdata : in std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  s_axis_tvalid: in std_logic;
+
+  -- Master side
+  m_axis_tready : in std_logic;
+  m_axis_tdata : out std_logic_vector(AXIS_TDATA_WIDTH-1 downto 0);
+  m_axis_tvalid : out std_logic
+);
+end axis_zeroer;
+
+architecture rtl of axis_zeroer is
+
+begin
+
+  s_axis_tready <= m_axis_tready;
+  m_axis_tdata <= s_axis_tdata when (s_axis_tvalid = '1') else (others => '0');
+  m_axis_tvalid <= '1';
+
+end rtl;
diff --git a/cores/axis_zeroer_v1_0/core_config.tcl b/cores/axis_zeroer_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..6074dff78ffe33c848380b3c6df9fcf52c1392e2
--- /dev/null
+++ b/cores/axis_zeroer_v1_0/core_config.tcl
@@ -0,0 +1,20 @@
+set display_name {AXI4-Stream Zeroer}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter AXIS_TDATA_WIDTH {AXIS TDATA WIDTH} {Width of the M_AXIS and S_AXIS data buses.}
+
+set bus [ipx::get_bus_interfaces -of_objects $core m_axis]
+set_property NAME M_AXIS $bus
+set_property INTERFACE_MODE master $bus
+
+set bus [ipx::get_bus_interfaces -of_objects $core s_axis]
+set_property NAME S_AXIS $bus
+set_property INTERFACE_MODE slave $bus
+
+set bus [ipx::get_bus_interfaces aclk]
+set parameter [ipx::get_bus_parameters -of_objects $bus ASSOCIATED_BUSIF]
+set_property VALUE M_AXIS:S_AXIS $parameter
diff --git a/cores/bram_counter_v1_0/bram_counter.vhd b/cores/bram_counter_v1_0/bram_counter.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..432426e3b9053adceecdacd5967752b007d2284c
--- /dev/null
+++ b/cores/bram_counter_v1_0/bram_counter.vhd
@@ -0,0 +1,77 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity bram_counter is
+				generic (
+												BRAM_DATA_WIDTH : natural := 32;
+												BRAM_ADDR_WIDTH : natural := 14
+								);
+				port (
+										 -- System signals
+										 aclk              : in std_logic;
+										 aresetn           : in std_logic;
+
+										 cfg_data           : in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+
+										 -- BRAM port
+										 bram_porta_clk    : out std_logic;
+										 bram_porta_rst    : out std_logic;
+										 bram_porta_addr   : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+										 bram_porta_wrdata : out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+										 bram_porta_rddata : in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+										 bram_porta_we     : out std_logic
+						 );
+
+end bram_counter;
+
+architecture rtl of bram_counter is
+
+				signal cntr_reg, cntr_next   : unsigned(BRAM_DATA_WIDTH-1 downto 0);
+				signal comp_reg, comp_next   : std_logic;
+				signal addr_reg, addr_next   : unsigned(BRAM_ADDR_WIDTH-1 downto 0);
+				signal wren_reg, wren_next   : std_logic;
+
+
+begin
+
+				bram_porta_clk    <= aclk;
+				bram_porta_rst    <= not aresetn;
+				bram_porta_addr   <= std_logic_vector(addr_reg);
+				bram_porta_wrdata <= std_logic_vector(cntr_reg);
+				bram_porta_we     <= wren_reg;
+
+				process(aclk)
+				begin
+								if (rising_edge(aclk)) then
+												if(aresetn = '0') then
+																addr_reg <= (others => '0');
+																cntr_reg <= (others => '0');
+																comp_reg <= '0';
+																wren_reg <= '0';
+												else
+																addr_reg <= addr_next;
+																cntr_reg <= cntr_next;
+																comp_reg <= comp_next;
+																wren_reg <= wren_next;
+												end if;
+								end if;
+				end process;
+
+				wren_next <= '0' when (cntr_reg = unsigned(cfg_data)-1) else
+										 '1';
+
+				comp_next <= '0' when (cntr_reg = unsigned(cfg_data)-1) else 
+										 '1';
+
+				addr_next <= addr_reg + 1 when (comp_reg = '1') else
+										 (others => '0') when (comp_reg = '0') else --reset
+										 addr_reg;
+
+				cntr_next <= cntr_reg + 1 when (comp_reg = '1') else
+										 (others => '0') when (comp_reg = '0') else --reset
+										 cntr_reg;
+
+		
+end rtl;
diff --git a/cores/bram_counter_v1_0/core_config.tcl b/cores/bram_counter_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..ae4bc7225bf5859613900749140ce006c4242c15
--- /dev/null
+++ b/cores/bram_counter_v1_0/core_config.tcl
@@ -0,0 +1,29 @@
+set display_name {BRAM Counter}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter BRAM_DATA_WIDTH {BRAM DATA WIDTH} {Width of the BRAM data port.}
+core_parameter BRAM_ADDR_WIDTH {BRAM ADDR WIDTH} {Width of the BRAM address port.}
+
+set bus [ipx::add_bus_interface BRAM_PORTA $core]
+set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus
+set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus
+set_property INTERFACE_MODE master $bus
+foreach {logical physical} {
+  RST  bram_porta_rst
+  CLK  bram_porta_clk
+  ADDR bram_porta_addr
+  DIN  bram_porta_wrdata
+  DOUT bram_porta_rddata
+  WE   bram_porta_we
+} {
+  set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus]
+}
+
+set bus [ipx::get_bus_interfaces bram_porta_clk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE BRAM_PORTA $parameter
+
diff --git a/cores/bram_selector_v1_0/bram_selector.vhd b/cores/bram_selector_v1_0/bram_selector.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..0b1c18bf6489a201e8c3eafeabd79b017eda8c75
--- /dev/null
+++ b/cores/bram_selector_v1_0/bram_selector.vhd
@@ -0,0 +1,69 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity axis_bram_sel is
+  generic (
+            BRAM_DATA_WIDTH    : natural := 32;
+            BRAM_ADDR_WIDTH    : natural := 14  -- 2^11 = 2048 positions
+          );
+  port (
+         -- System signals
+         aclk             : in std_logic;
+
+         sel              : in std_logic;
+
+         -- BRAM PORT A
+         bram_porta_clk   : in std_logic;
+         bram_porta_rst   : in std_logic;
+         bram_porta_addr  : in std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+         bram_porta_wrdata: in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+         bram_porta_rddata: out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+         bram_porta_we    : in std_logic;
+
+         -- BRAM PORT B
+         bram_portb_clk   : in std_logic;
+         bram_portb_rst   : in std_logic;
+         bram_portb_addr  : in std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+         bram_portb_wrdata: in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+         bram_portb_rddata: out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+         bram_portb_we    : in std_logic;
+
+         -- BRAM PORT C
+         bram_portc_clk   : out std_logic;
+         bram_portc_rst   : out std_logic;
+         bram_portc_addr  : out std_logic_vector(BRAM_ADDR_WIDTH-1 downto 0);
+         bram_portc_wrdata: out std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+         bram_portc_rddata: in std_logic_vector(BRAM_DATA_WIDTH-1 downto 0);
+         bram_portc_we    : out std_logic
+       );
+end axis_bram_sel;
+
+architecture rtl of axis_bram_sel is
+
+begin
+
+  bram_portc_rst    <= bram_porta_rst when (sel = '1') else
+                       bram_portb_rst;
+  bram_portc_addr   <= bram_porta_addr when (sel = '1') else
+                       bram_portb_addr;
+  bram_portc_wrdata <= bram_porta_wrdata when (sel = '1') else
+                       bram_portb_wrdata;
+  bram_portc_we     <= bram_porta_we when (sel = '1') else 
+                       bram_portb_we;
+
+  bram_porta_rddata <= bram_portc_rddata when (sel = '1') else
+                       (others => '0');
+  bram_portb_rddata <= bram_portc_rddata when (sel = '0') else
+                       (others => '0');
+
+  BUFGMUX_inst: BUFGMUX 
+  port map (
+             O  => bram_portc_clk, -- 1-bit output: Clock output
+             I0 => bram_portb_clk, -- 1-bit input: Clock input (S=0)
+             I1 => bram_porta_clk, -- 1-bit input: Clock input (S=1)
+             S  => sel             -- 1-bit input: Clock select
+           );
+
+end rtl;
diff --git a/cores/bram_selector_v1_0/core_config.tcl b/cores/bram_selector_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..eda9171b4473dd6da0820fd97b29cdaeaa8c8998
--- /dev/null
+++ b/cores/bram_selector_v1_0/core_config.tcl
@@ -0,0 +1,66 @@
+set display_name {BRAM Selector}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter BRAM_DATA_WIDTH {BRAM DATA WIDTH} {Width of the BRAM data port.}
+core_parameter BRAM_ADDR_WIDTH {BRAM ADDR WIDTH} {Width of the BRAM address port.}
+
+set bus [ipx::add_bus_interface BRAM_PORTA $core]
+set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus
+set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus
+set_property INTERFACE_MODE slave $bus
+foreach {logical physical} {
+  RST  bram_porta_rst
+  CLK  bram_porta_clk
+  ADDR bram_porta_addr
+  DIN  bram_porta_wrdata
+  DOUT bram_porta_rddata
+  WE   bram_porta_we
+} {
+  set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus]
+}
+
+set bus [ipx::get_bus_interfaces bram_porta_clk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE BRAM_PORTA $parameter
+
+set bus [ipx::add_bus_interface BRAM_PORTB $core]
+set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus
+set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus
+set_property INTERFACE_MODE slave $bus
+foreach {logical physical} {
+  RST  bram_portb_rst
+  CLK  bram_portb_clk
+  ADDR bram_portb_addr
+  DIN  bram_portb_wrdata
+  DOUT bram_portb_rddata
+  WE   bram_portb_we
+} {
+  set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus]
+}
+
+set bus [ipx::get_bus_interfaces bram_portb_clk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE BRAM_PORTB $parameter
+
+set bus [ipx::add_bus_interface BRAM_PORTC $core]
+set_property ABSTRACTION_TYPE_VLNV xilinx.com:interface:bram_rtl:1.0 $bus
+set_property BUS_TYPE_VLNV xilinx.com:interface:bram:1.0 $bus
+set_property INTERFACE_MODE master $bus
+foreach {logical physical} {
+  RST  bram_portc_rst
+  CLK  bram_portc_clk
+  ADDR bram_portc_addr
+  DIN  bram_portc_wrdata
+  DOUT bram_portc_rddata
+  WE   bram_portc_we
+} {
+  set_property PHYSICAL_NAME $physical [ipx::add_port_map $logical $bus]
+}
+
+set bus [ipx::get_bus_interfaces bram_portc_clk]
+set parameter [ipx::add_bus_parameter ASSOCIATED_BUSIF $bus]
+set_property VALUE BRAM_PORTB $parameter
diff --git a/cores/dc_removal_v1_0/core_config.tcl b/cores/dc_removal_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..b6d4f20b1d14950e57e94777fe5523cfd0965765
--- /dev/null
+++ b/cores/dc_removal_v1_0/core_config.tcl
@@ -0,0 +1,8 @@
+set display_name {Digital DC removal circuit}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter DATA_WIDTH {DATA WIDTH} {Width of the data bus.}
diff --git a/cores/dc_removal_v1_0/dc_removal.vhd b/cores/dc_removal_v1_0/dc_removal.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..bc0b25f1586c83d8d50e8127b1722e18469f3fed
--- /dev/null
+++ b/cores/dc_removal_v1_0/dc_removal.vhd
@@ -0,0 +1,92 @@
+-- See WP279 from Xilinx
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity dc_removal is
+				generic(
+											 DATA_WIDTH : integer := 16
+							 );
+				port (
+										 aclk    : in std_logic;
+										 aresetn : in std_logic;
+										 k_i     : in std_logic_vector(DATA_WIDTH-1 downto 0);
+										 data_i  : in std_logic_vector(DATA_WIDTH-1 downto 0);
+										 data_o  : out std_logic_vector(DATA_WIDTH-1 downto 0)
+						 );
+end dc_removal;
+
+architecture rtl of dc_removal is
+				signal k_reg, k_next     : std_logic_vector(DATA_WIDTH-1 downto 0);
+				signal d0_reg, d0_next   : std_logic_vector(DATA_WIDTH-1 downto 0);
+				signal d11_reg, d11_next : std_logic_vector(DATA_WIDTH-1 downto 0);
+				signal d12_reg, d12_next : std_logic_vector(DATA_WIDTH-1 downto 0);
+				signal d21_reg, d21_next : std_logic_vector(DATA_WIDTH-1 downto 0);
+				signal d22_reg, d22_next : std_logic_vector(2*DATA_WIDTH-1 downto 0);
+				signal d31_reg, d31_next : std_logic_vector(DATA_WIDTH-1 downto 0);
+				signal d32_reg, d32_next : std_logic_vector(2*DATA_WIDTH-1 downto 0);
+				signal d4_reg, d4_next   : std_logic_vector(DATA_WIDTH-1 downto 0);
+				signal mult_s            : std_logic_vector(2*DATA_WIDTH-1 downto 0);
+				signal sub_s             : std_logic_vector(DATA_WIDTH-1 downto 0);
+				signal sub2_s            : std_logic_vector(DATA_WIDTH-1 downto 0);
+				signal data_fbk          : std_logic_vector(DATA_WIDTH-1 downto 0);
+
+begin
+
+				process(aclk)
+				begin
+								if rising_edge(aclk) then
+												if aresetn = '0' then
+																k_reg   <= (others => '0');     
+																d0_reg  <= (others => '0');     
+																d11_reg <= (others => '0');     
+																d12_reg <= (others => '0');     
+																d21_reg <= (others => '0');     
+																d22_reg <= (others => '0');     
+																d31_reg <= (others => '0');     
+																d32_reg <= (others => '0');     
+																d4_reg  <= (others => '0');     
+												else
+																k_reg   <= k_next;
+																d0_reg  <= d0_next;
+																d11_reg <= d11_next;
+																d12_reg <= d12_next;
+																d21_reg <= d21_next;
+																d22_reg <= d22_next;
+																d31_reg <= d31_next;
+																d32_reg <= d32_next;
+																d4_reg  <= d4_next;
+												end if;
+								end if;
+				end process;
+
+				k_next <= k_i;
+
+				d0_next <= data_i;
+
+				d11_next <= d0_reg;
+
+				sub_s <= std_logic_vector(signed(d0_reg) - signed(data_fbk));
+
+				d12_next <= sub_s; 
+
+				d21_next <= d11_reg; 
+
+				mult_s <= std_logic_vector(signed(k_reg) * signed(d12_reg));
+
+				d22_next <= mult_s;
+
+				d31_next <= d21_reg; 
+
+				d32_next <= std_logic_vector(signed(d32_reg) + signed(d22_reg));
+
+				data_fbk <= d32_reg(2*DATA_WIDTH-1 downto DATA_WIDTH);
+
+				sub2_s <= std_logic_vector(signed(d31_reg) - signed(data_fbk));
+
+				d4_next <= sub2_s;
+
+				data_o <= d4_reg;
+
+end rtl;     
diff --git a/cores/dna_reader_v1_0/core_config.tcl b/cores/dna_reader_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..072eb85645e01f74bdb1881665b57d3ad07fe74d
--- /dev/null
+++ b/cores/dna_reader_v1_0/core_config.tcl
@@ -0,0 +1,6 @@
+set display_name {DNA Reader}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
diff --git a/cores/dna_reader_v1_0/dna_reader.vhd b/cores/dna_reader_v1_0/dna_reader.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..9aa89306f26a99e36840fb901b4a1e7e7d106dd5
--- /dev/null
+++ b/cores/dna_reader_v1_0/dna_reader.vhd
@@ -0,0 +1,81 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity dna_reader is
+port (
+  aclk 		: in std_logic;
+  aresetn 	: in std_logic;
+
+  dna_data 	: out std_logic_vector(56 downto 0)
+);
+end dna_reader;
+
+architecture rtl of dna_reader is
+
+  constant CNTR_WIDTH : integer := 16;
+  constant DATA_WIDTH : integer := 57;
+
+  signal int_enbl_reg, int_enbl_next : std_logic;
+  signal int_read_reg, int_read_next: std_logic;
+  signal int_shift_reg, int_shift_next : std_logic;
+  signal int_cntr_reg, int_cntr_next: unsigned(CNTR_WIDTH-1 downto 0);
+  signal int_data_reg, int_data_next: std_logic_vector(DATA_WIDTH-1 downto 0);
+  signal int_comp_wire, int_data_wire: std_logic;
+
+begin
+
+  int_comp_wire <= '1' when (int_cntr_reg < 64*DATA_WIDTH) else '0';
+
+  dna_0: DNA_PORT
+   port map (
+      DOUT => int_data_wire,
+      CLK => int_cntr_reg(5),
+      DIN => '0',    
+      READ => int_read_reg,  
+      SHIFT => int_shift_reg
+   );
+
+  process(aclk)
+  begin
+    if rising_edge(aclk) then
+    if(aresetn = '0') then
+      int_enbl_reg <= '0';
+      int_read_reg <= '0';
+      int_shift_reg <= '0';
+      int_cntr_reg <= (others => '0');
+      int_data_reg <= (others => '0');
+    else
+      int_enbl_reg <= int_enbl_next;
+      int_read_reg <= int_read_next;
+      int_shift_reg <= int_shift_next;
+      int_cntr_reg <= int_cntr_next;
+      int_data_reg <= int_data_next;
+    end if;
+    end if;
+  end process;
+
+  int_enbl_next <= '1' when (int_enbl_reg = '0') and (int_comp_wire = '1') else 
+                   '0' when (int_comp_wire = '0') else
+		     	         int_enbl_reg;
+
+  int_read_next <= '1' when (int_enbl_reg = '0') and (int_comp_wire = '1') else
+                   '0' when (int_cntr_reg(5 downto 0) = "111111") else
+                   int_read_reg;
+
+  int_data_next <= int_data_reg(DATA_WIDTH-2 downto 0) & int_data_wire when (int_cntr_reg(5 downto 0) = "111111") else
+                   int_data_reg;
+
+  int_cntr_next <= int_cntr_reg + 1 when (int_enbl_reg = '1') else int_cntr_reg;
+
+  int_shift_next <= '0' when (int_comp_wire = '0') else 
+                    '1' when (int_cntr_reg(5 downto 0) = "111111") else 
+                    int_shift_reg;
+
+  dna_data <= int_data_reg;
+
+end rtl;
diff --git a/cores/int_counter_v1_0/core_config.tcl b/cores/int_counter_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..e74d0bf1dca1ce66b65a02df052483b506ad685b
--- /dev/null
+++ b/cores/int_counter_v1_0/core_config.tcl
@@ -0,0 +1,7 @@
+set display_name {Interrupt Generator}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
diff --git a/cores/int_counter_v1_0/int_counter.vhd b/cores/int_counter_v1_0/int_counter.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..e483a9dc36cf98541881092ebe63463b8617de4d
--- /dev/null
+++ b/cores/int_counter_v1_0/int_counter.vhd
@@ -0,0 +1,38 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity int_counter is
+  port (
+    aclk    : in  std_logic;
+    aresetn : in  std_logic;
+    int_o   : out std_logic
+    );
+end int_counter;
+
+architecture rtl of int_counter is
+
+  signal counter_reg, counter_next  : std_logic_vector(30-1 downto 0);
+  signal int_reg, int_next          : std_logic;
+
+begin
+
+ process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn = '0') then
+        counter_reg <= (others => '0');
+        int_reg <= '0';
+      else
+        counter_reg <= counter_next;
+        int_reg <= int_next;
+      end if;
+    end if;
+  end process;
+  
+  counter_next <= std_logic_vector(unsigned(counter_reg) + 1);
+  int_next <= '1' when (unsigned(counter_reg) = 0) or (unsigned(counter_reg) = 1) or (unsigned(counter_reg) = 2) else '0';
+ 
+  int_o <= int_reg;
+
+end rtl;
diff --git a/cores/port_selector_v1_0/core_config.tcl b/cores/port_selector_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..bc9e8a6ae4ebff2ef54d72d22f6cf0bee588393a
--- /dev/null
+++ b/cores/port_selector_v1_0/core_config.tcl
@@ -0,0 +1,8 @@
+set display_name {Port Selector}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter DOUT_WIDTH {DOUT WIDTH} {Width of the output port.}
diff --git a/cores/port_selector_v1_0/port_selector.vhd b/cores/port_selector_v1_0/port_selector.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..2f1ff77d0a2b2e4c0db83821522be2445363284c
--- /dev/null
+++ b/cores/port_selector_v1_0/port_selector.vhd
@@ -0,0 +1,30 @@
+library ieee;
+  
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity port_selector is
+generic(
+  DOUT_WIDTH : integer := 32
+);
+port (
+  cfg     : in std_logic;
+  din     : in std_logic_vector(2*DOUT_WIDTH-1 downto 0);
+  dout    : out std_logic_vector(DOUT_WIDTH-1 downto 0)
+  );
+end port_selector;
+
+architecture rtl of port_selector is
+
+begin
+
+				process(cfg)
+				begin
+								if cfg = '1' then
+												dout <= din(2*DOUT_WIDTH-1 downto DOUT_WIDTH);
+								else
+												dout <= din(DOUT_WIDTH-1 downto 0);
+								end if;
+				end process;
+
+end rtl;
diff --git a/cores/port_slicer_v1_0/core_config.tcl b/cores/port_slicer_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..500225d0f778825d4f6890f40ac162dd54804489
--- /dev/null
+++ b/cores/port_slicer_v1_0/core_config.tcl
@@ -0,0 +1,10 @@
+set display_name {Port Slicer}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter DIN_WIDTH {DIN WIDTH} {Width of the input port.}
+core_parameter DIN_FROM {DIN FROM} {Index of the highest selected bit.}
+core_parameter DIN_TO {DIN TO} {Index of the lowest selected bit.}
diff --git a/cores/port_slicer_v1_0/port_slicer.vhd b/cores/port_slicer_v1_0/port_slicer.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..b0159258a79f0c5bb90bac1f08283d151a16aadb
--- /dev/null
+++ b/cores/port_slicer_v1_0/port_slicer.vhd
@@ -0,0 +1,23 @@
+library ieee;
+  
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity port_slicer is
+generic(
+  DIN_WIDTH : integer := 32;
+  DIN_FROM  : integer := 31;
+  DIN_TO    : integer := 0
+);
+port (
+  din     : in std_logic_vector(DIN_WIDTH-1 downto 0);
+  dout    : out std_logic_vector(DIN_FROM-DIN_TO downto 0)
+  );
+end port_slicer;
+
+architecture rtl of port_slicer is
+
+begin
+  dout <= din(DIN_FROM downto DIN_TO);
+
+end rtl;
diff --git a/cores/pps_gen_v1_0/core_config.tcl b/cores/pps_gen_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..ecd0ba753672bdd7b6a6a0a9c8f41506a8fcf697
--- /dev/null
+++ b/cores/pps_gen_v1_0/core_config.tcl
@@ -0,0 +1,7 @@
+set display_name {LAGO PPS Generator}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
diff --git a/cores/pps_gen_v1_0/pps_gen.vhd b/cores/pps_gen_v1_0/pps_gen.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..6e479166e6c0c33f11b61d8e73e349a5df1e6ad5
--- /dev/null
+++ b/cores/pps_gen_v1_0/pps_gen.vhd
@@ -0,0 +1,131 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity pps_gen is
+generic (
+  CLK_FREQ : natural := 125000000
+);
+port (
+  -- System signals
+  aclk               : in std_logic;
+  aresetn            : in std_logic;
+
+  pps_i              : in  std_logic; -- GPS PPS input
+  gpsen_i            : in  std_logic; -- PPS enable 0 -> GPS, 1 -> False PPS 
+  pps_o              : out std_logic;
+  clk_cnt_pps_o      : out std_logic_vector(27-1 downto 0);
+  pps_gps_led_o      : out std_logic;
+  false_pps_led_o    : out std_logic;
+  int_o              : out std_logic
+);
+end pps_gen;
+
+architecture rtl of pps_gen is
+
+  --PPS related signals
+  -- clock counter in a second
+  signal one_sec_cnt: std_logic_vector(27-1 downto 0);      
+  -- counter for clock pulses between PPS, it goes to zero at every PPS pulse 
+  signal clk_cnt_pps : std_logic_vector(27-1 downto 0); 
+  signal pps         : std_logic;
+  signal false_pps   : std_logic := '0';
+
+  type pps_st_t is (ZERO, EDGE, ONE);
+  signal pps_st_reg, pps_st_next: pps_st_t;
+  signal one_clk_pps       : std_logic;
+  signal pps_ibuf          : std_logic;
+
+begin
+    
+  int_o <= one_clk_pps;
+ 
+  IBUF_inst : IBUF
+   port map (
+    O => pps_ibuf,
+    I => pps_i
+   );
+
+  pps_gps_led_o <= pps_ibuf when (gpsen_i = '0') else '0';
+
+  false_pps_led_o <=  false_pps when (gpsen_i = '1') else '0';
+
+  --PPS MUX 
+  pps             <=  false_pps when (gpsen_i = '1') else pps_ibuf;
+
+  pps_o           <= one_clk_pps;
+  clk_cnt_pps_o   <= clk_cnt_pps;
+
+  -- false PPS
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+      if (aresetn = '0') then
+        one_sec_cnt <= (others => '0');   
+        clk_cnt_pps <= (others => '0');   
+      else
+        if (unsigned(one_sec_cnt) = CLK_FREQ-1) then
+          one_sec_cnt <= (others => '0');
+        else
+          one_sec_cnt <= std_logic_vector(unsigned(one_sec_cnt) + 1);
+        end if;
+       
+        -- false PPS is UP for 200 ms
+        if (unsigned(one_sec_cnt) < CLK_FREQ/5) then
+          false_pps <= '1';
+        else
+          false_pps <= '0';
+        end if;
+        
+        if (one_clk_pps = '1') then 
+          clk_cnt_pps <=  (others => '0');
+        else
+          clk_cnt_pps <= std_logic_vector(unsigned(clk_cnt_pps) + 1);
+        end if;
+
+      end if;
+    end if;
+  end process;
+
+  -- edge detector
+  -- state register
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+        pps_st_reg <= ZERO;
+    else
+        pps_st_reg <= pps_st_next;
+    end if;
+    end if;
+  end process;
+
+  -- next-state/output logic
+  process(pps_st_reg, pps)
+  begin
+     pps_st_next <= pps_st_reg;
+     one_clk_pps <= '0';
+     case pps_st_reg is
+        when ZERO =>
+           if pps = '1' then
+              pps_st_next <= EDGE;
+           end if;
+        when EDGE =>
+           one_clk_pps <= '1';
+           if pps = '1' then
+              pps_st_next <= ONE;
+           else
+              pps_st_next <= ZERO;
+           end if;
+        when ONE =>
+           if pps = '0' then
+              pps_st_next <= ZERO;
+           end if;
+     end case;
+  end process;
+
+end architecture rtl;
diff --git a/cores/pps_gen_v1_1/core_config.tcl b/cores/pps_gen_v1_1/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..ac7b403ebaaf2e92e60e397f4f07680452ad86bf
--- /dev/null
+++ b/cores/pps_gen_v1_1/core_config.tcl
@@ -0,0 +1,7 @@
+set display_name {LAGO PPS Generator v1r1}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
diff --git a/cores/pps_gen_v1_1/pps_gen.vhd b/cores/pps_gen_v1_1/pps_gen.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..e0a411916228a0659adb0d6e0463bf8394a00e81
--- /dev/null
+++ b/cores/pps_gen_v1_1/pps_gen.vhd
@@ -0,0 +1,138 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+library unisim;
+use unisim.vcomponents.all;
+
+entity pps_gen is
+generic (
+  CLK_FREQ : natural := 125000000
+);
+port (
+  -- System signals
+  aclk               : in std_logic;
+  aresetn            : in std_logic;
+  resetn_i           : in std_logic;
+
+  pps_i              : in  std_logic; -- GPS PPS input
+  gpsen_i            : in  std_logic; -- PPS enable 0 -> GPS, 1 -> False PPS 
+  pps_o              : out std_logic;
+  clk_cnt_pps_o      : out std_logic_vector(27-1 downto 0);
+  pps_gps_led_o      : out std_logic;
+  false_pps_led_o    : out std_logic;
+  pps_sig_o          : out std_logic;
+  int_o              : out std_logic
+);
+end pps_gen;
+
+architecture rtl of pps_gen is
+
+  --PPS related signals
+  -- clock counter in a second
+  signal one_sec_cnt: std_logic_vector(27-1 downto 0);      
+  -- counter for clock pulses between PPS, it goes to zero at every PPS pulse 
+  signal clk_cnt_pps : std_logic_vector(27-1 downto 0); 
+  signal pps         : std_logic;
+  signal false_pps   : std_logic := '0';
+
+  type pps_st_t is (ZERO, EDGE, ONE);
+  signal pps_st_reg, pps_st_next: pps_st_t;
+  signal one_clk_pps       : std_logic;
+  signal pps_ibuf          : std_logic;
+  signal rst_sig           : std_logic;
+
+begin
+
+  pps_sig_o <= '1' when (((pps_ibuf = '1') and (gpsen_i = '0')) or ((false_pps = '1') and (gpsen_i = '1'))) else '0';
+
+  rst_sig <= '1' when ((aresetn = '0') or (resetn_i = '0')) else '0';
+    
+  int_o <= one_clk_pps;
+ 
+  IBUF_inst : IBUF
+   port map (
+    O => pps_ibuf,
+    I => pps_i
+   );
+
+  pps_gps_led_o <= pps_ibuf when (gpsen_i = '0') else '0';
+
+  false_pps_led_o <=  false_pps when (gpsen_i = '1') else '0';
+
+  --PPS MUX 
+  pps             <=  false_pps when (gpsen_i = '1') else pps_ibuf;
+
+  pps_o           <= one_clk_pps;
+  clk_cnt_pps_o   <= clk_cnt_pps;
+
+  -- false PPS
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+      if (rst_sig = '1') then
+        one_sec_cnt <= (others => '0');   
+        clk_cnt_pps <= (others => '0');   
+      else
+        if (unsigned(one_sec_cnt) = CLK_FREQ-1) then
+          one_sec_cnt <= (others => '0');
+        else
+          one_sec_cnt <= std_logic_vector(unsigned(one_sec_cnt) + 1);
+        end if;
+       
+        -- false PPS is UP for 200 ms
+        if (unsigned(one_sec_cnt) < CLK_FREQ/5) then
+          false_pps <= '1';
+        else
+          false_pps <= '0';
+        end if;
+        
+        if (one_clk_pps = '1') then 
+          clk_cnt_pps <=  (others => '0');
+        else
+          clk_cnt_pps <= std_logic_vector(unsigned(clk_cnt_pps) + 1);
+        end if;
+
+      end if;
+    end if;
+  end process;
+
+  -- edge detector
+  -- state register
+  process(aclk)
+  begin
+    if (rising_edge(aclk)) then
+    if (aresetn = '0') then
+        pps_st_reg <= ZERO;
+    else
+        pps_st_reg <= pps_st_next;
+    end if;
+    end if;
+  end process;
+
+  -- next-state/output logic
+  process(pps_st_reg, pps)
+  begin
+     pps_st_next <= pps_st_reg;
+     one_clk_pps <= '0';
+     case pps_st_reg is
+        when ZERO =>
+           if pps = '1' then
+              pps_st_next <= EDGE;
+           end if;
+        when EDGE =>
+           one_clk_pps <= '1';
+           if pps = '1' then
+              pps_st_next <= ONE;
+           else
+              pps_st_next <= ZERO;
+           end if;
+        when ONE =>
+           if pps = '0' then
+              pps_st_next <= ZERO;
+           end if;
+     end case;
+  end process;
+
+end architecture rtl;
diff --git a/cores/pwm_gen_v1_0/core_config.tcl b/cores/pwm_gen_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..f7a308e0c7fe6f1b55e075c1b9973847da4aacbe
--- /dev/null
+++ b/cores/pwm_gen_v1_0/core_config.tcl
@@ -0,0 +1,9 @@
+set display_name {PWM Signal Generator}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter DATA_WIDTH {DATA WIDTH} {Width of the data bus.}
+core_parameter MAX_CNT {MAX COUNT} {Counter maximum count.}
diff --git a/cores/pwm_gen_v1_0/pwm_gen.vhd b/cores/pwm_gen_v1_0/pwm_gen.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..30750f038de27c2cae5d5fc58afdef93312d3c18
--- /dev/null
+++ b/cores/pwm_gen_v1_0/pwm_gen.vhd
@@ -0,0 +1,64 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity pwm_rp is
+generic(
+  DATA_WIDTH : integer := 24;
+  MAX_CNT : integer := 156
+);
+port (
+  aclk    : in std_logic;
+  aresetn : in std_logic;
+  cfg_i   : in std_logic_vector(DATA_WIDTH-1 downto 0);
+  pwm_o   : out std_logic
+  );
+end pwm_rp;
+
+architecture rtl of pwm_rp is
+  signal bcnt_reg, bcnt_next : std_logic_vector(4-1 downto 0);
+  signal b_reg, b_next : std_logic_vector(16-1 downto 0); 
+  signal vcnt_reg, vcnt_next: std_logic_vector(8-1 downto 0);
+  signal v_reg, v_next, v_r_reg, v_r_next : std_logic_vector(8-1 downto 0);
+
+begin
+
+process(aclk)
+begin
+if rising_edge(aclk) then
+  if aresetn = '0' then
+    vcnt_reg <= (others => '0');     
+    bcnt_reg <= (others => '0');     
+    v_reg <= (others => '0');     
+    v_r_reg <= (others => '0');     
+    b_reg <= (others => '0');     
+  else
+    vcnt_reg <= vcnt_next;
+    bcnt_reg <= bcnt_next;
+    v_reg <= v_next;
+    v_r_reg <= v_r_next;
+    b_reg <= b_next;
+  end if;
+end if;
+end process;
+
+ vcnt_next <= (others => '0') when unsigned(vcnt_reg) = MAX_CNT else
+              std_logic_vector(unsigned(vcnt_reg)+1);
+              
+ bcnt_next <= std_logic_vector(unsigned(bcnt_reg) + 1) when unsigned(vcnt_reg) = MAX_CNT else
+              bcnt_reg;
+              
+ b_next    <= cfg_i(16-1 downto 0) when (unsigned(vcnt_reg) = MAX_CNT) and (bcnt_reg = "1111") else
+              "0" & b_reg(15 downto 1) when (unsigned(vcnt_reg) = MAX_CNT) and (bcnt_reg /= "1111") else
+              b_reg;
+
+ v_next    <= cfg_i(24-1 downto 16) when (unsigned(vcnt_reg) = MAX_CNT) and (bcnt_reg = "1111") else 
+              v_reg;
+
+ v_r_next  <= std_logic_vector(unsigned(v_reg) + 1) when b_reg(0) = '1' else
+              v_reg;
+              
+ pwm_o     <= '1' when (unsigned(vcnt_reg) <= unsigned(v_r_reg)) else '0';
+
+end rtl;     
diff --git a/cores/ramp_gen_v1_0/core_config.tcl b/cores/ramp_gen_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..b2c5e3be847cafc43684d6bcc8f9df0c2a17f486
--- /dev/null
+++ b/cores/ramp_gen_v1_0/core_config.tcl
@@ -0,0 +1,10 @@
+set display_name {Ramp Signal Generator}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
+core_parameter COUNT_NBITS {COUNTER BITS} {Width of the counter in bits.}
+core_parameter COUNT_MOD {MODULE OF COUNTER} {Module of the counter.}
+core_parameter DATA_BITS {DATA WIDTH} {Width of the data bus.}
diff --git a/cores/ramp_gen_v1_0/ramp_gen.vhd b/cores/ramp_gen_v1_0/ramp_gen.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..58e2199b31cb87d9ad1b34bd76ea398713f2529c
--- /dev/null
+++ b/cores/ramp_gen_v1_0/ramp_gen.vhd
@@ -0,0 +1,83 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity ramp_gen is
+	generic(
+	  COUNT_NBITS : integer := 18;     -- number of bits of the counter
+  	COUNT_MOD   : integer := 200000;		-- mod-n
+		DATA_BITS   : integer := 12);			-- number of bits for the data
+  port(
+    aclk    : in  std_logic;
+		aresetn	: in 	std_logic;
+		data_i	: in 	std_logic_vector(DATA_BITS-1 downto 0);
+		data_o	: out std_logic_vector(DATA_BITS-1 downto 0);
+		pwm_o		: out	std_logic;
+		led_o		: out std_logic);
+end ramp_gen;
+
+architecture rtl of ramp_gen is
+  signal cnt_reg, cnt_next	 : std_logic_vector(COUNT_NBITS-1 downto 0);
+  signal in_reg, in_next	   : std_logic_vector(DATA_BITS-1 downto 0);
+  signal r_reg, r_next	     : std_logic_vector(DATA_BITS-1 downto 0);
+  signal out_reg, out_next	 : std_logic_vector(DATA_BITS-1 downto 0);
+	signal buff_reg, buff_next : std_logic;
+	signal max_tick			       : std_logic;
+
+begin
+	-- Drive inputs
+	in_next	<= data_i;
+
+	--registers
+ 	process (aclk)
+ 	begin
+    if rising_edge(aclk) then
+      if (aresetn = '0') then
+    	  cnt_reg 	<= (others => '0');
+    	  in_reg 		<= (others => '0');
+    	  out_reg 	<= (others => '0');
+    	  r_reg		 	<= (others => '0');
+    	  buff_reg 	<= '0';
+      else
+     	  cnt_reg 	<= cnt_next;
+     	  r_reg 		<= r_next;
+     	  buff_reg 	<= buff_next;
+     	  in_reg 		<= in_next;
+     	  out_reg 	<= out_next;
+      end if;
+    end if;
+ 	end process;
+	--next-state logic for counter
+	cnt_next	<= 	(others => '0') when unsigned(cnt_reg) = (COUNT_MOD-1) else
+          			std_logic_vector(unsigned(cnt_reg) + 1);
+
+	buff_next <= '1' when (unsigned(r_reg) < unsigned(out_reg)) else '0';          		
+
+	r_next <= std_logic_vector(unsigned(r_reg) + 1);          		
+
+	--output logic
+	max_tick <= '1' when unsigned(cnt_reg) = (COUNT_MOD-1) else '0';
+
+	process(max_tick, in_reg, out_reg)
+	begin
+		if (max_tick = '1') then
+			if (unsigned(in_reg) > unsigned(out_reg)) then			
+				out_next <= std_logic_vector(unsigned(out_reg) + 1);
+			elsif (unsigned(in_reg) < unsigned(out_reg)) then
+				out_next <= std_logic_vector(unsigned(out_reg) - 1);
+			else
+				out_next <= out_reg;	-- default
+			end if;
+		else
+			out_next <= out_reg;
+		end if;
+	end process;
+	
+	--next-state logic for output
+	data_o <= out_reg;
+	led_o <= 	'0' when (unsigned(out_reg) = 0) else
+						'1';
+	pwm_o <= buff_reg;
+
+end rtl;
diff --git a/cores/selector_v1_0/core_config.tcl b/cores/selector_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..9f9def717d69da28292d2c459c8a26e9ba5f7aa7
--- /dev/null
+++ b/cores/selector_v1_0/core_config.tcl
@@ -0,0 +1,7 @@
+set display_name {Data Selector}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
diff --git a/cores/selector_v1_0/selector.vhd b/cores/selector_v1_0/selector.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a57f5167096a25f8e250123dc5d6c191627a7166
--- /dev/null
+++ b/cores/selector_v1_0/selector.vhd
@@ -0,0 +1,27 @@
+library ieee;
+
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity selector is
+generic (
+    A_WIDTH   : natural := 32;
+    DIV_WIDTH : natural := 5;
+    OFFSET    : natural := 26; -- Slice bit position 26 ... 1.07 s
+    SCALE     : integer := -1 
+);
+port (
+  -- System signals
+  a   : in std_logic_vector(A_WIDTH-1 downto 0);
+  div : in std_logic_vector(DIV_WIDTH-1 downto 0);
+  s   : out std_logic
+);
+end selector;
+
+architecture rtl of selector is
+
+begin
+
+        s <= a(OFFSET + SCALE*div);
+    
+end rtl;
diff --git a/cores/time_trig_gen_v1_0/core_config.tcl b/cores/time_trig_gen_v1_0/core_config.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..f931d39ff2769c59ab02c91c0271fbc88c79cb54
--- /dev/null
+++ b/cores/time_trig_gen_v1_0/core_config.tcl
@@ -0,0 +1,7 @@
+set display_name {Time Trigger Generator}
+
+set core [ipx::current_core]
+
+set_property DISPLAY_NAME $display_name $core
+set_property DESCRIPTION $display_name $core
+
diff --git a/cores/time_trig_gen_v1_0/time_trig_gen.vhd b/cores/time_trig_gen_v1_0/time_trig_gen.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..660101b10241b849d2352863c6a4d99f5f491e21
--- /dev/null
+++ b/cores/time_trig_gen_v1_0/time_trig_gen.vhd
@@ -0,0 +1,49 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+entity time_trig_gen is
+  port (
+    aclk    : in std_logic;
+    aresetn : in std_logic;
+    cfg_data: in std_logic_vector(32-1 downto 0);
+    trig_o  : out std_logic
+    );
+end time_trig_gen;
+
+architecture rtl of time_trig_gen is
+
+  signal cntr_reg, cntr_next : std_logic_vector(32-1 downto 0);
+  signal trig_reg, trig_next : std_logic;
+  signal comp_reg, comp_next : std_logic;
+
+begin
+
+ process(aclk)
+  begin
+    if rising_edge(aclk) then
+      if (aresetn = '0') then
+        cntr_reg <= (others => '0');
+        trig_reg <= '0';
+        comp_reg <= '0';
+      else
+        cntr_reg <= cntr_next;
+        trig_reg <= trig_next;
+        comp_reg <= comp_next;
+      end if;
+    end if;
+  end process;
+  
+  comp_next <= '0' when (unsigned(cntr_reg) = unsigned(cfg_data)-1) else 
+               '1';
+
+  cntr_next <= std_logic_vector(unsigned(cntr_reg) + 1) when (comp_reg = '1') else
+               (others => '0') when (comp_reg = '0') else --reset
+               cntr_reg;
+
+  trig_next <= '1' when (unsigned(cntr_reg) = unsigned(cfg_data)-1) else 
+               '0';
+ 
+  trig_o    <= trig_reg;
+
+end rtl;
diff --git a/patches/cma.c b/patches/cma.c
new file mode 100644
index 0000000000000000000000000000000000000000..621210743df0156c7261ffba1f64744bc7a0f0e4
--- /dev/null
+++ b/patches/cma.c
@@ -0,0 +1,96 @@
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/dma-mapping.h>
+#include <linux/dma-map-ops.h>
+
+#define CMA_ALLOC _IOWR('Z', 0, u32)
+
+static struct device *dma_device = NULL;
+static size_t dma_size = 0;
+static void *cpu_addr = NULL;
+static dma_addr_t dma_addr;
+
+static void cma_free(void)
+{
+  if(!cpu_addr) return;
+  dma_free_coherent(dma_device, dma_size, cpu_addr, dma_addr);
+  cpu_addr = NULL;
+}
+
+static long cma_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+  long rc;
+  u32 buffer;
+
+  if(cmd != CMA_ALLOC) return -ENOTTY;
+
+  rc = copy_from_user(&buffer, (void __user *)arg, sizeof(buffer));
+  if(rc) return rc;
+
+  cma_free();
+
+  dma_size = buffer;
+  cpu_addr = dma_alloc_coherent(dma_device, dma_size, &dma_addr, GFP_KERNEL);
+
+  if(IS_ERR_OR_NULL(cpu_addr))
+  {
+    rc = PTR_ERR(cpu_addr);
+    if(rc == 0) rc = -ENOMEM;
+    cpu_addr = NULL;
+    return rc;
+  }
+
+  buffer = dma_addr;
+  return copy_to_user((void __user *)arg, &buffer, sizeof(buffer));
+}
+
+static int cma_mmap(struct file *file, struct vm_area_struct *vma)
+{
+  return dma_mmap_coherent(dma_device, vma, cpu_addr, dma_addr, dma_size);
+}
+
+static int cma_release(struct inode *inode, struct file *file)
+{
+  cma_free();
+  return 0;
+}
+
+static struct file_operations cma_fops =
+{
+  .unlocked_ioctl = cma_ioctl,
+  .mmap = cma_mmap,
+  .release = cma_release
+};
+
+struct miscdevice cma_device =
+{
+  .minor = MISC_DYNAMIC_MINOR,
+  .name = "cma",
+  .fops = &cma_fops
+};
+
+static int __init cma_init(void)
+{
+  int rc;
+
+  rc = misc_register(&cma_device);
+  if(rc) return rc;
+
+  dma_device = cma_device.this_device;
+
+  dma_device->dma_ops = &arm_coherent_dma_ops;
+  dma_device->coherent_dma_mask = DMA_BIT_MASK(32);
+
+  return 0;
+}
+
+static void __exit cma_exit(void)
+{
+  cma_free();
+  misc_deregister(&cma_device);
+}
+
+module_init(cma_init);
+module_exit(cma_exit);
+MODULE_LICENSE("MIT");
diff --git a/patches/devicetree.patch b/patches/devicetree.patch
new file mode 100644
index 0000000000000000000000000000000000000000..fc16466a0c4bfdde90d537e80901fbe747e8173e
--- /dev/null
+++ b/patches/devicetree.patch
@@ -0,0 +1,147 @@
+diff -rupN pl.dtsi.old pl.dtsi
+--- pl.dtsi.old
++++ pl.dtsi
+@@ -15,7 +15,7 @@
+ 			#interrupt-cells = <2>;
+ 			clock-names = "s_axi_aclk";
+ 			clocks = <&misc_clk_0>;
+-			compatible = "xlnx,axi-intc-4.1", "xlnx,xps-intc-1.00.a";
++      compatible = "generic-uio";
+ 			interrupt-controller ;
+ 			interrupt-names = "irq";
+ 			interrupt-parent = <&intc>;
+@@ -32,19 +32,19 @@
+ 		cfg_0: axi_cfg_register@40001000 {
+ 			clock-names = "aclk";
+ 			clocks = <&misc_clk_0>;
+-			compatible = "xlnx,axi-cfg-register-1.0";
++      compatible = "generic-uio";
+ 			reg = <0x40001000 0x1000>;
+ 		};
+ 		sts_0: axi_sts_register@40002000 {
+ 			clock-names = "aclk";
+ 			clocks = <&misc_clk_0>;
+-			compatible = "xlnx,axi-sts-register-1.0";
++      compatible = "generic-uio";
+ 			reg = <0x40002000 0x1000>;
+ 		};
+ 		xadc_wiz_0: xadc_wiz@40003000 {
+ 			clock-names = "s_axi_aclk";
+ 			clocks = <&misc_clk_0>;
+-			compatible = "xlnx,xadc-wiz-3.3", "xlnx,axi-xadc-1.00.a";
++      compatible = "generic-uio";
+ 			reg = <0x40003000 0x1000>;
+ 			xlnx,alarm-limit-r0 = <0xb5ed>;
+ 			xlnx,alarm-limit-r1 = <0x57e4>;
+@@ -126,5 +126,17 @@
+ 			xlnx,vaux8 = <0x1>;
+ 			xlnx,vaux9 = <0x1>;
+ 		};
+-	};
++		hst0_reader_0: axi_bram_reader@40010000 {
++			clock-names = "aclk";
++			clocks = <&misc_clk_0>;
++      compatible = "generic-uio";
++			reg = <0x40010000 0x10000>;
++		};
++		hst1_reader_1: axi_bram_reader@40020000 {
++			clock-names = "aclk";
++			clocks = <&misc_clk_0>;
++      compatible = "generic-uio";
++			reg = <0x40020000 0x10000>;
++		};
++  };
+ };
+diff -rupN pcw.dtsi.old pcw.dtsi
+--- pcw.dtsi.old
++++ pcw.dtsi
+@@ -26,6 +26,19 @@
+ 	clock-frequency = <400000>;
+ 	status = "okay";
+ };
++&i2c0 {
++	eep@50 {
++		compatible = "24c64";
++ 		size = <8192>;
++ 		pagesize = <32>;
++		reg = <0x50>;
++	};
++  bmp180@77{
++    compatible = "bosch,bmp280";
++    reg = <0x77>;
++    status = "okay";
++  };
++};
+ &intc {
+ 	num_cpus = <2>;
+ 	num_interrupts = <96>;
+@@ -45,6 +51,11 @@
+ 	is-decoded-cs = <0>;
+ 	num-cs = <1>;
+ 	status = "okay";
++	spidev@0 {
++		compatible = "spidev";
++		reg = <0x0>;
++		spi-max-frequency = <10000000>;
++	};
+ };
+ &uart0 {
+ 	device_type = "serial";
+@@ -57,11 +68,33 @@
+ 	status = "okay";
+ };
+ &usb0 {
++	dr_mode = "host";
+-	phy_type = "ulpi";
++	usb-phy = <&usb_phy0>;
+ 	status = "okay";
+-	usb-reset = <&gpio0 48 0>;
++	xlnx,phy-reset-gpio = <&gpio0 48 0>;
+ };
+ &clkc {
+ 	fclk-enable = <0x0>;
+ 	ps-clk-frequency = <33333333>;
+ };
++&adc {
++	xlnx,channels {
++		#address-cells = <1>;
++		#size-cells = <0>;
++		channel@0 {
++			reg = <0>;
++		};
++		channel@1 {
++			reg = <1>;
++		};
++		channel@2 {
++			reg = <2>;
++		};
++		channel@9 {
++			reg = <9>;
++		};
++		channel@10 {
++			reg = <10>;
++		};
++	};
++};
+diff -rupN system-top.dts.old system-top.dts
+--- system-top.dts.old
++++ system-top.dts
+@@ -14,6 +14,18 @@
+ 		bootargs = "console=ttyPS0,115200 earlyprintk earlycon";
+ 		stdout-path = "serial0:115200n8";
+ 	};
++	usb_phy0: phy0 {
++		#phy-cells = <0>;
++		compatible = "ulpi-phy";
++		reg = <0xe0002000 0x1000>;
++		view-port = <0x0170>;
++		drv-vbus;
++	};
++	pps {
++		compatible = "pps-gpio";
++		gpios = <&gpio0 54 0>;
++		capture-clear;
++	};
+ 	aliases {
+ 		ethernet0 = &gem0;
+ 		i2c0 = &i2c0;
diff --git a/patches/linux-5.10.patch b/patches/linux-5.10.patch
new file mode 100644
index 0000000000000000000000000000000000000000..f37550adb0d9daa8bbb5ba74dd6b79a316365496
--- /dev/null
+++ b/patches/linux-5.10.patch
@@ -0,0 +1,494 @@
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/common.c linux-5.10/arch/arm/mach-zynq/common.c
+--- old/linux-5.10/arch/arm/mach-zynq/common.c
++++ linux-5.10/arch/arm/mach-zynq/common.c
+@@ -95,6 +95,7 @@ static void __init zynq_init_late(void)
+ {
+ 	zynq_core_pm_init();
+ 	zynq_pm_late_init();
++	zynq_prefetch_init();
+ }
+ 
+ /**
+@@ -186,8 +187,13 @@ static const char * const zynq_dt_match[
+ 
+ DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
+ 	/* 64KB way size, 8-way associativity, parity disabled */
+-	.l2c_aux_val    = 0x00400000,
++#ifdef CONFIG_XILINX_PREFETCH
++	.l2c_aux_val	= 0x30400000,
++	.l2c_aux_mask	= 0xcfbfffff,
++#else
++	.l2c_aux_val	= 0x00400000,
+ 	.l2c_aux_mask	= 0xffbfffff,
++#endif
+ 	.smp		= smp_ops(zynq_smp_ops),
+ 	.map_io		= zynq_map_io,
+ 	.init_irq	= zynq_irq_init,
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/common.h linux-5.10/arch/arm/mach-zynq/common.h
+--- old/linux-5.10/arch/arm/mach-zynq/common.h
++++ linux-5.10/arch/arm/mach-zynq/common.h
+@@ -15,6 +15,7 @@ extern void zynq_slcr_cpu_stop(int cpu);
+ extern void zynq_slcr_cpu_start(int cpu);
+ extern bool zynq_slcr_cpu_state_read(int cpu);
+ extern void zynq_slcr_cpu_state_write(int cpu, bool die);
++extern u32 zynq_slcr_get_ocm_config(void);
+ extern u32 zynq_slcr_get_device_id(void);
+ 
+ #ifdef CONFIG_SMP
+@@ -29,6 +30,22 @@ extern void __iomem *zynq_scu_base;
+ 
+ void zynq_pm_late_init(void);
+ 
++static inline void zynq_prefetch_init(void)
++{
++	/*
++	 * Enable prefetching in aux control register. L2 prefetch must
++	 * only be enabled if the slave supports it (PL310 does)
++	 */
++	asm volatile ("mrc   p15, 0, r1, c1, c0, 1\n"
++#ifdef CONFIG_XILINX_PREFETCH
++		      "orr   r1, r1, #6\n"
++#else
++		      "bic   r1, r1, #6\n"
++#endif
++		      "mcr   p15, 0, r1, c1, c0, 1\n"
++		      : : : "r1");
++}
++
+ static inline void zynq_core_pm_init(void)
+ {
+ 	/* A9 clock gating */
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/Kconfig linux-5.10/arch/arm/mach-zynq/Kconfig
+--- old/linux-5.10/arch/arm/mach-zynq/Kconfig
++++ linux-5.10/arch/arm/mach-zynq/Kconfig
+@@ -16,3 +16,19 @@ config ARCH_ZYNQ
+ 	select SOC_BUS
+ 	help
+ 	  Support for Xilinx Zynq ARM Cortex A9 Platform
++
++if ARCH_ZYNQ
++
++menu "Xilinx Specific Options"
++
++config XILINX_PREFETCH
++	bool "Cache Prefetch"
++	default y
++	help
++	  This option turns on L1 & L2 cache prefetching to get the best performance
++	  in many cases. This may not always be the best performance depending on
++	  the usage.
++
++endmenu
++
++endif
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/Makefile linux-5.10/arch/arm/mach-zynq/Makefile
+--- old/linux-5.10/arch/arm/mach-zynq/Makefile
++++ linux-5.10/arch/arm/mach-zynq/Makefile
+@@ -4,5 +4,5 @@
+ #
+ 
+ # Common support
+-obj-y				:= common.o slcr.o pm.o
++obj-y				:= common.o slcr.o zynq_ocm.o pm.o
+ obj-$(CONFIG_SMP)		+= headsmp.o platsmp.o
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/platsmp.c linux-5.10/arch/arm/mach-zynq/platsmp.c
+--- old/linux-5.10/arch/arm/mach-zynq/platsmp.c
++++ linux-5.10/arch/arm/mach-zynq/platsmp.c
+@@ -115,6 +115,7 @@ static void __init zynq_smp_prepare_cpus
+ static void zynq_secondary_init(unsigned int cpu)
+ {
+ 	zynq_core_pm_init();
++	zynq_prefetch_init();
+ }
+ 
+ #ifdef CONFIG_HOTPLUG_CPU
+diff -rupN old/linux-5.10/arch/arm/mach-zynq/slcr.c linux-5.10/arch/arm/mach-zynq/slcr.c
+--- old/linux-5.10/arch/arm/mach-zynq/slcr.c
++++ linux-5.10/arch/arm/mach-zynq/slcr.c
+@@ -20,6 +20,7 @@
+ #define SLCR_REBOOT_STATUS_OFFSET	0x258 /* PS Reboot Status */
+ #define SLCR_PSS_IDCODE			0x530 /* PS IDCODE */
+ #define SLCR_L2C_RAM			0xA1C /* L2C_RAM in AR#54190 */
++#define SLCR_OCM_CFG_OFFSET		0x910 /* OCM Address Mapping */
+ 
+ #define SLCR_UNLOCK_MAGIC		0xDF0D
+ #define SLCR_A9_CPU_CLKSTOP		0x10
+@@ -116,6 +117,19 @@ static struct notifier_block zynq_slcr_r
+ };
+ 
+ /**
++ * zynq_slcr_get_ocm_config - Get SLCR OCM config
++ *
++ * return:	OCM config bits
++ */
++u32 zynq_slcr_get_ocm_config(void)
++{
++	u32 ret;
++
++	zynq_slcr_read(&ret, SLCR_OCM_CFG_OFFSET);
++	return ret;
++}
++
++/**
+  * zynq_slcr_cpu_start - Start cpu
+  * @cpu:	cpu number
+  */
+diff -rupN old/linux-5.10/drivers/char/Kconfig linux-5.10/drivers/char/Kconfig
+--- old/linux-5.10/drivers/char/Kconfig
++++ linux-5.10/drivers/char/Kconfig
+@@ -471,6 +471,14 @@ config ADI
+ 	  and SSM (Silicon Secured Memory).  Intended consumers of this
+ 	  driver include crash and makedumpfile.
+ 
++config DEVCMA
++	bool "/dev/cma virtual device support"
++	default y
++
++config XILINX_DEVCFG
++	tristate "Xilinx Device Configuration"
++	depends on ARCH_ZYNQ
++
+ endmenu
+ 
+ config RANDOM_TRUST_CPU
+diff -rupN old/linux-5.10/drivers/char/Makefile linux-5.10/drivers/char/Makefile
+--- old/linux-5.10/drivers/char/Makefile
++++ linux-5.10/drivers/char/Makefile
+@@ -47,3 +47,5 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
+ obj-$(CONFIG_XILLYBUS)		+= xillybus/
+ obj-$(CONFIG_POWERNV_OP_PANEL)	+= powernv-op-panel.o
+ obj-$(CONFIG_ADI)		+= adi.o
++obj-$(CONFIG_DEVCMA)		+= cma.o
++obj-$(CONFIG_XILINX_DEVCFG)	+= xilinx_devcfg.o
+diff -rupN old/linux-5.10/drivers/net/phy/intel-xway.c linux-5.10/drivers/net/phy/intel-xway.c
+--- old/linux-5.10/drivers/net/phy/intel-xway.c
++++ linux-5.10/drivers/net/phy/intel-xway.c
+@@ -180,6 +180,12 @@ static int xway_gphy_config_init(struct
+ 	if (err)
+ 		return err;
+ 
++	/* Set SGMII RX & TX timing skew to 2 ns & 2.5 ns respectively. */
++	/* Set MII power supply to 2V5. */
++	err = phy_write(phydev, 0x17, 0x4D00);
++	if (err)
++		return err;
++
+ 	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LEDCH,
+ 		      XWAY_MMD_LEDCH_NACS_NONE |
+ 		      XWAY_MMD_LEDCH_SBF_F02HZ |
+@@ -189,20 +195,16 @@ static int xway_gphy_config_init(struct
+ 		      XWAY_MMD_LEDCH_SCAN_NONE);
+ 
+ 	/**
+-	 * In most cases only one LED is connected to this phy, so
+-	 * configure them all to constant on and pulse mode. LED3 is
+-	 * only available in some packages, leave it in its reset
+-	 * configuration.
++	 * Set LED0 blinking on RX/TX.
++	 * Set LED1 blinking on link speed: slow=10M, fast=100M, on=1G.
+ 	 */
+-	ledxh = XWAY_MMD_LEDxH_BLINKF_NONE | XWAY_MMD_LEDxH_CON_LINK10XX;
+-	ledxl = XWAY_MMD_LEDxL_PULSE_TXACT | XWAY_MMD_LEDxL_PULSE_RXACT |
+-		XWAY_MMD_LEDxL_BLINKS_NONE;
+-	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED0H, ledxh);
++	ledxl = XWAY_MMD_LEDxL_PULSE_TXACT | XWAY_MMD_LEDxL_PULSE_RXACT;
++	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED0H, 0);
+ 	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED0L, ledxl);
++	ledxh = XWAY_MMD_LEDxH_CON_LINK1000 | XWAY_MMD_LEDxH_BLINKF_LINK100;
++	ledxl = XWAY_MMD_LEDxH_CON_LINK10;
+ 	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED1H, ledxh);
+ 	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED1L, ledxl);
+-	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2H, ledxh);
+-	phy_write_mmd(phydev, MDIO_MMD_VEND2, XWAY_MMD_LED2L, ledxl);
+ 
+ 	return 0;
+ }
+diff -rupN old/linux-5.10/drivers/net/wireless/realtek/Kconfig linux-5.10/drivers/net/wireless/realtek/Kconfig
+--- old/linux-5.10/drivers/net/wireless/realtek/Kconfig
++++ linux-5.10/drivers/net/wireless/realtek/Kconfig
+@@ -13,8 +13,9 @@ config WLAN_VENDOR_REALTEK
+ if WLAN_VENDOR_REALTEK
+ 
+ source "drivers/net/wireless/realtek/rtl818x/Kconfig"
+-source "drivers/net/wireless/realtek/rtlwifi/Kconfig"
+ source "drivers/net/wireless/realtek/rtl8xxxu/Kconfig"
+ source "drivers/net/wireless/realtek/rtw88/Kconfig"
++source "drivers/net/wireless/realtek/rtl8188eu/Kconfig"
++source "drivers/net/wireless/realtek/rtl8192cu/Kconfig"
+ 
+ endif # WLAN_VENDOR_REALTEK
+diff -rupN old/linux-5.10/drivers/net/wireless/realtek/Makefile linux-5.10/drivers/net/wireless/realtek/Makefile
+--- old/linux-5.10/drivers/net/wireless/realtek/Makefile
++++ linux-5.10/drivers/net/wireless/realtek/Makefile
+@@ -5,7 +5,8 @@
+ 
+ obj-$(CONFIG_RTL8180)		+= rtl818x/
+ obj-$(CONFIG_RTL8187)		+= rtl818x/
+-obj-$(CONFIG_RTLWIFI)		+= rtlwifi/
+ obj-$(CONFIG_RTL8XXXU)		+= rtl8xxxu/
+ obj-$(CONFIG_RTW88)		+= rtw88/
++obj-$(CONFIG_RTL8188EU)		+= rtl8188eu/
++obj-$(CONFIG_RTL8192CU)		+= rtl8192cu/
+ 
+diff -rupN old/linux-5.10/drivers/net/wireless/realtek/rtl8188eu/Kconfig linux-5.10/drivers/net/wireless/realtek/rtl8188eu/Kconfig
+--- old/linux-5.10/drivers/net/wireless/realtek/rtl8188eu/Kconfig
++++ linux-5.10/drivers/net/wireless/realtek/rtl8188eu/Kconfig
+@@ -1,6 +1,6 @@
+ config RTL8188EU
+ 	tristate "Realtek 8188E USB WiFi"
+ 	depends on USB
+-	---help---
++	help
+ 	  Help message of RTL8188EU
+ 
+diff -rupN old/linux-5.10/drivers/net/wireless/realtek/rtl8192cu/Kconfig linux-5.10/drivers/net/wireless/realtek/rtl8192cu/Kconfig
+--- old/linux-5.10/drivers/net/wireless/realtek/rtl8192cu/Kconfig	1970-01-01 00:00:00.000000000 +0000
++++ linux-5.10/drivers/net/wireless/realtek/rtl8192cu/Kconfig
+@@ -0,0 +1,9 @@
++config RTL8192CU
++	tristate "Realtek 8192CU USB WiFi"
++	depends on MAC80211 && USB
++	select CFG80211_WEXT
++	select WIRELESS_EXT
++	select WEXT_PRIV
++	help
++	  This option adds the Realtek RTL8192CU USB device.
++
+diff -rupN old/linux-5.10/drivers/pps/clients/pps-gpio.c linux-5.10/drivers/pps/clients/pps-gpio.c
+--- old/linux-5.10/drivers/pps/clients/pps-gpio.c
++++ linux-5.10/drivers/pps/clients/pps-gpio.c
+@@ -145,6 +145,8 @@ static int pps_gpio_setup(struct platfor
+ 
+ 	if (of_property_read_bool(np, "assert-falling-edge"))
+ 		data->assert_falling_edge = true;
++	if (of_get_property(np, "capture-clear", NULL))
++		data->capture_clear = true;
+ 	return 0;
+ }
+ 
+diff -rupN old/linux-5.10/drivers/usb/chipidea/ci_hdrc_usb2.c linux-5.10/drivers/usb/chipidea/ci_hdrc_usb2.c
+--- old/linux-5.10/drivers/usb/chipidea/ci_hdrc_usb2.c
++++ linux-5.10/drivers/usb/chipidea/ci_hdrc_usb2.c
+@@ -30,6 +30,7 @@ static const struct ci_hdrc_platform_dat
+ 
+ static const struct ci_hdrc_platform_data ci_zynq_pdata = {
+ 	.capoffset	= DEF_CAPOFFSET,
++	.flags		= CI_HDRC_PHY_VBUS_CONTROL,
+ };
+ 
+ static const struct ci_hdrc_platform_data ci_zevio_pdata = {
+@@ -64,6 +65,9 @@ static int ci_hdrc_usb2_probe(struct pla
+ 	if (match && match->data) {
+ 		/* struct copy */
+ 		*ci_pdata = *(struct ci_hdrc_platform_data *)match->data;
++		ci_pdata->usb_phy = devm_usb_get_phy_by_phandle(dev, "usb-phy", 0);
++		if (IS_ERR(ci_pdata->usb_phy))
++			return PTR_ERR(ci_pdata->usb_phy);
+ 	}
+ 
+ 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+diff -rupN old/linux-5.10/drivers/usb/chipidea/host.c linux-5.10/drivers/usb/chipidea/host.c
+--- old/linux-5.10/drivers/usb/chipidea/host.c
++++ linux-5.10/drivers/usb/chipidea/host.c
+@@ -57,6 +57,14 @@ static int ehci_ci_portpower(struct usb_
+ 		priv->enabled = enable;
+ 	}
+ 
++	if (ci->platdata->flags & CI_HDRC_PHY_VBUS_CONTROL &&
++			ci->usb_phy && ci->usb_phy->set_vbus) {
++		if (enable)
++			ci->usb_phy->set_vbus(ci->usb_phy, 1);
++		else
++			ci->usb_phy->set_vbus(ci->usb_phy, 0);
++	}
++
+ 	if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) {
+ 		/*
+ 		 * Marvell 28nm HSIC PHY requires forcing the port to HS mode.
+diff -rupN old/linux-5.10/drivers/usb/chipidea/otg_fsm.c linux-5.10/drivers/usb/chipidea/otg_fsm.c
+--- old/linux-5.10/drivers/usb/chipidea/otg_fsm.c
++++ linux-5.10/drivers/usb/chipidea/otg_fsm.c
+@@ -471,6 +471,11 @@ static void ci_otg_drv_vbus(struct otg_f
+ 				return;
+ 			}
+ 		}
++
++		if (ci->platdata->flags & CI_HDRC_PHY_VBUS_CONTROL &&
++				ci->usb_phy && ci->usb_phy->set_vbus)
++			ci->usb_phy->set_vbus(ci->usb_phy, 1);
++
+ 		/* Disable data pulse irq */
+ 		hw_write_otgsc(ci, OTGSC_DPIE, 0);
+ 
+@@ -480,6 +485,10 @@ static void ci_otg_drv_vbus(struct otg_f
+ 		if (ci->platdata->reg_vbus)
+ 			regulator_disable(ci->platdata->reg_vbus);
+ 
++		if (ci->platdata->flags & CI_HDRC_PHY_VBUS_CONTROL &&
++				ci->usb_phy && ci->usb_phy->set_vbus)
++			ci->usb_phy->set_vbus(ci->usb_phy, 0);
++
+ 		fsm->a_bus_drop = 1;
+ 		fsm->a_bus_req = 0;
+ 	}
+diff -rupN old/linux-5.10/drivers/usb/phy/phy-ulpi.c linux-5.10/drivers/usb/phy/phy-ulpi.c
+--- old/linux-5.10/drivers/usb/phy/phy-ulpi.c
++++ linux-5.10/drivers/usb/phy/phy-ulpi.c
+@@ -13,9 +13,16 @@
+ #include <linux/kernel.h>
+ #include <linux/slab.h>
+ #include <linux/export.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/io.h>
++#include <linux/of_address.h>
++#include <linux/of_device.h>
++#include <linux/platform_device.h>
+ #include <linux/usb.h>
+ #include <linux/usb/otg.h>
+ #include <linux/usb/ulpi.h>
++#include <linux/usb/phy.h>
+ 
+ 
+ struct ulpi_info {
+@@ -39,6 +46,13 @@ static struct ulpi_info ulpi_ids[] = {
+ 	ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"),
+ };
+ 
++struct ulpi_phy {
++	struct usb_phy	*usb_phy;
++	void __iomem *regs;
++	unsigned int vp_offset;
++	unsigned int flags;
++};
++
+ static int ulpi_set_otg_flags(struct usb_phy *phy)
+ {
+ 	unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN |
+@@ -240,6 +254,23 @@ static int ulpi_set_vbus(struct usb_otg
+ 	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
+ }
+ 
++static int usbphy_set_vbus(struct usb_phy *phy, int on)
++{
++	unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL);
++
++	flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT);
++
++	if (on) {
++		if (phy->flags & ULPI_OTG_DRVVBUS)
++			flags |= ULPI_OTG_CTRL_DRVVBUS;
++
++		if (phy->flags & ULPI_OTG_DRVVBUS_EXT)
++			flags |= ULPI_OTG_CTRL_DRVVBUS_EXT;
++	}
++
++	return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL);
++}
++
+ static void otg_ulpi_init(struct usb_phy *phy, struct usb_otg *otg,
+ 			  struct usb_phy_io_ops *ops,
+ 			  unsigned int flags)
+@@ -249,6 +280,7 @@ static void otg_ulpi_init(struct usb_phy
+ 	phy->io_ops	= ops;
+ 	phy->otg	= otg;
+ 	phy->init	= ulpi_init;
++	phy->set_vbus	= usbphy_set_vbus;
+ 
+ 	otg->usb_phy	= phy;
+ 	otg->set_host	= ulpi_set_host;
+@@ -301,3 +333,83 @@ devm_otg_ulpi_create(struct device *dev,
+ 	return phy;
+ }
+ EXPORT_SYMBOL_GPL(devm_otg_ulpi_create);
++
++static int ulpi_phy_probe(struct platform_device *pdev)
++{
++	struct device_node *np = pdev->dev.of_node;
++	struct resource *res;
++	struct ulpi_phy *uphy;
++	bool flag;
++	int ret;
++
++	uphy = devm_kzalloc(&pdev->dev, sizeof(*uphy), GFP_KERNEL);
++	if (!uphy)
++		return -ENOMEM;
++
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (!res) {
++		dev_err(&pdev->dev, "no phy I/O memory resource defined\n");
++		return -ENODEV;
++	}
++
++	uphy->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
++	if (!uphy->regs) {
++		dev_err(&pdev->dev, "failed to map phy I/O memory\n");
++		return -EFAULT;
++	}
++
++	if (IS_ERR(uphy->regs))
++		return PTR_ERR(uphy->regs);
++
++	if (of_property_read_u32(np, "view-port", &uphy->vp_offset))
++		dev_dbg(&pdev->dev, "Missing view-port property\n");
++
++	if (IS_ERR(uphy->regs)) {
++		dev_err(&pdev->dev, "view-port register not specified\n");
++		return PTR_ERR(uphy->regs);
++	}
++
++	flag = of_property_read_bool(np, "drv-vbus");
++	if (flag)
++		uphy->flags |= ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT;
++
++	uphy->usb_phy = otg_ulpi_create(&ulpi_viewport_access_ops, uphy->flags);
++
++	uphy->usb_phy->dev = &pdev->dev;
++
++	uphy->usb_phy->io_priv = uphy->regs + uphy->vp_offset;
++
++	ret = usb_add_phy_dev(uphy->usb_phy);
++	if (ret < 0)
++		return ret;
++
++	return 0;
++}
++
++static int ulpi_phy_remove(struct platform_device *pdev)
++{
++	struct ulpi_phy *uphy = platform_get_drvdata(pdev);
++
++	usb_remove_phy(uphy->usb_phy);
++
++	return 0;
++}
++
++static const struct of_device_id ulpi_phy_table[] = {
++	{ .compatible = "ulpi-phy" },
++	{ },
++};
++MODULE_DEVICE_TABLE(of, ulpi_phy_table);
++
++static struct platform_driver ulpi_phy_driver = {
++	.probe		= ulpi_phy_probe,
++	.remove		= ulpi_phy_remove,
++	.driver		= {
++		.name	= "ulpi-phy",
++		.of_match_table = ulpi_phy_table,
++	},
++};
++module_platform_driver(ulpi_phy_driver);
++
++MODULE_DESCRIPTION("ULPI PHY driver");
++MODULE_LICENSE("GPL v2");
+diff -rupN old/linux-5.10/include/linux/usb/chipidea.h linux-5.10/include/linux/usb/chipidea.h
+--- old/linux-5.10/include/linux/usb/chipidea.h
++++ linux-5.10/include/linux/usb/chipidea.h
+@@ -62,6 +62,7 @@ struct ci_hdrc_platform_data {
+ #define CI_HDRC_REQUIRES_ALIGNED_DMA	BIT(13)
+ #define CI_HDRC_IMX_IS_HSIC		BIT(14)
+ #define CI_HDRC_PMQOS			BIT(15)
++#define CI_HDRC_PHY_VBUS_CONTROL	BIT(16)
+ 	enum usb_dr_mode	dr_mode;
+ #define CI_HDRC_CONTROLLER_RESET_EVENT		0
+ #define CI_HDRC_CONTROLLER_STOPPED_EVENT	1
diff --git a/patches/u-boot-2021.04.patch b/patches/u-boot-2021.04.patch
new file mode 100644
index 0000000000000000000000000000000000000000..c9223599e86eb6b4f48407080ca17a51b89424d3
--- /dev/null
+++ b/patches/u-boot-2021.04.patch
@@ -0,0 +1,43 @@
+diff -rupN old/u-boot-2021.04/arch/arm/dts/Makefile u-boot-2021.04/arch/arm/dts/Makefile
+--- old/u-boot-2021.04/arch/arm/dts/Makefile
++++ u-boot-2021.04/arch/arm/dts/Makefile
+@@ -286,7 +286,8 @@ dtb-$(CONFIG_ARCH_ZYNQ) += \
+ 	zynq-zturn.dtb \
+ 	zynq-zturn-v5.dtb \
+ 	zynq-zybo.dtb \
+-	zynq-zybo-z7.dtb
++	zynq-zybo-z7.dtb \
++	zynq-red-pitaya.dtb
+ dtb-$(CONFIG_ARCH_ZYNQMP) += \
+ 	avnet-ultra96-rev1.dtb			\
+ 	avnet-ultrazedev-cc-v1.0-ultrazedev-som-v1.0.dtb	\
+diff -rupN old/u-boot-2021.04/board/xilinx/zynq/board.c u-boot-2021.04/board/xilinx/zynq/board.c
+--- old/u-boot-2021.04/board/xilinx/zynq/board.c
++++ u-boot-2021.04/board/xilinx/zynq/board.c
+@@ -37,12 +37,12 @@ int board_late_init(void)
+ 	const char *mode;
+ 	char *new_targets;
+ 	char *env_targets;
+-
++/*
+ 	if (!(gd->flags & GD_FLG_ENV_DEFAULT)) {
+ 		debug("Saved variables - Skipping\n");
+ 		return 0;
+ 	}
+-
++*/
+ 	if (!CONFIG_IS_ENABLED(ENV_VARS_UBOOT_RUNTIME_CONFIG))
+ 		return 0;
+ 
+diff -rupN old/u-boot-2021.04/common/main.c u-boot-2021.04/common/main.c
+--- old/u-boot-2021.04/common/main.c
++++ u-boot-2021.04/common/main.c
+@@ -61,6 +61,8 @@ void main_loop(void)
+ 	if (cli_process_fdt(&s))
+ 		cli_secure_boot_cmd(s);
+ 
++	env_set("sdboot", "echo Importing environment from SD... && mmcinfo && load mmc 0 0x2000000 uEnv.txt && env import -t 0x2000000 ${filesize} && boot");
++
+ 	autoboot_command(s);
+ 
+ 	cli_loop();
diff --git a/patches/xilinx_devcfg.c b/patches/xilinx_devcfg.c
new file mode 100644
index 0000000000000000000000000000000000000000..ea36195621022c59a3f49ba02d4ea3e672489d56
--- /dev/null
+++ b/patches/xilinx_devcfg.c
@@ -0,0 +1,2160 @@
+/*
+ * Xilinx Zynq Device Config driver
+ *
+ * Copyright (c) 2011 - 2013 Xilinx Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/cdev.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/sysctl.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#define DRIVER_NAME "xdevcfg"
+#define XDEVCFG_DEVICES 1
+
+/* An array, which is set to true when the device is registered. */
+static DEFINE_MUTEX(xdevcfg_mutex);
+
+/* Constant Definitions */
+#define XDCFG_CTRL_OFFSET		0x00 /* Control Register */
+#define XDCFG_LOCK_OFFSET		0x04 /* Lock Register */
+#define XDCFG_INT_STS_OFFSET		0x0C /* Interrupt Status Register */
+#define XDCFG_INT_MASK_OFFSET		0x10 /* Interrupt Mask Register */
+#define XDCFG_STATUS_OFFSET		0x14 /* Status Register */
+#define XDCFG_DMA_SRC_ADDR_OFFSET	0x18 /* DMA Source Address Register */
+#define XDCFG_DMA_DEST_ADDR_OFFSET	0x1C /* DMA Destination Address Reg */
+#define XDCFG_DMA_SRC_LEN_OFFSET	0x20 /* DMA Source Transfer Length */
+#define XDCFG_DMA_DEST_LEN_OFFSET	0x24 /* DMA Destination Transfer */
+#define XDCFG_UNLOCK_OFFSET		0x34 /* Unlock Register */
+#define XDCFG_MCTRL_OFFSET		0x80 /* Misc. Control Register */
+
+/* Control Register Bit definitions */
+#define XDCFG_CTRL_PCFG_PROG_B_MASK	0x40000000 /* Program signal to
+						    * Reset FPGA
+						    */
+#define XDCFG_CTRL_PCAP_PR_MASK		0x08000000 /* Enable PCAP for PR */
+#define XDCFG_CTRL_PCAP_MODE_MASK	0x04000000 /* Enable PCAP */
+#define XDCFG_CTRL_PCAP_RATE_EN_MASK  0x02000000 /* Enable PCAP Quad Rate */
+#define XDCFG_CTRL_PCFG_AES_EN_MASK	0x00000E00 /* AES Enable Mask */
+#define XDCFG_CTRL_SEU_EN_MASK		0x00000100 /* SEU Enable Mask */
+#define XDCFG_CTRL_SPNIDEN_MASK		0x00000040 /* Secure Non Invasive
+						    *  Debug Enable
+						    */
+#define XDCFG_CTRL_SPIDEN_MASK		0x00000020 /* Secure Invasive
+						    *  Debug Enable
+						    */
+#define XDCFG_CTRL_NIDEN_MASK		0x00000010 /* Non-Invasive Debug
+						    *  Enable
+						    */
+#define XDCFG_CTRL_DBGEN_MASK		0x00000008 /* Invasive Debug
+						    *  Enable
+						    */
+#define XDCFG_CTRL_DAP_EN_MASK		0x00000007 /* DAP Enable Mask */
+
+/* Lock register bit definitions */
+
+#define XDCFG_LOCK_AES_EN_MASK		0x00000008 /* Lock AES_EN update */
+#define XDCFG_LOCK_SEU_MASK		0x00000004 /* Lock SEU_En update */
+#define XDCFG_LOCK_DBG_MASK		0x00000001 /* This bit locks
+						    *  security config
+						    *  including: DAP_En,
+						    *  DBGEN,NIDEN, SPNIEN
+						    */
+
+/* Miscellaneous Control Register bit definitions */
+#define XDCFG_MCTRL_PCAP_LPBK_MASK	0x00000010 /* Internal PCAP loopback */
+
+/* Status register bit definitions */
+#define XDCFG_STATUS_PCFG_INIT_MASK	0x00000010 /* FPGA init status */
+
+/* Interrupt Status/Mask Register Bit definitions */
+#define XDCFG_IXR_DMA_DONE_MASK		0x00002000 /* DMA Command Done */
+#define XDCFG_IXR_D_P_DONE_MASK		0x00001000 /* DMA and PCAP Cmd Done */
+#define XDCFG_IXR_PCFG_DONE_MASK	0x00000004 /* FPGA programmed */
+#define XDCFG_IXR_ERROR_FLAGS_MASK	0x00F0F860
+#define XDCFG_IXR_ALL_MASK		0xF8F7F87F
+/* Miscellaneous constant values */
+#define XDCFG_DMA_INVALID_ADDRESS	0xFFFFFFFF  /* Invalid DMA address */
+
+static const char * const fclk_name[] = {
+	"fclk0",
+	"fclk1",
+	"fclk2",
+	"fclk3"
+};
+#define NUMFCLKS ARRAY_SIZE(fclk_name)
+
+/**
+ * struct xdevcfg_drvdata - Device Configuration driver structure
+ *
+ * @dev: Pointer to the device structure
+ * @cdev: Instance of the cdev structure
+ * @devt: Pointer to the dev_t structure
+ * @class: Pointer to device class
+ * @fclk_class: Pointer to fclk device class
+ * @dma_done: The dma_done status bit for the DMA command completion
+ * @error_status: The error status captured during the DMA transfer
+ * @irq: Interrupt number
+ * @clk: Peripheral clock for devcfg
+ * @fclk: Array holding references to the FPGA clocks
+ * @fclk_exported: Flag inidcating whether an FPGA clock is exported
+ * @is_open: The status bit to indicate whether the device is opened
+ * @sem: Instance for the mutex
+ * @lock: Instance of spinlock
+ * @base_address: The virtual device base address of the device registers
+ * @ep107: Flags is used to identify the platform
+ * @endian_swap: Flags is used to identify the endianness format
+ * @residue_buf: Array holding stragglers from last time (0 to 3 bytes)
+ * @residue_len: stragglers length in bytes
+ * @is_partial_bitstream: Status bit to indicate partial/full bitstream
+ */
+struct xdevcfg_drvdata {
+	struct device *dev;
+	struct cdev cdev;
+	dev_t devt;
+	struct class *class;
+	struct class *fclk_class;
+	int irq;
+	struct clk *clk;
+	struct clk *fclk[NUMFCLKS];
+	u8 fclk_exported[NUMFCLKS];
+	bool dma_done;
+	int error_status;
+	bool is_open;
+	struct mutex sem;
+	spinlock_t lock;
+	void __iomem *base_address;
+	int ep107;
+	bool is_partial_bitstream;
+	bool endian_swap;
+	char residue_buf[3];
+	int residue_len;
+};
+
+/**
+ * struct fclk_data - FPGA clock data
+ * @clk: Pointer to clock
+ * @enabled: Flag indicating enable status of the clock
+ * @rate_rnd: Rate to be rounded for round rate operation
+ */
+struct fclk_data {
+	struct clk *clk;
+	int enabled;
+	unsigned long rate_rnd;
+};
+
+/* Register read/write access routines */
+#define xdevcfg_writereg(offset, val)	__raw_writel(val, offset)
+#define xdevcfg_readreg(offset)		__raw_readl(offset)
+
+#define SLCR_FPGA_RST_CTRL_OFFSET	0x240 /* FPGA Software Reset Control */
+#define SLCR_LVL_SHFTR_EN_OFFSET	0x900 /* Level Shifters Enable */
+
+static struct regmap *zynq_slcr_regmap;
+
+/**
+ * zynq_slcr_write - Write to a register in SLCR block
+ *
+ * @val:	Value to write to the register
+ * @offset:	Register offset in SLCR block
+ *
+ * Return:	a negative value on error, 0 on success
+ */
+static int zynq_slcr_write(u32 val, u32 offset)
+{
+	return regmap_write(zynq_slcr_regmap, offset, val);
+}
+
+/**
+ * zynq_slcr_init_preload_fpga - Disable communication from the PL to PS.
+ */
+static void zynq_slcr_init_preload_fpga(void)
+{
+	/* Assert FPGA top level output resets */
+	zynq_slcr_write(0xF, SLCR_FPGA_RST_CTRL_OFFSET);
+
+	/* Disable level shifters */
+	zynq_slcr_write(0, SLCR_LVL_SHFTR_EN_OFFSET);
+
+	/* Enable output level shifters */
+	zynq_slcr_write(0xA, SLCR_LVL_SHFTR_EN_OFFSET);
+}
+
+/**
+ * zynq_slcr_init_postload_fpga - Re-enable communication from the PL to PS.
+ */
+static void zynq_slcr_init_postload_fpga(void)
+{
+	/* Enable level shifters */
+	zynq_slcr_write(0xf, SLCR_LVL_SHFTR_EN_OFFSET);
+
+	/* Deassert AXI interface resets */
+	zynq_slcr_write(0, SLCR_FPGA_RST_CTRL_OFFSET);
+}
+
+/**
+ * xdevcfg_reset_pl - Reset the programmable logic.
+ * @base_address:	The base address of the device.
+ *
+ * Must be called with PCAP clock enabled
+ */
+static void xdevcfg_reset_pl(void __iomem *base_address)
+{
+	/*
+	 * Create a rising edge on PCFG_INIT. PCFG_INIT follows PCFG_PROG_B,
+	 * so we need to * poll it after setting PCFG_PROG_B to make sure that
+	 * the rising edge happens.
+	 */
+	xdevcfg_writereg(base_address + XDCFG_CTRL_OFFSET,
+			(xdevcfg_readreg(base_address + XDCFG_CTRL_OFFSET) &
+			 ~XDCFG_CTRL_PCFG_PROG_B_MASK));
+	while (xdevcfg_readreg(base_address + XDCFG_STATUS_OFFSET) &
+			XDCFG_STATUS_PCFG_INIT_MASK)
+		;
+
+	usleep_range(5000, 5100);
+	xdevcfg_writereg(base_address + XDCFG_CTRL_OFFSET,
+			(xdevcfg_readreg(base_address + XDCFG_CTRL_OFFSET) |
+			 XDCFG_CTRL_PCFG_PROG_B_MASK));
+	while (!(xdevcfg_readreg(base_address + XDCFG_STATUS_OFFSET) &
+				XDCFG_STATUS_PCFG_INIT_MASK))
+		;
+}
+
+/**
+ * xdevcfg_irq - The main interrupt handler.
+ * @irq:	The interrupt number.
+ * @data:	Pointer to the driver data structure.
+ * returns: IRQ_HANDLED after the interrupt is handled.
+ **/
+static irqreturn_t xdevcfg_irq(int irq, void *data)
+{
+	u32 intr_status;
+	struct xdevcfg_drvdata *drvdata = data;
+
+	spin_lock(&drvdata->lock);
+
+	intr_status = xdevcfg_readreg(drvdata->base_address +
+					XDCFG_INT_STS_OFFSET);
+
+	/* Clear the interrupts */
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_STS_OFFSET,
+				intr_status);
+
+	if ((intr_status & XDCFG_IXR_D_P_DONE_MASK) ==
+				XDCFG_IXR_D_P_DONE_MASK)
+		drvdata->dma_done = 1;
+
+	if ((intr_status & XDCFG_IXR_ERROR_FLAGS_MASK) ==
+			XDCFG_IXR_ERROR_FLAGS_MASK)
+		drvdata->error_status = 1;
+
+	spin_unlock(&drvdata->lock);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * xdevcfg_write - The is the driver write function.
+ *
+ * @file:	Pointer to the file structure.
+ * @buf:	Pointer to the bitstream location.
+ * @count:	The number of bytes to be written.
+ * @ppos:	Pointer to the offset value
+ * returns:	Success or error status.
+ **/
+static ssize_t
+xdevcfg_write(struct file *file, const char __user *buf, size_t count,
+		loff_t *ppos)
+{
+	char *kbuf;
+	int status;
+	unsigned long timeout;
+	u32 intr_reg, dma_len;
+	dma_addr_t dma_addr;
+	u32 transfer_length = 0;
+	struct xdevcfg_drvdata *drvdata = file->private_data;
+	size_t user_count = count;
+	int i;
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	status = mutex_lock_interruptible(&drvdata->sem);
+
+	if (status)
+		goto err_clk;
+
+	dma_len = count + drvdata->residue_len;
+	kbuf = dma_alloc_coherent(drvdata->dev, dma_len, &dma_addr, GFP_KERNEL);
+	if (!kbuf) {
+		status = -ENOMEM;
+		goto err_unlock;
+	}
+
+	/* Collect stragglers from last time (0 to 3 bytes) */
+	memcpy(kbuf, drvdata->residue_buf, drvdata->residue_len);
+
+	/* Fetch user data, appending to stragglers */
+	if (copy_from_user(kbuf + drvdata->residue_len, buf, count)) {
+		status = -EFAULT;
+		goto error;
+	}
+
+	/* Include stragglers in total bytes to be handled */
+	count += drvdata->residue_len;
+
+	/* First block contains a header */
+	if (*ppos == 0 && count > 4) {
+		/* Look for sync word */
+		for (i = 0; i < count - 4; i++) {
+			if (memcmp(kbuf + i, "\x66\x55\x99\xAA", 4) == 0) {
+				pr_debug("Found normal sync word\n");
+				drvdata->endian_swap = 0;
+				break;
+			}
+			if (memcmp(kbuf + i, "\xAA\x99\x55\x66", 4) == 0) {
+				pr_debug("Found swapped sync word\n");
+				drvdata->endian_swap = 1;
+				break;
+			}
+		}
+		/* Remove the header, aligning the data on word boundary */
+		if (i != count - 4) {
+			count -= i;
+			memmove(kbuf, kbuf + i, count);
+		}
+	}
+
+	/* Save stragglers for next time */
+	drvdata->residue_len = count % 4;
+	count -= drvdata->residue_len;
+	memcpy(drvdata->residue_buf, kbuf + count, drvdata->residue_len);
+
+	/* Fixup endianess of the data */
+	if (drvdata->endian_swap) {
+		for (i = 0; i < count; i += 4) {
+			u32 *p = (u32 *)&kbuf[i];
+			*p = swab32(*p);
+		}
+	}
+
+	/* Enable DMA and error interrupts */
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_STS_OFFSET,
+				XDCFG_IXR_ALL_MASK);
+
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_MASK_OFFSET,
+				(u32) (~(XDCFG_IXR_D_P_DONE_MASK |
+				XDCFG_IXR_ERROR_FLAGS_MASK)));
+
+	drvdata->dma_done = 0;
+	drvdata->error_status = 0;
+
+	/* Initiate DMA write command */
+	if (count < 0x1000)
+		xdevcfg_writereg(drvdata->base_address +
+			XDCFG_DMA_SRC_ADDR_OFFSET, (u32)(dma_addr + 1));
+	else
+		xdevcfg_writereg(drvdata->base_address +
+			XDCFG_DMA_SRC_ADDR_OFFSET, (u32) dma_addr);
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_DEST_ADDR_OFFSET,
+				(u32)XDCFG_DMA_INVALID_ADDRESS);
+	/* Convert number of bytes to number of words.  */
+	if (count % 4)
+		transfer_length	= (count / 4 + 1);
+	else
+		transfer_length	= count / 4;
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_SRC_LEN_OFFSET,
+				transfer_length);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_DEST_LEN_OFFSET, 0);
+
+	timeout = jiffies + msecs_to_jiffies(1000);
+
+	while (!READ_ONCE(drvdata->dma_done)) {
+		if (time_after(jiffies, timeout)) {
+			status = -ETIMEDOUT;
+			goto error;
+		}
+	}
+
+	if (READ_ONCE(drvdata->error_status))
+		status = drvdata->error_status;
+
+	/* Disable the DMA and error interrupts */
+	intr_reg = xdevcfg_readreg(drvdata->base_address +
+					XDCFG_INT_MASK_OFFSET);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_MASK_OFFSET,
+				intr_reg | (XDCFG_IXR_D_P_DONE_MASK |
+				XDCFG_IXR_ERROR_FLAGS_MASK));
+
+	/* If we didn't write correctly, then bail out. */
+	if (status) {
+		status = -EFAULT;
+		goto error;
+	}
+
+	*ppos += user_count;
+	status = user_count;
+
+error:
+	dma_free_coherent(drvdata->dev, dma_len, kbuf, dma_addr);
+err_unlock:
+	mutex_unlock(&drvdata->sem);
+err_clk:
+	clk_disable(drvdata->clk);
+	return status;
+}
+
+
+/**
+ * xdevcfg_read - The is the driver read function.
+ * @file:	Pointer to the file structure.
+ * @buf:	Pointer to the bitstream location.
+ * @count:	The number of bytes read.
+ * @ppos:	Pointer to the offsetvalue
+ * returns:	Success or error status.
+ */
+static ssize_t
+xdevcfg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+	u32 *kbuf;
+	int status;
+	unsigned long timeout;
+	dma_addr_t dma_addr;
+	struct xdevcfg_drvdata *drvdata = file->private_data;
+	u32 intr_reg;
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	status = mutex_lock_interruptible(&drvdata->sem);
+	if (status)
+		goto err_clk;
+
+	/* Get new data from the ICAP, and return was requested. */
+	kbuf = dma_alloc_coherent(drvdata->dev, count, &dma_addr, GFP_KERNEL);
+	if (!kbuf) {
+		status = -ENOMEM;
+		goto err_unlock;
+	}
+
+	drvdata->dma_done = 0;
+	drvdata->error_status = 0;
+
+	/* Enable DMA and error interrupts */
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_STS_OFFSET,
+				XDCFG_IXR_ALL_MASK);
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_MASK_OFFSET,
+				(u32) (~(XDCFG_IXR_D_P_DONE_MASK |
+				XDCFG_IXR_ERROR_FLAGS_MASK)));
+	/* Initiate DMA read command */
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_SRC_ADDR_OFFSET,
+				(u32)XDCFG_DMA_INVALID_ADDRESS);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_DEST_ADDR_OFFSET,
+				(u32)dma_addr);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_SRC_LEN_OFFSET, 0);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_DMA_DEST_LEN_OFFSET,
+				count / 4);
+
+	timeout = jiffies + msecs_to_jiffies(1000);
+
+	while (!drvdata->dma_done) {
+		if (time_after(jiffies, timeout)) {
+			status = -ETIMEDOUT;
+			goto error;
+		}
+	}
+
+	if (drvdata->error_status)
+		status = drvdata->error_status;
+
+	/* Disable and clear DMA and error interrupts */
+	intr_reg = xdevcfg_readreg(drvdata->base_address +
+					XDCFG_INT_MASK_OFFSET);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_MASK_OFFSET,
+				intr_reg | (XDCFG_IXR_D_P_DONE_MASK |
+				XDCFG_IXR_ERROR_FLAGS_MASK));
+
+
+	/* If we didn't read correctly, then bail out. */
+	if (status) {
+		status = -EFAULT;
+		goto error;
+	}
+
+	/* If we fail to return the data to the user, then bail out. */
+	if (copy_to_user(buf, kbuf, count)) {
+		status = -EFAULT;
+		goto error;
+	}
+
+	status = count;
+error:
+	dma_free_coherent(drvdata->dev, count, kbuf, dma_addr);
+err_unlock:
+	mutex_unlock(&drvdata->sem);
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+static void xdevcfg_enable_partial(struct xdevcfg_drvdata *drvdata)
+{
+	u32 reg = xdevcfg_readreg(drvdata->base_address + XDCFG_CTRL_OFFSET);
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+			 reg | XDCFG_CTRL_PCAP_PR_MASK);
+}
+
+static void xdevcfg_disable_partial(struct xdevcfg_drvdata *drvdata)
+{
+	u32 reg = xdevcfg_readreg(drvdata->base_address + XDCFG_CTRL_OFFSET);
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+			 reg & ~XDCFG_CTRL_PCAP_PR_MASK);
+}
+
+/**
+ * xdevcfg_open - The is the driver open function.
+ * @inode:	Pointer to the inode structure of this device.
+ * @file:	Pointer to the file structure.
+ * returns:	Success or error status.
+ */
+static int xdevcfg_open(struct inode *inode, struct file *file)
+{
+	struct xdevcfg_drvdata *drvdata;
+	int status;
+
+	drvdata = container_of(inode->i_cdev, struct xdevcfg_drvdata, cdev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	status = mutex_lock_interruptible(&drvdata->sem);
+	if (status)
+		goto err_clk;
+
+	if (drvdata->is_open) {
+		status = -EBUSY;
+		goto error;
+	}
+
+	file->private_data = drvdata;
+	drvdata->is_open = 1;
+	drvdata->endian_swap = 0;
+	drvdata->residue_len = 0;
+
+	/*
+	 * If is_partial_bitstream is set, then PROG_B is not asserted
+	 * (xdevcfg_reset_pl function) and also zynq_slcr_init_preload_fpga and
+	 * zynq_slcr_init_postload_fpga functions are not invoked.
+	 */
+	if (drvdata->is_partial_bitstream)
+		xdevcfg_enable_partial(drvdata);
+	else
+		zynq_slcr_init_preload_fpga();
+
+	/*
+	 * Only do the reset of the PL for Zynq as it causes problems on the
+	 * EP107 and the issue is not understood, but not worth investigating
+	 * as the emulation platform is very different than silicon and not a
+	 * complete implementation. Also, do not reset if it is a partial
+	 * bitstream.
+	 */
+	if ((!drvdata->ep107) && (!drvdata->is_partial_bitstream))
+		xdevcfg_reset_pl(drvdata->base_address);
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_INT_STS_OFFSET,
+			XDCFG_IXR_PCFG_DONE_MASK);
+
+error:
+	mutex_unlock(&drvdata->sem);
+err_clk:
+	clk_disable(drvdata->clk);
+	return status;
+}
+
+/**
+ * xdevcfg_release - The is the driver release function.
+ * @inode:	Pointer to the inode structure of this device.
+ * @file:	Pointer to the file structure.
+ * returns:	Success.
+ */
+static int xdevcfg_release(struct inode *inode, struct file *file)
+{
+	struct xdevcfg_drvdata *drvdata = file->private_data;
+
+	if (drvdata->is_partial_bitstream)
+		xdevcfg_disable_partial(drvdata);
+	else
+		zynq_slcr_init_postload_fpga();
+
+	if (drvdata->residue_len)
+		dev_info(drvdata->dev, "Did not transfer last %d bytes\n",
+			 drvdata->residue_len);
+
+	drvdata->is_open = 0;
+
+	return 0;
+}
+
+static const struct file_operations xdevcfg_fops = {
+	.owner = THIS_MODULE,
+	.write = xdevcfg_write,
+	.read = xdevcfg_read,
+	.open = xdevcfg_open,
+	.release = xdevcfg_release,
+};
+
+/*
+ * The following functions are the routines provided to the user to
+ * set/get the status bit value in the control/lock registers.
+ */
+
+/**
+ * xdevcfg_set_dap_en - This function sets the DAP bits in the
+ * control register with the given value.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	negative error if the string could not be converted
+ *		or the size of the buffer.
+ */
+static ssize_t xdevcfg_set_dap_en(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_unlock;
+
+	if (mask_bit > 7) {
+		status = -EINVAL;
+		goto err_unlock;
+	}
+
+	xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+			(ctrl_reg_status |
+			 (((u32)mask_bit) & XDCFG_CTRL_DAP_EN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_unlock:
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_dap_en_status - The function returns the DAP_EN bits status in
+ * the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	Size of the buffer.
+ */
+static ssize_t xdevcfg_show_dap_en_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 dap_en_status;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	dap_en_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET) & XDCFG_CTRL_DAP_EN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", dap_en_status);
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_dap, 0644, xdevcfg_show_dap_en_status,
+				xdevcfg_set_dap_en);
+
+/**
+ * xdevcfg_set_dbgen - This function sets the DBGEN bit in the
+ * control register with the given value.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_dbgen(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status | XDCFG_CTRL_DBGEN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status & (~XDCFG_CTRL_DBGEN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_dbgen_status - The function returns the DBGEN bit status in
+ * the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	Size of the buffer.
+ */
+static ssize_t xdevcfg_show_dbgen_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 dbgen_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	dbgen_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET) & XDCFG_CTRL_DBGEN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (dbgen_status >> 3));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_dbg_in, 0644, xdevcfg_show_dbgen_status,
+				xdevcfg_set_dbgen);
+
+/**
+ * xdevcfg_set_niden - This function sets the NIDEN bit in the
+ * control register with the given value.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_niden(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status | XDCFG_CTRL_NIDEN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status & (~XDCFG_CTRL_NIDEN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_niden_status - The function returns the NIDEN bit status in
+ * the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	Size of the buffer.
+ */
+static ssize_t xdevcfg_show_niden_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 niden_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	niden_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET) & XDCFG_CTRL_NIDEN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (niden_status >> 4));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_dbg_nonin, 0644, xdevcfg_show_niden_status,
+			xdevcfg_set_niden);
+
+/**
+ * xdevcfg_set_spiden - This function sets the SPIDEN bit in the
+ * control register with the given value.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_spiden(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status | XDCFG_CTRL_SPIDEN_MASK));
+	else
+
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status & (~XDCFG_CTRL_SPIDEN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_spiden_status - The function returns the SPIDEN bit status in
+ * the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	Size of the buffer.
+ */
+static ssize_t xdevcfg_show_spiden_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 spiden_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	spiden_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_CTRL_OFFSET) & XDCFG_CTRL_SPIDEN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (spiden_status >> 5));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_sec_dbg_in, 0644, xdevcfg_show_spiden_status,
+				xdevcfg_set_spiden);
+
+/**
+ * xdevcfg_set_spniden - This function sets the SPNIDEN bit in the
+ * control register with the given value.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or the size of buffer
+ */
+static ssize_t xdevcfg_set_spniden(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status | XDCFG_CTRL_SPNIDEN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status & (~XDCFG_CTRL_SPNIDEN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_spniden_status - The function returns the SPNIDEN bit status
+ * in the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	Size of the buffer.
+ */
+static ssize_t xdevcfg_show_spniden_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 spniden_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	spniden_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_CTRL_OFFSET) & XDCFG_CTRL_SPNIDEN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (spniden_status >> 6));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_sec_dbg_nonin, 0644, xdevcfg_show_spniden_status,
+					xdevcfg_set_spniden);
+
+/**
+ * xdevcfg_set_seu - This function sets the SEU_EN bit in the
+ * control register with the given value
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_seu(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status | XDCFG_CTRL_SEU_EN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status & (~XDCFG_CTRL_SEU_EN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_seu_status - The function returns the SEU_EN bit status
+ * in the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_seu_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 seu_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	seu_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_CTRL_OFFSET) & XDCFG_CTRL_SEU_EN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (seu_status > 8));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_seu, 0644, xdevcfg_show_seu_status, xdevcfg_set_seu);
+
+/**
+ * xdevcfg_set_aes - This function sets the AES_EN bits in the
+ * control register with either all 1s or all 0s.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ *
+ * The user must send only one bit in the buffer to notify whether he wants to
+ * either set or reset these bits.
+ */
+static ssize_t xdevcfg_set_aes(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 ctrl_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	int status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	ctrl_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_CTRL_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status < 0)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status |
+				 XDCFG_CTRL_PCFG_AES_EN_MASK |
+				 XDCFG_CTRL_PCAP_RATE_EN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET,
+				(ctrl_reg_status &
+				 ~(XDCFG_CTRL_PCFG_AES_EN_MASK |
+				 XDCFG_CTRL_PCAP_RATE_EN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_aes_status - The function returns the AES_EN bit status
+ * in the control register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_aes_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 aes_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	aes_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_CTRL_OFFSET) & XDCFG_CTRL_PCFG_AES_EN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (aes_status >> 9));
+
+	return status;
+}
+
+static DEVICE_ATTR(enable_aes, 0644, xdevcfg_show_aes_status, xdevcfg_set_aes);
+
+/**
+ * xdevcfg_set_aes_en_lock - This function sets the LOCK_AES_EN bit in the
+ * lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_aes_en_lock(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 aes_en_lock_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	aes_en_lock_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_LOCK_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(aes_en_lock_status | XDCFG_LOCK_AES_EN_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(aes_en_lock_status &
+				 (~XDCFG_LOCK_AES_EN_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_aes_en_lock_status - The function returns the LOCK_AES_EN bit
+ * status in the lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_aes_en_lock_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 aes_en_lock_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	aes_en_lock_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_LOCK_OFFSET) & XDCFG_LOCK_AES_EN_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (aes_en_lock_status >> 3));
+
+	return status;
+}
+
+static DEVICE_ATTR(aes_en_lock, 0644, xdevcfg_show_aes_en_lock_status,
+				xdevcfg_set_aes_en_lock);
+
+/**
+ * xdevcfg_set_seu_lock - This function sets the LOCK_SEU bit in the
+ * lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_seu_lock(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 seu_lock_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	seu_lock_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_LOCK_OFFSET);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(seu_lock_status | XDCFG_LOCK_SEU_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(seu_lock_status  & (~XDCFG_LOCK_SEU_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_seu_lock_status - The function returns the LOCK_SEU bit
+ * status in the lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_seu_lock_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 seu_lock_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	seu_lock_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_LOCK_OFFSET) & XDCFG_LOCK_SEU_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (seu_lock_status >> 2));
+
+	return status;
+}
+
+static DEVICE_ATTR(seu_lock, 0644, xdevcfg_show_seu_lock_status,
+					xdevcfg_set_seu_lock);
+
+/**
+ * xdevcfg_set_dbg_lock - This function sets the LOCK_DBG bit in the
+ * lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_dbg_lock(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	u32 lock_reg_status;
+	unsigned long flags;
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	lock_reg_status = xdevcfg_readreg(drvdata->base_address +
+				XDCFG_LOCK_OFFSET);
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		goto err_clk;
+
+	if (mask_bit > 1) {
+		status = -EINVAL;
+		goto err_clk;
+	}
+
+	spin_lock_irqsave(&drvdata->lock, flags);
+
+	if (mask_bit)
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(lock_reg_status | XDCFG_LOCK_DBG_MASK));
+	else
+		xdevcfg_writereg(drvdata->base_address + XDCFG_LOCK_OFFSET,
+				(lock_reg_status & (~XDCFG_LOCK_DBG_MASK)));
+
+	spin_unlock_irqrestore(&drvdata->lock, flags);
+
+	clk_disable(drvdata->clk);
+
+	return size;
+
+err_clk:
+	clk_disable(drvdata->clk);
+
+	return status;
+}
+
+/**
+ * xdevcfg_show_dbg_lock_status - The function returns the LOCK_DBG bit
+ * status in the lock register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_dbg_lock_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 dbg_lock_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	dbg_lock_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_LOCK_OFFSET) & XDCFG_LOCK_DBG_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", dbg_lock_status);
+
+	return status;
+}
+
+static DEVICE_ATTR(dbg_lock, 0644, xdevcfg_show_dbg_lock_status,
+				xdevcfg_set_dbg_lock);
+
+/**
+ * xdevcfg_show_prog_done_status - The function returns the PROG_DONE bit
+ * status in the interrupt status register.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_prog_done_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	u32 prog_done_status;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = clk_enable(drvdata->clk);
+	if (status)
+		return status;
+
+	prog_done_status = xdevcfg_readreg(drvdata->base_address +
+			XDCFG_INT_STS_OFFSET) & XDCFG_IXR_PCFG_DONE_MASK;
+
+	clk_disable(drvdata->clk);
+
+	status = sprintf(buf, "%d\n", (prog_done_status >> 2));
+
+	return status;
+}
+
+static DEVICE_ATTR(prog_done, 0644, xdevcfg_show_prog_done_status,
+				NULL);
+
+/**
+ * xdevcfg_set_is_partial_bitstream - This function sets the
+ * is_partial_bitstream variable. If is_partial_bitstream is set,
+ * then PROG_B is not asserted (xdevcfg_reset_pl) and also
+ * zynq_slcr_init_preload_fpga and zynq_slcr_init_postload_fpga functions
+ * are not invoked.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * @size:	The number of bytes used from the buffer
+ * returns:	-EINVAL if invalid parameter is sent or size
+ */
+static ssize_t xdevcfg_set_is_partial_bitstream(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	unsigned long mask_bit;
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = kstrtoul(buf, 10, &mask_bit);
+
+	if (status)
+		return status;
+
+	if (mask_bit > 1)
+		return -EINVAL;
+
+	if (mask_bit)
+		drvdata->is_partial_bitstream = 1;
+	else
+		drvdata->is_partial_bitstream = 0;
+
+	return size;
+}
+
+/**
+ * xdevcfg_show_is_partial_bitstream_status - The function returns the
+ * value of is_partial_bitstream variable.
+ * @dev:	Pointer to the device structure.
+ * @attr:	Pointer to the device attribute structure.
+ * @buf:	Pointer to the buffer location for the configuration
+ *		data.
+ * returns:	size of the buffer.
+ */
+static ssize_t xdevcfg_show_is_partial_bitstream_status(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	ssize_t status;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	status = sprintf(buf, "%d\n", drvdata->is_partial_bitstream);
+
+	return status;
+}
+
+static DEVICE_ATTR(is_partial_bitstream, 0644,
+				xdevcfg_show_is_partial_bitstream_status,
+				xdevcfg_set_is_partial_bitstream);
+
+static const struct attribute *xdevcfg_attrs[] = {
+	&dev_attr_prog_done.attr, /* PCFG_DONE bit in Intr Status register */
+	&dev_attr_dbg_lock.attr, /* Debug lock bit in Lock register */
+	&dev_attr_seu_lock.attr, /* SEU lock bit in Lock register */
+	&dev_attr_aes_en_lock.attr, /* AES EN lock bit in Lock register */
+	&dev_attr_enable_aes.attr, /* AES EN bit in Control register */
+	&dev_attr_enable_seu.attr, /* SEU EN bit in Control register */
+	&dev_attr_enable_sec_dbg_nonin.attr, /*SPNIDEN bit in Control register*/
+	&dev_attr_enable_sec_dbg_in.attr, /*SPIDEN bit in Control register */
+	&dev_attr_enable_dbg_nonin.attr, /* NIDEN bit in Control register */
+	&dev_attr_enable_dbg_in.attr, /* DBGEN bit in Control register */
+	&dev_attr_enable_dap.attr, /* DAP_EN bits in Control register */
+	&dev_attr_is_partial_bitstream.attr, /* Flag for partial bitstream */
+	NULL,
+};
+
+
+static const struct attribute_group xdevcfg_attr_group = {
+	.attrs = (struct attribute **) xdevcfg_attrs,
+};
+
+static ssize_t fclk_enable_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%u\n", pdata->enabled);
+}
+
+static ssize_t fclk_enable_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	unsigned long enable;
+	int ret;
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	ret = kstrtoul(buf, 0, &enable);
+	if (ret)
+		return -EINVAL;
+
+	enable = !!enable;
+	if (enable == pdata->enabled)
+		return count;
+
+	if (enable)
+		ret = clk_enable(pdata->clk);
+	else
+		clk_disable(pdata->clk);
+
+	if (ret)
+		return ret;
+
+	pdata->enabled = enable;
+	return count;
+}
+
+static DEVICE_ATTR(enable, 0644, fclk_enable_show, fclk_enable_store);
+
+static ssize_t fclk_set_rate_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%lu\n", clk_get_rate(pdata->clk));
+}
+
+static ssize_t fclk_set_rate_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret = 0;
+	unsigned long rate;
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	ret = kstrtoul(buf, 0, &rate);
+	if (ret)
+		return -EINVAL;
+
+	rate = clk_round_rate(pdata->clk, rate);
+	ret = clk_set_rate(pdata->clk, rate);
+
+	return ret ? ret : count;
+}
+
+static DEVICE_ATTR(set_rate, 0644, fclk_set_rate_show, fclk_set_rate_store);
+
+static ssize_t fclk_round_rate_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	return scnprintf(buf, PAGE_SIZE, "%lu => %lu\n", pdata->rate_rnd,
+			clk_round_rate(pdata->clk, pdata->rate_rnd));
+}
+
+static ssize_t fclk_round_rate_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	int ret = 0;
+	unsigned long rate;
+	struct fclk_data *pdata = dev_get_drvdata(dev);
+
+	ret = kstrtoul(buf, 0, &rate);
+	if (ret)
+		return -EINVAL;
+
+	pdata->rate_rnd = rate;
+
+	return count;
+}
+
+static DEVICE_ATTR(round_rate, 0644, fclk_round_rate_show,
+		fclk_round_rate_store);
+
+static const struct attribute *fclk_ctrl_attrs[] = {
+	&dev_attr_enable.attr,
+	&dev_attr_set_rate.attr,
+	&dev_attr_round_rate.attr,
+	NULL,
+};
+
+static const struct attribute_group fclk_ctrl_attr_grp = {
+	.attrs = (struct attribute **)fclk_ctrl_attrs,
+};
+
+static ssize_t xdevcfg_fclk_export_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	int i, ret;
+	struct device *subdev;
+	struct fclk_data *fdata;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		if (!strncmp(buf, fclk_name[i], strlen(fclk_name[i])))
+			break;
+	}
+
+	if (i < NUMFCLKS && !drvdata->fclk_exported[i]) {
+		drvdata->fclk_exported[i] = 1;
+		subdev = device_create(drvdata->fclk_class, dev, MKDEV(0, 0),
+				NULL, fclk_name[i]);
+		if (IS_ERR(subdev))
+			return PTR_ERR(subdev);
+		ret = clk_prepare(drvdata->fclk[i]);
+		if (ret)
+			return ret;
+		fdata = kzalloc(sizeof(*fdata), GFP_KERNEL);
+		if (!fdata) {
+			ret = -ENOMEM;
+			goto err_unprepare;
+		}
+		fdata->clk = drvdata->fclk[i];
+		dev_set_drvdata(subdev, fdata);
+		ret = sysfs_create_group(&subdev->kobj, &fclk_ctrl_attr_grp);
+		if (ret)
+			goto err_free;
+	} else {
+		return -EINVAL;
+	}
+
+	return size;
+
+err_free:
+	kfree(fdata);
+err_unprepare:
+	clk_unprepare(drvdata->fclk[i]);
+
+	return ret;
+}
+
+static ssize_t xdevcfg_fclk_export_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int i;
+	ssize_t count = 0;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		if (!drvdata->fclk_exported[i])
+			count += scnprintf(buf + count, PAGE_SIZE - count,
+					"%s\n", fclk_name[i]);
+	}
+	return count;
+}
+
+static DEVICE_ATTR(fclk_export, 0644, xdevcfg_fclk_export_show,
+		xdevcfg_fclk_export_store);
+
+static int match_fclk(struct device *dev, const void *data)
+{
+	struct fclk_data *fdata = dev_get_drvdata(dev);
+
+	return fdata->clk == data;
+}
+
+static ssize_t xdevcfg_fclk_unexport_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	int i;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		if (!strncmp(buf, fclk_name[i], strlen(fclk_name[i])))
+			break;
+	}
+
+	if (i < NUMFCLKS && drvdata->fclk_exported[i]) {
+		struct fclk_data *fdata;
+		struct device *subdev;
+
+		drvdata->fclk_exported[i] = 0;
+		subdev = class_find_device(drvdata->fclk_class, NULL,
+				drvdata->fclk[i], match_fclk);
+		fdata = dev_get_drvdata(subdev);
+		if (fdata->enabled)
+			clk_disable(fdata->clk);
+		clk_unprepare(fdata->clk);
+		kfree(fdata);
+		device_unregister(subdev);
+		put_device(subdev);
+	} else {
+		return -EINVAL;
+	}
+
+	return size;
+}
+
+static ssize_t xdevcfg_fclk_unexport_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int i;
+	ssize_t count = 0;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		if (drvdata->fclk_exported[i])
+			count += scnprintf(buf + count, PAGE_SIZE - count,
+					"%s\n", fclk_name[i]);
+	}
+	return count;
+}
+
+static DEVICE_ATTR(fclk_unexport, 0644, xdevcfg_fclk_unexport_show,
+		xdevcfg_fclk_unexport_store);
+
+static const struct attribute *fclk_exp_attrs[] = {
+	&dev_attr_fclk_export.attr,
+	&dev_attr_fclk_unexport.attr,
+	NULL,
+};
+
+static const struct attribute_group fclk_exp_attr_grp = {
+	.attrs = (struct attribute **)fclk_exp_attrs,
+};
+
+static void xdevcfg_fclk_init(struct device *dev)
+{
+	int i;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		drvdata->fclk[i] = clk_get(dev, fclk_name[i]);
+		if (IS_ERR(drvdata->fclk[i])) {
+			dev_warn(dev, "fclk not found\n");
+			return;
+		}
+	}
+
+	drvdata->fclk_class = class_create(THIS_MODULE, "fclk");
+	if (IS_ERR(drvdata->fclk_class)) {
+		dev_warn(dev, "failed to create fclk class\n");
+		return;
+	}
+
+	if (sysfs_create_group(&dev->kobj, &fclk_exp_attr_grp))
+		dev_warn(dev, "failed to create sysfs entries\n");
+}
+
+static void xdevcfg_fclk_remove(struct device *dev)
+{
+	int i;
+	struct xdevcfg_drvdata *drvdata = dev_get_drvdata(dev);
+
+	for (i = 0; i < NUMFCLKS; i++) {
+		if (drvdata->fclk_exported[i]) {
+			struct fclk_data *fdata;
+			struct device *subdev;
+
+			drvdata->fclk_exported[i] = 0;
+			subdev = class_find_device(drvdata->fclk_class, NULL,
+					drvdata->fclk[i], match_fclk);
+			fdata = dev_get_drvdata(subdev);
+			if (fdata->enabled)
+				clk_disable(fdata->clk);
+			clk_unprepare(fdata->clk);
+			kfree(fdata);
+			device_unregister(subdev);
+			put_device(subdev);
+
+		}
+	}
+
+	class_destroy(drvdata->fclk_class);
+	sysfs_remove_group(&dev->kobj, &fclk_exp_attr_grp);
+
+}
+
+/**
+ * xdevcfg_drv_probe -  Probe call for the device.
+ *
+ * @pdev:	handle to the platform device structure.
+ *
+ * Returns: 0 on success, negative error otherwise.
+ *
+ * It does all the memory allocation and registration for the device.
+ */
+static int xdevcfg_drv_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct xdevcfg_drvdata *drvdata;
+	dev_t devt;
+	int retval;
+	u32 ctrlreg;
+	struct device_node *np;
+	const void *prop;
+	int size;
+	struct device *dev;
+
+	zynq_slcr_regmap = syscon_regmap_lookup_by_compatible("xlnx,zynq-slcr");
+	if (IS_ERR(zynq_slcr_regmap)) {
+		pr_err("%s: failed to find zynq-slcr\n", __func__);
+		return -ENODEV;
+	}
+
+	drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	drvdata->base_address = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(drvdata->base_address))
+		return PTR_ERR(drvdata->base_address);
+
+	drvdata->irq = platform_get_irq(pdev, 0);
+	retval = devm_request_irq(&pdev->dev, drvdata->irq, &xdevcfg_irq,
+				0, dev_name(&pdev->dev), drvdata);
+	if (retval) {
+		dev_err(&pdev->dev, "No IRQ available");
+		return retval;
+	}
+
+	platform_set_drvdata(pdev, drvdata);
+	spin_lock_init(&drvdata->lock);
+	mutex_init(&drvdata->sem);
+	drvdata->is_open = 0;
+	drvdata->is_partial_bitstream = 0;
+	drvdata->dma_done = 0;
+	drvdata->error_status = 0;
+	dev_info(&pdev->dev, "ioremap %pa to %p\n",
+		 &res->start, drvdata->base_address);
+
+	drvdata->clk = devm_clk_get(&pdev->dev, "ref_clk");
+	if (IS_ERR(drvdata->clk)) {
+		dev_err(&pdev->dev, "input clock not found\n");
+		return PTR_ERR(drvdata->clk);
+	}
+
+	retval = clk_prepare_enable(drvdata->clk);
+	if (retval) {
+		dev_err(&pdev->dev, "unable to enable clock\n");
+		return retval;
+	}
+
+	/*
+	 * Figure out from the device tree if this is running on the EP107
+	 * emulation platform as it doesn't match the silicon exactly and the
+	 * driver needs to work accordingly.
+	 */
+	np = of_get_next_parent(pdev->dev.of_node);
+	np = of_get_next_parent(np);
+	prop = of_get_property(np, "compatible", &size);
+
+	if (prop != NULL) {
+		if ((strcmp((const char *)prop, "xlnx,zynq-ep107")) == 0)
+			drvdata->ep107 = 1;
+		else
+			drvdata->ep107 = 0;
+	}
+
+	/* Unlock the device */
+	xdevcfg_writereg(drvdata->base_address + XDCFG_UNLOCK_OFFSET,
+				0x757BDF0D);
+
+	/*
+	 * Set the configuration register with the following options
+	 *  - Reset FPGA
+	 *  - Enable the PCAP interface
+	 *  - Set the throughput rate for maximum speed
+	 *  - Set the CPU in user mode
+	 */
+	ctrlreg = xdevcfg_readreg(drvdata->base_address + XDCFG_CTRL_OFFSET);
+	ctrlreg &= ~XDCFG_CTRL_PCAP_PR_MASK;
+	ctrlreg |= XDCFG_CTRL_PCFG_PROG_B_MASK | XDCFG_CTRL_PCAP_MODE_MASK;
+	xdevcfg_writereg(drvdata->base_address + XDCFG_CTRL_OFFSET, ctrlreg);
+
+	/* Ensure internal PCAP loopback is disabled */
+	ctrlreg = xdevcfg_readreg(drvdata->base_address + XDCFG_MCTRL_OFFSET);
+	xdevcfg_writereg(drvdata->base_address + XDCFG_MCTRL_OFFSET,
+				(~XDCFG_MCTRL_PCAP_LPBK_MASK &
+				ctrlreg));
+
+
+	retval = alloc_chrdev_region(&devt, 0, XDEVCFG_DEVICES, DRIVER_NAME);
+	if (retval < 0)
+		goto failed5;
+
+	drvdata->devt = devt;
+
+	cdev_init(&drvdata->cdev, &xdevcfg_fops);
+	drvdata->cdev.owner = THIS_MODULE;
+	retval = cdev_add(&drvdata->cdev, devt, 1);
+	if (retval) {
+		dev_err(&pdev->dev, "cdev_add() failed\n");
+		goto failed6;
+	}
+
+	drvdata->class = class_create(THIS_MODULE, DRIVER_NAME);
+	if (IS_ERR(drvdata->class)) {
+		dev_err(&pdev->dev, "failed to create class\n");
+		goto failed6;
+	}
+
+	dev = device_create(drvdata->class, &pdev->dev, devt, drvdata,
+			DRIVER_NAME);
+	if (IS_ERR(dev)) {
+		dev_err(&pdev->dev, "unable to create device\n");
+		goto failed7;
+	}
+
+	drvdata->dev = &pdev->dev;
+
+	/* create sysfs files for the device */
+	retval = sysfs_create_group(&(pdev->dev.kobj), &xdevcfg_attr_group);
+	if (retval) {
+		dev_err(&pdev->dev, "Failed to create sysfs attr group\n");
+		cdev_del(&drvdata->cdev);
+		goto failed8;
+	}
+
+	xdevcfg_fclk_init(&pdev->dev);
+
+	clk_disable(drvdata->clk);
+
+	return 0;		/* Success */
+
+failed8:
+	device_destroy(drvdata->class, drvdata->devt);
+failed7:
+	class_destroy(drvdata->class);
+failed6:
+	/* Unregister char driver */
+	unregister_chrdev_region(devt, XDEVCFG_DEVICES);
+failed5:
+	clk_disable_unprepare(drvdata->clk);
+
+	return retval;
+}
+
+/**
+ * xdevcfg_drv_remove -  Remove call for the device.
+ *
+ * @pdev:	handle to the platform device structure.
+ *
+ * Returns: 0 or error status.
+ *
+ * Unregister the device after releasing the resources.
+ */
+static int xdevcfg_drv_remove(struct platform_device *pdev)
+{
+	struct xdevcfg_drvdata *drvdata;
+
+	drvdata = platform_get_drvdata(pdev);
+
+	if (!drvdata)
+		return -ENODEV;
+
+	unregister_chrdev_region(drvdata->devt, XDEVCFG_DEVICES);
+
+	sysfs_remove_group(&pdev->dev.kobj, &xdevcfg_attr_group);
+
+	xdevcfg_fclk_remove(&pdev->dev);
+	device_destroy(drvdata->class, drvdata->devt);
+	class_destroy(drvdata->class);
+	cdev_del(&drvdata->cdev);
+	clk_unprepare(drvdata->clk);
+
+	return 0;		/* Success */
+}
+
+static const struct of_device_id xdevcfg_of_match[] = {
+	{ .compatible = "xlnx,zynq-devcfg-1.0", },
+	{ /* end of table */}
+};
+MODULE_DEVICE_TABLE(of, xdevcfg_of_match);
+
+/* Driver Structure */
+static struct platform_driver xdevcfg_platform_driver = {
+	.probe = xdevcfg_drv_probe,
+	.remove = xdevcfg_drv_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = DRIVER_NAME,
+		.of_match_table = xdevcfg_of_match,
+	},
+};
+
+module_platform_driver(xdevcfg_platform_driver);
+
+MODULE_AUTHOR("Xilinx, Inc");
+MODULE_DESCRIPTION("Xilinx Device Config Driver");
+MODULE_LICENSE("GPL");
diff --git a/patches/xilinx_zynq_defconfig b/patches/xilinx_zynq_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..e09e9a641a42eae371bf4588672700956a5acb7e
--- /dev/null
+++ b/patches/xilinx_zynq_defconfig
@@ -0,0 +1,397 @@
+CONFIG_LOCALVERSION="-xilinx"
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BPF_SYSCALL=y
+# CONFIG_BUG is not set
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_GCC_PLUGINS=n
+CONFIG_PERF_EVENTS=y
+CONFIG_SLAB=y
+CONFIG_ARCH_VEXPRESS=y
+CONFIG_ARCH_ZYNQ=y
+CONFIG_PL310_ERRATA_588369=y
+CONFIG_PL310_ERRATA_727915=y
+CONFIG_PL310_ERRATA_769419=y
+CONFIG_ARM_ERRATA_754322=y
+CONFIG_ARM_ERRATA_754327=y
+CONFIG_ARM_ERRATA_764369=y
+CONFIG_ARM_ERRATA_775420=y
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
+CONFIG_SCHED_SMT=y
+CONFIG_BIG_LITTLE=y
+CONFIG_BL_SWITCHER=y
+CONFIG_HIGHMEM=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_IDLE=y
+CONFIG_ARM_ZYNQ_CPUIDLE=y
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_COMPACTION is not set
+CONFIG_CMA=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=m
+CONFIG_SYN_COOKIES=y
+CONFIG_BRIDGE=m
+CONFIG_VLAN_8021Q=m
+CONFIG_CAN=y
+CONFIG_CAN_XILINXCAN=y
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PCI=y
+CONFIG_PCI_MSI=y
+CONFIG_PCIE_XILINX=y
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_NAND_PL353=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_OF_OVERLAY=y
+CONFIG_OF_CONFIGFS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_XILINX_TRAFGEN=y
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_NETDEVICES=y
+CONFIG_MACB=y
+# CONFIG_NET_VENDOR_CIRRUS is not set
+# CONFIG_NET_VENDOR_FARADAY is not set
+CONFIG_E1000E=y
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MICROCHIP is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+CONFIG_R8169=y
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_XILINX_EMACLITE=y
+CONFIG_XILINX_AXI_EMAC=y
+CONFIG_MARVELL_PHY=y
+CONFIG_VITESSE_PHY=y
+CONFIG_INTEL_XWAY_PHY=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_INPUT_SPARSEKMAP=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_XILINX_PS_UART=y
+CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_XILINX_DEVCFG=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA954x=y
+CONFIG_I2C_CADENCE=y
+CONFIG_SPI=y
+CONFIG_SPI_CADENCE=y
+CONFIG_SPI_XILINX=y
+CONFIG_SPI_ZYNQ_QSPI=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_XILINX=y
+CONFIG_GPIO_ZYNQ=y
+CONFIG_PMBUS=y
+CONFIG_SENSORS_UCD9000=y
+CONFIG_SENSORS_UCD9200=y
+CONFIG_BMP280=y
+CONFIG_THERMAL=y
+CONFIG_CPU_THERMAL=y
+CONFIG_WATCHDOG=y
+CONFIG_XILINX_WATCHDOG=y
+CONFIG_CADENCE_WATCHDOG=y
+CONFIG_REGULATOR=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_XILINX=y
+CONFIG_VIDEO_XILINX_CFA=y
+CONFIG_VIDEO_XILINX_CRESAMPLE=y
+CONFIG_VIDEO_XILINX_REMAPPER=y
+CONFIG_VIDEO_XILINX_RGB2YUV=y
+CONFIG_VIDEO_XILINX_SCALER=y
+CONFIG_VIDEO_XILINX_SWITCH=y
+CONFIG_VIDEO_XILINX_TPG=y
+CONFIG_VIDEO_ADV7604=y
+CONFIG_DRM=y
+CONFIG_DRM_XLNX=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_ADI=y
+CONFIG_SND_SOC_ADI_AXI_I2S=y
+CONFIG_SND_SOC_ADI_AXI_SPDIF=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_STORAGE=y
+CONFIG_USB_UAS=m
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_CHIPIDEA_HOST=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_ULPI=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_XILINX=y
+CONFIG_USB_CONFIGFS=m
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_ZERO=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_OF_ARASAN=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_TRANSIENT=y
+CONFIG_LEDS_TRIGGER_CAMERA=y
+CONFIG_EDAC=y
+CONFIG_EDAC_SYNOPSYS=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PCF8563=y
+CONFIG_DMADEVICES=y
+CONFIG_PL330_DMA=y
+CONFIG_XILINX_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_PDRV_GENIRQ=y
+CONFIG_UIO_XILINX_APM=y
+CONFIG_COMMON_CLK_SI570=y
+CONFIG_REMOTEPROC=y
+CONFIG_ZYNQ_REMOTEPROC=m
+CONFIG_MEMORY=y
+CONFIG_IIO=y
+CONFIG_XILINX_XADC=y
+CONFIG_XILINX_INTC=y
+CONFIG_RAS=y
+CONFIG_EXT3_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DMA_CMA=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_FTRACE is not set
+CONFIG_OVERLAY_FS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_SYN_COOKIES=y
+CONFIG_WIRELESS=y
+CONFIG_CFG80211=m
+CONFIG_MAC80211=m
+CONFIG_RTL8188EU=m
+CONFIG_RTL8192CU=m
+CONFIG_RT2X00=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT3573=y
+CONFIG_RT2800USB_RT53XX=y
+CONFIG_RT2800USB_RT55XX=y
+CONFIG_RT2800USB_UNKNOWN=y
+CONFIG_MT7601U=m
+CONFIG_ATH9K_HTC=m
+CONFIG_B43=m
+CONFIG_BRCMFMAC=m
+CONFIG_BRCMFMAC_USB=y
+CONFIG_PPP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_MBIM=m
+CONFIG_USB_NET_HUAWEI_CDC_NCM=m
+CONFIG_USB_NET_QMI_WWAN=m
+CONFIG_NAMESPACES=y
+CONFIG_NETFILTER=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_NAT_IPV4=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_NAT=m
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_MACVLAN=m
+CONFIG_TUN=m
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_FB_DEFERRED_IO=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_UDL=m
+CONFIG_FUSE_FS=m
+CONFIG_SPI_SPIDEV=m
+CONFIG_PPS_CLIENT_GPIO=m
+CONFIG_PPS_CLIENT_LDISC=m
+CONFIG_USB_GPIO_VBUS=y
+CONFIG_USB_ULPI_BUS=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_CIFS=m
+CONFIG_CIFS_STATS2=y
+CONFIG_CIFS_UPCALL=y
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_ACL=y
+CONFIG_CIFS_DFS_UPCALL=y
+CONFIG_STAGING=y
+CONFIG_FB_TFT=m
+CONFIG_FB_TFT_AGM1264K_FL=m
+CONFIG_FB_TFT_BD663474=m
+CONFIG_FB_TFT_HX8340BN=m
+CONFIG_FB_TFT_HX8347D=m
+CONFIG_FB_TFT_HX8353D=m
+CONFIG_FB_TFT_HX8357D=m
+CONFIG_FB_TFT_ILI9163=m
+CONFIG_FB_TFT_ILI9320=m
+CONFIG_FB_TFT_ILI9325=m
+CONFIG_FB_TFT_ILI9340=m
+CONFIG_FB_TFT_ILI9341=m
+CONFIG_FB_TFT_ILI9481=m
+CONFIG_FB_TFT_ILI9486=m
+CONFIG_FB_TFT_PCD8544=m
+CONFIG_FB_TFT_RA8875=m
+CONFIG_FB_TFT_S6D02A1=m
+CONFIG_FB_TFT_S6D1121=m
+CONFIG_FB_TFT_SSD1289=m
+CONFIG_FB_TFT_SSD1306=m
+CONFIG_FB_TFT_SSD1331=m
+CONFIG_FB_TFT_SSD1351=m
+CONFIG_FB_TFT_ST7735R=m
+CONFIG_FB_TFT_ST7789V=m
+CONFIG_FB_TFT_TINYLCD=m
+CONFIG_FB_TFT_TLS8204=m
+CONFIG_FB_TFT_UC1611=m
+CONFIG_FB_TFT_UC1701=m
+CONFIG_FB_TFT_UPD161704=m
+CONFIG_FB_TFT_WATTEROTT=m
+CONFIG_FB_FLEX=m
+CONFIG_FB_TFT_FBTFT_DEVICE=m
+CONFIG_USB_ACM=m
+CONFIG_USB_TMC=m
+CONFIG_VIDEOBUF2_VMALLOC=m
+CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=8
+CONFIG_U_SERIAL_CONSOLE=y
+CONFIG_USB_F_ACM=m
+CONFIG_USB_U_SERIAL=m
+CONFIG_USB_U_ETHER=m
+CONFIG_USB_F_SERIAL=m
+CONFIG_USB_F_OBEX=m
+CONFIG_USB_F_NCM=m
+CONFIG_USB_F_ECM=m
+CONFIG_USB_F_EEM=m
+CONFIG_USB_F_SUBSET=m
+CONFIG_USB_F_RNDIS=m
+CONFIG_USB_F_FS=m
+CONFIG_USB_F_UAC1=m
+CONFIG_USB_F_UAC2=m
+CONFIG_USB_F_UVC=m
+CONFIG_USB_F_MIDI=m
+CONFIG_USB_F_HID=m
+CONFIG_USB_F_PRINTER=m
+CONFIG_USB_CONFIGFS_SERIAL=y
+CONFIG_USB_CONFIGFS_ACM=y
+CONFIG_USB_CONFIGFS_OBEX=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_ECM=y
+CONFIG_USB_CONFIGFS_ECM_SUBSET=y
+CONFIG_USB_CONFIGFS_RNDIS=y
+CONFIG_USB_CONFIGFS_EEM=y
+CONFIG_USB_CONFIGFS_F_LB_SS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_UAC1=y
+CONFIG_USB_CONFIGFS_F_UAC2=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_UVC=y
+CONFIG_USB_CONFIGFS_F_PRINTER=y
+CONFIG_USB_AUDIO=m
+CONFIG_GADGET_UAC1=y
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_ETH_EEM=y
+CONFIG_USB_G_NCM=m
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FUNCTIONFS=m
+CONFIG_USB_FUNCTIONFS_ETH=y
+CONFIG_USB_FUNCTIONFS_RNDIS=y
+CONFIG_USB_FUNCTIONFS_GENERIC=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+CONFIG_USB_MIDI_GADGET=m
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+CONFIG_USB_G_ACM_MS=m
+CONFIG_USB_G_MULTI=m
+CONFIG_USB_G_MULTI_RNDIS=y
+CONFIG_USB_G_MULTI_CDC=y
+CONFIG_USB_G_HID=m
+CONFIG_USB_G_WEBCAM=m
diff --git a/patches/zynq-red-pitaya.dts b/patches/zynq-red-pitaya.dts
new file mode 100644
index 0000000000000000000000000000000000000000..1c6ceb9dfd064193c954d9241b118a3c4f97370b
--- /dev/null
+++ b/patches/zynq-red-pitaya.dts
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ *  Copyright (C) 2011 - 2015 Xilinx
+ *  Copyright (C) 2012 National Instruments Corp.
+ */
+/dts-v1/;
+#include "zynq-7000.dtsi"
+
+/ {
+	model = "Red Pitaya Board";
+	compatible = "xlnx,zynq-red-pitaya", "xlnx,zynq-7000";
+
+	aliases {
+		ethernet0 = &gem0;
+		serial0 = &uart0;
+		mmc0 = &sdhci0;
+	};
+
+	memory@0 {
+		device_type = "memory";
+		reg = <0x0 0x20000000>;
+	};
+
+	chosen {
+		bootargs = "";
+		stdout-path = "serial0:115200n8";
+	};
+
+	usb_phy0: phy0 {
+		#phy-cells = <0>;
+		compatible = "usb-nop-xceiv";
+	};
+};
+
+&clkc {
+	ps-clk-frequency = <33333333>;
+};
+
+&gem0 {
+	status = "okay";
+	phy-mode = "rgmii-id";
+	phy-handle = <&ethernet_phy>;
+
+	ethernet_phy: ethernet-phy@1 {
+		reg = <1>;
+		device_type = "ethernet-phy";
+	};
+};
+
+&i2c0 {
+	status = "okay";
+	clock-frequency = <400000>;
+	eeprom@50 {
+		compatible = "24c64";
+		reg = <0x50>;
+	};
+   bmp180@77{
+     compatible = "bosch,bmp280";
+     reg = <0x77>;
+     };
+};
+
+&sdhci0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&uart0 {
+	u-boot,dm-pre-reloc;
+	status = "okay";
+};
+
+&usb0 {
+	status = "okay";
+	dr_mode = "host";
+	usb-phy = <&usb_phy0>;
+};
diff --git a/patches/zynq_ocm.c b/patches/zynq_ocm.c
new file mode 100644
index 0000000000000000000000000000000000000000..324b7c125bf5681ecff2bb5f6f090bcd293ffc44
--- /dev/null
+++ b/patches/zynq_ocm.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2013 Xilinx
+ *
+ * Based on "Generic on-chip SRAM allocation driver"
+ *
+ * Copyright (C) 2012 Philipp Zabel, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_irq.h>
+#include <linux/platform_device.h>
+#include <linux/genalloc.h>
+
+#include "common.h"
+
+#define ZYNQ_OCM_HIGHADDR	0xfffc0000
+#define ZYNQ_OCM_LOWADDR	0x0
+#define ZYNQ_OCM_BLOCK_SIZE	0x10000
+#define ZYNQ_OCM_BLOCKS		4
+#define ZYNQ_OCM_GRANULARITY	32
+
+#define ZYNQ_OCM_PARITY_CTRL	0x0
+#define ZYNQ_OCM_PARITY_ENABLE	0x1e
+
+#define ZYNQ_OCM_PARITY_ERRADDRESS	0x4
+
+#define ZYNQ_OCM_IRQ_STS		0x8
+#define ZYNQ_OCM_IRQ_STS_ERR_MASK	0x7
+
+struct zynq_ocm_dev {
+	void __iomem *base;
+	int irq;
+	struct gen_pool *pool;
+	struct resource res[ZYNQ_OCM_BLOCKS];
+};
+
+/**
+ * zynq_ocm_irq_handler - Interrupt service routine of the OCM controller
+ * @irq:	IRQ number
+ * @data:	Pointer to the zynq_ocm_dev structure
+ *
+ * Return:	IRQ_HANDLED when handled; IRQ_NONE otherwise.
+ */
+static irqreturn_t zynq_ocm_irq_handler(int irq, void *data)
+{
+	u32 sts;
+	u32 err_addr;
+	struct zynq_ocm_dev *zynq_ocm = data;
+
+	/* check status */
+	sts = readl(zynq_ocm->base + ZYNQ_OCM_IRQ_STS);
+	if (sts & ZYNQ_OCM_IRQ_STS_ERR_MASK) {
+		/* check error address */
+		err_addr = readl(zynq_ocm->base + ZYNQ_OCM_PARITY_ERRADDRESS);
+		pr_err("%s: OCM err intr generated at 0x%04x (stat: 0x%08x).",
+		       __func__, err_addr, sts & ZYNQ_OCM_IRQ_STS_ERR_MASK);
+		return IRQ_HANDLED;
+	}
+	pr_warn("%s: Interrupt generated by OCM, but no error is found.",
+		__func__);
+
+	return IRQ_NONE;
+}
+
+/**
+ * zynq_ocm_probe - Probe method for the OCM driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function initializes the driver data structures and the hardware.
+ *
+ * Return:	0 on success and error value on failure
+ */
+static int zynq_ocm_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct zynq_ocm_dev *zynq_ocm;
+	u32 i, ocm_config, curr;
+	struct resource *res;
+
+	ocm_config = zynq_slcr_get_ocm_config();
+
+	zynq_ocm = devm_kzalloc(&pdev->dev, sizeof(*zynq_ocm), GFP_KERNEL);
+	if (!zynq_ocm)
+		return -ENOMEM;
+
+	zynq_ocm->pool = devm_gen_pool_create(&pdev->dev,
+					      ilog2(ZYNQ_OCM_GRANULARITY),
+					      NUMA_NO_NODE, NULL);
+	if (!zynq_ocm->pool)
+		return -ENOMEM;
+
+	curr = 0; /* For storing current struct resource for OCM */
+	for (i = 0; i < ZYNQ_OCM_BLOCKS; i++) {
+		u32 base, start, end;
+
+		/* Setup base address for 64kB OCM block */
+		if (ocm_config & BIT(i))
+			base = ZYNQ_OCM_HIGHADDR;
+		else
+			base = ZYNQ_OCM_LOWADDR;
+
+		/* Calculate start and end block addresses */
+		start = i * ZYNQ_OCM_BLOCK_SIZE + base;
+		end = start + (ZYNQ_OCM_BLOCK_SIZE - 1);
+
+		/* Concatenate OCM blocks together to get bigger pool */
+		if (i > 0 && start == (zynq_ocm->res[curr - 1].end + 1)) {
+			zynq_ocm->res[curr - 1].end = end;
+		} else {
+#ifdef CONFIG_SMP
+			/*
+			 * OCM block if placed at 0x0 has special meaning
+			 * for SMP because jump trampoline is added there.
+			 * Ensure that this address won't be allocated.
+			 */
+			if (!base) {
+				u32 trampoline_code_size =
+					&zynq_secondary_trampoline_end -
+					&zynq_secondary_trampoline;
+				dev_dbg(&pdev->dev,
+					"Allocate reset vector table %dB\n",
+					trampoline_code_size);
+				/* postpone start offset */
+				start += trampoline_code_size;
+			}
+#endif
+			/* First resource is always initialized */
+			zynq_ocm->res[curr].start = start;
+			zynq_ocm->res[curr].end = end;
+			zynq_ocm->res[curr].flags = IORESOURCE_MEM;
+			curr++; /* Increment curr value */
+		}
+		dev_dbg(&pdev->dev, "OCM block %d, start %x, end %x\n",
+			i, start, end);
+	}
+
+	/*
+	 * Separate pool allocation from OCM block detection to ensure
+	 * the biggest possible pool.
+	 */
+	for (i = 0; i < ZYNQ_OCM_BLOCKS; i++) {
+		unsigned long size;
+		void __iomem *virt_base;
+
+		/* Skip all zero size resources */
+		if (zynq_ocm->res[i].end == 0)
+			break;
+		dev_dbg(&pdev->dev, "OCM resources %d, start %x, end %x\n",
+			i, zynq_ocm->res[i].start, zynq_ocm->res[i].end);
+		size = resource_size(&zynq_ocm->res[i]);
+		virt_base = devm_ioremap_resource(&pdev->dev,
+						  &zynq_ocm->res[i]);
+		if (IS_ERR(virt_base))
+			return PTR_ERR(virt_base);
+
+		ret = gen_pool_add_virt(zynq_ocm->pool,
+					(unsigned long)virt_base,
+					zynq_ocm->res[i].start, size, -1);
+		if (ret < 0) {
+			dev_err(&pdev->dev, "Gen pool failed\n");
+			return ret;
+		}
+		dev_info(&pdev->dev, "ZYNQ OCM pool: %ld KiB @ 0x%p\n",
+			 size / 1024, virt_base);
+	}
+
+	/* Get OCM config space */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	zynq_ocm->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(zynq_ocm->base))
+		return PTR_ERR(zynq_ocm->base);
+
+	/* Allocate OCM parity IRQ */
+	zynq_ocm->irq = platform_get_irq(pdev, 0);
+	if (zynq_ocm->irq < 0) {
+		dev_err(&pdev->dev, "irq resource not found\n");
+		return zynq_ocm->irq;
+	}
+	ret = devm_request_irq(&pdev->dev, zynq_ocm->irq, zynq_ocm_irq_handler,
+			       0, pdev->name, zynq_ocm);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "request_irq failed\n");
+		return ret;
+	}
+
+	/* Enable parity errors */
+	writel(ZYNQ_OCM_PARITY_ENABLE, zynq_ocm->base + ZYNQ_OCM_PARITY_CTRL);
+
+	platform_set_drvdata(pdev, zynq_ocm);
+
+	return 0;
+}
+
+/**
+ * zynq_ocm_remove - Remove method for the OCM driver
+ * @pdev:	Pointer to the platform_device structure
+ *
+ * This function is called if a device is physically removed from the system or
+ * if the driver module is being unloaded. It frees all resources allocated to
+ * the device.
+ *
+ * Return:	0 on success and error value on failure
+ */
+static int zynq_ocm_remove(struct platform_device *pdev)
+{
+	struct zynq_ocm_dev *zynq_ocm = platform_get_drvdata(pdev);
+
+	if (gen_pool_avail(zynq_ocm->pool) < gen_pool_size(zynq_ocm->pool))
+		dev_dbg(&pdev->dev, "removed while SRAM allocated\n");
+
+	return 0;
+}
+
+static struct of_device_id zynq_ocm_dt_ids[] = {
+	{ .compatible = "xlnx,zynq-ocmc-1.0" },
+	{ /* end of table */ }
+};
+
+static struct platform_driver zynq_ocm_driver = {
+	.driver = {
+		.name = "zynq-ocm",
+		.of_match_table = zynq_ocm_dt_ids,
+	},
+	.probe = zynq_ocm_probe,
+	.remove = zynq_ocm_remove,
+};
+
+static int __init zynq_ocm_init(void)
+{
+	return platform_driver_register(&zynq_ocm_driver);
+}
+
+arch_initcall(zynq_ocm_init);
diff --git a/patches/zynq_red_pitaya.h b/patches/zynq_red_pitaya.h
new file mode 100644
index 0000000000000000000000000000000000000000..2be3bd17d46527f12d4f8ec1e060f24d4272dac9
--- /dev/null
+++ b/patches/zynq_red_pitaya.h
@@ -0,0 +1,16 @@
+#ifndef __CONFIG_ZYNQ_RED_PITAYA_H
+#define __CONFIG_ZYNQ_RED_PITAYA_H
+
+#include <configs/zynq-common.h>
+
+#undef CONFIG_SYS_I2C_EEPROM_ADDR_LEN
+#undef CONFIG_SYS_I2C_EEPROM_ADDR
+#undef CONFIG_SYS_EEPROM_PAGE_WRITE_BITS
+#undef CONFIG_SYS_EEPROM_SIZE
+
+#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN		2
+#define CONFIG_SYS_I2C_EEPROM_ADDR		0x50
+#define CONFIG_SYS_EEPROM_PAGE_WRITE_BITS	5
+#define CONFIG_SYS_EEPROM_SIZE			8192 /* Bytes */
+
+#endif /* __CONFIG_ZYNQ_RED_PITAYA_H */
diff --git a/patches/zynq_red_pitaya_defconfig b/patches/zynq_red_pitaya_defconfig
new file mode 100644
index 0000000000000000000000000000000000000000..6b6197b2750e68e1107a02975ebe6dad68af6955
--- /dev/null
+++ b/patches/zynq_red_pitaya_defconfig
@@ -0,0 +1,24 @@
+CONFIG_ARM=y
+CONFIG_ARCH_ZYNQ=y
+CONFIG_SYS_TEXT_BASE=0x4000000
+CONFIG_SYS_CUSTOM_LDSCRIPT=y
+CONFIG_SYS_LDSCRIPT="arch/arm/mach-zynq/u-boot.lds"
+CONFIG_DEFAULT_DEVICE_TREE="zynq-red-pitaya"
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_CMD_MMC=y
+CONFIG_ENV_OVERWRITE=y
+CONFIG_ENV_IS_IN_EEPROM=y
+CONFIG_ENV_OFFSET=0x1800
+CONFIG_ENV_SIZE=0x400
+CONFIG_SYS_RELOC_GD_ENV_ADDR=y
+CONFIG_MISC=y
+CONFIG_I2C_EEPROM=y
+CONFIG_DM_I2C=y
+CONFIG_SYS_I2C_CADENCE=y
+CONFIG_SYS_I2C_EEPROM_ADDR=0x50
+CONFIG_SYS_I2C_EEPROM_ADDR_LEN=2
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_ZYNQ=y
+CONFIG_NET_RANDOM_ETHADDR=y
+CONFIG_ZYNQ_GEM=y
+CONFIG_ZYNQ_SERIAL=y
diff --git a/projects/adc_recorder/adc-recorder.c b/projects/adc_recorder/adc-recorder.c
new file mode 100644
index 0000000000000000000000000000000000000000..9da00513b13e756fcb1247951b106a42f252ba10
--- /dev/null
+++ b/projects/adc_recorder/adc-recorder.c
@@ -0,0 +1,81 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#define CMA_ALLOC _IOWR('Z', 0, uint32_t)
+
+int main()
+{
+	int fd, i;
+	volatile uint8_t *rst;
+	volatile void *cfg;
+	volatile int16_t *ram;
+	uint32_t size;
+	int16_t value[2];
+
+	if((fd = open("/dev/mem", O_RDWR)) < 0)
+	{
+		perror("open");
+		return EXIT_FAILURE;
+	}
+
+	cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x40000000);
+
+	close(fd);
+
+	if((fd = open("/dev/cma", O_RDWR)) < 0)
+	{
+		perror("open");
+		return EXIT_FAILURE;
+	}
+
+	size = 1024*sysconf(_SC_PAGESIZE);
+
+	if(ioctl(fd, CMA_ALLOC, &size) < 0)
+	{
+		perror("ioctl");
+		return EXIT_FAILURE;
+	}
+
+	ram = mmap(NULL, 1024*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+	rst = (uint8_t *)(cfg + 0);
+
+	// set writer address
+	*(uint32_t *)(cfg + 4) = size;
+
+	// set number of samples
+	*(uint32_t *)(cfg + 8) = 1024 * 1024 - 1;
+
+	// reset writer
+	*rst &= ~4;
+	*rst |= 4;
+
+	// reset fifo and filters
+	*rst &= ~1;
+	*rst |= 1;
+
+	// wait 1 second
+	sleep(1);
+
+	// reset packetizer
+	*rst &= ~2;
+	*rst |= 2;
+
+	// wait 1 second
+	sleep(1);
+
+	// print IN1 and IN2 samples
+	for(i = 0; i < 1024 * 1024; ++i)
+	{
+		value[0] = ram[2 * i + 0];
+		value[1] = ram[2 * i + 1];
+		printf("%5d %5d\n", value[0], value[1]);
+	}
+
+	return EXIT_SUCCESS;
+}
diff --git a/projects/adc_recorder/block_design.tcl b/projects/adc_recorder/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..083ce736b386ebf335cf4cbef5ae96181fc8f7cc
--- /dev/null
+++ b/projects/adc_recorder/block_design.tcl
@@ -0,0 +1,241 @@
+# Create clk_wiz
+cell xilinx.com:ip:clk_wiz pll_0 {
+  PRIMITIVE PLL
+  PRIM_IN_FREQ.VALUE_SRC USER
+  PRIM_IN_FREQ 125.0
+  PRIM_SOURCE Differential_clock_capable_pin
+  CLKOUT1_USED true
+  CLKOUT1_REQUESTED_OUT_FREQ 125.0
+  USE_RESET false
+} {
+  clk_in1_p adc_clk_p_i
+  clk_in1_n adc_clk_n_i
+}
+
+# Create processing_system7
+cell xilinx.com:ip:processing_system7 ps_0 {
+  PCW_IMPORT_BOARD_PRESET cfg/red_pitaya.xml
+  PCW_USE_S_AXI_ACP 1
+  PCW_USE_DEFAULT_ACP_USER_VAL 1
+} {
+  M_AXI_GP0_ACLK pll_0/clk_out1
+  S_AXI_ACP_ACLK pll_0/clk_out1
+}
+
+# Create all required interconnections
+apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config {
+  make_external {FIXED_IO, DDR}
+  Master Disable
+  Slave Disable
+} [get_bd_cells ps_0]
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+# GPIO
+
+# Delete input/output port
+delete_bd_objs [get_bd_ports exp_p_tri_io]
+
+# Create output port
+create_bd_port -dir O -from 7 -to 0 exp_p_tri_io
+
+# ADC
+
+# Create axis_red_pitaya_adc
+cell labdpr:user:axis_rp_adc adc_0 {
+  ADC_DATA_WIDTH 14
+} {
+  aclk pll_0/clk_out1
+  adc_dat_a adc_dat_a_i
+  adc_dat_b adc_dat_b_i
+  adc_csn adc_csn_o
+}
+
+# Create axi_cfg_register
+cell labdpr:user:axi_cfg_register cfg_0 {
+  CFG_DATA_WIDTH 96
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_0 {
+  DIN_WIDTH 96 DIN_FROM 0 DIN_TO 0
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_1 {
+  DIN_WIDTH 96 DIN_FROM 1 DIN_TO 1
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_2 {
+  DIN_WIDTH 96 DIN_FROM 2 DIN_TO 2
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_3 {
+  DIN_WIDTH 96 DIN_FROM 63 DIN_TO 32
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_4 {
+  DIN_WIDTH 96 DIN_FROM 95 DIN_TO 64
+} {
+  din cfg_0/cfg_data
+}
+
+# Create util_vector_logic
+cell xilinx.com:ip:util_vector_logic not_0 {
+  C_SIZE 1
+  C_OPERATION not
+} {
+  Op1 slice_1/dout
+}
+
+# Create xlconcat
+cell xilinx.com:ip:xlconcat concat_0 {
+  NUM_PORTS 2
+  IN0_WIDTH 1
+  IN1_WIDTH 7
+} {
+  In0 not_0/Res
+  dout exp_p_tri_io
+}
+
+# Create axis_broadcaster
+cell xilinx.com:ip:axis_broadcaster bcast_0 {
+  S_TDATA_NUM_BYTES.VALUE_SRC USER
+  M_TDATA_NUM_BYTES.VALUE_SRC USER
+  S_TDATA_NUM_BYTES 4
+  M_TDATA_NUM_BYTES 2
+  M00_TDATA_REMAP {tdata[15:0]}
+  M01_TDATA_REMAP {tdata[31:16]}
+} {
+  S_AXIS adc_0/M_AXIS
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+# Create cic_compiler
+cell xilinx.com:ip:cic_compiler cic_0 {
+  INPUT_DATA_WIDTH.VALUE_SRC USER
+  FILTER_TYPE Decimation
+  NUMBER_OF_STAGES 6
+  FIXED_OR_INITIAL_RATE 32
+  INPUT_SAMPLE_FREQUENCY 125
+  CLOCK_FREQUENCY 125
+  INPUT_DATA_WIDTH 14
+  QUANTIZATION Truncation
+  OUTPUT_DATA_WIDTH 16
+  USE_XTREME_DSP_SLICE true
+  HAS_ARESETN true
+} {
+  S_AXIS_DATA bcast_0/M00_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_0/dout
+}
+
+# Create cic_compiler
+cell xilinx.com:ip:cic_compiler cic_1 {
+  INPUT_DATA_WIDTH.VALUE_SRC USER
+  FILTER_TYPE Decimation
+  NUMBER_OF_STAGES 6
+  FIXED_OR_INITIAL_RATE 32
+  INPUT_SAMPLE_FREQUENCY 125
+  CLOCK_FREQUENCY 125
+  INPUT_DATA_WIDTH 14
+  QUANTIZATION Truncation
+  OUTPUT_DATA_WIDTH 16
+  USE_XTREME_DSP_SLICE true
+  HAS_ARESETN true
+} {
+  S_AXIS_DATA bcast_0/M01_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_0/dout
+}
+
+# Create axis_combiner
+cell  xilinx.com:ip:axis_combiner comb_0 {
+  TDATA_NUM_BYTES.VALUE_SRC USER
+  TDATA_NUM_BYTES 2
+} {
+  S00_AXIS cic_0/M_AXIS_DATA
+  S01_AXIS cic_1/M_AXIS_DATA
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+# Create fir_compiler
+cell xilinx.com:ip:fir_compiler fir_0 {
+  DATA_WIDTH.VALUE_SRC USER
+  DATA_WIDTH 16
+  COEFFICIENTVECTOR {-1.64753028794138e-08, -4.72969860103254e-08, -7.81983994864729e-10, 3.09179315378013e-08, 1.8600476137934e-08, 3.27300695910419e-08, -6.27121813377163e-09, -1.52196115352429e-07, -8.30377969926702e-08, 3.14361841397898e-07, 3.05515872274853e-07, -4.73906648324436e-07, -7.13188274738437e-07, 5.47004771774003e-07, 1.33401100809314e-06, -4.13867548024707e-07, -2.14949555259695e-06, -6.77977800948474e-08, 3.07398932714553e-06, 1.0366230107463e-06, -3.94245232963009e-06, -2.59076839821521e-06, 4.51317323767107e-06, 4.74563996488482e-06, -4.49064349142054e-06, -7.3947777960083e-06, 3.57041197419745e-06, 1.02846684426837e-05, -1.50308472093842e-06, -1.30146997163052e-05, -1.8311731233767e-06, 1.50710364353895e-05, 6.3515248701083e-06, -1.58982472678568e-05, -1.17267343142635e-05, 1.50041199296265e-05, 1.73635115814309e-05, -1.20890304109726e-05, -2.24560062957254e-05, 7.16700059796055e-06, 2.60907689345942e-05, -6.64193032293714e-07, -2.74163749798938e-05, -6.54632074532538e-06, 2.5852558776971e-05, 1.31966582845397e-05, -2.13079073598636e-05, -1.77801135294917e-05, 1.43611952054032e-05, 1.88093817512436e-05, -6.35698021047062e-06, -1.51543007857966e-05, -6.31269475321274e-07, 6.41236246473726e-06, 4.00235076480002e-06, 6.75384652715119e-06, -1.00102812372645e-06, -2.23907547607786e-05, -1.07614170164429e-05, 3.72128949266483e-05, 3.26888314865614e-05, -4.68343172264928e-05, -6.46247522446593e-05, 4.62331324663801e-05, 0.000104353987875991, -3.05204178369922e-05, -0.000147387572103254, -4.12376672483791e-06, 0.000187096070793206, 5.94492160104715e-05, -0.000215270553995213, -0.000134242574203586, 0.000223115373945588, 0.000223732063932204, -0.000202601585158347, -0.000319473722277179, 0.000148023831554525, 0.000409856470754451, -5.75319241913947e-05, -0.00048128691789378, -6.56435551088113e-05, 0.000520005389882914, 0.000212559310978688, -0.000514378040456993, -0.000368824791639381, 0.000457257636791032, 0.00051572189965271, -0.000348325111720936, -0.000632574861580132, 0.000195575644936742, 0.000699853643923955, -1.5816811333843e-05, -0.000702875004558909, -0.000166267212059945, 0.000635554670416145, 0.000320646045613507, -0.000503596369030625, -0.000416023690327203, 0.000326453158345306, 0.00042516016658693, -0.000137454215410763, -0.000330867755122004, -1.83577770104995e-05, 0.000131884375290827, 8.88732824246191e-05, 0.000152320700965935, -2.19145324792827e-05, -0.000478845867687744, -0.000226130995959082, 0.000781165284659716, 0.000680083599509367, -0.000973297239795462, -0.00133684955123469, 0.000956951103249511, 0.00215724393391554, -0.000632647805407322, -0.00306094569410801, -8.63474252426424e-05, 0.00392560461099799, 0.00125840455441931, -0.00459097537930345, -0.00289777037472875, 0.00486843895178868, 0.00496041688761007, -0.00455566278421732, -0.0073332195556104, 0.00345548961533671, 0.00982788076765724, -0.0013975392826423, -0.0121803938743171, -0.00173944634676796, 0.0140556603140014, 0.00600554245501628, -0.0150585666700821, -0.0113645359721422, 0.0147416608531572, 0.0176785888467245, -0.0126130926725902, -0.0247012339350495, 0.00812796467212303, 0.0320712315374266, -0.000646259298618774, -0.0392988478933562, -0.0106852885932714, 0.0457163887873562, 0.0272344645510023, -0.0503010855018923, -0.0516879242105393, 0.0510032995068897, 0.0905252892059647, -0.0416077244968566, -0.163677972614864, -0.0107434888500177, 0.356350050991766, 0.554721342376512, 0.356350050991766, -0.0107434888500177, -0.163677972614864, -0.0416077244968565, 0.0905252892059646, 0.0510032995068897, -0.0516879242105392, -0.0503010855018923, 0.0272344645510023, 0.0457163887873562, -0.0106852885932714, -0.0392988478933562, -0.000646259298618766, 0.0320712315374266, 0.008127964672123, -0.0247012339350495, -0.0126130926725902, 0.0176785888467245, 0.0147416608531572, -0.0113645359721422, -0.0150585666700821, 0.00600554245501627, 0.0140556603140014, -0.00173944634676796, -0.0121803938743171, -0.0013975392826423, 0.00982788076765723, 0.00345548961533672, -0.0073332195556104, -0.00455566278421732, 0.00496041688761004, 0.00486843895178868, -0.00289777037472874, -0.00459097537930345, 0.00125840455441931, 0.003925604610998, -8.6347425242651e-05, -0.00306094569410801, -0.000632647805407327, 0.00215724393391554, 0.000956951103249513, -0.00133684955123469, -0.000973297239795458, 0.00068008359950937, 0.000781165284659718, -0.000226130995959085, -0.000478845867687734, -2.19145324792814e-05, 0.000152320700965923, 8.88732824246168e-05, 0.000131884375290828, -1.83577770104952e-05, -0.000330867755122008, -0.000137454215410769, 0.000425160166586931, 0.000326453158345309, -0.000416023690327193, -0.000503596369030629, 0.000320646045613497, 0.000635554670416148, -0.000166267212059939, -0.000702875004558908, -1.58168113338674e-05, 0.000699853643923955, 0.000195575644936758, -0.000632574861580132, -0.000348325111720941, 0.000515721899652708, 0.000457257636791035, -0.000368824791639379, -0.000514378040456997, 0.000212559310978687, 0.000520005389882915, -6.56435551088096e-05, -0.000481286917893776, -5.7531924191395e-05, 0.000409856470754451, 0.000148023831554525, -0.000319473722277176, -0.000202601585158348, 0.000223732063932204, 0.000223115373945587, -0.000134242574203588, -0.000215270553995212, 5.944921601047e-05, 0.000187096070793206, -4.12376672483805e-06, -0.000147387572103254, -3.05204178369924e-05, 0.000104353987875991, 4.62331324663777e-05, -6.46247522446589e-05, -4.68343172264921e-05, 3.26888314865612e-05, 3.72128949266458e-05, -1.07614170164428e-05, -2.23907547607785e-05, -1.0010281237264e-06, 6.7538465271515e-06, 4.00235076480007e-06, 6.41236246473652e-06, -6.31269475321259e-07, -1.5154300785797e-05, -6.35698021047036e-06, 1.88093817512439e-05, 1.43611952054029e-05, -1.77801135294911e-05, -2.13079073598635e-05, 1.31966582845395e-05, 2.58525587769708e-05, -6.54632074532428e-06, -2.74163749798938e-05, -6.64193032294061e-07, 2.60907689345942e-05, 7.16700059796085e-06, -2.24560062957254e-05, -1.20890304109726e-05, 1.7363511581431e-05, 1.50041199296266e-05, -1.17267343142635e-05, -1.58982472678571e-05, 6.3515248701082e-06, 1.50710364353894e-05, -1.83117312337678e-06, -1.30146997163053e-05, -1.50308472093845e-06, 1.02846684426836e-05, 3.57041197419745e-06, -7.39477779600816e-06, -4.49064349142055e-06, 4.74563996488478e-06, 4.51317323767109e-06, -2.59076839821518e-06, -3.94245232963005e-06, 1.03662301074629e-06, 3.07398932714552e-06, -6.77977800948646e-08, -2.14949555259695e-06, -4.13867548024735e-07, 1.33401100809314e-06, 5.47004771773993e-07, -7.13188274738437e-07, -4.73906648324394e-07, 3.05515872274853e-07, 3.14361841397861e-07, -8.30377969926656e-08, -1.5219611535243e-07, -6.27121813377245e-09, 3.27300695910341e-08, 1.86004761379317e-08, 3.0917931537805e-08, -7.81983994865244e-10, -4.72969860103212e-08, -1.64753028794135e-08}
+  COEFFICIENT_WIDTH 16
+  QUANTIZATION Quantize_Only
+  BESTPRECISION true
+  FILTER_TYPE Decimation
+  DECIMATION_RATE 2
+  NUMBER_PATHS 2
+  RATESPECIFICATION Input_Sample_Period
+  SAMPLEPERIOD 32
+  OUTPUT_ROUNDING_MODE Truncate_LSBs
+  OUTPUT_WIDTH 16
+  HAS_ARESETN true
+} {
+  S_AXIS_DATA comb_0/M_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_0/dout
+}
+
+# Create axis_packetizer
+cell labdpr:user:axis_packetizer pktzr_0 {
+  AXIS_TDATA_WIDTH 32
+  CNTR_WIDTH 32
+  CONTINUOUS FALSE
+} {
+  S_AXIS fir_0/M_AXIS_DATA
+  cfg_data slice_4/dout
+  aclk pll_0/clk_out1
+  aresetn slice_1/dout
+}
+
+# Create axis_dwidth_converter
+cell xilinx.com:ip:axis_dwidth_converter conv_0 {
+  S_TDATA_NUM_BYTES.VALUE_SRC USER
+  S_TDATA_NUM_BYTES 4
+  M_TDATA_NUM_BYTES 8
+} {
+  S_AXIS pktzr_0/M_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_2/dout
+}
+
+# Create axis_ram_writer
+cell labdpr:user:axis_ram_writer writer_0 {
+  ADDR_WIDTH 22
+  AXI_ID_WIDTH 3
+} {
+  S_AXIS conv_0/M_AXIS
+  M_AXI ps_0/S_AXI_ACP
+  cfg_data slice_3/dout
+  aclk pll_0/clk_out1
+  aresetn slice_2/dout
+}
+
+addr 0x40000000 4K cfg_0/S_AXI /ps_0/M_AXI_GP0
+
diff --git a/projects/adc_recorder/src/Makefile b/projects/adc_recorder/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..858880d0d10cb4a7d382f7b05b409b6faded4414
--- /dev/null
+++ b/projects/adc_recorder/src/Makefile
@@ -0,0 +1,16 @@
+CC=gcc
+FLAGS=-Wall -O3
+ARCH=arm
+CROSS_COMPILE=arm-xilinx-linux-gnueabi-
+
+####
+PROG=adc_recorder
+EXTRA= zynq_io.c
+
+all: $(PROG)
+
+$(PROG): $(PROG).c $(EXTRA) 
+	$(CC) $(FLAGS) -o $(PROG) $(PROG).c $(EXTRA) -lm -lpthread
+
+clean:
+	rm -f $(PROG)
diff --git a/projects/adc_recorder/src/adc_recorder.c b/projects/adc_recorder/src/adc_recorder.c
new file mode 100644
index 0000000000000000000000000000000000000000..ffe2730cc2e63784da1bc465e8ea04dcbe466d58
--- /dev/null
+++ b/projects/adc_recorder/src/adc_recorder.c
@@ -0,0 +1,103 @@
+#include "zynq_io.h"
+
+int main(int argc, char *argv[])
+{
+	//int fd;
+	//unsigned int size;
+	uint32_t i,val=0;
+	uint32_t wo;
+	int16_t ch[2];
+
+	printf("ADC RECORDER test\n");
+
+	//initialize devices. TODO: add error checking 
+	//intc_init();
+	cfg_init();    
+	cma_init();
+	//sts_init();
+	//xadc_init();
+
+	// set writer address
+	//   *(uint32_t *)(cfg + 4) = size;
+	//
+	printf("Set writer address...\n");
+	val=rd_reg_value(1, CFG_WR_ADDR_OFFSET);
+	printf("dev_size es: %d ...\n",dev_size);
+	wr_reg_value(1, CFG_WR_ADDR_OFFSET, dev_size);
+
+	 // set number of samples
+	 //   *(uint32_t *)(cfg + 8) = 1024 * 1024 - 1;
+	 //
+	printf("Set number of samples...\n");
+	val=rd_reg_value(1, CFG_NSAMPLES_OFFSET);
+	wr_reg_value(1, CFG_NSAMPLES_OFFSET, 1024 * 1024 - 1);
+
+	// reset writer
+	//*((uint32_t *)(cfg + 0)) &= ~4;
+	printf("Reseting writer...\n");
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &= ~4);
+	//*((uint32_t *)(cfg + 0)) |= 4;
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |= 4);
+//	printf("Reseting writer %d ...\n",val);
+	printf("Reseting fifo and filters...\n");
+//	// reset fifo and filters
+	//*((uint32_t *)(cfg + 0)) &= ~1;
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &=~1);
+//	//*((uint32_t *)(cfg + 0)) |= 1;
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |=1);
+//	printf("Reseting fifo and filters %d ...\n",val);
+//
+//	// wait 1 second
+	sleep(1);
+//
+	printf("Reseting packetizer...\n");
+	// enter reset mode for packetizer
+	//*((uint32_t *)(cfg + 0)) &= ~2; 
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &=~2);
+
+	// set number of samples
+	//*((uint32_t *)(cfg + 4)) = 1024 * 1024 - 1;
+//	wr_reg_value(1, CFG_NSAMPLES_OFFSET, 1024 * 1024 - 1);
+
+	// enter normal mode
+//	//*((uint32_t *)(cfg + 0)) |= 2;
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |=2);
+//	printf("Reseting packetizer %d ...\n",val);
+//
+//	// wait 1 second
+	sleep(1);
+
+	// print IN1 and IN2 samples
+	for(i = 0; i < 1024 * 1024; ++i){
+		ch[0] = *((int16_t *)(cma_ptr + 2*i + 0));
+		ch[1] = *((int16_t *)(cma_ptr + 2*i + 2));
+		wo = *((uint32_t *)(cma_ptr + i));
+		printf("%5d %5d %10d\n", ch[0], ch[1], wo);
+//		ch[0] = cma_ptr[2 * i + 0];
+//		ch[1] = cma_ptr[2 * i + 1];
+//		//wo    = cma_ptr[i] 
+//		printf("%5d %5d\n", ch[0], ch[1]);
+	}
+
+	// unmap and close the devices 
+	//munmap(intc_ptr, sysconf(_SC_PAGESIZE));
+//	munmap(cfg_ptr, sysconf(_SC_PAGESIZE));
+//	//munmap(sts_ptr, sysconf(_SC_PAGESIZE));
+//	//munmap(xadc_ptr, sysconf(_SC_PAGESIZE));
+//	munmap(cma_ptr, sysconf(_SC_PAGESIZE));
+
+	//close(intc_fd);
+	close(cfg_fd);
+	//close(sts_fd);
+	//close(xadc_fd);
+	printf("Saliendo ...\n");
+
+	return 0;
+
+}
diff --git a/projects/adc_recorder/src/zynq_io.c b/projects/adc_recorder/src/zynq_io.c
new file mode 100644
index 0000000000000000000000000000000000000000..35d23c6c4c05627959bf900fe3fb16485ec1e311
--- /dev/null
+++ b/projects/adc_recorder/src/zynq_io.c
@@ -0,0 +1,470 @@
+#include "zynq_io.h"
+
+int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, cma_fd;
+void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *cma_ptr;
+uint32_t dev_size;
+
+void dev_write(void *dev_base, uint32_t offset, int32_t value)
+{
+	*((volatile unsigned *)(dev_base + offset)) = value;
+}
+
+uint32_t dev_read(void *dev_base, uint32_t offset)
+{
+	return *((volatile unsigned *)(dev_base + offset));
+}
+
+/*int dev_init(int n_dev)
+	{
+	char *uiod; = "/dev/uio1";
+
+	printf("Initializing device...\n");
+
+// open the UIO device file to allow access to the device in user space
+cfg_fd = open(uiod, O_RDWR);
+if (cfg_fd < 1) {
+printf("cfg_init: Invalid UIO device file:%s.\n", uiod);
+return -1;
+}
+
+dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size");
+
+// mmap the cfgC device into user space
+cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0);
+if (cfg_ptr == MAP_FAILED) {
+printf("cfg_init: mmap call failure.\n");
+return -1;
+}
+
+return 0;
+}*/
+
+int32_t rd_reg_value(int n_dev, uint32_t reg_off)
+{
+	int32_t reg_val;
+	switch(n_dev)
+	{
+		case 0:
+			reg_val = dev_read(intc_ptr, reg_off);
+			break;
+		case 1:
+			reg_val = dev_read(cfg_ptr, reg_off);
+			break;
+		case 2:
+			reg_val = dev_read(sts_ptr, reg_off);
+			break;
+		case 3:
+			reg_val = dev_read(xadc_ptr, reg_off);
+			break;
+		default:
+			printf("Invalid option: %d\n", n_dev);
+			return -1;
+	}
+	printf("Complete. Received data 0x%08x\n", reg_val);
+	//printf("Complete. Received data %d\n", reg_val);
+
+	return reg_val;
+}
+
+int32_t wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val)
+{
+	switch(n_dev)
+	{
+		case 0:
+			dev_write(intc_ptr, reg_off, reg_val);
+			break;
+		case 1:
+			dev_write(cfg_ptr, reg_off, reg_val);
+			break;
+		case 2:
+			dev_write(sts_ptr, reg_off, reg_val);
+			break;
+		case 3:
+			dev_write(xadc_ptr, reg_off, reg_val);
+			break;
+		default:
+			printf("Invalid option: %d\n", n_dev);
+			return -1;
+	}
+	printf("Complete. Data written: 0x%08x\n", reg_val);
+	//printf("Complete. Data written: %d\n", reg_val);
+
+	return 0;
+}
+
+int32_t rd_cfg_status(void)
+{
+	//float a = 0.0382061, b = 4.11435;  // For gain = 1.45
+	float a = 0.0882006, b = 7.73516;  // For gain = 3.2
+
+	printf("#Trigger Level Ch1 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_1_OFFSET));
+	printf("#Trigger Level Ch2 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_2_OFFSET));
+	//printf("#Subtrigger Ch1    = %d\n", dev_read(cfg_ptr, CFG_STRLVL_1_OFFSET));
+	//printf("#Subtrigger Ch2    = %d\n", dev_read(cfg_ptr, CFG_STRLVL_2_OFFSET));
+	printf("#High Voltage 1    = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV1_OFFSET)+b);
+	printf("#High Voltage 2    = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV2_OFFSET)+b);
+	printf("#Trigger Scaler 1  = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_A_OFFSET));
+	printf("#Trigger Scaler 2  = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_B_OFFSET));
+	if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // No GPS is present
+		printf("#No GPS device is present or enabled\n");
+	}else{
+		printf("#Using GPS data\n");
+	}
+	if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>5) & 0x1) == 0) //Slave
+	{
+		printf("#Working mode is SLAVE\n");
+	}else{
+		printf("#Working mode is MASTER\n");
+	}
+	printf("\n");
+	printf("Status from registers complete!\n");
+	return 0;
+}
+
+static uint32_t get_memory_size(char *sysfs_path_file)
+{
+	FILE *size_fp;
+	uint32_t size;
+
+	// open the file that describes the memory range size that is based on
+	// the reg property of the node in the device tree
+	size_fp = fopen(sysfs_path_file, "r");
+
+	if (!size_fp) {
+		printf("unable to open the uio size file\n");
+		exit(-1);
+	}
+
+	// get the size which is an ASCII string such as 0xXXXXXXXX and then be
+	// stop using the file
+	if(fscanf(size_fp, "0x%08X", &size) == EOF){
+		printf("unable to get the size of the uio size file\n");
+		exit(-1);
+	}
+	fclose(size_fp);
+
+	return size;
+}
+
+int intc_init(void)
+{
+	char *uiod = "/dev/uio0";
+
+	//printf("Initializing INTC device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	intc_fd = open(uiod, O_RDWR);
+	if (intc_fd < 1) {
+		printf("intc_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio0/maps/map0/size");
+
+	// mmap the INTC device into user space
+	intc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, intc_fd, 0);
+	if (intc_ptr == MAP_FAILED) {
+		printf("intc_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int cfg_init(void)
+{
+	char *mem_name = "/dev/mem";
+
+	//printf("Initializing CFG device...\n");
+
+	// open the CFG device file to allow access to the device in user space
+	cfg_fd = open(mem_name, O_RDWR);
+	if (cfg_fd < 1) {
+		printf("cfg_init: Invalid memory device file:%s.\n", mem_name);
+		return -1;
+	}
+
+	dev_size = sysconf(_SC_PAGESIZE);
+
+	// mmap the cfg device into user space
+	cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, CFG_BASEADDR);
+	if (cfg_ptr == MAP_FAILED) {
+		printf("cfg_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int sts_init(void)
+{
+	char *uiod = "/dev/uio2";
+
+	//printf("Initializing STS device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	sts_fd = open(uiod, O_RDWR);
+	if (sts_fd < 1) {
+		printf("sts_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio2/maps/map0/size");
+
+	// mmap the STS device into user space
+	sts_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, sts_fd, 0);
+	if (sts_ptr == MAP_FAILED) {
+		printf("sts_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int xadc_init(void)
+{
+	char *uiod = "/dev/uio3";
+
+	//printf("Initializing XADC device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	xadc_fd = open(uiod, O_RDWR);
+	if (xadc_fd < 1) {
+		printf("xadc_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio3/maps/map0/size"); 
+
+	// mmap the XADC device into user space
+	xadc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, xadc_fd, 0);
+	if (xadc_ptr == MAP_FAILED) {
+		printf("xadc_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int mem_init(void)
+{
+	char *mem_name = "/dev/mem";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	mem_fd = open(mem_name, O_RDWR);
+	if (mem_fd < 1) {
+		printf("mem_init: Invalid device file:%s.\n", mem_name);
+		return -1;
+	}
+
+	dev_size = 2048*sysconf(_SC_PAGESIZE);
+
+	// mmap the mem device into user space 
+	mem_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0x1E000000);
+	if (mem_ptr == MAP_FAILED) {
+		printf("mem_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int cma_init(void)
+{
+	char *cma_name = "/dev/cma";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	cma_fd = open(cma_name, O_RDWR);
+	if (cma_fd < 1) {
+		printf("cma_init: Invalid device file:%s.\n", cma_name);
+		return -1;
+	}
+
+	dev_size = 1024*sysconf(_SC_PAGESIZE);
+
+	if(ioctl(cma_fd, CMA_ALLOC, &dev_size) < 0) {
+		perror("ioctl");
+		return EXIT_FAILURE;
+	}
+	// mmap the mem device into user space 
+	cma_ptr = mmap(NULL, 1024*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, cma_fd, 0);
+	if (cma_ptr == MAP_FAILED) {
+		printf("cma_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+float get_voltage(uint32_t offset)
+{
+	int16_t value;
+	value = (int16_t) dev_read(xadc_ptr, offset);
+	//  printf("The Voltage is: %lf V\n", (value>>4)*XADC_CONV_VAL);
+	return ((value>>4)*XADC_CONV_VAL);
+}       
+
+/*void set_voltage(uint32_t offset, int32_t value)
+	{       
+//fit after calibration. See file data_calib.txt in /ramp_test directory 
+// y = a*x + b
+//a               = 0.0382061     
+//b               = 4.11435   
+uint32_t dac_val;
+float a = 0.0382061, b = 4.11435; 
+
+dac_val = (uint32_t)(value - b)/a;
+
+dev_write(cfg_ptr, offset, dac_val);
+printf("The Voltage is: %d mV\n", value);
+printf("The DAC value is: %d DACs\n", dac_val);
+}
+*/
+
+void set_voltage(uint32_t offset, int32_t value)
+{       
+	//fit after calibration. See file data_calib2.txt in /ramp_test directory 
+	// y = a*x + b
+	//a               = 0.0882006     
+	//b               = 7.73516   
+	uint32_t dac_val;
+	float a = 0.0882006, b = 7.73516; 
+
+	dac_val = (uint32_t)(value - b)/a;
+
+	dev_write(cfg_ptr, offset, dac_val);
+	printf("The Voltage is: %d mV\n", value);
+	printf("The DAC value is: %d DACs\n", dac_val);
+}
+
+float get_temp_AD592(uint32_t offset)
+{
+	float value;
+	value = get_voltage(offset);
+	return ((value*1000)-273.15);
+}       
+
+//System initialization
+int init_system(void)
+{
+	uint32_t reg_val;
+
+	//FIXME: replace hardcoded values for defines
+	// set trigger_lvl_1
+	dev_write(cfg_ptr,CFG_TRLVL_1_OFFSET,8190);
+
+	// set trigger_lvl_2
+	dev_write(cfg_ptr,CFG_TRLVL_2_OFFSET,8190);
+
+	// set subtrigger_lvl_1
+	dev_write(cfg_ptr,CFG_STRLVL_1_OFFSET,8190);
+
+	// set subtrigger_lvl_2
+	dev_write(cfg_ptr,CFG_STRLVL_2_OFFSET,8190);
+
+	// set hv1 and hv2 to zero
+	dev_write(cfg_ptr,CFG_HV1_OFFSET,0);
+	dev_write(cfg_ptr,CFG_HV2_OFFSET,0);
+
+	// reset ramp generators
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~8);
+
+	// reset pps_gen, fifo and trigger modules
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~1);
+
+	/* reset data converter and writer */
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~4);
+
+	// enter reset mode for tlast_gen
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~2);
+
+	// set number of samples
+	dev_write(cfg_ptr,CFG_NSAMPLES_OFFSET, 1024 * 1024);
+
+	// set default value for trigger scalers a and b
+	dev_write(cfg_ptr,CFG_TR_SCAL_A_OFFSET, 1);
+	dev_write(cfg_ptr,CFG_TR_SCAL_B_OFFSET, 1);
+
+	// enter normal mode for tlast_gen
+	/*        reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 2);
+	//printf("written reg_val tlast : 0x%08x\n",reg_val | 2);
+	// enter normal mode for pps_gen, fifo and trigger modules
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 1);
+	//printf("written reg_val pps_gen, fifo : 0x%08x\n",reg_val | 1);
+	*/
+	// enable false GPS
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | FGPS_EN_MASK);
+	//printf("written reg_val : 0x%08x\n",reg_val | 16);
+	// disable
+	//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~16);
+	//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~FGPS_EN_MASK);
+	//printf("written reg_val : 0x%08x\n",reg_val & ~16);
+
+	/*        // enter normal mode for data converter and writer
+						reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+						dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 4);
+	//printf("written reg_val : 0x%08hx\n",reg_val | 4);
+	*/
+	// enter normal mode for ramp generators
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 8);
+	// enter in MASTER mode (default)
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 0x20);
+
+	return 0;
+}
+
+int enable_interrupt(void)
+{
+	// steps to accept interrupts -> as pg. 26 of pg099-axi-intc.pdf
+	//1) Each bit in the IER corresponding to an interrupt must be set to 1.
+	dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 1);
+	//2) There are two bits in the MER. The ME bit must be set to enable the
+	//interrupt request outputs.
+	dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK | XIL_AXI_INTC_MER_HIE_MASK);
+	//dev_write(dev_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK);
+
+	//The next block of code is to test interrupts by software
+	//3) Software testing can now proceed by writing a 1 to any bit position
+	//in the ISR that corresponds to an existing interrupt input.
+	/*        dev_write(intc_ptr,XIL_AXI_INTC_IPR_OFFSET, 1);
+
+						for(a=0; a<10; a++)
+						{
+						wait_for_interrupt(fd, dev_ptr);
+						dev_write(dev_ptr,XIL_AXI_INTC_ISR_OFFSET, 1); //regenerate interrupt
+						}
+						*/
+	return 0;
+
+}
+
+int disable_interrupt(void)
+{
+	uint32_t value;
+	//Disable interrupt INTC0
+	dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 0);
+	//disable IRQ
+	value = dev_read(intc_ptr, XIL_AXI_INTC_MER_OFFSET);
+	dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, value | ~1);
+	//Acknowledge any previous interrupt
+	dev_write(intc_ptr, XIL_AXI_INTC_IAR_OFFSET, 1);
+
+	return 0;
+}
+
diff --git a/projects/adc_recorder/src/zynq_io.h b/projects/adc_recorder/src/zynq_io.h
new file mode 100644
index 0000000000000000000000000000000000000000..b430eb3d4ccd6d73af5abc5a085f03a78818ecb0
--- /dev/null
+++ b/projects/adc_recorder/src/zynq_io.h
@@ -0,0 +1,154 @@
+#ifndef _ZYNQ_IO_H_
+#define _ZYNQ_IO_H_
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#define CMA_ALLOC _IOWR('Z', 0, uint32_t)
+#define INTC_BASEADDR 0x40000000
+#define INTC_HIGHADDR 0x40000FFF
+
+#define CFG_BASEADDR  0x40000000
+#define CFG_HIGHADDR  0x40000FFF
+
+#define STS_BASEADDR  0x40002000
+#define STS_HIGHADDR  0x40002FFF
+
+#define XADC_BASEADDR 0x40003000
+#define XADC_HIGHADDR 0x40003FFF
+
+#define XIL_AXI_INTC_ISR_OFFSET    0x0
+#define XIL_AXI_INTC_IPR_OFFSET    0x4
+#define XIL_AXI_INTC_IER_OFFSET    0x8
+#define XIL_AXI_INTC_IAR_OFFSET    0xC
+#define XIL_AXI_INTC_SIE_OFFSET    0x10
+#define XIL_AXI_INTC_CIE_OFFSET    0x14
+#define XIL_AXI_INTC_IVR_OFFSET    0x18
+#define XIL_AXI_INTC_MER_OFFSET    0x1C
+#define XIL_AXI_INTC_IMR_OFFSET    0x20
+#define XIL_AXI_INTC_ILR_OFFSET    0x24
+#define XIL_AXI_INTC_IVAR_OFFSET   0x100
+
+#define XIL_AXI_INTC_MER_ME_MASK 0x00000001
+#define XIL_AXI_INTC_MER_HIE_MASK 0x00000002
+
+//CFG
+#define CFG_RESET_GRAL_OFFSET    0x0
+#define CFG_WR_ADDR_OFFSET       0x4
+#define CFG_NSAMPLES_OFFSET      0x8
+#define CFG_TRLVL_1_OFFSET       0x8
+#define CFG_TRLVL_2_OFFSET       0xC
+#define CFG_STRLVL_1_OFFSET      0x10
+#define CFG_STRLVL_2_OFFSET      0x14
+#define CFG_TEMPERATURE_OFFSET   0x18
+#define CFG_PRESSURE_OFFSET      0x1C
+#define CFG_TIME_OFFSET          0x20
+#define CFG_DATE_OFFSET          0x24
+#define CFG_LATITUDE_OFFSET      0x28
+#define CFG_LONGITUDE_OFFSET     0x2C
+#define CFG_ALTITUDE_OFFSET      0x30
+#define CFG_SATELLITE_OFFSET     0x34
+#define CFG_TR_SCAL_A_OFFSET     0x38
+#define CFG_TR_SCAL_B_OFFSET     0x3C
+#define CFG_HV1_OFFSET           0x4C //DAC_PWM3
+#define CFG_HV2_OFFSET           0x48 //DAC_PWM2
+#define CFG_HV3_OFFSET           0x40 //DAC_PWM0
+#define CFG_HV4_OFFSET           0x44 //DAC_PWM1
+
+//CFG Slow DAC
+#define CFG_DAC_PWM0_OFFSET 0x40
+#define CFG_DAC_PWM1_OFFSET 0x44
+#define CFG_DAC_PWM2_OFFSET 0x48
+#define CFG_DAC_PWM3_OFFSET 0x4C
+
+#define ENBL_ALL_MASK         0xFFFFFFFF
+#define RST_ALL_MASK          0x00000000
+#define RST_PPS_TRG_FIFO_MASK 0x00000001
+#define RST_TLAST_GEN_MASK    0x00000002
+#define RST_WRITER_MASK       0x00000004
+#define RST_AO_MASK           0x00000008
+#define FGPS_EN_MASK          0x00000010
+
+//STS
+#define STS_STATUS_OFFSET     0x0
+
+//XADC
+//See page 17 of PG091
+#define XADC_SRR_OFFSET          0x00   //Software reset register
+#define XADC_SR_OFFSET           0x04   //Status Register
+#define XADC_AOSR_OFFSET         0x08   //Alarm Out Status Register
+#define XADC_CONVSTR_OFFSET      0x0C   //CONVST Register
+#define XADC_SYSMONRR_OFFSET     0x10   //XADC Reset Register
+#define XADC_GIER_OFFSET         0x5C   //Global Interrupt Enable Register
+#define XADC_IPISR_OFFSET        0x60   //IP Interrupt Status Register
+#define XADC_IPIER_OFFSET        0x68   //IP Interrupt Enable Register
+#define XADC_TEMPERATURE_OFFSET  0x200  //Temperature
+#define XADC_VCCINT_OFFSET       0x204  //VCCINT
+#define XADC_VCCAUX_OFFSET       0x208  //VCCAUX
+#define XADC_VPVN_OFFSET         0x20C  //VP/VN
+#define XADC_VREFP_OFFSET        0x210  //VREFP
+#define XADC_VREFN_OFFSET        0x214  //VREFN
+#define XADC_VBRAM_OFFSET        0x218  //VBRAM
+#define XADC_UNDEF_OFFSET        0x21C  //Undefined
+#define XADC_SPLYOFF_OFFSET      0x220  //Supply Offset
+#define XADC_ADCOFF_OFFSET       0x224  //ADC Offset
+#define XADC_GAIN_ERR_OFFSET     0x228  //Gain Error
+#define XADC_ZDC_SPLY_OFFSET     0x234  //Zynq-7000 Device Core Supply
+#define XADC_ZDC_AUX_SPLY_OFFSET 0x238  //Zynq-7000 Device Core Aux Supply
+#define XADC_ZDC_MEM_SPLY_OFFSET 0x23C  //Zynq-7000 Device Core Memory Supply
+#define XADC_VAUX_PN_0_OFFSET    0x240  //VAUXP[0]/VAUXN[0]
+#define XADC_VAUX_PN_1_OFFSET    0x244  //VAUXP[1]/VAUXN[1]
+#define XADC_VAUX_PN_2_OFFSET    0x248  //VAUXP[2]/VAUXN[2]
+#define XADC_VAUX_PN_3_OFFSET    0x24C  //VAUXP[3]/VAUXN[3]
+#define XADC_VAUX_PN_4_OFFSET    0x250  //VAUXP[4]/VAUXN[4]
+#define XADC_VAUX_PN_5_OFFSET    0x254  //VAUXP[5]/VAUXN[5]
+#define XADC_VAUX_PN_6_OFFSET    0x258  //VAUXP[6]/VAUXN[6]
+#define XADC_VAUX_PN_7_OFFSET    0x25C  //VAUXP[7]/VAUXN[7]
+#define XADC_VAUX_PN_8_OFFSET    0x260  //VAUXP[8]/VAUXN[8]
+#define XADC_VAUX_PN_9_OFFSET    0x264  //VAUXP[9]/VAUXN[9]
+#define XADC_VAUX_PN_10_OFFSET   0x268  //VAUXP[10]/VAUXN[10]
+#define XADC_VAUX_PN_11_OFFSET   0x26C  //VAUXP[11]/VAUXN[11]
+#define XADC_VAUX_PN_12_OFFSET   0x270  //VAUXP[12]/VAUXN[12]
+#define XADC_VAUX_PN_13_OFFSET   0x274  //VAUXP[13]/VAUXN[13]
+#define XADC_VAUX_PN_14_OFFSET   0x278  //VAUXP[14]/VAUXN[14]
+#define XADC_VAUX_PN_15_OFFSET   0x27C  //VAUXP[15]/VAUXN[15]
+
+#define XADC_AI0_OFFSET XADC_VAUX_PN_8_OFFSET
+#define XADC_AI1_OFFSET XADC_VAUX_PN_0_OFFSET
+#define XADC_AI2_OFFSET XADC_VAUX_PN_1_OFFSET
+#define XADC_AI3_OFFSET XADC_VAUX_PN_9_OFFSET
+
+#define XADC_CONV_VAL 0.00171191993362 //(A_ip/2^12)*(34.99/4.99)
+#define XADC_RDIV_VAL 1.883236177     //voltage divisor in board (15k+16.983k)/16.983k = 1.88
+#define XADC_BASE_HVDIV 0.00294088    //voltage divisor in HV base board (100k/31.3Meg) = 3.194888179. The value I put here is the measured one.
+
+extern int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, cma_fd;
+extern void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *cma_ptr;
+extern uint32_t dev_size;
+
+void     dev_write(void *dev_base, uint32_t offset, int32_t value);
+uint32_t dev_read(void *dev_base, uint32_t offset);
+//int    dev_init(int n_dev);
+int32_t  rd_reg_value(int n_dev, uint32_t reg_off);
+int32_t  wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val);
+int32_t  rd_cfg_status(void);
+int      intc_init(void);
+int      cfg_init(void);
+int      sts_init(void);
+int      xadc_init(void);
+int      mem_init(void);
+int      cma_init(void);
+float    get_voltage(uint32_t offset);
+void     set_voltage(uint32_t offset, int32_t value);
+float    get_temp_AD592(uint32_t offset);
+int      init_system(void);
+int      enable_interrupt(void);
+int      disable_interrupt(void);
+
+#endif
+
diff --git a/projects/adc_recorder_old/adc-recorder.c b/projects/adc_recorder_old/adc-recorder.c
new file mode 100644
index 0000000000000000000000000000000000000000..c8c6e7ba100ee61ce849e72981afc9bd3930eee6
--- /dev/null
+++ b/projects/adc_recorder_old/adc-recorder.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+int main()
+{
+  int fd, i;
+  int16_t value[2];
+  void *cfg, *ram;
+  char *name = "/dev/mem";
+
+  if((fd = open(name, O_RDWR)) < 0)
+  {
+    perror("open");
+    return 1;
+  }
+
+  cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x40000000);
+  ram = mmap(NULL, 1024*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x1E000000);
+
+  // reset writer
+  *((uint32_t *)(cfg + 0)) &= ~4;
+  *((uint32_t *)(cfg + 0)) |= 4;
+
+  // reset fifo and filters
+  *((uint32_t *)(cfg + 0)) &= ~1;
+  *((uint32_t *)(cfg + 0)) |= 1;
+
+  // wait 1 second
+  sleep(1);
+
+  // enter reset mode for packetizer
+  *((uint32_t *)(cfg + 0)) &= ~2;
+
+  // set number of samples
+  *((uint32_t *)(cfg + 4)) = 1024 * 1024 - 1;
+
+  // enter normal mode
+  *((uint32_t *)(cfg + 0)) |= 2;
+
+  // wait 1 second
+  sleep(1);
+
+  // print IN1 and IN2 samples
+  for(i = 0; i < 1024 * 1024; ++i)
+  {
+    value[0] = *((int16_t *)(ram + 4*i + 0));
+    value[1] = *((int16_t *)(ram + 4*i + 2));
+    printf("%5d %5d\n", value[0], value[1]);
+  }
+
+  munmap(cfg, sysconf(_SC_PAGESIZE));
+  munmap(ram, sysconf(_SC_PAGESIZE));
+
+  return 0;
+}
diff --git a/projects/adc_recorder_old/block_design.tcl b/projects/adc_recorder_old/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..2658cdb573969173151812a10bd7c5d6a237c357
--- /dev/null
+++ b/projects/adc_recorder_old/block_design.tcl
@@ -0,0 +1,244 @@
+# Create clk_wiz
+cell xilinx.com:ip:clk_wiz pll_0 {
+  PRIMITIVE PLL
+  PRIM_IN_FREQ.VALUE_SRC USER
+  PRIM_IN_FREQ 125.0
+  PRIM_SOURCE Differential_clock_capable_pin
+  CLKOUT1_USED true
+  CLKOUT1_REQUESTED_OUT_FREQ 125.0
+  USE_RESET false
+} {
+  clk_in1_p adc_clk_p_i
+  clk_in1_n adc_clk_n_i
+}
+
+# Create processing_system7
+cell xilinx.com:ip:processing_system7 ps_0 {
+  PCW_IMPORT_BOARD_PRESET cfg/red_pitaya.xml
+  PCW_USE_S_AXI_HP0 1
+} {
+  M_AXI_GP0_ACLK pll_0/clk_out1
+  S_AXI_HP0_ACLK pll_0/clk_out1
+}
+
+# Create all required interconnections
+apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config {
+  make_external {FIXED_IO, DDR}
+  Master Disable
+  Slave Disable
+} [get_bd_cells ps_0]
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+# GPIO
+
+# Delete input/output port
+delete_bd_objs [get_bd_ports exp_p_tri_io]
+
+# Create output port
+create_bd_port -dir O -from 7 -to 0 exp_p_tri_io
+
+# ADC
+
+# Create axis_red_pitaya_adc
+cell labdpr:user:axis_rp_adc adc_0 {} {
+  aclk pll_0/clk_out1
+  adc_dat_a adc_dat_a_i
+  adc_dat_b adc_dat_b_i
+  adc_csn adc_csn_o
+}
+
+# Create axi_cfg_register
+cell labdpr:user:axi_cfg_register cfg_0 {
+  CFG_DATA_WIDTH 64
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+}
+
+# Create all required interconnections
+apply_bd_automation -rule xilinx.com:bd_rule:axi4 -config {
+  Master /ps_0/M_AXI_GP0
+  Clk Auto
+} [get_bd_intf_pins cfg_0/S_AXI]
+
+set_property RANGE 4K [get_bd_addr_segs ps_0/Data/SEG_cfg_0_reg0]
+set_property OFFSET 0x40000000 [get_bd_addr_segs ps_0/Data/SEG_cfg_0_reg0]
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_1 {
+  DIN_WIDTH 64 DIN_FROM 0 DIN_TO 0
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_2 {
+  DIN_WIDTH 64 DIN_FROM 1 DIN_TO 1
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_3 {
+  DIN_WIDTH 64 DIN_FROM 2 DIN_TO 2
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_4 {
+  DIN_WIDTH 64 DIN_FROM 63 DIN_TO 32
+} {
+  din cfg_0/cfg_data
+}
+
+# Create util_vector_logic
+cell xilinx.com:ip:util_vector_logic not_0 {
+  C_SIZE 1
+  C_OPERATION not
+} {
+  Op1 slice_2/dout
+}
+
+# Create xlconcat
+cell xilinx.com:ip:xlconcat concat_0 {
+  NUM_PORTS 2
+  IN0_WIDTH 1
+  IN1_WIDTH 7
+} {
+  In0 not_0/Res
+  dout exp_p_tri_io
+}
+
+# Create axis_broadcaster
+cell xilinx.com:ip:axis_broadcaster bcast_0 {
+  S_TDATA_NUM_BYTES.VALUE_SRC USER
+  M_TDATA_NUM_BYTES.VALUE_SRC USER
+  S_TDATA_NUM_BYTES 4
+  M_TDATA_NUM_BYTES 2
+  M00_TDATA_REMAP {tdata[13:0],2'b00}
+  M01_TDATA_REMAP {tdata[29:16],2'b00}
+} {
+  S_AXIS adc_0/M_AXIS
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+# Create cic_compiler
+cell xilinx.com:ip:cic_compiler cic_0 {
+  INPUT_DATA_WIDTH.VALUE_SRC USER
+  FILTER_TYPE Decimation
+  NUMBER_OF_STAGES 6
+  FIXED_OR_INITIAL_RATE 32
+  INPUT_SAMPLE_FREQUENCY 125
+  CLOCK_FREQUENCY 125
+  INPUT_DATA_WIDTH 16
+  QUANTIZATION Truncation
+  OUTPUT_DATA_WIDTH 16
+  USE_XTREME_DSP_SLICE true
+  HAS_ARESETN true
+} {
+  S_AXIS_DATA bcast_0/M00_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_1/dout
+}
+
+# Create cic_compiler
+cell xilinx.com:ip:cic_compiler cic_1 {
+  INPUT_DATA_WIDTH.VALUE_SRC USER
+  FILTER_TYPE Decimation
+  NUMBER_OF_STAGES 6
+  FIXED_OR_INITIAL_RATE 32
+  INPUT_SAMPLE_FREQUENCY 125
+  CLOCK_FREQUENCY 125
+  INPUT_DATA_WIDTH 16
+  QUANTIZATION Truncation
+  OUTPUT_DATA_WIDTH 16
+  USE_XTREME_DSP_SLICE true
+  HAS_ARESETN true
+} {
+  S_AXIS_DATA bcast_0/M01_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_1/dout
+}
+
+# Create axis_combiner
+cell  xilinx.com:ip:axis_combiner comb_0 {
+  TDATA_NUM_BYTES.VALUE_SRC USER
+  TDATA_NUM_BYTES 2
+} {
+  S00_AXIS cic_0/M_AXIS_DATA
+  S01_AXIS cic_1/M_AXIS_DATA
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+# Create fir_compiler
+cell xilinx.com:ip:fir_compiler fir_0 {
+  DATA_WIDTH.VALUE_SRC USER
+  DATA_WIDTH 16
+  COEFFICIENTVECTOR {-1.64753028794138e-08, -4.72969860103254e-08, -7.81983994864729e-10, 3.09179315378013e-08, 1.8600476137934e-08, 3.27300695910419e-08, -6.27121813377163e-09, -1.52196115352429e-07, -8.30377969926702e-08, 3.14361841397898e-07, 3.05515872274853e-07, -4.73906648324436e-07, -7.13188274738437e-07, 5.47004771774003e-07, 1.33401100809314e-06, -4.13867548024707e-07, -2.14949555259695e-06, -6.77977800948474e-08, 3.07398932714553e-06, 1.0366230107463e-06, -3.94245232963009e-06, -2.59076839821521e-06, 4.51317323767107e-06, 4.74563996488482e-06, -4.49064349142054e-06, -7.3947777960083e-06, 3.57041197419745e-06, 1.02846684426837e-05, -1.50308472093842e-06, -1.30146997163052e-05, -1.8311731233767e-06, 1.50710364353895e-05, 6.3515248701083e-06, -1.58982472678568e-05, -1.17267343142635e-05, 1.50041199296265e-05, 1.73635115814309e-05, -1.20890304109726e-05, -2.24560062957254e-05, 7.16700059796055e-06, 2.60907689345942e-05, -6.64193032293714e-07, -2.74163749798938e-05, -6.54632074532538e-06, 2.5852558776971e-05, 1.31966582845397e-05, -2.13079073598636e-05, -1.77801135294917e-05, 1.43611952054032e-05, 1.88093817512436e-05, -6.35698021047062e-06, -1.51543007857966e-05, -6.31269475321274e-07, 6.41236246473726e-06, 4.00235076480002e-06, 6.75384652715119e-06, -1.00102812372645e-06, -2.23907547607786e-05, -1.07614170164429e-05, 3.72128949266483e-05, 3.26888314865614e-05, -4.68343172264928e-05, -6.46247522446593e-05, 4.62331324663801e-05, 0.000104353987875991, -3.05204178369922e-05, -0.000147387572103254, -4.12376672483791e-06, 0.000187096070793206, 5.94492160104715e-05, -0.000215270553995213, -0.000134242574203586, 0.000223115373945588, 0.000223732063932204, -0.000202601585158347, -0.000319473722277179, 0.000148023831554525, 0.000409856470754451, -5.75319241913947e-05, -0.00048128691789378, -6.56435551088113e-05, 0.000520005389882914, 0.000212559310978688, -0.000514378040456993, -0.000368824791639381, 0.000457257636791032, 0.00051572189965271, -0.000348325111720936, -0.000632574861580132, 0.000195575644936742, 0.000699853643923955, -1.5816811333843e-05, -0.000702875004558909, -0.000166267212059945, 0.000635554670416145, 0.000320646045613507, -0.000503596369030625, -0.000416023690327203, 0.000326453158345306, 0.00042516016658693, -0.000137454215410763, -0.000330867755122004, -1.83577770104995e-05, 0.000131884375290827, 8.88732824246191e-05, 0.000152320700965935, -2.19145324792827e-05, -0.000478845867687744, -0.000226130995959082, 0.000781165284659716, 0.000680083599509367, -0.000973297239795462, -0.00133684955123469, 0.000956951103249511, 0.00215724393391554, -0.000632647805407322, -0.00306094569410801, -8.63474252426424e-05, 0.00392560461099799, 0.00125840455441931, -0.00459097537930345, -0.00289777037472875, 0.00486843895178868, 0.00496041688761007, -0.00455566278421732, -0.0073332195556104, 0.00345548961533671, 0.00982788076765724, -0.0013975392826423, -0.0121803938743171, -0.00173944634676796, 0.0140556603140014, 0.00600554245501628, -0.0150585666700821, -0.0113645359721422, 0.0147416608531572, 0.0176785888467245, -0.0126130926725902, -0.0247012339350495, 0.00812796467212303, 0.0320712315374266, -0.000646259298618774, -0.0392988478933562, -0.0106852885932714, 0.0457163887873562, 0.0272344645510023, -0.0503010855018923, -0.0516879242105393, 0.0510032995068897, 0.0905252892059647, -0.0416077244968566, -0.163677972614864, -0.0107434888500177, 0.356350050991766, 0.554721342376512, 0.356350050991766, -0.0107434888500177, -0.163677972614864, -0.0416077244968565, 0.0905252892059646, 0.0510032995068897, -0.0516879242105392, -0.0503010855018923, 0.0272344645510023, 0.0457163887873562, -0.0106852885932714, -0.0392988478933562, -0.000646259298618766, 0.0320712315374266, 0.008127964672123, -0.0247012339350495, -0.0126130926725902, 0.0176785888467245, 0.0147416608531572, -0.0113645359721422, -0.0150585666700821, 0.00600554245501627, 0.0140556603140014, -0.00173944634676796, -0.0121803938743171, -0.0013975392826423, 0.00982788076765723, 0.00345548961533672, -0.0073332195556104, -0.00455566278421732, 0.00496041688761004, 0.00486843895178868, -0.00289777037472874, -0.00459097537930345, 0.00125840455441931, 0.003925604610998, -8.6347425242651e-05, -0.00306094569410801, -0.000632647805407327, 0.00215724393391554, 0.000956951103249513, -0.00133684955123469, -0.000973297239795458, 0.00068008359950937, 0.000781165284659718, -0.000226130995959085, -0.000478845867687734, -2.19145324792814e-05, 0.000152320700965923, 8.88732824246168e-05, 0.000131884375290828, -1.83577770104952e-05, -0.000330867755122008, -0.000137454215410769, 0.000425160166586931, 0.000326453158345309, -0.000416023690327193, -0.000503596369030629, 0.000320646045613497, 0.000635554670416148, -0.000166267212059939, -0.000702875004558908, -1.58168113338674e-05, 0.000699853643923955, 0.000195575644936758, -0.000632574861580132, -0.000348325111720941, 0.000515721899652708, 0.000457257636791035, -0.000368824791639379, -0.000514378040456997, 0.000212559310978687, 0.000520005389882915, -6.56435551088096e-05, -0.000481286917893776, -5.7531924191395e-05, 0.000409856470754451, 0.000148023831554525, -0.000319473722277176, -0.000202601585158348, 0.000223732063932204, 0.000223115373945587, -0.000134242574203588, -0.000215270553995212, 5.944921601047e-05, 0.000187096070793206, -4.12376672483805e-06, -0.000147387572103254, -3.05204178369924e-05, 0.000104353987875991, 4.62331324663777e-05, -6.46247522446589e-05, -4.68343172264921e-05, 3.26888314865612e-05, 3.72128949266458e-05, -1.07614170164428e-05, -2.23907547607785e-05, -1.0010281237264e-06, 6.7538465271515e-06, 4.00235076480007e-06, 6.41236246473652e-06, -6.31269475321259e-07, -1.5154300785797e-05, -6.35698021047036e-06, 1.88093817512439e-05, 1.43611952054029e-05, -1.77801135294911e-05, -2.13079073598635e-05, 1.31966582845395e-05, 2.58525587769708e-05, -6.54632074532428e-06, -2.74163749798938e-05, -6.64193032294061e-07, 2.60907689345942e-05, 7.16700059796085e-06, -2.24560062957254e-05, -1.20890304109726e-05, 1.7363511581431e-05, 1.50041199296266e-05, -1.17267343142635e-05, -1.58982472678571e-05, 6.3515248701082e-06, 1.50710364353894e-05, -1.83117312337678e-06, -1.30146997163053e-05, -1.50308472093845e-06, 1.02846684426836e-05, 3.57041197419745e-06, -7.39477779600816e-06, -4.49064349142055e-06, 4.74563996488478e-06, 4.51317323767109e-06, -2.59076839821518e-06, -3.94245232963005e-06, 1.03662301074629e-06, 3.07398932714552e-06, -6.77977800948646e-08, -2.14949555259695e-06, -4.13867548024735e-07, 1.33401100809314e-06, 5.47004771773993e-07, -7.13188274738437e-07, -4.73906648324394e-07, 3.05515872274853e-07, 3.14361841397861e-07, -8.30377969926656e-08, -1.5219611535243e-07, -6.27121813377245e-09, 3.27300695910341e-08, 1.86004761379317e-08, 3.0917931537805e-08, -7.81983994865244e-10, -4.72969860103212e-08, -1.64753028794135e-08}
+  COEFFICIENT_WIDTH 16
+  QUANTIZATION Quantize_Only
+  BESTPRECISION true
+  FILTER_TYPE Decimation
+  DECIMATION_RATE 2
+  NUMBER_PATHS 2
+  RATESPECIFICATION Input_Sample_Period
+  SAMPLEPERIOD 32
+  OUTPUT_ROUNDING_MODE Truncate_LSBs
+  OUTPUT_WIDTH 16
+  HAS_ARESETN true
+} {
+  S_AXIS_DATA comb_0/M_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_1/dout
+}
+
+# Create axis_packetizer
+cell labdpr:user:axis_packetizer pktzr_0 {
+  AXIS_TDATA_WIDTH 32
+  CNTR_WIDTH 32
+  CONTINUOUS FALSE
+} {
+  S_AXIS fir_0/M_AXIS_DATA
+  cfg_data slice_4/dout
+  aclk pll_0/clk_out1
+  aresetn slice_2/dout
+}
+
+# Create axis_dwidth_converter
+cell xilinx.com:ip:axis_dwidth_converter conv_0 {
+  S_TDATA_NUM_BYTES.VALUE_SRC USER
+  S_TDATA_NUM_BYTES 4
+  M_TDATA_NUM_BYTES 8
+} {
+  S_AXIS pktzr_0/M_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_3/dout
+}
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_1 {
+  CONST_WIDTH 32
+  CONST_VAL 503316480
+}
+
+# Create axis_ram_writer
+cell labdpr:user:axis_ram_writer writer_0 {
+  ADDR_WIDTH 22
+} {
+  S_AXIS conv_0/M_AXIS
+  M_AXI ps_0/S_AXI_HP0
+  cfg_data const_1/dout
+  aclk pll_0/clk_out1
+  aresetn slice_3/dout
+}
+
+assign_bd_address [get_bd_addr_segs ps_0/S_AXI_HP0/HP0_DDR_LOWOCM]
diff --git a/projects/adc_recorder_old/src/Makefile b/projects/adc_recorder_old/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..3949c777a22024657bcf96313056f149c2373b2f
--- /dev/null
+++ b/projects/adc_recorder_old/src/Makefile
@@ -0,0 +1,16 @@
+CC=gcc
+FLAGS=-Wall -O3
+ARCH=arm
+CROSS_COMPILE=arm-xilinx-linux-gnueabi-
+
+####
+PROG=adc_recorder
+EXTRA=
+
+all: $(PROG)
+
+$(PROG): $(PROG).c $(EXTRA) 
+	$(CC) $(FLAGS) -o $(PROG) $(PROG).c $(EXTRA) -lm -lpthread
+
+clean:
+	rm -f $(PROG)
diff --git a/projects/adc_recorder_old/src/adc_recorder.c b/projects/adc_recorder_old/src/adc_recorder.c
new file mode 100644
index 0000000000000000000000000000000000000000..febaf6b14ee289a3ca507268ee427e58c9e34d95
--- /dev/null
+++ b/projects/adc_recorder_old/src/adc_recorder.c
@@ -0,0 +1,361 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#include "zynq_io.h"
+
+int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd;
+void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr;
+int dev_size;
+
+void dev_write(void *dev_base, uint32_t offset, int32_t value)
+{
+				*((volatile unsigned *)(dev_base + offset)) = value;
+}
+
+uint32_t dev_read(void *dev_base, uint32_t offset)
+{
+				return *((volatile unsigned *)(dev_base + offset));
+}
+
+int32_t rd_reg_value(int n_dev, uint32_t reg_off)
+{
+				int32_t reg_val;
+				switch(n_dev)
+				{
+								case 0:
+												reg_val = dev_read(intc_ptr, reg_off);
+												break;
+								case 1:
+												reg_val = dev_read(cfg_ptr, reg_off);
+												break;
+								case 2:
+												reg_val = dev_read(sts_ptr, reg_off);
+												break;
+								case 3:
+												reg_val = dev_read(xadc_ptr, reg_off);
+												break;
+								default:
+												printf("Invalid option: %d\n", n_dev);
+												return -1;
+				}
+				printf("Complete. Received data 0x%08x\n", reg_val);
+				//printf("Complete. Received data %d\n", reg_val);
+
+				return reg_val;
+}
+
+int32_t wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val)
+{
+				switch(n_dev)
+				{
+								case 0:
+												dev_write(intc_ptr, reg_off, reg_val);
+												break;
+								case 1:
+												dev_write(cfg_ptr, reg_off, reg_val);
+												break;
+								case 2:
+												dev_write(sts_ptr, reg_off, reg_val);
+												break;
+								case 3:
+												dev_write(xadc_ptr, reg_off, reg_val);
+												break;
+								default:
+												printf("Invalid option: %d\n", n_dev);
+												return -1;
+				}
+				printf("Complete. Data written: 0x%08x\n", reg_val);
+				//printf("Complete. Data written: %d\n", reg_val);
+
+				return 0;
+}       
+
+static uint32_t get_memory_size(char *sysfs_path_file)
+{
+				FILE *size_fp;
+				uint32_t size;
+
+				// open the file that describes the memory range size that is based on
+				// the reg property of the node in the device tree
+				size_fp = fopen(sysfs_path_file, "r");
+
+				if (!size_fp) {
+								printf("unable to open the uio size file\n");
+								exit(-1);
+				}
+
+				// get the size which is an ASCII string such as 0xXXXXXXXX and then be
+				// stop using the file
+				if(fscanf(size_fp, "0x%08X", &size) == EOF){
+								printf("unable to get the size of the uio size file\n");
+								exit(-1);
+				}
+				fclose(size_fp);
+
+				return size;
+}
+
+int intc_init(void)
+{
+				char *uiod = "/dev/uio0";
+
+				//printf("Initializing INTC device...\n");
+
+				// open the UIO device file to allow access to the device in user space
+				intc_fd = open(uiod, O_RDWR);
+				if (intc_fd < 1) {
+								printf("intc_init: Invalid UIO device file:%s.\n", uiod);
+								return -1;
+				}
+
+				dev_size = get_memory_size("/sys/class/uio/uio0/maps/map0/size"); 
+
+				// mmap the INTC device into user space
+				intc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, intc_fd, 0);
+				if (intc_ptr == MAP_FAILED) {
+								printf("intc_init: mmap call failure.\n");
+								return -1;
+				}
+
+				return 0;
+}
+
+int cfg_init(void)
+{
+				char *uiod = "/dev/uio0";
+
+				printf("Initializing CFG device...\n");
+
+				// open the UIO device file to allow access to the device in user space
+				cfg_fd = open(uiod, O_RDWR);
+				if (cfg_fd < 1) {
+								printf("cfg_init: Invalid UIO device file:%s.\n", uiod);
+								return -1;
+				}
+
+				dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size");
+
+				// mmap the cfgC device into user space
+				cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0);
+				if (cfg_ptr == MAP_FAILED) {
+								printf("cfg_init: mmap call failure.\n");
+								return -1;
+				}
+
+				return 0;
+}
+
+int sts_init(void)
+{
+				char *uiod = "/dev/uio2";
+
+				//printf("Initializing STS device...\n");
+
+				// open the UIO device file to allow access to the device in user space
+				sts_fd = open(uiod, O_RDWR);
+				if (sts_fd < 1) {
+								printf("sts_init: Invalid UIO device file:%s.\n", uiod);
+								return -1;
+				}
+
+				dev_size = get_memory_size("/sys/class/uio/uio2/maps/map0/size");
+
+				// mmap the STS device into user space
+				sts_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, sts_fd, 0);
+				if (sts_ptr == MAP_FAILED) {
+								printf("sts_init: mmap call failure.\n");
+								return -1;
+				}
+
+				return 0;
+}
+
+int mem_init(void)
+{
+				char *mem_name = "/dev/mem";
+
+				//printf("Initializing mem device...\n");
+
+				// open the UIO device file to allow access to the device in user space
+				mem_fd = open(mem_name, O_RDWR);
+				if (mem_fd < 1) {
+								printf("mem_init: Invalid device file:%s.\n", mem_name);
+								return -1;
+				}
+
+				//dev_size = 2048*sysconf(_SC_PAGESIZE);
+				dev_size = 1024*sysconf(_SC_PAGESIZE);
+
+				// mmap the mem device into user space 
+				mem_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0x1E000000);
+				if (mem_ptr == MAP_FAILED) {
+								printf("mem_init: mmap call failure.\n");
+								return -1;
+				}
+
+				return 0;
+}
+
+//System initialization
+int init_system(void)
+{
+				uint32_t reg_val;
+
+				// set trigger_lvl_1
+				dev_write(cfg_ptr,CFG_TRLVL_1_OFFSET,8190);
+
+				// set trigger_lvl_2
+				dev_write(cfg_ptr,CFG_TRLVL_2_OFFSET,8190);
+
+				// set subtrigger_lvl_1
+				dev_write(cfg_ptr,CFG_STRLVL_1_OFFSET,8190);
+
+				// set subtrigger_lvl_2
+				dev_write(cfg_ptr,CFG_STRLVL_2_OFFSET,8190);
+
+				// set hv1 and hv2 to zero
+				dev_write(cfg_ptr,CFG_HV1_OFFSET,0);
+				dev_write(cfg_ptr,CFG_HV2_OFFSET,0);
+
+				// reset ramp generators
+				reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+				dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~8);
+
+				// reset pps_gen, fifo and trigger modules
+				reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+				dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~1);
+
+				/* reset data converter and writer */
+				reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+				dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~4);
+
+				// enter reset mode for tlast_gen
+				reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+				dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~2);
+
+				// set number of samples
+				dev_write(cfg_ptr,CFG_NSAMPLES_OFFSET, 1024 * 1024);
+
+				// set default value for trigger scalers a and b
+				dev_write(cfg_ptr,CFG_TR_SCAL_A_OFFSET, 1);
+				dev_write(cfg_ptr,CFG_TR_SCAL_B_OFFSET, 1);
+
+				// enter normal mode for tlast_gen
+				/*        reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+				//printf("reg_val : 0x%08x\n",reg_val);
+				dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 2);
+				//printf("written reg_val tlast : 0x%08x\n",reg_val | 2);
+				// enter normal mode for pps_gen, fifo and trigger modules
+				reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+				//printf("reg_val : 0x%08x\n",reg_val);
+				dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 1);
+				//printf("written reg_val pps_gen, fifo : 0x%08x\n",reg_val | 1);
+				*/
+				// enable false GPS
+				reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+				//printf("reg_val : 0x%08x\n",reg_val);
+				dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | FGPS_EN_MASK);
+				//printf("written reg_val : 0x%08x\n",reg_val | 16);
+				// disable
+				//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~16);
+				//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~FGPS_EN_MASK);
+				//printf("written reg_val : 0x%08x\n",reg_val & ~16);
+
+				/*        // enter normal mode for data converter and writer
+									reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+									dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 4);
+				//printf("written reg_val : 0x%08hx\n",reg_val | 4);
+				*/
+				// enter normal mode for ramp generators
+				reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+				dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 8);
+				// enter in MASTER mode (default)
+				reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+				dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 0x20);
+
+				return 0;
+}
+
+int main(int argc, char *argv[])
+{
+				//int fd;
+				//unsigned int size;
+				uint32_t i,val=0;
+				uint32_t wo;
+				int16_t ch[2];
+
+				printf("CFG UIO test\n");
+
+				//initialize devices. TODO: add error checking 
+				mem_init();
+				//intc_init();
+				cfg_init();    
+				//sts_init();
+				//xadc_init();
+
+				// reset writer
+				//*((uint32_t *)(cfg + 0)) &= ~4;
+				printf("Reseting writer...\n");
+				val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+				wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &= ~4);
+				//*((uint32_t *)(cfg + 0)) |= 4;
+				val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+				wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |= 4);
+				printf("Reseting writer %d ...\n",val);
+				printf("Reseting fifo and filters...\n");
+				// reset fifo and filters
+				//*((uint32_t *)(cfg + 0)) &= ~1;
+				val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+				wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &=~1);
+				//*((uint32_t *)(cfg + 0)) |= 1;
+				val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+				wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |=1);
+				printf("Reseting fifo and filters %d ...\n",val);
+
+				// wait 1 second
+				sleep(1);
+
+				printf("Reseting packetizer...\n");
+				// enter reset mode for packetizer
+				//*((uint32_t *)(cfg + 0)) &= ~2; 
+				val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+				wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &=~2);
+
+				// set number of samples
+				//*((uint32_t *)(cfg + 4)) = 1024 * 1024 - 1;
+				wr_reg_value(1, CFG_NSAMPLES_OFFSET, 1024 * 1024 - 1);
+
+				// enter normal mode
+				//*((uint32_t *)(cfg + 0)) |= 2;
+				val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET);
+				wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |=2);
+				printf("Reseting packetizer %d ...\n",val);
+
+				// wait 1 second
+				sleep(1);
+
+				// print IN1 and IN2 samples
+				for(i = 0; i < 1024 * 1024; ++i){
+								ch[0] = *((int16_t *)(mem_ptr + 4*i + 0));
+								ch[1] = *((int16_t *)(mem_ptr + 4*i + 2));
+								wo = *((uint32_t *)(mem_ptr + i));
+								printf("%5d %5d %10d\n", ch[0], ch[1], wo);
+				}
+
+				// unmap and close the devices 
+				//munmap(intc_ptr, sysconf(_SC_PAGESIZE));
+				munmap(cfg_ptr, sysconf(_SC_PAGESIZE));
+				//munmap(sts_ptr, sysconf(_SC_PAGESIZE));
+				//munmap(xadc_ptr, sysconf(_SC_PAGESIZE));
+				munmap(mem_ptr, sysconf(_SC_PAGESIZE));
+
+				//close(intc_fd);
+				close(cfg_fd);
+				//close(sts_fd);
+				//close(xadc_fd);
+
+				return 0;
+
+}
diff --git a/projects/adc_recorder_old/src/zynq_io.h b/projects/adc_recorder_old/src/zynq_io.h
new file mode 100644
index 0000000000000000000000000000000000000000..812e09686d7d600ef860f2fd73a67161466e1fb4
--- /dev/null
+++ b/projects/adc_recorder_old/src/zynq_io.h
@@ -0,0 +1,149 @@
+#ifndef _ZYNQ_IO_H_
+#define _ZYNQ_IO_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#define INTC_BASEADDR 0x40000000
+#define INTC_HIGHADDR 0x40000FFF
+
+#define CFG_BASEADDR  0x40000000
+#define CFG_HIGHADDR  0x40000FFF
+
+#define STS_BASEADDR  0x40002000
+#define STS_HIGHADDR  0x40002FFF
+
+#define XADC_BASEADDR 0x40003000
+#define XADC_HIGHADDR 0x40003FFF
+
+#define XIL_AXI_INTC_ISR_OFFSET    0x0
+#define XIL_AXI_INTC_IPR_OFFSET    0x4
+#define XIL_AXI_INTC_IER_OFFSET    0x8
+#define XIL_AXI_INTC_IAR_OFFSET    0xC
+#define XIL_AXI_INTC_SIE_OFFSET    0x10
+#define XIL_AXI_INTC_CIE_OFFSET    0x14
+#define XIL_AXI_INTC_IVR_OFFSET    0x18
+#define XIL_AXI_INTC_MER_OFFSET    0x1C
+#define XIL_AXI_INTC_IMR_OFFSET    0x20
+#define XIL_AXI_INTC_ILR_OFFSET    0x24
+#define XIL_AXI_INTC_IVAR_OFFSET   0x100
+
+#define XIL_AXI_INTC_MER_ME_MASK 0x00000001
+#define XIL_AXI_INTC_MER_HIE_MASK 0x00000002
+
+//CFG
+#define CFG_RESET_GRAL_OFFSET    0x0
+#define CFG_NSAMPLES_OFFSET      0x4
+#define CFG_TRLVL_1_OFFSET       0x8
+#define CFG_TRLVL_2_OFFSET       0xC
+#define CFG_STRLVL_1_OFFSET      0x10
+#define CFG_STRLVL_2_OFFSET      0x14
+#define CFG_TEMPERATURE_OFFSET   0x18
+#define CFG_PRESSURE_OFFSET      0x1C
+#define CFG_TIME_OFFSET          0x20
+#define CFG_DATE_OFFSET          0x24
+#define CFG_LATITUDE_OFFSET      0x28
+#define CFG_LONGITUDE_OFFSET     0x2C
+#define CFG_ALTITUDE_OFFSET      0x30
+#define CFG_SATELLITE_OFFSET     0x34
+#define CFG_TR_SCAL_A_OFFSET     0x38
+#define CFG_TR_SCAL_B_OFFSET     0x3C
+#define CFG_HV1_OFFSET           0x4C //DAC_PWM3
+#define CFG_HV2_OFFSET           0x48 //DAC_PWM2
+#define CFG_HV3_OFFSET           0x40 //DAC_PWM0
+#define CFG_HV4_OFFSET           0x44 //DAC_PWM1
+
+//CFG Slow DAC
+#define CFG_DAC_PWM0_OFFSET 0x40
+#define CFG_DAC_PWM1_OFFSET 0x44
+#define CFG_DAC_PWM2_OFFSET 0x48
+#define CFG_DAC_PWM3_OFFSET 0x4C
+
+#define ENBL_ALL_MASK         0xFFFFFFFF
+#define RST_ALL_MASK          0x00000000
+#define RST_PPS_TRG_FIFO_MASK 0x00000001
+#define RST_TLAST_GEN_MASK    0x00000002
+#define RST_WRITER_MASK       0x00000004
+#define RST_AO_MASK           0x00000008
+#define FGPS_EN_MASK          0x00000010
+
+//STS
+#define STS_STATUS_OFFSET     0x0
+
+//XADC
+//See page 17 of PG091
+#define XADC_SRR_OFFSET          0x00   //Software reset register
+#define XADC_SR_OFFSET           0x04   //Status Register
+#define XADC_AOSR_OFFSET         0x08   //Alarm Out Status Register
+#define XADC_CONVSTR_OFFSET      0x0C   //CONVST Register
+#define XADC_SYSMONRR_OFFSET     0x10   //XADC Reset Register
+#define XADC_GIER_OFFSET         0x5C   //Global Interrupt Enable Register
+#define XADC_IPISR_OFFSET        0x60   //IP Interrupt Status Register
+#define XADC_IPIER_OFFSET        0x68   //IP Interrupt Enable Register
+#define XADC_TEMPERATURE_OFFSET  0x200  //Temperature
+#define XADC_VCCINT_OFFSET       0x204  //VCCINT
+#define XADC_VCCAUX_OFFSET       0x208  //VCCAUX
+#define XADC_VPVN_OFFSET         0x20C  //VP/VN
+#define XADC_VREFP_OFFSET        0x210  //VREFP
+#define XADC_VREFN_OFFSET        0x214  //VREFN
+#define XADC_VBRAM_OFFSET        0x218  //VBRAM
+#define XADC_UNDEF_OFFSET        0x21C  //Undefined
+#define XADC_SPLYOFF_OFFSET      0x220  //Supply Offset
+#define XADC_ADCOFF_OFFSET       0x224  //ADC Offset
+#define XADC_GAIN_ERR_OFFSET     0x228  //Gain Error
+#define XADC_ZDC_SPLY_OFFSET     0x234  //Zynq-7000 Device Core Supply
+#define XADC_ZDC_AUX_SPLY_OFFSET 0x238  //Zynq-7000 Device Core Aux Supply
+#define XADC_ZDC_MEM_SPLY_OFFSET 0x23C  //Zynq-7000 Device Core Memory Supply
+#define XADC_VAUX_PN_0_OFFSET    0x240  //VAUXP[0]/VAUXN[0]
+#define XADC_VAUX_PN_1_OFFSET    0x244  //VAUXP[1]/VAUXN[1]
+#define XADC_VAUX_PN_2_OFFSET    0x248  //VAUXP[2]/VAUXN[2]
+#define XADC_VAUX_PN_3_OFFSET    0x24C  //VAUXP[3]/VAUXN[3]
+#define XADC_VAUX_PN_4_OFFSET    0x250  //VAUXP[4]/VAUXN[4]
+#define XADC_VAUX_PN_5_OFFSET    0x254  //VAUXP[5]/VAUXN[5]
+#define XADC_VAUX_PN_6_OFFSET    0x258  //VAUXP[6]/VAUXN[6]
+#define XADC_VAUX_PN_7_OFFSET    0x25C  //VAUXP[7]/VAUXN[7]
+#define XADC_VAUX_PN_8_OFFSET    0x260  //VAUXP[8]/VAUXN[8]
+#define XADC_VAUX_PN_9_OFFSET    0x264  //VAUXP[9]/VAUXN[9]
+#define XADC_VAUX_PN_10_OFFSET   0x268  //VAUXP[10]/VAUXN[10]
+#define XADC_VAUX_PN_11_OFFSET   0x26C  //VAUXP[11]/VAUXN[11]
+#define XADC_VAUX_PN_12_OFFSET   0x270  //VAUXP[12]/VAUXN[12]
+#define XADC_VAUX_PN_13_OFFSET   0x274  //VAUXP[13]/VAUXN[13]
+#define XADC_VAUX_PN_14_OFFSET   0x278  //VAUXP[14]/VAUXN[14]
+#define XADC_VAUX_PN_15_OFFSET   0x27C  //VAUXP[15]/VAUXN[15]
+
+#define XADC_AI0_OFFSET XADC_VAUX_PN_8_OFFSET
+#define XADC_AI1_OFFSET XADC_VAUX_PN_0_OFFSET
+#define XADC_AI2_OFFSET XADC_VAUX_PN_1_OFFSET
+#define XADC_AI3_OFFSET XADC_VAUX_PN_9_OFFSET
+
+#define XADC_CONV_VAL 0.00171191993362 //(A_ip/2^12)*(34.99/4.99)
+#define XADC_RDIV_VAL 1.883236177     //voltage divisor in board (15k+16.983k)/16.983k = 1.88
+#define XADC_BASE_HVDIV 0.00294088    //voltage divisor in HV base board (100k/31.3Meg) = 3.194888179. The value I put here is the measured one.
+
+extern int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd;
+extern void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr;
+
+void     dev_write(void *dev_base, uint32_t offset, int32_t value);
+uint32_t dev_read(void *dev_base, uint32_t offset);
+//int    dev_init(int n_dev);
+int32_t  rd_reg_value(int n_dev, uint32_t reg_off);
+int32_t  wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val);
+int32_t  rd_cfg_status(void);
+int      intc_init(void);
+int      cfg_init(void);
+int      sts_init(void);
+int      xadc_init(void);
+int      mem_init(void);
+float    get_voltage(uint32_t offset);
+void     set_voltage(uint32_t offset, int32_t value);
+float    get_temp_AD592(uint32_t offset);
+int      init_system(void);
+int      enable_interrupt(void);
+int      disable_interrupt(void);
+
+#endif
+
diff --git a/projects/adc_recorder_uio/adc-recorder.c b/projects/adc_recorder_uio/adc-recorder.c
new file mode 100644
index 0000000000000000000000000000000000000000..e409e86032df3315b8b6d858fad12850eb819d9f
--- /dev/null
+++ b/projects/adc_recorder_uio/adc-recorder.c
@@ -0,0 +1,81 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+
+#define CMA_ALLOC _IOWR('Z', 0, uint32_t)
+
+int main()
+{
+  int fd, i;
+  volatile uint8_t *rst;
+  volatile void *cfg;
+  volatile int16_t *ram;
+  uint32_t size;
+  int16_t value[2];
+
+  if((fd = open("/dev/mem", O_RDWR)) < 0)
+  {
+    perror("open");
+    return EXIT_FAILURE;
+  }
+
+  cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x40001000);
+
+  close(fd);
+
+  if((fd = open("/dev/cma", O_RDWR)) < 0)
+  {
+    perror("open");
+    return EXIT_FAILURE;
+  }
+
+  size = 1024*sysconf(_SC_PAGESIZE);
+
+  if(ioctl(fd, CMA_ALLOC, &size) < 0)
+  {
+    perror("ioctl");
+    return EXIT_FAILURE;
+  }
+
+  ram = mmap(NULL, 1024*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+  rst = (uint8_t *)(cfg + 0);
+
+  // set writer address
+  *(uint32_t *)(cfg + 4) = size;
+
+  // set number of samples
+  *(uint32_t *)(cfg + 8) = 1024 * 1024 - 1;
+
+  // reset writer
+  *rst &= ~4;
+  *rst |= 4;
+
+  // reset fifo and filters
+  *rst &= ~1;
+  *rst |= 1;
+
+  // wait 1 second
+  sleep(1);
+
+  // reset packetizer
+  *rst &= ~2;
+  *rst |= 2;
+
+  // wait 1 second
+  sleep(1);
+
+  // print IN1 and IN2 samples
+  for(i = 0; i < 1024 * 1024; ++i)
+  {
+    value[0] = ram[2 * i + 0];
+    value[1] = ram[2 * i + 1];
+    printf("%5d %5d\n", value[0], value[1]);
+  }
+
+  return EXIT_SUCCESS;
+}
diff --git a/projects/adc_recorder_uio/block_design.tcl b/projects/adc_recorder_uio/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..f55a85517bc3e4b668dc3d6dddd5b1d77f9d8f14
--- /dev/null
+++ b/projects/adc_recorder_uio/block_design.tcl
@@ -0,0 +1,213 @@
+source projects/base_system/block_design.tcl
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+# Create axis_red_pitaya_adc
+cell labdpr:user:axis_rp_adc adc_0 {
+  ADC_DATA_WIDTH 14
+} {
+  aclk pll_0/clk_out1
+  adc_dat_a adc_dat_a_i
+  adc_dat_b adc_dat_b_i
+  adc_csn adc_csn_o
+}
+
+# Create axi_cfg_register
+cell labdpr:user:axi_cfg_register cfg_0 {
+  CFG_DATA_WIDTH 96
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_0 {
+  DIN_WIDTH 96 DIN_FROM 0 DIN_TO 0
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_1 {
+  DIN_WIDTH 96 DIN_FROM 1 DIN_TO 1
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_2 {
+  DIN_WIDTH 96 DIN_FROM 2 DIN_TO 2
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_3 {
+  DIN_WIDTH 96 DIN_FROM 63 DIN_TO 32
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_4 {
+  DIN_WIDTH 96 DIN_FROM 95 DIN_TO 64
+} {
+  din cfg_0/cfg_data
+}
+
+# Create util_vector_logic
+cell xilinx.com:ip:util_vector_logic not_0 {
+  C_SIZE 1
+  C_OPERATION not
+} {
+  Op1 slice_1/dout
+}
+
+# Create xlconcat
+cell xilinx.com:ip:xlconcat concat_0 {
+  NUM_PORTS 2
+  IN0_WIDTH 1
+  IN1_WIDTH 7
+} {
+  In0 not_0/Res
+  dout exp_p_tri_io
+}
+
+# Create axis_broadcaster
+cell xilinx.com:ip:axis_broadcaster bcast_0 {
+  S_TDATA_NUM_BYTES.VALUE_SRC USER
+  M_TDATA_NUM_BYTES.VALUE_SRC USER
+  S_TDATA_NUM_BYTES 4
+  M_TDATA_NUM_BYTES 2
+  M00_TDATA_REMAP {tdata[15:0]}
+  M01_TDATA_REMAP {tdata[31:16]}
+} {
+  S_AXIS adc_0/M_AXIS
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+# Create cic_compiler
+cell xilinx.com:ip:cic_compiler cic_0 {
+  INPUT_DATA_WIDTH.VALUE_SRC USER
+  FILTER_TYPE Decimation
+  NUMBER_OF_STAGES 6
+  FIXED_OR_INITIAL_RATE 32
+  INPUT_SAMPLE_FREQUENCY 125
+  CLOCK_FREQUENCY 125
+  INPUT_DATA_WIDTH 14
+  QUANTIZATION Truncation
+  OUTPUT_DATA_WIDTH 16
+  USE_XTREME_DSP_SLICE true
+  HAS_ARESETN true
+} {
+  S_AXIS_DATA bcast_0/M00_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_0/dout
+}
+
+# Create cic_compiler
+cell xilinx.com:ip:cic_compiler cic_1 {
+  INPUT_DATA_WIDTH.VALUE_SRC USER
+  FILTER_TYPE Decimation
+  NUMBER_OF_STAGES 6
+  FIXED_OR_INITIAL_RATE 32
+  INPUT_SAMPLE_FREQUENCY 125
+  CLOCK_FREQUENCY 125
+  INPUT_DATA_WIDTH 14
+  QUANTIZATION Truncation
+  OUTPUT_DATA_WIDTH 16
+  USE_XTREME_DSP_SLICE true
+  HAS_ARESETN true
+} {
+  S_AXIS_DATA bcast_0/M01_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_0/dout
+}
+
+# Create axis_combiner
+cell  xilinx.com:ip:axis_combiner comb_0 {
+  TDATA_NUM_BYTES.VALUE_SRC USER
+  TDATA_NUM_BYTES 2
+} {
+  S00_AXIS cic_0/M_AXIS_DATA
+  S01_AXIS cic_1/M_AXIS_DATA
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+# Create fir_compiler
+cell xilinx.com:ip:fir_compiler fir_0 {
+  DATA_WIDTH.VALUE_SRC USER
+  DATA_WIDTH 16
+  COEFFICIENTVECTOR {-1.64753028794138e-08, -4.72969860103254e-08, -7.81983994864729e-10, 3.09179315378013e-08, 1.8600476137934e-08, 3.27300695910419e-08, -6.27121813377163e-09, -1.52196115352429e-07, -8.30377969926702e-08, 3.14361841397898e-07, 3.05515872274853e-07, -4.73906648324436e-07, -7.13188274738437e-07, 5.47004771774003e-07, 1.33401100809314e-06, -4.13867548024707e-07, -2.14949555259695e-06, -6.77977800948474e-08, 3.07398932714553e-06, 1.0366230107463e-06, -3.94245232963009e-06, -2.59076839821521e-06, 4.51317323767107e-06, 4.74563996488482e-06, -4.49064349142054e-06, -7.3947777960083e-06, 3.57041197419745e-06, 1.02846684426837e-05, -1.50308472093842e-06, -1.30146997163052e-05, -1.8311731233767e-06, 1.50710364353895e-05, 6.3515248701083e-06, -1.58982472678568e-05, -1.17267343142635e-05, 1.50041199296265e-05, 1.73635115814309e-05, -1.20890304109726e-05, -2.24560062957254e-05, 7.16700059796055e-06, 2.60907689345942e-05, -6.64193032293714e-07, -2.74163749798938e-05, -6.54632074532538e-06, 2.5852558776971e-05, 1.31966582845397e-05, -2.13079073598636e-05, -1.77801135294917e-05, 1.43611952054032e-05, 1.88093817512436e-05, -6.35698021047062e-06, -1.51543007857966e-05, -6.31269475321274e-07, 6.41236246473726e-06, 4.00235076480002e-06, 6.75384652715119e-06, -1.00102812372645e-06, -2.23907547607786e-05, -1.07614170164429e-05, 3.72128949266483e-05, 3.26888314865614e-05, -4.68343172264928e-05, -6.46247522446593e-05, 4.62331324663801e-05, 0.000104353987875991, -3.05204178369922e-05, -0.000147387572103254, -4.12376672483791e-06, 0.000187096070793206, 5.94492160104715e-05, -0.000215270553995213, -0.000134242574203586, 0.000223115373945588, 0.000223732063932204, -0.000202601585158347, -0.000319473722277179, 0.000148023831554525, 0.000409856470754451, -5.75319241913947e-05, -0.00048128691789378, -6.56435551088113e-05, 0.000520005389882914, 0.000212559310978688, -0.000514378040456993, -0.000368824791639381, 0.000457257636791032, 0.00051572189965271, -0.000348325111720936, -0.000632574861580132, 0.000195575644936742, 0.000699853643923955, -1.5816811333843e-05, -0.000702875004558909, -0.000166267212059945, 0.000635554670416145, 0.000320646045613507, -0.000503596369030625, -0.000416023690327203, 0.000326453158345306, 0.00042516016658693, -0.000137454215410763, -0.000330867755122004, -1.83577770104995e-05, 0.000131884375290827, 8.88732824246191e-05, 0.000152320700965935, -2.19145324792827e-05, -0.000478845867687744, -0.000226130995959082, 0.000781165284659716, 0.000680083599509367, -0.000973297239795462, -0.00133684955123469, 0.000956951103249511, 0.00215724393391554, -0.000632647805407322, -0.00306094569410801, -8.63474252426424e-05, 0.00392560461099799, 0.00125840455441931, -0.00459097537930345, -0.00289777037472875, 0.00486843895178868, 0.00496041688761007, -0.00455566278421732, -0.0073332195556104, 0.00345548961533671, 0.00982788076765724, -0.0013975392826423, -0.0121803938743171, -0.00173944634676796, 0.0140556603140014, 0.00600554245501628, -0.0150585666700821, -0.0113645359721422, 0.0147416608531572, 0.0176785888467245, -0.0126130926725902, -0.0247012339350495, 0.00812796467212303, 0.0320712315374266, -0.000646259298618774, -0.0392988478933562, -0.0106852885932714, 0.0457163887873562, 0.0272344645510023, -0.0503010855018923, -0.0516879242105393, 0.0510032995068897, 0.0905252892059647, -0.0416077244968566, -0.163677972614864, -0.0107434888500177, 0.356350050991766, 0.554721342376512, 0.356350050991766, -0.0107434888500177, -0.163677972614864, -0.0416077244968565, 0.0905252892059646, 0.0510032995068897, -0.0516879242105392, -0.0503010855018923, 0.0272344645510023, 0.0457163887873562, -0.0106852885932714, -0.0392988478933562, -0.000646259298618766, 0.0320712315374266, 0.008127964672123, -0.0247012339350495, -0.0126130926725902, 0.0176785888467245, 0.0147416608531572, -0.0113645359721422, -0.0150585666700821, 0.00600554245501627, 0.0140556603140014, -0.00173944634676796, -0.0121803938743171, -0.0013975392826423, 0.00982788076765723, 0.00345548961533672, -0.0073332195556104, -0.00455566278421732, 0.00496041688761004, 0.00486843895178868, -0.00289777037472874, -0.00459097537930345, 0.00125840455441931, 0.003925604610998, -8.6347425242651e-05, -0.00306094569410801, -0.000632647805407327, 0.00215724393391554, 0.000956951103249513, -0.00133684955123469, -0.000973297239795458, 0.00068008359950937, 0.000781165284659718, -0.000226130995959085, -0.000478845867687734, -2.19145324792814e-05, 0.000152320700965923, 8.88732824246168e-05, 0.000131884375290828, -1.83577770104952e-05, -0.000330867755122008, -0.000137454215410769, 0.000425160166586931, 0.000326453158345309, -0.000416023690327193, -0.000503596369030629, 0.000320646045613497, 0.000635554670416148, -0.000166267212059939, -0.000702875004558908, -1.58168113338674e-05, 0.000699853643923955, 0.000195575644936758, -0.000632574861580132, -0.000348325111720941, 0.000515721899652708, 0.000457257636791035, -0.000368824791639379, -0.000514378040456997, 0.000212559310978687, 0.000520005389882915, -6.56435551088096e-05, -0.000481286917893776, -5.7531924191395e-05, 0.000409856470754451, 0.000148023831554525, -0.000319473722277176, -0.000202601585158348, 0.000223732063932204, 0.000223115373945587, -0.000134242574203588, -0.000215270553995212, 5.944921601047e-05, 0.000187096070793206, -4.12376672483805e-06, -0.000147387572103254, -3.05204178369924e-05, 0.000104353987875991, 4.62331324663777e-05, -6.46247522446589e-05, -4.68343172264921e-05, 3.26888314865612e-05, 3.72128949266458e-05, -1.07614170164428e-05, -2.23907547607785e-05, -1.0010281237264e-06, 6.7538465271515e-06, 4.00235076480007e-06, 6.41236246473652e-06, -6.31269475321259e-07, -1.5154300785797e-05, -6.35698021047036e-06, 1.88093817512439e-05, 1.43611952054029e-05, -1.77801135294911e-05, -2.13079073598635e-05, 1.31966582845395e-05, 2.58525587769708e-05, -6.54632074532428e-06, -2.74163749798938e-05, -6.64193032294061e-07, 2.60907689345942e-05, 7.16700059796085e-06, -2.24560062957254e-05, -1.20890304109726e-05, 1.7363511581431e-05, 1.50041199296266e-05, -1.17267343142635e-05, -1.58982472678571e-05, 6.3515248701082e-06, 1.50710364353894e-05, -1.83117312337678e-06, -1.30146997163053e-05, -1.50308472093845e-06, 1.02846684426836e-05, 3.57041197419745e-06, -7.39477779600816e-06, -4.49064349142055e-06, 4.74563996488478e-06, 4.51317323767109e-06, -2.59076839821518e-06, -3.94245232963005e-06, 1.03662301074629e-06, 3.07398932714552e-06, -6.77977800948646e-08, -2.14949555259695e-06, -4.13867548024735e-07, 1.33401100809314e-06, 5.47004771773993e-07, -7.13188274738437e-07, -4.73906648324394e-07, 3.05515872274853e-07, 3.14361841397861e-07, -8.30377969926656e-08, -1.5219611535243e-07, -6.27121813377245e-09, 3.27300695910341e-08, 1.86004761379317e-08, 3.0917931537805e-08, -7.81983994865244e-10, -4.72969860103212e-08, -1.64753028794135e-08}
+  COEFFICIENT_WIDTH 16
+  QUANTIZATION Quantize_Only
+  BESTPRECISION true
+  FILTER_TYPE Decimation
+  DECIMATION_RATE 2
+  NUMBER_PATHS 2
+  RATESPECIFICATION Input_Sample_Period
+  SAMPLEPERIOD 32
+  OUTPUT_ROUNDING_MODE Truncate_LSBs
+  OUTPUT_WIDTH 16
+  HAS_ARESETN true
+} {
+  S_AXIS_DATA comb_0/M_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_0/dout
+}
+
+# Create axis_packetizer
+cell labdpr:user:axis_packetizer pktzr_0 {
+  AXIS_TDATA_WIDTH 32
+  CNTR_WIDTH 32
+  CONTINUOUS FALSE
+} {
+  S_AXIS fir_0/M_AXIS_DATA
+  cfg_data slice_4/dout
+  aclk pll_0/clk_out1
+  aresetn slice_1/dout
+}
+
+# Create axis_dwidth_converter
+cell xilinx.com:ip:axis_dwidth_converter conv_0 {
+  S_TDATA_NUM_BYTES.VALUE_SRC USER
+  S_TDATA_NUM_BYTES 4
+  M_TDATA_NUM_BYTES 8
+} {
+  S_AXIS pktzr_0/M_AXIS
+  aclk pll_0/clk_out1
+  aresetn slice_2/dout
+}
+
+# Create axis_ram_writer
+cell labdpr:user:axis_ram_writer writer_0 {
+  ADDR_WIDTH 22
+  AXI_ID_WIDTH 3
+} {
+  S_AXIS conv_0/M_AXIS
+  M_AXI ps_0/S_AXI_ACP
+  cfg_data slice_3/dout
+  aclk pll_0/clk_out1
+  aresetn slice_2/dout
+}
+
+# Create axi_sts_register
+cell labdpr:user:axi_sts_register sts_0 {
+  STS_DATA_WIDTH 32
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+} { 
+  sts_data writer_0/sts_data 
+
+}
+
+addr 0x40001000 4K cfg_0/S_AXI /ps_0/M_AXI_GP0
+
+addr 0x40002000 4K sts_0/S_AXI /ps_0/M_AXI_GP0
diff --git a/projects/adc_recorder_uio/uio_src/Makefile b/projects/adc_recorder_uio/uio_src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..858880d0d10cb4a7d382f7b05b409b6faded4414
--- /dev/null
+++ b/projects/adc_recorder_uio/uio_src/Makefile
@@ -0,0 +1,16 @@
+CC=gcc
+FLAGS=-Wall -O3
+ARCH=arm
+CROSS_COMPILE=arm-xilinx-linux-gnueabi-
+
+####
+PROG=adc_recorder
+EXTRA= zynq_io.c
+
+all: $(PROG)
+
+$(PROG): $(PROG).c $(EXTRA) 
+	$(CC) $(FLAGS) -o $(PROG) $(PROG).c $(EXTRA) -lm -lpthread
+
+clean:
+	rm -f $(PROG)
diff --git a/projects/adc_recorder_uio/uio_src/adc_recorder.c b/projects/adc_recorder_uio/uio_src/adc_recorder.c
new file mode 100644
index 0000000000000000000000000000000000000000..62fdb0656adde3c48cdb5321ee43f748b50df183
--- /dev/null
+++ b/projects/adc_recorder_uio/uio_src/adc_recorder.c
@@ -0,0 +1,105 @@
+#include "zynq_io.h"
+
+int main(int argc, char *argv[])
+{
+	//int fd;
+	//unsigned int size;
+	uint32_t i,val=0;
+	uint32_t wo;
+	int16_t ch[2];
+
+	//printf("ADC RECORDER test\n");
+
+	//initialize devices. TODO: add error checking 
+	//intc_init();
+	cfg_init();    
+	cma_init();
+	//sts_init();
+	//xadc_init();
+
+	// set writer address
+	//   *(uint32_t *)(cfg + 4) = size;
+	//
+	//printf("Set writer address...\n");
+	val=rd_reg_value(1, CFG_WR_ADDR_OFFSET,0);
+	//printf("dev_size es: %d ...\n",dev_size);
+	wr_reg_value(1, CFG_WR_ADDR_OFFSET, dev_size,0);
+
+	 // set number of samples
+	 //   *(uint32_t *)(cfg + 8) = 1024 * 1024 - 1;
+	 //
+	//printf("Set number of samples...\n");
+	val=rd_reg_value(1, CFG_NSAMPLES_OFFSET,0);
+	wr_reg_value(1, CFG_NSAMPLES_OFFSET, 1024 * 1024 - 1,0);
+
+	// reset writer
+	//*((uint32_t *)(cfg + 0)) &= ~4;
+	//printf("Reseting writer...\n");
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &= ~4,0);
+	//*((uint32_t *)(cfg + 0)) |= 4;
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |= 4,0);
+//	printf("Reseting writer %d ...\n",val);
+	//printf("Reseting fifo and filters...\n");
+//	// reset fifo and filters
+	//*((uint32_t *)(cfg + 0)) &= ~1;
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &=~1,0);
+//	//*((uint32_t *)(cfg + 0)) |= 1;
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |=1,0);
+//	printf("Reseting fifo and filters %d ...\n",val);
+//
+//	// wait 1 second
+	sleep(1);
+//
+	//printf("Reseting packetizer...\n");
+	// enter reset mode for packetizer
+	//*((uint32_t *)(cfg + 0)) &= ~2; 
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &=~2,0);
+
+	// set number of samples
+	//*((uint32_t *)(cfg + 4)) = 1024 * 1024 - 1;
+//	wr_reg_value(1, CFG_NSAMPLES_OFFSET, 1024 * 1024 - 1);
+
+	// enter normal mode
+//	//*((uint32_t *)(cfg + 0)) |= 2;
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |=2,0);
+//	printf("Reseting packetizer %d ...\n",val);
+//
+//	// wait 1 second
+	sleep(1);
+
+	// print IN1 and IN2 samples
+	for(i = 0; i < 1024 * 1024; ++i){
+		ch[0] = cma_ptr[2*i + 0];
+		ch[1] = cma_ptr[2*i + 1];
+		//ch[0] = *((int16_t *)(cma_ptr + 2*i + 0));
+		//ch[1] = *((int16_t *)(cma_ptr + 2*i + 1));
+		wo = *((uint32_t *)(cma_ptr + 2*i));
+		printf("%5d %5d %10d\n", ch[0], ch[1], wo);
+//		ch[0] = cma_ptr[2 * i + 0];
+//		ch[1] = cma_ptr[2 * i + 1];
+//		//wo    = cma_ptr[i] 
+//		printf("%5d %5d\n", ch[0], ch[1]);
+	}
+
+	// unmap and close the devices 
+	//munmap(intc_ptr, sysconf(_SC_PAGESIZE));
+//	munmap(cfg_ptr, sysconf(_SC_PAGESIZE));
+//	//munmap(sts_ptr, sysconf(_SC_PAGESIZE));
+//	//munmap(xadc_ptr, sysconf(_SC_PAGESIZE));
+//	munmap(cma_ptr, sysconf(_SC_PAGESIZE));
+
+	//close(intc_fd);
+	close(cfg_fd);
+	//close(sts_fd);
+	//close(xadc_fd);
+	//printf("Saliendo ...\n");
+
+	return 0;
+
+}
diff --git a/projects/adc_recorder_uio/uio_src/zynq_io.c b/projects/adc_recorder_uio/uio_src/zynq_io.c
new file mode 100644
index 0000000000000000000000000000000000000000..9ab308cac762116a4f745707fa28a167fd25d8bb
--- /dev/null
+++ b/projects/adc_recorder_uio/uio_src/zynq_io.c
@@ -0,0 +1,473 @@
+#include "zynq_io.h"
+
+int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, hst0_fd, hst1_fd, cma_fd;
+void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *hst0_ptr, *hst1_ptr;
+volatile int16_t *cma_ptr;
+uint32_t dev_size;
+
+void dev_write(void *dev_base, uint32_t offset, int32_t value)
+{
+	*((volatile unsigned *)(dev_base + offset)) = value;
+}
+
+uint32_t dev_read(void *dev_base, uint32_t offset)
+{
+	return *((volatile unsigned *)(dev_base + offset));
+}
+
+/*int dev_init(int n_dev)
+	{
+	char *uiod; = "/dev/uio1";
+
+	printf("Initializing device...\n");
+
+// open the UIO device file to allow access to the device in user space
+cfg_fd = open(uiod, O_RDWR);
+if (cfg_fd < 1) {
+printf("cfg_init: Invalid UIO device file:%s.\n", uiod);
+return -1;
+}
+
+dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size");
+
+// mmap the cfgC device into user space
+cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0);
+if (cfg_ptr == MAP_FAILED) {
+printf("cfg_init: mmap call failure.\n");
+return -1;
+}
+
+return 0;
+}*/
+
+int32_t rd_reg_value(int n_dev, uint32_t reg_off, uint8_t debug)
+{
+	int32_t reg_val;
+	switch(n_dev)
+	{
+		case 0:
+			reg_val = dev_read(intc_ptr, reg_off);
+			break;
+		case 1:
+			reg_val = dev_read(cfg_ptr, reg_off);
+			break;
+		case 2:
+			reg_val = dev_read(sts_ptr, reg_off);
+			break;
+		case 3:
+			reg_val = dev_read(xadc_ptr, reg_off);
+			break;
+		default:
+			printf("Invalid option: %d\n", n_dev);
+			return -1;
+	}
+	if(debug)
+		printf("Complete. Received data 0x%08x\n", reg_val);
+	//printf("Complete. Received data %d\n", reg_val);
+
+	return reg_val;
+}
+
+int32_t wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val, uint8_t debug)
+{
+	switch(n_dev)
+	{
+		case 0:
+			dev_write(intc_ptr, reg_off, reg_val);
+			break;
+		case 1:
+			dev_write(cfg_ptr, reg_off, reg_val);
+			break;
+		case 2:
+			dev_write(sts_ptr, reg_off, reg_val);
+			break;
+		case 3:
+			dev_write(xadc_ptr, reg_off, reg_val);
+			break;
+		default:
+			printf("Invalid option: %d\n", n_dev);
+			return -1;
+	}
+	if(debug)
+		printf("Complete. Data written: 0x%08x\n", reg_val);
+	//printf("Complete. Data written: %d\n", reg_val);
+
+	return 0;
+}
+
+int32_t rd_cfg_status(void)
+{
+	//float a = 0.0382061, b = 4.11435;  // For gain = 1.45
+	float a = 0.0882006, b = 7.73516;  // For gain = 3.2
+
+	printf("#Trigger Level Ch1 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_1_OFFSET));
+	printf("#Trigger Level Ch2 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_2_OFFSET));
+	//printf("#Subtrigger Ch1    = %d\n", dev_read(cfg_ptr, CFG_STRLVL_1_OFFSET));
+	//printf("#Subtrigger Ch2    = %d\n", dev_read(cfg_ptr, CFG_STRLVL_2_OFFSET));
+	printf("#High Voltage 1    = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV1_OFFSET)+b);
+	printf("#High Voltage 2    = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV2_OFFSET)+b);
+	printf("#Trigger Scaler 1  = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_A_OFFSET));
+	printf("#Trigger Scaler 2  = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_B_OFFSET));
+	if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // No GPS is present
+		printf("#No GPS device is present or enabled\n");
+	}else{
+		printf("#Using GPS data\n");
+	}
+	if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>5) & 0x1) == 0) //Slave
+	{
+		printf("#Working mode is SLAVE\n");
+	}else{
+		printf("#Working mode is MASTER\n");
+	}
+	printf("\n");
+	printf("Status from registers complete!\n");
+	return 0;
+}
+
+static uint32_t get_memory_size(char *sysfs_path_file)
+{
+	FILE *size_fp;
+	uint32_t size;
+
+	// open the file that describes the memory range size that is based on
+	// the reg property of the node in the device tree
+	size_fp = fopen(sysfs_path_file, "r");
+
+	if (!size_fp) {
+		printf("unable to open the uio size file\n");
+		exit(-1);
+	}
+
+	// get the size which is an ASCII string such as 0xXXXXXXXX and then be
+	// stop using the file
+	if(fscanf(size_fp, "0x%08X", &size) == EOF){
+		printf("unable to get the size of the uio size file\n");
+		exit(-1);
+	}
+	fclose(size_fp);
+
+	return size;
+}
+
+int intc_init(void)
+{
+	char *uiod = "/dev/uio0";
+
+	//printf("Initializing INTC device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	intc_fd = open(uiod, O_RDWR);
+	if (intc_fd < 1) {
+		printf("intc_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio0/maps/map0/size");
+
+	// mmap the INTC device into user space
+	intc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, intc_fd, 0);
+	if (intc_ptr == MAP_FAILED) {
+		printf("intc_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int cfg_init(void)
+{
+	char *uiod = "/dev/uio1";
+
+	//printf("Initializing CFG device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	cfg_fd = open(uiod, O_RDWR);
+	if (cfg_fd < 1) {
+		printf("cfg_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size");
+
+	// mmap the cfgC device into user space
+	cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0);
+	if (cfg_ptr == MAP_FAILED) {
+		printf("cfg_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int sts_init(void)
+{
+	char *uiod = "/dev/uio4";
+
+	//printf("Initializing STS device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	sts_fd = open(uiod, O_RDWR);
+	if (sts_fd < 1) {
+		printf("sts_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio4/maps/map0/size");
+
+	// mmap the STS device into user space
+	sts_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, sts_fd, 0);
+	if (sts_ptr == MAP_FAILED) {
+		printf("sts_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int xadc_init(void)
+{
+	char *uiod = "/dev/uio5";
+
+	//printf("Initializing XADC device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	xadc_fd = open(uiod, O_RDWR);
+	if (xadc_fd < 1) {
+		printf("xadc_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio5/maps/map0/size"); 
+
+	// mmap the XADC device into user space
+	xadc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, xadc_fd, 0);
+	if (xadc_ptr == MAP_FAILED) {
+		printf("xadc_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int mem_init(void)
+{
+	char *mem_name = "/dev/mem";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	mem_fd = open(mem_name, O_RDWR);
+	if (mem_fd < 1) {
+		printf("mem_init: Invalid device file:%s.\n", mem_name);
+		return -1;
+	}
+
+	dev_size = 2048*sysconf(_SC_PAGESIZE);
+
+	// mmap the mem device into user space 
+	mem_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0x1E000000);
+	if (mem_ptr == MAP_FAILED) {
+		printf("mem_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int cma_init(void)
+{
+	char *cma_name = "/dev/cma";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	cma_fd = open(cma_name, O_RDWR);
+	if (cma_fd < 1) {
+		printf("cma_init: Invalid device file:%s.\n", cma_name);
+		return -1;
+	}
+
+	dev_size = 1024*sysconf(_SC_PAGESIZE);
+
+	if(ioctl(cma_fd, CMA_ALLOC, &dev_size) < 0) {
+		perror("ioctl");
+		return EXIT_FAILURE;
+	}
+	// mmap the mem device into user space 
+	cma_ptr = mmap(NULL, 1024*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, cma_fd, 0);
+	if (cma_ptr == MAP_FAILED) {
+		printf("cma_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+float get_voltage(uint32_t offset)
+{
+	int16_t value;
+	value = (int16_t) dev_read(xadc_ptr, offset);
+	//  printf("The Voltage is: %lf V\n", (value>>4)*XADC_CONV_VAL);
+	return ((value>>4)*XADC_CONV_VAL);
+}       
+
+/*void set_voltage(uint32_t offset, int32_t value)
+	{       
+//fit after calibration. See file data_calib.txt in /ramp_test directory 
+// y = a*x + b
+//a               = 0.0382061     
+//b               = 4.11435   
+uint32_t dac_val;
+float a = 0.0382061, b = 4.11435; 
+
+dac_val = (uint32_t)(value - b)/a;
+
+dev_write(cfg_ptr, offset, dac_val);
+printf("The Voltage is: %d mV\n", value);
+printf("The DAC value is: %d DACs\n", dac_val);
+}
+*/
+
+void set_voltage(uint32_t offset, int32_t value)
+{       
+	//fit after calibration. See file data_calib2.txt in /ramp_test directory 
+	// y = a*x + b
+	//a               = 0.0882006     
+	//b               = 7.73516   
+	uint32_t dac_val;
+	float a = 0.0882006, b = 7.73516; 
+
+	dac_val = (uint32_t)(value - b)/a;
+
+	dev_write(cfg_ptr, offset, dac_val);
+	printf("The Voltage is: %d mV\n", value);
+	printf("The DAC value is: %d DACs\n", dac_val);
+}
+
+float get_temp_AD592(uint32_t offset)
+{
+	float value;
+	value = get_voltage(offset);
+	return ((value*1000)-273.15);
+}       
+
+//System initialization
+int init_system(void)
+{
+	uint32_t reg_val;
+
+	//FIXME: replace hardcoded values for defines
+	// set trigger_lvl_1
+	dev_write(cfg_ptr,CFG_TRLVL_1_OFFSET,8190);
+
+	// set trigger_lvl_2
+	dev_write(cfg_ptr,CFG_TRLVL_2_OFFSET,8190);
+
+	// set subtrigger_lvl_1
+	dev_write(cfg_ptr,CFG_STRLVL_1_OFFSET,8190);
+
+	// set subtrigger_lvl_2
+	dev_write(cfg_ptr,CFG_STRLVL_2_OFFSET,8190);
+
+	// set hv1 and hv2 to zero
+	dev_write(cfg_ptr,CFG_HV1_OFFSET,0);
+	dev_write(cfg_ptr,CFG_HV2_OFFSET,0);
+
+	// reset ramp generators
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~8);
+
+	// reset pps_gen, fifo and trigger modules
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~1);
+
+	/* reset data converter and writer */
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~4);
+
+	// enter reset mode for tlast_gen
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~2);
+
+	// set number of samples
+	dev_write(cfg_ptr,CFG_NSAMPLES_OFFSET, 1024 * 1024);
+
+	// set default value for trigger scalers a and b
+	dev_write(cfg_ptr,CFG_TR_SCAL_A_OFFSET, 1);
+	dev_write(cfg_ptr,CFG_TR_SCAL_B_OFFSET, 1);
+
+	// enter normal mode for tlast_gen
+	/*        reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 2);
+	//printf("written reg_val tlast : 0x%08x\n",reg_val | 2);
+	// enter normal mode for pps_gen, fifo and trigger modules
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 1);
+	//printf("written reg_val pps_gen, fifo : 0x%08x\n",reg_val | 1);
+	*/
+	// enable false GPS
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | FGPS_EN_MASK);
+	//printf("written reg_val : 0x%08x\n",reg_val | 16);
+	// disable
+	//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~16);
+	//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~FGPS_EN_MASK);
+	//printf("written reg_val : 0x%08x\n",reg_val & ~16);
+
+	/*        // enter normal mode for data converter and writer
+						reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+						dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 4);
+	//printf("written reg_val : 0x%08hx\n",reg_val | 4);
+	*/
+	// enter normal mode for ramp generators
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 8);
+	// enter in MASTER mode (default)
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 0x20);
+
+	return 0;
+}
+
+int enable_interrupt(void)
+{
+	// steps to accept interrupts -> as pg. 26 of pg099-axi-intc.pdf
+	//1) Each bit in the IER corresponding to an interrupt must be set to 1.
+	dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 1);
+	//2) There are two bits in the MER. The ME bit must be set to enable the
+	//interrupt request outputs.
+	dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK | XIL_AXI_INTC_MER_HIE_MASK);
+	//dev_write(dev_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK);
+
+	//The next block of code is to test interrupts by software
+	//3) Software testing can now proceed by writing a 1 to any bit position
+	//in the ISR that corresponds to an existing interrupt input.
+	/*        dev_write(intc_ptr,XIL_AXI_INTC_IPR_OFFSET, 1);
+
+						for(a=0; a<10; a++)
+						{
+						wait_for_interrupt(fd, dev_ptr);
+						dev_write(dev_ptr,XIL_AXI_INTC_ISR_OFFSET, 1); //regenerate interrupt
+						}
+						*/
+	return 0;
+
+}
+
+int disable_interrupt(void)
+{
+	uint32_t value;
+	//Disable interrupt INTC0
+	dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 0);
+	//disable IRQ
+	value = dev_read(intc_ptr, XIL_AXI_INTC_MER_OFFSET);
+	dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, value | ~1);
+	//Acknowledge any previous interrupt
+	dev_write(intc_ptr, XIL_AXI_INTC_IAR_OFFSET, 1);
+
+	return 0;
+}
+
diff --git a/projects/adc_recorder_uio/uio_src/zynq_io.h b/projects/adc_recorder_uio/uio_src/zynq_io.h
new file mode 100644
index 0000000000000000000000000000000000000000..42620d529cf6ca26b85f11b980729e66ee57b179
--- /dev/null
+++ b/projects/adc_recorder_uio/uio_src/zynq_io.h
@@ -0,0 +1,155 @@
+#ifndef _ZYNQ_IO_H_
+#define _ZYNQ_IO_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#define CMA_ALLOC _IOWR('Z', 0, uint32_t)
+#define INTC_BASEADDR 0x40000000
+#define INTC_HIGHADDR 0x40000FFF
+
+#define CFG_BASEADDR  0x40001000
+#define CFG_HIGHADDR  0x40001FFF
+
+#define STS_BASEADDR  0x40002000
+#define STS_HIGHADDR  0x40002FFF
+
+#define XADC_BASEADDR 0x40003000
+#define XADC_HIGHADDR 0x40003FFF
+
+#define XIL_AXI_INTC_ISR_OFFSET    0x0
+#define XIL_AXI_INTC_IPR_OFFSET    0x4
+#define XIL_AXI_INTC_IER_OFFSET    0x8
+#define XIL_AXI_INTC_IAR_OFFSET    0xC
+#define XIL_AXI_INTC_SIE_OFFSET    0x10
+#define XIL_AXI_INTC_CIE_OFFSET    0x14
+#define XIL_AXI_INTC_IVR_OFFSET    0x18
+#define XIL_AXI_INTC_MER_OFFSET    0x1C
+#define XIL_AXI_INTC_IMR_OFFSET    0x20
+#define XIL_AXI_INTC_ILR_OFFSET    0x24
+#define XIL_AXI_INTC_IVAR_OFFSET   0x100
+
+#define XIL_AXI_INTC_MER_ME_MASK 0x00000001
+#define XIL_AXI_INTC_MER_HIE_MASK 0x00000002
+
+//CFG
+#define CFG_RESET_GRAL_OFFSET    0x0
+#define CFG_WR_ADDR_OFFSET       0x4
+#define CFG_NSAMPLES_OFFSET      0x8
+#define CFG_TRLVL_1_OFFSET       0x8
+#define CFG_TRLVL_2_OFFSET       0xC
+#define CFG_STRLVL_1_OFFSET      0x10
+#define CFG_STRLVL_2_OFFSET      0x14
+#define CFG_TEMPERATURE_OFFSET   0x18
+#define CFG_PRESSURE_OFFSET      0x1C
+#define CFG_TIME_OFFSET          0x20
+#define CFG_DATE_OFFSET          0x24
+#define CFG_LATITUDE_OFFSET      0x28
+#define CFG_LONGITUDE_OFFSET     0x2C
+#define CFG_ALTITUDE_OFFSET      0x30
+#define CFG_SATELLITE_OFFSET     0x34
+#define CFG_TR_SCAL_A_OFFSET     0x38
+#define CFG_TR_SCAL_B_OFFSET     0x3C
+#define CFG_HV1_OFFSET           0x4C //DAC_PWM3
+#define CFG_HV2_OFFSET           0x48 //DAC_PWM2
+#define CFG_HV3_OFFSET           0x40 //DAC_PWM0
+#define CFG_HV4_OFFSET           0x44 //DAC_PWM1
+
+//CFG Slow DAC
+#define CFG_DAC_PWM0_OFFSET 0x40
+#define CFG_DAC_PWM1_OFFSET 0x44
+#define CFG_DAC_PWM2_OFFSET 0x48
+#define CFG_DAC_PWM3_OFFSET 0x4C
+
+#define ENBL_ALL_MASK         0xFFFFFFFF
+#define RST_ALL_MASK          0x00000000
+#define RST_PPS_TRG_FIFO_MASK 0x00000001
+#define RST_TLAST_GEN_MASK    0x00000002
+#define RST_WRITER_MASK       0x00000004
+#define RST_AO_MASK           0x00000008
+#define FGPS_EN_MASK          0x00000010
+
+//STS
+#define STS_STATUS_OFFSET     0x0
+
+//XADC
+//See page 17 of PG091
+#define XADC_SRR_OFFSET          0x00   //Software reset register
+#define XADC_SR_OFFSET           0x04   //Status Register
+#define XADC_AOSR_OFFSET         0x08   //Alarm Out Status Register
+#define XADC_CONVSTR_OFFSET      0x0C   //CONVST Register
+#define XADC_SYSMONRR_OFFSET     0x10   //XADC Reset Register
+#define XADC_GIER_OFFSET         0x5C   //Global Interrupt Enable Register
+#define XADC_IPISR_OFFSET        0x60   //IP Interrupt Status Register
+#define XADC_IPIER_OFFSET        0x68   //IP Interrupt Enable Register
+#define XADC_TEMPERATURE_OFFSET  0x200  //Temperature
+#define XADC_VCCINT_OFFSET       0x204  //VCCINT
+#define XADC_VCCAUX_OFFSET       0x208  //VCCAUX
+#define XADC_VPVN_OFFSET         0x20C  //VP/VN
+#define XADC_VREFP_OFFSET        0x210  //VREFP
+#define XADC_VREFN_OFFSET        0x214  //VREFN
+#define XADC_VBRAM_OFFSET        0x218  //VBRAM
+#define XADC_UNDEF_OFFSET        0x21C  //Undefined
+#define XADC_SPLYOFF_OFFSET      0x220  //Supply Offset
+#define XADC_ADCOFF_OFFSET       0x224  //ADC Offset
+#define XADC_GAIN_ERR_OFFSET     0x228  //Gain Error
+#define XADC_ZDC_SPLY_OFFSET     0x234  //Zynq-7000 Device Core Supply
+#define XADC_ZDC_AUX_SPLY_OFFSET 0x238  //Zynq-7000 Device Core Aux Supply
+#define XADC_ZDC_MEM_SPLY_OFFSET 0x23C  //Zynq-7000 Device Core Memory Supply
+#define XADC_VAUX_PN_0_OFFSET    0x240  //VAUXP[0]/VAUXN[0]
+#define XADC_VAUX_PN_1_OFFSET    0x244  //VAUXP[1]/VAUXN[1]
+#define XADC_VAUX_PN_2_OFFSET    0x248  //VAUXP[2]/VAUXN[2]
+#define XADC_VAUX_PN_3_OFFSET    0x24C  //VAUXP[3]/VAUXN[3]
+#define XADC_VAUX_PN_4_OFFSET    0x250  //VAUXP[4]/VAUXN[4]
+#define XADC_VAUX_PN_5_OFFSET    0x254  //VAUXP[5]/VAUXN[5]
+#define XADC_VAUX_PN_6_OFFSET    0x258  //VAUXP[6]/VAUXN[6]
+#define XADC_VAUX_PN_7_OFFSET    0x25C  //VAUXP[7]/VAUXN[7]
+#define XADC_VAUX_PN_8_OFFSET    0x260  //VAUXP[8]/VAUXN[8]
+#define XADC_VAUX_PN_9_OFFSET    0x264  //VAUXP[9]/VAUXN[9]
+#define XADC_VAUX_PN_10_OFFSET   0x268  //VAUXP[10]/VAUXN[10]
+#define XADC_VAUX_PN_11_OFFSET   0x26C  //VAUXP[11]/VAUXN[11]
+#define XADC_VAUX_PN_12_OFFSET   0x270  //VAUXP[12]/VAUXN[12]
+#define XADC_VAUX_PN_13_OFFSET   0x274  //VAUXP[13]/VAUXN[13]
+#define XADC_VAUX_PN_14_OFFSET   0x278  //VAUXP[14]/VAUXN[14]
+#define XADC_VAUX_PN_15_OFFSET   0x27C  //VAUXP[15]/VAUXN[15]
+
+#define XADC_AI0_OFFSET XADC_VAUX_PN_8_OFFSET
+#define XADC_AI1_OFFSET XADC_VAUX_PN_0_OFFSET
+#define XADC_AI2_OFFSET XADC_VAUX_PN_1_OFFSET
+#define XADC_AI3_OFFSET XADC_VAUX_PN_9_OFFSET
+
+#define XADC_CONV_VAL 0.00171191993362 //(A_ip/2^12)*(34.99/4.99)
+#define XADC_RDIV_VAL 1.883236177     //voltage divisor in board (15k+16.983k)/16.983k = 1.88
+#define XADC_BASE_HVDIV 0.00294088    //voltage divisor in HV base board (100k/31.3Meg) = 3.194888179. The value I put here is the measured one.
+
+extern int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, hst0_fd, hst1_fd, cma_fd;
+extern void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *hst0_ptr, *hst1_ptr;
+extern volatile int16_t *cma_ptr;
+extern uint32_t dev_size;
+
+void     dev_write(void *dev_base, uint32_t offset, int32_t value);
+uint32_t dev_read(void *dev_base, uint32_t offset);
+//int    dev_init(int n_dev);
+int32_t  rd_reg_value(int n_dev, uint32_t reg_off, uint8_t degug);
+int32_t  wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val, uint8_t debug);
+int32_t  rd_cfg_status(void);
+int      intc_init(void);
+int      cfg_init(void);
+int      sts_init(void);
+int      xadc_init(void);
+int      mem_init(void);
+int      cma_init(void);
+float    get_voltage(uint32_t offset);
+void     set_voltage(uint32_t offset, int32_t value);
+float    get_temp_AD592(uint32_t offset);
+int      init_system(void);
+int      enable_interrupt(void);
+int      disable_interrupt(void);
+
+#endif
+
diff --git a/projects/adc_test/block_design.tcl b/projects/adc_test/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..4eddd181bfaf945343eb87e9a085ecd038d3fc44
--- /dev/null
+++ b/projects/adc_test/block_design.tcl
@@ -0,0 +1,299 @@
+# Create clk_wiz
+cell xilinx.com:ip:clk_wiz pll_0 {
+  PRIMITIVE PLL
+  PRIM_IN_FREQ.VALUE_SRC USER
+  PRIM_IN_FREQ 125.0
+  PRIM_SOURCE Differential_clock_capable_pin
+  CLKOUT1_USED true
+  CLKOUT1_REQUESTED_OUT_FREQ 125.0
+  CLKOUT2_USED true
+  CLKOUT2_REQUESTED_OUT_FREQ 250.0
+  CLKOUT2_REQUESTED_PHASE 157.5
+  CLKOUT3_USED true
+  CLKOUT3_REQUESTED_OUT_FREQ 250.0
+  CLKOUT3_REQUESTED_PHASE 202.5
+  USE_RESET false
+} {
+  clk_in1_p adc_clk_p_i
+  clk_in1_n adc_clk_n_i
+}
+
+# Create processing_system7
+cell xilinx.com:ip:processing_system7 ps_0 {
+  PCW_IMPORT_BOARD_PRESET cfg/red_pitaya.xml
+  PCW_USE_S_AXI_ACP 1
+  PCW_USE_DEFAULT_ACP_USER_VAL 1
+} {
+  M_AXI_GP0_ACLK pll_0/clk_out1
+  S_AXI_ACP_ACLK pll_0/clk_out1
+}
+
+# Create all required interconnections
+apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config {
+  make_external {FIXED_IO, DDR}
+  Master Disable
+  Slave Disable
+} [get_bd_cells ps_0]
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+# ADC
+
+# Create axis_rp_adc
+cell labdpr:user:axis_rp_adc adc_0 {
+  ADC_DATA_WIDTH 14
+} {
+  aclk pll_0/clk_out1
+  adc_dat_a adc_dat_a_i
+  adc_dat_b adc_dat_b_i
+  adc_csn adc_csn_o
+}
+
+# DAC
+
+# Create axis_rp_dac
+cell labdpr:user:axis_rp_dac dac_0 {
+  DAC_DATA_WIDTH 14
+} {
+  aclk pll_0/clk_out1
+  ddr_clk pll_0/clk_out2
+  wrt_clk pll_0/clk_out3
+  locked pll_0/locked
+  dac_clk dac_clk_o
+  dac_rst dac_rst_o
+  dac_sel dac_sel_o
+  dac_wrt dac_wrt_o
+  dac_dat dac_dat_o
+  s_axis_tvalid const_0/dout
+}
+
+# CFG
+
+# Create axi_cfg_register
+cell labdpr:user:axi_cfg_register cfg_0 {
+  CFG_DATA_WIDTH 160
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_0 {
+  DIN_WIDTH 160 DIN_FROM 0 DIN_TO 0
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_1 {
+  DIN_WIDTH 160 DIN_FROM 1 DIN_TO 1
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_2 {
+  DIN_WIDTH 160 DIN_FROM 31 DIN_TO 16
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_3 {
+  DIN_WIDTH 160 DIN_FROM 63 DIN_TO 32
+} {
+  din cfg_0/cfg_data
+}
+
+# RX
+
+# Create axis_subset_converter
+cell xilinx.com:ip:axis_subset_converter subset_0 {
+  S_TDATA_NUM_BYTES.VALUE_SRC USER
+  M_TDATA_NUM_BYTES.VALUE_SRC USER
+  S_TDATA_NUM_BYTES 4
+  M_TDATA_NUM_BYTES 2
+  TDATA_REMAP {tdata[15:0]}
+} {
+  S_AXIS adc_0/M_AXIS
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+# Create axis_constant
+cell labdpr:user:axis_variable rate_0 {
+  AXIS_TDATA_WIDTH 16
+} {
+  cfg_data slice_2/dout
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+# Create cic_compiler
+cell xilinx.com:ip:cic_compiler cic_0 {
+  INPUT_DATA_WIDTH.VALUE_SRC USER
+  FILTER_TYPE Decimation
+  NUMBER_OF_STAGES 6
+  SAMPLE_RATE_CHANGES Programmable
+  MINIMUM_RATE 4
+  MAXIMUM_RATE 6250
+  FIXED_OR_INITIAL_RATE 4
+  INPUT_SAMPLE_FREQUENCY 125
+  CLOCK_FREQUENCY 125
+  INPUT_DATA_WIDTH 16
+  QUANTIZATION Truncation
+  OUTPUT_DATA_WIDTH 16
+  USE_XTREME_DSP_SLICE false
+  HAS_ARESETN true
+} {
+  S_AXIS_DATA subset_0/M_AXIS
+  S_AXIS_CONFIG rate_0/M_AXIS
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+# Create axis_dwidth_converter
+cell xilinx.com:ip:axis_dwidth_converter conv_0 {
+  S_TDATA_NUM_BYTES.VALUE_SRC USER
+  S_TDATA_NUM_BYTES 2
+  M_TDATA_NUM_BYTES 8
+} {
+  S_AXIS cic_0/M_AXIS_DATA
+  aclk pll_0/clk_out1
+  aresetn slice_0/dout
+}
+
+# DMA
+
+# Create axis_ram_writer
+cell labdpr:user:axis_ram_writer writer_0 {
+  ADDR_WIDTH 16
+  AXI_ID_WIDTH 3
+} {
+  S_AXIS conv_0/M_AXIS
+  M_AXI ps_0/S_AXI_ACP
+  cfg_data slice_3/dout
+  aclk pll_0/clk_out1
+  aresetn slice_1/dout
+}
+
+# GEN
+
+# Create axis_lfsr
+cell labdpr:user:axis_lfsr lfsr_0 {} {
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+for {set i 0} {$i <= 1} {incr i} {
+
+  # Create port_slicer
+  cell labdpr:user:port_slicer slice_[expr $i + 4] {
+    DIN_WIDTH 160 DIN_FROM [expr 32 * $i + 95] DIN_TO [expr 32 * $i + 64]
+  } {
+    din cfg_0/cfg_data
+  }
+
+  # Create port_slicer
+  cell labdpr:user:port_slicer slice_[expr $i + 6] {
+    DIN_WIDTH 160 DIN_FROM [expr 16 * $i + 143] DIN_TO [expr 16 * $i + 128]
+  } {
+    din cfg_0/cfg_data
+  }
+
+  # Create axis_constant
+  cell labdpr:user:axis_constant phase_$i {
+    AXIS_TDATA_WIDTH 32
+  } {
+    cfg_data slice_[expr $i + 4]/dout
+    aclk pll_0/clk_out1
+  }
+
+  # Create dds_compiler
+  cell xilinx.com:ip:dds_compiler dds_$i {
+    DDS_CLOCK_RATE 125
+    SPURIOUS_FREE_DYNAMIC_RANGE 138
+    FREQUENCY_RESOLUTION 0.2
+    PHASE_INCREMENT Streaming
+    HAS_PHASE_OUT false
+    PHASE_WIDTH 30
+    OUTPUT_WIDTH 24
+    DSP48_USE Minimal
+    NEGATIVE_SINE true
+  } {
+    S_AXIS_PHASE phase_$i/M_AXIS
+    aclk pll_0/clk_out1
+  }
+
+  # Create xbip_dsp48_macro
+  cell xilinx.com:ip:xbip_dsp48_macro mult_$i {
+    INSTRUCTION1 RNDSIMPLE(A*B+CARRYIN)
+    A_WIDTH.VALUE_SRC USER
+    B_WIDTH.VALUE_SRC USER
+    OUTPUT_PROPERTIES User_Defined
+    A_WIDTH 24
+    B_WIDTH 16
+    P_WIDTH 15
+  } {
+    A dds_$i/m_axis_data_tdata
+    B slice_[expr $i + 6]/dout
+    CARRYIN lfsr_0/m_axis_tdata
+    CLK pll_0/clk_out1
+  }
+
+}
+
+# Create xlconcat
+cell xilinx.com:ip:xlconcat concat_0 {
+  NUM_PORTS 2
+  IN0_WIDTH 16
+  IN1_WIDTH 16
+} {
+  In0 mult_0/P
+  In1 mult_1/P
+  dout dac_0/s_axis_tdata
+}
+
+# STS
+
+# Create dna_reader
+cell labdpr:user:dna_reader dna_0 {} {
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+# Create xlconcat
+cell xilinx.com:ip:xlconcat concat_1 {
+  NUM_PORTS 3
+  IN0_WIDTH 32
+  IN1_WIDTH 64
+  IN2_WIDTH 32
+} {
+  In0 const_0/dout
+  In1 dna_0/dna_data
+  In2 writer_0/sts_data
+}
+
+# Create axi_sts_register
+cell labdpr:user:axi_sts_register sts_0 {
+  STS_DATA_WIDTH 128
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+} {
+  sts_data concat_1/dout
+}
+
+addr 0x40000000 4K sts_0/S_AXI /ps_0/M_AXI_GP0
+
+addr 0x40001000 4K cfg_0/S_AXI /ps_0/M_AXI_GP0
+
+assign_bd_address [get_bd_addr_segs ps_0/S_AXI_ACP/ACP_DDR_LOWOCM]
+
+group_bd_cells PS7 [get_bd_cells rst_0] [get_bd_cells pll_0] [get_bd_cells const_0] [get_bd_cells ps_0] [get_bd_cells ps_0_axi_periph]
+group_bd_cells ACQ [get_bd_cells rate_0] [get_bd_cells adc_0] [get_bd_cells subset_0] [get_bd_cells slice_0] [get_bd_cells slice_1] [get_bd_cells conv_0] [get_bd_cells slice_2] [get_bd_cells cic_0] [get_bd_cells writer_0] [get_bd_cells slice_3]
+group_bd_cells CMPLX_GEN [get_bd_cells phase_1] [get_bd_cells mult_0] [get_bd_cells dds_0] [get_bd_cells dds_1] [get_bd_cells mult_1] [get_bd_cells dac_0] [get_bd_cells slice_4] [get_bd_cells slice_5] [get_bd_cells concat_0] [get_bd_cells slice_6] [get_bd_cells phase_0] [get_bd_cells lfsr_0]
diff --git a/projects/adc_test/client/Makefile b/projects/adc_test/client/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..7743a466c1922d7de70cb66b48d07009ae6389f7
--- /dev/null
+++ b/projects/adc_test/client/Makefile
@@ -0,0 +1,11 @@
+CC=gcc
+CFLAGS =-Wall -O3 
+
+all: adc-test-client_lnx
+
+sdr-transceiver: adc-test-client_lnx.c
+	$(CC) $(CFLAGS) -o $@ $^ -lm -lpthread
+
+clean:
+	rm -f adc-test-client_lnx
+
diff --git a/projects/adc_test/client/adc-test-client_lnx b/projects/adc_test/client/adc-test-client_lnx
new file mode 100755
index 0000000000000000000000000000000000000000..9e083c1bc5e2f7f114602e5b2b331d7c353386d3
Binary files /dev/null and b/projects/adc_test/client/adc-test-client_lnx differ
diff --git a/projects/adc_test/client/adc-test-client_lnx.c b/projects/adc_test/client/adc-test-client_lnx.c
new file mode 100644
index 0000000000000000000000000000000000000000..23d0ff61b4028940c02c789583ee2bb3d75d117c
--- /dev/null
+++ b/projects/adc_test/client/adc-test-client_lnx.c
@@ -0,0 +1,102 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h> 
+
+void error(const char *msg)
+{
+	perror(msg);
+	exit(0);
+}
+
+int main(int argc, char *argv[])
+{
+	int sockfd, portno, n, i;
+	struct sockaddr_in serv_addr;
+	struct hostent *server;
+	int bytesReceived=0;
+
+	//char buffer[256];
+	int32_t buffer[256*4096];
+	//int32_t bufferIn[256];
+	float bufferOut[256*4096];
+
+	if (argc < 3) {
+		fprintf(stderr,"usage %s hostname port\n", argv[0]);
+		exit(0);
+	}
+	portno = atoi(argv[2]);
+	sockfd = socket(AF_INET, SOCK_STREAM, 0);
+	if (sockfd < 0) 
+		error("ERROR opening socket");
+	server = gethostbyname(argv[1]);
+	if (server == NULL) {
+		fprintf(stderr,"ERROR, no such host\n");
+		exit(0);
+	}
+	bzero((char *) &serv_addr, sizeof(serv_addr));
+	serv_addr.sin_family = AF_INET;
+	bcopy((char *)server->h_addr, 
+			(char *)&serv_addr.sin_addr.s_addr,
+			server->h_length);
+	serv_addr.sin_port = htons(portno);
+	if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
+	{
+		perror("connect");
+		return 1;
+	}
+
+//	while(1)
+//  {
+//    bytesReceived=recv(sockfd, buffer, 256*4096, MSG_WAITALL);
+//    for(i = 0; i < bytesReceived; ++i)
+//    {
+//      bufferOut[i] = ((float)buffer[i]) / 2147483647.0;
+//    }
+//    //printf("%f\n",*bufferOut);
+//    //printf(bufferOut);
+//
+//    fwrite(bufferOut, 1, 256*4096, stdout);
+//    fflush(stdout);
+//  }
+
+	do
+    {
+        bytesReceived = recv(
+                sockfd,
+                buffer,
+                256*4096,
+                MSG_WAITALL);
+
+        for (i = 0; i < bytesReceived; ++i)
+            printf("%f\n", (float)buffer[i]/2147483647.0);
+    }
+    while(bytesReceived);
+
+	//while(1)
+	//{
+		//recv(sockfd, buffer, 256*4096, MSG_WAITALL);
+	//	n=read(sockfd,buffer,256*4096);
+	//	printf("%s\n",buffer);
+	//}
+
+	//    if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) 
+	//        error("ERROR connecting");
+	//    printf("Please enter the message: ");
+	//    bzero(buffer,256);
+	//    fgets(buffer,255,stdin);
+	//    n = write(sockfd,buffer,strlen(buffer));
+	//    if (n < 0) 
+	//         error("ERROR writing to socket");
+	//    bzero(buffer,256);
+	//    n = read(sockfd,buffer,255);
+	//    if (n < 0) 
+	//         error("ERROR reading from socket");
+	//    printf("%s\n",buffer);
+	close(sockfd);
+	return 0;
+}
diff --git a/projects/adc_test/client/adc-test-client_win.c b/projects/adc_test/client/adc-test-client_win.c
new file mode 100644
index 0000000000000000000000000000000000000000..521989794b0bc5279cb1d0d3145a29d96ddb7014
--- /dev/null
+++ b/projects/adc_test/client/adc-test-client_win.c
@@ -0,0 +1,44 @@
+/*
+command to compile:
+gcc adc-test-client.c -o adc-test-client -lws2_32
+*/
+
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <windows.h>
+
+#define TCP_ADDR "192.168.137.111"
+#define TCP_PORT 1001
+
+int main(int argc, char**argv)
+{
+  SOCKET sock;
+  struct sockaddr_in addr;
+  char buffer[256*4096];
+
+  WSADATA wsaData;
+  WSAStartup(MAKEWORD(2, 2), &wsaData);
+
+  if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+  {
+    perror("socket");
+    return 1;
+  }
+
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = inet_addr(TCP_ADDR);
+  addr.sin_port = htons(TCP_PORT);
+
+  if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+  {
+    perror("connect");
+    return 1;
+  }
+
+  while(1)
+  {
+    recv(sock, buffer, 256*4096, MSG_WAITALL);
+  }
+}
+
diff --git a/projects/adc_test/server/adc-test-server.c b/projects/adc_test/server/adc-test-server.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee727d97c0033106e1a59eb07b2f64b3e7b87702
--- /dev/null
+++ b/projects/adc_test/server/adc-test-server.c
@@ -0,0 +1,164 @@
+/*
+command to compile:
+gcc -O3 -D_GNU_SOURCE adc-test-server.c -o adc-test-server
+*/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <sched.h>
+#include <fcntl.h>
+#include <math.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#define TCP_PORT 1001
+
+#define CMA_ALLOC _IOWR('Z', 0, uint32_t)
+
+int interrupted = 0;
+
+void signal_handler(int sig)
+{
+  interrupted = 1;
+}
+
+int main ()
+{
+  int fd, sock_server, sock_client;
+  int position, limit, offset;
+  volatile uint32_t *rx_addr, *rx_cntr;
+  volatile uint16_t *rx_rate;
+  volatile uint8_t *rx_rst;
+  volatile void *cfg, *sts, *ram;
+  cpu_set_t mask;
+  struct sched_param param;
+  struct sockaddr_in addr;
+  uint32_t size;
+  int yes = 1;
+
+  memset(&param, 0, sizeof(param));
+  param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+  sched_setscheduler(0, SCHED_FIFO, &param);
+
+  CPU_ZERO(&mask);
+  CPU_SET(1, &mask);
+  sched_setaffinity(0, sizeof(cpu_set_t), &mask);
+
+  if((fd = open("/dev/mem", O_RDWR)) < 0)
+  {
+    perror("open");
+    return EXIT_FAILURE;
+  }
+
+  sts = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x40000000);
+  cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x40001000);
+
+  close(fd);
+
+  if((fd = open("/dev/cma", O_RDWR)) < 0)
+  {
+    perror("open");
+    return EXIT_FAILURE;
+  }
+
+  size = 128*sysconf(_SC_PAGESIZE);
+
+  if(ioctl(fd, CMA_ALLOC, &size) < 0)
+  {
+    perror("ioctl");
+    return EXIT_FAILURE;
+  }
+
+  ram = mmap(NULL, 128*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+
+  rx_rst = (uint8_t *)(cfg + 0);
+  rx_rate = (uint16_t *)(cfg + 2);
+  rx_addr = (uint32_t *)(cfg + 4);
+
+  rx_cntr = (uint32_t *)(sts + 12);
+
+  *rx_addr = size;
+
+  if((sock_server = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+  {
+    perror("socket");
+    return EXIT_FAILURE;
+  }
+
+  setsockopt(sock_server, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));
+
+  /* setup listening address */
+  memset(&addr, 0, sizeof(addr));
+  addr.sin_family = AF_INET;
+  addr.sin_addr.s_addr = htonl(INADDR_ANY);
+  addr.sin_port = htons(TCP_PORT);
+
+  if(bind(sock_server, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+  {
+    perror("bind");
+    return EXIT_FAILURE;
+  }
+
+  listen(sock_server, 1024);
+
+  while(!interrupted)
+  {
+    /* enter reset mode */
+    *rx_rst &= ~1;
+    usleep(100);
+    *rx_rst &= ~2;
+    /* set default sample rate */
+    *rx_rate = 4;
+
+    if((sock_client = accept(sock_server, NULL, NULL)) < 0)
+    {
+      perror("accept");
+      return EXIT_FAILURE;
+    }
+
+    signal(SIGINT, signal_handler);
+
+    /* enter normal operating mode */
+    *rx_rst |= 3;
+
+    limit = 32*1024;
+
+    while(!interrupted)
+    {
+      /* read ram writer position */
+      position = *rx_cntr;
+
+      /* send 256 kB if ready, otherwise sleep 0.1 ms */
+      if((limit > 0 && position > limit) || (limit == 0 && position < 32*1024))
+      {
+        offset = limit > 0 ? 0 : 256*1024;
+        limit = limit > 0 ? 0 : 32*1024;
+        if(send(sock_client, ram + offset, 256*1024, MSG_NOSIGNAL) < 0) break;
+      }
+      else
+      {
+        usleep(100);
+      }
+    }
+
+    signal(SIGINT, SIG_DFL);
+    close(sock_client);
+  }
+
+  /* enter reset mode */
+  *rx_rst &= ~1;
+  usleep(100);
+  *rx_rst &= ~2;
+
+  close(sock_server);
+
+  return EXIT_SUCCESS;
+}
diff --git a/projects/adc_test/server/gen.c b/projects/adc_test/server/gen.c
new file mode 100644
index 0000000000000000000000000000000000000000..b362ae40c45671a04f0681f859d907037becfbf3
--- /dev/null
+++ b/projects/adc_test/server/gen.c
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <sys/mman.h>
+
+int main(int argc, char *argv[])
+{
+  int fd, i;
+  char *end;
+  volatile void *cfg;
+  long number[3];
+
+  for(i = 0; i < 3; ++i)
+  {
+    errno = 0;
+    number[i] = (argc == 4) ? strtol(argv[i + 1], &end, 10) : -1;
+    if(errno != 0 || end == argv[i + 1])
+    {
+      printf("Usage: gen [1-2] [0-32766] [0-61440000]\n");
+      return EXIT_FAILURE;
+    }
+  }
+
+  if(number[0] < 1 || number[0] > 2 || number[1] < 0 || number[1] > 32766 || number[2] < 0 || number[2] > 61440000)
+  {
+    printf("Usage: gen [1-2] [0-32766] [0-61440000]\n");
+    return EXIT_FAILURE;
+  }
+
+  if((fd = open("/dev/mem", O_RDWR)) < 0)
+  {
+    fprintf(stderr, "Cannot open /dev/mem.\n");
+    return EXIT_FAILURE;
+  }
+
+  cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x40001000);
+
+  switch(number[0])
+  {
+    case 1:
+      *(uint32_t *)(cfg + 8) = (uint32_t)floor(number[2] / 125.0e6 * (1<<30) + 0.5);
+      *(uint16_t *)(cfg + 16) = (uint16_t)number[1];
+      break;
+    case 2:
+      *(uint32_t *)(cfg + 12) = (uint32_t)floor(number[2] / 125.0e6 * (1<<30) + 0.5);
+      *(uint16_t *)(cfg + 18) = (uint16_t)number[1];
+      break;
+  }
+
+  return EXIT_SUCCESS;
+}
diff --git a/projects/base_system/block_design.tcl b/projects/base_system/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..80ab85eaa9c8662cb1c21208b16e9936985567f9
--- /dev/null
+++ b/projects/base_system/block_design.tcl
@@ -0,0 +1,30 @@
+# Create clk_wiz
+cell xilinx.com:ip:clk_wiz pll_0 {
+  PRIMITIVE PLL
+  PRIM_IN_FREQ.VALUE_SRC USER
+  PRIM_IN_FREQ 125.0
+  PRIM_SOURCE Differential_clock_capable_pin
+  CLKOUT1_USED true
+  CLKOUT1_REQUESTED_OUT_FREQ 125.0
+  USE_RESET false
+} {
+  clk_in1_p adc_clk_p_i
+  clk_in1_n adc_clk_n_i
+}
+
+# Create processing_system7
+cell xilinx.com:ip:processing_system7 ps_0 {
+  PCW_IMPORT_BOARD_PRESET cfg/red_pitaya.xml
+  PCW_USE_S_AXI_ACP 1
+  PCW_USE_DEFAULT_ACP_USER_VAL 1
+} {
+  M_AXI_GP0_ACLK pll_0/clk_out1
+  S_AXI_ACP_ACLK pll_0/clk_out1
+}
+
+# Create all required interconnections
+apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config {
+  make_external {FIXED_IO, DDR}
+  Master Disable
+  Slave Disable
+} [get_bd_cells ps_0]
diff --git a/projects/cfg_test/block_design.tcl b/projects/cfg_test/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..51fa542cdcd254c4f1437d40cdaa8b958eb54506
--- /dev/null
+++ b/projects/cfg_test/block_design.tcl
@@ -0,0 +1,48 @@
+source projects/base_system/block_design.tcl
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+# Create c_counter_binary
+cell xilinx.com:ip:c_counter_binary cntr_0 {
+  Output_Width 32
+} {
+  CLK pll_0/clk_out1
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_0 {
+  DIN_FROM 26 DIN_TO 26
+} {
+  din cntr_0/Q
+}
+
+# Create axi_cfg_register
+cell labdpr:user:axi_cfg_register cfg_0 {
+  CFG_DATA_WIDTH 1024
+  AXI_ADDR_WIDTH 7
+  AXI_DATA_WIDTH 32
+}
+
+addr 0x40001000 4K cfg_0/S_AXI /ps_0/M_AXI_GP0
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_1 {
+  DIN_WIDTH 1024 DIN_FROM 134 DIN_TO 128
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlconcat
+cell xilinx.com:ip:xlconcat concat_0 {
+  IN1_WIDTH 7
+} {
+  In0 slice_0/dout
+  In1 slice_1/dout
+  dout led_o
+}
diff --git a/projects/counter_test/block_design.tcl b/projects/counter_test/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..59e81896f9a28cc050691a17185d9567ef772e5a
--- /dev/null
+++ b/projects/counter_test/block_design.tcl
@@ -0,0 +1,162 @@
+source projects/base_system/block_design.tcl
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+
+# ADC
+
+# Create axis_red_pitaya_adc
+cell labdpr:user:axis_rp_adc adc_0 {
+  ADC_DATA_WIDTH 14
+} {
+  aclk pll_0/clk_out1
+  adc_dat_a adc_dat_a_i
+  adc_dat_b adc_dat_b_i
+  adc_csn adc_csn_o
+}
+
+# Create axi_cfg_register
+cell labdpr:user:axi_cfg_register cfg_0 {
+  CFG_DATA_WIDTH 128
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_0 {
+  DIN_WIDTH 128 DIN_FROM 0 DIN_TO 0
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_1 {
+  DIN_WIDTH 128 DIN_FROM 1 DIN_TO 1
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_2 {
+  DIN_WIDTH 128 DIN_FROM 2 DIN_TO 2
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_3 {
+  DIN_WIDTH 128 DIN_FROM 63 DIN_TO 32
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_4 {
+  DIN_WIDTH 128 DIN_FROM 95 DIN_TO 64
+} {
+  din cfg_0/cfg_data
+}
+
+# Create axis_clock_converter
+cell xilinx.com:ip:axis_clock_converter fifo_0 {} {
+  S_AXIS adc_0/M_AXIS
+  s_axis_aclk pll_0/clk_out1
+  s_axis_aresetn const_0/dout
+  m_axis_aclk ps_0/FCLK_CLK0
+  m_axis_aresetn slice_0/Dout
+}
+
+# Create counter
+cell labdpr:user:axis_counter axis_counter_0 {
+  AXIS_TDATA_WIDTH 16
+  CNTR_WIDTH 16
+} {
+  aclk pll_0/clk_out1
+  aresetn slice_0/dout
+}
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_2 {
+ CONST_VAL 65535
+ CONST_WIDTH 16
+} {
+ dout axis_counter_0/cfg_data
+}
+
+# Create counter
+cell labdpr:user:axis_counter axis_counter_1 {
+  AXIS_TDATA_WIDTH 16
+  CNTR_WIDTH 16
+} {
+  aclk pll_0/clk_out1
+  aresetn slice_0/dout
+}
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_3 {
+ CONST_VAL 65535
+ CONST_WIDTH 16
+} {
+ dout axis_counter_1/cfg_data
+}
+
+#Create combiner
+cell xilinx.com:ip:axis_combiner comb_0 {} {
+  aclk pll_0/clk_out1
+ aresetn slice_1/Dout
+ S00_AXIS axis_counter_0/M_AXIS
+ S01_AXIS axis_counter_1/M_AXIS
+}
+
+# Create the tlast generator
+cell labdpr:user:axis_tlast_gen tlast_gen_0 {
+  AXIS_TDATA_WIDTH 32
+  PKT_CNTR_BITS 32
+} {
+  aclk pll_0/clk_out1
+  aresetn slice_1/dout
+  pkt_length slice_4/dout
+  S_AXIS comb_0/M_AXIS
+}
+
+# Create axis_dwidth_converter
+cell xilinx.com:ip:axis_dwidth_converter conv_0 {
+  S_TDATA_NUM_BYTES.VALUE_SRC USER
+  S_TDATA_NUM_BYTES 4
+  M_TDATA_NUM_BYTES 8
+} {
+  aclk pll_0/clk_out1
+  aresetn slice_2/dout
+  S_AXIS tlast_gen_0/M_AXIS
+}
+
+# Create axis_ram_writer
+cell labdpr:user:axis_ram_writer writer_0 {
+  ADDR_WIDTH 16
+  AXI_ID_WIDTH 3
+} {
+  aclk pll_0/clk_out1
+  aresetn slice_2/dout
+  S_AXIS conv_0/M_AXIS
+  M_AXI ps_0/S_AXI_ACP
+  cfg_data slice_3/dout
+}
+
+# Create axi_sts_register
+cell labdpr:user:axi_sts_register sts_0 {
+  STS_DATA_WIDTH 32
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+} {
+  sts_data writer_0/sts_data
+}
+
+addr 0x40001000 4K cfg_0/S_AXI /ps_0/M_AXI_GP0
+addr 0x40002000 4K sts_0/S_AXI /ps_0/M_AXI_GP0
+
diff --git a/projects/counter_test/uio_src/Makefile b/projects/counter_test/uio_src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..ed776e24b065938e7d0f6e14224b15254568b959
--- /dev/null
+++ b/projects/counter_test/uio_src/Makefile
@@ -0,0 +1,16 @@
+CC=gcc
+FLAGS=-Wall -O3
+ARCH=arm
+CROSS_COMPILE=arm-xilinx-linux-gnueabi-
+
+####
+PROG=counter_test
+EXTRA= zynq_io.c
+
+all: $(PROG)
+
+$(PROG): $(PROG).c $(EXTRA) 
+	$(CC) $(FLAGS) -o $(PROG) $(PROG).c $(EXTRA) -lm -lpthread
+
+clean:
+	rm -f $(PROG)
diff --git a/projects/counter_test/uio_src/counter_test.c b/projects/counter_test/uio_src/counter_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..1bd5bcfd7ad00ab81c3585eac345fc416ab4c7df
--- /dev/null
+++ b/projects/counter_test/uio_src/counter_test.c
@@ -0,0 +1,98 @@
+#include "zynq_io.h"
+
+int main(int argc, char *argv[])
+{
+	//int fd;
+	//unsigned int size;
+	uint32_t i,val=0;
+	uint32_t wo,wo2;
+	int16_t ch[4];
+
+	printf("ADC RECORDER test\n");
+
+	//initialize devices. TODO: add error checking 
+	cfg_init();    
+	sts_init();    
+	cma_init();
+
+	printf("Reseting counters...\n");
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &= ~1,0);
+	printf("Reseting tlast_gen core...\n");
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &=~2,0);
+	printf("Reseting writer...\n");
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &= ~4,0);
+
+	printf("Set writer address...\n");
+	val=rd_reg_value(1, CFG_WR_ADDR_OFFSET,0);
+	printf("val es: %d ...\n",val);
+	printf("dev_size es: %d ...\n",dev_size);
+	wr_reg_value(1, CFG_WR_ADDR_OFFSET, dev_size,0);
+
+	printf("Set number of samples...\n");
+	val=rd_reg_value(1, CFG_NSAMPLES_OFFSET,0);
+	wr_reg_value(1, CFG_NSAMPLES_OFFSET, 65536,0);
+
+	// wait 1 second
+	//sleep(1);
+
+	// enter normal mode
+	// tlast_gen
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |= 2,0);
+  //writer
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |= 4,0);
+	// wait 1 second
+	sleep(2);
+	//counters
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val |= 1,0);
+
+	//val=rd_reg_value(1, STS_STATUS_OFFSET,1);
+	//printf("%5d\n", val);
+	// wait 1 second
+	//sleep(1);
+
+	// print IN1 and IN2 samples
+	for(i = 0; i < 2*65536; ++i){
+	//for(i = 0; i < 65536; i+=2){
+		//ch[0] = *(cma_ptr + 2*i + 0);
+		//ch[1] = *(cma_ptr + 2*i + 1);
+		ch[0] = cma_ptr[2*i + 0];
+		ch[1] = cma_ptr[2*i + 1]; 
+		//ch[2] = *((uint16_t *)(cma_ptr2 + i));
+		//ch[3] = *((uint16_t *)(cma_ptr2 + 2*i));
+		wo = *((uint32_t *)(cma_ptr + 2*i));
+		wo2 = *((uint32_t *)(cma_ptr2 + i));
+		//printf("%5d %5d %10d\n", ch[0], ch[1], wo);
+		//printf("%5d %5d %10d\n", ch[2], ch[3], wo2);
+		printf("%5d %5d %10d %5d %5d %10d\n", ch[0], ch[1], wo, (int16_t)(wo&0xFFFF), (int16_t)(wo>>16), wo2);
+	//	printf("%5d %5d %10d %5d %5d %10d\n", ch[0], ch[1], wo, ch[2], ch[3], wo2);
+		//printf("%5d %5d %10d\n", ch[2], ch[3], wo2);
+	//val=rd_reg_value(1, STS_STATUS_OFFSET,1);
+	//printf("#%5d\n", val);
+//		ch[0] = cma_ptr[2 * i + 0];
+//		ch[1] = cma_ptr[2 * i + 1];
+//		//wo    = cma_ptr[i] 
+//		printf("%5d %5d\n", ch[0], ch[1]);
+	}
+	//val=rd_reg_value(1, STS_STATUS_OFFSET,1);
+	//printf("%5d\n", val);
+
+	//reset counters again
+	val=rd_reg_value(1, CFG_RESET_GRAL_OFFSET,0);
+	wr_reg_value(1, CFG_RESET_GRAL_OFFSET, val &= ~1,0);
+	// unmap and close the devices 
+	munmap(cfg_ptr, sysconf(_SC_PAGESIZE));
+	munmap(sts_ptr, sysconf(_SC_PAGESIZE));
+
+	close(cfg_fd);
+	close(sts_fd);
+	//printf("Saliendo ...\n");
+
+	return 0;
+
+}
diff --git a/projects/counter_test/uio_src/zynq_io.c b/projects/counter_test/uio_src/zynq_io.c
new file mode 100644
index 0000000000000000000000000000000000000000..23a86c8829f560e6e48e30835213ac797eacfbeb
--- /dev/null
+++ b/projects/counter_test/uio_src/zynq_io.c
@@ -0,0 +1,475 @@
+#include "zynq_io.h"
+
+int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, hst0_fd, hst1_fd, cma_fd;
+void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *hst0_ptr, *hst1_ptr;
+volatile int16_t *cma_ptr;
+volatile uint32_t *cma_ptr2;
+uint32_t dev_size;
+
+void dev_write(void *dev_base, uint32_t offset, int32_t value)
+{
+	*((volatile unsigned *)(dev_base + offset)) = value;
+}
+
+uint32_t dev_read(void *dev_base, uint32_t offset)
+{
+	return *((volatile unsigned *)(dev_base + offset));
+}
+
+/*int dev_init(int n_dev)
+	{
+	char *uiod; = "/dev/uio1";
+
+	printf("Initializing device...\n");
+
+// open the UIO device file to allow access to the device in user space
+cfg_fd = open(uiod, O_RDWR);
+if (cfg_fd < 1) {
+printf("cfg_init: Invalid UIO device file:%s.\n", uiod);
+return -1;
+}
+
+dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size");
+
+// mmap the cfgC device into user space
+cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0);
+if (cfg_ptr == MAP_FAILED) {
+printf("cfg_init: mmap call failure.\n");
+return -1;
+}
+
+return 0;
+}*/
+
+int32_t rd_reg_value(int n_dev, uint32_t reg_off, uint8_t debug)
+{
+	int32_t reg_val;
+	switch(n_dev)
+	{
+		case 0:
+			reg_val = dev_read(intc_ptr, reg_off);
+			break;
+		case 1:
+			reg_val = dev_read(cfg_ptr, reg_off);
+			break;
+		case 2:
+			reg_val = dev_read(sts_ptr, reg_off);
+			break;
+		case 3:
+			reg_val = dev_read(xadc_ptr, reg_off);
+			break;
+		default:
+			printf("Invalid option: %d\n", n_dev);
+			return -1;
+	}
+	if(debug)
+		printf("Complete. Received data 0x%08x\n", reg_val);
+	//printf("Complete. Received data %d\n", reg_val);
+
+	return reg_val;
+}
+
+int32_t wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val, uint8_t debug)
+{
+	switch(n_dev)
+	{
+		case 0:
+			dev_write(intc_ptr, reg_off, reg_val);
+			break;
+		case 1:
+			dev_write(cfg_ptr, reg_off, reg_val);
+			break;
+		case 2:
+			dev_write(sts_ptr, reg_off, reg_val);
+			break;
+		case 3:
+			dev_write(xadc_ptr, reg_off, reg_val);
+			break;
+		default:
+			printf("Invalid option: %d\n", n_dev);
+			return -1;
+	}
+	if(debug)
+		printf("Complete. Data written: 0x%08x\n", reg_val);
+	//printf("Complete. Data written: %d\n", reg_val);
+
+	return 0;
+}
+
+int32_t rd_cfg_status(void)
+{
+	//float a = 0.0382061, b = 4.11435;  // For gain = 1.45
+	float a = 0.0882006, b = 7.73516;  // For gain = 3.2
+
+	printf("#Trigger Level Ch1 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_1_OFFSET));
+	printf("#Trigger Level Ch2 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_2_OFFSET));
+	//printf("#Subtrigger Ch1    = %d\n", dev_read(cfg_ptr, CFG_STRLVL_1_OFFSET));
+	//printf("#Subtrigger Ch2    = %d\n", dev_read(cfg_ptr, CFG_STRLVL_2_OFFSET));
+	printf("#High Voltage 1    = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV1_OFFSET)+b);
+	printf("#High Voltage 2    = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV2_OFFSET)+b);
+	printf("#Trigger Scaler 1  = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_A_OFFSET));
+	printf("#Trigger Scaler 2  = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_B_OFFSET));
+	if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // No GPS is present
+		printf("#No GPS device is present or enabled\n");
+	}else{
+		printf("#Using GPS data\n");
+	}
+	if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>5) & 0x1) == 0) //Slave
+	{
+		printf("#Working mode is SLAVE\n");
+	}else{
+		printf("#Working mode is MASTER\n");
+	}
+	printf("\n");
+	printf("Status from registers complete!\n");
+	return 0;
+}
+
+static uint32_t get_memory_size(char *sysfs_path_file)
+{
+	FILE *size_fp;
+	uint32_t size;
+
+	// open the file that describes the memory range size that is based on
+	// the reg property of the node in the device tree
+	size_fp = fopen(sysfs_path_file, "r");
+
+	if (!size_fp) {
+		printf("unable to open the uio size file\n");
+		exit(-1);
+	}
+
+	// get the size which is an ASCII string such as 0xXXXXXXXX and then be
+	// stop using the file
+	if(fscanf(size_fp, "0x%08X", &size) == EOF){
+		printf("unable to get the size of the uio size file\n");
+		exit(-1);
+	}
+	fclose(size_fp);
+
+	return size;
+}
+
+int intc_init(void)
+{
+	char *uiod = "/dev/uio0";
+
+	//printf("Initializing INTC device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	intc_fd = open(uiod, O_RDWR);
+	if (intc_fd < 1) {
+		printf("intc_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio0/maps/map0/size");
+
+	// mmap the INTC device into user space
+	intc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, intc_fd, 0);
+	if (intc_ptr == MAP_FAILED) {
+		printf("intc_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int cfg_init(void)
+{
+	char *uiod = "/dev/uio1";
+
+	//printf("Initializing CFG device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	cfg_fd = open(uiod, O_RDWR);
+	if (cfg_fd < 1) {
+		printf("cfg_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size");
+
+	// mmap the cfgC device into user space
+	cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0);
+	if (cfg_ptr == MAP_FAILED) {
+		printf("cfg_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int sts_init(void)
+{
+	char *uiod = "/dev/uio4";
+
+	//printf("Initializing STS device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	sts_fd = open(uiod, O_RDWR);
+	if (sts_fd < 1) {
+		printf("sts_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio4/maps/map0/size");
+
+	// mmap the STS device into user space
+	sts_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, sts_fd, 0);
+	if (sts_ptr == MAP_FAILED) {
+		printf("sts_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int xadc_init(void)
+{
+	char *uiod = "/dev/uio5";
+
+	//printf("Initializing XADC device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	xadc_fd = open(uiod, O_RDWR);
+	if (xadc_fd < 1) {
+		printf("xadc_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio5/maps/map0/size"); 
+
+	// mmap the XADC device into user space
+	xadc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, xadc_fd, 0);
+	if (xadc_ptr == MAP_FAILED) {
+		printf("xadc_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int mem_init(void)
+{
+	char *mem_name = "/dev/mem";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	mem_fd = open(mem_name, O_RDWR);
+	if (mem_fd < 1) {
+		printf("mem_init: Invalid device file:%s.\n", mem_name);
+		return -1;
+	}
+
+	dev_size = 2048*sysconf(_SC_PAGESIZE);
+
+	// mmap the mem device into user space 
+	mem_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0x1E000000);
+	if (mem_ptr == MAP_FAILED) {
+		printf("mem_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int cma_init(void)
+{
+	char *cma_name = "/dev/cma";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	cma_fd = open(cma_name, O_RDWR);
+	if (cma_fd < 1) {
+		printf("cma_init: Invalid device file:%s.\n", cma_name);
+		return -1;
+	}
+
+	dev_size = 1024*sysconf(_SC_PAGESIZE);
+
+	if(ioctl(cma_fd, CMA_ALLOC, &dev_size) < 0) {
+		perror("ioctl");
+		return EXIT_FAILURE;
+	}
+	// mmap the mem device into user space 
+	cma_ptr = mmap(NULL, 1024*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, cma_fd, 0);
+	cma_ptr2 = mmap(NULL, 1024*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, cma_fd, 0);
+	if (cma_ptr == MAP_FAILED) {
+		printf("cma_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+float get_voltage(uint32_t offset)
+{
+	int16_t value;
+	value = (int16_t) dev_read(xadc_ptr, offset);
+	//  printf("The Voltage is: %lf V\n", (value>>4)*XADC_CONV_VAL);
+	return ((value>>4)*XADC_CONV_VAL);
+}       
+
+/*void set_voltage(uint32_t offset, int32_t value)
+	{       
+//fit after calibration. See file data_calib.txt in /ramp_test directory 
+// y = a*x + b
+//a               = 0.0382061     
+//b               = 4.11435   
+uint32_t dac_val;
+float a = 0.0382061, b = 4.11435; 
+
+dac_val = (uint32_t)(value - b)/a;
+
+dev_write(cfg_ptr, offset, dac_val);
+printf("The Voltage is: %d mV\n", value);
+printf("The DAC value is: %d DACs\n", dac_val);
+}
+*/
+
+void set_voltage(uint32_t offset, int32_t value)
+{       
+	//fit after calibration. See file data_calib2.txt in /ramp_test directory 
+	// y = a*x + b
+	//a               = 0.0882006     
+	//b               = 7.73516   
+	uint32_t dac_val;
+	float a = 0.0882006, b = 7.73516; 
+
+	dac_val = (uint32_t)(value - b)/a;
+
+	dev_write(cfg_ptr, offset, dac_val);
+	printf("The Voltage is: %d mV\n", value);
+	printf("The DAC value is: %d DACs\n", dac_val);
+}
+
+float get_temp_AD592(uint32_t offset)
+{
+	float value;
+	value = get_voltage(offset);
+	return ((value*1000)-273.15);
+}       
+
+//System initialization
+int init_system(void)
+{
+	uint32_t reg_val;
+
+	//FIXME: replace hardcoded values for defines
+	// set trigger_lvl_1
+	dev_write(cfg_ptr,CFG_TRLVL_1_OFFSET,8190);
+
+	// set trigger_lvl_2
+	dev_write(cfg_ptr,CFG_TRLVL_2_OFFSET,8190);
+
+	// set subtrigger_lvl_1
+	dev_write(cfg_ptr,CFG_STRLVL_1_OFFSET,8190);
+
+	// set subtrigger_lvl_2
+	dev_write(cfg_ptr,CFG_STRLVL_2_OFFSET,8190);
+
+	// set hv1 and hv2 to zero
+	dev_write(cfg_ptr,CFG_HV1_OFFSET,0);
+	dev_write(cfg_ptr,CFG_HV2_OFFSET,0);
+
+	// reset ramp generators
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~8);
+
+	// reset pps_gen, fifo and trigger modules
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~1);
+
+	/* reset data converter and writer */
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~4);
+
+	// enter reset mode for tlast_gen
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~2);
+
+	// set number of samples
+	dev_write(cfg_ptr,CFG_NSAMPLES_OFFSET, 1024 * 1024);
+
+	// set default value for trigger scalers a and b
+	dev_write(cfg_ptr,CFG_TR_SCAL_A_OFFSET, 1);
+	dev_write(cfg_ptr,CFG_TR_SCAL_B_OFFSET, 1);
+
+	// enter normal mode for tlast_gen
+	/*        reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 2);
+	//printf("written reg_val tlast : 0x%08x\n",reg_val | 2);
+	// enter normal mode for pps_gen, fifo and trigger modules
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 1);
+	//printf("written reg_val pps_gen, fifo : 0x%08x\n",reg_val | 1);
+	*/
+	// enable false GPS
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | FGPS_EN_MASK);
+	//printf("written reg_val : 0x%08x\n",reg_val | 16);
+	// disable
+	//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~16);
+	//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~FGPS_EN_MASK);
+	//printf("written reg_val : 0x%08x\n",reg_val & ~16);
+
+	/*        // enter normal mode for data converter and writer
+						reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+						dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 4);
+	//printf("written reg_val : 0x%08hx\n",reg_val | 4);
+	*/
+	// enter normal mode for ramp generators
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 8);
+	// enter in MASTER mode (default)
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 0x20);
+
+	return 0;
+}
+
+int enable_interrupt(void)
+{
+	// steps to accept interrupts -> as pg. 26 of pg099-axi-intc.pdf
+	//1) Each bit in the IER corresponding to an interrupt must be set to 1.
+	dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 1);
+	//2) There are two bits in the MER. The ME bit must be set to enable the
+	//interrupt request outputs.
+	dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK | XIL_AXI_INTC_MER_HIE_MASK);
+	//dev_write(dev_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK);
+
+	//The next block of code is to test interrupts by software
+	//3) Software testing can now proceed by writing a 1 to any bit position
+	//in the ISR that corresponds to an existing interrupt input.
+	/*        dev_write(intc_ptr,XIL_AXI_INTC_IPR_OFFSET, 1);
+
+						for(a=0; a<10; a++)
+						{
+						wait_for_interrupt(fd, dev_ptr);
+						dev_write(dev_ptr,XIL_AXI_INTC_ISR_OFFSET, 1); //regenerate interrupt
+						}
+						*/
+	return 0;
+
+}
+
+int disable_interrupt(void)
+{
+	uint32_t value;
+	//Disable interrupt INTC0
+	dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 0);
+	//disable IRQ
+	value = dev_read(intc_ptr, XIL_AXI_INTC_MER_OFFSET);
+	dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, value | ~1);
+	//Acknowledge any previous interrupt
+	dev_write(intc_ptr, XIL_AXI_INTC_IAR_OFFSET, 1);
+
+	return 0;
+}
+
diff --git a/projects/counter_test/uio_src/zynq_io.h b/projects/counter_test/uio_src/zynq_io.h
new file mode 100644
index 0000000000000000000000000000000000000000..f5b442845168bd320a52ddfdc44a228fb93d9925
--- /dev/null
+++ b/projects/counter_test/uio_src/zynq_io.h
@@ -0,0 +1,156 @@
+#ifndef _ZYNQ_IO_H_
+#define _ZYNQ_IO_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#define CMA_ALLOC _IOWR('Z', 0, uint32_t)
+#define INTC_BASEADDR 0x40000000
+#define INTC_HIGHADDR 0x40000FFF
+
+#define CFG_BASEADDR  0x40001000
+#define CFG_HIGHADDR  0x40001FFF
+
+#define STS_BASEADDR  0x40002000
+#define STS_HIGHADDR  0x40002FFF
+
+#define XADC_BASEADDR 0x40003000
+#define XADC_HIGHADDR 0x40003FFF
+
+#define XIL_AXI_INTC_ISR_OFFSET    0x0
+#define XIL_AXI_INTC_IPR_OFFSET    0x4
+#define XIL_AXI_INTC_IER_OFFSET    0x8
+#define XIL_AXI_INTC_IAR_OFFSET    0xC
+#define XIL_AXI_INTC_SIE_OFFSET    0x10
+#define XIL_AXI_INTC_CIE_OFFSET    0x14
+#define XIL_AXI_INTC_IVR_OFFSET    0x18
+#define XIL_AXI_INTC_MER_OFFSET    0x1C
+#define XIL_AXI_INTC_IMR_OFFSET    0x20
+#define XIL_AXI_INTC_ILR_OFFSET    0x24
+#define XIL_AXI_INTC_IVAR_OFFSET   0x100
+
+#define XIL_AXI_INTC_MER_ME_MASK 0x00000001
+#define XIL_AXI_INTC_MER_HIE_MASK 0x00000002
+
+//CFG
+#define CFG_RESET_GRAL_OFFSET    0x0
+#define CFG_WR_ADDR_OFFSET       0x4
+#define CFG_NSAMPLES_OFFSET      0x8
+#define CFG_TRLVL_1_OFFSET       0x8
+#define CFG_TRLVL_2_OFFSET       0xC
+#define CFG_STRLVL_1_OFFSET      0x10
+#define CFG_STRLVL_2_OFFSET      0x14
+#define CFG_TEMPERATURE_OFFSET   0x18
+#define CFG_PRESSURE_OFFSET      0x1C
+#define CFG_TIME_OFFSET          0x20
+#define CFG_DATE_OFFSET          0x24
+#define CFG_LATITUDE_OFFSET      0x28
+#define CFG_LONGITUDE_OFFSET     0x2C
+#define CFG_ALTITUDE_OFFSET      0x30
+#define CFG_SATELLITE_OFFSET     0x34
+#define CFG_TR_SCAL_A_OFFSET     0x38
+#define CFG_TR_SCAL_B_OFFSET     0x3C
+#define CFG_HV1_OFFSET           0x4C //DAC_PWM3
+#define CFG_HV2_OFFSET           0x48 //DAC_PWM2
+#define CFG_HV3_OFFSET           0x40 //DAC_PWM0
+#define CFG_HV4_OFFSET           0x44 //DAC_PWM1
+
+//CFG Slow DAC
+#define CFG_DAC_PWM0_OFFSET 0x40
+#define CFG_DAC_PWM1_OFFSET 0x44
+#define CFG_DAC_PWM2_OFFSET 0x48
+#define CFG_DAC_PWM3_OFFSET 0x4C
+
+#define ENBL_ALL_MASK         0xFFFFFFFF
+#define RST_ALL_MASK          0x00000000
+#define RST_PPS_TRG_FIFO_MASK 0x00000001
+#define RST_TLAST_GEN_MASK    0x00000002
+#define RST_WRITER_MASK       0x00000004
+#define RST_AO_MASK           0x00000008
+#define FGPS_EN_MASK          0x00000010
+
+//STS
+#define STS_STATUS_OFFSET     0x0
+
+//XADC
+//See page 17 of PG091
+#define XADC_SRR_OFFSET          0x00   //Software reset register
+#define XADC_SR_OFFSET           0x04   //Status Register
+#define XADC_AOSR_OFFSET         0x08   //Alarm Out Status Register
+#define XADC_CONVSTR_OFFSET      0x0C   //CONVST Register
+#define XADC_SYSMONRR_OFFSET     0x10   //XADC Reset Register
+#define XADC_GIER_OFFSET         0x5C   //Global Interrupt Enable Register
+#define XADC_IPISR_OFFSET        0x60   //IP Interrupt Status Register
+#define XADC_IPIER_OFFSET        0x68   //IP Interrupt Enable Register
+#define XADC_TEMPERATURE_OFFSET  0x200  //Temperature
+#define XADC_VCCINT_OFFSET       0x204  //VCCINT
+#define XADC_VCCAUX_OFFSET       0x208  //VCCAUX
+#define XADC_VPVN_OFFSET         0x20C  //VP/VN
+#define XADC_VREFP_OFFSET        0x210  //VREFP
+#define XADC_VREFN_OFFSET        0x214  //VREFN
+#define XADC_VBRAM_OFFSET        0x218  //VBRAM
+#define XADC_UNDEF_OFFSET        0x21C  //Undefined
+#define XADC_SPLYOFF_OFFSET      0x220  //Supply Offset
+#define XADC_ADCOFF_OFFSET       0x224  //ADC Offset
+#define XADC_GAIN_ERR_OFFSET     0x228  //Gain Error
+#define XADC_ZDC_SPLY_OFFSET     0x234  //Zynq-7000 Device Core Supply
+#define XADC_ZDC_AUX_SPLY_OFFSET 0x238  //Zynq-7000 Device Core Aux Supply
+#define XADC_ZDC_MEM_SPLY_OFFSET 0x23C  //Zynq-7000 Device Core Memory Supply
+#define XADC_VAUX_PN_0_OFFSET    0x240  //VAUXP[0]/VAUXN[0]
+#define XADC_VAUX_PN_1_OFFSET    0x244  //VAUXP[1]/VAUXN[1]
+#define XADC_VAUX_PN_2_OFFSET    0x248  //VAUXP[2]/VAUXN[2]
+#define XADC_VAUX_PN_3_OFFSET    0x24C  //VAUXP[3]/VAUXN[3]
+#define XADC_VAUX_PN_4_OFFSET    0x250  //VAUXP[4]/VAUXN[4]
+#define XADC_VAUX_PN_5_OFFSET    0x254  //VAUXP[5]/VAUXN[5]
+#define XADC_VAUX_PN_6_OFFSET    0x258  //VAUXP[6]/VAUXN[6]
+#define XADC_VAUX_PN_7_OFFSET    0x25C  //VAUXP[7]/VAUXN[7]
+#define XADC_VAUX_PN_8_OFFSET    0x260  //VAUXP[8]/VAUXN[8]
+#define XADC_VAUX_PN_9_OFFSET    0x264  //VAUXP[9]/VAUXN[9]
+#define XADC_VAUX_PN_10_OFFSET   0x268  //VAUXP[10]/VAUXN[10]
+#define XADC_VAUX_PN_11_OFFSET   0x26C  //VAUXP[11]/VAUXN[11]
+#define XADC_VAUX_PN_12_OFFSET   0x270  //VAUXP[12]/VAUXN[12]
+#define XADC_VAUX_PN_13_OFFSET   0x274  //VAUXP[13]/VAUXN[13]
+#define XADC_VAUX_PN_14_OFFSET   0x278  //VAUXP[14]/VAUXN[14]
+#define XADC_VAUX_PN_15_OFFSET   0x27C  //VAUXP[15]/VAUXN[15]
+
+#define XADC_AI0_OFFSET XADC_VAUX_PN_8_OFFSET
+#define XADC_AI1_OFFSET XADC_VAUX_PN_0_OFFSET
+#define XADC_AI2_OFFSET XADC_VAUX_PN_1_OFFSET
+#define XADC_AI3_OFFSET XADC_VAUX_PN_9_OFFSET
+
+#define XADC_CONV_VAL 0.00171191993362 //(A_ip/2^12)*(34.99/4.99)
+#define XADC_RDIV_VAL 1.883236177     //voltage divisor in board (15k+16.983k)/16.983k = 1.88
+#define XADC_BASE_HVDIV 0.00294088    //voltage divisor in HV base board (100k/31.3Meg) = 3.194888179. The value I put here is the measured one.
+
+extern int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, hst0_fd, hst1_fd, cma_fd;
+extern void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *hst0_ptr, *hst1_ptr;
+extern volatile int16_t *cma_ptr;
+extern volatile uint32_t *cma_ptr2;
+extern uint32_t dev_size;
+
+void     dev_write(void *dev_base, uint32_t offset, int32_t value);
+uint32_t dev_read(void *dev_base, uint32_t offset);
+//int    dev_init(int n_dev);
+int32_t  rd_reg_value(int n_dev, uint32_t reg_off, uint8_t degug);
+int32_t  wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val, uint8_t debug);
+int32_t  rd_cfg_status(void);
+int      intc_init(void);
+int      cfg_init(void);
+int      sts_init(void);
+int      xadc_init(void);
+int      mem_init(void);
+int      cma_init(void);
+float    get_voltage(uint32_t offset);
+void     set_voltage(uint32_t offset, int32_t value);
+float    get_temp_AD592(uint32_t offset);
+int      init_system(void);
+int      enable_interrupt(void);
+int      disable_interrupt(void);
+
+#endif
+
diff --git a/projects/gpio_led_test/block_design.tcl b/projects/gpio_led_test/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..06376a358f82839f9418f04521637ea84eced20c
--- /dev/null
+++ b/projects/gpio_led_test/block_design.tcl
@@ -0,0 +1,56 @@
+source projects/base_system/block_design.tcl
+
+#Enable interrupts
+set_property -dict [list CONFIG.PCW_USE_FABRIC_INTERRUPT {1} CONFIG.PCW_IRQ_F2P_INTR {1}] [get_bd_cells ps_0]
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+# Create axis_rp_adc
+cell labdpr:user:axis_rp_adc adc_0 {
+  ADC_DATA_WIDTH 14
+} {
+  aclk pll_0/clk_out1
+  adc_dat_a adc_dat_a_i
+  adc_dat_b adc_dat_b_i
+  adc_csn adc_csn_o
+}
+
+# Create c_counter_binary
+cell xilinx.com:ip:c_counter_binary cntr_0 {
+  Output_Width 32
+} {
+  CLK pll_0/clk_out1
+}
+
+# Create xlslice
+cell xilinx.com:ip:xlslice slice_0 {
+  DIN_WIDTH 32 DIN_FROM 26 DIN_TO 26 DOUT_WIDTH 1
+} {
+  Din cntr_0/Q
+}
+
+# Create GPIO core
+cell xilinx.com:ip:axi_gpio axi_gpio_0 {
+   C_GPIO_WIDTH 8
+  C_GPIO2_WIDTH 1
+  C_ALL_OUTPUTS 1
+  C_IS_DUAL 1 
+  C_ALL_INPUTS 0 
+  C_ALL_INPUTS_2 1
+  C_INTERRUPT_PRESENT 1 
+  C_ALL_OUTPUTS 1
+} {
+  s_axi_aclk pll_0/clk_out1
+  s_axi_aresetn rst_0/peripheral_aresetn
+  ip2intc_irpt ps_0/IRQ_F2P
+  gpio_io_o led_o
+  gpio2_io_i slice_0/Dout
+}
+
+addr 0x40000000 4K axi_gpio_0/S_AXI /ps_0/M_AXI_GP0
diff --git a/projects/gpio_led_test/gpio_led_test.c b/projects/gpio_led_test/gpio_led_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..bd79c4a74b5a5fe7c0bf50834880205f6d4419c3
--- /dev/null
+++ b/projects/gpio_led_test/gpio_led_test.c
@@ -0,0 +1,575 @@
+/* basic_design_zynq_hw_exerciser.c
+ *
+ * This program demonstrates the basic capabilities of a Zynq platform
+ * communicating with two axi_gpio peripherals (from the IP catalog) that
+ * are implemented as hardware in the PL.
+ *
+ * NOTE: THE GPIO THAT IS CONTAINED IN THE PS IS NOT BEING USED
+ *
+ * One of the GPIO's is configured as an 8 bit output driving 8 LED's.
+ * The other GPIO is configured as a three input device being driven
+ * from push buttons.
+ *
+ * The program functions in a forever loop, monitoring the input push
+ * buttons.  The three buttons are UP, DOWN, and STOP that directly
+ * control the a binary counting pattern on the LED's.
+ *
+ * This application is written to either, use the Standalone library
+ * or be compiled as a Linux application. Either flow is supported in
+ * the SDK programming development. The default compilation is using
+ * the Standalone library. To compile this application as a Linux
+ * application, add to the properties of the associated application
+ * project, a #define of a symbol named "LINUX_APP". Select properties and
+ * C/C++ Build => Settings => ARM Linux gcc compiler => Symbols,
+ * adding a -D LINUX_APP to the gcc compiler tool command line.
+ *
+ * The hardware (axi_gpio) physical device pinout in the PL may vary
+ * with the target evaluation board being used. This variation is
+ * typically manifested in the constraints file which determines
+ * device pin locations for the actual pin numbers used for the LED's
+ * and pushbuttons. Other variations in the hardware may be needed to
+ * accommodate the fact that varying numbers of pushbutton inputs or
+ * LED output actually exist.
+ * 
+ * The goal is that  this application can be targeted to multiple
+ * hardware Zynq platforms (or configurations) either as a Standalone
+ * or Linux application.
+ *
+ * THE FOLLOWING HARDWARE PLATFORMS ARE DEFINED
+ * ZC702 BOARD
+ * LED's - Eight LED's, DS15-DS22, located towards the center of the
+ *         board from the SD card slot
+ * Push Buttons - Only two buttons are use, located adjacent to the LED's
+ *         UP - SW7
+ *         DOWN - SW5
+ *         STOP - Pressing both, SW5 and SW7, at the same time provides a STOP
+ *         (Due to a lack of pushbuttons accessible by PL pins, hardware
+ *          in the PL was added to emulate a third button)
+ *
+ * ZC702 BOARD WITH CE (Customer Education) FMC CARD IN FMC1 SLOT
+ * LED's - Eight LED's, LD0-LD7, located between slide switches and LCD display
+ * Push Buttons - Rosetta buttons located on CE FMC card,
+ *         UP - BTN3 - West
+ *         DOWN - BTN0 - Center
+ *         STOP - BTN1 - East
+ *
+ * ******************************************************************************************************************
+ *
+ * 
+ *   basic_design_exerciser
+ *   Ver.:  1.0    6/1/2012 WK/LR
+ *
+ *   This code generates an LED pattern for the 8 bit LED array present on the ZC702 board. It must have
+ *   one of several symbols defined: 
+ *      hardware_test   - infinite loop,         long delays for LEDs so user can visually recognize what is happening, uses standalone drivers
+ *      profiler_test   - finite loop for gprof, short delays so profiler doesn't report all the activity being in the wait_loop function, uses standalone drivers
+ *      CSP_test        - infinite loop,         short delays so multiple datum can be captured with the Analyzer, uses standalone drivers
+ *      LINUX_APP       - infinite loop,         long delays for LEDs so user can visually recogize what is happening, uses Linux drivers
+ *
+ * ******************************************************************************************************************
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+// Stuff needed for Linux DEVMEM access
+#define MAP_SIZE 4096UL
+#define MAP_MASK (MAP_SIZE - 1)
+#define TRUE 1
+#define FALSE 1
+typedef int u32;	                              // add this compatibility for int's between Linux and Standalone
+
+// Linux pointers to GPIO's in PL hardware
+void *mapped_led_dev_base;		// Address of LED GPIO
+void *mapped_button_dev_base;	// Address of Push Button GPIO
+void *mapped_base;				// Address of device memory window, it is global for visibility in main to unmount device memory
+int memfd; 						// device memory handle for Linux device to memory mapping, it is global for visibility in main to unmount device memory
+
+// Linux application needs gpio base address and register offsets, Standalone application gets it from xparameters.h
+#define GPIO_BUTTON_BASE_ADDRESS	0x41240000
+#define GPIO_LED_BASE_ADDRESS    	0x40000000
+#define GPIO_DATA_OFFSET     		  0x0000
+#define GPIO_DIRECTION_OFFSET    	0x0004
+
+// access the serial output
+#define print printf
+
+// constants
+#define LED_DELAY_NORMAL   5000000
+#define LED_DELAY_PROFILE        2
+#define BUTTON_CHANNEL           1
+#define LED_CHANNEL              1
+#define ALL_OUTPUTS              0
+#define ALL_INPUTS      0xffffffff
+
+
+// function prototypes  (functions defined in this file after the main)
+void *Linux_GPIO_initialize(int gpio_base_address, int direction, int first_call);
+
+// for the hardware exerciser...
+void    hardware_exerciser();                                     // name of routine follows common 'C' language convention
+#define PI (double)3.141592653                                    // approximation of PI
+void    do_sine_sample(int sample);                               // takes sample and calls other routines to get results to LEDs, serial port
+void    doBarGraph(int value, int style);                         // name of routine follows common Java language convention (legal for C)
+void    driveBarGraph(int value);                                 // actually selects which LEDs are active and makes peripheral call
+#define CYLON  1
+#define BAR    2
+#define BINARY 3
+double  sine(double angle_in_radians);
+double  factorial(int final_term);
+char   *itoa(int value, char *string, int radix);
+char   *strcat (char *destination, const char *source);
+void    delay_loop(long int delay_count);
+int     buttons_get_state(void);
+void    LEDs_driver(int pattern);
+
+int   LED_delay_max;                                              // maximum value to delay to for the LED wait loop
+
+/*
+ *  ***********************************************************
+ */
+int main() {
+
+	// local variable
+	int mode = 0;                                                 // used to check that one of the environment variables used
+
+	// let the user know that we're starting
+	print("---basic_design_zynq Exerciser---\n\r");
+
+	//***** initialize the GPIOs *****
+	// For Linux access memory mapped GPIO without kernel driver and initialize.
+	// The function returns a pointer address to the associated GPIO and sets the GPIO direction
+	mapped_led_dev_base = Linux_GPIO_initialize(GPIO_LED_BASE_ADDRESS, ALL_OUTPUTS, TRUE);
+	mapped_button_dev_base = Linux_GPIO_initialize(GPIO_BUTTON_BASE_ADDRESS, ALL_INPUTS, FALSE);
+
+
+	// determine the use of this software - are we exercising the hardware or doing the profiling exercise?
+#ifdef hardware_test
+	LED_delay_max = LED_DELAY_NORMAL;
+	print("running the hardware test...\n\r");
+	mode = 1;
+#endif
+
+#ifdef profiler_test
+	LED_delay_max = LED_DELAY_PROFILE;
+	print("running the profiler code...\n\r");
+	mode = 2;
+#endif
+
+#ifdef CSP_test
+	LED_delay_max = LED_DELAY_PROFILE;
+	print("running the CSP analyzer code...\n\r");
+	mode = 3;
+#endif
+
+	LED_delay_max = LED_DELAY_NORMAL;
+	print("running the Linux app...\n\r");
+	mode = 4;
+
+	// check to see that one or the other mode was selected, otherwise warn the user and abort
+	if (mode != 0) {
+		hardware_exerciser();                                // read switches, detect changes, increment/decrement counter, display count on LEDs...
+	} else {
+		print("you must set the symbol \"hardware_test\", \"profiler_test\", \"CSP_test\", or \"LINUX_APP\" in the compiler settings!\n\r");
+	}
+
+	print("---Exiting main---\n\r");							// never reached...
+
+	// unmap the memory used for the GPIO device before exiting
+	// Linux only, but will never be reached
+	// It is a good programming practice to always release the memory space the device was accessing
+	// Since the Standalone drivers can always access memory, this sort of functionality is not needed
+	if (munmap(mapped_base, MAP_SIZE) == -1) {
+		printf("Can't unmap memory from user space.\n");
+		exit(0);
+	}
+	printf("Memory Unmapped\n");
+	close(memfd);
+
+	return 0;
+}
+
+
+
+/*
+ * ************** Hardware Exerciser Code *************************
+ */
+#define UP    0
+#define LEFT  0
+#define DOWN  1
+#define RIGHT 1
+#define STOP  2
+
+#define ONE_PERIOD 128
+#define AMPLITUDE  256
+#define ABS(a) (((a) < 0) ? -(a) : (a))
+
+/*
+ * ****************************************************************************************************
+ *    HARDWARE EXERCISER CODE 
+ * ****************************************************************************************************
+ */
+
+void hardware_exerciser() {
+	// local variables
+	u32 last_button_state = 0;
+	u32 current_button_state = 0;
+	u32 button_difference = 0;
+	int count_direction = UP;
+	int sample = 0;
+	int keep_running = 1;
+	int profile_iteration_count = 500000;                        // used only in profile mode
+
+	// deliberate infinite loop
+	while (keep_running) {
+		// read current switch configuration
+		current_button_state = buttons_get_state();
+		button_difference = (current_button_state ^ last_button_state) & current_button_state; // detect a change and that it has been pushed (not released)
+		if (button_difference != 0) {
+
+			// has anything changed based on the buttons?
+			if      (button_difference & 0x04) { print("Stop counting..."); count_direction = STOP; }
+			else if (button_difference & 0x02) { print("Counting down..."); count_direction = DOWN; }
+			else if (button_difference & 0x01) { print("Counting up...");   count_direction = UP;   }
+		}
+		last_button_state = current_button_state;                    // update the button status to prevent runaway button action
+
+		// compute the next sample number (period of 256)
+		if      (count_direction = UP)   { sample++; sample %= ONE_PERIOD; }
+		else if (count_direction = DOWN) { sample--; if (sample < -1) sample = ONE_PERIOD-1; }
+		else                              { /* no change */}
+
+		// do the math and drive the LEDs
+		do_sine_sample(sample);
+
+		// wait loop - caution - delay loops like this are removed when optimization is turned on!
+		delay_loop(LED_delay_max);                                      // delay for a slower display
+
+		// if this is the profiler mode, we need to quit after a while
+#ifdef profiler_test
+		keep_running = profile_iteration_count--;
+#endif
+
+	}
+}
+
+
+// compute sine, drive LEDs and serial port
+// 0 < sample < ONE_PERIOD
+void do_sine_sample(int location_in_period) {
+	// local variables
+	double radian_equivalent;
+	int    sine_value;
+	char   buf[32],*message, *strValue;                         // used in hardware_test mode only
+
+	// do the computation of this point for sine
+	radian_equivalent = (double)(location_in_period)/(double)(ONE_PERIOD) * 3.1415927f * 2.0;   // one full circle
+	sine_value = (int)((double)(AMPLITUDE) * sine(radian_equivalent) / 2);                      // this is +/- (i.e. range -1:1 converted to 0:1), so...
+	sine_value += AMPLITUDE/2;                                                                  // bias this up so that 0 is in the middle
+
+	// drive the bar graph display
+	driveBarGraph(sine_value);
+
+#ifdef hardware_test
+	// display the value on the serial port and wait a bit for the LEDs/user to catch up - but only in hardware test mode
+	// no output will be present in the profiler_test
+	strValue = itoa(sine_value,buf,10);
+	message = strcat(strValue,"...");
+	xil_printf(message);
+#endif
+}
+
+/*
+ * sine(angle in radians)
+ *
+ * where: 0 <= angle in radians <= 2 PI
+ *
+ * does Taylor series expansion (4 terms) to compute sine
+ * taylor series good only for small angles - use reflection technique to determine value outside of Q1
+ * Q2 = PI - x
+ * Q3 = - (x - PI)
+ * Q4 = - (2PI - x)
+ *
+ * Note: this algorithm deliberately uses a slow, iterative way to compute factorials. The faster way:
+ * int factorial[] = { 1, 1, 2, 6, 24, 120, 720, 5040 };           // the "fast" way to do it - precompute for the # of terms you need, then it's just a memory lookup
+ * result = angle_in_radians - X3/factorial[3] + X5/factorial[5] - X7/factorial[7];
+ *
+ */
+double sine(double angle_in_radians) {
+	double X2;
+	double X3;
+	double X5;
+	double X7;
+	double result;
+	int    quadrant   = 1;                            // begin by assuming Q1
+
+	// determine quadrant and reflect horizontally (if necessary)
+	if (angle_in_radians > 3*PI/2) {                  // in Q4?
+		quadrant = 4;                                  // remember for later
+		angle_in_radians = 2 * PI - angle_in_radians;  // do horizontal (x) reflection, y reflection done later
+	} else if (angle_in_radians > PI) {               // in Q3?
+		quadrant = 3;                                  // remember for later
+		angle_in_radians = angle_in_radians - PI;      // no x reflection, y reflection done later
+	} else if (angle_in_radians > PI/2) {             // in Q2?
+		quadrant = 2;                                  // remember for later
+		angle_in_radians = PI - angle_in_radians;      // do horizontal (x) reflection
+	}
+
+	// compute powers of angle_in_radians
+	X2 = angle_in_radians * angle_in_radians;
+	X3 = X2 * angle_in_radians;
+	X5 = X3 * X2;
+	X7 = X5 * X2;
+
+	// compute the sine approximation to 4 places for Q1
+	result = angle_in_radians - X3/factorial(3) + X5/factorial(5) - X7/factorial(7);
+
+	// do vertical reflection for Q3 and Q4
+	if (quadrant > 2) {
+		result *= -1;                                 // flip the Q1/Q2 result
+	}
+
+	return result;
+}
+
+double factorial(int final_term) {
+	double result = 1.0;
+	int    term;
+
+	for (term=2; term<=final_term; term++) {
+		result *= term;
+	}
+
+	return result;
+}
+
+
+/******************************************************************************************************
+ * LINUX GPIO INITIALIZATION
+ * This function performs two operations:
+ * 1) Opens a device to memory window in Linux so a GPIO that exists at a physical address is mapped
+ *    to a fixed logical address. This logical address is returned by the function.
+ * 2) Initialize the GPIO for either input or output mode.
+ *
+ * INPUT PARAMETERS:
+ * gpio_base_address - physical hardware base address of GPIO, you have to get this from XML file
+ * direction - 32 bits indicating direction for each bit; 0 - output; 1 - input
+ * first_call - boolean indicating that this is first call to function. The first time and only the first
+ *              time should the Linux device memory mapping service be mounted. Call for subsequent
+ *              gpio mapping this should be set to FALSE (0).
+ *
+ * RETURNS:
+ * mapped_dev_base - memory pointer to the GPIO that was specified by the gpio_base_address
+ *******************************************************************************************************/
+void *Linux_GPIO_initialize(int gpio_base_address, int direction, int first_call)
+{
+	void *mapped_dev_base;
+	off_t dev_base = gpio_base_address;
+
+	// Linux service to directly access PL hardware as memory without using a device driver
+	// The memory mapping to device service should only be called once
+	if (first_call) {
+		memfd = open("/dev/mem", O_RDWR | O_SYNC);
+		if (memfd == -1) {
+			printf("Can't open /dev/mem.\n");
+			exit(0);
+		}
+		printf("/dev/mem opened.\n");
+	}
+
+	// Map one page of memory into user space such that the device is in that page, but it may not
+	// be at the start of the page.
+	mapped_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, dev_base & ~MAP_MASK);
+	if (mapped_base == (void *) -1) {
+		printf("Can't map the memory to user space for LED GPIO.\n");
+		exit(0);
+	}
+	printf("LED GPIO memory mapped at address %p.\n", mapped_base);
+
+	// Get the address of the device in user space which will be an offset from the base
+	// that was mapped as memory is mapped at the start of a page
+	mapped_dev_base = mapped_base + (dev_base & MAP_MASK);
+
+	// Slight delay for Linux memory access problem
+	usleep(50);
+	// write to the direction GPIO direction register to set as all inputs or outputs
+	*((volatile unsigned long *) (mapped_dev_base + GPIO_DIRECTION_OFFSET)) = direction;
+	return mapped_dev_base;
+}
+
+/*
+ * driveBarGraph(12 bit value)
+ *
+ * calls doBarGraph. this routine determines which of the 8 possible bins/bars should be illuminated
+ *
+ */
+#define NUMBER_OF_LEDS    8
+void driveBarGraph(int value) {
+	char buf[32];                                                    // used in hardware test mode
+	double bin_range = (AMPLITUDE) / (NUMBER_OF_LEDS);               // how large is each bin?
+	int nBars = (int)((double)value / bin_range);                    // how many bars should be lit?
+
+#ifdef hardware_test
+	// only print the diagnostic text in hardware_test mode
+	xil_printf(itoa(nBars,buf,10)); print("\n\r");
+#endif
+
+	// turn on the proper LEDs based on the # of bars and the style
+	doBarGraph(nBars,CYLON);                                        //
+}
+
+
+/*
+ * doBarGraph(device, value to display, style in which to display
+ *
+ *
+ *    example value = 5,    style shown below:    LED  7  6  5  4  3  2  1  0
+ * Style: BAR   - solid up to value                    -  -  *  *  *  *  *  *     * = on, - = off
+ *        CYLON - single bar at value                  -  -  *  -  -  -  -  -
+ *        BINARY- binary representation of value       -  -  -  -  -  *  -  *
+ *        other - displays error pattern               -  *  -  *  -  *  -  *
+ *
+ */
+void doBarGraph(int value, int style) {
+
+	if (style == BAR) {
+		switch (value) {
+			case 0:  LEDs_driver(0x00); break;
+			case 1:  LEDs_driver(0x01); break;
+			case 2:  LEDs_driver(0x03); break;
+			case 3:  LEDs_driver(0x07); break;
+			case 4:  LEDs_driver(0x0f); break;
+			case 5:  LEDs_driver(0x1f); break;
+			case 6:  LEDs_driver(0x3f); break;
+			case 7:  LEDs_driver(0x7f); break;
+			case 8:  LEDs_driver(0xff); break;
+			default: LEDs_driver(0x55);                                          // non-contiguous pattern indicates error
+		}
+	} else if (style == CYLON) {
+		switch (value) {
+			case 0:  LEDs_driver(0x01); break;
+			case 1:  LEDs_driver(0x02); break;
+			case 2:  LEDs_driver(0x04); break;
+			case 3:  LEDs_driver(0x08); break;
+			case 4:  LEDs_driver(0x10); break;
+			case 5:  LEDs_driver(0x20); break;
+			case 6:  LEDs_driver(0x40); break;
+			case 7:  LEDs_driver(0x80); break;
+			default: LEDs_driver(0x55);                                         // non-contiguous pattern indicates error
+		}
+	} else if (style == BINARY) {
+		LEDs_driver(value);                                                    // simple binary value to display
+	} else {
+		LEDs_driver(0x69);                                                     // different error pattern
+	}
+
+}
+
+
+/*
+ * *** buttons_get_state()
+ *
+ * returns an integer representing the value of the buttons
+ *   0 - no buttons pressed
+ *   1 - left/down button pressed
+ *   2 - right/up button pressed
+ *   3 - both buttons pressed
+ *
+ * this function is coded this way so that it is clear what the Linux vs. Standalone/bare-metal are.
+ */
+int buttons_get_state()
+{
+	// local variables
+	int current_button_state = 0;
+	// Linux read of gpio, notice that it accesses the data register of the GPIO as a memory location, no device driver needed!
+	current_button_state = *((volatile unsigned long *) (mapped_button_dev_base + GPIO_DATA_OFFSET));
+}
+
+
+/*
+ * *** LEDs_driver(led image (int))
+ *
+ * sets the LED channel 1 device to the passed value
+ *
+ * this function is coded this way so that it is clear what the Linux vs. Standalone/bare-metal are.
+ */
+void LEDs_driver(int led_image)
+{
+	// Linux write to gpio, by writing to a memory address of the gpio data register, no device driver needed!
+	*((volatile unsigned long *) (mapped_led_dev_base + GPIO_DATA_OFFSET)) = led_image;
+}
+
+
+/*
+ * *** delay_loop(int delay_count)
+ *
+ * finite loop which causes a simple delay
+ * could have been also performed, more accurately, using the usleep() function
+ *
+ */
+void delay_loop(long int count)
+{
+	int i;
+	for (i=0; i<count; i++); 
+}
+
+
+/*
+ * *** itoa
+ *
+ * converts an integer into a string - also found in the C library
+ *
+ */
+char *itoa(int value, char *string, int radix)
+{
+	char tmp[33];
+	char *tp = tmp;
+	int i;
+	unsigned v;
+	int sign;
+	char *sp;
+
+	if (radix > 36 || radix <= 1) { string = "radix out of range 1..36"; return 0; }
+
+	sign = (radix == 10 && value < 0);
+	if (sign) { v = -value; }
+	else      { v = (unsigned)value; }
+	while (v || tp == tmp)  {
+		i = v % radix;
+		v = v / radix;
+		if (i < 10) { *tp++ = i+'0'; }
+		else        { *tp++ = i + 'a' - 10; }
+	}
+
+	if (string == 0) {
+		string = (char *)malloc((tp-tmp)+sign+1);
+		// xil_printf("call to malloc() made\n\r");
+	}
+	sp = string;
+
+	if (sign) { *sp++ = '-'; }
+	while (tp > tmp) { *sp++ = *--tp; }
+	*sp = 0;
+	return string;
+}
+
+/*
+ * *** strcat
+ *
+ * returns the concatonation of two strings
+ *
+ * may also be found in string.h
+ *
+ */
+char * strcat ( char * destination, const char * source ){
+	char *d = destination;
+	while (*d) ++d;
+	while ((*d++ = *source++) != '\0') ;
+	return (destination);
+}
+
+
+
diff --git a/projects/lago_v1_3/adc.tcl b/projects/lago_v1_3/adc.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..ac08dc20c95038028b5f67d9c9627ec14fb304ea
--- /dev/null
+++ b/projects/lago_v1_3/adc.tcl
@@ -0,0 +1,79 @@
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_2 {
+  CONST_WIDTH 16
+  CONST_VAL 1
+}
+
+# Create dc removal circuit
+cell labdpr:user:axis_dc_removal dc_removal_0 {} {
+  aclk /pll_0/clk_out1
+  aresetn /reset_0/Dout
+  S_AXIS /adc_0/M_AXIS
+	k1_i const_2/dout
+	k2_i const_2/dout
+}
+
+# Create pps generator
+cell labdpr:user:pps_gen pps_0 {} {
+  aclk /pll_0/clk_out1
+  aresetn /reset_0/Dout
+}
+
+# Create lago trigger
+cell labdpr:user:axis_lago_trigger trigger_0 {
+  DATA_ARRAY_LENGTH 32
+} {
+  S_AXIS dc_removal_0/M_AXIS
+  aclk /pll_0/clk_out1
+  aresetn /reset_0/Dout
+  trig_lvl_a_i /trig_lvl_a/dout
+  trig_lvl_b_i /trig_lvl_b/dout
+  subtrig_lvl_a_i /subtrig_lvl_a/dout
+  subtrig_lvl_b_i /subtrig_lvl_b/dout
+  pps_i pps_0/pps_o
+  clk_cnt_pps_i pps_0/clk_cnt_pps_o
+  temp_i /reg_temp/dout
+  pressure_i /reg_pressure/dout
+  time_i /reg_time/dout
+  date_i /reg_date/dout
+  latitude_i /reg_latitude/dout
+  longitude_i /reg_longitude/dout
+  altitude_i  /reg_altitude/dout 
+  satellites_i /reg_satellite/dout     
+  scaler_a_i /reg_trig_scaler_a/dout
+  scaler_b_i /reg_trig_scaler_b/dout
+}
+
+# Create the tlast generator
+cell labdpr:user:axis_tlast_gen tlast_gen_0 {
+  AXIS_TDATA_WIDTH 32
+  PKT_CNTR_BITS 32
+} {
+  S_AXIS trigger_0/M_AXIS
+  aclk /pll_0/clk_out1
+  aresetn /reset_1/Dout
+}
+
+# Create axis_dwidth_converter
+cell xilinx.com:ip:axis_dwidth_converter conv_0 {
+  S_TDATA_NUM_BYTES.VALUE_SRC USER
+  S_TDATA_NUM_BYTES 4
+  M_TDATA_NUM_BYTES 8
+} {
+  S_AXIS tlast_gen_0/M_AXIS
+  aclk /pll_0/clk_out1
+  aresetn /reset_2/Dout
+}
+
+# Create axis_ram_writer
+cell labdpr:user:axis_ram_writer writer_0 {
+  ADDR_WIDTH 20
+  AXI_ID_WIDTH 3
+} {
+  aclk /pll_0/clk_out1
+  aresetn /reset_2/Dout
+  S_AXIS conv_0/M_AXIS
+  M_AXI /ps_0/S_AXI_ACP
+}
+
diff --git a/projects/lago_v1_3/block_design.tcl b/projects/lago_v1_3/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..e07ae62578b774f135b35c15d3583ecfeec2d830
--- /dev/null
+++ b/projects/lago_v1_3/block_design.tcl
@@ -0,0 +1,336 @@
+source projects/base_system/block_design.tcl
+
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+#Enable interrupts
+set_property -dict [list CONFIG.PCW_USE_FABRIC_INTERRUPT {1} CONFIG.PCW_IRQ_F2P_INTR {1}] [get_bd_cells ps_0]
+
+# Delete input/output port
+delete_bd_objs [get_bd_ports exp_p_tri_io]
+delete_bd_objs [get_bd_ports exp_n_tri_io]
+
+# Create input port
+create_bd_port -dir I -from 7 -to 7 exp_n_tri_io
+create_bd_port -dir O -from 7 -to 7 exp_p_tri_io
+create_bd_port -dir I -from 0 -to 0 ext_resetn
+
+# Create axis_rp_adc
+cell labdpr:user:axis_rp_adc adc_0 {
+  ADC_DATA_WIDTH 14
+} {
+  aclk pll_0/clk_out1
+  adc_dat_a adc_dat_a_i
+  adc_dat_b adc_dat_b_i
+  adc_csn adc_csn_o
+}
+
+# Create axi_cfg_register
+cell labdpr:user:axi_cfg_register cfg_0 {
+  CFG_DATA_WIDTH 1024
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+}
+
+#Create concatenator
+cell xilinx.com:ip:xlconcat concat_0 {
+  NUM_PORTS 6
+} {
+  dout led_o
+}
+
+#Create concatenator
+cell xilinx.com:ip:xlconcat concat_1 {
+  NUM_PORTS 4
+} {
+  dout dac_pwm_o
+}
+
+# Create axi_intc
+cell xilinx.com:ip:axi_intc axi_intc_0 {
+  C_IRQ_CONNECTION 1
+  C_S_AXI_ACLK_FREQ_MHZ 125.0
+  C_PROCESSOR_CLK_FREQ_MHZ 125.0
+} {
+  irq ps_0/IRQ_F2P
+}
+
+# Create axi_sts_register
+cell labdpr:user:axi_sts_register sts_0 {
+  STS_DATA_WIDTH 32
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+} { }
+
+# Create xlslice for reset fifo, pps_gen and trigger modules. off=0
+cell labdpr:user:port_slicer reset_0 {
+  DIN_WIDTH 1024 DIN_FROM 0 DIN_TO 0
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for reset tlast_gen. off=0
+cell labdpr:user:port_slicer reset_1 {
+  DIN_WIDTH 1024 DIN_FROM 1 DIN_TO 1
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for reset conv_0 and writer_0. off=0
+cell labdpr:user:port_slicer reset_2 {
+  DIN_WIDTH 1024 DIN_FROM 2 DIN_TO 2
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the # of samples to get. off=1
+cell labdpr:user:port_slicer nsamples {
+  DIN_WIDTH 1024 DIN_FROM 63 DIN_TO 32
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the trigger_lvl_a. off=2
+cell labdpr:user:port_slicer trig_lvl_a {
+  DIN_WIDTH 1024 DIN_FROM 95 DIN_TO 64
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the trigger_lvl_b. off=3
+cell labdpr:user:port_slicer trig_lvl_b {
+  DIN_WIDTH 1024 DIN_FROM 127 DIN_TO 96
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the subtrigger_lvl_a. off=4
+cell labdpr:user:port_slicer subtrig_lvl_a {
+  DIN_WIDTH 1024 DIN_FROM 159 DIN_TO 128
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the subtrigger_lvl_b. off=5
+cell labdpr:user:port_slicer subtrig_lvl_b {
+  DIN_WIDTH 1024 DIN_FROM 191 DIN_TO 160
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the temperature data. off=6
+cell labdpr:user:port_slicer reg_temp {
+  DIN_WIDTH 1024 DIN_FROM 223 DIN_TO 192
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the pressure data. off=7
+cell labdpr:user:port_slicer reg_pressure {
+  DIN_WIDTH 1024 DIN_FROM 255 DIN_TO 224
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the time data. off=8
+cell labdpr:user:port_slicer reg_time {
+  DIN_WIDTH 1024 DIN_FROM 287 DIN_TO 256
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the date data. off=9
+cell labdpr:user:port_slicer reg_date {
+  DIN_WIDTH 1024 DIN_FROM 319 DIN_TO 288
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the latitude data. off=10
+cell labdpr:user:port_slicer reg_latitude {
+  DIN_WIDTH 1024 DIN_FROM 351 DIN_TO 320
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the longitude data. off=11
+cell labdpr:user:port_slicer reg_longitude {
+  DIN_WIDTH 1024 DIN_FROM 383 DIN_TO 352
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the altitude data. off=12
+cell labdpr:user:port_slicer reg_altitude {
+  DIN_WIDTH 1024 DIN_FROM 415 DIN_TO 384
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the satellite data. off=13
+cell labdpr:user:port_slicer reg_satellite {
+  DIN_WIDTH 1024 DIN_FROM 447 DIN_TO 416
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the trigger scaler a. off=14
+cell labdpr:user:port_slicer reg_trig_scaler_a {
+  DIN_WIDTH 1024 DIN_FROM 479 DIN_TO 448
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for the trigger scaler b. off=15
+cell labdpr:user:port_slicer reg_trig_scaler_b {
+  DIN_WIDTH 1024 DIN_FROM 511 DIN_TO 480
+} {
+  din cfg_0/cfg_data
+}
+
+# Create port_slicer for cfg RAM writer. off=22
+cell labdpr:user:port_slicer cfg_ram_wr {
+  DIN_WIDTH 1024 DIN_FROM 735 DIN_TO 704
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice for set the gpsen_i input
+cell labdpr:user:port_slicer gpsen {
+  DIN_WIDTH 1024 DIN_FROM 4 DIN_TO 4
+} {
+  din cfg_0/cfg_data
+}
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_1 {} {
+  slowest_sync_clk pll_0/clk_out1
+  dcm_locked pll_0/locked
+  ext_reset_in ext_resetn
+}
+
+module fadc_0 {
+  source projects/lago_v1_3/adc.tcl
+} {
+  writer_0/sts_data sts_0/sts_data 
+  pps_0/resetn_i rst_1/peripheral_aresetn 
+  pps_0/int_o axi_intc_0/intr
+	writer_0/M_AXI ps_0/S_AXI_ACP
+	writer_0/cfg_data cfg_ram_wr/dout
+	tlast_gen_0/pkt_length nsamples/dout
+	pps_0/gpsen_i gpsen/dout
+  pps_0/pps_i exp_n_tri_io
+  pps_0/pps_sig_o exp_p_tri_io
+  pps_0/pps_gps_led_o concat_0/In0
+  pps_0/false_pps_led_o concat_0/In1
+}
+
+#Now all related to the DAC PWM
+# Create xlslice. off=0
+cell labdpr:user:port_slicer reset_3 {
+  DIN_WIDTH 1024 DIN_FROM 3 DIN_TO 3
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice. off=16
+cell labdpr:user:port_slicer cfg_dac_pwm_0 {
+  DIN_WIDTH 1024 DIN_FROM 543 DIN_TO 512
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice.. off=17
+cell labdpr:user:port_slicer cfg_dac_pwm_1 {
+  DIN_WIDTH 1024 DIN_FROM 575 DIN_TO 544
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice.. off=18
+cell labdpr:user:port_slicer cfg_dac_pwm_2 {
+  DIN_WIDTH 1024 DIN_FROM 607 DIN_TO 576
+} {
+  din cfg_0/cfg_data
+}
+
+# Create xlslice.. off=19
+cell labdpr:user:port_slicer cfg_dac_pwm_3 {
+  DIN_WIDTH 1024 DIN_FROM 639 DIN_TO 608
+} {
+  din cfg_0/cfg_data
+}
+
+module slow_dac_0 {
+  source projects/lago_v1_3/slow_dac.tcl
+} {
+	gen_0/pwm_o	concat_1/In0
+	gen_0/led_o concat_0/In2
+	gen_0/data_i cfg_dac_pwm_0/Dout
+	gen_1/pwm_o	concat_1/In1
+	gen_1/led_o concat_0/In3
+	gen_1/data_i cfg_dac_pwm_1/Dout
+	gen_2/pwm_o	concat_1/In2
+	gen_2/led_o concat_0/In4
+	gen_2/data_i cfg_dac_pwm_2/Dout
+	gen_3/pwm_o	concat_1/In3
+	gen_3/led_o concat_0/In5
+	gen_3/data_i cfg_dac_pwm_3/Dout
+}
+
+#XADC related
+# Create xadc
+cell xilinx.com:ip:xadc_wiz xadc_wiz_0 {
+	DCLK_FREQUENCY 125
+	ADC_CONVERSION_RATE 500
+  XADC_STARUP_SELECTION channel_sequencer
+	CHANNEL_AVERAGING 64
+  OT_ALARM false
+  USER_TEMP_ALARM false
+  VCCINT_ALARM false
+  VCCAUX_ALARM false
+  ENABLE_VCCPINT_ALARM false
+  ENABLE_VCCPAUX_ALARM false
+  ENABLE_VCCDDRO_ALARM false
+  CHANNEL_ENABLE_CALIBRATION true
+  CHANNEL_ENABLE_TEMPERATURE true
+  CHANNEL_ENABLE_VCCINT true
+  CHANNEL_ENABLE_VP_VN true
+  CHANNEL_ENABLE_VAUXP0_VAUXN0 true
+  CHANNEL_ENABLE_VAUXP1_VAUXN1 true
+  CHANNEL_ENABLE_VAUXP8_VAUXN8 true
+  CHANNEL_ENABLE_VAUXP9_VAUXN9 true
+  AVERAGE_ENABLE_VP_VN true
+  AVERAGE_ENABLE_VAUXP0_VAUXN0 true
+  AVERAGE_ENABLE_VAUXP1_VAUXN1 true
+  AVERAGE_ENABLE_VAUXP8_VAUXN8 true
+  AVERAGE_ENABLE_VAUXP9_VAUXN9 true
+  AVERAGE_ENABLE_TEMPERATURE true
+  AVERAGE_ENABLE_VCCINT true
+  EXTERNAL_MUX_CHANNEL VP_VN
+  SINGLE_CHANNEL_SELECTION TEMPERATURE
+} {}
+
+connect_bd_intf_net [get_bd_intf_ports Vp_Vn] [get_bd_intf_pins xadc_wiz_0/Vp_Vn]
+connect_bd_intf_net [get_bd_intf_ports Vaux0] [get_bd_intf_pins xadc_wiz_0/Vaux0]
+connect_bd_intf_net [get_bd_intf_ports Vaux1] [get_bd_intf_pins xadc_wiz_0/Vaux1]
+connect_bd_intf_net [get_bd_intf_ports Vaux8] [get_bd_intf_pins xadc_wiz_0/Vaux8]
+connect_bd_intf_net [get_bd_intf_ports Vaux9] [get_bd_intf_pins xadc_wiz_0/Vaux9]
+
+addr 0x40000000 4K axi_intc_0/S_AXI /ps_0/M_AXI_GP0
+
+addr 0x40001000 4K cfg_0/S_AXI /ps_0/M_AXI_GP0
+
+addr 0x40002000 4K sts_0/S_AXI /ps_0/M_AXI_GP0
+
+addr 0x40003000 4K xadc_wiz_0/s_axi_lite /ps_0/M_AXI_GP0
+
+
+group_bd_cells PS7 [get_bd_cells rst_0] [get_bd_cells rst_1] [get_bd_cells pll_0] [get_bd_cells const_0] [get_bd_cells ps_0] [get_bd_cells ps_0_axi_periph]
+
diff --git a/projects/lago_v1_3/ports.xdc b/projects/lago_v1_3/ports.xdc
new file mode 100644
index 0000000000000000000000000000000000000000..ff256d11c022b18c3865e2caec0b33af40abd6f5
--- /dev/null
+++ b/projects/lago_v1_3/ports.xdc
@@ -0,0 +1,7 @@
+set_property IOSTANDARD LVCMOS33 [get_ports {ext_resetn}]
+set_property SLEW FAST [get_ports {ext_resetn}]
+set_property DRIVE 8 [get_ports {ext_resetn}]
+set_property PULLTYPE PULLUP [get_ports {ext_resetn}]
+
+set_property PACKAGE_PIN J16 [get_ports {ext_resetn}]
+
diff --git a/projects/lago_v1_3/slow_dac.tcl b/projects/lago_v1_3/slow_dac.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..03ac194549e07eac3671f99b10e12af12460f9a6
--- /dev/null
+++ b/projects/lago_v1_3/slow_dac.tcl
@@ -0,0 +1,40 @@
+#Create PWM generator
+cell labdpr:user:ramp_gen:1.0 gen_0 {
+  COUNT_NBITS 20
+  COUNT_MOD 5000
+  DATA_BITS 16
+} {
+	aclk /pll_0/clk_out1
+  aresetn /reset_3/Dout
+}
+
+#Create PWM generator
+cell labdpr:user:ramp_gen:1.0 gen_1 {
+  COUNT_NBITS 20
+  COUNT_MOD 5000
+  DATA_BITS 16
+} {
+	aclk /pll_0/clk_out1
+  aresetn /reset_3/Dout
+}
+
+#Create PWM generator
+cell labdpr:user:ramp_gen:1.0 gen_2 {
+  COUNT_NBITS 20
+  COUNT_MOD 5000
+  DATA_BITS 16
+} {
+	aclk /pll_0/clk_out1
+  aresetn /reset_3/Dout
+}
+
+#Create PWM generator
+cell labdpr:user:ramp_gen:1.0 gen_3 {
+  COUNT_NBITS 20
+  COUNT_MOD 5000
+  DATA_BITS 16
+} {
+	aclk /pll_0/clk_out1
+  aresetn /reset_3/Dout
+}
+
diff --git a/projects/lago_v1_3/src/Makefile b/projects/lago_v1_3/src/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d9b4e5552811e84ccd2b0acc75a8fa438eed4161
--- /dev/null
+++ b/projects/lago_v1_3/src/Makefile
@@ -0,0 +1,16 @@
+CC=gcc
+FLAGS=-Wall -O3 -li2c
+ARCH=arm
+CROSS_COMPILE=arm-xilinx-linux-gnueabi-
+
+####
+PROG=lago
+EXTRA=uart_rp.c nmea_rp.c gps_rp.c zynq_io.c bmp180.c
+
+all: $(PROG)
+
+$(PROG): $(PROG).c $(EXTRA) 
+	$(CC) $(FLAGS) -o $(PROG) $(PROG).c $(EXTRA) -lm -lpthread
+
+clean:
+	rm -f $(PROG)
diff --git a/projects/lago_v1_3/src/bmp180.c b/projects/lago_v1_3/src/bmp180.c
new file mode 100644
index 0000000000000000000000000000000000000000..99f3323e9d5df8a586793ad052bd81755b181b42
--- /dev/null
+++ b/projects/lago_v1_3/src/bmp180.c
@@ -0,0 +1,366 @@
+#include "bmp180.h"
+
+/* Lookup table for BMP180 register addresses */
+int32_t bmp180_register_table[11][2] = 
+{
+    {BMP180_REG_AC1_H, 1},
+    {BMP180_REG_AC2_H, 1},
+    {BMP180_REG_AC3_H, 1},
+    {BMP180_REG_AC4_H, 0},
+    {BMP180_REG_AC5_H, 0},
+    {BMP180_REG_AC6_H, 0},
+    {BMP180_REG_B1_H, 1},
+    {BMP180_REG_B2_H, 1},
+    {BMP180_REG_MB_H, 1},
+    {BMP180_REG_MC_H, 1},
+    {BMP180_REG_MD_H, 1}
+};
+
+/*
+ * Returns the raw measured temperature value of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ */
+static int32_t bmp180_read_raw_temperature(void *_bmp) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	i2c_smbus_write_byte_data(bmp->file, BMP180_CTRL, BMP180_TMP_READ_CMD);
+
+	usleep(BMP180_TMP_READ_WAIT_US);
+	int32_t data = i2c_smbus_read_word_data(bmp->file, BMP180_REG_TMP) & 0xFFFF;
+	
+	data = ((data << 8) & 0xFF00) + (data >> 8);
+	
+	return data;
+}
+
+/*
+ * Returns the raw measured pressure value of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ */
+static int32_t bmp180_read_raw_pressure(void *_bmp, uint8_t oss) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	uint16_t wait;
+	uint8_t cmd;
+	
+	switch(oss) {
+		case BMP180_PRE_OSS1:
+			wait = BMP180_PRE_OSS1_WAIT_US; cmd = BMP180_PRE_OSS1_CMD;
+			break;
+		
+		case BMP180_PRE_OSS2:
+			wait = BMP180_PRE_OSS2_WAIT_US; cmd = BMP180_PRE_OSS2_CMD;
+			break;
+		
+		case BMP180_PRE_OSS3:
+			wait = BMP180_PRE_OSS3_WAIT_US; cmd = BMP180_PRE_OSS3_CMD;
+			break;
+		
+		case BMP180_PRE_OSS0:
+		default:
+			wait = BMP180_PRE_OSS0_WAIT_US; cmd = BMP180_PRE_OSS0_CMD;
+			break;
+	}
+	
+	i2c_smbus_write_byte_data(bmp->file, BMP180_CTRL, cmd);
+
+	usleep(wait);
+	
+	int32_t msb, lsb, xlsb, data;
+	msb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE) & 0xFF;
+	lsb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE+1) & 0xFF;
+	xlsb = i2c_smbus_read_byte_data(bmp->file, BMP180_REG_PRE+2) & 0xFF;
+	
+	data = ((msb << 16)  + (lsb << 8)  + xlsb) >> (8 - bmp->oss);
+	
+	return data;
+}
+
+/**
+ * Returns the measured pressure in pascal.
+ * 
+ * @param bmp180 sensor
+ * @return pressure
+ */
+float bmp180_pressure(void *_bmp) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	long UT, UP, B6, B5, X1, X2, X3, B3, p;
+	unsigned long B4, B7;
+	
+	UT = bmp180_read_raw_temperature(_bmp);
+	UP = bmp180_read_raw_pressure(_bmp, bmp->oss);
+	
+	X1 = ((UT - bmp->ac6) * bmp->ac5) >> 15;
+	X2 = (bmp->mc << 11) / (X1 + bmp->md);
+	
+	B5 = X1 + X2;
+	
+	B6 = B5 - 4000;
+	
+	X1 = (bmp->b2 * (B6 * B6) >> 12) >> 11;
+	X2 = (bmp->ac2 * B6) >> 11;
+	X3 = X1 + X2;
+	
+	B3 = ((((bmp->ac1 * 4) + X3) << bmp->oss) + 2) / 4;
+	X1 = (bmp->ac3 * B6) >> 13;
+	X2 = (bmp->b1 * ((B6 * B6) >> 12)) >> 16;
+	X3 = ((X1 + X2) + 2) >> 2;
+	
+	
+	B4 = bmp->ac4 * (unsigned long)(X3 + 32768) >> 15;
+	B7 = ((unsigned long) UP - B3) * (50000 >> bmp->oss);
+	
+	if(B7 < 0x80000000) {
+		p = (B7 * 2) / B4;
+	} else {
+		p = (B7 / B4) * 2;
+	}
+	
+	X1 = (p >> 8) * (p >> 8);
+	X1 = (X1 * 3038) >> 16;
+	X2 = (-7357 * p) >> 16;
+	p = p + ((X1 + X2 + 3791) >> 4);
+	
+	return p;
+}
+
+/*
+ * Sets the address for the i2c device file.
+ * 
+ * @param bmp180 sensor
+ */
+static int bmp180_set_addr(void *_bmp) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	int error;
+
+	if((error = ioctl(bmp->file, I2C_SLAVE, bmp->address)) < 0) {
+		DEBUG("error: ioctl() failed\n");
+	}
+
+	return error;
+}
+
+/*
+ * Frees allocated memory in the init function.
+ * 
+ * @param bmp180 sensor
+ */
+static void bmp180_init_error_cleanup(void *_bmp) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	
+	if(bmp->i2c_device != NULL) {
+		free(bmp->i2c_device);
+		bmp->i2c_device = NULL;
+	}
+	
+	free(bmp);
+	bmp = NULL;
+}
+
+/*
+ * Reads a single calibration coefficient from the BMP180 eprom.
+ * 
+ * @param bmp180 sensor
+ */
+static void bmp180_read_eprom_reg(void *_bmp, int32_t *_store, uint8_t reg, int32_t sign) 
+{
+	bmp180_t *bmp = TO_BMP(_bmp);
+	int32_t data = i2c_smbus_read_word_data(bmp->file, reg) & 0xFFFF;
+	
+	// i2c_smbus_read_word_data assumes little endian 
+	// but ARM uses big endian. Thus the ordering of the bytes is reversed.
+	// data = 	 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15   bit position
+	//          |      lsb      |          msb        |  
+	
+	//                 msb           +     lsb
+	*_store = ((data << 8) & 0xFF00) + (data >> 8);
+	
+	if(sign && (*_store > 32767)) {
+		*_store -= 65536;
+	}
+}
+
+/*
+ * Reads the eprom of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ */
+void bmp180_read_eprom(void *_bmp) 
+{
+	bmp180_t *bmp = TO_BMP(_bmp);	
+	
+	int32_t *bmp180_register_addr[11] = {
+		&bmp->ac1, &bmp->ac2, &bmp->ac3, &bmp->ac4, &bmp->ac5, &bmp->ac6,
+		&bmp->b1, &bmp->b2, &bmp->mb, &bmp->mc, &bmp->md
+	};
+	
+	uint8_t sign, reg;
+	int32_t *data;
+	int i;
+	for(i = 0; i < 11; i++) {
+		reg = (uint8_t) bmp180_register_table[i][0];
+		sign = (uint8_t) bmp180_register_table[i][1];
+		data = bmp180_register_addr[i];
+		bmp180_read_eprom_reg(_bmp, data, reg, sign);
+	}
+}
+
+/**
+ * Dumps the eprom values of this BMP180 sensor.
+ * 
+ * @param bmp180 sensor
+ * @param bmp180 eprom struct
+ */
+void bmp180_dump_eprom(void *_bmp, bmp180_eprom_t *eprom) 
+{
+	bmp180_t *bmp = TO_BMP(_bmp);
+	eprom->ac1 = bmp->ac1;
+	eprom->ac2 = bmp->ac2;
+	eprom->ac3 = bmp->ac3;
+	eprom->ac4 = bmp->ac4;
+	eprom->ac5 = bmp->ac5;
+	eprom->ac6 = bmp->ac6;
+	eprom->b1 = bmp->b1;
+	eprom->b2 = bmp->b2;
+	eprom->mb = bmp->mb;
+	eprom->mc = bmp->mc;
+	eprom->md = bmp->md;
+}
+
+/**
+ * Creates a BMP180 sensor object.
+ *
+ * @param i2c device address
+ * @param i2c device file path
+ * @return bmp180 sensor
+ */
+void *bmp180_init(int address, const char* i2c_device_filepath) 
+{
+	DEBUG("device: init using address %#x and i2cbus %s\n", address, i2c_device_filepath);
+	
+	// setup BMP180
+	void *_bmp = malloc(sizeof(bmp180_t));
+	if(_bmp == NULL)  {
+		DEBUG("error: malloc returns NULL pointer\n");
+		return NULL;
+	}
+
+	bmp180_t *bmp = TO_BMP(_bmp);
+	bmp->address = address;
+
+	// setup i2c device path
+	bmp->i2c_device = (char*) malloc(strlen(i2c_device_filepath) * sizeof(char));
+	if(bmp->i2c_device == NULL) {
+		DEBUG("error: malloc returns NULL pointer!\n");
+		bmp180_init_error_cleanup(bmp);
+		return NULL;
+	}
+
+	// copy string
+	strcpy(bmp->i2c_device, i2c_device_filepath);
+	
+	// open i2c device
+	int file;
+	if((file = open(bmp->i2c_device, O_RDWR)) < 0) {
+		DEBUG("error: %s open() failed\n", bmp->i2c_device);
+		bmp180_init_error_cleanup(bmp);
+		return NULL;
+	}
+	bmp->file = file;
+
+	// set i2c device address
+	if(bmp180_set_addr(_bmp) < 0) {
+		bmp180_init_error_cleanup(bmp);
+		return NULL;
+	}
+
+	// setup i2c device
+	bmp180_read_eprom(_bmp);
+	bmp->oss = 0;
+	
+	DEBUG("device: open ok\n");
+
+	return _bmp;
+}
+
+/**
+ * Closes a BMP180 object.
+ * 
+ * @param bmp180 sensor
+ */
+void bmp180_close(void *_bmp) 
+{
+	if(_bmp == NULL) {
+		return;
+	}
+	
+	DEBUG("close bmp180 device\n");
+	bmp180_t *bmp = TO_BMP(_bmp);
+	
+	if(close(bmp->file) < 0) {
+		DEBUG("error: %s close() failed\n", bmp->i2c_device);
+	}
+	
+	free(bmp->i2c_device); // free string
+	bmp->i2c_device = NULL;
+	free(bmp); // free bmp structure
+	_bmp = NULL;
+} 
+
+/**
+ * Returns the measured temperature in celsius.
+ * 
+ * @param bmp180 sensor
+ * @return temperature
+ */
+float bmp180_temperature(void *_bmp) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	long UT, X1, X2, B5;
+	float T;
+	
+	UT = bmp180_read_raw_temperature(_bmp);
+	
+	DEBUG("UT=%lu\n",UT);
+	
+	X1 = ((UT - bmp->ac6) * bmp->ac5) >> 15;
+	X2 = (bmp->mc << 11) / (X1 + bmp->md);
+	B5 = X1 + X2;
+	T = ((B5 + 8) >> 4) / 10.0;
+	
+	return T;
+}
+
+/**
+ * Returns altitude in meters based on the measured pressure 
+ * and temperature of this sensor.
+ * 
+ * @param bmp180 sensor
+ * @return altitude
+ */
+float bmp180_altitude(void *_bmp) 
+{
+	float p, alt;
+	p = bmp180_pressure(_bmp);
+	alt = 44330 * (1 - pow(( (p/100) / BMP180_SEA_LEVEL),1/5.255));
+	
+	return alt;
+}
+
+/**
+ * Sets the oversampling setting for this sensor.
+ * 
+ * @param bmp180 sensor
+ * @param oversampling mode
+ */
+void bmp180_set_oss(void *_bmp, int oss) 
+{
+	bmp180_t* bmp = TO_BMP(_bmp);
+	bmp->oss = oss;
+}
+
diff --git a/projects/lago_v1_3/src/bmp180.h b/projects/lago_v1_3/src/bmp180.h
new file mode 100644
index 0000000000000000000000000000000000000000..ecaaab8dfbd37825238eb31c05e57073fff3d1c4
--- /dev/null
+++ b/projects/lago_v1_3/src/bmp180.h
@@ -0,0 +1,142 @@
+#ifndef __BMP180__
+#define __BMP180__
+
+#include <string.h> 
+#include <stdlib.h> 
+#include <fcntl.h> 
+#include <sys/ioctl.h>
+#include <i2c/smbus.h> 
+#include <linux/i2c-dev.h> 
+#include <math.h> 
+#include<unistd.h>
+#include<inttypes.h>
+
+#define BMP180_PRE_OSS0 0 // ultra low power
+#define BMP180_PRE_OSS1 1 // standard
+#define BMP180_PRE_OSS2 2 // high resolution
+#define BMP180_PRE_OSS3 3 // ultra high resoultion
+
+/* AC register */
+#define BMP180_REG_AC1_H 0xAA
+#define BMP180_REG_AC2_H 0xAC
+#define BMP180_REG_AC3_H 0xAE
+#define BMP180_REG_AC4_H 0xB0
+#define BMP180_REG_AC5_H 0xB2
+#define BMP180_REG_AC6_H 0xB4
+
+/* B1 register */
+#define BMP180_REG_B1_H 0xB6
+
+/* B2 register */
+#define BMP180_REG_B2_H 0xB8
+
+/* MB register */
+#define BMP180_REG_MB_H 0xBA
+
+/* MC register */
+#define BMP180_REG_MC_H 0xBC
+
+/* MD register */
+#define BMP180_REG_MD_H 0xBE
+
+/* AC register */
+#define BMP180_CTRL 0xF4
+
+/* Temperature register */
+#define BMP180_REG_TMP 0xF6
+
+/* Pressure register */
+#define BMP180_REG_PRE 0xF6
+
+/* Temperature read command */
+#define BMP180_TMP_READ_CMD 0x2E
+
+/* Waiting time in us for reading temperature values */
+#define BMP180_TMP_READ_WAIT_US 5000
+
+/* Pressure oversampling modes */
+#define BMP180_PRE_OSS0 0 // ultra low power
+#define BMP180_PRE_OSS1 1 // standard
+#define BMP180_PRE_OSS2 2 // high resolution
+#define BMP180_PRE_OSS3 3 // ultra high resoultion
+
+/* Pressure read commands */
+#define BMP180_PRE_OSS0_CMD 0x34
+#define BMP180_PRE_OSS1_CMD 0x74
+#define BMP180_PRE_OSS2_CMD 0xB4
+#define BMP180_PRE_OSS3_CMD 0xF4
+
+/* Waiting times in us for reading pressure values */
+#define BMP180_PRE_OSS0_WAIT_US 5000
+#define BMP180_PRE_OSS1_WAIT_US 8000
+#define BMP180_PRE_OSS2_WAIT_US 14000
+#define BMP180_PRE_OSS3_WAIT_US 26000
+
+/* Average sea-level pressure in hPa */
+#define BMP180_SEA_LEVEL 1013.25
+
+/* Define debug function. */
+//#define __BMP180_DEBUG__
+#ifdef __BMP180_DEBUG__
+#define DEBUG(...)  printf(__VA_ARGS__)
+#else
+#define DEBUG(...)
+#endif
+
+/* Shortcut to cast void pointer to a bmp180_t pointer */
+#define TO_BMP(x) (bmp180_t*) x
+
+/* Basic structure for the bmp180 sensor */
+typedef struct {
+				/* file descriptor */
+				int file;
+				/* i2c device address */
+				int address;
+				/* BMP180 oversampling mode */
+				int oss;
+				/* i2c device file path */
+				char *i2c_device;
+				/* Eprom values */
+				int32_t ac1;
+				int32_t ac2;
+				int32_t ac3;
+				int32_t ac4;
+				int32_t ac5;
+				int32_t ac6;
+				int32_t b1;
+				int32_t b2;
+				int32_t mb;
+				int32_t mc;
+				int32_t md;
+} bmp180_t;
+
+
+/* Lookup table for BMP180 register addresses */
+extern int32_t bmp180_register_table[11][2];
+
+typedef struct {
+				/* Eprom values */
+				int ac1;
+				int ac2;
+				int ac3;
+				int ac4;
+				int ac5;
+				int ac6;
+				int b1;
+				int b2;
+				int mb;
+				int mc;
+				int md;
+} bmp180_eprom_t;
+
+/* Prototypes for helper functions */
+void bmp180_read_eprom(void *_bmp);
+void *bmp180_init(int address, const char* i2c_device_filepath);
+void bmp180_close(void *_bmp);
+void bmp180_set_oss(void *_bmp, int oss);
+float bmp180_pressure(void *_bmp);
+float bmp180_temperature(void *_bmp);
+float bmp180_altitude(void *_bmp);
+void bmp180_dump_eprom(void *_bmp, bmp180_eprom_t *eprom);
+
+#endif
diff --git a/projects/lago_v1_3/src/defs.h b/projects/lago_v1_3/src/defs.h
new file mode 100644
index 0000000000000000000000000000000000000000..104ff7078f07d06663424fda158256f8b6c4d444
--- /dev/null
+++ b/projects/lago_v1_3/src/defs.h
@@ -0,0 +1,136 @@
+#define  _CRT_SECURE_NO_WARNINGS
+
+#define _FILE_OFFSET_BITS  64
+
+#ifndef EXP
+#define EXP "LAGO"
+#endif
+
+/* Output format version */
+#define DATAVERSION 			5
+#define VERSION 				2
+#define REVISION	 			1
+
+#define MAXCHRLEN 				1024
+#define BLOCKSIZE				16384
+#define MAXFILENAMELEN			255
+#define MAXPRESS 				1100 //1100Hpa
+#define PRESSUREBLOCKSIZE		22
+#define GPSBLOCKSIZE 			64
+
+#define XIL_AXI_INTC_BASEADDR 0x40000000
+#define XIL_AXI_INTC_HIGHADDR 0x40000FFF
+
+#define XIL_AXI_INTC_ISR_OFFSET    0x0
+#define XIL_AXI_INTC_IPR_OFFSET    0x4
+#define XIL_AXI_INTC_IER_OFFSET    0x8
+#define XIL_AXI_INTC_IAR_OFFSET    0xC
+#define XIL_AXI_INTC_SIE_OFFSET    0x10
+#define XIL_AXI_INTC_CIE_OFFSET    0x14
+#define XIL_AXI_INTC_IVR_OFFSET    0x18
+#define XIL_AXI_INTC_MER_OFFSET    0x1C
+#define XIL_AXI_INTC_IMR_OFFSET    0x20
+#define XIL_AXI_INTC_ILR_OFFSET    0x24
+#define XIL_AXI_INTC_IVAR_OFFSET   0x100
+
+#define XIL_AXI_INTC_MER_ME_MASK 0x00000001
+#define XIL_AXI_INTC_MER_HIE_MASK 0x00000002
+
+//CFG
+#define CFG_RESET_GRAL_OFFSET    0x0
+#define CFG_NSAMPLES_OFFSET      0x4
+#define CFG_TRLVL_1_OFFSET       0x8
+#define CFG_TRLVL_2_OFFSET       0xC
+#define CFG_STRLVL_1_OFFSET      0x10
+#define CFG_STRLVL_2_OFFSET      0x14
+#define CFG_TEMPERATURE_OFFSET   0x18
+#define CFG_PRESSURE_OFFSET      0x1C
+#define CFG_TIME_OFFSET          0x20
+#define CFG_LATITUDE_OFFSET      0x24
+#define CFG_LONGITUDE_OFFSET     0x28
+#define CFG_ALTITUDE_OFFSET      0x2C
+#define CFG_SATELLITE_OFFSET     0x30
+#define CFG_HV1_OFFSET           0x40
+#define CFG_HV2_OFFSET           0x44
+
+//CFG Slow DAC
+#define CFG_DAC_PWM0_OFFSET 0x40
+#define CFG_DAC_PWM1_OFFSET 0x44
+#define CFG_DAC_PWM2_OFFSET 0x48
+#define CFG_DAC_PWM3_OFFSET 0x4C
+
+#define ENBL_ALL_MASK         0xFFFFFFFF
+#define RST_ALL_MASK          0x00000000
+#define RST_PPS_TRG_FIFO_MASK 0x00000001
+#define RST_TLAST_GEN_MASK    0x00000002
+#define RST_WRITER_MASK       0x00000004
+#define RST_AO_MASK           0x00000008
+#define FGPS_EN_MASK          0x00000010
+
+//STS
+#define STS_STATUS_OFFSET     0x0
+
+//XADC
+#define XADC_SRR_OFFSET          0x0
+#define XADC_SR_OFFSET           0x4
+#define XADC_AOSR_OFFSET         0x8
+#define XADC_CONVSTR_OFFSET      0xC
+#define XADC_SYSMONRR_OFFSET     0x10
+#define XADC_GIER_OFFSET         0x5C
+#define XADC_IPISR_OFFSET        0x60
+#define XADC_IPIER_OFFSET        0x68
+#define XADC_TEMPERATURE_OFFSET  0x200
+#define XADC_VCCINT_OFFSET       0x204
+#define XADC_VCCAUX_OFFSET       0x208
+#define XADC_VPVN_OFFSET         0x20C
+#define XADC_VREFP_OFFSET        0x210
+#define XADC_VREFN_OFFSET        0x214
+#define XADC_VBRAM_OFFSET        0x218
+#define XADC_UNDEF_OFFSET        0x21C
+#define XADC_SPLYOFF_OFFSET      0x220
+#define XADC_ADCOFF_OFFSET       0x224
+#define XADC_GAIN_ERR_OFFSET     0x228
+#define XADC_ZDC_SPLY_OFFSET     0x234
+#define XADC_ZDC_AUX_SPLY_OFFSET 0x238
+#define XADC_ZDC_MEM_SPLY_OFFSET 0x23C
+#define XADC_VAUX_PN_0_OFFSET    0x240
+#define XADC_VAUX_PN_1_OFFSET    0x244
+#define XADC_VAUX_PN_2_OFFSET    0x248
+#define XADC_VAUX_PN_3_OFFSET    0x24C
+#define XADC_VAUX_PN_4_OFFSET    0x250
+#define XADC_VAUX_PN_5_OFFSET    0x254
+#define XADC_VAUX_PN_6_OFFSET    0x258
+#define XADC_VAUX_PN_7_OFFSET    0x25C
+#define XADC_VAUX_PN_8_OFFSET    0x260
+#define XADC_VAUX_PN_9_OFFSET    0x264
+#define XADC_VAUX_PN_10_OFFSET   0x268
+#define XADC_VAUX_PN_11_OFFSET   0x26C
+#define XADC_VAUX_PN_12_OFFSET   0x270
+#define XADC_VAUX_PN_13_OFFSET   0x274
+#define XADC_VAUX_PN_14_OFFSET   0x278
+#define XADC_VAUX_PN_15_OFFSET   0x27C
+
+#define XADC_AI0_OFFSET XADC_VAUX_PN_8_OFFSET
+#define XADC_AI1_OFFSET XADC_VAUX_PN_0_OFFSET
+#define XADC_AI2_OFFSET XADC_VAUX_PN_1_OFFSET
+#define XADC_AI3_OFFSET XADC_VAUX_PN_9_OFFSET
+
+#define XADC_CONV_VAL 0.00171191993362 //(A_ip/2^12)*(34.99/4.99)
+
+
+//#define XIL_AXI_INTC_IPISR_INT_OCCURED_MASK 0x00000001
+//#define XIL_AXI_INTC2_IPISR_INT_OCCURED_MASK  0x00000002
+//#define XIL_AXI_INTC_GIER_ENABLE_INT_MASK 0x80000000
+//
+//#define XIL_AXI_INTC_CSR_CASC_MASK    0x00000800
+//#define XIL_AXI_INTC_CSR_ENABLE_ALL_MASK  0x00000400
+//#define XIL_AXI_INTC_CSR_ENABLE_PWM_MASK  0x00000200
+//#define XIL_AXI_INTC_CSR_ENABLE_TMR_MASK  0x00000080
+//#define XIL_AXI_INTC_CSR_ENABLE_INT_MASK  0x00000040
+//#define XIL_AXI_INTC_CSR_LOAD_MASK    0x00000020
+//#define XIL_AXI_INTC_CSR_AUTO_RELOAD_MASK 0x00000010
+//#define XIL_AXI_INTC_CSR_EXT_CAPTURE_MASK 0x00000008
+//#define XIL_AXI_INTC_CSR_EXT_GENERATE_MASK  0x00000004
+//#define XIL_AXI_INTC_CSR_DOWN_COUNT_MASK  0x00000002
+//#define XIL_AXI_INTC_CSR_CAPTURE_MODE_MASK  0x00000001
+
diff --git a/projects/lago_v1_3/src/globaldefs.h b/projects/lago_v1_3/src/globaldefs.h
new file mode 100644
index 0000000000000000000000000000000000000000..33b3ac5ac8dcfd53ba594b6df1168f2f7480845d
--- /dev/null
+++ b/projects/lago_v1_3/src/globaldefs.h
@@ -0,0 +1,20 @@
+#define  _CRT_SECURE_NO_WARNINGS
+
+#define _FILE_OFFSET_BITS  64
+
+#ifndef EXP
+#define EXP "LAGO"
+#endif
+
+/* Output format version */
+#define DATAVERSION 		5
+#define VERSION 				2
+#define REVISION	 			0
+
+#define MAXCHRLEN 			1024
+#define BLOCKSIZE				16384
+#define MAXFILENAMELEN	255
+#define MAXPRESS 				1100 //1100Hpa
+#define PRESSUREBLOCKSIZE	22
+#define GPSBLOCKSIZE 			64
+
diff --git a/projects/lago_v1_3/src/gps_rp.c b/projects/lago_v1_3/src/gps_rp.c
new file mode 100644
index 0000000000000000000000000000000000000000..708a69158fc59d6ab23c3f0ccd1d747aae8534e9
--- /dev/null
+++ b/projects/lago_v1_3/src/gps_rp.c
@@ -0,0 +1,96 @@
+#include "gps_rp.h"
+
+static double gps_deg_dec(double deg_point)
+{
+  double ddeg;
+  double sec = modf(deg_point, &ddeg)*60;
+  int deg = (int)(ddeg/100);
+  int min = (int)(deg_point-(deg*100));
+
+  double absdlat = round(deg * 1000000.);
+  double absmlat = round(min * 1000000.);
+  double absslat = round(sec * 1000000.);
+
+  return round(absdlat + (absmlat/60) + (absslat/3600)) /1000000;
+}
+
+// Convert lat and lon to decimals (from deg)
+static void gps_convert_deg_to_dec(double *latitude, char ns,  double *longitude, char we)
+{
+  double lat = (ns == 'N') ? *latitude : -1 * (*latitude);
+  double lon = (we == 'E') ? *longitude : -1 * (*longitude);
+
+  *latitude = gps_deg_dec(lat);
+  *longitude = gps_deg_dec(lon);
+}
+
+void gps_init(void) 
+{
+  rp_UartInit();
+  rp_UartConfig();
+}
+
+void gps_on(void) 
+{
+}
+
+// Compute the GPS location using decimal scale
+void gps_location(loc_t *coord) 
+{
+  uint8_t status = _EMPTY;
+  while(status != _COMPLETED) {
+    gpgga_t gpgga;
+    gprmc_t gprmc;
+    char buffer[256];
+
+    rp_UartReadln(buffer, 256);
+    switch (rp_NmeaGetMessageType(buffer)) {
+      case NMEA_GPGGA:
+        rp_NmeaParseGpgga(buffer, &gpgga);
+
+        gps_convert_deg_to_dec(&(gpgga.latitude), gpgga.lat, &(gpgga.longitude), gpgga.lon);
+
+        coord->times = gpgga.times;
+        coord->latitude = gpgga.latitude;
+        coord->longitude = gpgga.longitude;
+        coord->altitude = gpgga.altitude;
+        coord->satellites = gpgga.satellites;
+
+        status |= NMEA_GPGGA;
+        break;
+      case NMEA_GPRMC:
+        rp_NmeaParseGprmc(buffer, &gprmc);
+
+        coord->speed = gprmc.speed;
+        coord->course = gprmc.course;
+        coord->date = gprmc.date;
+
+        status |= NMEA_GPRMC;
+        break;
+    }
+  }
+}
+
+void gps_off(void) 
+{
+  //Write off
+  rp_UartClose();
+}
+
+int gps_print_data()
+{
+        gps_init();
+
+        loc_t data;
+
+        gps_location(&data);
+
+        printf("Time      : %06d\n",(uint32_t)data.times);
+        printf("Date      : %06d\n",(uint32_t)data.date);
+        printf("Latitude  : %lf\n", data.latitude);
+        printf("Longitude : %lf\n", data.longitude);
+        printf("Altitude  : %.1lf\n", data.altitude);
+        printf("Satellites: %d\n", (uint32_t)data.satellites);
+
+        return 0;
+}
diff --git a/projects/lago_v1_3/src/gps_rp.h b/projects/lago_v1_3/src/gps_rp.h
new file mode 100644
index 0000000000000000000000000000000000000000..046a852a76dce31a715548532618217f124fed0d
--- /dev/null
+++ b/projects/lago_v1_3/src/gps_rp.h
@@ -0,0 +1,28 @@
+#ifndef _GPS_RP_H_
+#define _GPS_RP_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "nmea_rp.h"
+#include "uart_rp.h"
+
+typedef struct location {
+    double times;
+    double date;
+    double latitude;
+    double longitude;
+    double speed;
+    double altitude;
+    double course;
+    double satellites;
+} loc_t;
+
+void gps_init(void);
+void gps_on(void);
+void gps_location(loc_t *);
+void gps_off(void);
+int  gps_print_data(void);
+
+#endif
diff --git a/projects/lago_v1_3/src/lago.c b/projects/lago_v1_3/src/lago.c
new file mode 100644
index 0000000000000000000000000000000000000000..bb1bf3c8ee1cbacc245c00abad92c58345a48a7e
--- /dev/null
+++ b/projects/lago_v1_3/src/lago.c
@@ -0,0 +1,1000 @@
+#include "lago.h"
+
+//*****************************************************
+// Pressure, temperature and other constants
+//****************************************************
+double  gps_lat,gps_lon,gps_alt;
+
+//Globals
+int interrupted = 0;
+int n_dev;
+uint32_t reg_off;
+int32_t reg_val;
+//double r_val;
+int limit;
+int current;
+loc_t g_data;
+// detector rates
+int r1,r2;
+// timing horrible hack
+int hack=0;
+
+int fReadReg, fGetCfgStatus, fGetPT, fGetGPS, fGetXADC, fInitSystem, fWriteReg, 
+		fSetCfgReg, fToFile, fToStdout, fFile, fCount, fByte, fRegValue, fData, 
+		fFirstTime=1,	fshowversion;
+
+char charAction[MAXCHRLEN], scRegister[MAXCHRLEN], charReg[MAXCHRLEN],
+		 charFile[MAXCHRLEN], charCurrentFile[MAXCHRLEN], charCount[MAXCHRLEN],
+		 scByte[MAXCHRLEN], charRegValue[MAXCHRLEN], charCurrentMetaData[MAXCHRLEN];
+
+//FILE        *fhin = NULL;
+FILE         *fhout = NULL;
+FILE         *fhmtd = NULL;
+struct FLContext  *handle = NULL;
+
+#ifdef FUTURE
+unordered_map<string, string> hConfigs;
+#endif
+
+//****************************************************
+// Time globals for filenames
+//****************************************************
+time_t    fileTime;
+struct tm *fileDate;
+int       falseGPS=0;
+
+//****************************************************
+// Metadata
+//****************************************************
+// Metadata calculations, dataversion v5 need them
+// average rates and deviation per trigger condition
+// average baseline and deviation per channel
+// using long int as max_rate ~ 50 kHz * 3600 s = 1.8x10^7 ~ 2^(20.5)
+// and is even worst for baseline
+#define MTD_TRG   8
+#define MTD_BL    3
+#define MTD_BLBIN 1
+//daq time
+int mtd_seconds=0;
+// trigger rates
+long int mtd_rates[MTD_TRG], mtd_rates2[MTD_TRG];
+//base lines
+long int mtd_bl[MTD_BL], mtd_bl2[MTD_BL];
+int mtd_iBin=0;
+long int mtd_cbl=0;
+// deat time defined as the number of missing pulses over the total number
+// of triggers. We can determine missing pulses as the sum of the differences 
+// between consecutive pulses
+long int mtd_dp = 0, mtd_cdp = 0, mtd_pulse_cnt = 0, mtd_pulse_pnt = 0;
+// and finally, a vector of strings to handle configs file. I'm also including a
+// hash table
+// for future implementations. For now, we just dump the lago-configs file
+//vector <string> configs_lines;
+int position;
+int main(int argc, char *argv[])
+{
+	int rc;
+	//PT device
+	float t, p, alt, volt;
+	char *i2c_device = "/dev/i2c-0";
+	int address = 0x77;
+
+	void *bmp = bmp180_init(address, i2c_device);
+
+	bmp180_eprom_t eprom;
+	bmp180_dump_eprom(bmp, &eprom);
+
+
+	bmp180_set_oss(bmp, 1);
+	//end PT device
+
+	pthread_t not_gps;
+	//pthread_t actual_gps;
+
+	//Check the arguments
+	if (!parse_param(argc, argv)) {
+		show_usage(argv[0]);
+		return 1;
+	}
+
+	//initialize devices. TODO: add error checking 
+	intc_init();    
+	cfg_init();    
+	sts_init();    
+	xadc_init();
+	cma_init();
+	//printf("dev_size es: %d ...\n",dev_size);
+	//printf("Set writer address...\n");
+	rd_reg_value(1, CFG_WR_ADDR_OFFSET,0);
+	//printf("dev_size es: %d ...\n",dev_size);
+	wr_reg_value(1, CFG_WR_ADDR_OFFSET, dev_size,0);
+
+	//Check if it is the first time we access the PL
+	//This is for initial configuration
+	//default is MASTER mode, using false PPS
+	if (dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET) == 0) //first time access
+	{
+		printf("Initializing registers...\n");
+		init_system();
+		//FIXME: here i should initialise my thread for working with false PPS
+		rc = pthread_create(&not_gps,NULL,thread_isr_not_gps,NULL);
+		if (rc != EXIT_SUCCESS) {
+			perror("pthread_create :: error \n");
+			exit(EXIT_FAILURE);
+		}
+
+		enable_interrupt();
+	}
+
+	//Ckeck if we should use GPS data or PC data
+	/*				if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 0) //ok, we should use GPS data
+						{
+						rc = pthread_create(&actual_gps,NULL,thread_isr,NULL);
+						if (rc != EXIT_SUCCESS) {
+						perror("pthread_create :: error \n");
+						exit(EXIT_FAILURE);
+						}
+
+						enable_interrupt();
+						}*/
+
+	signal(SIGINT, signal_handler);
+
+	if(fReadReg) {
+		rd_reg_value(n_dev, reg_off,1);  // Read single register
+	}
+	else if (fWriteReg) {
+		wr_reg_value(n_dev, reg_off, reg_val, 1);  // Write single register
+	}
+	else if (fSetCfgReg) {
+		if (fRegValue) set_voltage(reg_off, atoi(charRegValue)); // For HV, OV
+		else wr_reg_value(1,reg_off, atoi(charRegValue), 1);        // For t1, t2, st1, st2  
+	}
+	else if (fGetCfgStatus) {
+		rd_cfg_status();        // Get registers status
+	}
+	else if (fGetPT) {
+		if(bmp != NULL){
+			//int i;
+			//for(i = 0; i < 10; i++) {
+			t = bmp180_temperature(bmp);
+			p = bmp180_pressure(bmp);
+			alt = bmp180_altitude(bmp);
+			// Temperature in Celsius, Presure in HectoPascal and Altitude in meters
+			printf("Temperature = %.1f, Pressure = %.2f, Altitude= %.1f\n", t, p/100., alt);
+			//usleep(2 * 1000 * 1000);
+			//}
+
+			bmp180_close(bmp);
+		}else{
+			printf("Error! NO BMP device is present!\n");
+		}
+	}
+	else if (fGetGPS) { 
+		if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // No GPS is present
+			printf("No GPS device is present or enabled!!!\n");
+		}
+		else{
+			gps_print_data();     // Print GPS data to stdout 
+		}		
+	}
+	else if (fInitSystem) {
+		printf("Initializing registers...\n");
+		init_system();
+	}
+	else if (fGetXADC) {
+		printf("Reading XADC channels...\n");
+		printf("Voltage CH1: %.3f\n",get_voltage(XADC_AI0_OFFSET));
+		printf("Voltage CH2: %.3f\n",get_voltage(XADC_AI1_OFFSET));
+		volt = get_voltage(XADC_AI2_OFFSET);
+		printf("Voltage CH3: %.3f V (%.1f V)\n",volt, (volt/0.0031949));
+		volt = get_voltage(XADC_AI3_OFFSET);
+		printf("Voltage CH4: %.3f V (%.1f V)\n",volt, (volt/0.0031949));
+		printf("Base temperature CH1: %.1f ºC\n",get_temp_AD592(XADC_AI0_OFFSET));
+		printf("Base temperature CH2: %.1f ºC\n",get_temp_AD592(XADC_AI1_OFFSET));
+
+	}
+	else if (fToFile || fToStdout) {
+
+		limit = 1024*1024; // whole memory
+		current = -2; // new readout system, hack due to using +4 for readout
+		// enter normal mode for tlast_gen
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 2);
+		// enter normal mode for pps_gen, fifo and trigger modules
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 1);
+		// enter normal mode for data converter and writer
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 4);
+
+		//FIXME: here we should enable interrupts 
+		while(!interrupted){
+			// alarm(2);   // setting 1 sec timeout
+			// read writer position 
+			//position = dev_read(sts_ptr, STS_STATUS_OFFSET); 
+			wait_for_interrupt(intc_fd, intc_ptr);
+			read_buffer(position, bmp);
+			// alarm(0);   // cancelling 1 sec timeout
+		}
+		// reset pps_gen, fifo and trigger modules
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~1);
+		/* reset data converter and writer */
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~4);
+		// enter reset mode for tlast_gen
+		reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+		dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~2);
+
+	}
+
+	// unmap and close the devices 
+	munmap(intc_ptr, sysconf(_SC_PAGESIZE));
+	munmap(cfg_ptr, sysconf(_SC_PAGESIZE));
+	munmap(sts_ptr, sysconf(_SC_PAGESIZE));
+	munmap(xadc_ptr, sysconf(_SC_PAGESIZE));
+	//munmap(mem_ptr, sysconf(_SC_PAGESIZE));
+
+	close(intc_fd);
+	close(cfg_fd);
+	close(sts_fd);
+	close(xadc_fd);
+
+	return 0;
+
+}
+
+void signal_handler(int sig)
+{
+	interrupted = 1;
+}
+
+int wait_for_interrupt(int fd_int, void *dev_ptr) 
+{
+	uint32_t value;
+	uint32_t info = 1; /* unmask */
+
+	ssize_t nb = write(fd_int, &info, sizeof(info));
+	if (nb != (ssize_t)sizeof(info)) {
+		perror("write");
+		close(fd_int);
+		exit(EXIT_FAILURE);
+	}
+
+	// block (timeout for poll) on the file waiting for an interrupt 
+	struct pollfd fds = 
+	{
+		.fd = fd_int,
+		.events = POLLIN,
+	};
+
+	int ret = poll(&fds, 1, 1000);
+	//printf("ret is : %d\n", ret);
+	if (ret >= 1) {
+		nb = read(fd_int, &info, sizeof(info));
+		if (nb == (ssize_t)sizeof(info)) {
+			/* Do something in response to the interrupt. */
+			value = dev_read(dev_ptr, XIL_AXI_INTC_IPR_OFFSET);
+			if ((value & 0x00000001) != 0) {
+				dev_write(dev_ptr, XIL_AXI_INTC_IAR_OFFSET, 1);
+				// read writer position 
+				position = dev_read(sts_ptr, STS_STATUS_OFFSET);
+
+			}
+		} else {
+			perror("poll()");
+			close(fd_int);
+			exit(EXIT_FAILURE);
+		}
+	}
+	return ret;
+}
+
+void *thread_isr(void *p) 
+{
+	int32_t g_tim, g_dat, g_lat, g_lon, g_alt, g_sat;
+	//initialize GPS connection
+	gps_init();
+	while(1)
+		if (wait_for_interrupt(intc_fd, intc_ptr)){
+			//get GPS data
+			gps_location(&g_data);
+			//write GPS data into registers
+			//FIXME: see how and where to write pressure and temperature data
+			// convert float to int32_t to write to FPGA
+			g_tim = (int32_t)(g_data.times); 
+			g_dat = (int32_t)(g_data.date); 
+			g_lat = (int32_t)(g_data.latitude * 65536);
+			g_lon = (int32_t)(g_data.longitude * 65536);
+			g_alt = (int32_t)(g_data.altitude * 65536);
+			g_sat = (int32_t)(g_data.satellites); 
+
+			dev_write(cfg_ptr,CFG_TIME_OFFSET, g_tim);
+			dev_write(cfg_ptr,CFG_DATE_OFFSET, g_dat);
+			dev_write(cfg_ptr,CFG_LATITUDE_OFFSET, g_lat);
+			dev_write(cfg_ptr,CFG_LONGITUDE_OFFSET, g_lon);
+			dev_write(cfg_ptr,CFG_ALTITUDE_OFFSET, g_alt);
+			dev_write(cfg_ptr,CFG_SATELLITE_OFFSET, g_sat);
+			//printf("%lf %lf\n", gps_data.latitude, gps_data.longitude);
+		}
+}
+
+void *thread_isr_not_gps(void *p) 
+{
+	//int32_t g_tim, g_dat, g_lat, g_lon, g_alt, g_sat;
+	while(1)
+		if (wait_for_interrupt(intc_fd, intc_ptr)){
+			//write GPS data into registers
+			//FIXME: see how and where to write pressure and temperature data
+			// convert float to int32_t to write to FPGA
+			/*g_tim = (int32_t)(g_data.times); 
+				g_dat = (int32_t)(g_data.date); 
+				g_lat = (int32_t)(g_data.latitude * 65536);
+				g_lon = (int32_t)(g_data.longitude * 65536);
+				g_alt = (int32_t)(g_data.altitude * 65536);
+				g_sat = (int32_t)(g_data.satellites); 
+
+				dev_write(cfg_ptr,CFG_TIME_OFFSET, g_tim);
+				dev_write(cfg_ptr,CFG_DATE_OFFSET, g_dat);
+				dev_write(cfg_ptr,CFG_LATITUDE_OFFSET, g_lat);
+				dev_write(cfg_ptr,CFG_LONGITUDE_OFFSET, g_lon);
+				dev_write(cfg_ptr,CFG_ALTITUDE_OFFSET, g_alt);
+				dev_write(cfg_ptr,CFG_SATELLITE_OFFSET, g_sat);
+				*/
+			//printf("%lf %lf\n", gps_data.latitude, gps_data.longitude);
+		}
+}
+
+void show_usage(char *progname) 
+{
+	if (fshowversion) {
+		printf("LAGO ACQUA BRC v%dr%d data v%d\n",VERSION,REVISION,DATAVERSION);
+	} else {
+		printf("\n\tThe LAGO ACQUA suite\n");
+		printf("\tData acquisition system for the LAGO BRC electronic\n");
+		printf("\t(c) 2012-Today, The LAGO Project, http://lagoproject.net\n");
+		printf("\t(c) 2012, LabDPR, http://labdpr.cab.cnea.gov.ar\n");
+		printf("\n\tThe LAGO Project, lago@lagoproject.org\n");
+		printf("\n\tDPR Lab. 2021\n");
+		printf("\tH. Arnaldi, lharnaldi@gmail.com\n");
+		printf("\tX. Bertou, bertou@gmail.com\n");
+		printf("\t%s v%dr%d comms soft\n\n",EXP,VERSION,REVISION);
+		printf("Usage: %s <action> <register> <value> [options]\n", progname);
+
+		printf("\n\tActions:\n");
+		//  printf("\t-r\t\t\t\tGet a single register value\n");
+		//  printf("\t-p\t\t\t\tSet a value into a single register\n");
+		printf("\t-a\t\t\t\tGet all registers status\n");
+		printf("\t-s\t\t\t\tSet registers\n");
+		printf("\t-f\t\t\t\tStart DAQ and save data to file\n");
+		printf("\t-o\t\t\t\tStart DAQ and send data to stdout\n");
+		printf("\t-g\t\t\t\tGet GPS data\n");
+		printf("\t-t\t\t\t\tGet Pressure and Temperature data\n");
+		printf("\t-i\t\t\t\tInitialise registers to default values\n");
+		printf("\t-x\t\t\t\tRead the voltage in the XADC channels\n");
+		printf("\t-v\t\t\t\tShow DAQ version\n");
+
+		printf("\n\tRegisters:\n");
+		printf("\tt1, t2\t\t\t\tSpecify triggers 1 and 2\n");
+		printf("\tsc1, sc2\t\t\tSpecify scaling factor 1 and 2\n");
+		//printf("\tst1, st2, st3\t\t\tSpecify subtriggers 1, 2 and
+		//3\n");
+		printf("\thv1, hv2\t\t\tSpecify high voltages\n");
+		printf("\tov1, ov2, ov3, ov4\t\tSpecify output voltages\n");
+		//printf("\tiv1, iv2, iv3, iv4\t\t\tRead input voltages\n");
+
+		printf("\n\tOptions:\n");
+		printf("\t-f <filename>\t\t\tSpecify file name\n");
+		//printf("\t-c <# bytes>\t\t\tNumber of bytes to read/write\n");
+		//printf("\t-b <byte>\t\t\tValue to load into register\n");
+
+		printf("\n\n");
+	}
+}
+
+//TODO: change this function to just strncpy
+void StrcpyS(char *szDst, size_t cchDst, const char *szSrc) 
+{
+
+#if defined (WIN32)     
+
+	strcpy_s(szDst, cchDst, szSrc);
+
+#else
+
+	if ( 0 < cchDst ) {
+
+		strncpy(szDst, szSrc, cchDst - 1);
+		szDst[cchDst - 1] = '\0';
+	}
+
+#endif
+}      
+
+int parse_param(int argc, char *argv[]) 
+{
+
+	int    arg;
+
+	// Initialize default flag values 
+	fReadReg    = 0;
+	fWriteReg    = 0;
+	fGetCfgStatus = 0;
+	fSetCfgReg = 0;
+	fToFile    = 0;
+	fToStdout  = 0;
+	fGetPT     = 0;
+	fGetGPS    = 0;
+	fFile      = 0;
+	fCount     = 0;
+	fByte      = 0;
+	fData      = 0;
+	fRegValue  = 0;
+	fGetXADC   = 0;
+
+	// Ensure sufficient paramaters. Need at least program name and action
+	// flag
+	if (argc < 2) 
+	{
+		return 0;
+	}
+
+	// The first parameter is the action to perform. Copy the first
+	// parameter into the action string.
+	StrcpyS(charAction, MAXCHRLEN, argv[1]);
+	if(strcmp(charAction, "-r") == 0) {
+		fReadReg = 1;
+	} 
+	else if( strcmp(charAction, "-w") == 0) {
+		fWriteReg = 1;
+	} 
+	else if( strcmp(charAction, "-a") == 0) {
+		fGetCfgStatus = 1;
+		return 1;
+	} 
+	else if( strcmp(charAction, "-v") == 0) {
+		fshowversion = 1;
+		return 0;
+	} 
+	else if( strcmp(charAction, "-s") == 0) {
+		fSetCfgReg = 1;
+	} 
+	else if( strcmp(charAction, "-f") == 0) {
+		fToFile = 1;
+	} 
+	else if( strcmp(charAction, "-o") == 0) {
+		fToStdout = 1;
+		return 1;
+	} 
+	else if( strcmp(charAction, "-t") == 0) {
+		fGetPT = 1;
+		return 1;
+	} 
+	else if( strcmp(charAction, "-g") == 0) {
+		fGetGPS = 1;
+		return 1;
+	} 
+	else if( strcmp(charAction, "-i") == 0) {
+		fInitSystem = 1;
+		return 1;
+	} 
+	else if( strcmp(charAction, "-x") == 0) {
+		fGetXADC = 1;
+		return 1;
+	} 
+	else { // unrecognized action
+		return 0;
+	}
+
+	// Second paramater is target register on device. Copy second paramater
+	// to the register string
+	if((fReadReg == 1) || (fWriteReg == 1)) {
+		StrcpyS(charReg, MAXCHRLEN, argv[2]);
+		if(strcmp(charReg, "intc") == 0) {
+			n_dev = 0; 
+		} 
+		else if(strcmp(charReg, "cfg") == 0) {
+			n_dev = 1; 
+		} 
+		else if(strcmp(charReg, "sts") == 0) {
+			n_dev = 2; 
+		} 
+		else if(strcmp(charReg, "xadc") == 0) {
+			n_dev = 3; 
+		}
+		else { // unrecognized device to set
+			return 0;
+		}
+		reg_off = strtoul(argv[3],NULL, 16);
+		//FIXME: see if this can be done better
+		if (fWriteReg) reg_val = strtoul(argv[4],NULL,16);
+		return 1;
+	}
+
+	else if(fSetCfgReg) {
+		StrcpyS(charReg, MAXCHRLEN, argv[2]);
+		// Registers for Triggers
+		if(strcmp(charReg, "t1") == 0) {
+			reg_off = CFG_TRLVL_1_OFFSET;
+		} 
+		else if(strcmp(charReg, "t2") == 0) {
+			reg_off = CFG_TRLVL_2_OFFSET;
+		} 
+		// Registers for Subtriggers
+		else if(strcmp(charReg, "st1") == 0) {
+			reg_off = CFG_STRLVL_1_OFFSET;
+		} 
+		else if(strcmp(charReg, "st2") == 0) {
+			reg_off = CFG_STRLVL_2_OFFSET;
+		} 
+		// Registers for High Voltage
+		else if(strcmp(charReg, "hv1") == 0) {
+			reg_off = CFG_HV1_OFFSET;
+		} 
+		else if(strcmp(charReg, "hv2") == 0) {
+			reg_off = CFG_HV2_OFFSET;
+		} 
+		// Registers for output voltages
+		else if(strcmp(charReg, "ov1") == 0) {
+			reg_off = CFG_HV1_OFFSET;
+		} 
+		else if(strcmp(charReg, "ov2") == 0) {
+			reg_off = CFG_HV2_OFFSET;
+		} 
+		else if(strcmp(charReg, "ov3") == 0) {
+			reg_off = CFG_HV3_OFFSET;
+		} 
+		else if(strcmp(charReg, "ov4") == 0) {
+			reg_off = CFG_HV4_OFFSET;
+		} 
+		// Registers for scalers
+		else if(strcmp(charReg, "sc1") == 0) {
+			reg_off = CFG_TR_SCAL_A_OFFSET;
+		} 
+		else if(strcmp(charReg, "sc2") == 0) {
+			reg_off = CFG_TR_SCAL_B_OFFSET;
+		} 
+		// Unrecognized
+		else { // unrecognized register to set
+			return 0;
+		}
+		//charCount[0] = '4';
+		//fCount = 1;
+		StrcpyS(charRegValue, 16, argv[3]);
+		if((strncmp(charReg, "hv", 2) == 0) || (strncmp(charReg, "ov", 2) == 0)) {
+			if (atoi(charRegValue)>2500) {
+				printf ("Error: maximum voltage is 2500 mV\n");
+				exit(1);
+			}
+			fRegValue = 1;
+		}
+		//fData = 1; FIXME: not used apparently
+	} 
+	else if(fToFile) {
+		if(argv[2] != NULL) {
+			StrcpyS(charFile, MAXFILENAMELEN, argv[2]);
+			fFile = 1;
+		} 
+		else {
+			return 0;
+		}
+	} 
+	else {
+		StrcpyS(scRegister, MAXCHRLEN, argv[2]);
+
+		// Parse the command line parameters.
+		arg = 3;
+		while(arg < argc) {
+
+			// Check for the -f parameter used to specify the
+			// input/output file name.
+			if (strcmp(argv[arg], "-f") == 0) {
+				arg += 1;
+				if (arg >= argc) {
+					return 0;
+				}
+				StrcpyS(charFile, 16, argv[arg++]);
+				fFile = 1;
+			}
+
+			// Check for the -c parameter used to specify the number
+			// of bytes to read/write from file.
+			else if (strcmp(argv[arg], "-c") == 0) {
+				arg += 1;
+				if (arg >= argc) {
+					return 0;
+				}
+				StrcpyS(charCount, 16, argv[arg++]);
+				fCount = 1;
+			}
+
+			// Check for the -b paramater used to specify the value
+			// of a single data byte to be written to the register 
+			else if (strcmp(argv[arg], "-b") == 0) {
+				arg += 1;
+				if (arg >= argc) {
+					return 0;
+				}
+				StrcpyS(scByte, 16, argv[arg++]);
+				fByte = 1;
+			}
+
+			// Not a recognized parameter
+			else {
+				return 0;
+			}
+		} // End while
+
+		// Input combination validity checks 
+		if( fWriteReg && !fByte ) {
+			printf("Error: No byte value provided\n");
+			return 0;
+		}
+		if( (fToFile ) && !fFile ) {
+			printf("Error: No filename provided\n");
+			return 0;
+		}
+
+		return 1;
+	}
+	return 1;
+}
+
+int new_file() 
+{
+	char buf[256];
+	time_t currt=time(NULL);
+	//uint32_t i;
+
+	if (!fToStdout) {
+		if (fhout) {
+			fclose(fhout);
+		}
+		/*if (fhmtd) {
+		//before to close the file we have to fill DAQ status metadata
+		// Average and deviation trigger rates
+		double mtd_avg[MTD_TRG], mtd_dev[MTD_TRG];
+		if (!mtd_seconds) {
+		for (int i=0; i<MTD_TRG; i++)
+		mtd_avg[i] = mtd_dev[i] = -1.;
+		} 
+		else {
+		for (int i=0; i<MTD_TRG; i++) {
+		mtd_avg[i] = 1. * mtd_rates[i] / mtd_seconds;
+		mtd_dev[i] = sqrt(1. * mtd_rates2[i] / mtd_seconds - mtd_avg[i] * mtd_avg[i]);
+		}
+		}
+		for (int i=1; i<MTD_TRG; i++)
+		fprintf(fhmtd, "triggerRateAvg%02d=%lf\n", i, mtd_avg[i]);
+		for (int i=1; i<MTD_TRG; i++)
+		fprintf(fhmtd, "trigggerRateDev%02d=%lf\n", i, mtd_dev[i]);
+		for (int i=0; i<MTD_TRG; i++)
+		mtd_rates[i] = mtd_rates2[i] = 0;
+		//baselines
+		double mtd_bl_avg[MTD_BL], mtd_bl_dev[MTD_BL];
+		double mtd_cdpf;
+		if (!mtd_cbl) {
+		for (int i=0; i<MTD_BL; i++)
+		mtd_bl_avg[i] = mtd_bl_dev[i] = -1.;
+		mtd_cdpf = -1;
+		} 
+		else {
+		for (int i=0; i<MTD_BL; i++) {
+		mtd_bl_avg[i] = 1. * mtd_bl[i] / mtd_cbl;
+		mtd_bl_dev[i] = sqrt(1. * mtd_bl2[i] / mtd_cbl - mtd_bl_avg[i] * mtd_bl_avg[i]);
+		}
+		mtd_cdpf = 1. * mtd_cdp / mtd_cbl;
+		}
+		for (int i=1; i<MTD_BL; i++)
+		fprintf(fhmtd, "baselineAvg%02d=%lf\n", i+1, mtd_bl_avg[i]);
+		for (int i=1; i<MTD_BL; i++)
+		fprintf(fhmtd, "baselineDev%02d=%lf\n", i+1, mtd_bl_dev[i]);
+		for (int i=0; i<MTD_BL; i++)
+		mtd_bl[i] = mtd_bl2[i] = 0;
+		// daq time, pulses and dead time
+		fprintf(fhmtd, "daqTime=%d\n", mtd_seconds);
+		fprintf(fhmtd, "totalPulses=%ld\n", mtd_cbl);
+		fprintf(fhmtd, "totalPulsesLost=%ld\n", mtd_cdp);
+		fprintf(fhmtd, "fractionPulsesLost=%le\n", mtd_cdpf);
+		//and now, let's close the file
+		mtd_seconds = 0;
+		mtd_cbl = mtd_cdp = 0;
+		fclose(fhmtd);
+		}*/
+		fileTime=timegm(fileDate);
+		fileDate=gmtime(&fileTime); // filling all fields with properly computed values (for new month/year)
+		if (falseGPS) {
+			snprintf(charCurrentFile,MAXCHRLEN,"%s_nogps_%04d_%02d_%02d_%02dh00.dat",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour);
+			snprintf(charCurrentMetaData,MAXCHRLEN,"%s_nogps_%04d_%02d_%02d_%02dh00.mtd",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour);
+		} 
+		else {
+			snprintf(charCurrentFile,MAXCHRLEN,"%s_%04d_%02d_%02d_%02dh00.dat",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour);
+			snprintf(charCurrentMetaData,MAXCHRLEN,"%s_%04d_%02d_%02d_%02dh00.mtd",charFile,fileDate->tm_year+1900, fileDate->tm_mon+1,fileDate->tm_mday,fileDate->tm_hour);
+		}
+		fhout = fopen(charCurrentFile, "ab");
+		//fhmtd = fopen(charCurrentMetaData, "w");
+		//fprintf(stderr,"Opening files %s and %s for data taking\n",charCurrentFile, charCurrentMetaData);
+		fprintf(stderr,"Opening file %s at %02dh%02d for data taking\n",charCurrentFile,fileDate->tm_hour,fileDate->tm_min);
+	}
+	fprintf(fhout,"# v %d\n", DATAVERSION);
+	fprintf(fhout,"# #\n");
+	fprintf(fhout,"# # This is a %s raw data file, version %d\n",EXP,DATAVERSION);
+	fprintf(fhout,"# # It contains the following data:\n");
+	fprintf(fhout,"# #   <N1> <N2>        : line with values of the 2 ADC for a triggered pulse\n");
+	//fprintf(fhout,"# #                      it is a subtrigger with the pulse maximum bin if only one such line is found\n");
+	//fprintf(fhout,"# #                      it is a trigger with the full pulse if 16 lines are found\n");
+	fprintf(fhout,"# #   # t <C> <V>      : end of a trigger\n");
+	fprintf(fhout,"# #                      gives the channel trigger (<C>: 3 bit mask) and 125 MHz clock count (<V>) of the trigger time\n");
+	fprintf(fhout,"# #   # c <C>          : internal trigger counter\n");
+	fprintf(fhout,"# #   # x f <V>        : 125 MHz frequency\n");
+	fprintf(fhout,"# #   # x t <V>        : temperature value\n");
+	fprintf(fhout,"# #   # x p <V>        : pressure value\n");
+	fprintf(fhout,"# #   # x r1 <V>       : pulse rate at channel 1\n");
+	fprintf(fhout,"# #   # x r2 <V>       : pulse rate at channel 2\n");
+	fprintf(fhout,"# #   # x h <HH:MM:SS> <DD/MM/YYYY> <S> : GPS time (every new second, last number is seconds since EPOCH)\n");
+	fprintf(fhout,"# #   # x s <T> C <P> hPa <A> m : temperature <T>, pressure <P> and altitude (from pressure) <A>\n");
+	fprintf(fhout,"# #   # x g <LAT> <LON> <ALT>   : GPS data - latitude, longitude, altitude\n");
+	fprintf(fhout,"# #   # x v <HV1> <HV2>         : HV voltages for channels 1 and 2\n");
+	fprintf(fhout,"# #   # x b <B1> <B2> <B3>      : baselines (NOT IMPLEMENTED IN LAGO)\n");
+	fprintf(fhout,"# # In case of error, an unfinished line will be finished by # E @@@\n");
+	fprintf(fhout,"# # Followed by a line with # E <N> and the error message in human readable format, where <N> is the error code:\n");
+	fprintf(fhout,"# #   # E 1 : read timeout of 2 seconds\n");
+	fprintf(fhout,"# #   # E 2 : too many buffer reading tries\n");
+	fprintf(fhout,"# #   # E 3 : unknown word from FPGA\n");
+	fprintf(fhout,"# #\n");
+	fprintf(fhout,"# # Current registers setting\n");
+	fprintf(fhout,"# #\n");
+	// Save settings into file
+	fprintf(fhout,"# x c T1 %d\n",dev_read(cfg_ptr, CFG_TRLVL_1_OFFSET));
+	fprintf(fhout,"# x c T2 %d\n",dev_read(cfg_ptr, CFG_TRLVL_2_OFFSET));
+	{
+		//float a = 0.0382061, b = 4.11435;  // For gain = 1.45
+		float a = 0.0882006, b = 7.73516;  // For gain = 3.2
+		fprintf(fhout,"# x c HV1 %.1f mV\n",a*dev_read(cfg_ptr, CFG_HV1_OFFSET)+b);
+		fprintf(fhout,"# x c HV2 %.1f mV\n",a*dev_read(cfg_ptr, CFG_HV2_OFFSET)+b);
+	}
+	fprintf(fhout,"# x c SC1 %d\n",dev_read(cfg_ptr, CFG_TR_SCAL_A_OFFSET));
+	fprintf(fhout,"# x c SC2 %d\n",dev_read(cfg_ptr, CFG_TR_SCAL_B_OFFSET));
+	gethostname(buf, 256);
+	fprintf(fhout,"# # This file was started on %s\n",buf);
+	//				fprintf(fhmtd, "daqHost=\"%s\"\n",buf);
+	ctime_r(&currt,buf);
+	fprintf(fhout,"# # Machine local time was %s",buf);
+	strtok(buf, "\n");
+	//				fprintf(fhmtd, "machineTime=\"%s\"\n",buf);
+	if (falseGPS) fprintf(fhout,"# # WARNING, there is no GPS, using PC time\n");
+	fprintf(fhout,"# #\n");
+	//				fprintf(fhmtd, "dataFile=\"%s\"\n",charCurrentFile);
+	//				fprintf(fhmtd, "metadataFile=\"%s\"\n",charCurrentMetaData);
+	//				fprintf(fhmtd, "daqVersion=%d\n",VERSION);
+	//				fprintf(fhmtd, "daqUseGPS=%s", (!falseGPS)?"true":"false");
+	//				fprintf(fhmtd, "dataVersion=%d\n",DATAVERSION);
+	//				for (i=0; i<configs_lines.size(); i++)
+	//								fprintf(fhmtd, "%s\n", configs_lines[i].c_str());
+	//				fprintf(fhmtd, "version=\"LAGO ACQUA BRC v%dr%d data v%d\"\n",VERSION,REVISION,DATAVERSION);
+	fflush(fhout);
+	//				fflush(fhmtd);
+	return 0;
+}
+
+int r[MTD_TRG];
+
+int read_buffer(int pos, void *bmp)
+{
+	uint32_t wo;
+	int16_t ch[2];
+	//uint32_t i, j;
+	uint32_t i;
+	//int offset;
+	int trig;
+	//int32_t v_temp;
+	int readinit=0;
+	int readend=limit;
+
+	if (fToStdout)
+		fhout=stdout;
+	if (fFirstTime) {
+		// if no GPS 
+		if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // get time form PC
+			fileTime=time(NULL);
+			fileDate=gmtime(&fileTime); // filling all fields
+			falseGPS=1;
+		} 
+		else {
+			fileTime=time(NULL);
+			fileDate=gmtime(&fileTime);
+			//FIXME: fill with actual data
+			fileDate->tm_sec=55;
+			fileDate->tm_min=55;
+			fileDate->tm_hour=10;
+			fileDate->tm_mday=29;
+			fileDate->tm_mon=8;
+			fileDate->tm_year=2018;
+
+			fileTime=timegm(fileDate);
+			fileDate=gmtime(&fileTime); // filling all fields
+		}
+		if (fhout != stdout) {
+			//FIXME: here read PyT data
+
+		}
+		new_file();
+		fFirstTime=0;
+	}
+
+	// pos is the number of 8 bytes word written. I need the memory
+	// location... Therefore, pos=pos*8
+	//pos=pos*4;
+
+	//printf("%d %d %d\n",current,pos,limit);
+	//fprintf(fhout,"# XB %d %d %d\n", current,pos,limit);
+	// print 512 IN1 and IN2 samples if ready, otherwise sleep 1 ms
+	// compare current writing location (pos) with previous (limit)
+	// if current<pos, then read from current to pos and adjust current
+	// if current>pos, then read from current to end of buffer and set current to 0 at the end
+	if (current==limit-2) current=-2; // hack, because I do +4 next to read from next position
+	if (current<pos+2) {
+		readinit=current+2;
+		readend=pos;
+	} else if (current>pos) {
+		readinit=current+2;
+		readend=limit; // note: don't read after limit
+	}
+	if(current!=pos) {
+
+		//printf("# # # # NEW BUFFER %d %d %d %d %d \n", readinit, readend, current, pos, limit);
+		//offset = limit > 0 ? 0 : 4096*1024;
+		//limit = limit > 0 ? 0 : 512*1024;
+
+		//for(i = readinit; i < readend; i+=4) {
+		for(i = readinit; i < readend; i++) {
+			ch[0] = *((cma_ptr + 2*i + 0));
+			ch[1] = *((cma_ptr + 2*i + 1));
+			//printf("%5d %5d\n", ch[0], ch[1]);
+			wo = *((uint32_t *)(cma_ptr + 2*i));
+			if (wo>>30==0) {
+				fprintf(fhout,"%5hd %5hd\n", (((ch[0]>>13)<<14) + ((ch[0]>>13)<<15) + ch[0]),(((ch[1]>>13)<<14) + ((ch[1]>>13)<<15) + ch[1]));
+				mtd_iBin++;
+				if (mtd_iBin == MTD_BLBIN) {
+					mtd_bl[0] += ch[0];
+					mtd_bl2[0] += ch[0] * ch[0];
+					mtd_bl[1] += ch[1];
+					mtd_bl2[1] += ch[1] * ch[1];
+					mtd_cbl++;
+				}
+			} 
+			else {
+				if (wo>>30==1) { //get trigger status and counter between PPS
+					fprintf(fhout,"# t %d %d\n", (wo>>27)&0x7, wo&0x7FFFFFF);
+					trig=(wo>>27)&0x7;
+					r[trig]++;
+					mtd_iBin=0;
+				} 
+				else {
+					if (wo>>30==2) {//get counter status
+						mtd_pulse_pnt = mtd_pulse_cnt;
+						mtd_pulse_cnt = (wo&0x3FFFFFFF);
+						mtd_dp = (mtd_pulse_cnt - mtd_pulse_pnt - 1);
+						if (mtd_dp > 0 && mtd_pulse_pnt)
+							mtd_cdp += mtd_dp;
+						fprintf(fhout,"# c %ld\n", mtd_pulse_cnt);
+					} 
+					else {
+						switch(wo>>27) {
+							case 0x18:
+								fprintf(fhout,"# x f %d \n", wo&0x07FFFFFF);//PPS counter
+								break;
+							case 0x19:
+								fprintf(fhout,"# x t %.1f \n", bmp180_temperature(bmp));
+								break;
+							case 0x1A:
+								fprintf(fhout,"# x p %.2f \n", (bmp180_pressure(bmp)/100.));
+								break;
+							case 0x1B:
+								if(falseGPS) {
+									fileDate->tm_sec++;
+									if (fileDate->tm_sec==60 && fileDate->tm_min==59) { // new hour
+										if (!fToStdout)
+											new_file();
+									} 
+									else {
+										fileTime=timegm(fileDate);
+										fileDate=gmtime(&fileTime); // filling all fields with properly comupted values (for new month/year)
+									}
+								} 
+								else {
+									if ((uint32_t)fileDate->tm_hour!=((wo>>16)&0x000000FF)) {
+										// new hour of data
+										if ((uint32_t)fileDate->tm_hour>((wo>>16)&0x000000FF)) { // new day
+											fileDate->tm_mday++;
+										}
+										fileDate->tm_hour=(wo>>16)&0x000000FF;
+										if (!fToStdout)
+											new_file();
+									}
+									fileDate->tm_hour=(wo>>16)&0x000000FF;
+									fileDate->tm_min=(wo>>8)&0x000000FF;
+									fileDate->tm_sec=wo&0x000000FF;
+								}
+								mtd_seconds++;
+								fileTime=timegm(fileDate);
+								fileDate=gmtime(&fileTime); // filling all fields with properly computed values (for new month/year)
+								fprintf(fhout,"# x h   %02d:%02d:%02d %02d/%02d/%04d %d %d\n",
+										fileDate->tm_hour, fileDate->tm_min, fileDate->tm_sec,
+										fileDate->tm_mday, fileDate->tm_mon+1,fileDate->tm_year+1900,
+										(int)fileTime,wo&0x03FFFFFF
+										);
+								fprintf(fhout,"# x v %.1f %.1f\n",(get_voltage(XADC_AI2_OFFSET)/0.0031949),(get_voltage(XADC_AI3_OFFSET)/0.0031949));
+								fprintf(fhout,"# p %u %.1f %.1f\n",hack++,get_temp_AD592(XADC_AI0_OFFSET),get_temp_AD592(XADC_AI1_OFFSET));
+								if (hack%60==0) printf("\n");
+								printf("rates %5d %5d, PPS %u        \r",r1,r2,hack);
+								fflush(stdout);
+								/*fprintf(stderr,"# %02d:%02d:%02d %02d/%02d/%04d %d - second %d - rates: %d %d %d (%d - %d - %d) [%d]\r", 
+									fileDate->tm_hour, fileDate->tm_min, fileDate->tm_sec,
+									fileDate->tm_mday, fileDate->tm_mon+1, fileDate->tm_year+1900,
+									(int)fileTime,
+									mtd_seconds,
+									r[1], r[2], r[4], r[3], r[5], r[6], r[7]
+									);*/
+								//for (j=0; j<MTD_TRG; j++) {
+								//				mtd_rates[i] += r[i];
+								//				mtd_rates2[i] += r[i] * r[i];
+								//				r[i] = 0;
+								//}
+								break;
+								//FIXME: see if can add the FPGA interface in this stage
+							case 0x1C: // Longitude, latitude, defined by other bits
+								switch(((wo)>>24) & 0x7) {
+									case 0:
+										gps_lat=((int32_t)(wo&0xFFFFFF)<<8>>8)/65536.0;
+										//gps_lat=v_temp/65536.0;
+										break;
+									case 1:
+										gps_lon=((int32_t)(wo&0xFFFFFF)<<8>>8)/65536.0;
+										//gps_lat=v_temp/65536.0;
+										break;
+									case 2:
+										gps_alt=((int32_t)(wo&0xFFFFFF)<<8>>8)/65536.0;
+										//gps_lat=v_temp/65536.0;
+										//fprintf(fhout,"# x g %.6f %.6f %.2f\n",gps_lat,gps_lon,gps_alt);
+										fprintf(fhout,"# x g %.6f %.6f %.2f\n",g_data.latitude,g_data.longitude,g_data.altitude);
+										//tmp_gps_lon=((wo & 0xFFFFFF)<<8);
+										break;
+										/*case 3: FIXME: here is the date data
+										// Not used here
+										//gps_lon=((int)(tmp_gps_lon+(wo & 0xFF)))/3600000.;
+										break;
+										case 4:
+										//tmp_gps_elips=((wo & 0xFFFFFF)<<8);
+										break;
+										case 5:
+										//gps_elips=((int)(tmp_gps_elips+(wo & 0xFF)))/100.;
+										//fprintf(fhout,"# x g %.6f %.6f %.2f\n",gps_lat,gps_lon,gps_elips);
+										break;*/
+									default:
+										break;
+								}
+								break;
+							case 0x1D: //rate ch1 counter
+								fprintf(fhout,"# r1 %d \n", (int32_t)wo&0x00FFFFFF);
+								r1= (int32_t)wo&0x00FFFFFF;
+								break;
+							case 0x1E: //rate ch2 counter
+								fprintf(fhout,"# r2 %d \n", (int32_t)wo&0x00FFFFFF);
+								r2= (int32_t)wo&0x00FFFFFF;
+								break;
+							default:
+								fprintf(fhout,"# E @@@\n");
+								fprintf(fhout,"# E 3 - unknown word from FPGA: %d %x\n",wo>>27,wo>>27);
+								break;
+						}
+					}
+				}
+			}
+			current=i;
+		}
+	}
+	return 1;
+}
+
diff --git a/projects/lago_v1_3/src/lago.h b/projects/lago_v1_3/src/lago.h
new file mode 100644
index 0000000000000000000000000000000000000000..2c07e341a8e60088498349072e92979314dd759d
--- /dev/null
+++ b/projects/lago_v1_3/src/lago.h
@@ -0,0 +1,48 @@
+#ifndef _MAIN_H_
+#define _MAIN_H_
+
+#include <poll.h>
+#include <signal.h>
+#include <string.h>
+#include <time.h>
+//#include <fstream>
+//#include <iostream>
+//#include <vector>
+
+#define _GNU_SOURCE
+#include <pthread.h>
+
+#include "zynq_io.h"
+#include "gps_rp.h"
+#include "bmp180.h"
+#include "globaldefs.h"
+
+typedef struct ldata 
+{
+        int trigg_1;   // trigger level ch1
+        int trigg_2;   // trigger level ch2
+        int strigg_1;  // sub-trigger level ch1
+        int strigg_2;  // sub-trigger level ch2
+        int nsamples;  // N of samples
+        int time;
+        double latitude;
+        char lat;
+        double longitude;
+        char lon;
+        uint8_t quality;
+        uint8_t satellites;
+        double altitude;
+} ldata_t;
+
+int  main(int argc, char *argv[]);
+void signal_handler(int sig);
+int  wait_for_interrupt(int fd_int, void *dev_ptr);
+void *thread_isr_not_gps(void *p);  
+void *thread_isr(void *p);  
+void show_usage(char *progname);
+void StrcpyS(char *szDst, size_t cchDst, const char *szSrc); 
+int  parse_param(int argc, char *argv[]);  
+int  new_file(void);
+int  read_buffer(int position, void *bmp);
+
+#endif
diff --git a/projects/lago_v1_3/src/nmea_rp.c b/projects/lago_v1_3/src/nmea_rp.c
new file mode 100644
index 0000000000000000000000000000000000000000..d8c5446bf9e17c46295dd96ffd0696733b218e23
--- /dev/null
+++ b/projects/lago_v1_3/src/nmea_rp.c
@@ -0,0 +1,148 @@
+#include "nmea_rp.h"
+
+static uint8_t rp_NmeaValidChecksum(const char *message) 
+{
+    uint8_t checksum= (uint8_t)strtol(strchr(message, '*')+1, NULL, 16);
+
+    char p;
+    uint8_t sum = 0;
+    ++message;
+    while ((p = *message++) != '*') {
+        sum ^= p;
+    }
+
+    if (sum != checksum) {
+        return NMEA_CHECKSUM_ERR;
+    }
+
+    return _EMPTY;
+}
+
+void rp_NmeaParseGpgga(char *nmea, gpgga_t *loc)
+{
+    char *ptr = nmea;
+    
+    ptr = strchr(ptr, ',')+1; //skip time
+    loc->times = atof(ptr); 
+
+    ptr = strchr(ptr, ',')+1;
+    loc->latitude = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    switch (ptr[0]) {
+        case 'N':
+            loc->lat = 'N';
+            break;
+        case 'S':
+            loc->lat = 'S';
+            break;
+        case ',':
+            loc->lat = '\0';
+            break;
+    }
+
+    ptr = strchr(ptr, ',')+1;
+    loc->longitude = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    switch (ptr[0]) {
+        case 'W':
+            loc->lon = 'W';
+            break;
+        case 'E':
+            loc->lon = 'E';
+            break;
+        case ',':
+            loc->lon = '\0';
+            break;
+    }
+
+    ptr = strchr(ptr, ',')+1;
+    loc->quality = (uint8_t)atoi(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    loc->satellites = (uint8_t)atoi(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+
+    ptr = strchr(ptr, ',')+1;
+    loc->altitude = atof(ptr);
+}
+
+void rp_NmeaParseGprmc(char *nmea, gprmc_t *loc)
+{
+    char *ptr = nmea;
+
+    ptr = strchr(ptr, ',')+1; //skip time
+    loc->times = atof(ptr); 
+
+    ptr = strchr(ptr, ',')+1; //skip status
+
+    ptr = strchr(ptr, ',')+1;
+    loc->latitude = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    switch (ptr[0]) {
+        case 'N':
+            loc->lat = 'N';
+            break;
+        case 'S':
+            loc->lat = 'S';
+            break;
+        case ',':
+            loc->lat = '\0';
+            break;
+    }
+
+    ptr = strchr(ptr, ',')+1;
+    loc->longitude = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    switch (ptr[0]) {
+        case 'W':
+            loc->lon = 'W';
+            break;
+        case 'E':
+            loc->lon = 'E';
+            break;
+        case ',':
+            loc->lon = '\0';
+            break;
+    }
+
+    ptr = strchr(ptr, ',')+1;
+    loc->speed = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    loc->course = atof(ptr);
+
+    ptr = strchr(ptr, ',')+1;
+    loc->date = atof(ptr);
+}
+
+/**
+ * Get the message type (GPGGA, GPRMC, etc..)
+ *
+ * This function filters out also wrong packages (invalid checksum)
+ *
+ * @param message The NMEA message
+ * @return The type of message if it is valid
+ */
+uint8_t rp_NmeaGetMessageType(const char *message)
+{
+    uint8_t checksum = 0;
+    if ((checksum = rp_NmeaValidChecksum(message)) != _EMPTY) {
+        return checksum;
+    }
+
+    if (strstr(message, NMEA_GPGGA_STR) != NULL) {
+        return NMEA_GPGGA;
+    }
+
+    if (strstr(message, NMEA_GPRMC_STR) != NULL) {
+        return NMEA_GPRMC;
+    }
+
+    return NMEA_UNKNOWN;
+}
+
diff --git a/projects/lago_v1_3/src/nmea_rp.h b/projects/lago_v1_3/src/nmea_rp.h
new file mode 100644
index 0000000000000000000000000000000000000000..819c5e132f3d0502a3a048d199979a380f71542d
--- /dev/null
+++ b/projects/lago_v1_3/src/nmea_rp.h
@@ -0,0 +1,48 @@
+#ifndef _NMEA_RP_H_
+#define _NMEA_RP_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <string.h>
+#include <math.h>
+
+#define _EMPTY 0x00
+#define NMEA_GPRMC 0x01
+#define NMEA_GPRMC_STR "$GPRMC"
+#define NMEA_GPGGA 0x02
+#define NMEA_GPGGA_STR "$GPGGA"
+#define NMEA_UNKNOWN 0x00
+#define _COMPLETED 0x03
+
+#define NMEA_CHECKSUM_ERR 0x80
+#define NMEA_MESSAGE_ERR 0xC0
+
+typedef struct gpgga {
+    double times;
+    double latitude;
+    char lat;
+    double longitude;
+    char lon;
+    uint8_t quality;
+    uint8_t satellites;
+    double altitude;
+} gpgga_t;
+
+typedef struct gprmc {
+    double times;
+    double latitude;
+    char lat;
+    double longitude;
+    char lon;
+    double speed;
+    double course;
+    double date;
+} gprmc_t;
+
+uint8_t rp_NmeaGetMessageType(const char *);
+void rp_NmeaParseGpgga(char *, gpgga_t *);
+void rp_NmeaParseGprmc(char *, gprmc_t *);
+
+#endif
+
diff --git a/projects/lago_v1_3/src/uart_rp.c b/projects/lago_v1_3/src/uart_rp.c
new file mode 100644
index 0000000000000000000000000000000000000000..8c8391c588c174fca38c5a81f6af27617c8b6c50
--- /dev/null
+++ b/projects/lago_v1_3/src/uart_rp.c
@@ -0,0 +1,79 @@
+#include "uart_rp.h"
+
+/* File descriptor definition */
+int uart_fd = -1;
+
+int rp_UartInit(void)
+{
+	uart_fd = open(PORTNAME, O_RDWR | O_NOCTTY | O_NDELAY);
+
+  if(uart_fd == -1){
+    fprintf(stderr, "Failed to open uart.\n");
+    return -1;
+  }
+	return 0;
+}
+
+void rp_UartConfig(void)
+{
+    struct termios options;
+    tcgetattr(uart_fd, &options);
+		/*Configure the UART
+			see http://pubs.opengroup.org/onlinepubs/007908799/xsh/termios.h.html */
+    options.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
+    options.c_iflag = IGNPAR;
+    options.c_oflag = 0;
+    options.c_lflag = 0;
+		/* Setting attributes */
+    tcflush(uart_fd, TCIFLUSH);
+    tcsetattr(uart_fd, TCSANOW, &options);
+}
+
+int rp_UartPrintln(const char *line, int len)
+{
+    if (uart_fd != -1) {
+        char *cpstr = (char *)malloc((len+1) * sizeof(char));
+        strcpy(cpstr, line);
+        cpstr[len-1] = '\r';
+        cpstr[len] = '\n';
+
+        int count = write(uart_fd, cpstr, len+1);
+        if (count < 0) {
+					fprintf(stderr, "UART TX error.\n");
+					return -1;
+        }
+        free(cpstr);
+    }
+	return 0;
+}
+
+/* Read a line from UART */
+int rp_UartReadln(char *buffer, int len)
+{
+	char c;
+	char *b = buffer;
+	int rx_length = -1;
+
+	while(1) {
+		rx_length = read(uart_fd, (void*)(&c), 1);
+		
+		if (rx_length <= 0) {
+			//wait for messages
+			 sleep(1);
+		} else {
+		  	if (c == '\n') {
+		    	*b++ = '\0';
+		      break;
+		    }
+		    *b++ = c;
+		}
+	}
+	return 0;
+}
+
+void rp_UartClose(void)
+{
+	tcflush(uart_fd, TCIFLUSH);
+	close(uart_fd);
+}
+
diff --git a/projects/lago_v1_3/src/uart_rp.h b/projects/lago_v1_3/src/uart_rp.h
new file mode 100644
index 0000000000000000000000000000000000000000..72e0fbcfe7a4f2c3d4fbdf02c0b8fce8e9d270da
--- /dev/null
+++ b/projects/lago_v1_3/src/uart_rp.h
@@ -0,0 +1,23 @@
+#ifndef _UART_RP_H_
+#define _UART_RP_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <inttypes.h>
+#include <string.h>
+
+//Default name for UART port in E2 expansion conector
+#ifndef PORTNAME
+#define PORTNAME "/dev/ttyPS1"
+#endif
+
+int rp_UartInit(void);
+void rp_UartConfig(void);
+int rp_UartPrintln(const char *, int);
+int rp_UartReadln(char *, int);
+void rp_UartClose(void);
+
+#endif
diff --git a/projects/lago_v1_3/src/zynq_io.c b/projects/lago_v1_3/src/zynq_io.c
new file mode 100644
index 0000000000000000000000000000000000000000..772c6b431af5c19059e8543d872724795d007448
--- /dev/null
+++ b/projects/lago_v1_3/src/zynq_io.c
@@ -0,0 +1,519 @@
+#include "zynq_io.h"
+
+int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, hst0_fd, hst1_fd, cma_fd;
+void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *hst0_ptr, *hst1_ptr;
+volatile int16_t *cma_ptr;
+uint32_t dev_size;
+
+void dev_write(void *dev_base, uint32_t offset, int32_t value)
+{
+	*((volatile unsigned *)(dev_base + offset)) = value;
+}
+
+uint32_t dev_read(void *dev_base, uint32_t offset)
+{
+	return *((volatile unsigned *)(dev_base + offset));
+}
+
+/*int dev_init(int n_dev)
+	{
+	char *uiod; = "/dev/uio1";
+
+	printf("Initializing device...\n");
+
+// open the UIO device file to allow access to the device in user space
+cfg_fd = open(uiod, O_RDWR);
+if (cfg_fd < 1) {
+printf("cfg_init: Invalid UIO device file:%s.\n", uiod);
+return -1;
+}
+
+dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size");
+
+// mmap the cfgC device into user space
+cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0);
+if (cfg_ptr == MAP_FAILED) {
+printf("cfg_init: mmap call failure.\n");
+return -1;
+}
+
+return 0;
+}*/
+
+int32_t rd_reg_value(int n_dev, uint32_t reg_off, uint8_t debug)
+{
+	int32_t reg_val;
+	switch(n_dev)
+	{
+		case 0:
+			reg_val = dev_read(intc_ptr, reg_off);
+			break;
+		case 1:
+			reg_val = dev_read(cfg_ptr, reg_off);
+			break;
+		case 2:
+			reg_val = dev_read(sts_ptr, reg_off);
+			break;
+		case 3:
+			reg_val = dev_read(xadc_ptr, reg_off);
+			break;
+		default:
+			printf("Invalid option: %d\n", n_dev);
+			return -1;
+	}
+	if(debug)
+		printf("Complete. Received data 0x%08x\n", reg_val);
+	//printf("Complete. Received data %d\n", reg_val);
+
+	return reg_val;
+}
+
+int32_t wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val, uint8_t debug)
+{
+	switch(n_dev)
+	{
+		case 0:
+			dev_write(intc_ptr, reg_off, reg_val);
+			break;
+		case 1:
+			dev_write(cfg_ptr, reg_off, reg_val);
+			break;
+		case 2:
+			dev_write(sts_ptr, reg_off, reg_val);
+			break;
+		case 3:
+			dev_write(xadc_ptr, reg_off, reg_val);
+			break;
+		default:
+			printf("Invalid option: %d\n", n_dev);
+			return -1;
+	}
+	if(debug)
+		printf("Complete. Data written: 0x%08x\n", reg_val);
+	//printf("Complete. Data written: %d\n", reg_val);
+
+	return 0;
+}
+
+int32_t rd_cfg_status(void)
+{
+	//float a = 0.0382061, b = 4.11435;  // For gain = 1.45
+	float a = 0.0882006, b = 7.73516;  // For gain = 3.2
+
+	printf("#Trigger Level Ch1 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_1_OFFSET));
+	printf("#Trigger Level Ch2 = %d\n", dev_read(cfg_ptr, CFG_TRLVL_2_OFFSET));
+	//printf("#Subtrigger Ch1    = %d\n", dev_read(cfg_ptr, CFG_STRLVL_1_OFFSET));
+	//printf("#Subtrigger Ch2    = %d\n", dev_read(cfg_ptr, CFG_STRLVL_2_OFFSET));
+	printf("#High Voltage 1    = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV1_OFFSET)+b);
+	printf("#High Voltage 2    = %.1f mV\n", a*dev_read(cfg_ptr, CFG_HV2_OFFSET)+b);
+	printf("#Trigger Scaler 1  = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_A_OFFSET));
+	printf("#Trigger Scaler 2  = %d\n", dev_read(cfg_ptr, CFG_TR_SCAL_B_OFFSET));
+	if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>4) & 0x1) == 1) { // No GPS is present
+		printf("#No GPS device is present or enabled\n");
+	}else{
+		printf("#Using GPS data\n");
+	}
+	if (((dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET)>>5) & 0x1) == 0) //Slave
+	{
+		printf("#Working mode is SLAVE\n");
+	}else{
+		printf("#Working mode is MASTER\n");
+	}
+	printf("\n");
+	printf("Status from registers complete!\n");
+	return 0;
+}
+
+static uint32_t get_memory_size(char *sysfs_path_file)
+{
+	FILE *size_fp;
+	uint32_t size;
+
+	// open the file that describes the memory range size that is based on
+	// the reg property of the node in the device tree
+	size_fp = fopen(sysfs_path_file, "r");
+
+	if (!size_fp) {
+		printf("unable to open the uio size file\n");
+		exit(-1);
+	}
+
+	// get the size which is an ASCII string such as 0xXXXXXXXX and then be
+	// stop using the file
+	if(fscanf(size_fp, "0x%08X", &size) == EOF){
+		printf("unable to get the size of the uio size file\n");
+		exit(-1);
+	}
+	fclose(size_fp);
+
+	return size;
+}
+
+int intc_init(void)
+{
+	char *uiod = "/dev/uio0";
+
+	//printf("Initializing INTC device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	intc_fd = open(uiod, O_RDWR);
+	if (intc_fd < 1) {
+		printf("intc_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio0/maps/map0/size");
+
+	// mmap the INTC device into user space
+	intc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, intc_fd, 0);
+	if (intc_ptr == MAP_FAILED) {
+		printf("intc_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int cfg_init(void)
+{
+	char *uiod = "/dev/uio1";
+
+	//printf("Initializing CFG device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	cfg_fd = open(uiod, O_RDWR);
+	if (cfg_fd < 1) {
+		printf("cfg_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio1/maps/map0/size");
+
+	// mmap the cfgC device into user space
+	cfg_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, cfg_fd, 0);
+	if (cfg_ptr == MAP_FAILED) {
+		printf("cfg_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int sts_init(void)
+{
+	char *uiod = "/dev/uio4";
+
+	//printf("Initializing STS device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	sts_fd = open(uiod, O_RDWR);
+	if (sts_fd < 1) {
+		printf("sts_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio4/maps/map0/size");
+
+	// mmap the STS device into user space
+	sts_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, sts_fd, 0);
+	if (sts_ptr == MAP_FAILED) {
+		printf("sts_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int xadc_init(void)
+{
+	char *uiod = "/dev/uio5";
+
+	//printf("Initializing XADC device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	xadc_fd = open(uiod, O_RDWR);
+	if (xadc_fd < 1) {
+		printf("xadc_init: Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio5/maps/map0/size"); 
+
+	// mmap the XADC device into user space
+	xadc_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, xadc_fd, 0);
+	if (xadc_ptr == MAP_FAILED) {
+		printf("xadc_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int mem_init(void)
+{
+	char *mem_name = "/dev/mem";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	mem_fd = open(mem_name, O_RDWR);
+	if (mem_fd < 1) {
+		printf("mem_init: Invalid device file:%s.\n", mem_name);
+		return -1;
+	}
+
+	dev_size = 2048*sysconf(_SC_PAGESIZE);
+
+	// mmap the mem device into user space 
+	mem_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0x1E000000);
+	if (mem_ptr == MAP_FAILED) {
+		printf("mem_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int hst0_init(void)
+{
+	char *mem_name = "/dev/mem";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	hst0_fd = open(mem_name, O_RDWR);
+	if (hst0_fd < 1) {
+		printf("hst0_init: Invalid device file:%s.\n", mem_name);
+		return -1;
+	}
+
+	// mmap the mem device into user space 
+	hst0_ptr = mmap(NULL, 16*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, hst0_fd, HST0_BASEADDR);
+	if (hst0_ptr == MAP_FAILED) {
+		printf("mem_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int hst1_init(void)
+{
+	char *mem_name = "/dev/mem";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	hst1_fd = open(mem_name, O_RDWR);
+	if (hst1_fd < 1) {
+		printf("hst1_init: Invalid device file:%s.\n", mem_name);
+		return -1;
+	}
+
+	// mmap the mem device into user space 
+	hst1_ptr = mmap(NULL, 16*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, hst1_fd, HST1_BASEADDR);
+	if (hst1_ptr == MAP_FAILED) {
+		printf("mem_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int cma_init(void)
+{
+	char *cma_name = "/dev/cma";
+
+	//printf("Initializing mem device...\n");
+
+	// open the UIO device file to allow access to the device in user space
+	cma_fd = open(cma_name, O_RDWR);
+	if (cma_fd < 1) {
+		printf("cma_init: Invalid device file:%s.\n", cma_name);
+		return -1;
+	}
+
+	dev_size = 1024*sysconf(_SC_PAGESIZE);
+
+	if(ioctl(cma_fd, CMA_ALLOC, &dev_size) < 0) {
+		perror("ioctl");
+		return EXIT_FAILURE;
+	}
+	// mmap the mem device into user space 
+	cma_ptr = mmap(NULL, 1024*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, cma_fd, 0);
+	if (cma_ptr == MAP_FAILED) {
+		printf("cma_init: mmap call failure.\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+float get_voltage(uint32_t offset)
+{
+	int16_t value;
+	value = (int16_t) dev_read(xadc_ptr, offset);
+	//  printf("The Voltage is: %lf V\n", (value>>4)*XADC_CONV_VAL);
+	return ((value>>4)*XADC_CONV_VAL);
+}       
+
+/*void set_voltage(uint32_t offset, int32_t value)
+	{       
+//fit after calibration. See file data_calib.txt in /ramp_test directory 
+// y = a*x + b
+//a               = 0.0382061     
+//b               = 4.11435   
+uint32_t dac_val;
+float a = 0.0382061, b = 4.11435; 
+
+dac_val = (uint32_t)(value - b)/a;
+
+dev_write(cfg_ptr, offset, dac_val);
+printf("The Voltage is: %d mV\n", value);
+printf("The DAC value is: %d DACs\n", dac_val);
+}
+*/
+
+void set_voltage(uint32_t offset, int32_t value)
+{       
+	//fit after calibration. See file data_calib2.txt in /ramp_test directory 
+	// y = a*x + b
+	//a               = 0.0882006     
+	//b               = 7.73516   
+	uint32_t dac_val;
+	float a = 0.0882006, b = 7.73516; 
+
+	dac_val = (uint32_t)(value - b)/a;
+
+	dev_write(cfg_ptr, offset, dac_val);
+	printf("The Voltage is: %d mV\n", value);
+	printf("The DAC value is: %d DACs\n", dac_val);
+}
+
+float get_temp_AD592(uint32_t offset)
+{
+	float value;
+	value = get_voltage(offset);
+	return ((value*1000)-273.15);
+}       
+
+//System initialization
+int init_system(void)
+{
+	uint32_t reg_val;
+
+	//FIXME: replace hardcoded values for defines
+	// set trigger_lvl_1
+	dev_write(cfg_ptr,CFG_TRLVL_1_OFFSET,8190);
+
+	// set trigger_lvl_2
+	dev_write(cfg_ptr,CFG_TRLVL_2_OFFSET,8190);
+
+	// set subtrigger_lvl_1
+	dev_write(cfg_ptr,CFG_STRLVL_1_OFFSET,8190);
+
+	// set subtrigger_lvl_2
+	dev_write(cfg_ptr,CFG_STRLVL_2_OFFSET,8190);
+
+	// set hv1 and hv2 to zero
+	dev_write(cfg_ptr,CFG_HV1_OFFSET,0);
+	dev_write(cfg_ptr,CFG_HV2_OFFSET,0);
+
+	// reset ramp generators
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~8);
+
+	// reset pps_gen, fifo and trigger modules
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~1);
+
+	/* reset data converter and writer */
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~4);
+
+	// enter reset mode for tlast_gen
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~2);
+
+	// set number of samples
+	dev_write(cfg_ptr,CFG_NSAMPLES_OFFSET, 1024 * 1024);
+
+	// set default value for trigger scalers a and b
+	dev_write(cfg_ptr,CFG_TR_SCAL_A_OFFSET, 1);
+	dev_write(cfg_ptr,CFG_TR_SCAL_B_OFFSET, 1);
+
+	// enter normal mode for tlast_gen
+	/*        reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 2);
+	//printf("written reg_val tlast : 0x%08x\n",reg_val | 2);
+	// enter normal mode for pps_gen, fifo and trigger modules
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 1);
+	//printf("written reg_val pps_gen, fifo : 0x%08x\n",reg_val | 1);
+	*/
+	// enable false GPS
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	//printf("reg_val : 0x%08x\n",reg_val);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | FGPS_EN_MASK);
+	//printf("written reg_val : 0x%08x\n",reg_val | 16);
+	// disable
+	//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~16);
+	//dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val & ~FGPS_EN_MASK);
+	//printf("written reg_val : 0x%08x\n",reg_val & ~16);
+
+	/*        // enter normal mode for data converter and writer
+						reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+						dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 4);
+	//printf("written reg_val : 0x%08hx\n",reg_val | 4);
+	*/
+	// enter normal mode for ramp generators
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 8);
+	// enter in MASTER mode (default)
+	reg_val = dev_read(cfg_ptr, CFG_RESET_GRAL_OFFSET);
+	dev_write(cfg_ptr,CFG_RESET_GRAL_OFFSET, reg_val | 0x20);
+
+	return 0;
+}
+
+int enable_interrupt(void)
+{
+	// steps to accept interrupts -> as pg. 26 of pg099-axi-intc.pdf
+	//1) Each bit in the IER corresponding to an interrupt must be set to 1.
+	dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 1);
+	//2) There are two bits in the MER. The ME bit must be set to enable the
+	//interrupt request outputs.
+	dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK | XIL_AXI_INTC_MER_HIE_MASK);
+	//dev_write(dev_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK);
+
+	//The next block of code is to test interrupts by software
+	//3) Software testing can now proceed by writing a 1 to any bit position
+	//in the ISR that corresponds to an existing interrupt input.
+	/*        dev_write(intc_ptr,XIL_AXI_INTC_IPR_OFFSET, 1);
+
+						for(a=0; a<10; a++)
+						{
+						wait_for_interrupt(fd, dev_ptr);
+						dev_write(dev_ptr,XIL_AXI_INTC_ISR_OFFSET, 1); //regenerate interrupt
+						}
+						*/
+	return 0;
+
+}
+
+int disable_interrupt(void)
+{
+	uint32_t value;
+	//Disable interrupt INTC0
+	dev_write(intc_ptr,XIL_AXI_INTC_IER_OFFSET, 0);
+	//disable IRQ
+	value = dev_read(intc_ptr, XIL_AXI_INTC_MER_OFFSET);
+	dev_write(intc_ptr,XIL_AXI_INTC_MER_OFFSET, value | ~1);
+	//Acknowledge any previous interrupt
+	dev_write(intc_ptr, XIL_AXI_INTC_IAR_OFFSET, 1);
+
+	return 0;
+}
+
diff --git a/projects/lago_v1_3/src/zynq_io.h b/projects/lago_v1_3/src/zynq_io.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba466da87eadb67d983e57d2e42340f23a0eb3dd
--- /dev/null
+++ b/projects/lago_v1_3/src/zynq_io.h
@@ -0,0 +1,163 @@
+#ifndef _ZYNQ_IO_H_
+#define _ZYNQ_IO_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#define CMA_ALLOC _IOWR('Z', 0, uint32_t)
+#define INTC_BASEADDR 0x40000000
+#define INTC_HIGHADDR 0x40000FFF
+
+#define CFG_BASEADDR  0x40001000
+#define CFG_HIGHADDR  0x40001FFF
+
+#define STS_BASEADDR  0x40002000
+#define STS_HIGHADDR  0x40002FFF
+
+#define XADC_BASEADDR 0x40003000
+#define XADC_HIGHADDR 0x40003FFF
+
+#define HST0_BASEADDR 0x40010000
+#define HST0_HIGHADDR 0x4001FFFF
+
+#define HST1_BASEADDR 0x40020000
+#define HST1_HIGHADDR 0x4002FFFF
+
+#define XIL_AXI_INTC_ISR_OFFSET    0x0
+#define XIL_AXI_INTC_IPR_OFFSET    0x4
+#define XIL_AXI_INTC_IER_OFFSET    0x8
+#define XIL_AXI_INTC_IAR_OFFSET    0xC
+#define XIL_AXI_INTC_SIE_OFFSET    0x10
+#define XIL_AXI_INTC_CIE_OFFSET    0x14
+#define XIL_AXI_INTC_IVR_OFFSET    0x18
+#define XIL_AXI_INTC_MER_OFFSET    0x1C
+#define XIL_AXI_INTC_IMR_OFFSET    0x20
+#define XIL_AXI_INTC_ILR_OFFSET    0x24
+#define XIL_AXI_INTC_IVAR_OFFSET   0x100
+
+#define XIL_AXI_INTC_MER_ME_MASK 0x00000001
+#define XIL_AXI_INTC_MER_HIE_MASK 0x00000002
+
+//CFG
+#define CFG_RESET_GRAL_OFFSET    0x0
+#define CFG_NSAMPLES_OFFSET      0x4
+#define CFG_TRLVL_1_OFFSET       0x8
+#define CFG_TRLVL_2_OFFSET       0xC
+#define CFG_STRLVL_1_OFFSET      0x10
+#define CFG_STRLVL_2_OFFSET      0x14
+#define CFG_TEMPERATURE_OFFSET   0x18
+#define CFG_PRESSURE_OFFSET      0x1C
+#define CFG_TIME_OFFSET          0x20
+#define CFG_DATE_OFFSET          0x24
+#define CFG_LATITUDE_OFFSET      0x28
+#define CFG_LONGITUDE_OFFSET     0x2C
+#define CFG_ALTITUDE_OFFSET      0x30
+#define CFG_SATELLITE_OFFSET     0x34
+#define CFG_TR_SCAL_A_OFFSET     0x38
+#define CFG_TR_SCAL_B_OFFSET     0x3C
+#define CFG_HV1_OFFSET           0x4C //DAC_PWM3
+#define CFG_HV2_OFFSET           0x48 //DAC_PWM2
+#define CFG_HV3_OFFSET           0x40 //DAC_PWM0
+#define CFG_HV4_OFFSET           0x44 //DAC_PWM1
+#define CFG_HST0_OFFSET          0x50
+#define CFG_HST1_OFFSET          0x54
+#define CFG_WR_ADDR_OFFSET       0x58 //writer address
+
+//CFG Slow DAC
+#define CFG_DAC_PWM0_OFFSET 0x40
+#define CFG_DAC_PWM1_OFFSET 0x44
+#define CFG_DAC_PWM2_OFFSET 0x48
+#define CFG_DAC_PWM3_OFFSET 0x4C
+
+#define ENBL_ALL_MASK         0xFFFFFFFF
+#define RST_ALL_MASK          0x00000000
+#define RST_PPS_TRG_FIFO_MASK 0x00000001
+#define RST_TLAST_GEN_MASK    0x00000002
+#define RST_WRITER_MASK       0x00000004
+#define RST_AO_MASK           0x00000008
+#define FGPS_EN_MASK          0x00000010
+
+//STS
+#define STS_STATUS_OFFSET     0x0
+
+//XADC
+//See page 17 of PG091
+#define XADC_SRR_OFFSET          0x00   //Software reset register
+#define XADC_SR_OFFSET           0x04   //Status Register
+#define XADC_AOSR_OFFSET         0x08   //Alarm Out Status Register
+#define XADC_CONVSTR_OFFSET      0x0C   //CONVST Register
+#define XADC_SYSMONRR_OFFSET     0x10   //XADC Reset Register
+#define XADC_GIER_OFFSET         0x5C   //Global Interrupt Enable Register
+#define XADC_IPISR_OFFSET        0x60   //IP Interrupt Status Register
+#define XADC_IPIER_OFFSET        0x68   //IP Interrupt Enable Register
+#define XADC_TEMPERATURE_OFFSET  0x200  //Temperature
+#define XADC_VCCINT_OFFSET       0x204  //VCCINT
+#define XADC_VCCAUX_OFFSET       0x208  //VCCAUX
+#define XADC_VPVN_OFFSET         0x20C  //VP/VN
+#define XADC_VREFP_OFFSET        0x210  //VREFP
+#define XADC_VREFN_OFFSET        0x214  //VREFN
+#define XADC_VBRAM_OFFSET        0x218  //VBRAM
+#define XADC_UNDEF_OFFSET        0x21C  //Undefined
+#define XADC_SPLYOFF_OFFSET      0x220  //Supply Offset
+#define XADC_ADCOFF_OFFSET       0x224  //ADC Offset
+#define XADC_GAIN_ERR_OFFSET     0x228  //Gain Error
+#define XADC_ZDC_SPLY_OFFSET     0x234  //Zynq-7000 Device Core Supply
+#define XADC_ZDC_AUX_SPLY_OFFSET 0x238  //Zynq-7000 Device Core Aux Supply
+#define XADC_ZDC_MEM_SPLY_OFFSET 0x23C  //Zynq-7000 Device Core Memory Supply
+#define XADC_VAUX_PN_0_OFFSET    0x240  //VAUXP[0]/VAUXN[0]
+#define XADC_VAUX_PN_1_OFFSET    0x244  //VAUXP[1]/VAUXN[1]
+#define XADC_VAUX_PN_2_OFFSET    0x248  //VAUXP[2]/VAUXN[2]
+#define XADC_VAUX_PN_3_OFFSET    0x24C  //VAUXP[3]/VAUXN[3]
+#define XADC_VAUX_PN_4_OFFSET    0x250  //VAUXP[4]/VAUXN[4]
+#define XADC_VAUX_PN_5_OFFSET    0x254  //VAUXP[5]/VAUXN[5]
+#define XADC_VAUX_PN_6_OFFSET    0x258  //VAUXP[6]/VAUXN[6]
+#define XADC_VAUX_PN_7_OFFSET    0x25C  //VAUXP[7]/VAUXN[7]
+#define XADC_VAUX_PN_8_OFFSET    0x260  //VAUXP[8]/VAUXN[8]
+#define XADC_VAUX_PN_9_OFFSET    0x264  //VAUXP[9]/VAUXN[9]
+#define XADC_VAUX_PN_10_OFFSET   0x268  //VAUXP[10]/VAUXN[10]
+#define XADC_VAUX_PN_11_OFFSET   0x26C  //VAUXP[11]/VAUXN[11]
+#define XADC_VAUX_PN_12_OFFSET   0x270  //VAUXP[12]/VAUXN[12]
+#define XADC_VAUX_PN_13_OFFSET   0x274  //VAUXP[13]/VAUXN[13]
+#define XADC_VAUX_PN_14_OFFSET   0x278  //VAUXP[14]/VAUXN[14]
+#define XADC_VAUX_PN_15_OFFSET   0x27C  //VAUXP[15]/VAUXN[15]
+
+#define XADC_AI0_OFFSET XADC_VAUX_PN_8_OFFSET
+#define XADC_AI1_OFFSET XADC_VAUX_PN_0_OFFSET
+#define XADC_AI2_OFFSET XADC_VAUX_PN_1_OFFSET
+#define XADC_AI3_OFFSET XADC_VAUX_PN_9_OFFSET
+
+#define XADC_CONV_VAL 0.00171191993362 //(A_ip/2^12)*(34.99/4.99)
+#define XADC_RDIV_VAL 1.883236177     //voltage divisor in board (15k+16.983k)/16.983k = 1.88
+#define XADC_BASE_HVDIV 0.00294088    //voltage divisor in HV base board (100k/31.3Meg) = 3.194888179. The value I put here is the measured one.
+
+extern int intc_fd, cfg_fd, sts_fd, xadc_fd, mem_fd, hst0_fd, hst1_fd, cma_fd;
+extern void *intc_ptr, *cfg_ptr, *sts_ptr, *xadc_ptr, *mem_ptr, *hst0_ptr, *hst1_ptr;
+extern volatile int16_t *cma_ptr;
+extern uint32_t dev_size;
+
+void     dev_write(void *dev_base, uint32_t offset, int32_t value);
+uint32_t dev_read(void *dev_base, uint32_t offset);
+//int    dev_init(int n_dev);
+int32_t  rd_reg_value(int n_dev, uint32_t reg_off, uint8_t degug);
+int32_t  wr_reg_value(int n_dev, uint32_t reg_off, int32_t reg_val, uint8_t debug);
+int32_t  rd_cfg_status(void);
+int      intc_init(void);
+int      cfg_init(void);
+int      sts_init(void);
+int      xadc_init(void);
+int      mem_init(void);
+int      cma_init(void);
+float    get_voltage(uint32_t offset);
+void     set_voltage(uint32_t offset, int32_t value);
+float    get_temp_AD592(uint32_t offset);
+int      init_system(void);
+int      enable_interrupt(void);
+int      disable_interrupt(void);
+
+#endif
+
diff --git a/projects/led_blinker/app/index.html b/projects/led_blinker/app/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..11f7dfe5413654d2d0510fad5afa1ea8374eff22
--- /dev/null
+++ b/projects/led_blinker/app/index.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>LED blinker</title>
+<link rel="stylesheet" href="/css/main.css">
+<link rel="stylesheet" href="/css/pygments.css">
+</head>
+<body>
+<div id="header">
+<div id="logo">
+<a href="/">Back to all apps</a>
+</div>
+<div id="menu">
+<a href="https://github.com/pavel-demin/red-pitaya-notes" target="_blank">Source</a>
+<a href="https://github.com/pavel-demin/red-pitaya-notes/issues" target="_blank">Issues</a>
+</div>
+</div>
+<div id="content">
+<h1>LED blinker</h1>
+<p>The LED blinker application is ready.</p>
+</div>
+</body>
+</html>
diff --git a/projects/led_blinker/app/start.sh b/projects/led_blinker/app/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..c2cb31d1eefd065502e603fdbe0b6b3e6c4f59c1
--- /dev/null
+++ b/projects/led_blinker/app/start.sh
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+apps_dir=/media/mmcblk0p1/apps
+
+source $apps_dir/stop.sh
+
+cat $apps_dir/led_blinker/led_blinker.bit > /dev/xdevcfg
diff --git a/projects/led_blinker/block_design.tcl b/projects/led_blinker/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..e9d794f47d206af9ca96933d876cd9726adf6cac
--- /dev/null
+++ b/projects/led_blinker/block_design.tcl
@@ -0,0 +1,55 @@
+source projects/base_system/block_design.tcl
+
+# Create xlconstant
+cell xilinx.com:ip:xlconstant const_0
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0 {} {
+  ext_reset_in const_0/dout
+}
+
+# LED
+
+# Create c_counter_binary
+cell xilinx.com:ip:c_counter_binary cntr_0 {
+  Output_Width 32
+} {
+  CLK pll_0/clk_out1
+}
+
+# Create port_slicer
+cell labdpr:user:port_slicer slice_0 {
+  DIN_WIDTH 32 DIN_FROM 26 DIN_TO 26
+} {
+  din cntr_0/Q
+  dout led_o
+}
+
+# STS
+
+# Create dna_reader
+cell labdpr:user:dna_reader dna_0 {} {
+  aclk pll_0/clk_out1
+  aresetn rst_0/peripheral_aresetn
+}
+
+# Create xlconcat
+cell xilinx.com:ip:xlconcat concat_0 {
+  NUM_PORTS 2
+  IN0_WIDTH 32
+  IN1_WIDTH 64
+} {
+  In0 const_0/dout
+  In1 dna_0/dna_data
+}
+
+# Create axi_sts_register
+cell labdpr:user:axi_sts_register sts_0 {
+  STS_DATA_WIDTH 96
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+} {
+  sts_data concat_0/dout
+}
+
+addr 0x40002000 4K sts_0/S_AXI /ps_0/M_AXI_GP0
diff --git a/projects/ramp_test/block_design.tcl b/projects/ramp_test/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..ff3d05000f76744f219f586d193a097f1ccb8dad
--- /dev/null
+++ b/projects/ramp_test/block_design.tcl
@@ -0,0 +1,47 @@
+source projects/base_system/block_design.tcl
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset rst_0
+
+# Create axi_cfg_register
+cell labdpr:user:axi_cfg_register cfg_0 {
+  CFG_DATA_WIDTH 96
+  AXI_ADDR_WIDTH 32
+  AXI_DATA_WIDTH 32
+}
+
+# Create xlslice
+cell xilinx.com:ip:xlslice slice_1 {
+  DIN_WIDTH 96 DIN_FROM 0 DIN_TO 0 DOUT_WIDTH 1
+} {
+  Din cfg_0/cfg_data
+}
+
+# Create xlslice. Change the frequency
+cell xilinx.com:ip:xlslice slice_2 {
+  DIN_WIDTH 96 DIN_FROM 47 DIN_TO 32 DOUT_WIDTH 16
+} {
+  Din cfg_0/cfg_data
+}
+
+#Create PWM generator
+cell labdpr:user:ramp_gen ramp_gen_0 {
+  COUNT_NBITS 20
+  COUNT_MOD 5000
+  DATA_BITS 16
+} {
+  aclk ps_0/FCLK_CLK0
+  aresetn slice_1/Dout
+  data_i slice_2/Dout
+  pwm_o dac_pwm_o
+}
+
+# Create all required interconnections
+apply_bd_automation -rule xilinx.com:bd_rule:axi4 -config {
+  Master /ps_0/M_AXI_GP0
+  Clk Auto
+} [get_bd_intf_pins cfg_0/S_AXI]
+
+set_property RANGE 4K [get_bd_addr_segs ps_0/Data/SEG_cfg_0_reg0]
+set_property OFFSET 0x40000000 [get_bd_addr_segs ps_0/Data/SEG_cfg_0_reg0]
+
diff --git a/projects/ramp_test/ramp_test.c b/projects/ramp_test/ramp_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..e4dc57380d81813d346a4cc1f5f5f2fb8e0e9bd4
--- /dev/null
+++ b/projects/ramp_test/ramp_test.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#define VERSION "0.1"
+int main(int argc, char *argv[])
+{
+  int mfd, i;
+  uint32_t wo;
+  int16_t ch[2];
+  void *cfg, *ram;
+  char *name = "/dev/mem";
+  int32_t mtd_dp = 0, mtd_cdp = 0, mtd_pulse_cnt = 0, mtd_pulse_pnt = 0;
+
+  printf("%d\n",argc);
+
+  if (argc<1) {
+    printf("%s version %s\n",argv[0],VERSION);
+    printf("The clock freq. is 143MHz and the PWM signal freq. is 1.06 Hz (T aprox. 0.93s)\n");
+    printf("Syntax: %s [pwm value](from 0 to 2**27-1)\n  ex: %s 10000 \n", argv[0], argv[0]);
+    printf("for ~ 70 us PWM signal in state '1' and the rest in state \n");
+    printf("'0' up to ~0.94s)\n");
+    exit(EXIT_FAILURE);
+  }
+
+  if((mfd = open(name, O_RDWR)) < 0)
+  {
+    perror("open");
+    return 1;
+  }
+
+  cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, mfd, 0x40000000);
+
+  // reset pwm_gen
+  *((uint32_t *)(cfg + 0)) &= ~1;
+  *((uint32_t *)(cfg + 0)) |= 1;
+
+
+  // set trigger_lvl_a
+  *((uint32_t *)(cfg + 4)) = atoi(argv[1]);
+
+
+  // print IN1 and IN2 samples
+//  for(i = 0; i < 64; ++i)
+//  {
+//    ch[0] = *((int16_t *)(cfg + i));
+//    //ch[1] = *((int16_t *)(ram + 4*i + 2));
+//    printf("%5d \n", (ch[0]>>4));
+//  }
+
+
+  munmap(cfg, sysconf(_SC_PAGESIZE));
+
+  return 0;
+}
diff --git a/projects/xadc_test/block_design.tcl b/projects/xadc_test/block_design.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..ecf33424a75c116b3aace72ae146abecc2b34f23
--- /dev/null
+++ b/projects/xadc_test/block_design.tcl
@@ -0,0 +1,49 @@
+source projects/base_system/block_design.tcl
+
+# Create proc_sys_reset
+cell xilinx.com:ip:proc_sys_reset:5.0 rst_0
+
+# Create xadc
+cell xilinx.com:ip:xadc_wiz:3.3 xadc_wiz_0 {
+  XADC_STARUP_SELECTION channel_sequencer 
+  OT_ALARM false
+  USER_TEMP_ALARM false 
+  VCCINT_ALARM false 
+  VCCAUX_ALARM false
+  ENABLE_VCCPINT_ALARM false 
+  ENABLE_VCCPAUX_ALARM false
+  ENABLE_VCCDDRO_ALARM false 
+  CHANNEL_ENABLE_CALIBRATION true
+  CHANNEL_ENABLE_TEMPERATURE true 
+  CHANNEL_ENABLE_VCCINT true
+  CHANNEL_ENABLE_VP_VN true
+  CHANNEL_ENABLE_VAUXP0_VAUXN0 true 
+  CHANNEL_ENABLE_VAUXP1_VAUXN1 true 
+  CHANNEL_ENABLE_VAUXP8_VAUXN8 true
+  CHANNEL_ENABLE_VAUXP9_VAUXN9 true 
+  AVERAGE_ENABLE_VP_VN true
+  AVERAGE_ENABLE_VAUXP0_VAUXN0 true 
+  AVERAGE_ENABLE_VAUXP1_VAUXN1 true 
+  AVERAGE_ENABLE_VAUXP8_VAUXN8 true
+  AVERAGE_ENABLE_VAUXP9_VAUXN9 true 
+  AVERAGE_ENABLE_TEMPERATURE true 
+  AVERAGE_ENABLE_VCCINT true 
+  EXTERNAL_MUX_CHANNEL VP_VN 
+  SINGLE_CHANNEL_SELECTION TEMPERATURE 
+} {}
+
+connect_bd_intf_net [get_bd_intf_ports Vp_Vn] [get_bd_intf_pins xadc_wiz_0/Vp_Vn]
+connect_bd_intf_net [get_bd_intf_ports Vaux0] [get_bd_intf_pins xadc_wiz_0/Vaux0]
+connect_bd_intf_net [get_bd_intf_ports Vaux1] [get_bd_intf_pins xadc_wiz_0/Vaux1]
+connect_bd_intf_net [get_bd_intf_ports Vaux8] [get_bd_intf_pins xadc_wiz_0/Vaux8]
+connect_bd_intf_net [get_bd_intf_ports Vaux9] [get_bd_intf_pins xadc_wiz_0/Vaux9]
+
+# Create all required interconnections
+apply_bd_automation -rule xilinx.com:bd_rule:axi4 -config {
+  Master /ps_0/M_AXI_GP0
+  Clk Auto 
+} [get_bd_intf_pins xadc_wiz_0/s_axi_lite]
+
+set_property range 4K [get_bd_addr_segs {ps_0/Data/SEG_xadc_wiz_0_Reg}]
+set_property offset 0x40001000 [get_bd_addr_segs {ps_0/Data/SEG_xadc_wiz_0_Reg}]
+
diff --git a/projects/xadc_test/xadc_test.c b/projects/xadc_test/xadc_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..1bdbc6c5184d1de740ca1af39b8d4a14848206bb
--- /dev/null
+++ b/projects/xadc_test/xadc_test.c
@@ -0,0 +1,119 @@
+/*
+ * devmem2.c: Simple program to read/write from/to any location in memory.
+ *
+ *  Copyright (C) 2000, Jan-Derk Bakker (jdb@lartmaker.nl)
+ *
+ *
+ * This software has been developed for the LART computing board
+ * (http://www.lart.tudelft.nl/). The development has been sponsored by
+ * the Mobile MultiMedia Communications (http://www.mmc.tudelft.nl/)
+ * and Ubiquitous Communications (http://www.ubicom.tudelft.nl/)
+ * projects.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as  published by
+ * the Free Software Foundation; either version 2 of the   License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <termios.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+
+#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", \
+		__LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
+
+#define MAP_SIZE 4096UL
+#define MAP_MASK (MAP_SIZE - 1)
+
+int main(int argc, char **argv) {
+	int fd;
+	void *map_base, *virt_addr; 
+	unsigned long read_result, writeval;
+	off_t target;
+	int access_type = 'w';
+
+	if(argc < 2) {
+		fprintf(stderr, "\nUsage:\t%s { address } [ type [ data ] ]\n"
+				"\taddress : memory address to act upon\n"
+				"\ttype    : access operation type : [b]yte, [h]alfword, [w]ord\n"
+				"\tdata    : data to be written\n\n",
+				argv[0]);
+		exit(1);
+	}
+	target = strtoul(argv[1], 0, 0);
+
+	if(argc > 2)
+		access_type = tolower(argv[2][0]);
+
+
+	if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
+	printf("/dev/mem opened.\n"); 
+	fflush(stdout);
+
+	/* Map one page */
+	map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
+	if(map_base == (void *) -1) FATAL;
+	printf("Memory mapped at address %p.\n", map_base); 
+	fflush(stdout);
+
+	virt_addr = map_base + (target & MAP_MASK);
+	switch(access_type) {
+		case 'b':
+			read_result = *((unsigned char *) virt_addr);
+			break;
+		case 'h':
+			read_result = *((unsigned short *) virt_addr);
+			break;
+		case 'w':
+			read_result = *((unsigned long *) virt_addr);
+			break;
+		default:
+			fprintf(stderr, "Illegal data type '%c'.\n", access_type);
+			exit(2);
+	}
+	printf("Value at address 0x%X (%p): 0x%X\n", target, virt_addr, read_result); 
+	fflush(stdout);
+
+	if(argc > 3) {
+		writeval = strtoul(argv[3], 0, 0);
+		switch(access_type) {
+			case 'b':
+				*((unsigned char *) virt_addr) = writeval;
+				read_result = *((unsigned char *) virt_addr);
+				break;
+			case 'h':
+				*((unsigned short *) virt_addr) = writeval;
+				read_result = *((unsigned short *) virt_addr);
+				break;
+			case 'w':
+				*((unsigned long *) virt_addr) = writeval;
+				read_result = *((unsigned long *) virt_addr);
+				break;
+		}
+		printf("Written 0x%X; readback 0x%X\n", writeval, read_result); 
+		fflush(stdout);
+	}
+
+	if(munmap(map_base, MAP_SIZE) == -1) FATAL;
+	close(fd);
+	return 0;
+}
diff --git a/projects/xadc_test/xadc_uio.c b/projects/xadc_test/xadc_uio.c
new file mode 100644
index 0000000000000000000000000000000000000000..7d35b0c51e9fdffe5495aa389a94508f55a2fc94
--- /dev/null
+++ b/projects/xadc_test/xadc_uio.c
@@ -0,0 +1,266 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <poll.h>
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+//See page 17 of PG091
+#define XADC_SRR_OFFSET          0x00	//Software reset register
+#define XADC_SR_OFFSET           0x04	//Status Register
+#define XADC_AOSR_OFFSET         0x08	//Alarm Out Status Register
+#define XADC_CONVSTR_OFFSET      0x0C	//CONVST Register
+#define XADC_SYSMONRR_OFFSET     0x10	//XADC Reset Register
+#define XADC_GIER_OFFSET         0x5C	//Global Interrupt Enable Register
+#define XADC_IPISR_OFFSET        0x60	//IP Interrupt Status Register
+#define XADC_IPIER_OFFSET        0x68	//IP Interrupt Enable Register
+#define XADC_TEMPERATURE_OFFSET  0x200	//Temperature
+#define XADC_VCCINT_OFFSET       0x204	//VCCINT
+#define XADC_VCCAUX_OFFSET       0x208	//VCCAUX
+#define XADC_VPVN_OFFSET         0x20C	//VP/VN
+#define XADC_VREFP_OFFSET        0x210	//VREFP
+#define XADC_VREFN_OFFSET        0x214	//VREFN
+#define XADC_VBRAM_OFFSET        0x218	//VBRAM
+#define XADC_UNDEF_OFFSET        0x21C	//Undefined
+#define XADC_SPLYOFF_OFFSET      0x220	//Supply Offset
+#define XADC_ADCOFF_OFFSET       0x224	//ADC Offset
+#define XADC_GAIN_ERR_OFFSET     0x228	//Gain Error
+#define XADC_ZDC_SPLY_OFFSET     0x234	//Zynq-7000 Device Core Supply
+#define XADC_ZDC_AUX_SPLY_OFFSET 0x238	//Zynq-7000 Device Core Aux Supply
+#define XADC_ZDC_MEM_SPLY_OFFSET 0x23C	//Zynq-7000 Device Core Memory Supply
+#define XADC_VAUX_PN_0_OFFSET    0x240	//VAUXP[0]/VAUXN[0]
+#define XADC_VAUX_PN_1_OFFSET    0x244	//VAUXP[1]/VAUXN[1]
+#define XADC_VAUX_PN_2_OFFSET    0x248	//VAUXP[2]/VAUXN[2]
+#define XADC_VAUX_PN_3_OFFSET    0x24C	//VAUXP[3]/VAUXN[3]
+#define XADC_VAUX_PN_4_OFFSET    0x250	//VAUXP[4]/VAUXN[4]
+#define XADC_VAUX_PN_5_OFFSET    0x254	//VAUXP[5]/VAUXN[5]
+#define XADC_VAUX_PN_6_OFFSET    0x258	//VAUXP[6]/VAUXN[6]
+#define XADC_VAUX_PN_7_OFFSET    0x25C	//VAUXP[7]/VAUXN[7]
+#define XADC_VAUX_PN_8_OFFSET    0x260	//VAUXP[8]/VAUXN[8]
+#define XADC_VAUX_PN_9_OFFSET    0x264	//VAUXP[9]/VAUXN[9]
+#define XADC_VAUX_PN_10_OFFSET   0x268	//VAUXP[10]/VAUXN[10]
+#define XADC_VAUX_PN_11_OFFSET   0x26C	//VAUXP[11]/VAUXN[11]
+#define XADC_VAUX_PN_12_OFFSET   0x270	//VAUXP[12]/VAUXN[12]
+#define XADC_VAUX_PN_13_OFFSET   0x274	//VAUXP[13]/VAUXN[13]
+#define XADC_VAUX_PN_14_OFFSET   0x278	//VAUXP[14]/VAUXN[14]
+#define XADC_VAUX_PN_15_OFFSET   0x27C	//VAUXP[15]/VAUXN[15]
+
+#define XADC_AI0_OFFSET XADC_VAUX_PN_8_OFFSET
+#define XADC_AI1_OFFSET XADC_VAUX_PN_0_OFFSET
+#define XADC_AI2_OFFSET XADC_VAUX_PN_1_OFFSET
+#define XADC_AI3_OFFSET XADC_VAUX_PN_9_OFFSET
+
+#define XADC_CONV_VAL 0.00171191993362
+#define XADC_RDIV_VAL 1.798     //voltage divisor in board (15k+16.983k)/16.983k
+
+int interrupted = 0;
+
+void signal_handler(int sig)
+{
+	interrupted = 1;
+}
+
+inline void dev_write(void *dev_base, unsigned int offset, unsigned int value)
+{
+	*((volatile unsigned *)(dev_base + offset)) = value;
+}
+
+inline unsigned int dev_read(void *dev_base, unsigned int offset)
+{
+	return *((volatile unsigned *)(dev_base + offset));
+}
+
+/*int wait_for_interrupt(int fd_int, void *dev_ptr) 
+  {
+  static unsigned int count = 0, bntd_flag = 0, bntu_flag = 0;
+  int flag_end=0;
+  int pending = 0;
+  int reenable = 1;
+  unsigned int reg;
+  unsigned int value;
+  uint32_t info = 1; // unmask
+
+  ssize_t nb = write(fd_int, &info, sizeof(info));
+  if (nb != (ssize_t)sizeof(info)) {
+  perror("write");
+  close(fd_int);
+  exit(EXIT_FAILURE);
+  }
+
+// block (timeout for poll) on the file waiting for an interrupt 
+struct pollfd fds = {
+.fd = fd_int,
+.events = POLLIN,
+};
+
+int ret = poll(&fds, 1, 8000);
+printf("ret is : %d\n", ret);
+if (ret >= 1) {
+nb = read(fd_int, &info, sizeof(info));
+if (nb == (ssize_t)sizeof(info)) {
+// Do something in response to the interrupt. 
+value = dev_read(dev_ptr, XIL_AXI_INTC_IPR_OFFSET);
+if ((value & 0x00000001) != 0) {
+dev_write(dev_ptr, XIL_AXI_INTC_IAR_OFFSET, 1);
+printf("Interrupt #%u!\n", info);
+}
+} else {
+perror("poll()");
+close(fd_int);
+exit(EXIT_FAILURE);
+}
+}
+
+return ret;
+}*/
+
+unsigned int get_memory_size(char *sysfs_path_file)
+{
+	FILE *size_fp;
+	unsigned int size;
+
+	// open the file that describes the memory range size that is based on the
+	// reg property of the node in the device tree
+
+	size_fp = fopen(sysfs_path_file, "r");
+
+	if (!size_fp) {
+		printf("unable to open the uio size file\n");
+		exit(-1);
+	}
+
+	// get the size which is an ASCII string such as 0xXXXXXXXX and then be stop
+	// using the file
+
+	fscanf(size_fp, "0x%08X", &size);
+	fclose(size_fp);
+
+	return size;
+}
+
+/*void *thread_isr(void *p) 
+  {
+  wait_for_interrupt(fd, dev_ptr);
+
+  }*/
+
+int main(int argc, char *argv[])
+{
+	int fd;
+	char *uiod = "/dev/uio3";
+	void *dev_ptr;
+	int dev_size;
+	int ocm_size;
+	int i, p=0,a;
+	unsigned int val;
+	int16_t value;  
+	float rvalue;
+	pthread_t t1;
+
+
+	signal(SIGINT, signal_handler);
+
+	printf("INTC UIO int test.\n");
+
+	// open the UIO device file to allow access to the device in user space
+
+	fd = open(uiod, O_RDWR);
+	if (fd < 1) {
+		printf("Invalid UIO device file:%s.\n", uiod);
+		return -1;
+	}
+
+	dev_size = get_memory_size("/sys/class/uio/uio3/maps/map0/size");
+
+	// mmap the INTC device into user space
+
+	dev_ptr = mmap(NULL, dev_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+	if (dev_ptr == MAP_FAILED) {
+		printf("mmap call failure.\n");
+		return -1;
+	}
+
+	value = (int16_t) dev_read(dev_ptr, XADC_AI0_OFFSET);
+	printf("The Voltage at pin AI0 is: %lf V\n", (value>>4)*XADC_CONV_VAL*XADC_RDIV_VAL);
+	value = (int16_t) dev_read(dev_ptr, XADC_AI1_OFFSET);
+	printf("The Voltage at pin AI1 is: %lf V\n", (value>>4)*XADC_CONV_VAL*XADC_RDIV_VAL);
+	value = (int16_t) dev_read(dev_ptr, XADC_AI2_OFFSET);
+	printf("The Voltage at pin AI2 is: %lf V\n", (value>>4)*XADC_CONV_VAL*XADC_RDIV_VAL);
+	value = (int16_t) dev_read(dev_ptr, XADC_AI3_OFFSET);
+	printf("The Voltage at pin AI3 is: %lf V\n", (value>>4)*XADC_CONV_VAL*XADC_RDIV_VAL);
+
+	//Temperature read
+	value = (uint16_t) dev_read(dev_ptr, XADC_TEMPERATURE_OFFSET);
+	printf("The internal temperature is: %lf degC\n", (((value>>4)*503.975)/65536) - 273.15);
+	printf("The internal temperature is: %d degC\n", (value>>4));
+
+	//Supply coefficient offset
+	value = (int16_t) dev_read(dev_ptr, XADC_SPLYOFF_OFFSET);
+	printf("The supply coeff. offset is: %04x \n", value);
+	//VCCINT read
+	value = (int16_t) dev_read(dev_ptr, XADC_VPVN_OFFSET);
+	printf("The internal VCCINT is: %lf V\n", (((value>>4))/4096)*3.0);
+	// steps to accept interrupts -> as pg. 26 of pg099-axi-intc.pdf
+	//1) Each bit in the IER corresponding to an interrupt must be set to 1.
+	//dev_write(dev_ptr,XIL_AXI_INTC_IER_OFFSET, 1);
+	//2) There are two bits in the MER. The ME bit must be set to enable the
+	//interrupt request outputs.
+	//dev_write(dev_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK | XIL_AXI_INTC_MER_HIE_MASK);
+	//				dev_write(dev_ptr,XIL_AXI_INTC_MER_OFFSET, XIL_AXI_INTC_MER_ME_MASK);
+
+	//The next block of code is to test interrupts by software
+	//3) Software testing can now proceed by writing a 1 to any bit position
+	//in the ISR that corresponds to an existing interrupt input.
+	//       dev_write(dev_ptr,XIL_AXI_INTC_ISR_OFFSET, 1);
+
+	//        for(a=0; a<10; a++)
+	//        {
+	//         wait_for_interrupt(fd, dev_ptr);
+	//         dev_write(dev_ptr,XIL_AXI_INTC_ISR_OFFSET, 1); //regenerate interrupt
+	//        }
+	//
+	//
+
+	//while(!interrupted) wait_for_interrupt(fd, dev_ptr);
+
+	//				printf("\n\n\n");
+	//				printf("STS: 0x%08d\n",dev_read(dev_ptr, XIL_AXI_INTC_ISR_OFFSET));
+	//				printf("IPR: 0x%08d\n",dev_read(dev_ptr, XIL_AXI_INTC_IPR_OFFSET));
+	//				printf("IER: 0x%08d\n",dev_read(dev_ptr, XIL_AXI_INTC_IER_OFFSET));
+	//				printf("IAR: 0x%08d\n",dev_read(dev_ptr, XIL_AXI_INTC_IAR_OFFSET));
+	//				printf("SIE: 0x%08d\n",dev_read(dev_ptr, XIL_AXI_INTC_SIE_OFFSET));
+	//				printf("CIE: 0x%08d\n",dev_read(dev_ptr, XIL_AXI_INTC_CIE_OFFSET));
+	//				printf("IVR: 0x%08d\n",dev_read(dev_ptr, XIL_AXI_INTC_IVR_OFFSET));
+	//				printf("MER: 0x%08d\n",dev_read(dev_ptr, XIL_AXI_INTC_MER_OFFSET));
+	//				printf("IMR: 0x%08d\n",dev_read(dev_ptr, XIL_AXI_INTC_IMR_OFFSET));
+	//				printf("ILR: 0x%08d\n",dev_read(dev_ptr, XIL_AXI_INTC_ILR_OFFSET));
+	//				printf("IVAR: 0x%08d\n",dev_read(dev_ptr, XIL_AXI_INTC_IVAR_OFFSET));
+
+	//				dev_write(dev_ptr, INTC_TRI_OFFSET, 0);
+	//				dev_write(dev_ptr, INTC_TRI2_OFFSET, 0xF);
+	//
+	//				// enable the interrupts from the INTC
+	//
+	//				dev_write(dev_ptr, INTC_GLOBAL_IRQ, 0x80000000);
+	//				dev_write(dev_ptr, INTC_IRQ_CONTROL, 2);
+	//
+	//        pthread_create(&t1,NULL,thread_isr,NULL);
+	//				// wait for interrupts from the INTC
+	//
+	//				while (!interrupted) {
+	//								
+	//				}
+	//
+	//				// unmap the INTC device 
+
+	munmap(dev_ptr, dev_size);
+	close(fd);
+
+	return 0;
+}
diff --git a/scripts/bitstream.tcl b/scripts/bitstream.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..5991488741baf7f9be89a4d671a0cdf6c47b82c8
--- /dev/null
+++ b/scripts/bitstream.tcl
@@ -0,0 +1,17 @@
+
+set project_name [lindex $argv 0]
+
+open_project tmp/$project_name.xpr
+
+if {[get_property PROGRESS [get_runs impl_1]] != "100%"} {
+  launch_runs impl_1 -to_step route_design
+  wait_on_run impl_1
+}
+
+open_run [get_runs impl_1]
+
+set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design]
+
+write_bitstream -force -file tmp/$project_name.bit
+
+close_project
diff --git a/scripts/core.tcl b/scripts/core.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..b8d56ff06e9882054ba708e132a61bb2a88a95c2
--- /dev/null
+++ b/scripts/core.tcl
@@ -0,0 +1,48 @@
+
+set core_name [lindex $argv 0]
+
+set part_name [lindex $argv 1]
+
+set elements [split $core_name _]
+set project_name [join [lrange $elements 0 end-2] _]
+set version [string trimleft [join [lrange $elements end-1 end] .] v]
+
+file delete -force tmp/cores/$core_name tmp/cores/$project_name.cache tmp/cores/$project_name.hw tmp/cores/$project_name.xpr tmp/cores/$project_name.ip_user_files
+
+create_project -part $part_name $project_name tmp/cores
+
+add_files -norecurse [glob cores/$core_name/*.vhd]
+
+ipx::package_project -import_files -root_dir tmp/cores/$core_name
+
+set core [ipx::current_core]
+
+set_property VERSION $version $core
+set_property NAME $project_name $core
+set_property LIBRARY {user} $core
+set_property VENDOR {labdpr} $core
+set_property VENDOR_DISPLAY_NAME {labdpr} $core
+set_property COMPANY_URL {http://labdpr.cab.cnea.gov.ar/} $core
+set_property SUPPORTED_FAMILIES {zynq Production} $core
+
+proc core_parameter {name display_name description} {
+  set core [ipx::current_core]
+
+  set parameter [ipx::get_user_parameters $name -of_objects $core]
+  set_property DISPLAY_NAME $display_name $parameter
+  set_property DESCRIPTION $description $parameter
+
+  set parameter [ipgui::get_guiparamspec -name $name -component $core]
+  set_property DISPLAY_NAME $display_name $parameter
+  set_property TOOLTIP $description $parameter
+}
+
+source cores/$core_name/core_config.tcl
+
+rename core_parameter {}
+
+ipx::create_xgui_files $core
+ipx::update_checksums $core
+ipx::save_core $core
+
+close_project
diff --git a/scripts/debian.sh b/scripts/debian.sh
new file mode 100755
index 0000000000000000000000000000000000000000..efe2b95f2638e1e732714b910cb4e76af8f1c06d
--- /dev/null
+++ b/scripts/debian.sh
@@ -0,0 +1,269 @@
+device=$1
+
+boot_dir=`mktemp -d /tmp/BOOT.XXXXXXXXXX`
+root_dir=`mktemp -d /tmp/ROOT.XXXXXXXXXX`
+
+linux_dir=tmp/linux-5.10
+linux_ver=5.10.107-xilinx
+
+# Choose mirror automatically, depending the geographic and network location
+mirror=http://deb.debian.org/debian
+
+distro=buster
+arch=armhf
+
+passwd=escondido
+timezone=America/Argentina/Mendoza
+
+# Create partitions
+
+parted -s $device mklabel msdos
+parted -s $device mkpart primary fat16 4MiB 16MiB
+parted -s $device mkpart primary ext4 16MiB 100%
+
+boot_dev=/dev/`lsblk -ln -o NAME -x NAME $device | sed '2!d'`
+root_dev=/dev/`lsblk -ln -o NAME -x NAME $device | sed '3!d'`
+
+# Create file systems
+
+mkfs.vfat -v $boot_dev
+mkfs.ext4 -F -j $root_dev
+
+# Mount file systems
+
+mount $boot_dev $boot_dir
+mount $root_dev $root_dir
+
+# Copy files to the boot file system
+
+cd ..
+cp boot.bin devicetree.dtb uImage $boot_dir
+cp uEnv-ext4.txt $boot_dir/uEnv.txt
+cd -
+
+# Install Debian base system to the root file system
+
+debootstrap --foreign --arch $arch $distro $root_dir $mirror
+
+# Install Linux modules
+
+modules_dir=$root_dir/lib/modules/$linux_ver
+
+mkdir -p $modules_dir/kernel
+
+find $linux_dir -name \*.ko -printf '%P\0' | tar --directory=$linux_dir --owner=0 --group=0 --null --files-from=- -zcf - | tar -zxf - --directory=$modules_dir/kernel
+
+cp $linux_dir/modules.order $linux_dir/modules.builtin $modules_dir/
+
+depmod -a -b $root_dir $linux_ver
+
+# Add missing configuration files and packages
+
+cp /etc/resolv.conf $root_dir/etc/
+cp /usr/bin/qemu-arm-static $root_dir/usr/bin/
+
+chroot $root_dir <<- EOF_CHROOT
+export LANG=C
+export LC_ALL=C
+
+export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+
+/debootstrap/debootstrap --second-stage
+
+cat <<- EOF_CAT > /etc/apt/sources.list
+deb $mirror $distro main contrib non-free
+deb-src $mirror $distro main contrib non-free
+deb $mirror $distro-updates main contrib non-free
+deb-src $mirror $distro-updates main contrib non-free
+deb http://security.debian.org/debian-security $distro/updates main contrib non-free
+deb-src http://security.debian.org/debian-security $distro/updates main contrib non-free
+EOF_CAT
+
+cat <<- EOF_CAT > etc/apt/apt.conf.d/99norecommends
+APT::Install-Recommends "0";
+APT::Install-Suggests "0";
+EOF_CAT
+
+cat <<- EOF_CAT > etc/fstab
+# /etc/fstab: static file system information.
+# <file system> <mount point>   <type>  <options>           <dump>  <pass>
+/dev/mmcblk0p2  /               ext4    errors=remount-ro   0       1
+/dev/mmcblk0p1  /boot           vfat    defaults            0       2
+EOF_CAT
+
+echo red-pitaya > etc/hostname
+
+apt-get update
+apt-get -y upgrade
+
+apt-get -y install locales
+
+sed -i "/^# en_US.UTF-8 UTF-8$/s/^# //" etc/locale.gen
+locale-gen
+update-locale LANG=en_US.UTF-8
+
+ln -sf /usr/share/zoneinfo/$timezone etc/localtime
+dpkg-reconfigure --frontend=noninteractive tzdata
+
+apt-get -y install openssh-server ca-certificates ntp ntpdate fake-hwclock \
+  usbutils psmisc lsof parted curl vim wpasupplicant hostapd isc-dhcp-server \
+  iw firmware-realtek firmware-ralink firmware-atheros firmware-brcm80211 \
+  ifplugd ntfs-3g net-tools less
+
+sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' etc/ssh/sshd_config
+
+cat <<- EOF_CAT >> etc/securetty
+
+# Serial Console for Xilinx Zynq-7000
+ttyPS0
+EOF_CAT
+
+touch etc/udev/rules.d/80-net-setup-link.rules
+
+cat <<- EOF_CAT > etc/network/interfaces.d/eth0
+iface eth0 inet dhcp
+EOF_CAT
+
+cat <<- EOF_CAT > etc/default/ifplugd
+INTERFACES="eth0"
+HOTPLUG_INTERFACES=""
+ARGS="-q -f -u0 -d10 -w -I"
+SUSPEND_ACTION="stop"
+EOF_CAT
+
+cat <<- EOF_CAT > etc/network/interfaces.d/wlan0
+allow-hotplug wlan0
+iface wlan0 inet static
+  address 192.168.42.1
+  netmask 255.255.255.0
+  post-up service hostapd restart
+  post-up service isc-dhcp-server restart
+  post-up iptables-restore < /etc/iptables.ipv4.nat
+  pre-down iptables-restore < /etc/iptables.ipv4.nonat
+  pre-down service isc-dhcp-server stop
+  pre-down service hostapd stop
+EOF_CAT
+
+cat <<- EOF_CAT > etc/hostapd/hostapd.conf
+interface=wlan0
+ssid=RedPitaya
+driver=nl80211
+hw_mode=g
+channel=6
+macaddr_acl=0
+auth_algs=1
+ignore_broadcast_ssid=0
+wpa=2
+wpa_passphrase=RedPitaya
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=CCMP
+rsn_pairwise=CCMP
+EOF_CAT
+
+cat <<- EOF_CAT > etc/default/hostapd
+DAEMON_CONF=/etc/hostapd/hostapd.conf
+EOF_CAT
+
+cat <<- EOF_CAT > etc/default/isc-dhcp-server
+INTERFACESv4=wlan0
+EOF_CAT
+
+cat <<- EOF_CAT > etc/dhcp/dhcpd.conf
+ddns-update-style none;
+default-lease-time 600;
+max-lease-time 7200;
+authoritative;
+log-facility local7;
+subnet 192.168.42.0 netmask 255.255.255.0 {
+  range 192.168.42.10 192.168.42.50;
+  option broadcast-address 192.168.42.255;
+  option routers 192.168.42.1;
+  default-lease-time 600;
+  max-lease-time 7200;
+  option domain-name "local";
+  option domain-name-servers 8.8.8.8, 8.8.4.4;
+}
+EOF_CAT
+
+cat <<- EOF_CAT >> etc/dhcp/dhclient.conf
+timeout 20;
+
+lease {
+  interface "eth0";
+  fixed-address 192.168.1.100;
+  option subnet-mask 255.255.255.0;
+  renew 2 2030/1/1 00:00:01;
+  rebind 2 2030/1/1 00:00:01;
+  expire 2 2030/1/1 00:00:01;
+}
+EOF_CAT
+
+sed -i '/^#net.ipv4.ip_forward=1$/s/^#//' etc/sysctl.conf
+
+cat <<- EOF_CAT > etc/iptables.ipv4.nat
+*nat
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+-A POSTROUTING -o eth0 -j MASQUERADE
+COMMIT
+*mangle
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+COMMIT
+*filter
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+-A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
+-A FORWARD -i wlan0 -o eth0 -j ACCEPT
+COMMIT
+EOF_CAT
+
+cat <<- EOF_CAT > etc/iptables.ipv4.nonat
+*nat
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+COMMIT
+*mangle
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+COMMIT
+*filter
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+COMMIT
+EOF_CAT
+
+apt-get clean
+
+echo root:$passwd | chpasswd
+
+service ntp stop
+service ssh stop
+
+history -c
+
+sync
+EOF_CHROOT
+
+rm $root_dir/etc/resolv.conf
+rm $root_dir/usr/bin/qemu-arm-static
+
+# Unmount file systems
+
+umount $boot_dir $root_dir
+
+rmdir $boot_dir $root_dir
+
+zerofree $root_dev
diff --git a/scripts/devicetree.tcl b/scripts/devicetree.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..f5bc140aaa99586774f1b6f1f7b3517de1551804
--- /dev/null
+++ b/scripts/devicetree.tcl
@@ -0,0 +1,27 @@
+
+set project_name [lindex $argv 0]
+
+set proc_name [lindex $argv 1]
+
+set repo_path [lindex $argv 2]
+
+set boot_args {console=ttyPS0,115200 earlyprintk}
+
+set hard_path tmp/$project_name.hard
+set tree_path tmp/$project_name.tree
+
+file mkdir $hard_path
+file copy -force tmp/$project_name.xsa $hard_path/$project_name.xsa
+
+hsi set_repo_path $repo_path
+
+hsi open_hw_design $hard_path/$project_name.xsa
+hsi create_sw_design -proc $proc_name -os device_tree devicetree
+
+hsi set_property CONFIG.kernel_version {2020.2} [hsi get_os]
+hsi set_property CONFIG.bootargs $boot_args [hsi get_os]
+
+hsi generate_target -dir $tree_path
+
+hsi close_sw_design [hsi current_sw_design]
+hsi close_hw_design [hsi current_hw_design]
diff --git a/scripts/fpga-bit-to-bin.py b/scripts/fpga-bit-to-bin.py
new file mode 100644
index 0000000000000000000000000000000000000000..607f4e365fcef4ce31776604160d9b61ceb3db26
--- /dev/null
+++ b/scripts/fpga-bit-to-bin.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+
+# copied from https://github.com/topic-embedded-products/meta-topic/blob/master/recipes-bsp/fpga/fpga-bit-to-bin/fpga-bit-to-bin.py
+
+import sys
+import os
+import struct
+
+def flip32(data):
+	sl = struct.Struct('<I')
+	sb = struct.Struct('>I')
+	b = buffer(data)
+	d = bytearray(len(data))
+	for offset in xrange(0, len(data), 4):
+		 sb.pack_into(d, offset, sl.unpack_from(b, offset)[0])
+	return d
+
+import argparse
+parser = argparse.ArgumentParser(description='Convert FPGA bit files to raw bin format suitable for flashing')
+parser.add_argument('-f', '--flip', dest='flip', action='store_true', default=False, help='Flip 32-bit endianess (needed for Zynq)')
+parser.add_argument("bitfile", help="Input bit file name")
+parser.add_argument("binfile", help="Output bin file name")
+args = parser.parse_args()
+
+short = struct.Struct('>H')
+ulong = struct.Struct('>I')
+
+bitfile = open(args.bitfile, 'rb')
+
+l = short.unpack(bitfile.read(2))[0]
+if l != 9:
+	raise Exception, "Missing <0009> header (0x%x), not a bit file" % l
+bitfile.read(l)
+l = short.unpack(bitfile.read(2))[0]
+d = bitfile.read(l)
+if d != 'a':
+	raise Exception, "Missing <a> header, not a bit file"
+
+l = short.unpack(bitfile.read(2))[0]
+d = bitfile.read(l)
+print "Design name:", d
+
+KEYNAMES = {'b': "Partname", 'c': "Date", 'd': "Time"}
+
+while 1:
+	k = bitfile.read(1)
+	if not k:
+		raise Exception, "unexpected EOF"
+	elif k == 'e':
+		l = ulong.unpack(bitfile.read(4))[0]
+		print "found binary data:", l
+		d = bitfile.read(l)
+		if args.flip:
+			d = flip32(d)
+		open(args.binfile, 'wb').write(d)
+		break
+	elif k in KEYNAMES:
+		l = short.unpack(bitfile.read(2))[0]
+		d = bitfile.read(l)
+		print KEYNAMES[k], d
+	else:
+		print "Unexpected key: ", k
+		l = short.unpack(bitfile.read(2))[0]
+		d = bitfile.read(l)
+
diff --git a/scripts/fsbl.tcl b/scripts/fsbl.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..64095abb9200786db655794222f44c5e41403597
--- /dev/null
+++ b/scripts/fsbl.tcl
@@ -0,0 +1,20 @@
+
+set project_name [lindex $argv 0]
+
+set proc_name [lindex $argv 1]
+
+set hard_path tmp/$project_name.hard
+set fsbl_path tmp/$project_name.fsbl
+
+file mkdir $hard_path
+file copy -force tmp/$project_name.xsa $hard_path/$project_name.xsa
+
+hsi open_hw_design $hard_path/$project_name.xsa
+hsi create_sw_design -proc $proc_name -os standalone fsbl
+
+hsi add_library xilffs
+hsi add_library xilrsa
+
+hsi generate_app -proc $proc_name -app zynq_fsbl -dir $fsbl_path -compile
+
+hsi close_hw_design [hsi current_hw_design]
diff --git a/scripts/hwdef.tcl b/scripts/hwdef.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..8adeabae18b110a200b2afb4c5fbaaed31c05ab7
--- /dev/null
+++ b/scripts/hwdef.tcl
@@ -0,0 +1,8 @@
+
+set project_name [lindex $argv 0]
+
+open_project tmp/$project_name.xpr
+
+write_hw_platform -fixed -force -file tmp/$project_name.xsa
+
+close_project
diff --git a/scripts/image.sh b/scripts/image.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6a8cffcfa6f6d40589a45c487b272fb5372db7a4
--- /dev/null
+++ b/scripts/image.sh
@@ -0,0 +1,19 @@
+script=$1
+image=$2
+
+size=512
+
+if [ $# -eq 3 ]
+then
+  size=$3
+fi
+
+dd if=/dev/zero of=$image bs=1M count=$size status=progress
+
+device=`losetup -f`
+
+losetup $device $image
+
+sh $script $device
+
+losetup -d $device
diff --git a/scripts/project.tcl b/scripts/project.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..1b105e74d9f5e53d2172ee7edd1325e55f415fee
--- /dev/null
+++ b/scripts/project.tcl
@@ -0,0 +1,107 @@
+
+set project_name [lindex $argv 0]
+
+set part_name [lindex $argv 1]
+
+file delete -force tmp/$project_name.cache tmp/$project_name.hw tmp/$project_name.srcs tmp/$project_name.runs tmp/$project_name.sim tmp/$project_name.ip_user_files tmp/$project_name.xpr tmp/$project_name.gen
+
+create_project -part $part_name $project_name tmp
+
+set_property IP_REPO_PATHS tmp/cores [current_project]
+
+update_ip_catalog
+
+set_property target_language VHDL [current_project]
+
+set bd_path tmp/$project_name.srcs/sources_1/bd/system
+
+create_bd_design system
+
+source cfg/ports.tcl
+
+proc cell {cell_vlnv cell_name {cell_props {}} {cell_ports {}}} {
+  set cell [create_bd_cell -type ip -vlnv $cell_vlnv $cell_name]
+  set prop_list {}
+  foreach {prop_name prop_value} [uplevel 1 [list subst $cell_props]] {
+    lappend prop_list CONFIG.$prop_name $prop_value
+  }
+  if {[llength $prop_list] > 1} {
+    set_property -dict $prop_list $cell
+  }
+  foreach {local_name remote_name} [uplevel 1 [list subst $cell_ports]] {
+    set local_port [get_bd_pins $cell_name/$local_name]
+    set remote_port [get_bd_pins $remote_name]
+    if {[llength $local_port] == 1 && [llength $remote_port] == 1} {
+      connect_bd_net $local_port $remote_port
+      continue
+    }
+    set local_port [get_bd_intf_pins $cell_name/$local_name]
+    set remote_port [get_bd_intf_pins $remote_name]
+    if {[llength $local_port] == 1 && [llength $remote_port] == 1} {
+      connect_bd_intf_net $local_port $remote_port
+      continue
+    }
+    error "** ERROR: can't connect $cell_name/$local_name and $remote_name"
+  }
+}
+
+proc module {module_name module_body {module_ports {}}} {
+  set bd [current_bd_instance .]
+  current_bd_instance [create_bd_cell -type hier $module_name]
+  eval $module_body
+  current_bd_instance $bd
+  foreach {local_name remote_name} [uplevel 1 [list subst $module_ports]] {
+    set local_port [get_bd_pins $module_name/$local_name]
+    set remote_port [get_bd_pins $remote_name]
+    if {[llength $local_port] == 1 && [llength $remote_port] == 1} {
+      connect_bd_net $local_port $remote_port
+      continue
+    }
+    set local_port [get_bd_intf_pins $module_name/$local_name]
+    set remote_port [get_bd_intf_pins $remote_name]
+    if {[llength $local_port] == 1 && [llength $remote_port] == 1} {
+      connect_bd_intf_net $local_port $remote_port
+      continue
+    }
+    error "** ERROR: can't connect $module_name/$local_name and $remote_name"
+  }
+}
+
+proc addr {offset range port master} {
+  set object [get_bd_intf_pins $port]
+  set segment [get_bd_addr_segs -of_objects $object]
+  set config [list Master $master Clk Auto]
+  apply_bd_automation -rule xilinx.com:bd_rule:axi4 -config $config $object
+  assign_bd_address -offset $offset -range $range $segment
+}
+
+source projects/$project_name/block_design.tcl
+
+rename cell {}
+rename module {}
+rename addr {}
+
+if {[version -short] >= 2016.3} {
+  set_property synth_checkpoint_mode None [get_files $bd_path/system.bd]
+}
+
+generate_target all [get_files $bd_path/system.bd]
+make_wrapper -files [get_files $bd_path/system.bd] -top
+
+add_files -norecurse $bd_path/hdl/system_wrapper.vhd
+
+set files [glob -nocomplain projects/$project_name/*.vhd]
+if {[llength $files] > 0} {
+  add_files -norecurse $files
+}
+
+set files [glob -nocomplain cfg/*.xdc projects/$project_name/*.xdc]
+if {[llength $files] > 0} {
+  add_files -norecurse -fileset constrs_1 $files
+}
+
+
+set_property STRATEGY Flow_PerfOptimized_high [get_runs synth_1]
+set_property STRATEGY Performance_NetDelay_high [get_runs impl_1]
+
+close_project
diff --git a/scripts/ubuntu.sh b/scripts/ubuntu.sh
new file mode 100755
index 0000000000000000000000000000000000000000..e877eb97f5262a27dc86ee1f872aec5eccaa1b3f
--- /dev/null
+++ b/scripts/ubuntu.sh
@@ -0,0 +1,250 @@
+device=$1
+
+boot_dir=`mktemp -d /tmp/BOOT.XXXXXXXXXX`
+root_dir=`mktemp -d /tmp/ROOT.XXXXXXXXXX`
+
+linux_dir=tmp/linux-5.10
+linux_ver=5.10.46-xilinx
+
+root_tar=ubuntu-base-20.04.2-base-armhf.tar.gz
+root_url=http://cdimage.ubuntu.com/ubuntu-base/releases/20.04/release/$root_tar
+
+passwd=escondido
+timezone=America/Argentina/Mendoza
+
+# Create partitions
+
+parted -s $device mklabel msdos
+parted -s $device mkpart primary fat16 4MiB 16MiB
+parted -s $device mkpart primary ext4 16MiB 100%
+
+boot_dev=/dev/`lsblk -ln -o NAME -x NAME $device | sed '2!d'`
+root_dev=/dev/`lsblk -ln -o NAME -x NAME $device | sed '3!d'`
+
+# Create file systems
+
+mkfs.vfat -v $boot_dev
+mkfs.ext4 -F -j $root_dev
+
+# Mount file systems
+
+mount $boot_dev $boot_dir
+mount $root_dev $root_dir
+
+# Copy files to the boot file system
+
+cp boot.bin devicetree.dtb uImage $boot_dir
+cp uEnv-ext4.txt $boot_dir/uEnv.txt
+
+# Copy Ubuntu Core to the root file system
+
+test -f $root_tar || curl -L $root_url -o $root_tar
+
+tar -zxf $root_tar --directory=$root_dir
+
+# Install Linux modules
+
+modules_dir=$root_dir/lib/modules/$linux_ver
+
+mkdir -p $modules_dir/kernel
+
+find $linux_dir -name \*.ko -printf '%P\0' | tar --directory=$linux_dir --owner=0 --group=0 --null --files-from=- -zcf - | tar -zxf - --directory=$modules_dir/kernel
+
+cp $linux_dir/modules.order $linux_dir/modules.builtin $modules_dir/
+
+depmod -a -b $root_dir $linux_ver
+
+# Add missing configuration files and packages
+
+cp /etc/resolv.conf $root_dir/etc/
+cp /usr/bin/qemu-arm-static $root_dir/usr/bin/
+
+chroot $root_dir <<- EOF_CHROOT
+export LANG=C
+export LC_ALL=C
+
+export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+
+cat <<- EOF_CAT > etc/apt/apt.conf.d/99norecommends
+APT::Install-Recommends "0";
+APT::Install-Suggests "0";
+EOF_CAT
+
+cat <<- EOF_CAT > etc/fstab
+# /etc/fstab: static file system information.
+# <file system> <mount point>   <type>  <options>           <dump>  <pass>
+/dev/mmcblk0p2  /               ext4    errors=remount-ro   0       1
+/dev/mmcblk0p1  /boot           vfat    defaults            0       2
+EOF_CAT
+
+cat <<- EOF_CAT >> etc/securetty
+
+# Serial Console for Xilinx Zynq-7000
+ttyPS0
+EOF_CAT
+
+sed 's/tty1/ttyPS0/g; s/38400/115200/' etc/init/tty1.conf > etc/init/ttyPS0.conf
+
+echo red-pitaya > etc/hostname
+
+sed -i '/^# deb .* universe$/s/^# //' etc/apt/sources.list
+
+sed -i '/### END INIT INFO/aexit 0' /etc/init.d/udev
+apt-get update
+apt-get -y upgrade
+sed -i '/### END INIT INFO/{n;d}' /etc/init.d/udev
+
+apt-get -y install locales
+
+locale-gen en_US.UTF-8
+update-locale LANG=en_US.UTF-8
+
+echo $timezone > etc/timezone
+dpkg-reconfigure --frontend=noninteractive tzdata
+
+apt-get -y install openssh-server ca-certificates ntp usbutils psmisc lsof \
+  parted curl less vim man-db iw wpasupplicant linux-firmware ntfs-3g
+
+sed -i 's/^PermitRootLogin.*/PermitRootLogin yes/' etc/ssh/sshd_config
+
+apt-get -y install hostapd isc-dhcp-server iptables
+
+touch etc/udev/rules.d/75-persistent-net-generator.rules
+
+cat <<- EOF_CAT >> etc/network/interfaces.d/eth0
+allow-hotplug eth0
+iface eth0 inet dhcp
+EOF_CAT
+
+cat <<- EOF_CAT > etc/network/interfaces.d/wlan0
+allow-hotplug wlan0
+iface wlan0 inet static
+  address 192.168.42.1
+  netmask 255.255.255.0
+  post-up service hostapd restart
+  post-up service isc-dhcp-server restart
+  post-up iptables-restore < /etc/iptables.ipv4.nat
+  pre-down iptables-restore < /etc/iptables.ipv4.nonat
+  pre-down service isc-dhcp-server stop
+  pre-down service hostapd stop
+EOF_CAT
+
+cat <<- EOF_CAT > etc/hostapd/hostapd.conf
+interface=wlan0
+ssid=RedPitaya
+driver=nl80211
+hw_mode=g
+channel=6
+macaddr_acl=0
+auth_algs=1
+ignore_broadcast_ssid=0
+wpa=2
+wpa_passphrase=RedPitaya
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=CCMP
+rsn_pairwise=CCMP
+EOF_CAT
+
+cat <<- EOF_CAT > etc/default/hostapd
+DAEMON_CONF=/etc/hostapd/hostapd.conf
+EOF_CAT
+
+cat <<- EOF_CAT > etc/dhcp/dhcpd.conf
+ddns-update-style none;
+default-lease-time 600;
+max-lease-time 7200;
+authoritative;
+log-facility local7;
+subnet 192.168.42.0 netmask 255.255.255.0 {
+  range 192.168.42.10 192.168.42.50;
+  option broadcast-address 192.168.42.255;
+  option routers 192.168.42.1;
+  default-lease-time 600;
+  max-lease-time 7200;
+  option domain-name "local";
+  option domain-name-servers 8.8.8.8, 8.8.4.4;
+}
+EOF_CAT
+
+cat <<- EOF_CAT >> etc/dhcp/dhclient.conf
+timeout 20;
+
+lease {
+  interface "eth0";
+  fixed-address 192.168.1.100;
+  option subnet-mask 255.255.255.0;
+  renew 2 2030/1/1 00:00:01;
+  rebind 2 2030/1/1 00:00:01;
+  expire 2 2030/1/1 00:00:01;
+}
+EOF_CAT
+
+sed -i '/^#net.ipv4.ip_forward=1$/s/^#//' etc/sysctl.conf
+
+cat <<- EOF_CAT > etc/iptables.ipv4.nat
+*nat
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+-A POSTROUTING -o eth0 -j MASQUERADE
+COMMIT
+*mangle
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+COMMIT
+*filter
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+-A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
+-A FORWARD -i wlan0 -o eth0 -j ACCEPT
+COMMIT
+EOF_CAT
+
+cat <<- EOF_CAT > etc/iptables.ipv4.nonat
+*nat
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+COMMIT
+*mangle
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+COMMIT
+*filter
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+COMMIT
+EOF_CAT
+
+apt-get clean
+
+echo root:$passwd | chpasswd
+
+service ntp stop
+service ssh stop
+
+history -c
+
+sync
+EOF_CHROOT
+
+rm $root_dir/etc/resolv.conf
+rm $root_dir/usr/bin/qemu-arm-static
+
+# Unmount file systems
+
+umount $boot_dir $root_dir
+
+rmdir $boot_dir $root_dir
+
+zerofree $root_dev
diff --git a/settings.sh b/settings.sh
new file mode 100644
index 0000000000000000000000000000000000000000..0a43e7b9f70d4d08f9c42812a9fba7b52262b96a
--- /dev/null
+++ b/settings.sh
@@ -0,0 +1,40 @@
+export LC_CTYPE="en_US.UTF-8" 
+export LC_NUMERIC="en_US.UTF-8"
+
+export LC_TIME="en_US.UTF-8" 
+export LC_COLLATE="en_US.UTF-8" 
+export LC_MONETARY="en_US.UTF-8" 
+export LC_MESSAGES="en_US.UTF-8" 
+export LC_PAPER="en_US.UTF-8" 
+export LC_NAME="en_US.UTF-8" 
+export LC_ADDRESS="en_US.UTF-8" 
+export LC_TELEPHONE="en_US.UTF-8" 
+export LC_MEASUREMENT="en_US.UTF-8" 
+export LC_IDENTIFICATION="en_US.UTF-8" 
+export LC_ALL="en_US.UTF-8"
+################################################################################
+# setup Xilinx Vivado FPGA tools
+################################################################################
+
+. /tools/Xilinx/SDK/2018.3/settings64.sh
+#. /tools/Xilinx/Vivado/2018.3/settings64.sh
+#. /tools/Xilinx/Vivado/2019.2/settings64.sh
+
+################################################################################
+# setup cross compiler toolchain
+################################################################################
+
+export CROSS_COMPILE=arm-linux-gnueabihf-
+
+################################################################################
+# setup download cache directory, to avoid downloads
+################################################################################
+
+#export DL=dl
+
+################################################################################
+# common make procedure, should not be run by this script
+################################################################################
+
+#GIT_COMMIT_SHORT=`git rev-parse --short HEAD`
+#make REVISION=$GIT_COMMIT_SHORT
diff --git a/uEnv-ext4.txt b/uEnv-ext4.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a063b3e09014bbd917a156a8b464a3b1729903d4
--- /dev/null
+++ b/uEnv-ext4.txt
@@ -0,0 +1,13 @@
+
+kernel_image=uImage
+
+devicetree_image=devicetree.dtb
+
+kernel_load_address=0x2080000
+
+devicetree_load_address=0x2000000
+
+bootcmd=fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image} && bootm ${kernel_load_address} - ${devicetree_load_address}
+
+bootargs=console=ttyPS0,115200 uio_pdrv_genirq.of_id=generic-uio root=/dev/mmcblk0p2 ro rootfstype=ext4 earlyprintk rootwait
+
diff --git a/uEnv.txt b/uEnv.txt
new file mode 100644
index 0000000000000000000000000000000000000000..0680df09760d730c201da902a4222c929c92f59e
--- /dev/null
+++ b/uEnv.txt
@@ -0,0 +1,15 @@
+kernel_image=uImage
+
+devicetree_image=devicetree.dtb
+
+ramdisk_image=uInitrd
+
+kernel_load_address=0x2080000
+
+devicetree_load_address=0x2000000
+
+ramdisk_load_address=0x3000000
+
+bootcmd=fatload mmc 0 ${kernel_load_address} ${kernel_image} && fatload mmc 0 ${devicetree_load_address} ${devicetree_image} && load mmc 0 ${ramdisk_load_address} ${ramdisk_image} && bootm ${kernel_load_address} ${ramdisk_load_address} ${devicetree_load_address}
+
+bootargs=console=ttyPS0,115200 earlyprintk modloop=modloop cma=36M