diff --git a/tests/puf_sram/Makefile b/tests/puf_sram/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..e8f75c97fa65367d67e6d01824c273ec658e129b
--- /dev/null
+++ b/tests/puf_sram/Makefile
@@ -0,0 +1,7 @@
+BOARD ?= nucleo-f411re
+
+include ../Makefile.tests_common
+
+USEMODULE += puf_sram
+
+include $(RIOTBASE)/Makefile.include
diff --git a/tests/puf_sram/README.md b/tests/puf_sram/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..7b1d0fe3ff19b3a38b5081944469fd257f244b4c
--- /dev/null
+++ b/tests/puf_sram/README.md
@@ -0,0 +1,33 @@
+# Tool Introduction
+This tool is designed to interface with a test to get the random numbers generated by the using a hash of a block of uninitialized SRAM.  In order to run the test a certain hardware setup is required due to the requirement to power off the DUT (device under test) for a certain time. Furthermore, the module detects button and/or software resets. If you push the reset button for example (without powering off the DUT), a warning should be printed to the console.
+
+# Setup
+## Required Tools
+- DUT (a supported RIOT target board)
+- USB to UART converter that supports setting the RTS pin and 5 volts (ie. FT232RL FTDI USB to TTL adapter)
+- MOSFET to control power to the DUT (ie. STP36NF06L)
+- Jumper cables
+- Solderless breadboard
+
+## Wiring Example
+1. RTS <--> MOSFET gate pin (FT232RL RTS - STP36NF06L 1)
+2. +5V <--> MOSFET drain pin (FT232RL 5V - STP36NF06L 2)
+3. DUT Power <--> MOSFET source pin (E15 - STP36NF06L 3)
+4. DUT UART TX <--> USB to UART RX
+5. GND <--> GND
+
+## Example Setup
+![PUF SRAM test setup](https://raw.githubusercontent.com/wiki/RIOT-OS/RIOT/images/puf-sram-setup.jpg)
+
+
+# Running the test
+1. Plug the USB to UART converter in (it should be done first so it can autoconnect to the serial port)
+2. Program the DUT with the puf_sram test
+3. Connect all wires
+4. change jumpers to only run on power provided by the USB to USRT converter
+5. Run the example_test.py
+
+# Running Custom Tests
+Different tests can be run using the get_seed_list(self, n=10000, off_time=1, allow_print=False)
+n -> the number of samples to take
+off_time -> The time that the device is powered off to properly randomize the RAM
diff --git a/tests/puf_sram/main.c b/tests/puf_sram/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..4c1e306d1c7f54cdbb0ee8637a8e024e827648b8
--- /dev/null
+++ b/tests/puf_sram/main.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 HAW Hamburg
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup tests
+ * @{
+ *
+ * @file
+ * @brief       Test application for the random number generator based of SRAM
+ *
+ * @author      Kevin Weiss <kevin.weiss@haw-hamburg.de>
+ *
+ * @}
+ */
+#include <stdio.h>
+#include "puf_sram.h"
+
+int main(void)
+{
+    puts("Start: Test random number generator");
+
+    printf("Success: Data for puf_sram_seed: [0x%08lX]", puf_sram_seed);
+
+    puts("End: Test finished");
+    return 0;
+}
diff --git a/tests/puf_sram/tests/example_test.py b/tests/puf_sram/tests/example_test.py
new file mode 100644
index 0000000000000000000000000000000000000000..c932608076ff5f43274dad923cf14da249117a84
--- /dev/null
+++ b/tests/puf_sram/tests/example_test.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2018 Kevin Weiss <kevin.weiss@haw-hamburg.de>
+# Copyright (C) 2018 Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
+#
+# This file is subject to the terms and conditions of the GNU Lesser
+# General Public License v2.1. See the file LICENSE in the top level
+# directory for more details.
+
+import puf_sram_if
+import numpy
+
+
+def min_erntropy(all_meas):
+    p1 = numpy.zeros(len(all_meas[0]))
+    # number of ones for each bit
+    for i in range(0, len(all_meas[0])):
+        tmp = list(map(lambda x: int(x[i]), all_meas))
+        p1[i] = numpy.count_nonzero(tmp)
+
+    # probability of ones
+    p1 = numpy.divide(p1, float(len(all_meas)))
+    # probability of zeros
+    p0 = 1 - p1
+
+    p0_1_max = numpy.maximum(p1, p0)
+    log2_p0_1_max = numpy.log2(p0_1_max)
+    H_min = numpy.sum(-log2_p0_1_max)
+    H_min_rel = 100 * H_min/len(p0_1_max)
+
+    return [H_min, H_min_rel]
+
+
+def main_func():
+    puf_sram = puf_sram_if.PufSram()
+    seeds = puf_sram.get_seed_list(n=500, off_time=1, allow_print=True)
+    seeds = [format(x, '0>32b') for x in seeds]
+    H_min, H_min_rel = min_erntropy(seeds)
+
+    print("Number of seeds: %i       " % len(seeds))
+    print("Seed length    : %i Bit   " % len(seeds[0]))
+    print("Abs. Entropy   : %02.02f Bit   " % H_min)
+    print("Rel. Entropy   : %02.02f perc. " % H_min_rel)
+
+
+if __name__ == "__main__":
+    main_func()
diff --git a/tests/puf_sram/tests/puf_sram_if.py b/tests/puf_sram/tests/puf_sram_if.py
new file mode 100644
index 0000000000000000000000000000000000000000..79cf363fe7075a20281d8f6e190728a03db23bf9
--- /dev/null
+++ b/tests/puf_sram/tests/puf_sram_if.py
@@ -0,0 +1,62 @@
+#!/usr/bin/env python3
+
+# Copyright (C) 2018 Kevin Weiss <kevin.weiss@haw-hamburg.de>
+#
+# This file is subject to the terms and conditions of the GNU Lesser
+# General Public License v2.1. See the file LICENSE in the top level
+# directory for more details.
+
+import serial
+import time
+
+
+class PufSram:
+
+    def __init__(self, port='/dev/ttyUSB0', baud=115200):
+        self.__dev = serial.Serial(port, baud, timeout=10)
+        if(self.__dev.isOpen() is False):
+            self.__dev.open()
+
+    def repower(self, shutdown_time=1):
+        self.__dev.setRTS(True)
+        time.sleep(shutdown_time)
+        self.__dev.setRTS(False)
+
+    def read_data(self):
+        data = None
+        start = False
+        str = 'no_exit'
+        while (str != ''):
+            str = self.__dev.readline()
+            if (b'Start: ' in str):
+                start = True
+            if ((b'Success: ' in str) and (start is True)):
+                if (b'[' in str) and (b']' in str):
+                    data_str = str[str.find(b"[")+1:str.find(b"]")]
+                    data = int(data_str, 0)
+            if ((b'End: ' in str) and (data is not None)):
+                return data
+        return None
+
+    def get_seed_list(self, n=10000, off_time=1, allow_print=False):
+        data = list()
+        for i in range(0, n):
+            self.repower(off_time)
+            data.append(self.read_data())
+            if (allow_print):
+                print('Iteration %i/%i' % (i, n))
+                print(data[-1])
+        return data
+
+    def connect(self, dev):
+        if (dev.isOpen()):
+            dev.close()
+        self.__dev = self
+        if(self.__dev.isOpen() is False):
+            self.__dev.open()
+
+    def disconnect(self):
+        self.__dev.close()
+
+    def __del__(self):
+        self.__dev.close()