Browse Source

Copy Pavel Demin's development enviroment

U-DESKTOP-M040OEH\slavs 1 week ago
commit
be4ccb594d
124 changed files with 12149 additions and 0 deletions
  1. 21 0
      alpine/apps/css/main.css
  2. 45 0
      alpine/apps/css/pygments.css
  3. 36 0
      alpine/apps/index.html
  4. 33 0
      alpine/apps/index_122_88.html
  5. 7 0
      alpine/apps/server/Makefile
  6. 160 0
      alpine/apps/server/server.c
  7. 8 0
      alpine/apps/stop.sh
  8. 13 0
      alpine/etc/avahi/services/http.service
  9. 13 0
      alpine/etc/avahi/services/sftp-ssh.service
  10. 13 0
      alpine/etc/avahi/services/ssh.service
  11. 4 0
      alpine/etc/chrony/chrony.conf
  12. 3 0
      alpine/etc/conf.d/gpsd
  13. 1 0
      alpine/etc/conf.d/hostname
  14. 0 0
      alpine/etc/conf.d/modloop
  15. 1 0
      alpine/etc/conf.d/syslog
  16. 61 0
      alpine/etc/dhcpcd.conf
  17. 10 0
      alpine/etc/dhcpcd.exit-hook
  18. 2 0
      alpine/etc/dnsmasq.d/ap.conf
  19. 2 0
      alpine/etc/fw_env.config
  20. 11 0
      alpine/etc/hostapd/hostapd.conf
  21. 21 0
      alpine/etc/iptables/rules-save
  22. 3 0
      alpine/etc/local.d/apps.start
  23. 5 0
      alpine/etc/wpa_supplicant/wpa_supplicant.conf
  24. 52 0
      alpine/gpsd-timepps/APKBUILD
  25. 29 0
      alpine/gpsd-timepps/gpsd.confd
  26. 38 0
      alpine/gpsd-timepps/gpsd.initd
  27. 216 0
      alpine/gpsd-timepps/timepps.h
  28. 13 0
      alpine/gpsd-timepps/timepps.patch
  29. 12 0
      alpine/gpsd-timepps/ttydefaults.patch
  30. 91 0
      alpine/hostapd-rtl871xdrv/APKBUILD
  31. 45 0
      alpine/hostapd-rtl871xdrv/CVE-2012-4445.patch
  32. 69 0
      alpine/hostapd-rtl871xdrv/crypto_tls_openssl_c.patch
  33. 5 0
      alpine/hostapd-rtl871xdrv/hostapd.confd
  34. 46 0
      alpine/hostapd-rtl871xdrv/hostapd.initd
  35. 22 0
      alpine/hostapd-rtl871xdrv/libressl-compat.patch
  36. 2722 0
      alpine/hostapd-rtl871xdrv/rtlxdrv.patch
  37. 13 0
      alpine/wifi/client.sh
  38. 13 0
      alpine/wifi/hotspot.sh
  39. 2 0
      cfg/clocks.xdc
  40. 2048 0
      cfg/dds.mem
  41. 43 0
      cfg/ports.tcl
  42. 208 0
      cfg/ports.xdc
  43. 70 0
      cfg/red_pitaya.xml
  44. 292 0
      cores/axi_hub.py
  45. 493 0
      cores/axi_hub.v
  46. 149 0
      cores/axis_accumulator.v
  47. 50 0
      cores/axis_adder.v
  48. 91 0
      cores/axis_alex.v
  49. 111 0
      cores/axis_averager.v
  50. 151 0
      cores/axis_bram_reader.v
  51. 62 0
      cores/axis_bram_writer.v
  52. 22 0
      cores/axis_constant.v
  53. 100 0
      cores/axis_counter.v
  54. 89 0
      cores/axis_decimator.v
  55. 85 0
      cores/axis_fifo.v
  56. 64 0
      cores/axis_gate_controller.v
  57. 40 0
      cores/axis_gpio_reader.v
  58. 105 0
      cores/axis_histogram.v
  59. 188 0
      cores/axis_i2s.v
  60. 107 0
      cores/axis_iir_filter.v
  61. 89 0
      cores/axis_interpolator.v
  62. 111 0
      cores/axis_keyer.v
  63. 79 0
      cores/axis_lfsr.v
  64. 87 0
      cores/axis_maxabs_finder.v
  65. 133 0
      cores/axis_misc_reader.v
  66. 82 0
      cores/axis_misc_writer.v
  67. 29 0
      cores/axis_negator.v
  68. 93 0
      cores/axis_oscilloscope.v
  69. 120 0
      cores/axis_packetizer.v
  70. 80 0
      cores/axis_pdm.v
  71. 58 0
      cores/axis_phase_generator.v
  72. 59 0
      cores/axis_pps_counter.v
  73. 48 0
      cores/axis_pulse_generator.v
  74. 135 0
      cores/axis_pulse_height_analyzer.v
  75. 125 0
      cores/axis_ram_reader.v
  76. 133 0
      cores/axis_ram_reader_radar.v
  77. 158 0
      cores/axis_ram_writer.v
  78. 40 0
      cores/axis_red_pitaya_adc.v
  79. 128 0
      cores/axis_red_pitaya_dac.v
  80. 47 0
      cores/axis_selector.v
  81. 29 0
      cores/axis_stepper.v
  82. 44 0
      cores/axis_tagger.v
  83. 71 0
      cores/axis_timer.v
  84. 51 0
      cores/axis_trigger.v
  85. 29 0
      cores/axis_validator.v
  86. 41 0
      cores/axis_variable.v
  87. 62 0
      cores/axis_variant.v
  88. 27 0
      cores/axis_zeroer.v
  89. 148 0
      cores/dds.v
  90. 88 0
      cores/dna_reader.v
  91. 44 0
      cores/dsp48.v
  92. 22 0
      cores/edge_detector.v
  93. 52 0
      cores/gpio_debouncer.v
  94. 16 0
      cores/port_selector.v
  95. 17 0
      cores/port_slicer.v
  96. 82 0
      cores/pulse_generator.v
  97. 26 0
      cores/shift_register.v
  98. 113 0
      cores/xadc_bram.v
  99. 11 0
      debian/etc/apt/sources.list.d/debian.sources
  100. 61 0
      debian/etc/dhcpcd.conf
  101. 22 0
      debian/etc/dhcpcd.exit-hook
  102. 2 0
      debian/etc/dnsmasq.d/ap.conf
  103. 4 0
      debian/etc/fstab
  104. 2 0
      debian/etc/fw_env.config
  105. 11 0
      debian/etc/hostapd/hostapd.conf
  106. 1 0
      debian/etc/hostname
  107. 21 0
      debian/etc/iptables.ipv4.nat
  108. 18 0
      debian/etc/iptables.ipv4.nonat
  109. 2 0
      debian/etc/securetty
  110. 1 0
      debian/etc/sysctl.d/99-net.conf
  111. 14 0
      debian/etc/systemd/system/dhcpcd.service
  112. 0 0
      debian/etc/udev/rules.d/80-net-setup-link.rules
  113. 5 0
      debian/etc/wpa_supplicant/wpa_supplicant.conf
  114. 161 0
      scripts/alpine-project.sh
  115. 188 0
      scripts/alpine.sh
  116. 22 0
      scripts/app_cpu1.tcl
  117. 17 0
      scripts/bitstream.tcl
  118. 35 0
      scripts/core.tcl
  119. 124 0
      scripts/debian.sh
  120. 22 0
      scripts/devicetree.tcl
  121. 20 0
      scripts/fsbl.tcl
  122. 8 0
      scripts/hwdef.tcl
  123. 19 0
      scripts/image.sh
  124. 133 0
      scripts/project.tcl

+ 21 - 0
alpine/apps/css/main.css

@@ -0,0 +1,21 @@
+body { font-family: Calibri, Verdana, Liberation Sans, DejaVu Sans, sans-serif; background-color: #f5f5f5; max-width: 800px; line-height: 1.4; margin-left: auto; margin-right: auto; padding-bottom: 3em; }
+h1, h2, h3, h4 { font-weight: normal; }
+a { color: #bf2334; text-decoration: none; }
+a:hover { text-decoration: underline; }
+pre, code { font-family: Consolas, Menlo, Liberation Mono, DejaVu Sans Mono, monospace; background: #f5f5f5; border-radius: 0.3em }
+code { padding: 0 0.3em; white-space: nowrap; }
+pre { padding: 0.1em 0.3em; overflow-x: auto; }
+pre > code { padding: 0; background: 0; white-space: pre }
+td, th { border: 1px solid #d3d3d3; padding: 0.1em 0.3em; }
+th { text-align: left; background-color: #f5f5f5; }
+tr.even td { background-color: #f5f5f5; }
+img { max-width: 100%; }
+
+#header { color: #bf2334; padding: 0 1em; }
+#header a { color: #bf2334; text-decoration: none; }
+#logo { margin-bottom: -1.4em; }
+#menu { padding-bottom: 0.3em; text-align: right; }
+#menu a { padding-left: 1em; }
+#content { background-color: #fff; padding: 1em 1em; border-radius: 0.6em; }
+
+@media print { #header { display: none; } }

+ 45 - 0
alpine/apps/css/pygments.css

@@ -0,0 +1,45 @@
+.highlight .c { color: #008800; font-style: italic }
+.highlight .err { color: #a61717; background-color: #e3d2d2 }
+.highlight .k { color: #000080; font-weight: bold }
+.highlight .cm { color: #008800; font-style: italic }
+.highlight .cp { color: #008080 }
+.highlight .c1 { color: #008800; font-style: italic }
+.highlight .cs { color: #008800; font-weight: bold }
+.highlight .gd { color: #000000; background-color: #ffdddd }
+.highlight .ge { font-style: italic }
+.highlight .gr { color: #aa0000 }
+.highlight .gh { color: #999999 }
+.highlight .gi { color: #000000; background-color: #ddffdd }
+.highlight .go { color: #888888 }
+.highlight .gp { color: #555555 }
+.highlight .gs { font-weight: bold }
+.highlight .gu { color: #aaaaaa }
+.highlight .gt { color: #aa0000 }
+.highlight .kc { color: #000080; font-weight: bold }
+.highlight .kd { color: #000080; font-weight: bold }
+.highlight .kn { color: #000080; font-weight: bold }
+.highlight .kp { color: #000080; font-weight: bold }
+.highlight .kr { color: #000080; font-weight: bold }
+.highlight .kt { color: #000080; font-weight: bold }
+.highlight .m { color: #0000ff }
+.highlight .s { color: #0000ff }
+.highlight .na { color: #ff0000 }
+.highlight .nt { color: #000080; font-weight: bold }
+.highlight .ow { font-weight: bold }
+.highlight .w { color: #bbbbbb }
+.highlight .mf { color: #0000ff }
+.highlight .mh { color: #0000ff }
+.highlight .mi { color: #0000ff }
+.highlight .mo { color: #0000ff }
+.highlight .sb { color: #0000ff }
+.highlight .sc { color: #800080 }
+.highlight .sd { color: #0000ff }
+.highlight .s2 { color: #0000ff }
+.highlight .se { color: #0000ff }
+.highlight .sh { color: #0000ff }
+.highlight .si { color: #0000ff }
+.highlight .sx { color: #0000ff }
+.highlight .sr { color: #0000ff }
+.highlight .s1 { color: #0000ff }
+.highlight .ss { color: #0000ff }
+.highlight .il { color: #0000ff }

+ 36 - 0
alpine/apps/index.html

@@ -0,0 +1,36 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Red Pitaya Apps</title>
+<link rel="stylesheet" href="/css/main.css">
+</head>
+<body>
+<div id="header">
+<div id="logo">
+<a href="http://pavel-demin.github.io/red-pitaya-notes" target="_blank">Red Pitaya Notes</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">
+<ol>
+<li><a href="led_blinker">LED blinker</a></li>
+<li><a href="playground">Playground</a></li>
+<li><a href="sdr_receiver">SDR receiver</a></li>
+<li><a href="sdr_transceiver">SDR transceiver</a></li>
+<li><a href="sdr_transceiver_hpsdr">SDR transceiver compatible with HPSDR</a></li>
+<li><a href="sdr_receiver_hpsdr">SDR receiver compatible with HPSDR</a></li>
+<li><a href="sdr_receiver_wide">Wideband SDR receiver</a></li>
+<li><a href="sdr_transceiver_wide">Wideband SDR transceiver</a></li>
+<li><a href="sdr_transceiver_wspr">Multiband WSPR transceiver</a></li>
+<li><a href="sdr_transceiver_ft8">Multiband FT8 transceiver</a></li>
+<li><a href="pulsed_nmr">Pulsed NMR system</a></li>
+<li><a href="mcpha">Multichannel Pulse Height Analyzer</a></li>
+<li><a href="vna">Vector Network Analyzer</a></li>
+</ol>
+</div>
+</body>
+</html>

+ 33 - 0
alpine/apps/index_122_88.html

@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Red Pitaya Apps</title>
+<link rel="stylesheet" href="/css/main.css">
+</head>
+<body>
+<div id="header">
+<div id="logo">
+<a href="http://pavel-demin.github.io/red-pitaya-notes" target="_blank">Red Pitaya Notes</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">
+<ol>
+<li><a href="led_blinker_122_88">LED blinker</a></li>
+<li><a href="sdr_receiver_122_88">SDR receiver</a></li>
+<li><a href="sdr_transceiver_122_88">SDR transceiver</a></li>
+<li><a href="sdr_transceiver_hpsdr_122_88">SDR transceiver compatible with HPSDR</a></li>
+<li><a href="sdr_receiver_hpsdr_122_88">SDR receiver compatible with HPSDR</a></li>
+<li><a href="sdr_receiver_wide_122_88">Wideband SDR receiver</a></li>
+<li><a href="sdr_transceiver_wspr_122_88">Multiband WSPR transceiver</a></li>
+<li><a href="sdr_transceiver_ft8_122_88">Multiband FT8 transceiver</a></li>
+<li><a href="pulsed_nmr_122_88">Pulsed NMR system</a></li>
+<li><a href="vna_122_88">Vector Network Analyzer</a></li>
+</ol>
+</div>
+</body>
+</html>

+ 7 - 0
alpine/apps/server/Makefile

@@ -0,0 +1,7 @@
+all: server
+
+server: server.c
+	gcc -o $@ $^
+
+clean:
+	rm -f server

+ 160 - 0
alpine/apps/server/server.c

@@ -0,0 +1,160 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#define DIR "/sys/bus/iio/devices/iio:device0/"
+
+const char *directory = "/media/mmcblk0p1/apps";
+const char *forbidden = "HTTP/1.0 403 Forbidden\n\n";
+const char *redirect = "HTTP/1.0 302 Found\nLocation: /\n\n";
+const char *okheader = "HTTP/1.0 200 OK\n\n";
+
+void detach(char *path)
+{
+  int pid = fork();
+  if(pid != 0) return;
+  close(STDIN_FILENO);
+  close(STDOUT_FILENO);
+  close(STDERR_FILENO);
+  execlp(path, path, NULL);
+  exit(0);
+}
+
+float read_value(char *name)
+{
+  FILE *fp;
+  char buffer[64];
+
+  if((fp = fopen(name, "r")) == NULL)
+  {
+    printf("Cannot open %s.\n", name);
+    exit(1);
+  }
+
+  fgets(buffer, sizeof(buffer), fp);
+  fclose(fp);
+
+  return atof(buffer);
+}
+
+int main(int argc, char *argv[])
+{
+  FILE *fp;
+  int fd, id, i, j, top;
+  float off, raw, scl;
+  struct stat sb;
+  size_t size;
+  char buffer[256];
+  char path[291];
+  char *end;
+  long freq;
+  volatile int *slcr;
+
+  if((fd = open("/dev/mem", O_RDWR)) < 0)
+  {
+    fwrite(forbidden, 24, 1, stdout);
+    return 1;
+  }
+
+  slcr = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0xF8000000);
+  id = (slcr[332] >> 12) & 0x1f;
+
+  freq = (argc == 2) ? strtol(argv[1], &end, 10) : -1;
+  if(errno != 0 || end == argv[1] || freq < 0)
+  {
+    freq = 125;
+  }
+
+  if(fgets(buffer, 256, stdin) == NULL)
+  {
+    fwrite(forbidden, 24, 1, stdout);
+    return 1;
+  }
+
+  if(buffer[4] != '/')
+  {
+    fwrite(forbidden, 24, 1, stdout);
+    return 1;
+  }
+
+  if(strncmp(buffer, "GET ", 4) && strncmp(buffer, "get ", 4))
+  {
+    fwrite(forbidden, 24, 1, stdout);
+    return 1;
+  }
+
+  top = 1;
+  for(i = 5; i < 255; ++i)
+  {
+    if(buffer[i] == ' ')
+    {
+      buffer[i] = 0;
+      break;
+    }
+    if(buffer[i] != '/') top = 0;
+  }
+
+  for(j = 5; j < i - 1; ++j)
+  {
+    if(buffer[j] == '.' && buffer[j + 1] == '.')
+    {
+      fwrite(forbidden, 24, 1, stdout);
+      return 1;
+    }
+  }
+
+  if(i == 10 && strncmp(buffer + 5, "temp0", 5) == 0)
+  {
+    fwrite(okheader, 17, 1, stdout);
+    off = read_value(DIR "in_temp0_offset");
+    raw = read_value(DIR "in_temp0_raw");
+    scl = read_value(DIR "in_temp0_scale");
+    printf("%.1f\n", (off + raw) * scl / 1000);
+    return 0;
+  }
+
+  memcpy(path, directory, 21);
+  memcpy(path + 21, buffer + 4, i - 3);
+
+  if(stat(path, &sb) < 0)
+  {
+    fwrite(redirect, 32, 1, stdout);
+    return 1;
+  }
+
+  if(S_ISDIR(sb.st_mode))
+  {
+    memcpy(path + 21 + i - 4, "/start.sh", 10);
+    detach(path);
+    if(top && id == 7 && freq == 122)
+    {
+      memcpy(path + 21 + i - 4, "/index_122_88.html", 19);
+    }
+    else
+    {
+      memcpy(path + 21 + i - 4, "/index.html", 12);
+    }
+  }
+
+  fp = fopen(path, "r");
+
+  if(fp == NULL)
+  {
+    fwrite(redirect, 32, 1, stdout);
+    return 1;
+  }
+
+  fwrite(okheader, 17, 1, stdout);
+
+  while((size = fread(buffer, 1, 256, fp)) > 0)
+  {
+    if(!fwrite(buffer, size, 1, stdout)) break;
+  }
+
+  return 0;
+}

+ 8 - 0
alpine/apps/stop.sh

@@ -0,0 +1,8 @@
+#! /bin/sh
+
+for script in /media/mmcblk0p1/apps/*/stop.sh
+do
+  $script &
+done
+
+wait

+ 13 - 0
alpine/etc/avahi/services/http.service

@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
+<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
+
+<service-group>
+
+  <name replace-wildcards="yes">%h HTTP</name>
+
+  <service>
+    <type>_http._tcp</type>
+    <port>80</port>
+  </service>
+
+</service-group>

+ 13 - 0
alpine/etc/avahi/services/sftp-ssh.service

@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
+<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
+
+<service-group>
+
+  <name replace-wildcards="yes">%h SFTP-SSH</name>
+
+  <service>
+    <type>_sftp-ssh._tcp</type>
+    <port>22</port>
+  </service>
+
+</service-group>

+ 13 - 0
alpine/etc/avahi/services/ssh.service

@@ -0,0 +1,13 @@
+<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
+<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
+
+<service-group>
+
+  <name replace-wildcards="yes">%h SSH</name>
+
+  <service>
+    <type>_ssh._tcp</type>
+    <port>22</port>
+  </service>
+
+</service-group>

+ 4 - 0
alpine/etc/chrony/chrony.conf

@@ -0,0 +1,4 @@
+refclock SHM 2 refid PPS precision 1e-9
+pool pool.ntp.org iburst offline
+makestep 1 -1
+driftfile /var/lib/chrony/chrony.drift

+ 3 - 0
alpine/etc/conf.d/gpsd

@@ -0,0 +1,3 @@
+GPSD_OPTIONS="-n"
+DEVICES="/dev/ttyPS1 /dev/pps0"
+GPSD_SOCKET="/var/run/gpsd.sock"

+ 1 - 0
alpine/etc/conf.d/hostname

@@ -0,0 +1 @@
+awk -F : '{print "rp-"$4$5$6}' /sys/class/net/eth0/address > /etc/hostname

+ 0 - 0
alpine/etc/conf.d/modloop


+ 1 - 0
alpine/etc/conf.d/syslog

@@ -0,0 +1 @@
+SYSLOGD_OPTS=""

+ 61 - 0
alpine/etc/dhcpcd.conf

@@ -0,0 +1,61 @@
+# Inform the DHCP server of our hostname for DDNS.
+hostname
+
+# Use the hardware address of the interface for the Client ID.
+clientid
+
+# Rapid commit support.
+# Safe to enable by default because it requires the equivalent option set
+# on the server to actually work.
+option rapid_commit
+
+# A list of options to request from the DHCP server.
+option domain_name_servers, domain_name, domain_search, host_name
+option classless_static_routes
+# Most distributions have NTP support.
+option ntp_servers
+# Respect the network MTU. This is applied to DHCP routes.
+option interface_mtu
+
+# A ServerID is required by RFC2131.
+require dhcp_server_identifier
+
+# Generate Stable Private IPv6 Addresses instead of hardware based ones.
+slaac private
+
+# Don't send any ARP requests.
+noarp
+
+# Only configure IPv4.
+ipv4only
+
+# Wait 20 seconds before falling back to static profile.
+reboot 20
+
+# Configure loopback interface.
+interface lo
+static ip_address=127.0.0.1/8
+
+# Define static profile for eth0.
+profile static_eth0
+static ip_address=192.168.1.100/24
+static routers=192.168.1.1
+static domain_name_servers=192.168.1.1
+
+# Fallback to static profile on eth0.
+interface eth0
+fallback static_eth0
+
+# Define static profile for mvl0.
+profile static_mvl0
+static ip_address=192.168.1.101/24
+static routers=192.168.1.1
+static domain_name_servers=192.168.1.1
+
+# Fallback to static profile on mvl0.
+interface mvl0
+fallback static_mvl0
+
+# Static IP address for Wi-Fi access point.
+interface wlan0
+static ip_address=192.168.42.1/24

+ 10 - 0
alpine/etc/dhcpcd.exit-hook

@@ -0,0 +1,10 @@
+if [ "$interface" = wlan0 ]; then
+  case "$reason" in
+    PREINIT) (sleep 3; openrc wifi > /dev/null 2>&1) & ;;
+    DEPARTED) (sleep 3; openrc default > /dev/null 2>&1) & ;;
+  esac
+fi
+
+if $if_up; then
+  (sleep 3; chronyc online > /dev/null 2>&1) &
+fi

+ 2 - 0
alpine/etc/dnsmasq.d/ap.conf

@@ -0,0 +1,2 @@
+interface=wlan0
+dhcp-range=192.168.42.20,192.168.42.254,12h

+ 2 - 0
alpine/etc/fw_env.config

@@ -0,0 +1,2 @@
+# MTD device name                       Device offset   Environment size
+/sys/bus/i2c/devices/0-0050/eeprom      0x1800          0x0400

+ 11 - 0
alpine/etc/hostapd/hostapd.conf

@@ -0,0 +1,11 @@
+interface=wlan0
+ssid=RedPitaya
+driver=nl80211
+hw_mode=g
+channel=6
+auth_algs=1
+wpa=2
+wpa_passphrase=RedPitaya
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=CCMP
+rsn_pairwise=CCMP

+ 21 - 0
alpine/etc/iptables/rules-save

@@ -0,0 +1,21 @@
+*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

+ 3 - 0
alpine/etc/local.d/apps.start

@@ -0,0 +1,3 @@
+freq=`fw_printenv -n hw_rev | awk -F _ '{print $2}' | awk -F - '{print $1}'`
+tcpserver -H -l 0 0 80 /media/mmcblk0p1/apps/server/server $freq &
+/media/mmcblk0p1/start.sh &

+ 5 - 0
alpine/etc/wpa_supplicant/wpa_supplicant.conf

@@ -0,0 +1,5 @@
+network={
+	ssid="RedPitaya"
+	#psk="RedPitaya"
+	psk=b9a64d92624634bd901c554a22794567fd6a9e6c6e686d475d6aea6c2f13fdf3
+}

+ 52 - 0
alpine/gpsd-timepps/APKBUILD

@@ -0,0 +1,52 @@
+pkgname=gpsd-timepps
+pkgver=3.17
+pkgrel=1
+pkgdesc="A GPS daemon"
+arch=all
+url="http://catb.org/gpsd/"
+license="BSD"
+makedepends="scons python2-dev libcap-dev ncurses-dev"
+subpackages="$pkgname-dev"
+source="https://download-mirror.savannah.gnu.org/releases/gpsd/gpsd-$pkgver.tar.gz
+	timepps.h
+	timepps.patch
+	ttydefaults.patch
+	gpsd.initd
+	gpsd.confd"
+
+builddir="$srcdir"/gpsd-$pkgver
+
+prepare() {
+	mkdir -p "$builddir"/sys
+	cp timepps.h "$builddir"/sys/
+
+	default_prepare
+}
+
+build() {
+	cd "$builddir"
+	scons -j${JOBS:-1} \
+		prefix=/usr
+}
+
+package() {
+	cd "$builddir"
+
+	mkdir -p "$pkgdir"/usr/lib
+	cp -a "$builddir"/libgps*.so* "$pkgdir"/usr/lib/
+
+	mkdir -p "$pkgdir"/usr/sbin
+	for a in gpsdecode gpsd gpsctl gpsdctl gpspipe; do
+		install -m755 -D "$builddir/"$a "$pkgdir"/usr/sbin/
+	done
+
+	install -m755 -D "$srcdir"/gpsd.initd "$pkgdir"/etc/init.d/gpsd
+	install -m644 -D "$srcdir"/gpsd.confd "$pkgdir"/etc/conf.d/gpsd
+}
+
+sha512sums="71085053f600730e0f2de269c59ce0a17ae106ef01403f02d78418b267c6adb9818d541fba59eb23bf71cdb67c5442c82b4948d262ef7e74bb993dcae677a1b1  gpsd-3.17.tar.gz
+eb11fc19243d1789016d88eb7645bfe67c46304547781489bf36eb1dd4c252d523681ff835a6488fa0ef62b6b9e2f781c672279f4439f5d5640a3f214a113048  timepps.h
+b6556bb16ea663ad1e4b5b43308b5e784472a7b2775ea9da4aa95ab03a3d88714455c346299cd0f98d0a204769b356ba1cf89da143b6f1a1b99b3e512f4035d2  timepps.patch
+e2af8f52fc2d7e663882b6d12c5f4d709aa267b16eb9aeca2a70d8ecc681ae72359f3efcd1636cde576bc8579e008f242574bc0adfab7252d3e763f039e86135  ttydefaults.patch
+a0e7bf206ad51c31195f86f79ef92adca425d7f988534c0f70a2dd3053613f6fc46820d62d0330aaef7ca100b5f2ab781ce9643f25b4c99c844ae66e7eec5cbc  gpsd.initd
+55d4a51f82d445d3ac93b2855132ef4380908ed045feba6298ed1d0b607cd9054b5325c024dc52b370983ebd5d9b377537aee7d7128c97aa22e3075f4134d404  gpsd.confd"

+ 29 - 0
alpine/gpsd-timepps/gpsd.confd

@@ -0,0 +1,29 @@
+# /etc/conf.d/gpsd
+
+# The GPS device (/dev/ttyUSB0, /dev/ttyS0, ...)
+ 
+DEVICE=""
+BAUDRATE="4800"
+
+# Optional arguments
+#  Options include:
+#   -b                        = bluetooth-safe: open data sources read-only
+#   -n                        = don't wait for client connects to poll GPS
+#   -N                        = don't go into background
+#   -F sockfile               = specify control socket location
+#   -G                        = make gpsd listen on INADDR_ANY
+#   -D integer (default 0)    = set debug level
+#   -S integer (default 2947) = set port for daemon
+
+ARGS="-n "
+
+# Serial setup
+#
+# For serial interfaces, options such as low_latency are recommended
+# Also, http://catb.org/gpsd/upstream-bugs.html#tiocmwait recommends
+#   setting the baudrate with stty
+# Uncomment the following lines if using a serial device:
+#
+# /bin/stty -F ${DEVICE} ${BAUDRATE}
+# /bin/setserial ${DEVICE} low_latency
+

+ 38 - 0
alpine/gpsd-timepps/gpsd.initd

@@ -0,0 +1,38 @@
+#!/sbin/openrc-run
+# Copyright 2012 Nathan Angelacos 
+
+description="GPS daemon"
+
+depend() {
+	need net
+	after firewall
+	use ntp-server
+}
+
+GPS=${SVCNAME#*.}
+if [ -n "${GPS}" ] && [ ${SVCNAME} != "gpsd" ]; then
+   GPSPID="/var/run/gpsd.${GPS}.pid"
+else
+   GPSPID="/var/run/gpsd.pid"
+fi
+
+start() {
+
+        if [ -z "${DEVICE}" ]; then
+		eerror "Specify a GPS device in /etc/conf.d/${SVCNAME}" 
+		return 1
+        fi
+
+	ebegin "Starting gpsd"
+	start-stop-daemon --start --quiet \
+		--exec /usr/sbin/gpsd \
+		--  ${ARGS} -P "${GPSPID}" ${DEVICE}
+	eend $? "Failed to start gpsd"
+}
+
+stop() {
+	ebegin "Stopping gpsd"
+	start-stop-daemon --stop --quiet \
+		--pidfile "${GPSPID}"
+	eend $? "Failed to stop gpsd"
+}

+ 216 - 0
alpine/gpsd-timepps/timepps.h

@@ -0,0 +1,216 @@
+/*
+ * timepps.h -- PPS API main header
+ *
+ * Copyright (C) 2005-2007   Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2009-2011   Alexander Gordeev <alex@gordick.net>
+ *
+ *   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.
+ *
+ * Source: https://github.com/ago/pps-tools/ - Retreived Dec 2013
+ */
+
+#ifndef _SYS_TIMEPPS_H_
+#define _SYS_TIMEPPS_H_
+
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/pps.h>
+
+#define LINUXPPS	1		/* signal we are using LinuxPPS */
+
+/*
+ * New data structures
+ */
+
+struct ntp_fp {
+	unsigned int integral;
+	unsigned int fractional;
+};
+
+union pps_timeu {
+	struct timespec tspec;
+	struct ntp_fp ntpfp;
+	unsigned long longpad[3];
+};
+
+struct pps_info {
+	unsigned long assert_sequence;	/* seq. num. of assert event */
+	unsigned long clear_sequence;	/* seq. num. of clear event */
+	union pps_timeu assert_tu;	/* time of assert event */
+	union pps_timeu clear_tu;	/* time of clear event */
+	int current_mode;		/* current mode bits */
+};
+
+struct pps_params {
+	int api_version;		/* API version # */
+	int mode;			/* mode bits */
+	union pps_timeu assert_off_tu;	/* offset compensation for assert */
+	union pps_timeu clear_off_tu;	/* offset compensation for clear */
+};
+
+typedef int pps_handle_t;		/* represents a PPS source */
+typedef unsigned long pps_seq_t;	/* sequence number */
+typedef struct ntp_fp ntp_fp_t;		/* NTP-compatible time stamp */
+typedef union pps_timeu pps_timeu_t;	/* generic data type for time stamps */
+typedef struct pps_info pps_info_t;
+typedef struct pps_params pps_params_t;
+
+#define assert_timestamp        assert_tu.tspec
+#define clear_timestamp         clear_tu.tspec
+
+#define assert_timestamp_ntpfp  assert_tu.ntpfp
+#define clear_timestamp_ntpfp   clear_tu.ntpfp
+
+#define assert_offset		assert_off_tu.tspec
+#define clear_offset		clear_off_tu.tspec
+
+#define assert_offset_ntpfp     assert_off_tu.ntpfp
+#define clear_offset_ntpfp      clear_off_tu.ntpfp
+
+/*
+ * The PPS API
+ */
+
+static __inline int time_pps_create(int source, pps_handle_t *handle)
+{
+	int ret;
+	struct pps_kparams dummy;
+
+	if (!handle) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* First we check if current device is a valid PPS one by
+	 * doing a dummy PPS_GETPARAMS...
+	 */
+	ret = ioctl(source, PPS_GETPARAMS, &dummy);
+	if (ret) {
+		errno = EOPNOTSUPP;
+		return -1;
+	}
+
+	/* ... then since in LinuxPPS there are no differences between a
+	 * "PPS source" and a "PPS handle", we simply return the same value.
+	 */
+	*handle = source;
+
+	return 0;
+}
+
+static __inline int time_pps_destroy(pps_handle_t handle)
+{
+	return close(handle);
+}
+
+static __inline int time_pps_getparams(pps_handle_t handle,
+					pps_params_t *ppsparams)
+{
+	int ret;
+	struct pps_kparams __ppsparams;
+
+	ret = ioctl(handle, PPS_GETPARAMS, &__ppsparams);
+
+	ppsparams->api_version = __ppsparams.api_version;
+	ppsparams->mode = __ppsparams.mode;
+	ppsparams->assert_off_tu.tspec.tv_sec = __ppsparams.assert_off_tu.sec;
+	ppsparams->assert_off_tu.tspec.tv_nsec = __ppsparams.assert_off_tu.nsec;
+	ppsparams->clear_off_tu.tspec.tv_sec = __ppsparams.clear_off_tu.sec;
+	ppsparams->clear_off_tu.tspec.tv_nsec = __ppsparams.clear_off_tu.nsec;
+
+	return ret;
+}
+
+static __inline int time_pps_setparams(pps_handle_t handle,
+					const pps_params_t *ppsparams)
+{
+	struct pps_kparams __ppsparams;
+
+	__ppsparams.api_version = ppsparams->api_version;
+	__ppsparams.mode = ppsparams->mode;
+	__ppsparams.assert_off_tu.sec = ppsparams->assert_off_tu.tspec.tv_sec;
+	__ppsparams.assert_off_tu.nsec = ppsparams->assert_off_tu.tspec.tv_nsec;
+	__ppsparams.clear_off_tu.sec = ppsparams->clear_off_tu.tspec.tv_sec;
+	__ppsparams.clear_off_tu.nsec = ppsparams->clear_off_tu.tspec.tv_nsec;
+
+	return ioctl(handle, PPS_SETPARAMS, &__ppsparams);
+}
+
+/* Get capabilities for handle */
+static __inline int time_pps_getcap(pps_handle_t handle, int *mode)
+{
+	return ioctl(handle, PPS_GETCAP, mode);
+}
+
+static __inline int time_pps_fetch(pps_handle_t handle, const int tsformat,
+					pps_info_t *ppsinfobuf,
+					const struct timespec *timeout)
+{
+	struct pps_fdata __fdata;
+	int ret;
+
+	/* Sanity checks */
+	if (tsformat != PPS_TSFMT_TSPEC) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (timeout) {
+		__fdata.timeout.sec = timeout->tv_sec;
+		__fdata.timeout.nsec = timeout->tv_nsec;
+		__fdata.timeout.flags = ~PPS_TIME_INVALID;
+	} else
+		__fdata.timeout.flags = PPS_TIME_INVALID;
+
+	ret = ioctl(handle, PPS_FETCH, &__fdata);
+
+	ppsinfobuf->assert_sequence = __fdata.info.assert_sequence;
+	ppsinfobuf->clear_sequence = __fdata.info.clear_sequence;
+	ppsinfobuf->assert_tu.tspec.tv_sec = __fdata.info.assert_tu.sec;
+	ppsinfobuf->assert_tu.tspec.tv_nsec = __fdata.info.assert_tu.nsec;
+	ppsinfobuf->clear_tu.tspec.tv_sec = __fdata.info.clear_tu.sec;
+	ppsinfobuf->clear_tu.tspec.tv_nsec = __fdata.info.clear_tu.nsec;
+	ppsinfobuf->current_mode = __fdata.info.current_mode;
+
+	return ret;
+}
+
+#ifdef PPS_KC_BIND
+
+static __inline int time_pps_kcbind(pps_handle_t handle,
+					const int kernel_consumer,
+					const int edge, const int tsformat)
+{
+	struct pps_bind_args __bind_args;
+
+	__bind_args.tsformat = tsformat;
+	__bind_args.edge = edge;
+	__bind_args.consumer = kernel_consumer;
+
+	return ioctl(handle, PPS_KC_BIND, &__bind_args);
+}
+
+#else /* !PPS_KC_BIND */
+
+static __inline int time_pps_kcbind(pps_handle_t handle,
+					const int kernel_consumer,
+					const int edge, const int tsformat)
+{
+	/* LinuxPPS doesn't implement kernel consumer feature */
+	errno = EOPNOTSUPP;
+	return -1;
+}
+
+#endif /* PPS_KC_BIND */
+
+#endif /* _SYS_TIMEPPS_H_ */

+ 13 - 0
alpine/gpsd-timepps/timepps.patch

@@ -0,0 +1,13 @@
+diff --git a/SConstruct b/SConstruct
+index 3318bb4..5c52d57 100644
+--- a/SConstruct
++++ b/SConstruct
+@@ -271,7 +271,7 @@ for var in import_env:
+         envs[var] = os.environ[var]
+ envs["GPSD_HOME"] = os.getcwd()
+ 
+-env = Environment(tools=["default", "tar", "textfile"], options=opts, ENV=envs)
++env = Environment(tools=["default", "tar", "textfile"], options=opts, ENV=envs, CPPPATH=".")
+ 
+ #  Minimal build turns off every option not set on the command line,
+ if ARGUMENTS.get('minimal'):

+ 12 - 0
alpine/gpsd-timepps/ttydefaults.patch

@@ -0,0 +1,12 @@
+diff --git a/gpsmon.c b/gpsmon.c
+index c3001c8..965ea98 100644
+--- a/gpsmon.c
++++ b/gpsmon.c
+@@ -19,6 +19,7 @@
+ #include <sys/time.h>		/* expected to declare select(2) a la SuS */
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include <sys/ttydefaults.h>
+ #include <sys/select.h>
+ #include <fcntl.h>
+ #include <unistd.h>

+ 91 - 0
alpine/hostapd-rtl871xdrv/APKBUILD

@@ -0,0 +1,91 @@
+pkgname=hostapd-rtl871xdrv
+pkgver=2.6
+pkgrel=1
+pkgdesc="daemon for wireless software access points with rtl871xdrv patches"
+url="https://github.com/pritambaral/hostapd-rtl871xdrv"
+arch="all"
+license="custom"
+depends=
+makedepends="libressl-dev libnl3-dev linux-headers"
+install=
+subpackages="$pkgname-doc"
+patches="
+	CVE-2012-4445.patch
+	libressl-compat.patch
+	rtlxdrv.patch
+	"
+
+source="https://w1.fi/releases/hostapd-$pkgver.tar.gz
+	$patches
+	hostapd.initd
+	hostapd.confd"
+
+builddir="$srcdir"/hostapd-$pkgver/hostapd
+
+prepare() {
+	local conf="$builddir/.config"
+
+	cd "$builddir"/..
+	for i in $patches; do
+		msg $i
+		patch -p1 -i "$srcdir"/$i || return 1
+	done
+
+	cd "$builddir"
+	sed -i -e "s:/etc/hostapd:/etc/hostapd/hostapd:g" \
+		hostapd.conf
+
+	# toolchain setup
+	sed \
+		-e '/^#CONFIG_DRIVER_NL80211=y/s/^#//' \
+		-e '/^#CONFIG_RADIUS_SERVER=y/s/^#//' \
+		-e '/^#CONFIG_DRIVER_WIRED=y/s/^#//' \
+		-e '/^#CONFIG_DRIVER_NONE=y/s/^#//' \
+		-e '/^#CONFIG_IEEE80211N=y/s/^#//' \
+		-e '/^#CONFIG_IEEE80211R=y/s/^#//' \
+		-e '/^#CONFIG_IEEE80211AC=y/s/^#//' \
+		-e '/^#CONFIG_FULL_DYNAMIC_VLAN=y/s/^#//' \
+		-e '/^#CONFIG_LIBNL32=y/s/^#//' \
+		-e '/^#CONFIG_ACS=y/s/^#//' \
+		defconfig >> .config
+	echo "CONFIG_DRIVER_RTW=y" >> .config
+	echo "CC ?= ${CC:-gcc}" >> .config
+	echo "CFLAGS += -I/usr/include/libnl3" >> .config
+	echo "LIBS += -L/usr/lib" >> .config
+}
+
+build() {
+	cd "$builddir"
+	make || return 1
+	msg "nt_password_hash"
+	make nt_password_hash || return 1
+}
+
+package() {
+	cd "$builddir"
+	install -d "$pkgdir"/etc/hostapd
+	install hostapd.conf hostapd.accept hostapd.deny hostapd.eap_user \
+		hostapd.radius_clients hostapd.sim_db hostapd.wpa_psk \
+		"$pkgdir"/etc/hostapd/ || return 1
+
+	install -Dm755 hostapd "$pkgdir"/usr/sbin/hostapd \
+		&& install -Dm755 hostapd_cli "$pkgdir"/usr/bin/hostapd_cli \
+		&& install -Dm755 nt_password_hash \
+			"$pkgdir"/usr/bin/nt_password_hash \
+		&& install -Dm755 "$srcdir"/hostapd.initd \
+			"$pkgdir"/etc/init.d/hostapd \
+		&& install -Dm644 "$srcdir"/hostapd.confd \
+			"$pkgdir"/etc/conf.d/hostapd \
+		&& install -Dm644 hostapd.8 \
+			"$pkgdir"/usr/share/man/man8/hostapd.8 \
+		&& install -Dm644 hostapd_cli.1 \
+			"$pkgdir"/usr/share/man/man1/hostapd_cli \
+		|| return 1
+}
+
+sha512sums="e60baaa092786250b8de9935f5417c7626f5d749210cce9f83d776b65c19fc92a8141f41923389f05c16295d482a15ae8d8b744f4667425040c99e3c2f5b1bda  hostapd-2.6.tar.gz
+619acce84516dead1e03e5da71657ea4c4b6f3ca8271574409773aeb316cbddc88095b50320804f457f001f4f3fe83053e660c008d8409f59bb4d3bfe058b601  CVE-2012-4445.patch
+e6428a7fde025550e8d8252a04dd3a9009f95b6cab064c1f76bf4e5c321bc6acba9a21511e25f996fe98f6c9f1c057bc5af7aa9e6dd19e0bbc537b2be67d494f  libressl-compat.patch
+b398fce88fdb541e6e034939dd530e4b3e8043c2a5ecb4dc94dabb794148cbe6ee4c0e2a8caf8ef2bd6c4f4d0499133f2849c90455174918d33ac86c0e591915  rtlxdrv.patch
+b54b7c6aa17e5cb86a9b354a516eb2dbefb544df18471339c61d82776de447011a2ac290bea1e6c8beae4b6cebefafb8174683ea42fb773e9e8fe6c679f33ba3  hostapd.initd
+0882263bbd7c0b05bf51f51d66e11a23a0b8ca7da2a3b8a30166d2c5f044c0c134e6bccb1d02c9e81819ca8fb0c0fb55c7121a08fe7233ccaa73ff8ab9a238fe  hostapd.confd"

+ 45 - 0
alpine/hostapd-rtl871xdrv/CVE-2012-4445.patch

@@ -0,0 +1,45 @@
+From: Jouni Malinen <j@w1.fi>
+Date: Sun, 7 Oct 2012 17:06:29 +0000 (+0300)
+Subject: EAP-TLS server: Fix TLS Message Length validation
+X-Git-Url: http://w1.fi/gitweb/gitweb.cgi?p=hostap.git;a=commitdiff_plain;h=586c446e0ff42ae00315b014924ec669023bd8de
+
+EAP-TLS server: Fix TLS Message Length validation
+
+EAP-TLS/PEAP/TTLS/FAST server implementation did not validate TLS
+Message Length value properly and could end up trying to store more
+information into the message buffer than the allocated size if the first
+fragment is longer than the indicated size. This could result in hostapd
+process terminating in wpabuf length validation. Fix this by rejecting
+messages that have invalid TLS Message Length value.
+
+This would affect cases that use the internal EAP authentication server
+in hostapd either directly with IEEE 802.1X or when using hostapd as a
+RADIUS authentication server and when receiving an incorrectly
+constructed EAP-TLS message. Cases where hostapd uses an external
+authentication are not affected.
+
+Thanks to Timo Warns for finding and reporting this issue.
+
+Signed-hostap: Jouni Malinen <j@w1.fi>
+intended-for: hostap-1
+---
+
+diff --git a/src/eap_server/eap_server_tls_common.c b/src/eap_server/eap_server_tls_common.c
+index 31be2ec..46f282b 100644
+--- a/src/eap_server/eap_server_tls_common.c
++++ b/src/eap_server/eap_server_tls_common.c
+@@ -228,6 +228,14 @@ static int eap_server_tls_process_fragment(struct eap_ssl_data *data,
+ 			return -1;
+ 		}
+ 
++		if (len > message_length) {
++			wpa_printf(MSG_INFO, "SSL: Too much data (%d bytes) in "
++				   "first fragment of frame (TLS Message "
++				   "Length %d bytes)",
++				   (int) len, (int) message_length);
++			return -1;
++		}
++
+ 		data->tls_in = wpabuf_alloc(message_length);
+ 		if (data->tls_in == NULL) {
+ 			wpa_printf(MSG_DEBUG, "SSL: No memory for message");

+ 69 - 0
alpine/hostapd-rtl871xdrv/crypto_tls_openssl_c.patch

@@ -0,0 +1,69 @@
+$OpenBSD: patch-src_crypto_tls_openssl_c,v 1.3 2015/09/29 11:57:54 dcoppa Exp $
+
+Compatibility fixes for LibreSSL
+
+--- a/src/crypto/tls_openssl.c.orig	Sun Sep 27 21:02:05 2015
++++ b/src/crypto/tls_openssl.c	Mon Sep 28 13:43:46 2015
+@@ -2229,7 +2229,7 @@ static int tls_parse_pkcs12(struct tls_data *data, SSL
+ 	}
+ 
+ 	if (certs) {
+-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
++#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
+ 		SSL_clear_chain_certs(ssl);
+ 		while ((cert = sk_X509_pop(certs)) != NULL) {
+ 			X509_NAME_oneline(X509_get_subject_name(cert), buf,
+@@ -2247,7 +2247,7 @@ static int tls_parse_pkcs12(struct tls_data *data, SSL
+ 			/* Try to continue anyway */
+ 		}
+ 		sk_X509_free(certs);
+-#ifndef OPENSSL_IS_BORINGSSL
++#if !defined(OPENSSL_IS_BORINGSSL) && !defined(LIBRESSL_VERSION_NUMBER)
+ 		res = SSL_build_cert_chain(ssl,
+ 					   SSL_BUILD_CHAIN_FLAG_CHECK |
+ 					   SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR);
+@@ -2812,7 +2812,7 @@ int tls_connection_get_random(void *ssl_ctx, struct tl
+ 	if (conn == NULL || keys == NULL)
+ 		return -1;
+ 	ssl = conn->ssl;
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ 	if (ssl == NULL || ssl->s3 == NULL || ssl->session == NULL)
+ 		return -1;
+ 
+@@ -2841,7 +2841,7 @@ int tls_connection_get_random(void *ssl_ctx, struct tl
+ #ifndef CONFIG_FIPS
+ static int openssl_get_keyblock_size(SSL *ssl)
+ {
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ 	const EVP_CIPHER *c;
+ 	const EVP_MD *h;
+ 	int md_size;
+@@ -2911,7 +2911,7 @@ static int openssl_tls_prf(struct tls_connection *conn
+ 		   "mode");
+ 	return -1;
+ #else /* CONFIG_FIPS */
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ 	SSL *ssl;
+ 	u8 *rnd;
+ 	int ret = -1;
+@@ -3394,7 +3394,7 @@ int tls_connection_set_cipher_list(void *tls_ctx, stru
+ 
+ 	wpa_printf(MSG_DEBUG, "OpenSSL: cipher suites: %s", buf + 1);
+ 
+-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
++#if OPENSSL_VERSION_NUMBER >= 0x10100000L && !defined(LIBRESSL_VERSION_NUMBER)
+ #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
+ 	if (os_strstr(buf, ":ADH-")) {
+ 		/*
+@@ -3977,7 +3977,7 @@ static int tls_sess_sec_cb(SSL *s, void *secret, int *
+ 	struct tls_connection *conn = arg;
+ 	int ret;
+ 
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ 	if (conn == NULL || conn->session_ticket_cb == NULL)
+ 		return 0;
+ 

+ 5 - 0
alpine/hostapd-rtl871xdrv/hostapd.confd

@@ -0,0 +1,5 @@
+# Space separated list of configuration files
+CONFIGS="/etc/hostapd/hostapd.conf"
+
+# Extra options to pass to hostapd, see hostapd(8)
+OPTIONS=""

+ 46 - 0
alpine/hostapd-rtl871xdrv/hostapd.initd

@@ -0,0 +1,46 @@
+#!/sbin/openrc-run
+# Copyright 1999-2006 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/net-wireless/hostapd/files/hostapd-0.6.9-init.d,v 1.2 2009/05/17 10:18:18 gurligebis Exp $
+
+extra_started_commands="reload"
+
+depend() {
+	need net
+	after firewall
+	use logger
+}
+
+checkconfig() {
+	local file
+
+	for file in ${CONFIGS}; do
+		if [ ! -r "${file}" ]; then
+			eerror "hostapd configuration file (${CONFIG}) not found"
+			return 1
+		fi
+	done
+}
+
+start() {
+	checkconfig || return 1
+
+	ebegin "Starting ${SVCNAME}"
+	start-stop-daemon --start --exec /usr/sbin/hostapd \
+		-- -B ${OPTIONS} ${CONFIGS}
+	eend $?
+}
+
+stop() {
+	ebegin "Stopping ${SVCNAME}"
+	start-stop-daemon --stop --exec /usr/sbin/hostapd
+	eend $?
+}
+
+reload() {
+	checkconfig || return 1
+
+	ebegin "Reloading ${SVCNAME} configuration"
+	kill -HUP $(pidof /usr/sbin/hostapd) > /dev/null 2>&1
+	eend $?
+}

+ 22 - 0
alpine/hostapd-rtl871xdrv/libressl-compat.patch

@@ -0,0 +1,22 @@
+diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
+index 19e0e2b..b3d1b07 100644
+--- a/src/crypto/crypto_openssl.c
++++ b/src/crypto/crypto_openssl.c
+@@ -611,7 +611,7 @@ void crypto_cipher_deinit(struct crypto_cipher *ctx)
+ 
+ void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
+ {
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ 	DH *dh;
+ 	struct wpabuf *pubkey = NULL, *privkey = NULL;
+ 	size_t publen, privlen;
+@@ -712,7 +712,7 @@ err:
+ 
+ void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
+ {
+-#if OPENSSL_VERSION_NUMBER < 0x10100000L
++#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
+ 	DH *dh;
+ 
+ 	dh = DH_new();

+ 2722 - 0
alpine/hostapd-rtl871xdrv/rtlxdrv.patch

@@ -0,0 +1,2722 @@
+diff --git a/hostapd/main.c b/hostapd/main.c
+index 2c8dbd3..9c12191 100644
+--- a/hostapd/main.c
++++ b/hostapd/main.c
+@@ -448,7 +448,7 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
+ static void show_version(void)
+ {
+ 	fprintf(stderr,
+-		"hostapd v" VERSION_STR "\n"
++		"hostapd v" VERSION_STR " for Realtek rtl871xdrv\n"
+ 		"User space daemon for IEEE 802.11 AP management,\n"
+ 		"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
+ 		"Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> "
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
+index 233320d..49b5b1e 100644
+--- a/src/ap/beacon.c
++++ b/src/ap/beacon.c
+@@ -1126,6 +1126,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
+ 
+ 	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
+ 	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
++
++	//DRIVER_RTW ADD
++	if(hapd->iconf->ieee80211n)
++		hapd->conf->wmm_enabled = 1;
++
+ #endif /* CONFIG_IEEE80211N */
+ 
+ 	tailpos = hostapd_eid_ext_capab(hapd, tailpos);
+diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
+index 16887ac..aa1f572 100644
+--- a/src/ap/hw_features.c
++++ b/src/ap/hw_features.c
+@@ -496,7 +496,10 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
+ 		iface->num_ht40_scan_tries = 1;
+ 		eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL);
+ 		eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL);
+-		return 1;
++
++		//DRIVER_RTW Modify
++		//return -1;
++		return 0;//ignore this error
+ 	}
+ 
+ 	if (ret < 0) {
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
+index a449cc9..3b9629c 100644
+--- a/src/drivers/driver.h
++++ b/src/drivers/driver.h
+@@ -4984,5 +4984,8 @@ extern const struct wpa_driver_ops wpa_driver_atheros_ops;
+ #ifdef CONFIG_DRIVER_NONE
+ extern const struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */
+ #endif /* CONFIG_DRIVER_NONE */
++#ifdef CONFIG_DRIVER_RTW
++extern const struct wpa_driver_ops wpa_driver_rtw_ops; /* driver_rtw.c */
++#endif /* CONFIG_DRIVER_RTW */
+ 
+ #endif /* DRIVER_H */
+diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
+index 2afd7df..0bd7fb2 100644
+--- a/src/drivers/driver_bsd.c
++++ b/src/drivers/driver_bsd.c
+@@ -56,6 +56,12 @@ struct bsd_driver_global {
+ 	struct dl_list	ifaces;			/* list of interfaces */
+ };
+ 
++#ifdef HOSTAPD
++#ifdef CONFIG_SUPPORT_RTW_DRIVER
++#define RTW_BSD_HOSTAPD_SET_BEACON (1100)
++#endif
++#endif
++
+ struct bsd_driver_data {
+ 	struct dl_list	list;
+ 	struct bsd_driver_global *global;
+@@ -846,6 +852,296 @@ handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
+ 	drv_event_eapol_rx(drv->hapd, src_addr, buf, len);
+ }
+ 
++#ifdef CONFIG_SUPPORT_RTW_DRIVER
++static int rtw_set_beacon_ops(void *priv, const u8 *head, size_t head_len,
++			  const u8 *tail, size_t tail_len, int dtim_period,
++			  int beacon_int)
++{
++	int ret=0;
++	u8 *pbuf;
++	size_t sz;
++	struct bsd_driver_data *drv = priv;
++
++	if((head_len<24) ||(!head))
++		return -1;
++
++	sz = head_len+tail_len - 24; // 24 = wlan hdr
++
++	printf("%s, beacon_sz=%d\n", __func__, sz);
++
++	pbuf = os_zalloc(sz);
++	if (pbuf == NULL) {
++		return -ENOMEM;
++	}
++
++	os_memcpy(pbuf, (head+24), (head_len-24));// 24=beacon header len.
++
++	os_memcpy(&pbuf[head_len-24], tail, tail_len);
++
++	ret = set80211var(drv, RTW_BSD_HOSTAPD_SET_BEACON, pbuf, sz);
++
++	os_free(pbuf);
++
++	return ret;
++
++}
++
++static struct hostapd_hw_modes *rtw_get_hw_feature_data_ops(
++	void *priv, u16 *num_modes, u16 *flags)
++{
++
++#define MAX_NUM_CHANNEL (14)
++#define MAX_NUM_CHANNEL_5G (24)
++
++	struct hostapd_hw_modes *modes;
++	size_t i;
++	int k;
++
++	printf("%s\n", __func__);
++
++	*num_modes = 3;
++	*flags = 0;
++
++	modes = os_zalloc(*num_modes * sizeof(struct hostapd_hw_modes));
++	if (modes == NULL)
++		return NULL;
++
++	//.1
++	modes[0].mode = HOSTAPD_MODE_IEEE80211G;
++	modes[0].num_channels = MAX_NUM_CHANNEL;
++	modes[0].num_rates = 12;
++	modes[0].channels =
++		os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
++	modes[0].rates = os_zalloc(modes[0].num_rates * sizeof(int));
++	if (modes[0].channels == NULL || modes[0].rates == NULL)
++		goto fail;
++	for (i = 0; i < MAX_NUM_CHANNEL; i++) {
++		modes[0].channels[i].chan = i + 1;
++		modes[0].channels[i].freq = 2412 + 5 * i;
++		modes[0].channels[i].flag = 0;
++		if (i >= 13)
++			modes[0].channels[i].flag = HOSTAPD_CHAN_DISABLED;
++	}
++	modes[0].rates[0] = 10;
++	modes[0].rates[1] = 20;
++	modes[0].rates[2] = 55;
++	modes[0].rates[3] = 110;
++	modes[0].rates[4] = 60;
++	modes[0].rates[5] = 90;
++	modes[0].rates[6] = 120;
++	modes[0].rates[7] = 180;
++	modes[0].rates[8] = 240;
++	modes[0].rates[9] = 360;
++	modes[0].rates[10] = 480;
++	modes[0].rates[11] = 540;
++
++
++	//.2
++	modes[1].mode = HOSTAPD_MODE_IEEE80211B;
++	modes[1].num_channels = MAX_NUM_CHANNEL;
++	modes[1].num_rates = 4;
++	modes[1].channels =
++		os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
++	modes[1].rates = os_zalloc(modes[1].num_rates * sizeof(int));
++	if (modes[1].channels == NULL || modes[1].rates == NULL)
++		goto fail;
++	for (i = 0; i < MAX_NUM_CHANNEL; i++) {
++		modes[1].channels[i].chan = i + 1;
++		modes[1].channels[i].freq = 2412 + 5 * i;
++		modes[1].channels[i].flag = 0;
++		if (i >= 11)
++			modes[1].channels[i].flag = HOSTAPD_CHAN_DISABLED;
++	}
++	modes[1].rates[0] = 10;
++	modes[1].rates[1] = 20;
++	modes[1].rates[2] = 55;
++	modes[1].rates[3] = 110;
++
++
++	//.3
++	modes[2].mode = HOSTAPD_MODE_IEEE80211A;
++#ifdef CONFIG_DRIVER_RTL_DFS
++	modes[2].num_channels = MAX_NUM_CHANNEL_5G;
++#else /* CONFIG_DRIVER_RTL_DFS */
++	modes[2].num_channels = 9;
++#endif /* CONFIG_DRIVER_RTL_DFS */
++
++	modes[2].num_rates = 8;
++	modes[2].channels = os_zalloc(modes[2].num_channels * sizeof(struct hostapd_channel_data));
++	modes[2].rates = os_zalloc(modes[2].num_rates * sizeof(int));
++	if (modes[2].channels == NULL || modes[2].rates == NULL)
++		goto fail;
++
++
++	k = 0;
++	// 5G band1 Channel: 36, 40, 44, 48
++	for (i=0; i < 4; i++) {
++		modes[2].channels[k].chan = 36+(i*4);
++		modes[2].channels[k].freq = 5180+(i*20);
++		modes[2].channels[k].flag = 0;
++		k++;
++	}
++
++#ifdef CONFIG_DRIVER_RTL_DFS
++	// 5G band2 Channel: 52, 56, 60, 64
++	for (i=0; i < 4; i++) {
++		modes[2].channels[k].chan = 52+(i*4);
++		modes[2].channels[k].freq = 5260+(i*20);
++		modes[2].channels[k].flag = 0;
++		k++;
++	}
++
++	// 5G band3 Channel: 100, 104, 108. 112, 116, 120, 124, 128, 132, 136, 140
++	for (i=0; i < 11; i++) {
++		modes[2].channels[k].chan = 100+(i*4);
++		modes[2].channels[k].freq = 5500+(i*20);
++		modes[2].channels[k].flag = 0;
++		k++;
++	}
++#endif /* CONFIG_DRIVER_RTL_DFS */
++
++	// 5G band4 Channel: 149, 153, 157, 161, 165
++	for (i=0; i < 5; i++) {
++		modes[2].channels[k].chan = 149+(i*4);
++		modes[2].channels[k].freq = 5745+(i*20);
++		modes[2].channels[k].flag = 0;
++		k++;
++	}
++
++	modes[2].rates[0] = 60;
++	modes[2].rates[1] = 90;
++	modes[2].rates[2] = 120;
++	modes[2].rates[3] = 180;
++	modes[2].rates[4] = 240;
++	modes[2].rates[5] = 360;
++	modes[2].rates[6] = 480;
++	modes[2].rates[7] = 540;
++
++
++	//
++#if 0
++#define HT_CAP_INFO_LDPC_CODING_CAP		((u16) BIT(0))
++#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET	((u16) BIT(1))
++#define HT_CAP_INFO_SMPS_MASK			((u16) (BIT(2) | BIT(3)))
++#define HT_CAP_INFO_SMPS_STATIC			((u16) 0)
++#define HT_CAP_INFO_SMPS_DYNAMIC		((u16) BIT(2))
++#define HT_CAP_INFO_SMPS_DISABLED		((u16) (BIT(2) | BIT(3)))
++#define HT_CAP_INFO_GREEN_FIELD			((u16) BIT(4))
++#define HT_CAP_INFO_SHORT_GI20MHZ		((u16) BIT(5))
++#define HT_CAP_INFO_SHORT_GI40MHZ		((u16) BIT(6))
++#define HT_CAP_INFO_TX_STBC			((u16) BIT(7))
++#define HT_CAP_INFO_RX_STBC_MASK		((u16) (BIT(8) | BIT(9)))
++#define HT_CAP_INFO_RX_STBC_1			((u16) BIT(8))
++#define HT_CAP_INFO_RX_STBC_12			((u16) BIT(9))
++#define HT_CAP_INFO_RX_STBC_123			((u16) (BIT(8) | BIT(9)))
++#define HT_CAP_INFO_DELAYED_BA			((u16) BIT(10))
++#define HT_CAP_INFO_MAX_AMSDU_SIZE		((u16) BIT(11))
++#define HT_CAP_INFO_DSSS_CCK40MHZ		((u16) BIT(12))
++#define HT_CAP_INFO_PSMP_SUPP			((u16) BIT(13))
++#define HT_CAP_INFO_40MHZ_INTOLERANT		((u16) BIT(14))
++#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT	((u16) BIT(15))
++#endif
++
++	//HOSTAPD_MODE_IEEE80211G
++	modes[0].ht_capab = HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET|HT_CAP_INFO_SHORT_GI20MHZ|
++			HT_CAP_INFO_SHORT_GI40MHZ|HT_CAP_INFO_MAX_AMSDU_SIZE|HT_CAP_INFO_DSSS_CCK40MHZ;
++
++	modes[0].mcs_set[0]= 0xff;
++	modes[0].mcs_set[1]= 0xff;
++
++	//HOSTAPD_MODE_IEEE80211B
++	modes[1].ht_capab = 0;
++
++	//HOSTAPD_MODE_IEEE80211A
++	modes[2].ht_capab = modes[0].ht_capab;
++
++	modes[2].mcs_set[0]= 0xff;
++	modes[2].mcs_set[1]= 0xff;
++
++	return modes;
++
++fail:
++	if (modes) {
++		for (i = 0; i < *num_modes; i++) {
++			os_free(modes[i].channels);
++			os_free(modes[i].rates);
++		}
++		os_free(modes);
++	}
++
++	return NULL;
++
++}
++
++#if 0
++#define 	IEEE80211_FC0_TYPE_MASK   0x0c
++#define 	IEEE80211_FC0_TYPE_SHIFT   2
++#define 	IEEE80211_FC0_TYPE_MGT   0x00
++#define 	IEEE80211_FC0_TYPE_CTL   0x04
++#define 	IEEE80211_FC0_TYPE_DATA   0x08
++#define 	IEEE80211_FC0_SUBTYPE_MASK   0xf0
++#define 	IEEE80211_FC0_SUBTYPE_SHIFT   4
++#define 	IEEE80211_FC0_SUBTYPE_ASSOC_REQ   0x00
++#define 	IEEE80211_FC0_SUBTYPE_ASSOC_RESP   0x10
++#define 	IEEE80211_FC0_SUBTYPE_REASSOC_REQ   0x20
++#define 	IEEE80211_FC0_SUBTYPE_REASSOC_RESP   0x30
++#define 	IEEE80211_FC0_SUBTYPE_PROBE_REQ   0x40
++#define 	IEEE80211_FC0_SUBTYPE_PROBE_RESP   0x50
++#define 	IEEE80211_FC0_SUBTYPE_BEACON   0x80
++#define 	IEEE80211_FC0_SUBTYPE_ATIM   0x90
++#define 	IEEE80211_FC0_SUBTYPE_DISASSOC   0xa0
++#define 	IEEE80211_FC0_SUBTYPE_AUTH   0xb0
++#define 	IEEE80211_FC0_SUBTYPE_DEAUTH   0xc0
++#define 	IEEE80211_FC0_SUBTYPE_ACTION   0xd0
++#define 	IEEE80211_FC0_SUBTYPE_ACTION_NOACK   0xe0
++
++#define IEEE80211_APPIE_WPA (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON | \
++         IEEE80211_FC0_SUBTYPE_PROBE_RESP)
++
++#endif
++
++#define RTW_IEEE80211_APPIE_BEACON (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_BEACON)
++#define RTW_IEEE80211_APPIE_PROBE_RESP (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_PROBE_RESP)
++#define RTW_IEEE80211_APPIE_ASSOC_RESP (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_ASSOC_RESP)
++
++
++static int rtw_set_wps_assoc_resp_ie(void *priv, const void *ie, size_t len)
++{
++	return bsd_set80211(priv, IEEE80211_IOC_APPIE, RTW_IEEE80211_APPIE_ASSOC_RESP,
++			    ie, len);
++}
++
++static int rtw_set_wps_beacon_ie(void *priv, const void *ie, size_t len)
++{
++	return bsd_set80211(priv, IEEE80211_IOC_APPIE, RTW_IEEE80211_APPIE_BEACON,
++			    ie, len);	
++}
++
++static int rtw_set_wps_probe_resp_ie(void *priv, const void *ie, size_t len)
++{
++	return bsd_set80211(priv, IEEE80211_IOC_APPIE, RTW_IEEE80211_APPIE_PROBE_RESP,
++			    ie, len);	
++}
++
++static int rtw_set_ap_wps_ie_ops(void *priv, const struct wpabuf *beacon,
++		      const struct wpabuf *proberesp, const struct wpabuf *assocresp)
++{
++	if (rtw_set_wps_assoc_resp_ie(priv, assocresp ? wpabuf_head(assocresp) : NULL,
++			       assocresp ? wpabuf_len(assocresp) : 0))
++		return -1;
++
++	if (rtw_set_wps_beacon_ie(priv, beacon ? wpabuf_head(beacon) : NULL,
++			       beacon ? wpabuf_len(beacon) : 0))
++		return -1;
++
++	return rtw_set_wps_probe_resp_ie(priv,
++				  proberesp ? wpabuf_head(proberesp) : NULL,
++				  proberesp ? wpabuf_len(proberesp): 0);
++
++}
++#endif
++
++
+ static void *
+ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
+ {
+@@ -887,6 +1183,12 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
+ 
+ 	dl_list_add(&drv->global->ifaces, &drv->list);
+ 
++#ifdef CONFIG_SUPPORT_RTW_DRIVER
++	/* mark up after init */
++	if (bsd_ctrl_iface(drv, 1) < 0)
++		goto bad;
++#endif
++
+ 	return drv;
+ bad:
+ 	if (drv->sock_xmit != NULL)
+@@ -1330,6 +1632,15 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
+ 					     EVENT_MICHAEL_MIC_FAILURE, &event);
+ 			break;
+ 		}
++		else{
++			os_strlcpy(event.interface_status.ifname, drv->ifname,
++				   sizeof(event.interface_status.ifname));
++			event.interface_status.ievent = EVENT_INTERFACE_ADDED;
++			wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
++				   event.interface_status.ifname);
++			wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
++		}
++
+ 		break;
+ 	case RTM_IFINFO:
+ 		ifm = (struct if_msghdr *) rtm;
+@@ -1719,7 +2030,52 @@ bsd_global_deinit(void *priv)
+ 	os_free(global);
+ }
+ 
+-
++#ifdef CONFIG_SUPPORT_RTW_DRIVER
++const struct wpa_driver_ops wpa_driver_bsd_ops = {
++	.name			= "bsd",
++	.desc			= "BSD 802.11 support",
++#ifdef HOSTAPD
++	.hapd_init		= bsd_init,
++	.hapd_deinit		= bsd_deinit,
++	.set_privacy		= bsd_set_privacy,//del ?
++	.get_seqnum		= bsd_get_seqnum,//del ?
++	.flush			= bsd_flush,
++	.read_sta_data	= bsd_read_sta_driver_data,//del ?
++	.sta_disassoc		= bsd_sta_disassoc,
++	.sta_deauth		= bsd_sta_deauth,
++	.get_hw_feature_data = rtw_get_hw_feature_data_ops,//add
++	//.sta_remove = rtl871x_sta_remove_ops,//add
++	.set_beacon = rtw_set_beacon_ops,	//add
++	.set_ap_wps_ie = rtw_set_ap_wps_ie_ops,//add
++#else /* HOSTAPD */
++	.init			= wpa_driver_bsd_init,
++	.deinit			= wpa_driver_bsd_deinit,
++	.get_bssid		= wpa_driver_bsd_get_bssid,
++	.get_ssid		= wpa_driver_bsd_get_ssid,
++	.set_countermeasures	= wpa_driver_bsd_set_countermeasures,
++	.scan2			= wpa_driver_bsd_scan,
++	.get_scan_results2	= wpa_driver_bsd_get_scan_results2,
++	.deauthenticate		= wpa_driver_bsd_deauthenticate,
++	.disassociate		= wpa_driver_bsd_disassociate,
++	.associate		= wpa_driver_bsd_associate,
++	.get_capa		= wpa_driver_bsd_get_capa,
++	.set_freq		= bsd_set_freq, //only for wpa_supplicant
++	.set_ieee8021x		= bsd_set_ieee8021x,//only for wpa_supplicant
++	.hapd_set_ssid		= bsd_set_ssid,//only for wpa_supplicant
++	.hapd_get_ssid		= bsd_get_ssid,//only for wpa_supplicant
++	.sta_set_flags		= bsd_set_sta_authorized, //only for wpa_supplicant
++	.set_generic_elem	= bsd_set_opt_ie, //only for wpa_supplicant
++#endif /* HOSTAPD */
++	//.set_freq		= bsd_set_freq, //only for wpa_supplicant
++	.set_key		= bsd_set_key,
++	//.set_ieee8021x		= bsd_set_ieee8021x, //only for wpa_supplicant
++	//.hapd_set_ssid		= bsd_set_ssid, //only for wpa_supplicant
++	//.hapd_get_ssid		= bsd_get_ssid, //only for wpa_supplicant
++	.hapd_send_eapol	= bsd_send_eapol, //only for wpa_supplicant
++	//.sta_set_flags		= bsd_set_sta_authorized, //only for wpa_supplicant
++	//.set_generic_elem	= bsd_set_opt_ie, //only for wpa_supplicant
++};
++#else
+ const struct wpa_driver_ops wpa_driver_bsd_ops = {
+ 	.name			= "bsd",
+ 	.desc			= "BSD 802.11 support",
+@@ -1756,3 +2112,4 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
+ 	.hapd_send_eapol	= bsd_send_eapol,
+ 	.set_generic_elem	= bsd_set_opt_ie,
+ };
++#endif
+diff --git a/src/drivers/driver_rtl.h b/src/drivers/driver_rtl.h
+new file mode 100644
+index 0000000..c5ee335
+--- /dev/null
++++ b/src/drivers/driver_rtl.h
+@@ -0,0 +1,114 @@
++
++#ifndef _DRIVER_RTL_H_
++#define _DRIVER_RTL_H_
++
++
++#define RTL_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 28)
++
++#define	IEEE_CRYPT_ALG_NAME_LEN (16)
++
++/* RTL871X_IOCTL_HOSTAPD ioctl() cmd: */
++enum {
++	RTL871X_HOSTAPD_FLUSH = 1,
++	RTL871X_HOSTAPD_ADD_STA = 2,
++	RTL871X_HOSTAPD_REMOVE_STA = 3,
++	RTL871X_HOSTAPD_GET_INFO_STA = 4,
++	/* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
++	RTL871X_HOSTAPD_GET_WPAIE_STA = 5,
++	RTL871X_SET_ENCRYPTION = 6,
++	RTL871X_GET_ENCRYPTION = 7,
++	RTL871X_HOSTAPD_SET_FLAGS_STA = 8,
++	RTL871X_HOSTAPD_GET_RID = 9,
++	RTL871X_HOSTAPD_SET_RID = 10,
++	RTL871X_HOSTAPD_SET_ASSOC_AP_ADDR = 11,
++	RTL871X_HOSTAPD_SET_GENERIC_ELEMENT = 12,
++	RTL871X_HOSTAPD_MLME = 13,
++	RTL871X_HOSTAPD_SCAN_REQ = 14,
++	RTL871X_HOSTAPD_STA_CLEAR_STATS = 15,
++	RTL871X_HOSTAPD_SET_BEACON = 16,
++	RTL871X_HOSTAPD_SET_WPS_BEACON = 17,
++	RTL871X_HOSTAPD_SET_WPS_PROBE_RESP = 18,
++	RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP = 19,
++	RTL871X_HOSTAPD_SET_HIDDEN_SSID = 20,
++};
++
++typedef struct ieee_param {
++	u32 cmd;
++	u8 sta_addr[ETH_ALEN];
++       union {
++		struct {
++			u8 name;
++			u32 value;
++		} wpa_param;
++		struct {
++			u32 len;
++			u8 reserved[32];
++			u8 data[0];
++		} wpa_ie;
++	        struct{
++			int command;
++    			int reason_code;
++		} mlme;
++		struct {
++			u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
++			u8 set_tx;
++			u32 err;
++			u8 idx;
++			u8 seq[8]; /* sequence counter (set: RX, get: TX) */
++			u16 key_len;
++			u8 key[0];
++		} crypt;
++		struct {
++			u16 aid;
++			u16 capability;
++			int flags;
++			u8 tx_supp_rates[16];			
++			//struct ieee80211_ht_capability ht_cap;
++			struct ieee80211_ht_capabilities ht_cap;
++		} add_sta;
++		struct {
++			u8	reserved[2];//for set max_num_sta
++			u8	buf[0];
++		} bcn_ie;
++
++	} u;
++	   
++} ieee_param;
++	   
++
++
++#define IEEE80211_CCK_RATE_LEN  		4
++#define IEEE80211_OFDM_RATE_LEN 		8
++
++#define IEEE80211_CCK_RATE_1MB		        0x02
++#define IEEE80211_CCK_RATE_2MB		        0x04
++#define IEEE80211_CCK_RATE_5MB		        0x0B
++#define IEEE80211_CCK_RATE_11MB		        0x16
++#define IEEE80211_OFDM_RATE_6MB		        0x0C
++#define IEEE80211_OFDM_RATE_9MB		        0x12
++#define IEEE80211_OFDM_RATE_12MB		0x18
++#define IEEE80211_OFDM_RATE_18MB		0x24
++#define IEEE80211_OFDM_RATE_24MB		0x30
++#define IEEE80211_OFDM_RATE_36MB		0x48
++#define IEEE80211_OFDM_RATE_48MB		0x60
++#define IEEE80211_OFDM_RATE_54MB		0x6C
++#define IEEE80211_BASIC_RATE_MASK		0x80
++
++#define IEEE80211_CCK_RATE_1MB_MASK		(1<<0)
++#define IEEE80211_CCK_RATE_2MB_MASK		(1<<1)
++#define IEEE80211_CCK_RATE_5MB_MASK		(1<<2)
++#define IEEE80211_CCK_RATE_11MB_MASK		(1<<3)
++#define IEEE80211_OFDM_RATE_6MB_MASK		(1<<4)
++#define IEEE80211_OFDM_RATE_9MB_MASK		(1<<5)
++#define IEEE80211_OFDM_RATE_12MB_MASK		(1<<6)
++#define IEEE80211_OFDM_RATE_18MB_MASK		(1<<7)
++#define IEEE80211_OFDM_RATE_24MB_MASK		(1<<8)
++#define IEEE80211_OFDM_RATE_36MB_MASK		(1<<9)
++#define IEEE80211_OFDM_RATE_48MB_MASK		(1<<10)
++#define IEEE80211_OFDM_RATE_54MB_MASK		(1<<11)
++
++#define IEEE80211_CCK_RATES_MASK	        0x0000000F
++#define IEEE80211_OFDM_RATES_MASK		0x00000FF0
++
++#endif
++
+diff --git a/src/drivers/driver_rtw.c b/src/drivers/driver_rtw.c
+new file mode 100644
+index 0000000..c10b9cc
+--- /dev/null
++++ b/src/drivers/driver_rtw.c
+@@ -0,0 +1,1971 @@
++/*
++ * hostapd / Driver interface for rtl871x driver
++ * Copyright (c) 2010,
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * Alternatively, this software may be distributed under the terms of BSD
++ * license.
++ *
++ * See README and COPYING for more details.
++ */
++
++//#define CONFIG_MGNT_L2SOCK 1
++#define CONFIG_MLME_OFFLOAD 1
++
++
++#include "includes.h"
++#include <net/if.h>
++#include <sys/ioctl.h>
++
++#include "common.h"
++
++/*#include "wireless_copy.h"*/
++#include "linux_wext.h"
++
++#include "driver.h"
++#include "eloop.h"
++#include "priv_netlink.h"
++#include "l2_packet/l2_packet.h"
++#include "common/ieee802_11_defs.h"
++#include "netlink.h"
++#include "linux_ioctl.h"
++
++//#include "../src/ap/hostapd.h"
++//#include "../src/ap/ap_config.h"
++#include "ap/hostapd.h"
++#include "ap/ap_config.h"
++
++#ifdef USE_KERNEL_HEADERS
++/* compat-wireless does not include linux/compiler.h to define __user, so
++ * define it here */
++#ifndef __user
++#define __user
++#endif /* __user */
++#include <asm/types.h>
++#include <linux/if_packet.h>
++#include <linux/if_ether.h>   /* The L2 protocols */
++#include <linux/if_arp.h>
++#include <linux/wireless.h>
++#else /* USE_KERNEL_HEADERS */
++#include <net/if_arp.h>
++#include <netpacket/packet.h>
++//#include "wireless_copy.h"
++#endif /* USE_KERNEL_HEADERS */
++
++//#include <net/if.h>
++
++
++#ifndef ETH_P_80211_RAW
++#define ETH_P_80211_RAW 0x0019
++#endif
++
++#if 0
++#include "hostapd.h"
++#include "driver.h"
++#include "ieee802_1x.h"
++#include "eloop.h"
++#include "priv_netlink.h"
++#include "sta_info.h"
++#include "l2_packet/l2_packet.h"
++
++#include "wpa.h"
++#include "accounting.h"
++#include "ieee802_11.h"
++#include "hw_features.h"
++#include "radius/radius.h"
++#endif
++
++#include "driver_rtl.h"
++
++
++//static int rtl871x_sta_remove_ops(void *priv, const u8 *addr);
++
++struct rtl871x_driver_data {
++	struct hostapd_data *hapd;
++
++	char	iface[IFNAMSIZ + 1];
++	int     ifindex;
++	struct l2_packet_data *l2_sock;/* socket for sending eapol frames*/
++	struct l2_packet_data *l2_sock_recv;/* raw packet recv socket from bridge interface*/
++#ifdef CONFIG_MGNT_L2SOCK
++	struct l2_packet_data *mgnt_l2_sock; /* socket for tx/rx management frames*/
++#else
++	int	mgnt_sock;/* socket for tx/rx management frames*/
++#endif
++	int	ioctl_sock;			/* socket for ioctl() use */
++	int	wext_sock;			/* socket for wireless events */
++
++	struct netlink_data *netlink;
++
++	int	we_version;
++
++	u8	hw_mac[ETH_ALEN];
++
++	u8	acct_mac[ETH_ALEN];
++
++	struct hostap_sta_driver_data acct_data;
++
++};
++
++/*
++static const char *ether_sprintf(const u8 *addr)
++{
++	static char buf[sizeof(MACSTR)];
++
++	if (addr != NULL)
++		snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
++	else
++		snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
++
++	return buf;
++}
++*/
++
++#ifndef CONFIG_MLME_OFFLOAD
++static int rtl871x_set_iface_flags(void *priv, int dev_up)
++{
++	struct rtl871x_driver_data *drv = priv;
++	struct ifreq ifr;
++
++	wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up);
++
++	if (drv->mgnt_sock < 0)
++		return -1;
++
++	memset(&ifr, 0, sizeof(ifr));
++	//os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
++	//os_strlcpy(ifr.ifr_name, "mgnt.wlan", IFNAMSIZ);
++	snprintf(ifr.ifr_name, IFNAMSIZ, "mgnt.%s", "wlan0");
++
++	if (ioctl(drv->mgnt_sock, SIOCGIFFLAGS, &ifr) != 0) {
++		perror("ioctl[SIOCGIFFLAGS]");
++		return -1;
++	}
++
++	if (dev_up)
++		ifr.ifr_flags |= IFF_UP;
++	else
++		ifr.ifr_flags &= ~IFF_UP;
++
++	if (ioctl(drv->mgnt_sock, SIOCSIFFLAGS, &ifr) != 0) {
++		perror("ioctl[SIOCSIFFLAGS]");
++		return -1;
++	}
++
++#if 0
++	if (dev_up) {
++		memset(&ifr, 0, sizeof(ifr));
++		os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
++		ifr.ifr_mtu = HOSTAPD_MTU;
++		if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
++			perror("ioctl[SIOCSIFMTU]");
++			printf("Setting MTU failed - trying to survive with "
++			       "current value\n");
++		}
++	}
++#endif
++
++	return 0;
++}
++#endif
++
++static int rtl871x_hostapd_ioctl(struct rtl871x_driver_data *drv, ieee_param *param, int len)
++{
++	struct iwreq iwr;
++
++	memset(&iwr, 0, sizeof(iwr));
++	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
++	iwr.u.data.pointer = (caddr_t) param;
++	iwr.u.data.length = len;
++
++	if (ioctl(drv->ioctl_sock, RTL_IOCTL_HOSTAPD, &iwr) < 0) {
++		perror("ioctl[RTL_IOCTL_HOSTAPD]");
++		return -1;
++	}
++
++	return 0;
++}
++
++static int rtl871x_set_mode(struct rtl871x_driver_data *drv, u32 mode)
++{
++	struct iwreq iwr;
++
++	if (drv->ioctl_sock < 0)
++		return -1;
++
++	memset(&iwr, 0, sizeof(iwr));
++
++	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
++
++	//iwr.u.mode = IW_MODE_MASTER;
++	iwr.u.mode = mode;
++
++	if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
++		perror("ioctl[SIOCSIWMODE]");
++		printf("Could not set interface to mode(%d)!\n", mode);
++		return -1;
++	}
++
++	return 0;
++
++}
++
++/*
++static int rtl871x_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
++			       const u8 *ie, size_t ielen)
++{
++	struct sta_info *sta;
++	int new_assoc, res;
++
++	//hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
++	//	       HOSTAPD_LEVEL_INFO, "associated");
++
++	sta = ap_get_sta(hapd, addr);
++	if (sta) {
++		accounting_sta_stop(hapd, sta);
++	} else {
++		sta = ap_sta_add(hapd, addr);
++		if (sta == NULL)
++		{
++			rtl871x_sta_remove_ops(hapd->drv_priv, addr);
++			return -1;
++		}
++	}
++	sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
++
++	if (hapd->conf->wpa) {
++		if (ie == NULL || ielen == 0) {
++			if (hapd->conf->wps_state) {
++				wpa_printf(MSG_DEBUG, "STA did not include "
++					   "WPA/RSN IE in (Re)Association "
++					   "Request - possible WPS use");
++				sta->flags |= WLAN_STA_MAYBE_WPS;
++				goto skip_wpa_check;
++			}
++
++			wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
++			return -1;
++		}
++		if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
++		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
++			sta->flags |= WLAN_STA_WPS;
++			goto skip_wpa_check;
++		}
++
++		if (sta->wpa_sm == NULL)
++			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
++							sta->addr);
++		if (sta->wpa_sm == NULL) {
++			wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
++				   "machine");
++			return -1;
++		}
++		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
++					  ie, ielen, NULL, 0);
++		if (res != WPA_IE_OK) {
++			wpa_printf(MSG_DEBUG, "WPA/RSN information element "
++				   "rejected? (res %u)", res);
++			wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
++			return -1;
++		}
++	} else if (hapd->conf->wps_state) {
++		if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
++		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
++			sta->flags |= WLAN_STA_WPS;
++		} else
++			sta->flags |= WLAN_STA_MAYBE_WPS;
++	}
++skip_wpa_check:
++
++	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
++	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
++	wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
++
++	hostapd_new_assoc_sta(hapd, sta, !new_assoc);
++
++	ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
++
++	return 0;
++}
++*/
++
++static int rtl871x_get_sta_wpaie(struct rtl871x_driver_data *drv, u8 *iebuf, u8 *addr)
++{
++	struct ieee_param param;
++
++	printf("+%s, " MACSTR " is sta's address\n", __func__, MAC2STR(addr));
++
++	memset(&param, 0, sizeof(param));
++
++	param.cmd = RTL871X_HOSTAPD_GET_WPAIE_STA;
++
++	memcpy(param.sta_addr, addr, ETH_ALEN);
++
++	if (rtl871x_hostapd_ioctl(drv, &param, sizeof(param))) {
++		printf("Could not get sta wpaie from kernel driver.\n");
++		return -1;
++	}
++
++
++	if(param.u.wpa_ie.len > 32)
++		return -1;
++
++	memcpy(iebuf, param.u.wpa_ie.reserved, param.u.wpa_ie.len);
++
++	return 0;
++
++}
++
++static int rtl871x_del_sta(struct rtl871x_driver_data *drv, u8 *addr)
++{
++	struct hostapd_data *hapd = drv->hapd;
++
++#if 1
++
++	//union wpa_event_data event;
++	//os_memset(&event, 0, sizeof(event));
++	//event.disassoc_info.addr = addr;
++	//wpa_supplicant_event(hapd, EVENT_DISASSOC, &event);
++
++	drv_event_disassoc(hapd, addr);
++
++#else
++
++	struct sta_info *sta;
++
++	//hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
++	//	       HOSTAPD_LEVEL_INFO, "disassociated");
++
++	sta = ap_get_sta(hapd, addr);
++	if (sta != NULL)
++	{
++		sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
++		wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
++		sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
++		ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
++		ap_free_sta(hapd, sta);
++	}
++	else
++	{
++		wpa_printf(MSG_DEBUG, "Disassociation notification for "
++			   "unknown STA " MACSTR, MAC2STR(addr));
++	}
++#endif
++
++	return 0;
++
++}
++
++static int rtl871x_new_sta(struct rtl871x_driver_data *drv, u8 *addr)
++{
++	struct hostapd_data *hapd = drv->hapd;
++	//struct ieee80211req_wpaie ie;
++	int ielen = 0, res=0;
++	//u8 *iebuf = NULL;
++	u8 iebuf[32], *piebuf=NULL;
++
++	/*
++	 * Fetch negotiated WPA/RSN parameters from the driver.
++	 */
++	//memset(&ie, 0, sizeof(ie));
++	//memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
++	memset(iebuf, 0 , sizeof(iebuf));
++	if (rtl871x_get_sta_wpaie(drv, iebuf, addr)) {
++	//if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) {
++
++		wpa_printf(MSG_DEBUG, "%s: Failed to get WPA/RSN IE: %s",
++			   __func__, strerror(errno));
++		goto no_ie;
++	}
++
++	//wpa_hexdump(MSG_MSGDUMP, "req WPA IE",
++	//	    ie.wpa_ie, IEEE80211_MAX_OPT_IE);
++
++	//wpa_hexdump(MSG_MSGDUMP, "req RSN IE",
++	//	    ie.rsn_ie, IEEE80211_MAX_OPT_IE);
++
++	//iebuf = ie.wpa_ie;
++
++/*
++	if (iebuf[0] != WLAN_EID_VENDOR_SPECIFIC)
++		iebuf[1] = 0;
++	if (iebuf[1] == 0 && ie.rsn_ie[1] > 0) {
++		iebuf = ie.rsn_ie;
++		if (iebuf[0] != WLAN_EID_RSN)
++			iebuf[1] = 0;
++	}
++*/
++
++	if ((iebuf[0] == WLAN_EID_VENDOR_SPECIFIC) || (iebuf[0] == WLAN_EID_RSN) )
++	{
++		piebuf = iebuf;
++		ielen = iebuf[1];
++
++		if (ielen == 0)
++			piebuf = NULL;
++		else
++			ielen += 2;
++	}
++
++no_ie:
++
++	//res = rtl871x_notif_assoc(hapd, addr, piebuf, ielen);
++	//drv_event_assoc(hapd, addr, piebuf, ielen);
++	drv_event_assoc(hapd, addr, piebuf, ielen, 0);
++
++	if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
++		/* Cached accounting data is not valid anymore. */
++		memset(drv->acct_mac, 0, ETH_ALEN);
++		memset(&drv->acct_data, 0, sizeof(drv->acct_data));
++	}
++
++	return res;
++
++}
++
++static void rtl871x_wireless_event_wireless(struct rtl871x_driver_data *drv,
++					    char *data, int len)
++{
++	struct iw_event iwe_buf, *iwe = &iwe_buf;
++	char *pos, *end, *custom, *buf;
++
++	pos = data;
++	end = data + len;
++
++	while (pos + IW_EV_LCP_LEN <= end) {
++		/* Event data may be unaligned, so make a local, aligned copy
++		 * before processing. */
++		memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
++		wpa_printf(MSG_MSGDUMP, "Wireless event: cmd=0x%x len=%d",
++			   iwe->cmd, iwe->len);
++		if (iwe->len <= IW_EV_LCP_LEN)
++			return;
++
++		custom = pos + IW_EV_POINT_LEN;
++		if (drv->we_version > 18 &&
++		    (iwe->cmd == IWEVMICHAELMICFAILURE ||
++		     iwe->cmd == IWEVCUSTOM)) {
++			/* WE-19 removed the pointer from struct iw_point */
++			char *dpos = (char *) &iwe_buf.u.data.length;
++			int dlen = dpos - (char *) &iwe_buf;
++			memcpy(dpos, pos + IW_EV_LCP_LEN,
++			       sizeof(struct iw_event) - dlen);
++		} else {
++			memcpy(&iwe_buf, pos, sizeof(struct iw_event));
++			custom += IW_EV_POINT_OFF;
++		}
++
++		//printf("got wireless event, iwe->cmd=%d\n", iwe->cmd);
++
++		switch (iwe->cmd) {
++		case IWEVEXPIRED:
++			rtl871x_del_sta(drv, (u8 *)iwe->u.addr.sa_data);
++			break;
++		case IWEVREGISTERED:
++			if(rtl871x_new_sta(drv, (u8 *)iwe->u.addr.sa_data))
++			{
++				printf("Failed to add new sta: "MACSTR" \n", MAC2STR((u8 *)iwe->u.addr.sa_data));
++			}
++			break;
++		case IWEVCUSTOM:
++			if (custom + iwe->u.data.length > end)
++				return;
++			buf = malloc(iwe->u.data.length + 1);
++			if (buf == NULL)
++				return;		/* XXX */
++			memcpy(buf, custom, iwe->u.data.length);
++			buf[iwe->u.data.length] = '\0';
++			//madwifi_wireless_event_wireless_custom(drv, buf);
++			free(buf);
++			break;
++		}
++
++		pos += iwe->len;
++	}
++
++}
++
++#if 1
++static void rtl871x_wireless_event_rtm_newlink(void *ctx,
++				   struct ifinfomsg *ifi, u8 *buf, size_t len)
++{
++	struct rtl871x_driver_data *drv = ctx;
++	int attrlen, rta_len;
++	struct rtattr *attr;
++
++	if (ifi->ifi_index != drv->ifindex)
++		return;
++
++	attrlen = len;
++	attr = (struct rtattr *) buf;
++
++	rta_len = RTA_ALIGN(sizeof(struct rtattr));
++	while (RTA_OK(attr, attrlen)) {
++		if (attr->rta_type == IFLA_WIRELESS) {
++			rtl871x_wireless_event_wireless(
++				drv, ((char *) attr) + rta_len,
++				attr->rta_len - rta_len);
++		}
++		attr = RTA_NEXT(attr, attrlen);
++	}
++}
++
++#else
++static void rtl871x_wireless_event_rtm_newlink(struct rtl871x_driver_data *drv,
++					       struct nlmsghdr *h, int len)
++{
++	struct ifinfomsg *ifi;
++	int attrlen, nlmsg_len, rta_len;
++	struct rtattr * attr;
++
++	if (len < (int) sizeof(*ifi))
++		return;
++
++	ifi = NLMSG_DATA(h);
++
++	if (ifi->ifi_index != drv->ifindex)
++		return;
++
++	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
++
++	attrlen = h->nlmsg_len - nlmsg_len;
++	if (attrlen < 0)
++		return;
++
++	attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
++
++	rta_len = RTA_ALIGN(sizeof(struct rtattr));
++	while (RTA_OK(attr, attrlen)) {
++		if (attr->rta_type == IFLA_WIRELESS) {
++			rtl871x_wireless_event_wireless(
++				drv, ((char *) attr) + rta_len,
++				attr->rta_len - rta_len);
++		}
++		attr = RTA_NEXT(attr, attrlen);
++	}
++}
++#endif
++
++/*
++static void rtl871x_wireless_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
++{
++	char buf[256];//!!!
++	int left;
++	struct sockaddr_nl from;
++	socklen_t fromlen;
++	struct nlmsghdr *h;
++	struct rtl871x_driver_data *drv = eloop_ctx;
++
++	//printf("+rtl871x_wireless_event_receive\n");
++
++	fromlen = sizeof(from);
++	left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
++			(struct sockaddr *) &from, &fromlen);
++	if (left < 0) {
++		if (errno != EINTR && errno != EAGAIN)
++			perror("recvfrom(netlink)");
++		return;
++	}
++
++	h = (struct nlmsghdr *)buf;
++	while (left >= (int) sizeof(*h)) {
++		int len, plen;
++
++		len = h->nlmsg_len;
++		plen = len - sizeof(*h);//payload len
++		if (len > left || plen < 0) {
++			printf("Malformed netlink message: "
++			       "len=%d left=%d plen=%d\n",
++			       len, left, plen);
++			break;
++		}
++
++		switch (h->nlmsg_type) {
++		case RTM_NEWLINK:
++			rtl871x_wireless_event_rtm_newlink(drv, h, plen);
++			break;
++		}
++
++		len = NLMSG_ALIGN(len);
++		left -= len;
++		h = (struct nlmsghdr *) ((char *) h + len);
++	}
++
++	if (left > 0) {
++		printf("%d extra bytes in the end of netlink message\n", left);
++	}
++
++}
++*/
++
++static int rtl871x_wireless_event_init(struct rtl871x_driver_data *drv)
++{
++	struct netlink_config *cfg;
++
++	//madwifi_get_we_version(drv);
++
++	cfg = os_zalloc(sizeof(*cfg));
++	if (cfg == NULL)
++		return -1;
++	cfg->ctx = drv;
++	cfg->newlink_cb = rtl871x_wireless_event_rtm_newlink;
++	drv->netlink = netlink_init(cfg);
++	if (drv->netlink == NULL) {
++		os_free(cfg);
++		return -1;
++	}
++
++	return 0;
++}
++
++/*
++static int rtl871x_wireless_event_init_ops(void *priv)
++{
++	int s;
++	struct sockaddr_nl local;
++	struct rtl871x_driver_data *drv = priv;
++
++	//madwifi_get_we_version(drv);
++
++	drv->wext_sock = -1;
++
++	s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
++	if (s < 0) {
++		perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
++		return -1;
++	}
++
++	memset(&local, 0, sizeof(local));
++	local.nl_family = AF_NETLINK;
++	local.nl_groups = RTMGRP_LINK;
++	if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
++		perror("bind(netlink)");
++		close(s);
++		return -1;
++	}
++
++	eloop_register_read_sock(s, rtl871x_wireless_event_receive, drv, NULL);
++	drv->wext_sock = s;
++
++	return 0;
++
++}
++
++static void rtl871x_wireless_event_deinit_ops(void *priv)
++{
++	struct rtl871x_driver_data *drv = priv;
++
++	if (drv != NULL) {
++		if (drv->wext_sock < 0)
++			return;
++		eloop_unregister_read_sock(drv->wext_sock);
++		close(drv->wext_sock);
++	}
++}
++*/
++
++#if 1
++static void rtl871x_handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
++{
++	struct rtl871x_driver_data *drv = ctx;
++	drv_event_eapol_rx(drv->hapd, src_addr, buf + sizeof(struct l2_ethhdr),
++			   len - sizeof(struct l2_ethhdr));
++}
++#else
++static void rtl871x_handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
++{
++	struct rtl871x_driver_data *drv = ctx;
++	struct hostapd_data *hapd = drv->hapd;
++	struct sta_info *sta;
++
++	sta = ap_get_sta(hapd, src_addr);
++	if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
++		printf("Data frame from not associated STA %s\n",
++		       ether_sprintf(src_addr));
++		/* XXX cannot happen */
++		return;
++	}
++	ieee802_1x_receive(hapd, src_addr, buf + sizeof(struct l2_ethhdr),
++			   len - sizeof(struct l2_ethhdr));
++}
++#endif
++
++static int rtl871x_send_eapol_ops(void *priv, const u8 *addr, const u8 *data, size_t data_len,
++		   int encrypt, const u8 *own_addr, u32 flags)
++{
++	struct rtl871x_driver_data *drv = priv;
++	unsigned char buf[3000];
++	unsigned char *bp = buf;
++	struct l2_ethhdr *eth;
++	size_t len;
++	int status;
++
++	printf("+rtl871x_send_eapol\n");
++
++	/*
++	 * Prepend the Ethernet header.  If the caller left us
++	 * space at the front we could just insert it but since
++	 * we don't know we copy to a local buffer.  Given the frequency
++	 * and size of frames this probably doesn't matter.
++	 */
++	len = data_len + sizeof(struct l2_ethhdr);
++	if (len > sizeof(buf)) {
++		bp = malloc(len);
++		if (bp == NULL) {
++			printf("EAPOL frame discarded, cannot malloc temp "
++			       "buffer of size %lu!\n", (unsigned long) len);
++			return -1;
++		}
++	}
++
++	eth = (struct l2_ethhdr *) bp;
++	memcpy(eth->h_dest, addr, ETH_ALEN);
++	memcpy(eth->h_source, own_addr, ETH_ALEN);
++	eth->h_proto = htons(ETH_P_EAPOL);
++	memcpy(eth+1, data, data_len);
++
++	wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
++
++	status = l2_packet_send(drv->l2_sock, addr, ETH_P_EAPOL, bp, len);
++
++	if (bp != buf)
++		free(bp);
++
++	return status;
++
++}
++
++#ifndef CONFIG_MLME_OFFLOAD
++static void rtl871x_receive_mgnt(struct rtl871x_driver_data *drv , const u8 *buf, size_t len)
++{
++	const struct ieee80211_mgmt *mgmt;
++	//const u8 *end, *ie;
++	u16 fc, type, stype;
++	//size_t ie_len;
++	struct hostapd_data *hapd = drv->hapd;
++
++	//printf("+rtl871x_receive_mgnt, " MACSTR " is our address\n", MAC2STR(hapd->own_addr));
++
++
++#if 0
++	{
++		int i;
++		for(i=0; i<len; i+=8)
++		{
++			printf("%x:%x:%x:%x:%x:%x:%x:%x\n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
++		}
++
++	}
++#endif
++
++	if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
++		return;
++
++	mgmt = (const struct ieee80211_mgmt *)buf;
++
++	fc = le_to_host16(mgmt->frame_control);
++	type = WLAN_FC_GET_TYPE(fc);
++	stype = WLAN_FC_GET_STYPE(fc);
++
++#if 1
++	if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
++	    WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP)
++	{
++		//printf("MGNT Frame - PROBE_RESP Frame\n");
++	}
++#endif
++
++	//end = buf + len;
++	//ie = mgmt->u.probe_req.variable;
++	//ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
++	//hostapd_wps_probe_req_rx(drv->hapd, mgmt->sa, ie, ie_len);
++
++	switch (type) {
++	case WLAN_FC_TYPE_MGMT:
++		if (stype != WLAN_FC_STYPE_BEACON)
++			wpa_printf(MSG_MSGDUMP, "MGMT");
++
++
++
++		if (stype == WLAN_FC_STYPE_PROBE_REQ)
++		{
++
++		}
++		else
++		{
++			//printf("rtl871x_receive_mgnt, type=0x%x, stype=0x%x\n", type, stype);
++		}
++
++
++		//ieee802_11_mgmt(hapd, (u8 *)buf, len, stype, NULL);
++
++		break;
++	case WLAN_FC_TYPE_CTRL:
++		printf("rtl871x_receive_mgnt, CTRL\n");
++		break;
++	case WLAN_FC_TYPE_DATA:
++		printf("rtl871x_receive_mgnt, DATA\n");
++		//handle_data(hapd, buf, data_len, stype);
++		break;
++	default:
++		printf("unknown frame type %d\n", type);
++		break;
++	}
++
++
++}
++
++#ifdef CONFIG_MGNT_L2SOCK
++static void rtl871x_recvive_mgmt_frame(void *ctx, const u8 *src_addr, const u8 *buf,
++				size_t len)
++{
++	struct rtl871x_driver_data *drv = ctx;
++
++	rtl871x_receive_mgnt(drv, buf, len);
++}
++#else
++static void rtl871x_recvive_mgmt_frame(int sock, void *eloop_ctx, void *sock_ctx)
++{
++#if 0
++	int len;
++	unsigned char buf[1024];
++	struct hostapd_data *hapd = (struct hostapd_data *)eloop_ctx;
++	struct rtl871x_driver_data *drv = (struct rtl871x_driver_data *)hapd->drv_priv;
++
++	len = recv(sock, buf, sizeof(buf), 0);
++	if (len < 0) {
++		perror("recv");
++		return;
++	}
++
++	rtl871x_receive_mgnt(drv, buf, len);
++#endif
++}
++
++static int rtl871x_mgnt_sock_init(struct rtl871x_driver_data *drv, const char *name)
++{
++	int sock;
++	struct ifreq ifr;
++	struct sockaddr_ll addr;
++
++	sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
++	if (sock < 0) {
++		perror("socket[PF_PACKET,SOCK_RAW]");
++		return -1;
++	}
++
++	if (eloop_register_read_sock(sock, rtl871x_recvive_mgmt_frame, drv->hapd, NULL))
++	{
++		printf("Could not register read socket\n");
++		return -1;
++	}
++
++	memset(&ifr, 0, sizeof(ifr));
++	//snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface);
++	os_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
++        if (ioctl(sock, SIOCGIFINDEX, &ifr) != 0) {
++		perror("ioctl(SIOCGIFINDEX)");
++		return -1;
++        }
++
++	//if (rtl871x_set_iface_flags(drv, 1)) {
++	//	return -1;
++	//}
++
++	memset(&addr, 0, sizeof(addr));
++	addr.sll_family = AF_PACKET;
++	addr.sll_ifindex = ifr.ifr_ifindex;
++	wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
++		   addr.sll_ifindex);
++
++	if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
++		perror("bind");
++		return -1;
++	}
++
++        memset(&ifr, 0, sizeof(ifr));
++        os_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
++        if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) {
++		perror("ioctl(SIOCGIFHWADDR)");
++		return -1;
++        }
++
++
++	if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
++		printf("Invalid HW-addr family 0x%04x\n",
++		       ifr.ifr_hwaddr.sa_family);
++		return -1;
++	}
++
++	//memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
++
++	return sock;
++
++}
++#endif
++#endif
++
++static void rtl871x_handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
++			       int ok)
++{
++#if 0
++	struct ieee80211_hdr *hdr;
++	u16 fc, type, stype;
++	struct sta_info *sta;
++
++	//printf("%s\n", __func__);
++
++	hdr = (struct ieee80211_hdr *) buf;
++	fc = le_to_host16(hdr->frame_control);
++
++	type = WLAN_FC_GET_TYPE(fc);
++	stype = WLAN_FC_GET_STYPE(fc);
++
++	switch (type) {
++	case WLAN_FC_TYPE_MGMT:
++		//printf("MGMT (TX callback) %s\n",
++		//	   ok ? "ACK" : "fail");
++		ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
++		break;
++	case WLAN_FC_TYPE_CTRL:
++		printf("CTRL (TX callback) %s\n",
++			   ok ? "ACK" : "fail");
++		break;
++	case WLAN_FC_TYPE_DATA:
++		printf("DATA (TX callback) %s\n",
++			   ok ? "ACK" : "fail");
++		sta = ap_get_sta(hapd, hdr->addr1);
++		if (sta && sta->flags & WLAN_STA_PENDING_POLL) {
++			wpa_printf(MSG_DEBUG, "STA " MACSTR
++				   " %s pending activity poll",
++				   MAC2STR(sta->addr),
++				   ok ? "ACKed" : "did not ACK");
++			if (ok)
++				sta->flags &= ~WLAN_STA_PENDING_POLL;
++		}
++		if (sta)
++			ieee802_1x_tx_status(hapd, sta, buf, len, ok);
++		break;
++	default:
++		printf("unknown TX callback frame type %d\n", type);
++		break;
++	}
++#endif
++}
++
++static int rtl871x_send_mgnt(struct rtl871x_driver_data *drv, const void *msg, size_t len)
++{
++	int res=0;
++
++	return res;
++}
++
++static int rtl871x_send_mgmt_frame_ops(void *priv, const void *msg, size_t len,
++				  int flags)
++{
++	struct rtl871x_driver_data *drv = priv;
++	//struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msg;
++	int res=0;
++
++	//printf("%s\n", __func__);
++
++
++	//hdr->frame_control |= host_to_le16(BIT(1));/* Request TX callback */
++#ifdef CONFIG_MGNT_L2SOCK
++	//res = send(drv->mgnt_l2_sock, msg, len, flags);
++	//res = l2_packet_send(drv->mgnt_l2_sock, addr, ETH_P_EAPOL, msg, len);
++	if(drv->mgnt_l2_sock == NULL)
++		return res;
++
++	res = l2_packet_send(drv->mgnt_l2_sock, NULL, ETH_P_80211_RAW, msg, len);
++#else
++
++	if(drv->mgnt_sock < 0)
++		return res;
++
++	res = send(drv->mgnt_sock, msg, len, flags);
++#endif
++	//hdr->frame_control &= ~host_to_le16(BIT(1));
++
++
++	rtl871x_send_mgnt(drv, msg, len);
++
++	rtl871x_handle_tx_callback(drv->hapd, (u8*)msg, len, 1);
++
++	return res;
++
++}
++
++/*
++static int rtl871x_driver_send_ether_ops(void *priv, const u8 *dst, const u8 *src,
++				  u16 proto, const u8 *data, size_t data_len)
++{
++	return 0;
++}
++*/
++
++static struct hostapd_hw_modes *rtl871x_get_hw_feature_data_ops(void *priv,
++							    u16 *num_modes,
++							    u16 *flags)
++{
++
++#define MAX_NUM_CHANNEL (14)
++#define MAX_NUM_CHANNEL_5G (24)
++
++	struct hostapd_hw_modes *modes;
++	size_t i;
++        int k;
++
++	*num_modes = 3;
++	*flags = 0;
++
++	modes = os_zalloc(*num_modes * sizeof(struct hostapd_hw_modes));
++	if (modes == NULL)
++		return NULL;
++
++	//.1
++	modes[0].mode = HOSTAPD_MODE_IEEE80211G;
++	modes[0].num_channels = MAX_NUM_CHANNEL;
++	modes[0].num_rates = 12;
++	modes[0].channels =
++		os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
++	modes[0].rates = os_zalloc(modes[0].num_rates * sizeof(int));
++	if (modes[0].channels == NULL || modes[0].rates == NULL)
++		goto fail;
++	for (i = 0; i < MAX_NUM_CHANNEL; i++) {
++		modes[0].channels[i].chan = i + 1;
++		modes[0].channels[i].freq = 2412 + 5 * i;
++		modes[0].channels[i].flag = 0;
++		if (i >= 13)
++			modes[0].channels[i].flag = HOSTAPD_CHAN_DISABLED;
++	}
++	modes[0].rates[0] = 10;
++	modes[0].rates[1] = 20;
++	modes[0].rates[2] = 55;
++	modes[0].rates[3] = 110;
++	modes[0].rates[4] = 60;
++	modes[0].rates[5] = 90;
++	modes[0].rates[6] = 120;
++	modes[0].rates[7] = 180;
++	modes[0].rates[8] = 240;
++	modes[0].rates[9] = 360;
++	modes[0].rates[10] = 480;
++	modes[0].rates[11] = 540;
++
++
++	//.2
++	modes[1].mode = HOSTAPD_MODE_IEEE80211B;
++	modes[1].num_channels = MAX_NUM_CHANNEL;
++	modes[1].num_rates = 4;
++	modes[1].channels =
++		os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
++	modes[1].rates = os_zalloc(modes[1].num_rates * sizeof(int));
++	if (modes[1].channels == NULL || modes[1].rates == NULL)
++		goto fail;
++	for (i = 0; i < MAX_NUM_CHANNEL; i++) {
++		modes[1].channels[i].chan = i + 1;
++		modes[1].channels[i].freq = 2412 + 5 * i;
++		modes[1].channels[i].flag = 0;
++		if (i >= 11)
++			modes[1].channels[i].flag = HOSTAPD_CHAN_DISABLED;
++	}
++	modes[1].rates[0] = 10;
++	modes[1].rates[1] = 20;
++	modes[1].rates[2] = 55;
++	modes[1].rates[3] = 110;
++
++
++	//.3
++	modes[2].mode = HOSTAPD_MODE_IEEE80211A;
++#ifdef CONFIG_DRIVER_RTL_DFS
++	modes[2].num_channels = MAX_NUM_CHANNEL_5G;
++#else /* CONFIG_DRIVER_RTL_DFS */
++	modes[2].num_channels = 9;
++#endif /* CONFIG_DRIVER_RTL_DFS */
++
++	modes[2].num_rates = 8;
++	modes[2].channels = os_zalloc(modes[2].num_channels * sizeof(struct hostapd_channel_data));
++	modes[2].rates = os_zalloc(modes[2].num_rates * sizeof(int));
++	if (modes[2].channels == NULL || modes[2].rates == NULL)
++		goto fail;
++
++
++	k = 0;
++	// 5G band1 Channel: 36, 40, 44, 48
++	for (i=0; i < 4; i++) {
++		modes[2].channels[k].chan = 36+(i*4);
++		modes[2].channels[k].freq = 5180+(i*20);
++		modes[2].channels[k].flag = 0;
++		k++;
++	}
++
++#ifdef CONFIG_DRIVER_RTL_DFS
++	// 5G band2 Channel: 52, 56, 60, 64
++	for (i=0; i < 4; i++) {
++		modes[2].channels[k].chan = 52+(i*4);
++		modes[2].channels[k].freq = 5260+(i*20);
++		modes[2].channels[k].flag = 0;
++		k++;
++	}
++
++	// 5G band3 Channel: 100, 104, 108. 112, 116, 120, 124, 128, 132, 136, 140
++	for (i=0; i < 11; i++) {
++		modes[2].channels[k].chan = 100+(i*4);
++		modes[2].channels[k].freq = 5500+(i*20);
++		modes[2].channels[k].flag = 0;
++		k++;
++	}
++#endif /* CONFIG_DRIVER_RTL_DFS */
++
++	// 5G band4 Channel: 149, 153, 157, 161, 165
++	for (i=0; i < 5; i++) {
++		modes[2].channels[k].chan = 149+(i*4);
++		modes[2].channels[k].freq = 5745+(i*20);
++		modes[2].channels[k].flag = 0;
++		k++;
++	}
++
++	modes[2].rates[0] = 60;
++	modes[2].rates[1] = 90;
++	modes[2].rates[2] = 120;
++	modes[2].rates[3] = 180;
++	modes[2].rates[4] = 240;
++	modes[2].rates[5] = 360;
++	modes[2].rates[6] = 480;
++	modes[2].rates[7] = 540;
++
++
++	//
++#if 0
++#define HT_CAP_INFO_LDPC_CODING_CAP		((u16) BIT(0))
++#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET	((u16) BIT(1))
++#define HT_CAP_INFO_SMPS_MASK			((u16) (BIT(2) | BIT(3)))
++#define HT_CAP_INFO_SMPS_STATIC			((u16) 0)
++#define HT_CAP_INFO_SMPS_DYNAMIC		((u16) BIT(2))
++#define HT_CAP_INFO_SMPS_DISABLED		((u16) (BIT(2) | BIT(3)))
++#define HT_CAP_INFO_GREEN_FIELD			((u16) BIT(4))
++#define HT_CAP_INFO_SHORT_GI20MHZ		((u16) BIT(5))
++#define HT_CAP_INFO_SHORT_GI40MHZ		((u16) BIT(6))
++#define HT_CAP_INFO_TX_STBC			((u16) BIT(7))
++#define HT_CAP_INFO_RX_STBC_MASK		((u16) (BIT(8) | BIT(9)))
++#define HT_CAP_INFO_RX_STBC_1			((u16) BIT(8))
++#define HT_CAP_INFO_RX_STBC_12			((u16) BIT(9))
++#define HT_CAP_INFO_RX_STBC_123			((u16) (BIT(8) | BIT(9)))
++#define HT_CAP_INFO_DELAYED_BA			((u16) BIT(10))
++#define HT_CAP_INFO_MAX_AMSDU_SIZE		((u16) BIT(11))
++#define HT_CAP_INFO_DSSS_CCK40MHZ		((u16) BIT(12))
++#define HT_CAP_INFO_PSMP_SUPP			((u16) BIT(13))
++#define HT_CAP_INFO_40MHZ_INTOLERANT		((u16) BIT(14))
++#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT	((u16) BIT(15))
++#endif
++
++	//HOSTAPD_MODE_IEEE80211G
++	modes[0].ht_capab = HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET|HT_CAP_INFO_SHORT_GI20MHZ|
++			HT_CAP_INFO_SHORT_GI40MHZ|HT_CAP_INFO_MAX_AMSDU_SIZE|HT_CAP_INFO_DSSS_CCK40MHZ;
++
++	modes[0].mcs_set[0]= 0xff;
++	modes[0].mcs_set[1]= 0xff;
++
++	//HOSTAPD_MODE_IEEE80211B
++	modes[1].ht_capab = 0;
++
++	//HOSTAPD_MODE_IEEE80211A
++	modes[2].ht_capab = modes[0].ht_capab;
++
++	modes[2].mcs_set[0]= 0xff;
++	modes[2].mcs_set[1]= 0xff;
++
++	return modes;
++
++fail:
++	if (modes) {
++		for (i = 0; i < *num_modes; i++) {
++			os_free(modes[i].channels);
++			os_free(modes[i].rates);
++		}
++		os_free(modes);
++	}
++
++	return NULL;
++
++}
++
++#if 0
++static int rtl871x_sta_add_ops(const char *ifname, void *priv, const u8 *addr,
++			  u16 aid, u16 capability, u8 *supp_rates,
++			  size_t supp_rates_len, int flags,
++			  u16 listen_interval)
++{
++
++#if 1
++	printf("+%s, " MACSTR " is new sta address added\n", __func__, MAC2STR(addr));
++	return 0;
++#else
++	struct hostap_driver_data *drv = priv;
++	struct prism2_hostapd_param param;
++	int tx_supp_rates = 0;
++	size_t i;
++
++#define WLAN_RATE_1M BIT(0)
++#define WLAN_RATE_2M BIT(1)
++#define WLAN_RATE_5M5 BIT(2)
++#define WLAN_RATE_11M BIT(3)
++
++	for (i = 0; i < supp_rates_len; i++) {
++		if ((supp_rates[i] & 0x7f) == 2)
++			tx_supp_rates |= WLAN_RATE_1M;
++		if ((supp_rates[i] & 0x7f) == 4)
++			tx_supp_rates |= WLAN_RATE_2M;
++		if ((supp_rates[i] & 0x7f) == 11)
++			tx_supp_rates |= WLAN_RATE_5M5;
++		if ((supp_rates[i] & 0x7f) == 22)
++			tx_supp_rates |= WLAN_RATE_11M;
++	}
++
++	memset(&param, 0, sizeof(param));
++	param.cmd = PRISM2_HOSTAPD_ADD_STA;
++	memcpy(param.sta_addr, addr, ETH_ALEN);
++	param.u.add_sta.aid = aid;
++	param.u.add_sta.capability = capability;
++	param.u.add_sta.tx_supp_rates = tx_supp_rates;
++	return hostapd_ioctl(drv, &param, sizeof(param));
++#endif
++}
++
++static int rtl871x_sta_add2_ops(const char *ifname, void *priv,
++			 struct hostapd_sta_add_params *params)
++{
++#if 0
++	ieee_param param;
++	//int i, tx_supp_rates = 0;
++	struct rtl871x_driver_data *drv = priv;
++
++	printf("%s\n", __func__);
++
++	memset(&param, 0, sizeof(param));
++	param.cmd = RTL871X_HOSTAPD_ADD_STA;
++	memcpy(param.sta_addr, params->addr, ETH_ALEN);
++	param.u.add_sta.aid = params->aid;
++	param.u.add_sta.capability = params->capability;
++	param.u.add_sta.flags = params->flags;
++
++	memcpy(param.u.add_sta.tx_supp_rates, params->supp_rates, params->supp_rates_len);
++
++/*
++	for (i = 0; i < params->supp_rates_len; i++)
++	{
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_1MB)
++			tx_supp_rates |= IEEE80211_CCK_RATE_1MB_MASK;
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_2MB)
++			tx_supp_rates |= IEEE80211_CCK_RATE_2MB_MASK;
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_5MB)
++			tx_supp_rates |= IEEE80211_CCK_RATE_5MB_MASK;
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_11MB)
++			tx_supp_rates |= IEEE80211_CCK_RATE_11MB_MASK;
++
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_6MB)
++			tx_supp_rates |= IEEE80211_OFDM_RATE_6MB_MASK;
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_9MB)
++			tx_supp_rates |= IEEE80211_OFDM_RATE_9MB_MASK;
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_12MB)
++			tx_supp_rates |= IEEE80211_OFDM_RATE_12MB_MASK;
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_18MB)
++			tx_supp_rates |= IEEE80211_OFDM_RATE_18MB_MASK;
++
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_24MB)
++			tx_supp_rates |= IEEE80211_OFDM_RATE_24MB_MASK;
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_36MB)
++			tx_supp_rates |= IEEE80211_OFDM_RATE_36MB_MASK;
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_48MB)
++			tx_supp_rates |= IEEE80211_OFDM_RATE_48MB_MASK;
++		if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_54MB)
++			tx_supp_rates |= IEEE80211_OFDM_RATE_54MB_MASK;
++
++	}
++
++	param.u.add_sta.tx_supp_rates = tx_supp_rates;
++*/
++
++#ifdef CONFIG_IEEE80211N
++	if (params->ht_capabilities && params->ht_capabilities->length>0)
++	{
++		struct ieee80211_ht_capability *pht_cap = (struct ieee80211_ht_capability *)&params->ht_capabilities->data;
++		memcpy((u8*)&param.u.add_sta.ht_cap, (u8*)pht_cap, sizeof(struct ieee80211_ht_capability));
++
++	}
++#endif /* CONFIG_IEEE80211N */
++
++	return rtl871x_hostapd_ioctl(drv, &param, sizeof(param));
++#else
++	return 0;
++#endif
++}
++#endif
++
++static int rtl871x_sta_remove_ops(void *priv, const u8 *addr)
++{
++	struct rtl871x_driver_data *drv = priv;
++	struct ieee_param param;
++
++	printf("+%s, " MACSTR " is sta address removed\n", __func__, MAC2STR(addr));
++
++	//hostap_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED);
++
++	memset(&param, 0, sizeof(param));
++	param.cmd = RTL871X_HOSTAPD_REMOVE_STA;
++	memcpy(param.sta_addr, addr, ETH_ALEN);
++	if (rtl871x_hostapd_ioctl(drv, &param, sizeof(param))) {
++		printf("Could not remove station from kernel driver.\n");
++		return -1;
++	}
++
++	return 0;
++
++}
++
++#define RTL871X_HIDDEN_SSID_SUPPORT
++#ifdef RTL871X_HIDDEN_SSID_SUPPORT
++static int rtl871x_set_hidden_ssid_ops(const char *iface, void *priv, u8 value)
++{
++	int ret;
++	ieee_param pparam;
++	struct rtl871x_driver_data *drv = priv;
++
++	printf("%s\n", __func__);
++
++	pparam.cmd = RTL871X_HOSTAPD_SET_HIDDEN_SSID;
++	pparam.u.wpa_param.name = 0;
++	pparam.u.wpa_param.value = value;
++
++	ret = rtl871x_hostapd_ioctl(drv, &pparam, sizeof(ieee_param));
++
++	return ret;
++}
++#endif //RTL871X_HIDDEN_SSID_SUPPORT
++
++static int rtl871x_set_beacon_ops(void *priv, struct wpa_driver_ap_params *params)
++{
++	int ret;
++	size_t sz;
++	ieee_param *pparam;
++	struct rtl871x_driver_data *drv = priv;
++	struct hostapd_data *hapd = drv->hapd;
++
++	u8 *ssid_ie;
++	u8 ssid_len;
++	u8 expend_len = 0;
++
++	if((params->head_len<24) ||(!params->head))
++		return -1;
++
++	printf("%s\n", __func__);
++
++
++#ifdef RTL871X_HIDDEN_SSID_SUPPORT
++	rtl871x_set_hidden_ssid_ops(drv->iface, priv, hapd->conf->ignore_broadcast_ssid);
++
++	ssid_ie = (u8 *)get_ie((params->head+24+12), (params->head_len-24-12), WLAN_EID_SSID);
++
++	if(hapd->conf->ignore_broadcast_ssid == 2)
++	{
++		ssid_len = ssid_ie[1];
++
++		//confirm the ssid_len
++		if(ssid_len != hapd->conf->ssid.ssid_len)
++		{
++			printf("%s ssid_len(%u) != hapd->conf->ssid.ssid_len(%u)!!\n", __func__
++				, ssid_len, hapd->conf->ssid.ssid_len
++			);
++		}
++
++		memcpy(ssid_ie+2, hapd->conf->ssid.ssid, ssid_len);
++	}
++	else if(hapd->conf->ignore_broadcast_ssid == 1)
++	{
++		expend_len = hapd->conf->ssid.ssid_len;
++		printf("%s ignore_broadcast_ssid:%d, %s,%u, expend_len:%u\n", __func__
++			, hapd->conf->ignore_broadcast_ssid
++			, hapd->conf->ssid.ssid
++			, hapd->conf->ssid.ssid_len
++			, expend_len
++		);
++	}
++#endif //RTL871X_HIDDEN_SSID_SUPPORT
++
++	sz = params->head_len+params->tail_len+12-24 + 2 + expend_len;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
++	pparam = os_zalloc(sz);
++	if (pparam == NULL) {
++		return -ENOMEM;
++	}
++
++	pparam->cmd = RTL871X_HOSTAPD_SET_BEACON;
++
++	memcpy(pparam->u.bcn_ie.reserved, &hapd->conf->max_num_sta, 2);//for set max_num_sta
++
++#ifdef RTL871X_HIDDEN_SSID_SUPPORT
++	if(hapd->conf->ignore_broadcast_ssid == 1)
++	{
++		u8 *ssid_ie_next = params->head+24+12+2;
++		size_t head_remain_len = params->head_len-24-12-2;
++
++		memcpy(pparam->u.bcn_ie.buf, (params->head+24), 12);
++
++		pparam->u.bcn_ie.buf[12] = WLAN_EID_SSID;
++		pparam->u.bcn_ie.buf[13] = expend_len;
++		memcpy(pparam->u.bcn_ie.buf+12+2, hapd->conf->ssid.ssid, expend_len);
++
++		memcpy(pparam->u.bcn_ie.buf+12+2+expend_len, ssid_ie_next, head_remain_len);// 24=beacon header len.
++		memcpy(&pparam->u.bcn_ie.buf[params->head_len-24+expend_len], params->tail, params->tail_len);
++	}
++	else
++#endif //RTL871X_HIDDEN_SSID_SUPPORT
++	{
++		memcpy(pparam->u.bcn_ie.buf, (params->head+24), (params->head_len-24));// 24=beacon header len.
++		memcpy(&pparam->u.bcn_ie.buf[params->head_len-24], params->tail, params->tail_len);
++	}
++
++	ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
++
++	os_free(pparam);
++
++	//rtl871x_set_max_num_sta(drv);
++
++	return ret;
++
++}
++
++/*
++enum wpa_alg {
++	WPA_ALG_NONE,
++	WPA_ALG_WEP,
++	WPA_ALG_TKIP,
++	WPA_ALG_CCMP,
++	WPA_ALG_IGTK,
++	WPA_ALG_PMK
++};
++*/
++static int rtl871x_set_key_ops(const char *ifname, void *priv, enum wpa_alg alg,
++		const u8 *addr, int idx, int txkey, const u8 *seq,
++		size_t seq_len, const u8 *key, size_t key_len)
++{
++	ieee_param *param;
++	u8 *buf;
++	char *alg_str;
++	size_t blen;
++	int ret = 0;
++	struct rtl871x_driver_data *drv = priv;
++
++	printf("%s\n", __func__);
++
++	blen = sizeof(*param) + key_len;
++	buf = os_zalloc(blen);
++	if (buf == NULL)
++		return -1;
++
++	param = (ieee_param *)buf;
++	param->cmd = RTL871X_SET_ENCRYPTION;
++	if (addr == NULL)
++		memset(param->sta_addr, 0xff, ETH_ALEN);
++	else
++		memcpy(param->sta_addr, addr, ETH_ALEN);
++
++
++	switch (alg) {
++	case WPA_ALG_NONE:
++		alg_str = "none";
++		break;
++	case WPA_ALG_WEP:
++		//cipher = IEEE80211_CIPHER_WEP;
++		alg_str = "WEP";
++		break;
++	case WPA_ALG_TKIP:
++		//cipher = IEEE80211_CIPHER_TKIP;
++		alg_str = "TKIP";
++		break;
++	case WPA_ALG_CCMP:
++		//cipher = IEEE80211_CIPHER_AES_CCM;
++		alg_str = "CCMP";
++		break;
++	default:
++		printf("%s: unknown/unsupported algorithm %d\n",
++			__func__, alg);
++		return -1;
++	}
++
++	os_strlcpy((char *) param->u.crypt.alg, alg_str,
++		   IEEE_CRYPT_ALG_NAME_LEN);
++
++	//param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
++	param->u.crypt.set_tx = txkey ? 1 : 0;
++	param->u.crypt.idx = idx;
++	param->u.crypt.key_len = key_len;
++
++	//memcpy((u8 *) (param + 1), key, key_len);
++	memcpy(param->u.crypt.key, key, key_len);
++
++	if (rtl871x_hostapd_ioctl(drv, param, blen)) {
++		printf("Failed to set encryption.\n");
++		ret = -1;
++	}
++
++	os_free(buf);
++
++	return ret;
++
++}
++
++/*
++static int rtl871x_set_encryption_ops(const char *ifname, void *priv,
++				 const char *alg, const u8 *addr,
++				 int idx, const u8 *key, size_t key_len,
++				 int txkey)
++{
++	ieee_param *param;
++	u8 *buf;
++	size_t blen;
++	int ret = 0;
++	struct rtl871x_driver_data *drv = priv;
++
++	printf("%s\n", __func__);
++#if 0
++	blen = sizeof(*param) + key_len;
++	buf = os_zalloc(blen);
++	if (buf == NULL)
++		return -1;
++
++	param = (ieee_param *)buf;
++	param->cmd = RTL871X_SET_ENCRYPTION;
++	if (addr == NULL)
++		memset(param->sta_addr, 0xff, ETH_ALEN);
++	else
++		memcpy(param->sta_addr, addr, ETH_ALEN);
++
++	os_strlcpy((char *) param->u.crypt.alg, alg,
++		   IEEE_CRYPT_ALG_NAME_LEN);
++
++	//param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
++	param->u.crypt.set_tx = txkey ? 1 : 0;
++	param->u.crypt.idx = idx;
++	param->u.crypt.key_len = key_len;
++
++	//memcpy((u8 *) (param + 1), key, key_len);
++	memcpy(param->u.crypt.key, key, key_len);
++
++	if (rtl871x_hostapd_ioctl(drv, param, blen)) {
++		printf("Failed to set encryption.\n");
++		ret = -1;
++	}
++
++	os_free(buf);
++#endif
++	return ret;
++
++}
++*/
++
++//static int rtl871x_sta_deauth_ops(void *priv, const u8 *addr, int reason)
++static int rtl871x_sta_deauth_ops(void *priv, const u8 *own_addr, const u8 *addr,
++		   int reason)
++{
++	printf("+%s, " MACSTR " is deauth, reason=%d\n", __func__, MAC2STR(addr), reason);
++
++	//struct hostap_driver_data *drv = priv;
++	struct rtl871x_driver_data *drv = priv;
++	struct ieee80211_mgmt mgmt;
++
++	memset(&mgmt, 0, sizeof(mgmt));
++	mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
++					  WLAN_FC_STYPE_DEAUTH);
++
++	memcpy(mgmt.da, addr, ETH_ALEN);
++	//memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
++	//memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
++	memcpy(mgmt.sa, own_addr, ETH_ALEN);
++	memcpy(mgmt.bssid, own_addr, ETH_ALEN);
++	mgmt.u.deauth.reason_code = host_to_le16(reason);
++
++	return rtl871x_send_mgmt_frame_ops(drv, &mgmt, IEEE80211_HDRLEN +
++				      sizeof(mgmt.u.deauth), 0);
++
++}
++
++
++//static int rtl871x_sta_disassoc_ops(void *priv, const u8 *addr, int reason)
++static int rtl871x_sta_disassoc_ops(void *priv, const u8 *own_addr, const u8 *addr,
++		     int reason)
++{
++	printf("+%s, " MACSTR " is disassoc, reason=%d\n", __func__, MAC2STR(addr), reason);
++
++	struct rtl871x_driver_data *drv = priv;
++	struct ieee80211_mgmt mgmt;
++
++	memset(&mgmt, 0, sizeof(mgmt));
++	mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
++					  WLAN_FC_STYPE_DISASSOC);
++
++	memcpy(mgmt.da, addr, ETH_ALEN);
++	//memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
++	//memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
++	memcpy(mgmt.sa, own_addr, ETH_ALEN);
++	memcpy(mgmt.bssid, own_addr, ETH_ALEN);
++
++	mgmt.u.disassoc.reason_code = host_to_le16(reason);
++
++	return  rtl871x_send_mgmt_frame_ops(drv, &mgmt, IEEE80211_HDRLEN +
++				       sizeof(mgmt.u.disassoc), 0);
++
++}
++
++static int rtl871x_set_wps_assoc_resp_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len)
++{
++	int ret;
++	size_t sz;
++	ieee_param *pparam;
++
++
++	printf("%s\n", __func__);
++
++	sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
++	pparam = os_zalloc(sz);
++	if (pparam == NULL) {
++		return -ENOMEM;
++	}
++
++	pparam->cmd = RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP;
++
++	if(ie && len>0)
++	{
++		memcpy(pparam->u.bcn_ie.buf, ie, len);
++	}
++
++	ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
++
++	os_free(pparam);
++
++	return ret;
++
++}
++
++static int rtl871x_set_wps_beacon_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len)
++{
++	int ret;
++	size_t sz;
++	ieee_param *pparam;
++
++
++	printf("%s\n", __func__);
++
++	sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
++	pparam = os_zalloc(sz);
++	if (pparam == NULL) {
++		return -ENOMEM;
++	}
++
++	pparam->cmd = RTL871X_HOSTAPD_SET_WPS_BEACON;
++
++	if(ie && len>0)
++	{
++		memcpy(pparam->u.bcn_ie.buf, ie, len);
++	}
++
++	ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
++
++	os_free(pparam);
++
++	return ret;
++
++}
++
++static int rtl871x_set_wps_probe_resp_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len)
++{
++	int ret;
++	size_t sz;
++	ieee_param *pparam;
++
++
++	printf("%s\n", __func__);
++
++	sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
++	pparam = os_zalloc(sz);
++	if (pparam == NULL) {
++		return -ENOMEM;
++	}
++
++	pparam->cmd = RTL871X_HOSTAPD_SET_WPS_PROBE_RESP;
++
++	if(ie && len>0)
++	{
++		memcpy(pparam->u.bcn_ie.buf, ie, len);
++	}
++
++	ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
++
++	os_free(pparam);
++
++	return ret;
++
++}
++
++static int rtl871x_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
++		      const struct wpabuf *proberesp, const struct wpabuf *assocresp)
++{
++	struct rtl871x_driver_data *drv = priv;
++
++	if (rtl871x_set_wps_assoc_resp_ie(drv, assocresp ? wpabuf_head(assocresp) : NULL,
++			       assocresp ? wpabuf_len(assocresp) : 0))
++		return -1;
++
++	if (rtl871x_set_wps_beacon_ie(drv, beacon ? wpabuf_head(beacon) : NULL,
++			       beacon ? wpabuf_len(beacon) : 0))
++		return -1;
++
++	return rtl871x_set_wps_probe_resp_ie(drv,
++				  proberesp ? wpabuf_head(proberesp) : NULL,
++				  proberesp ? wpabuf_len(proberesp): 0);
++
++}
++
++static int rtl871x_sta_flush_ops(void *priv)
++{
++	ieee_param param;
++	struct rtl871x_driver_data *drv = priv;
++
++	memset(&param, 0, sizeof(param));
++
++	param.cmd = RTL871X_HOSTAPD_FLUSH;
++
++	return rtl871x_hostapd_ioctl(drv, &param, sizeof(param));
++}
++
++static void *rtl871x_driver_init_ops(struct hostapd_data *hapd, struct wpa_init_params *params)
++{
++	struct rtl871x_driver_data *drv;
++	struct ifreq ifr;
++	//struct iwreq iwr;
++	char	ifrn_name[IFNAMSIZ + 1];//for mgnt_l2_sock/mgnt_sock
++	char brname[IFNAMSIZ];
++
++	drv = os_zalloc(sizeof(struct rtl871x_driver_data));
++	if (drv == NULL) {
++		printf("Could not allocate memory for rtl871x driver data\n");
++		return NULL;
++	}
++
++	drv->hapd = hapd;
++	drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
++	if (drv->ioctl_sock < 0) {
++		perror("socket[PF_INET,SOCK_DGRAM]");
++		goto bad;
++	}
++	os_memcpy(drv->iface, params->ifname, sizeof(drv->iface));
++
++	linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);/*set interface up*/
++
++	os_memset(&ifr, 0, sizeof(ifr));
++	os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
++	if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) {
++		perror("ioctl(SIOCGIFINDEX)");
++		goto bad;
++	}
++	drv->ifindex = ifr.ifr_ifindex;
++	printf("drv->ifindex=%d\n", drv->ifindex);
++
++	drv->l2_sock = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL,
++					rtl871x_handle_read, drv, 1);
++
++	if (drv->l2_sock == NULL)
++		goto bad;
++
++	if (l2_packet_get_own_addr(drv->l2_sock, params->own_addr))
++		goto bad;
++
++
++	if (params->bridge[0]) {
++		wpa_printf(MSG_DEBUG, "Configure bridge %s for EAPOL traffic.",
++			   params->bridge[0]);
++		drv->l2_sock_recv = l2_packet_init(params->bridge[0], NULL,
++						ETH_P_EAPOL, rtl871x_handle_read, drv,
++						1);
++		if (drv->l2_sock_recv == NULL)
++		{
++			//goto bad;
++			drv->l2_sock_recv = drv->l2_sock;
++			printf("no br0 interface , let l2_sock_recv==l2_sock_xmit=0x%p\n", drv->l2_sock);
++		}
++
++	} else if (linux_br_get(brname, drv->iface) == 0) {
++		wpa_printf(MSG_DEBUG, "Interface in bridge %s; configure for "
++			   "EAPOL receive", brname);
++		drv->l2_sock_recv = l2_packet_init(brname, NULL, ETH_P_EAPOL,
++						rtl871x_handle_read, drv, 1);
++		if (drv->l2_sock_recv == NULL)
++			goto bad;
++	}
++	else
++	{
++		drv->l2_sock_recv = drv->l2_sock;
++		printf("l2_sock_recv==l2_sock_xmit=0x%p\n", drv->l2_sock);
++	}
++
++
++	os_memset(ifrn_name, 0, sizeof(ifrn_name));
++	//snprintf(ifrn_name, sizeof(ifrn_name), "mgnt.%s_rena", drv->iface);
++	snprintf(ifrn_name, sizeof(ifrn_name), "mgnt.%s", "wlan0"/*drv->iface*/);
++#ifdef CONFIG_MGNT_L2SOCK
++	drv->mgnt_l2_sock = NULL;
++	drv->mgnt_l2_sock = l2_packet_init(ifrn_name, NULL, ETH_P_80211_RAW,
++				       rtl871x_recvive_mgmt_frame, drv, 1);
++	if (drv->mgnt_l2_sock == NULL)
++		goto bad;
++
++#else
++
++#ifdef CONFIG_MLME_OFFLOAD
++	drv->mgnt_sock = -1;
++#else
++	drv->mgnt_sock = rtl871x_mgnt_sock_init(drv, ifrn_name);
++	if (drv->mgnt_sock < 0) {
++		goto bad;
++	}
++#endif
++
++#endif
++
++
++	//madwifi_set_iface_flags(drv, 0);	/* mark down during setup */
++	//madwifi_set_privacy(drv->iface, drv, 0); /* default to no privacy */
++
++
++	//linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);/*set interface up*/
++
++
++	//enter MASTER MODE when init.
++	if(rtl871x_set_mode(drv, IW_MODE_MASTER)<0)
++	{
++		printf("Could not set interface to master mode!\n");
++		goto bad;
++	}
++
++/*
++	memset(&iwr, 0, sizeof(iwr));
++	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
++	iwr.u.mode = IW_MODE_MASTER;
++	if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
++		perror("ioctl[SIOCSIWMODE]");
++		printf("Could not set interface to master mode!\n");
++		goto bad;
++	}
++*/
++
++#ifndef CONFIG_MLME_OFFLOAD
++	rtl871x_set_iface_flags(drv, 1);	/*set mgnt interface up*/
++#endif
++
++
++	if (rtl871x_wireless_event_init(drv))
++		goto bad;
++
++
++	os_memcpy(drv->hw_mac, params->own_addr, ETH_ALEN);
++
++	return drv;
++
++bad:
++
++	if (drv->l2_sock_recv != NULL && drv->l2_sock_recv != drv->l2_sock)
++		l2_packet_deinit(drv->l2_sock_recv);
++
++	if (drv->l2_sock != NULL)
++		l2_packet_deinit(drv->l2_sock);
++
++	if (drv->ioctl_sock >= 0)
++		close(drv->ioctl_sock);
++
++#ifdef CONFIG_MGNT_L2SOCK
++	if ( drv->mgnt_l2_sock != NULL)
++		l2_packet_deinit(drv->mgnt_l2_sock);
++#else
++	if (drv->mgnt_sock >= 0)
++		close(drv->mgnt_sock);
++#endif
++
++	if (drv != NULL)
++		free(drv);
++
++	return NULL;
++
++}
++
++static void rtl871x_driver_deinit_ops(void *priv)
++{
++	//struct iwreq iwr;
++	struct rtl871x_driver_data *drv = priv;
++
++	//back to INFRA MODE when exit.
++/*
++	memset(&iwr, 0, sizeof(iwr));
++	os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
++	iwr.u.mode = IW_MODE_INFRA;
++	if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
++		perror("ioctl[SIOCSIWMODE]");
++	}
++*/
++	rtl871x_set_mode(drv, IW_MODE_INFRA);
++
++
++	if (drv->ioctl_sock >= 0)
++		close(drv->ioctl_sock);
++
++
++	if (drv->l2_sock_recv != NULL && drv->l2_sock_recv != drv->l2_sock)
++		l2_packet_deinit(drv->l2_sock_recv);
++
++	if(drv->l2_sock)
++		l2_packet_deinit(drv->l2_sock);
++
++	//if (drv->sock_xmit != NULL)
++	//	l2_packet_deinit(drv->sock_xmit);
++
++#ifdef CONFIG_MGNT_L2SOCK
++	if (drv->mgnt_l2_sock)
++		l2_packet_deinit(drv->mgnt_l2_sock);
++#else
++	if (drv->mgnt_sock >= 0)
++		close(drv->mgnt_sock);
++#endif
++
++	os_free(drv);
++
++}
++
++
++const struct wpa_driver_ops wpa_driver_rtw_ops = {
++	.name = "rtl871xdrv",
++	//.init = rtl871x_driver_init_ops,
++	//.deinit = rtl871x_driver_deinit_ops,
++	.hapd_init		= rtl871x_driver_init_ops,
++	.hapd_deinit		= rtl871x_driver_deinit_ops,
++	//.wireless_event_init	= rtl871x_wireless_event_init_ops,
++	//.wireless_event_deinit	= rtl871x_wireless_event_deinit_ops,
++	//.send_eapol		= rtl871x_send_eapol_ops,
++	.hapd_send_eapol	= rtl871x_send_eapol_ops,
++	//.send_ether = rtl871x_driver_send_ether_ops,
++	//.send_mgmt_frame = rtl871x_send_mgmt_frame_ops,
++	.get_hw_feature_data = rtl871x_get_hw_feature_data_ops,
++	//.sta_add = rtl871x_sta_add_ops,
++	//.sta_add2 = rtl871x_sta_add2_ops,
++	.sta_remove = rtl871x_sta_remove_ops,
++	.set_ap = rtl871x_set_beacon_ops,
++	//.set_encryption = rtl871x_set_encryption_ops,
++	.set_key = rtl871x_set_key_ops,
++	.sta_deauth = rtl871x_sta_deauth_ops,
++	.sta_disassoc = rtl871x_sta_disassoc_ops,
++	//.set_wps_beacon_ie = rtl871x_set_wps_beacon_ie_ops,
++	//.set_wps_probe_resp_ie = rtl871x_set_wps_probe_resp_ie_ops,
++	.set_ap_wps_ie = rtl871x_set_ap_wps_ie,
++	.flush			= rtl871x_sta_flush_ops,
++};
++
+diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
+index 791cd5d..c8cb71b 100644
+--- a/src/drivers/driver_wext.c
++++ b/src/drivers/driver_wext.c
+@@ -1081,6 +1081,38 @@ void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx)
+ 	wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
+ }
+ 
++//added for wps2.0 @20110519
++static int wpa_driver_wext_set_probe_req_ie(struct wpa_driver_wext_data *drv, const u8 *extra_ies,
++				size_t extra_ies_len)
++{
++	unsigned char *pbuf;
++	struct iwreq iwr;	
++	int ret = 0;
++
++	pbuf = os_malloc(extra_ies_len);
++	os_memset(pbuf, 0, extra_ies_len);
++
++	os_memset(&iwr, 0, sizeof(iwr));
++	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
++
++	os_memcpy(pbuf, extra_ies, extra_ies_len);
++
++	iwr.u.data.pointer = (caddr_t)pbuf;
++	iwr.u.data.length = extra_ies_len;
++	iwr.u.data.flags = 0x8766;//magic number
++
++	if (ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr) < 0) {
++		perror("ioctl[SIOCSIWMLME]");
++		ret = -1;
++	}
++
++	if(pbuf)
++		os_free(pbuf);
++
++	return ret;
++
++}
++
+ 
+ /**
+  * wpa_driver_wext_scan - Request the driver to initiate scan
+@@ -1103,6 +1135,10 @@ int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params)
+ 		return -1;
+ 	}
+ 
++	//added for wps2.0 @20110519
++	wpa_driver_wext_set_probe_req_ie(drv, params->extra_ies,
++				params->extra_ies_len);
++
+ 	os_memset(&iwr, 0, sizeof(iwr));
+ 	os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
+ 
+diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c
+index 00773a7..f422c95 100644
+--- a/src/drivers/drivers.c
++++ b/src/drivers/drivers.c
+@@ -46,5 +46,8 @@ const struct wpa_driver_ops *const wpa_drivers[] =
+ #ifdef CONFIG_DRIVER_NONE
+ 	&wpa_driver_none_ops,
+ #endif /* CONFIG_DRIVER_NONE */
++#ifdef CONFIG_DRIVER_RTW
++	&wpa_driver_rtw_ops,
++#endif /* CONFIG_DRIVER_RTW */
+ 	NULL
+ };
+diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
+index c6d3f81..a784e03 100644
+--- a/src/drivers/drivers.mak
++++ b/src/drivers/drivers.mak
+@@ -79,6 +79,10 @@ DRV_CFLAGS += -DCONFIG_DRIVER_BSD
+ DRV_OBJS += ../src/drivers/driver_bsd.o
+ CONFIG_L2_FREEBSD=y
+ CONFIG_DNET_PCAP=y
++ifdef CONFIG_SUPPORT_RTW_DRIVER
++DRV_CFLAGS += -DCONFIG_SUPPORT_RTW_DRIVER -DCONFIG_DRIVER_RTL_DFS
++NEED_AP_MLME=y
++endif
+ endif
+ 
+ ifdef CONFIG_DRIVER_OPENBSD
+@@ -89,6 +93,17 @@ DRV_CFLAGS += -DCONFIG_DRIVER_OPENBSD
+ DRV_OBJS += ../src/drivers/driver_openbsd.o
+ endif
+ 
++ifdef CONFIG_DRIVER_RTW
++#CFLAGS += -DCONFIG_DRIVER_RTL
++#OBJS += driver_rtl.o
++DRV_AP_CFLAGS += -DCONFIG_DRIVER_RTW -DCONFIG_DRIVER_RTL_DFS
++DRV_AP_OBJS += ../src/drivers/driver_rtw.o
++CONFIG_L2_PACKET=linux
++NEED_NETLINK=y
++NEED_LINUX_IOCTL=y
++NEED_AP_MLME=y
++endif
++
+ ifdef CONFIG_DRIVER_NONE
+ DRV_CFLAGS += -DCONFIG_DRIVER_NONE
+ DRV_OBJS += ../src/drivers/driver_none.o
+diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c
+index d140c88..df71540 100644
+--- a/src/eap_peer/eap_wsc.c
++++ b/src/eap_peer/eap_wsc.c
+@@ -565,8 +565,13 @@ send_msg:
+ 	r = eap_wsc_build_msg(data, ret, id);
+ 	if (data->state == FAIL && ret->methodState == METHOD_DONE) {
+ 		/* Use reduced client timeout for WPS to avoid long wait */
++#if 0		/*	Aries add, 2012/06/12,  extend timeout for AP IOT 	*/
++		if (sm->ClientTimeout > 4)
++			sm->ClientTimeout = 4;
++#else
+ 		if (sm->ClientTimeout > 2)
+ 			sm->ClientTimeout = 2;
++#endif
+ 	}
+ 	return r;
+ }
+diff --git a/src/wps/wps.c b/src/wps/wps.c
+index fade6b6..36cb3de 100644
+--- a/src/wps/wps.c
++++ b/src/wps/wps.c
+@@ -325,11 +325,15 @@ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
+ 	if (wps_parse_msg(msg, &attr) < 0)
+ 		return 0;
+ 
++	return is_selected_pin_registrar(&attr);
++//	Marked by Albert 2011/11/17
++//	Some APs won't carry the AuthorizedMACs in the probe response.
++//	So, skip this check will speed up the process to find the current AP out for WPS handshake.
++/*	
+ 	if (!attr.version2 && ver1_compat) {
+ 		/*
+ 		 * Version 1.0 AP - AuthorizedMACs not used, so revert back to
+ 		 * old mechanism of using SelectedRegistrar.
+-		 */
+ 		return is_selected_pin_registrar(&attr);
+ 	}
+ 
+@@ -346,6 +350,7 @@ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
+ 	}
+ 
+ 	return 0;
++*/
+ }
+ 
+ 
+diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
+index fac8bd8..7b41c90 100644
+--- a/src/wps/wps_registrar.c
++++ b/src/wps/wps_registrar.c
+@@ -589,9 +589,10 @@ static int wps_build_probe_config_methods(struct wps_registrar *reg,
+ 	 * These are the methods that the AP supports as an Enrollee for adding
+ 	 * external Registrars.
+ 	 */
+-	methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
+-	methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
+-		     WPS_CONFIG_PHY_PUSHBUTTON);
++	methods = reg->wps->config_methods;
++	//methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
++	//methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
++	//	     WPS_CONFIG_PHY_PUSHBUTTON);
+ 	wpa_printf(MSG_DEBUG, "WPS:  * Config Methods (%x)", methods);
+ 	wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
+ 	wpabuf_put_be16(msg, 2);

+ 13 - 0
alpine/wifi/client.sh

@@ -0,0 +1,13 @@
+#! /bin/sh
+
+openrc default
+
+rc-update del iptables wifi
+rc-update del dnsmasq wifi
+rc-update del hostapd wifi
+
+rc-update add wpa_supplicant wifi
+
+sed -i '/^interface wlan0/{s/^interface/#interface/;n;s/^static/#static/}' /etc/dhcpcd.conf
+
+service dhcpcd restart

+ 13 - 0
alpine/wifi/hotspot.sh

@@ -0,0 +1,13 @@
+#! /bin/sh
+
+openrc default
+
+rc-update del wpa_supplicant wifi
+
+rc-update add iptables wifi
+rc-update add dnsmasq wifi
+rc-update add hostapd wifi
+
+sed -i '/^#interface wlan0/{s/^#interface/interface/;n;s/^#static/static/}' /etc/dhcpcd.conf
+
+service dhcpcd restart

+ 2 - 0
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[*]]

+ 2048 - 0
cfg/dds.mem

@@ -0,0 +1,2048 @@
+7ffffd
+7ffff8
+7fffef
+7fffe0
+7fffcc
+7fffb3
+7fff96
+7fff73
+7fff4c
+7fff1f
+7ffeee
+7ffeb8
+7ffe7c
+7ffe3c
+7ffdf7
+7ffdad
+7ffd5e
+7ffd0a
+7ffcb2
+7ffc54
+7ffbf1
+7ffb89
+7ffb1d
+7ffaab
+7ffa35
+7ff9ba
+7ff939
+7ff8b4
+7ff82a
+7ff79b
+7ff707
+7ff66e
+7ff5d0
+7ff52d
+7ff485
+7ff3d9
+7ff327
+7ff270
+7ff1b5
+7ff0f5
+7ff02f
+7fef65
+7fee96
+7fedc1
+7fece8
+7fec0a
+7feb27
+7fea40
+7fe953
+7fe861
+7fe76a
+7fe66f
+7fe56e
+7fe469
+7fe35e
+7fe24f
+7fe13b
+7fe021
+7fdf03
+7fdde0
+7fdcb8
+7fdb8b
+7fda5a
+7fd923
+7fd7e7
+7fd6a6
+7fd561
+7fd416
+7fd2c7
+7fd173
+7fd019
+7fcebb
+7fcd58
+7fcbf0
+7fca83
+7fc911
+7fc79a
+7fc61f
+7fc49e
+7fc318
+7fc18e
+7fbffe
+7fbe6a
+7fbcd1
+7fbb32
+7fb98f
+7fb7e7
+7fb63a
+7fb488
+7fb2d1
+7fb115
+7faf55
+7fad8f
+7fabc5
+7fa9f5
+7fa821
+7fa647
+7fa469
+7fa286
+7fa09e
+7f9eb1
+7f9cbf
+7f9ac8
+7f98cc
+7f96cc
+7f94c6
+7f92bc
+7f90ac
+7f8e98
+7f8c7f
+7f8a60
+7f883d
+7f8615
+7f83e8
+7f81b7
+7f7f80
+7f7d44
+7f7b04
+7f78be
+7f7674
+7f7424
+7f71d0
+7f6f77
+7f6d19
+7f6ab6
+7f684e
+7f65e1
+7f636f
+7f60f9
+7f5e7d
+7f5bfd
+7f5977
+7f56ed
+7f545e
+7f51ca
+7f4f31
+7f4c93
+7f49f0
+7f4748
+7f449c
+7f41ea
+7f3f34
+7f3c78
+7f39b8
+7f36f3
+7f3429
+7f315a
+7f2e86
+7f2bad
+7f28cf
+7f25ed
+7f2305
+7f2019
+7f1d28
+7f1a31
+7f1736
+7f1436
+7f1131
+7f0e28
+7f0b19
+7f0805
+7f04ed
+7f01d0
+7efead
+7efb86
+7ef85a
+7ef529
+7ef1f3
+7eeeb8
+7eeb79
+7ee834
+7ee4eb
+7ee19c
+7ede49
+7edaf1
+7ed794
+7ed432
+7ed0cb
+7ecd60
+7ec9ef
+7ec67a
+7ec2ff
+7ebf80
+7ebbfc
+7eb873
+7eb4e5
+7eb152
+7eadbb
+7eaa1e
+7ea67d
+7ea2d7
+7e9f2b
+7e9b7b
+7e97c6
+7e940d
+7e904e
+7e8c8a
+7e88c2
+7e84f5
+7e8122
+7e7d4b
+7e796f
+7e758e
+7e71a9
+7e6dbe
+7e69cf
+7e65da
+7e61e1
+7e5de3
+7e59e0
+7e55d8
+7e51cb
+7e4dba
+7e49a3
+7e4588
+7e4168
+7e3d43
+7e3919
+7e34ea
+7e30b7
+7e2c7e
+7e2841
+7e23fe
+7e1fb7
+7e1b6b
+7e171b
+7e12c5
+7e0e6a
+7e0a0b
+7e05a7
+7e013d
+7dfccf
+7df85d
+7df3e5
+7def68
+7deae7
+7de661
+7de1d6
+7ddd46
+7dd8b1
+7dd417
+7dcf79
+7dcad5
+7dc62d
+7dc180
+7dbcce
+7db817
+7db35c
+7dae9b
+7da9d6
+7da50c
+7da03d
+7d9b69
+7d9690
+7d91b3
+7d8cd0
+7d87e9
+7d82fd
+7d7e0c
+7d7916
+7d741c
+7d6f1c
+7d6a18
+7d650f
+7d6001
+7d5aef
+7d55d7
+7d50bb
+7d4b99
+7d4673
+7d4148
+7d3c19
+7d36e4
+7d31ab
+7d2c6d
+7d2729
+7d21e2
+7d1c95
+7d1743
+7d11ed
+7d0c92
+7d0732
+7d01cd
+7cfc64
+7cf6f5
+7cf182
+7cec0a
+7ce68d
+7ce10b
+7cdb85
+7cd5f9
+7cd069
+7ccad4
+7cc53b
+7cbf9c
+7cb9f9
+7cb450
+7caea4
+7ca8f2
+7ca33b
+7c9d80
+7c97bf
+7c91fa
+7c8c31
+7c8662
+7c808f
+7c7ab6
+7c74d9
+7c6ef8
+7c6911
+7c6325
+7c5d35
+7c5740
+7c5146
+7c4b48
+7c4544
+7c3f3c
+7c392f
+7c331e
+7c2d07
+7c26ec
+7c20cc
+7c1aa7
+7c147d
+7c0e4f
+7c081b
+7c01e3
+7bfba6
+7bf565
+7bef1e
+7be8d3
+7be283
+7bdc2f
+7bd5d5
+7bcf77
+7bc914
+7bc2ac
+7bbc40
+7bb5ce
+7baf58
+7ba8dd
+7ba25e
+7b9bd9
+7b9550
+7b8ec2
+7b882f
+7b8198
+7b7afc
+7b745b
+7b6db5
+7b670a
+7b605b
+7b59a7
+7b52ee
+7b4c31
+7b456e
+7b3ea7
+7b37dc
+7b310b
+7b2a36
+7b235c
+7b1c7d
+7b1599
+7b0eb1
+7b07c4
+7b00d2
+7af9dc
+7af2e1
+7aebe1
+7ae4dc
+7addd2
+7ad6c4
+7acfb1
+7ac89a
+7ac17d
+7aba5c
+7ab336
+7aac0c
+7aa4dc
+7a9da8
+7a966f
+7a8f32
+7a87f0
+7a80a9
+7a795d
+7a720d
+7a6ab7
+7a635e
+7a5bff
+7a549c
+7a4d34
+7a45c7
+7a3e56
+7a36df
+7a2f65
+7a27e5
+7a2061
+7a18d8
+7a114a
+7a09b8
+7a0221
+79fa85
+79f2e4
+79eb3f
+79e395
+79dbe7
+79d433
+79cc7b
+79c4bf
+79bcfd
+79b537
+79ad6c
+79a59d
+799dc9
+7995f0
+798e12
+798630
+797e49
+79765e
+796e6d
+796678
+795e7f
+795680
+794e7d
+794676
+793e69
+793658
+792e43
+792628
+791e09
+7915e6
+790dbd
+790590
+78fd5e
+78f528
+78eced
+78e4ad
+78dc69
+78d420
+78cbd2
+78c380
+78bb29
+78b2cd
+78aa6d
+78a208
+78999f
+789130
+7888bd
+788046
+7877ca
+786f49
+7866c3
+785e39
+7855aa
+784d17
+78447f
+783be2
+783341
+782a9b
+7821f1
+781941
+78108d
+7807d5
+77ff18
+77f656
+77ed90
+77e4c5
+77dbf5
+77d321
+77ca48
+77c16b
+77b889
+77afa2
+77a6b7
+779dc7
+7794d2
+778bd9
+7782db
+7779d9
+7770d2
+7767c7
+775eb6
+7755a2
+774c88
+77436a
+773a48
+773121
+7727f5
+771ec5
+771590
+770c56
+770318
+76f9d5
+76f08e
+76e742
+76ddf2
+76d49d
+76cb43
+76c1e5
+76b882
+76af1b
+76a5af
+769c3e
+7692c9
+76894f
+767fd1
+76764e
+766cc7
+76633b
+7659ab
+765016
+76467c
+763cde
+76333b
+762994
+761fe8
+761637
+760c82
+7602c9
+75f90b
+75ef48
+75e581
+75dbb5
+75d1e5
+75c810
+75be37
+75b459
+75aa77
+75a090
+7596a4
+758cb4
+7582c0
+7578c7
+756ec9
+7564c7
+755ac0
+7550b5
+7546a6
+753c91
+753279
+75285b
+751e3a
+751413
+7509e9
+74ffb9
+74f585
+74eb4d
+74e110
+74d6cf
+74cc89
+74c23f
+74b7f0
+74ad9c
+74a345
+7498e8
+748e87
+748422
+7479b8
+746f4a
+7464d7
+745a60
+744fe4
+744564
+743adf
+743056
+7425c8
+741b36
+74109f
+740604
+73fb64
+73f0c0
+73e618
+73db6b
+73d0b9
+73c603
+73bb49
+73b08a
+73a5c7
+739aff
+739033
+738562
+737a8d
+736fb3
+7364d5
+7359f3
+734f0c
+734420
+733930
+732e3c
+732343
+731846
+730d44
+73023e
+72f734
+72ec25
+72e112
+72d5fa
+72cade
+72bfbd
+72b498
+72a96f
+729e41
+72930e
+7287d8
+727c9c
+72715d
+726619
+725ad1
+724f84
+724433
+7238dd
+722d83
+722225
+7216c2
+720b5b
+71ffef
+71f47f
+71e90b
+71dd92
+71d215
+71c693
+71bb0d
+71af83
+71a3f4
+719861
+718cc9
+71812e
+71758d
+7169e9
+715e40
+715292
+7146e1
+713b2b
+712f70
+7123b1
+7117ee
+710c27
+71005b
+70f48b
+70e8b6
+70dcdd
+70d100
+70c51e
+70b938
+70ad4e
+70a15f
+70956c
+708975
+707d79
+707179
+706574
+70596c
+704d5f
+70414d
+703538
+70291d
+701cff
+7010dc
+7004b5
+6ff88a
+6fec5a
+6fe027
+6fd3ee
+6fc7b2
+6fbb71
+6faf2c
+6fa2e2
+6f9694
+6f8a42
+6f7dec
+6f7191
+6f6532
+6f58cf
+6f4c67
+6f3ffb
+6f338b
+6f2717
+6f1a9e
+6f0e21
+6f01a0
+6ef51a
+6ee890
+6edc02
+6ecf70
+6ec2d9
+6eb63e
+6ea99f
+6e9cfb
+6e9053
+6e83a7
+6e76f7
+6e6a43
+6e5d8a
+6e50cd
+6e440b
+6e3746
+6e2a7c
+6e1dae
+6e10dc
+6e0405
+6df72a
+6dea4b
+6ddd68
+6dd081
+6dc395
+6db6a5
+6da9b1
+6d9cb8
+6d8fbc
+6d82bb
+6d75b6
+6d68ad
+6d5b9f
+6d4e8d
+6d4177
+6d345d
+6d273f
+6d1a1c
+6d0cf5
+6cffca
+6cf29b
+6ce568
+6cd830
+6ccaf4
+6cbdb4
+6cb070
+6ca328
+6c95db
+6c888b
+6c7b36
+6c6ddc
+6c607f
+6c531e
+6c45b8
+6c384e
+6c2ae0
+6c1d6e
+6c0ff8
+6c027d
+6bf4ff
+6be77c
+6bd9f5
+6bcc6a
+6bbeda
+6bb147
+6ba3af
+6b9614
+6b8874
+6b7ad0
+6b6d27
+6b5f7b
+6b51cb
+6b4416
+6b365d
+6b28a0
+6b1adf
+6b0d1a
+6aff51
+6af184
+6ae3b2
+6ad5dc
+6ac803
+6aba25
+6aac43
+6a9e5d
+6a9072
+6a8284
+6a7492
+6a669b
+6a58a1
+6a4aa2
+6a3c9f
+6a2e98
+6a208d
+6a127e
+6a046b
+69f653
+69e838
+69da19
+69cbf5
+69bdce
+69afa2
+69a172
+69933e
+698506
+6976ca
+69688a
+695a46
+694bfe
+693db2
+692f62
+69210d
+6912b5
+690458
+68f5f8
+68e793
+68d92b
+68cabe
+68bc4d
+68add9
+689f60
+6890e3
+688262
+6873de
+686555
+6856c8
+684837
+6839a2
+682b09
+681c6c
+680dcb
+67ff26
+67f07d
+67e1d0
+67d31f
+67c46a
+67b5b1
+67a6f4
+679833
+67896e
+677aa5
+676bd8
+675d07
+674e32
+673f59
+67307c
+67219b
+6712b7
+6703ce
+66f4e1
+66e5f0
+66d6fb
+66c803
+66b906
+66aa05
+669b01
+668bf8
+667cec
+666ddb
+665ec7
+664fae
+664092
+663172
+66224e
+661326
+6603fa
+65f4ca
+65e596
+65d65e
+65c722
+65b7e2
+65a89f
+659957
+658a0c
+657abc
+656b69
+655c12
+654cb7
+653d58
+652df5
+651e8e
+650f23
+64ffb5
+64f042
+64e0cc
+64d152
+64c1d3
+64b251
+64a2cb
+649342
+6483b4
+647422
+64648d
+6454f4
+644556
+6435b5
+642611
+641668
+6406bb
+63f70b
+63e756
+63d79e
+63c7e2
+63b822
+63a85f
+639897
+6388cc
+6378fc
+636929
+635952
+634978
+633999
+6329b7
+6319d0
+6309e6
+62f9f8
+62ea07
+62da11
+62ca18
+62ba1b
+62aa1a
+629a15
+628a0d
+627a00
+6269f0
+6259dc
+6249c5
+6239a9
+62298a
+621967
+620940
+61f915
+61e8e7
+61d8b5
+61c87f
+61b845
+61a808
+6197c6
+618781
+617739
+6166ec
+61569c
+614648
+6135f0
+612595
+611535
+6104d2
+60f46b
+60e401
+60d393
+60c321
+60b2ab
+60a232
+6091b4
+608134
+6070af
+606027
+604f9b
+603f0b
+602e77
+601de0
+600d45
+5ffca7
+5fec05
+5fdb5f
+5fcab5
+5fba08
+5fa957
+5f98a2
+5f87e9
+5f772d
+5f666d
+5f55aa
+5f44e3
+5f3418
+5f234a
+5f1277
+5f01a2
+5ef0c8
+5edfeb
+5ecf0a
+5ebe26
+5ead3e
+5e9c52
+5e8b62
+5e7a6f
+5e6979
+5e587e
+5e4780
+5e367f
+5e257a
+5e1471
+5e0364
+5df254
+5de140
+5dd029
+5dbf0e
+5dadef
+5d9ccd
+5d8ba7
+5d7a7e
+5d6951
+5d5820
+5d46ec
+5d35b4
+5d2479
+5d133a
+5d01f7
+5cf0b1
+5cdf67
+5cce1a
+5cbcc9
+5cab75
+5c9a1d
+5c88c1
+5c7762
+5c65ff
+5c5499
+5c432f
+5c31c1
+5c2050
+5c0edc
+5bfd64
+5bebe8
+5bda69
+5bc8e6
+5bb760
+5ba5d6
+5b9449
+5b82b8
+5b7124
+5b5f8c
+5b4df0
+5b3c51
+5b2aaf
+5b1909
+5b075f
+5af5b2
+5ae402
+5ad24e
+5ac096
+5aaedb
+5a9d1d
+5a8b5b
+5a7995
+5a67cc
+5a5600
+5a4430
+5a325c
+5a2085
+5a0eab
+59fccd
+59eaec
+59d907
+59c71e
+59b533
+59a344
+599151
+597f5b
+596d61
+595b64
+594964
+593760
+592559
+59134e
+590140
+58ef2e
+58dd19
+58cb00
+58b8e5
+58a6c5
+5894a3
+58827c
+587053
+585e26
+584bf5
+5839c2
+58278a
+581550
+580312
+57f0d0
+57de8c
+57cc44
+57b9f8
+57a7a9
+579557
+578301
+5770a8
+575e4c
+574bec
+573989
+572722
+5714b8
+57024b
+56efda
+56dd66
+56caef
+56b875
+56a5f7
+569375
+5680f1
+566e69
+565bdd
+56494f
+5636bd
+562427
+56118f
+55fef3
+55ec53
+55d9b1
+55c70b
+55b462
+55a1b5
+558f05
+557c52
+55699c
+5556e2
+554425
+553165
+551ea2
+550bdb
+54f911
+54e643
+54d373
+54c09f
+54adc7
+549aed
+54880f
+54752e
+54624a
+544f63
+543c78
+54298a
+541699
+5403a4
+53f0ac
+53ddb1
+53cab3
+53b7b2
+53a4ad
+5391a5
+537e9a
+536b8c
+53587a
+534566
+53324e
+531f33
+530c14
+52f8f3
+52e5ce
+52d2a6
+52bf7b
+52ac4c
+52991b
+5285e6
+5272ae
+525f73
+524c35
+5238f4
+5225af
+521267
+51ff1c
+51ebce
+51d87d
+51c529
+51b1d1
+519e76
+518b18
+5177b7
+516453
+5150ec
+513d82
+512a14
+5116a3
+510330
+50efb9
+50dc3f
+50c8c2
+50b541
+50a1be
+508e37
+507aae
+506721
+505391
+503fff
+502c69
+5018cf
+500533
+4ff194
+4fddf2
+4fca4c
+4fb6a4
+4fa2f8
+4f8f4a
+4f7b98
+4f67e3
+4f542b
+4f4070
+4f2cb3
+4f18f2
+4f052e
+4ef166
+4edd9c
+4ec9cf
+4eb5ff
+4ea22c
+4e8e55
+4e7a7c
+4e66a0
+4e52c0
+4e3ede
+4e2af9
+4e1710
+4e0325
+4def36
+4ddb45
+4dc751
+4db359
+4d9f5f
+4d8b61
+4d7761
+4d635e
+4d4f57
+4d3b4e
+4d2742
+4d1332
+4cff20
+4ceb0b
+4cd6f3
+4cc2d7
+4caeb9
+4c9a98
+4c8674
+4c724d
+4c5e23
+4c49f6
+4c35c6
+4c2194
+4c0d5e
+4bf925
+4be4ea
+4bd0ab
+4bbc6a
+4ba826
+4b93de
+4b7f94
+4b6b47
+4b56f7
+4b42a4
+4b2e4f
+4b19f6
+4b059a
+4af13c
+4adcda
+4ac876
+4ab40f
+4a9fa5
+4a8b38
+4a76c8
+4a6256
+4a4de0
+4a3968
+4a24ed
+4a106f
+49fbee
+49e76a
+49d2e3
+49be5a
+49a9ce
+49953e
+4980ac
+496c18
+495780
+4942e5
+492e48
+4919a8
+490505
+48f05f
+48dbb7
+48c70b
+48b25d
+489dac
+4888f8
+487442
+485f88
+484acc
+48360d
+48214b
+480c87
+47f7bf
+47e2f5
+47ce29
+47b959
+47a487
+478fb1
+477ad9
+4765ff
+475121
+473c41
+47275e
+471279
+46fd90
+46e8a5
+46d3b7
+46bec7
+46a9d3
+4694dd
+467fe4
+466ae9
+4655eb
+4640ea
+462be6
+4616e0
+4601d7
+45eccb
+45d7bd
+45c2ac
+45ad98
+459881
+458368
+456e4c
+45592e
+45440c
+452ee9
+4519c2
+450499
+44ef6d
+44da3e
+44c50d
+44afd9
+449aa3
+44856a
+44702e
+445af0
+4445af
+44306b
+441b25
+4405dc
+43f090
+43db42
+43c5f1
+43b09e
+439b48
+4385ef
+437094
+435b36
+4345d6
+433073
+431b0d
+4305a5
+42f03a
+42dacd
+42c55d
+42afea
+429a75
+4284fe
+426f83
+425a07
+424487
+422f05
+421981
+4203fa
+41ee70
+41d8e4
+41c356
+41adc5
+419831
+41829b
+416d02
+415767
+4141c9
+412c29
+411686
+4100e1
+40eb39
+40d58e
+40bfe2
+40aa32
+409480
+407ecc
+406915
+40535c
+403da0
+4027e2
+401221
+3ffc5e
+3fe699
+3fd0d1
+3fbb06
+3fa539
+3f8f6a
+3f7998
+3f63c3
+3f4dec
+3f3813
+3f2237
+3f0c59
+3ef679
+3ee096
+3ecab0
+3eb4c9
+3e9ede
+3e88f2
+3e7303
+3e5d11
+3e471d
+3e3127
+3e1b2e
+3e0533
+3def36
+3dd936
+3dc334
+3dad2f
+3d9728
+3d811f
+3d6b13
+3d5505
+3d3ef4
+3d28e2
+3d12cc
+3cfcb5
+3ce69b
+3cd07f
+3cba60
+3ca43f
+3c8e1c
+3c77f6
+3c61ce
+3c4ba4
+3c3577
+3c1f49
+3c0917
+3bf2e4
+3bdcae
+3bc676
+3bb03b
+3b99ff
+3b83bf
+3b6d7e
+3b573a
+3b40f5
+3b2aac
+3b1462
+3afe15
+3ae7c6
+3ad175
+3abb21
+3aa4cb
+3a8e73
+3a7819
+3a61bc
+3a4b5d
+3a34fc
+3a1e99
+3a0833
+39f1cb
+39db61
+39c4f5
+39ae86
+399816
+3981a3
+396b2d
+3954b6
+393e3c
+3927c0
+391142
+38fac2
+38e440
+38cdbb
+38b734
+38a0ab
+388a20
+387393
+385d03
+384671
+382fde
+381948
+3802af
+37ec15
+37d578
+37beda
+37a839
+379196
+377af1
+37644a
+374da0
+3736f5
+372047
+370997
+36f2e5
+36dc31
+36c57b
+36aec3
+369808
+36814c
+366a8d
+3653cd
+363d0a
+362645
+360f7e
+35f8b5
+35e1ea
+35cb1d
+35b44e
+359d7c
+3586a9
+356fd4
+3558fc
+354222
+352b47
+351469
+34fd89
+34e6a8
+34cfc4
+34b8de
+34a1f6
+348b0c
+347420
+345d32
+344642
+342f50
+34185c
+340166
+33ea6e
+33d374
+33bc78
+33a57a
+338e7a
+337778
+336075
+33496f
+333267
+331b5d
+330451
+32ed43
+32d633
+32bf22
+32a80e
+3290f8
+3279e1
+3262c7
+324bab
+32348e
+321d6f
+32064d
+31ef2a
+31d805
+31c0de
+31a9b5
+31928a
+317b5d
+31642e
+314cfe
+3135cb
+311e97
+310760
+30f028
+30d8ee
+30c1b2
+30aa74
+309334
+307bf3
+3064af
+304d6a
+303623
+301eda
+30078f
+2ff042
+2fd8f3
+2fc1a3
+2faa51
+2f92fc
+2f7ba6
+2f644f
+2f4cf5
+2f3599
+2f1e3c
+2f06dd
+2eef7c
+2ed819
+2ec0b5
+2ea94f
+2e91e6
+2e7a7c
+2e6311
+2e4ba3
+2e3434
+2e1cc3
+2e0550
+2deddb
+2dd665
+2dbeed
+2da773
+2d8ff7
+2d787a
+2d60fb
+2d497a
+2d31f7
+2d1a72
+2d02ec
+2ceb64
+2cd3db
+2cbc4f
+2ca4c2
+2c8d33
+2c75a3
+2c5e11
+2c467d
+2c2ee7
+2c1750
+2bffb7
+2be81c
+2bd07f
+2bb8e1
+2ba141
+2b89a0
+2b71fd
+2b5a58
+2b42b1
+2b2b09
+2b135f
+2afbb4
+2ae406
+2acc58
+2ab4a7
+2a9cf5
+2a8541
+2a6d8c
+2a55d5
+2a3e1c
+2a2662
+2a0ea6
+29f6e8
+29df29
+29c768
+29afa6
+2997e2
+29801c
+296855
+29508c
+2938c2
+2920f6
+290928
+28f159
+28d988
+28c1b6
+28a9e2
+28920c
+287a35
+28625d
+284a83
+2832a7
+281aca
+2802eb
+27eb0b
+27d329
+27bb45
+27a360
+278b7a
+277392
+275ba8
+2743bd
+272bd1
+2713e3
+26fbf3
+26e402
+26cc10
+26b41c
+269c26
+26842f
+266c36
+26543c
+263c41
+262444
+260c46
+25f446
+25dc44
+25c441
+25ac3d
+259437
+257c30
+256428
+254c1e
+253412
+251c05
+2503f7
+24ebe7
+24d3d6
+24bbc3
+24a3af
+248b9a
+247383
+245b6a
+244351
+242b36
+241319
+23fafb
+23e2dc
+23cabb
+23b299
+239a76
+238251
+236a2b
+235204
+2339db
+2321b1
+230985
+22f158
+22d92a
+22c0fa
+22a8c9
+229097
+227863
+22602e
+2247f8
+222fc1
+221788
+21ff4d
+21e712
+21ced5
+21b697
+219e57
+218617
+216dd5
+215591
+213d4d
+212507
+210cc0
+20f477
+20dc2d
+20c3e2
+20ab96
+209349
+207afa
+2062aa
+204a59
+203206
+2019b2
+20015d
+1fe907
+1fd0b0
+1fb857
+1f9ffd
+1f87a2
+1f6f46
+1f56e8
+1f3e89
+1f2629
+1f0dc8
+1ef566
+1edd02
+1ec49e
+1eac38
+1e93d1
+1e7b68
+1e62ff
+1e4a94
+1e3228
+1e19bb
+1e014d
+1de8de
+1dd06e
+1db7fc
+1d9f89
+1d8715
+1d6ea0
+1d562a
+1d3db3
+1d253b
+1d0cc1
+1cf446
+1cdbcb
+1cc34e
+1caad0
+1c9251
+1c79d0
+1c614f
+1c48cd
+1c3049
+1c17c5
+1bff3f
+1be6b8
+1bce30
+1bb5a8
+1b9d1e
+1b8493
+1b6c07
+1b5379
+1b3aeb
+1b225c
+1b09cc
+1af13a
+1ad8a8
+1ac015
+1aa780
+1a8eeb
+1a7654
+1a5dbd
+1a4524
+1a2c8b
+1a13f0
+19fb55
+19e2b8
+19ca1b
+19b17c
+1998dd
+19803c
+19679b
+194ef8
+193655
+191db0
+19050b
+18ec65
+18d3bd
+18bb15
+18a26c
+1889c2
+187116
+18586a
+183fbd
+18270f
+180e61
+17f5b1
+17dd00
+17c44e
+17ab9c
+1792e8
+177a34
+17617f
+1748c9
+173011
+17175a
+16fea1
+16e5e7
+16cd2c
+16b471
+169bb4
+1682f7
+166a39
+16517a
+1638ba
+161ff9
+160738
+15ee75
+15d5b2
+15bcee
+15a429
+158b63
+15729d
+1559d5
+15410d
+152844
+150f7a
+14f6af
+14dde4
+14c518
+14ac4b
+14937d
+147aae
+1461de
+14490e
+14303d
+14176b
+13fe99
+13e5c5
+13ccf1
+13b41c
+139b47
+138270
+136999
+1350c1
+1337e8
+131f0f
+130635
+12ed5a
+12d47e
+12bba2
+12a2c5
+1289e7
+127109
+125829
+123f49
+122669
+120d87
+11f4a5
+11dbc3
+11c2df
+11a9fb
+119117
+117831
+115f4b
+114664
+112d7d
+111495
+10fbac
+10e2c2
+10c9d8
+10b0ee
+109802
+107f16
+10662a
+104d3c
+10344e
+101b60
+100271
+0fe981
+0fd091
+0fb7a0
+0f9eae
+0f85bc
+0f6cc9
+0f53d6
+0f3ae2
+0f21ed
+0f08f8
+0ef002
+0ed70c
+0ebe15
+0ea51e
+0e8c26
+0e732d
+0e5a34
+0e413a
+0e2840
+0e0f45
+0df64a
+0ddd4e
+0dc452
+0dab55
+0d9257
+0d7959
+0d605b
+0d475c
+0d2e5c
+0d155c
+0cfc5c
+0ce35b
+0cca59
+0cb157
+0c9855
+0c7f52
+0c664e
+0c4d4a
+0c3446
+0c1b41
+0c023b
+0be936
+0bd02f
+0bb729
+0b9e21
+0b851a
+0b6c12
+0b5309
+0b3a00
+0b20f7
+0b07ed
+0aeee3
+0ad5d8
+0abccd
+0aa3c1
+0a8ab5
+0a71a9
+0a589c
+0a3f8f
+0a2682
+0a0d74
+09f466
+09db57
+09c248
+09a938
+099029
+097718
+095e08
+0944f7
+092be6
+0912d4
+08f9c2
+08e0b0
+08c79d
+08ae8a
+089577
+087c63
+08634f
+084a3b
+083126
+081811
+07fefc
+07e5e6
+07ccd1
+07b3ba
+079aa4
+07818d
+076876
+074f5f
+073647
+071d2f
+070417
+06eaff
+06d1e6
+06b8cd
+069fb4
+06869a
+066d80
+065466
+063b4c
+062232
+060917
+05effc
+05d6e1
+05bdc6
+05a4aa
+058b8e
+057272
+055956
+054039
+05271d
+050e00
+04f4e3
+04dbc6
+04c2a8
+04a98a
+04906d
+04774f
+045e31
+044512
+042bf4
+0412d5
+03f9b6
+03e097
+03c778
+03ae59
+03953a
+037c1a
+0362fa
+0349db
+0330bb
+03179b
+02fe7a
+02e55a
+02cc3a
+02b319
+0299f9
+0280d8
+0267b7
+024e96
+023575
+021c54
+020333
+01ea12
+01d0f1
+01b7cf
+019eae
+01858c
+016c6b
+015349
+013a28
+012106
+0107e4
+00eec2
+00d5a0
+00bc7f
+00a35d
+008a3b
+007119
+0057f7
+003ed5
+0025b3
+000c91

+ 43 - 0
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

+ 208 - 0
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]}]

+ 70 - 0
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>

+ 292 - 0
cores/axi_hub.py

@@ -0,0 +1,292 @@
+hub_size = 6
+source = """
+`timescale 1 ns / 1 ps
+
+module axi_hub #
+(
+  parameter integer CFG_DATA_WIDTH = 1024,
+  parameter integer STS_DATA_WIDTH = 1024
+)
+(
+  input  wire                      aclk,
+  input  wire                      aresetn,
+
+  input  wire [11:0]               s_axi_awid,
+  input  wire [31:0]               s_axi_awaddr,
+  input  wire                      s_axi_awvalid,
+  output wire                      s_axi_awready,
+
+  input  wire [3:0]                s_axi_wstrb,
+  input  wire                      s_axi_wlast,
+  input  wire [31:0]               s_axi_wdata,
+  input  wire                      s_axi_wvalid,
+  output wire                      s_axi_wready,
+
+  output wire [11:0]               s_axi_bid,
+  output wire                      s_axi_bvalid,
+  input  wire                      s_axi_bready,
+
+  input  wire [11:0]               s_axi_arid,
+  input  wire [3:0]                s_axi_arlen,
+  input  wire [31:0]               s_axi_araddr,
+  input  wire                      s_axi_arvalid,
+  output wire                      s_axi_arready,
+
+  output wire [11:0]               s_axi_rid,
+  output wire                      s_axi_rlast,
+  output wire [31:0]               s_axi_rdata,
+  output wire                      s_axi_rvalid,
+  input  wire                      s_axi_rready,
+
+  output wire [CFG_DATA_WIDTH-1:0] cfg_data,
+
+  input  wire [STS_DATA_WIDTH-1:0] sts_data,
+{% for i in range(hub_size) -%}
+{% set index =  "%02d" % i %}
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram CLK" *)
+  output wire                      b{{index}}_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram RST" *)
+  output wire                      b{{index}}_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram EN" *)
+  output wire                      b{{index}}_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram WE" *)
+  output wire [3:0]                b{{index}}_bram_we,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram ADDR" *)
+  output wire [21:0]               b{{index}}_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram DIN" *)
+  output wire [31:0]               b{{index}}_bram_wdata,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram DOUT" *)
+  input  wire [31:0]               b{{index}}_bram_rdata,
+
+  input  wire [31:0]               s{{index}}_axis_tdata,
+  input  wire                      s{{index}}_axis_tvalid,
+  output wire                      s{{index}}_axis_tready,
+
+  output wire [31:0]               m{{index}}_axis_tdata,
+  output wire                      m{{index}}_axis_tvalid,
+  input  wire                      m{{index}}_axis_tready{% if not loop.last %},{% endif %}
+{% endfor -%}
+);
+
+  localparam integer HUB_SIZE = {{hub_size}};
+  localparam integer MUX_SIZE = HUB_SIZE + 2;
+  localparam integer CFG_SIZE = CFG_DATA_WIDTH / 32;
+  localparam integer CFG_WIDTH = CFG_SIZE > 1 ? $clog2(CFG_SIZE) : 1;
+  localparam integer STS_SIZE = STS_DATA_WIDTH / 32;
+  localparam integer STS_WIDTH = STS_SIZE > 1 ? $clog2(STS_SIZE) : 1;
+
+  reg [3:0] int_awcntr_reg = 4'd0;
+  reg [3:0] int_arcntr_reg = 4'd0;
+
+  wire int_awvalid_wire, int_awready_wire;
+  wire int_wvalid_wire, int_wready_wire;
+  wire int_bvalid_wire, int_bready_wire;
+  wire int_arvalid_wire, int_arready_wire;
+  wire int_rvalid_wire, int_rready_wire;
+
+  wire [11:0] int_awid_wire;
+  wire [31:0] int_awaddr_wire;
+
+  wire [3:0] int_wstrb_wire;
+  wire int_wlast_wire;
+  wire [31:0] int_wdata_wire;
+
+  wire [11:0] int_arid_wire;
+  wire [3:0]  int_arlen_wire;
+  wire [31:0] int_araddr_wire;
+
+  wire [11:0] int_rid_wire;
+  wire int_rlast_wire;
+  wire [31:0] int_rdata_wire [MUX_SIZE-1:0];
+
+  wire [31:0] int_sdata_wire [HUB_SIZE-1:0];
+  wire [31:0] int_mdata_wire [HUB_SIZE-1:0];
+  wire [HUB_SIZE-1:0] int_svalid_wire, int_sready_wire;
+  wire [HUB_SIZE-1:0] int_mvalid_wire, int_mready_wire;
+
+  wire [31:0] int_bdata_wire [HUB_SIZE-1:0];
+
+  wire [21:0] int_waddr_wire;
+  wire [21:0] int_raddr_wire;
+
+  wire [31:0] int_cfg_mux [CFG_SIZE-1:0];
+  wire [31:0] int_sts_mux [STS_SIZE-1:0];
+
+  wire [31:0] int_rdata_mux [MUX_SIZE-1:0];
+  wire [MUX_SIZE-1:0] int_wsel_wire, int_rsel_wire;
+
+  wire [HUB_SIZE-1:0] int_bsel_wire;
+
+  wire [CFG_SIZE-1:0] int_ce_wire;
+  wire int_we_wire, int_re_wire;
+
+  genvar j, k;
+
+  assign int_awready_wire = int_bready_wire & int_wvalid_wire & int_wlast_wire;
+  assign int_wready_wire = int_bready_wire & int_awvalid_wire;
+  assign int_bvalid_wire = int_awvalid_wire & int_wvalid_wire & int_wlast_wire;
+
+  assign int_arready_wire = int_rready_wire & int_rlast_wire;
+  assign int_rvalid_wire = int_arvalid_wire;
+  assign int_rlast_wire = int_arcntr_reg == int_arlen_wire;
+
+  assign int_we_wire = int_bready_wire & int_awvalid_wire & int_wvalid_wire;
+  assign int_re_wire = int_rready_wire & int_arvalid_wire;
+
+  assign int_waddr_wire = int_awaddr_wire[23:2] + int_awcntr_reg;
+  assign int_raddr_wire = int_araddr_wire[23:2] + int_arcntr_reg;
+
+  assign int_rdata_wire[0] = int_rdata_mux[int_araddr_wire[27:24]];
+
+  assign int_rdata_mux[0] = int_cfg_mux[int_raddr_wire[CFG_WIDTH-1:0]];
+  assign int_rdata_mux[1] = int_sts_mux[int_raddr_wire[STS_WIDTH-1:0]];
+
+  generate
+    for(j = 0; j < HUB_SIZE; j = j + 1)
+    begin : MUXES
+      assign int_rdata_mux[j+2] = int_svalid_wire[j] ? int_sdata_wire[j] : 32'd0;
+      assign int_rdata_wire[j+2] = int_bsel_wire[j] ? int_bdata_wire[j] : 32'd0;
+      assign int_mdata_wire[j] = int_wdata_wire;
+      assign int_mvalid_wire[j] = int_wsel_wire[j+2];
+      assign int_sready_wire[j] = int_rsel_wire[j+2];
+    end
+  endgenerate
+
+  generate
+    for(j = 0; j < MUX_SIZE; j = j + 1)
+    begin : SELECTS
+      assign int_wsel_wire[j] = int_we_wire & (int_awaddr_wire[27:24] == j);
+      assign int_rsel_wire[j] = int_re_wire & (int_araddr_wire[27:24] == j);
+    end
+  endgenerate
+
+  generate
+    for(j = 0; j < CFG_SIZE; j = j + 1)
+    begin : CFG_WORDS
+      assign int_cfg_mux[j] = cfg_data[j*32+31:j*32];
+      assign int_ce_wire[j] = int_wsel_wire[0] & (int_waddr_wire[CFG_WIDTH-1:0] == j);
+      for(k = 0; k < 32; k = k + 1)
+      begin : CFG_BITS
+        FDRE #(
+          .INIT(1'b0)
+        ) FDRE_inst (
+          .CE(int_ce_wire[j] & int_wstrb_wire[k/8]),
+          .C(aclk),
+          .R(~aresetn),
+          .D(int_wdata_wire[k]),
+          .Q(cfg_data[j*32 + k])
+        );
+      end
+    end
+  endgenerate
+
+  generate
+    for(j = 0; j < STS_SIZE; j = j + 1)
+    begin : STS_WORDS
+      assign int_sts_mux[j] = sts_data[j*32+31:j*32];
+    end
+  endgenerate
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn | (int_awvalid_wire & int_awready_wire))
+    begin
+      int_awcntr_reg <= 4'd0;
+    end
+    else if(~int_wlast_wire & int_we_wire)
+    begin
+      int_awcntr_reg <= int_awcntr_reg + 1'b1;
+    end
+
+    if(~aresetn | (int_arvalid_wire & int_arready_wire))
+    begin
+      int_arcntr_reg <= 4'd0;
+    end
+    else if(~int_rlast_wire & int_re_wire)
+    begin
+      int_arcntr_reg <= int_arcntr_reg + 1'b1;
+    end
+  end
+
+  inout_buffer #(
+    .DATA_WIDTH(44)
+  ) buf_0 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data({s_axi_awid, s_axi_awaddr}),
+    .in_valid(s_axi_awvalid), .in_ready(s_axi_awready),
+    .out_data({int_awid_wire, int_awaddr_wire}),
+    .out_valid(int_awvalid_wire), .out_ready(int_awready_wire)
+  );
+
+  inout_buffer #(
+    .DATA_WIDTH(37)
+  ) buf_1 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data({s_axi_wstrb, s_axi_wlast, s_axi_wdata}),
+    .in_valid(s_axi_wvalid), .in_ready(s_axi_wready),
+    .out_data({int_wstrb_wire, int_wlast_wire, int_wdata_wire}),
+    .out_valid(int_wvalid_wire), .out_ready(int_wready_wire)
+  );
+
+  output_buffer #(
+    .DATA_WIDTH(12)
+  ) buf_2 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_awid_wire), .in_valid(int_bvalid_wire), .in_ready(int_bready_wire),
+    .out_data(s_axi_bid), .out_valid(s_axi_bvalid), .out_ready(s_axi_bready)
+  );
+
+  inout_buffer #(
+    .DATA_WIDTH(48)
+  ) buf_3 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data({s_axi_arid, s_axi_arlen, s_axi_araddr}),
+    .in_valid(s_axi_arvalid), .in_ready(s_axi_arready),
+    .out_data({int_arid_wire, int_arlen_wire, int_araddr_wire}),
+    .out_valid(int_arvalid_wire), .out_ready(int_arready_wire)
+  );
+
+  output_buffer #(
+    .DATA_WIDTH(HUB_SIZE + 45)
+  ) buf_4 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data({int_rsel_wire[MUX_SIZE-1:2] & ~int_svalid_wire, int_arid_wire, int_rlast_wire, int_rdata_wire[0]}),
+    .in_valid(int_rvalid_wire), .in_ready(int_rready_wire),
+    .out_data({int_bsel_wire, s_axi_rid, s_axi_rlast, int_rdata_wire[1]}),
+    .out_valid(s_axi_rvalid), .out_ready(s_axi_rready)
+  );
+
+  assign s_axi_rdata = {{s_axi_rdata(hub_size)}};
+{% for i in range(hub_size) -%}
+{% set index =  "%02d" % i %}
+  assign int_bdata_wire[{{i}}] = b{{index}}_bram_rdata;
+  assign b{{index}}_bram_clk = aclk;
+  assign b{{index}}_bram_rst = ~aresetn;
+  assign b{{index}}_bram_en = int_rsel_wire[{{i+2}}] | int_wsel_wire[{{i+2}}];
+  assign b{{index}}_bram_we = int_wsel_wire[{{i+2}}] ? int_wstrb_wire : 4'd0;
+  assign b{{index}}_bram_addr = int_we_wire ? int_waddr_wire : int_raddr_wire;
+  assign b{{index}}_bram_wdata = int_wdata_wire;
+
+  assign int_sdata_wire[{{i}}] = s{{index}}_axis_tdata;
+  assign int_svalid_wire[{{i}}] = s{{index}}_axis_tvalid;
+  assign s{{index}}_axis_tready = int_sready_wire[{{i}}];
+
+  inout_buffer #(
+    .DATA_WIDTH(32)
+  ) mbuf_{{i}} (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_mdata_wire[{{i}}]), .in_valid(int_mvalid_wire[{{i}}]), .in_ready(int_mready_wire[{{i}}]),
+    .out_data(m{{index}}_axis_tdata), .out_valid(m{{index}}_axis_tvalid), .out_ready(m{{index}}_axis_tready)
+  );
+{% endfor %}
+endmodule
+"""
+
+import jinja2
+
+
+def s_axi_rdata(n):
+    return " | ".join(map(lambda i: "int_rdata_wire[%d]" % i, range(1, n + 2)))
+
+
+print(jinja2.Template(source).render(hub_size=hub_size, s_axi_rdata=s_axi_rdata))

+ 493 - 0
cores/axi_hub.v

@@ -0,0 +1,493 @@
+
+`timescale 1 ns / 1 ps
+
+module axi_hub #
+(
+  parameter integer CFG_DATA_WIDTH = 1024,
+  parameter integer STS_DATA_WIDTH = 1024
+)
+(
+  input  wire                      aclk,
+  input  wire                      aresetn,
+
+  input  wire [11:0]               s_axi_awid,
+  input  wire [31:0]               s_axi_awaddr,
+  input  wire                      s_axi_awvalid,
+  output wire                      s_axi_awready,
+
+  input  wire [3:0]                s_axi_wstrb,
+  input  wire                      s_axi_wlast,
+  input  wire [31:0]               s_axi_wdata,
+  input  wire                      s_axi_wvalid,
+  output wire                      s_axi_wready,
+
+  output wire [11:0]               s_axi_bid,
+  output wire                      s_axi_bvalid,
+  input  wire                      s_axi_bready,
+
+  input  wire [11:0]               s_axi_arid,
+  input  wire [3:0]                s_axi_arlen,
+  input  wire [31:0]               s_axi_araddr,
+  input  wire                      s_axi_arvalid,
+  output wire                      s_axi_arready,
+
+  output wire [11:0]               s_axi_rid,
+  output wire                      s_axi_rlast,
+  output wire [31:0]               s_axi_rdata,
+  output wire                      s_axi_rvalid,
+  input  wire                      s_axi_rready,
+
+  output wire [CFG_DATA_WIDTH-1:0] cfg_data,
+
+  input  wire [STS_DATA_WIDTH-1:0] sts_data,
+
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b00_bram CLK" *)
+  output wire                      b00_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b00_bram RST" *)
+  output wire                      b00_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b00_bram EN" *)
+  output wire                      b00_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b00_bram WE" *)
+  output wire [3:0]                b00_bram_we,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b00_bram ADDR" *)
+  output wire [21:0]               b00_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b00_bram DIN" *)
+  output wire [31:0]               b00_bram_wdata,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b00_bram DOUT" *)
+  input  wire [31:0]               b00_bram_rdata,
+
+  input  wire [31:0]               s00_axis_tdata,
+  input  wire                      s00_axis_tvalid,
+  output wire                      s00_axis_tready,
+
+  output wire [31:0]               m00_axis_tdata,
+  output wire                      m00_axis_tvalid,
+  input  wire                      m00_axis_tready,
+
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b01_bram CLK" *)
+  output wire                      b01_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b01_bram RST" *)
+  output wire                      b01_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b01_bram EN" *)
+  output wire                      b01_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b01_bram WE" *)
+  output wire [3:0]                b01_bram_we,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b01_bram ADDR" *)
+  output wire [21:0]               b01_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b01_bram DIN" *)
+  output wire [31:0]               b01_bram_wdata,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b01_bram DOUT" *)
+  input  wire [31:0]               b01_bram_rdata,
+
+  input  wire [31:0]               s01_axis_tdata,
+  input  wire                      s01_axis_tvalid,
+  output wire                      s01_axis_tready,
+
+  output wire [31:0]               m01_axis_tdata,
+  output wire                      m01_axis_tvalid,
+  input  wire                      m01_axis_tready,
+
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b02_bram CLK" *)
+  output wire                      b02_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b02_bram RST" *)
+  output wire                      b02_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b02_bram EN" *)
+  output wire                      b02_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b02_bram WE" *)
+  output wire [3:0]                b02_bram_we,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b02_bram ADDR" *)
+  output wire [21:0]               b02_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b02_bram DIN" *)
+  output wire [31:0]               b02_bram_wdata,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b02_bram DOUT" *)
+  input  wire [31:0]               b02_bram_rdata,
+
+  input  wire [31:0]               s02_axis_tdata,
+  input  wire                      s02_axis_tvalid,
+  output wire                      s02_axis_tready,
+
+  output wire [31:0]               m02_axis_tdata,
+  output wire                      m02_axis_tvalid,
+  input  wire                      m02_axis_tready,
+
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b03_bram CLK" *)
+  output wire                      b03_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b03_bram RST" *)
+  output wire                      b03_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b03_bram EN" *)
+  output wire                      b03_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b03_bram WE" *)
+  output wire [3:0]                b03_bram_we,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b03_bram ADDR" *)
+  output wire [21:0]               b03_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b03_bram DIN" *)
+  output wire [31:0]               b03_bram_wdata,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b03_bram DOUT" *)
+  input  wire [31:0]               b03_bram_rdata,
+
+  input  wire [31:0]               s03_axis_tdata,
+  input  wire                      s03_axis_tvalid,
+  output wire                      s03_axis_tready,
+
+  output wire [31:0]               m03_axis_tdata,
+  output wire                      m03_axis_tvalid,
+  input  wire                      m03_axis_tready,
+
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b04_bram CLK" *)
+  output wire                      b04_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b04_bram RST" *)
+  output wire                      b04_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b04_bram EN" *)
+  output wire                      b04_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b04_bram WE" *)
+  output wire [3:0]                b04_bram_we,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b04_bram ADDR" *)
+  output wire [21:0]               b04_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b04_bram DIN" *)
+  output wire [31:0]               b04_bram_wdata,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b04_bram DOUT" *)
+  input  wire [31:0]               b04_bram_rdata,
+
+  input  wire [31:0]               s04_axis_tdata,
+  input  wire                      s04_axis_tvalid,
+  output wire                      s04_axis_tready,
+
+  output wire [31:0]               m04_axis_tdata,
+  output wire                      m04_axis_tvalid,
+  input  wire                      m04_axis_tready,
+
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b05_bram CLK" *)
+  output wire                      b05_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b05_bram RST" *)
+  output wire                      b05_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b05_bram EN" *)
+  output wire                      b05_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b05_bram WE" *)
+  output wire [3:0]                b05_bram_we,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b05_bram ADDR" *)
+  output wire [21:0]               b05_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b05_bram DIN" *)
+  output wire [31:0]               b05_bram_wdata,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b05_bram DOUT" *)
+  input  wire [31:0]               b05_bram_rdata,
+
+  input  wire [31:0]               s05_axis_tdata,
+  input  wire                      s05_axis_tvalid,
+  output wire                      s05_axis_tready,
+
+  output wire [31:0]               m05_axis_tdata,
+  output wire                      m05_axis_tvalid,
+  input  wire                      m05_axis_tready
+);
+
+  localparam integer HUB_SIZE = 6;
+  localparam integer MUX_SIZE = HUB_SIZE + 2;
+  localparam integer CFG_SIZE = CFG_DATA_WIDTH / 32;
+  localparam integer CFG_WIDTH = CFG_SIZE > 1 ? $clog2(CFG_SIZE) : 1;
+  localparam integer STS_SIZE = STS_DATA_WIDTH / 32;
+  localparam integer STS_WIDTH = STS_SIZE > 1 ? $clog2(STS_SIZE) : 1;
+
+  reg [3:0] int_awcntr_reg = 4'd0;
+  reg [3:0] int_arcntr_reg = 4'd0;
+
+  wire int_awvalid_wire, int_awready_wire;
+  wire int_wvalid_wire, int_wready_wire;
+  wire int_bvalid_wire, int_bready_wire;
+  wire int_arvalid_wire, int_arready_wire;
+  wire int_rvalid_wire, int_rready_wire;
+
+  wire [11:0] int_awid_wire;
+  wire [31:0] int_awaddr_wire;
+
+  wire [3:0] int_wstrb_wire;
+  wire int_wlast_wire;
+  wire [31:0] int_wdata_wire;
+
+  wire [11:0] int_arid_wire;
+  wire [3:0]  int_arlen_wire;
+  wire [31:0] int_araddr_wire;
+
+  wire [11:0] int_rid_wire;
+  wire int_rlast_wire;
+  wire [31:0] int_rdata_wire [MUX_SIZE-1:0];
+
+  wire [31:0] int_sdata_wire [HUB_SIZE-1:0];
+  wire [31:0] int_mdata_wire [HUB_SIZE-1:0];
+  wire [HUB_SIZE-1:0] int_svalid_wire, int_sready_wire;
+  wire [HUB_SIZE-1:0] int_mvalid_wire, int_mready_wire;
+
+  wire [31:0] int_bdata_wire [HUB_SIZE-1:0];
+
+  wire [21:0] int_waddr_wire;
+  wire [21:0] int_raddr_wire;
+
+  wire [31:0] int_cfg_mux [CFG_SIZE-1:0];
+  wire [31:0] int_sts_mux [STS_SIZE-1:0];
+
+  wire [31:0] int_rdata_mux [MUX_SIZE-1:0];
+  wire [MUX_SIZE-1:0] int_wsel_wire, int_rsel_wire;
+
+  wire [HUB_SIZE-1:0] int_bsel_wire;
+
+  wire [CFG_SIZE-1:0] int_ce_wire;
+  wire int_we_wire, int_re_wire;
+
+  genvar j, k;
+
+  assign int_awready_wire = int_bready_wire & int_wvalid_wire & int_wlast_wire;
+  assign int_wready_wire = int_bready_wire & int_awvalid_wire;
+  assign int_bvalid_wire = int_awvalid_wire & int_wvalid_wire & int_wlast_wire;
+
+  assign int_arready_wire = int_rready_wire & int_rlast_wire;
+  assign int_rvalid_wire = int_arvalid_wire;
+  assign int_rlast_wire = int_arcntr_reg == int_arlen_wire;
+
+  assign int_we_wire = int_bready_wire & int_awvalid_wire & int_wvalid_wire;
+  assign int_re_wire = int_rready_wire & int_arvalid_wire;
+
+  assign int_waddr_wire = int_awaddr_wire[23:2] + int_awcntr_reg;
+  assign int_raddr_wire = int_araddr_wire[23:2] + int_arcntr_reg;
+
+  assign int_rdata_wire[0] = int_rdata_mux[int_araddr_wire[27:24]];
+
+  assign int_rdata_mux[0] = int_cfg_mux[int_raddr_wire[CFG_WIDTH-1:0]];
+  assign int_rdata_mux[1] = int_sts_mux[int_raddr_wire[STS_WIDTH-1:0]];
+
+  generate
+    for(j = 0; j < HUB_SIZE; j = j + 1)
+    begin : MUXES
+      assign int_rdata_mux[j+2] = int_svalid_wire[j] ? int_sdata_wire[j] : 32'd0;
+      assign int_rdata_wire[j+2] = int_bsel_wire[j] ? int_bdata_wire[j] : 32'd0;
+      assign int_mdata_wire[j] = int_wdata_wire;
+      assign int_mvalid_wire[j] = int_wsel_wire[j+2];
+      assign int_sready_wire[j] = int_rsel_wire[j+2];
+    end
+  endgenerate
+
+  generate
+    for(j = 0; j < MUX_SIZE; j = j + 1)
+    begin : SELECTS
+      assign int_wsel_wire[j] = int_we_wire & (int_awaddr_wire[27:24] == j);
+      assign int_rsel_wire[j] = int_re_wire & (int_araddr_wire[27:24] == j);
+    end
+  endgenerate
+
+  generate
+    for(j = 0; j < CFG_SIZE; j = j + 1)
+    begin : CFG_WORDS
+      assign int_cfg_mux[j] = cfg_data[j*32+31:j*32];
+      assign int_ce_wire[j] = int_wsel_wire[0] & (int_waddr_wire[CFG_WIDTH-1:0] == j);
+      for(k = 0; k < 32; k = k + 1)
+      begin : CFG_BITS
+        FDRE #(
+          .INIT(1'b0)
+        ) FDRE_inst (
+          .CE(int_ce_wire[j] & int_wstrb_wire[k/8]),
+          .C(aclk),
+          .R(~aresetn),
+          .D(int_wdata_wire[k]),
+          .Q(cfg_data[j*32 + k])
+        );
+      end
+    end
+  endgenerate
+
+  generate
+    for(j = 0; j < STS_SIZE; j = j + 1)
+    begin : STS_WORDS
+      assign int_sts_mux[j] = sts_data[j*32+31:j*32];
+    end
+  endgenerate
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn | (int_awvalid_wire & int_awready_wire))
+    begin
+      int_awcntr_reg <= 4'd0;
+    end
+    else if(~int_wlast_wire & int_we_wire)
+    begin
+      int_awcntr_reg <= int_awcntr_reg + 1'b1;
+    end
+
+    if(~aresetn | (int_arvalid_wire & int_arready_wire))
+    begin
+      int_arcntr_reg <= 4'd0;
+    end
+    else if(~int_rlast_wire & int_re_wire)
+    begin
+      int_arcntr_reg <= int_arcntr_reg + 1'b1;
+    end
+  end
+
+  inout_buffer #(
+    .DATA_WIDTH(44)
+  ) buf_0 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data({s_axi_awid, s_axi_awaddr}),
+    .in_valid(s_axi_awvalid), .in_ready(s_axi_awready),
+    .out_data({int_awid_wire, int_awaddr_wire}),
+    .out_valid(int_awvalid_wire), .out_ready(int_awready_wire)
+  );
+
+  inout_buffer #(
+    .DATA_WIDTH(37)
+  ) buf_1 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data({s_axi_wstrb, s_axi_wlast, s_axi_wdata}),
+    .in_valid(s_axi_wvalid), .in_ready(s_axi_wready),
+    .out_data({int_wstrb_wire, int_wlast_wire, int_wdata_wire}),
+    .out_valid(int_wvalid_wire), .out_ready(int_wready_wire)
+  );
+
+  output_buffer #(
+    .DATA_WIDTH(12)
+  ) buf_2 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_awid_wire), .in_valid(int_bvalid_wire), .in_ready(int_bready_wire),
+    .out_data(s_axi_bid), .out_valid(s_axi_bvalid), .out_ready(s_axi_bready)
+  );
+
+  inout_buffer #(
+    .DATA_WIDTH(48)
+  ) buf_3 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data({s_axi_arid, s_axi_arlen, s_axi_araddr}),
+    .in_valid(s_axi_arvalid), .in_ready(s_axi_arready),
+    .out_data({int_arid_wire, int_arlen_wire, int_araddr_wire}),
+    .out_valid(int_arvalid_wire), .out_ready(int_arready_wire)
+  );
+
+  output_buffer #(
+    .DATA_WIDTH(HUB_SIZE + 45)
+  ) buf_4 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data({int_rsel_wire[MUX_SIZE-1:2] & ~int_svalid_wire, int_arid_wire, int_rlast_wire, int_rdata_wire[0]}),
+    .in_valid(int_rvalid_wire), .in_ready(int_rready_wire),
+    .out_data({int_bsel_wire, s_axi_rid, s_axi_rlast, int_rdata_wire[1]}),
+    .out_valid(s_axi_rvalid), .out_ready(s_axi_rready)
+  );
+
+  assign s_axi_rdata = int_rdata_wire[1] | int_rdata_wire[2] | int_rdata_wire[3] | int_rdata_wire[4] | int_rdata_wire[5] | int_rdata_wire[6] | int_rdata_wire[7];
+
+  assign int_bdata_wire[0] = b00_bram_rdata;
+  assign b00_bram_clk = aclk;
+  assign b00_bram_rst = ~aresetn;
+  assign b00_bram_en = int_rsel_wire[2] | int_wsel_wire[2];
+  assign b00_bram_we = int_wsel_wire[2] ? int_wstrb_wire : 4'd0;
+  assign b00_bram_addr = int_we_wire ? int_waddr_wire : int_raddr_wire;
+  assign b00_bram_wdata = int_wdata_wire;
+
+  assign int_sdata_wire[0] = s00_axis_tdata;
+  assign int_svalid_wire[0] = s00_axis_tvalid;
+  assign s00_axis_tready = int_sready_wire[0];
+
+  inout_buffer #(
+    .DATA_WIDTH(32)
+  ) mbuf_0 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_mdata_wire[0]), .in_valid(int_mvalid_wire[0]), .in_ready(int_mready_wire[0]),
+    .out_data(m00_axis_tdata), .out_valid(m00_axis_tvalid), .out_ready(m00_axis_tready)
+  );
+
+  assign int_bdata_wire[1] = b01_bram_rdata;
+  assign b01_bram_clk = aclk;
+  assign b01_bram_rst = ~aresetn;
+  assign b01_bram_en = int_rsel_wire[3] | int_wsel_wire[3];
+  assign b01_bram_we = int_wsel_wire[3] ? int_wstrb_wire : 4'd0;
+  assign b01_bram_addr = int_we_wire ? int_waddr_wire : int_raddr_wire;
+  assign b01_bram_wdata = int_wdata_wire;
+
+  assign int_sdata_wire[1] = s01_axis_tdata;
+  assign int_svalid_wire[1] = s01_axis_tvalid;
+  assign s01_axis_tready = int_sready_wire[1];
+
+  inout_buffer #(
+    .DATA_WIDTH(32)
+  ) mbuf_1 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_mdata_wire[1]), .in_valid(int_mvalid_wire[1]), .in_ready(int_mready_wire[1]),
+    .out_data(m01_axis_tdata), .out_valid(m01_axis_tvalid), .out_ready(m01_axis_tready)
+  );
+
+  assign int_bdata_wire[2] = b02_bram_rdata;
+  assign b02_bram_clk = aclk;
+  assign b02_bram_rst = ~aresetn;
+  assign b02_bram_en = int_rsel_wire[4] | int_wsel_wire[4];
+  assign b02_bram_we = int_wsel_wire[4] ? int_wstrb_wire : 4'd0;
+  assign b02_bram_addr = int_we_wire ? int_waddr_wire : int_raddr_wire;
+  assign b02_bram_wdata = int_wdata_wire;
+
+  assign int_sdata_wire[2] = s02_axis_tdata;
+  assign int_svalid_wire[2] = s02_axis_tvalid;
+  assign s02_axis_tready = int_sready_wire[2];
+
+  inout_buffer #(
+    .DATA_WIDTH(32)
+  ) mbuf_2 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_mdata_wire[2]), .in_valid(int_mvalid_wire[2]), .in_ready(int_mready_wire[2]),
+    .out_data(m02_axis_tdata), .out_valid(m02_axis_tvalid), .out_ready(m02_axis_tready)
+  );
+
+  assign int_bdata_wire[3] = b03_bram_rdata;
+  assign b03_bram_clk = aclk;
+  assign b03_bram_rst = ~aresetn;
+  assign b03_bram_en = int_rsel_wire[5] | int_wsel_wire[5];
+  assign b03_bram_we = int_wsel_wire[5] ? int_wstrb_wire : 4'd0;
+  assign b03_bram_addr = int_we_wire ? int_waddr_wire : int_raddr_wire;
+  assign b03_bram_wdata = int_wdata_wire;
+
+  assign int_sdata_wire[3] = s03_axis_tdata;
+  assign int_svalid_wire[3] = s03_axis_tvalid;
+  assign s03_axis_tready = int_sready_wire[3];
+
+  inout_buffer #(
+    .DATA_WIDTH(32)
+  ) mbuf_3 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_mdata_wire[3]), .in_valid(int_mvalid_wire[3]), .in_ready(int_mready_wire[3]),
+    .out_data(m03_axis_tdata), .out_valid(m03_axis_tvalid), .out_ready(m03_axis_tready)
+  );
+
+  assign int_bdata_wire[4] = b04_bram_rdata;
+  assign b04_bram_clk = aclk;
+  assign b04_bram_rst = ~aresetn;
+  assign b04_bram_en = int_rsel_wire[6] | int_wsel_wire[6];
+  assign b04_bram_we = int_wsel_wire[6] ? int_wstrb_wire : 4'd0;
+  assign b04_bram_addr = int_we_wire ? int_waddr_wire : int_raddr_wire;
+  assign b04_bram_wdata = int_wdata_wire;
+
+  assign int_sdata_wire[4] = s04_axis_tdata;
+  assign int_svalid_wire[4] = s04_axis_tvalid;
+  assign s04_axis_tready = int_sready_wire[4];
+
+  inout_buffer #(
+    .DATA_WIDTH(32)
+  ) mbuf_4 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_mdata_wire[4]), .in_valid(int_mvalid_wire[4]), .in_ready(int_mready_wire[4]),
+    .out_data(m04_axis_tdata), .out_valid(m04_axis_tvalid), .out_ready(m04_axis_tready)
+  );
+
+  assign int_bdata_wire[5] = b05_bram_rdata;
+  assign b05_bram_clk = aclk;
+  assign b05_bram_rst = ~aresetn;
+  assign b05_bram_en = int_rsel_wire[7] | int_wsel_wire[7];
+  assign b05_bram_we = int_wsel_wire[7] ? int_wstrb_wire : 4'd0;
+  assign b05_bram_addr = int_we_wire ? int_waddr_wire : int_raddr_wire;
+  assign b05_bram_wdata = int_wdata_wire;
+
+  assign int_sdata_wire[5] = s05_axis_tdata;
+  assign int_svalid_wire[5] = s05_axis_tvalid;
+  assign s05_axis_tready = int_sready_wire[5];
+
+  inout_buffer #(
+    .DATA_WIDTH(32)
+  ) mbuf_5 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_mdata_wire[5]), .in_valid(int_mvalid_wire[5]), .in_ready(int_mready_wire[5]),
+    .out_data(m05_axis_tdata), .out_valid(m05_axis_tvalid), .out_ready(m05_axis_tready)
+  );
+
+endmodule

+ 149 - 0
cores/axis_accumulator.v

@@ -0,0 +1,149 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_accumulator #
+(
+  parameter integer S_AXIS_TDATA_WIDTH = 16,
+  parameter integer M_AXIS_TDATA_WIDTH = 32,
+  parameter integer CNTR_WIDTH = 16,
+  parameter         AXIS_TDATA_SIGNED = "FALSE",
+  parameter         CONTINUOUS = "FALSE"
+)
+(
+  // System signals
+  input  wire                          aclk,
+  input  wire                          aresetn,
+
+  input  wire [CNTR_WIDTH-1:0]         cfg_data,
+
+  // Slave side
+  output wire                          s_axis_tready,
+  input  wire [S_AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                          s_axis_tvalid,
+
+  // Master side
+  input  wire                          m_axis_tready,
+  output wire [M_AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                          m_axis_tvalid
+);
+
+  reg [M_AXIS_TDATA_WIDTH-1:0] int_tdata_reg, int_tdata_next;
+  reg [M_AXIS_TDATA_WIDTH-1:0] int_accu_reg, int_accu_next;
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg int_tvalid_reg, int_tvalid_next;
+  reg int_tready_reg, int_tready_next;
+
+  wire [M_AXIS_TDATA_WIDTH-1:0] sum_accu_wire;
+  wire int_comp_wire, int_tvalid_wire;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_tdata_reg <= {(M_AXIS_TDATA_WIDTH){1'b0}};
+      int_tvalid_reg <= 1'b0;
+      int_tready_reg <= 1'b0;
+      int_accu_reg <= {(M_AXIS_TDATA_WIDTH){1'b0}};
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+    end
+    else
+    begin
+      int_tdata_reg <= int_tdata_next;
+      int_tvalid_reg <= int_tvalid_next;
+      int_tready_reg <= int_tready_next;
+      int_accu_reg <= int_accu_next;
+      int_cntr_reg <= int_cntr_next;
+    end
+  end
+
+  assign int_comp_wire = int_cntr_reg < cfg_data;
+  assign int_tvalid_wire = int_tready_reg & s_axis_tvalid;
+
+  generate
+    if(AXIS_TDATA_SIGNED == "TRUE")
+    begin : SIGNED
+      assign sum_accu_wire = $signed(int_accu_reg) + $signed(s_axis_tdata);
+    end
+    else
+    begin : UNSIGNED
+      assign sum_accu_wire = int_accu_reg + s_axis_tdata;
+    end
+  endgenerate
+
+  generate
+    if(CONTINUOUS == "TRUE")
+    begin : CONTINUE
+      always @*
+      begin
+        int_tdata_next = int_tdata_reg;
+        int_tvalid_next = int_tvalid_reg;
+        int_tready_next = int_tready_reg;
+        int_accu_next = int_accu_reg;
+        int_cntr_next = int_cntr_reg;
+
+        if(~int_tready_reg & int_comp_wire)
+        begin
+          int_tready_next = 1'b1;
+        end
+
+        if(int_tvalid_wire & int_comp_wire)
+        begin
+          int_cntr_next = int_cntr_reg + 1'b1;
+          int_accu_next = sum_accu_wire;
+        end
+
+        if(int_tvalid_wire & ~int_comp_wire)
+        begin
+          int_cntr_next = {(CNTR_WIDTH){1'b0}};
+          int_accu_next = {(M_AXIS_TDATA_WIDTH){1'b0}};
+          int_tdata_next = sum_accu_wire;
+          int_tvalid_next = 1'b1;
+        end
+
+        if(m_axis_tready & int_tvalid_reg)
+        begin
+          int_tvalid_next = 1'b0;
+        end
+      end
+    end
+    else
+    begin : STOP
+      always @*
+      begin
+        int_tdata_next = int_tdata_reg;
+        int_tvalid_next = int_tvalid_reg;
+        int_tready_next = int_tready_reg;
+        int_accu_next = int_accu_reg;
+        int_cntr_next = int_cntr_reg;
+
+        if(~int_tready_reg & int_comp_wire)
+        begin
+          int_tready_next = 1'b1;
+        end
+
+        if(int_tvalid_wire & int_comp_wire)
+        begin
+          int_cntr_next = int_cntr_reg + 1'b1;
+          int_accu_next = sum_accu_wire;
+        end
+
+        if(int_tvalid_wire & ~int_comp_wire)
+        begin
+          int_tready_next = 1'b0;
+          int_tdata_next = sum_accu_wire;
+          int_tvalid_next = 1'b1;
+        end
+
+        if(m_axis_tready & int_tvalid_reg)
+        begin
+          int_tvalid_next = 1'b0;
+        end
+      end
+    end
+  endgenerate
+
+  assign s_axis_tready = int_tready_reg;
+  assign m_axis_tdata = int_tdata_reg;
+  assign m_axis_tvalid = int_tvalid_reg;
+
+endmodule

+ 50 - 0
cores/axis_adder.v

@@ -0,0 +1,50 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_adder #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter         AXIS_TDATA_SIGNED = "FALSE"
+)
+(
+  // System signals
+  input  wire                        aclk,
+
+  // Slave side
+  output wire                        s_axis_a_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_a_tdata,
+  input  wire                        s_axis_a_tvalid,
+
+  output wire                        s_axis_b_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_b_tdata,
+  input  wire                        s_axis_b_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  wire [AXIS_TDATA_WIDTH-1:0] int_tdata_wire;
+  wire int_tready_wire, int_tvalid_wire;
+
+  generate
+    if(AXIS_TDATA_SIGNED == "TRUE")
+    begin : SIGNED
+      assign int_tdata_wire = $signed(s_axis_a_tdata) + $signed(s_axis_b_tdata);
+    end
+    else
+    begin : UNSIGNED
+      assign int_tdata_wire = s_axis_a_tdata + s_axis_b_tdata;
+    end
+  endgenerate
+
+  assign int_tvalid_wire = s_axis_a_tvalid & s_axis_b_tvalid;
+  assign int_tready_wire = int_tvalid_wire & m_axis_tready;
+
+  assign s_axis_a_tready = int_tready_wire;
+  assign s_axis_b_tready = int_tready_wire;
+  assign m_axis_tdata = int_tdata_wire;
+  assign m_axis_tvalid = int_tvalid_wire;
+
+endmodule

+ 91 - 0
cores/axis_alex.v

@@ -0,0 +1,91 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_alex
+(
+  // System signals
+  input  wire        aclk,
+  input  wire        aresetn,
+
+  output wire [3:0]  alex_data,
+
+  // Slave side
+  output wire        s_axis_tready,
+  input  wire [31:0] s_axis_tdata,
+  input  wire        s_axis_tvalid
+);
+
+  reg [15:0] int_data_reg, int_data_next;
+  reg [11:0] int_cntr_reg, int_cntr_next;
+  reg [1:0] int_load_reg, int_load_next;
+  reg int_enbl_reg, int_enbl_next;
+  reg int_tready_reg, int_tready_next;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_data_reg <= 16'd0;
+      int_cntr_reg <= 12'd0;
+      int_load_reg <= 2'd0;
+      int_enbl_reg <= 1'b0;
+      int_tready_reg <= 1'b0;
+    end
+    else
+    begin
+      int_data_reg <= int_data_next;
+      int_cntr_reg <= int_cntr_next;
+      int_load_reg <= int_load_next;
+      int_enbl_reg <= int_enbl_next;
+      int_tready_reg <= int_tready_next;
+    end
+  end
+
+  always @*
+  begin
+    int_data_next = int_data_reg;
+    int_cntr_next = int_cntr_reg;
+    int_load_next = int_load_reg;
+    int_enbl_next = int_enbl_reg;
+    int_tready_next = int_tready_reg;
+
+    if(s_axis_tvalid & ~int_enbl_reg)
+    begin
+      int_data_next = s_axis_tdata[15:0];
+      int_load_next = s_axis_tdata[17:16];
+      int_enbl_next = 1'b1;
+      int_tready_next = 1'b1;
+    end
+
+    if(int_tready_reg)
+    begin
+      int_tready_next = 1'b0;
+    end
+
+    if(int_enbl_reg)
+    begin
+      int_cntr_next = int_cntr_reg + 1'b1;
+    end
+
+    if(&int_cntr_reg[6:0])
+    begin
+      int_data_next = {int_data_reg[14:0], 1'b0};
+    end
+
+    if(int_cntr_reg[7] & int_cntr_reg[11])
+    begin
+      int_cntr_next = 12'd0;
+      int_load_next = 2'd0;
+      int_enbl_next = 1'b0;
+    end
+
+  end
+
+  assign s_axis_tready = int_tready_reg;
+
+  assign alex_data[0] = int_data_reg[15];
+  assign alex_data[1] = int_cntr_reg[6] & ~int_cntr_reg[11];
+  assign alex_data[2] = int_load_reg[0] & int_cntr_reg[6] & int_cntr_reg[11];
+  assign alex_data[3] = int_load_reg[1] & int_cntr_reg[6] & int_cntr_reg[11];
+
+endmodule

+ 111 - 0
cores/axis_averager.v

@@ -0,0 +1,111 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_averager #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter integer CNTR_WIDTH = 16,
+  parameter AXIS_TDATA_SIGNED = "FALSE"
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [CNTR_WIDTH-1:0]       pre_data,
+  input  wire [CNTR_WIDTH-1:0]       tot_data,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid,
+
+  // FIFO programmable flag
+  input  wire                        fifo_prog_full,
+
+  // FIFO_WRITE port
+  input  wire                        fifo_write_full,
+  output wire [AXIS_TDATA_WIDTH-1:0] fifo_write_data,
+  output wire                        fifo_write_wren,
+
+  // FIFO_READ port
+  input  wire                        fifo_read_empty,
+  input  wire [AXIS_TDATA_WIDTH-1:0] fifo_read_data,
+  output wire                        fifo_read_rden
+);
+
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg int_rden_reg, int_rden_next;
+  reg int_tvalid_reg, int_tvalid_next;
+
+  wire [AXIS_TDATA_WIDTH-1:0] int_data_wire, sum_data_wire;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_rden_reg <= 1'b0;
+      int_tvalid_reg <= 1'b1;
+    end
+    else
+    begin
+      int_cntr_reg <= int_cntr_next;
+      int_rden_reg <= int_rden_next;
+      int_tvalid_reg <= int_tvalid_next;
+    end
+  end
+
+  always @*
+  begin
+    int_cntr_next = int_cntr_reg;
+    int_rden_next = int_rden_reg;
+    int_tvalid_next = int_tvalid_reg;
+
+    if(s_axis_tvalid)
+    begin
+      int_cntr_next = int_cntr_reg + 1'b1;
+
+      if(int_cntr_reg == pre_data)
+      begin
+        int_rden_next = 1'b1;
+        int_tvalid_next = 1'b0;
+      end
+
+      if(int_cntr_reg == tot_data)
+      begin
+        int_cntr_next = {(CNTR_WIDTH){1'b0}};
+        int_tvalid_next = 1'b1;
+      end
+    end
+  end
+
+  assign int_data_wire = int_tvalid_reg ? {(AXIS_TDATA_WIDTH){1'b0}} : fifo_read_data;
+
+  generate
+    if(AXIS_TDATA_SIGNED == "TRUE")
+    begin : SIGNED
+      assign sum_data_wire = $signed(int_data_wire) + $signed(s_axis_tdata);
+    end
+    else
+    begin : UNSIGNED
+      assign sum_data_wire = int_data_wire + s_axis_tdata;
+    end
+  endgenerate
+
+  assign s_axis_tready = 1'b1;
+
+  assign m_axis_tdata = fifo_read_data;
+  assign m_axis_tvalid = fifo_prog_full & int_tvalid_reg & s_axis_tvalid;
+
+  assign fifo_read_rden = int_rden_reg & s_axis_tvalid;
+
+  assign fifo_write_data = sum_data_wire;
+  assign fifo_write_wren = s_axis_tvalid;
+
+endmodule

+ 151 - 0
cores/axis_bram_reader.v

@@ -0,0 +1,151 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_bram_reader #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter integer BRAM_DATA_WIDTH = 32,
+  parameter integer BRAM_ADDR_WIDTH = 10,
+  parameter         CONTINUOUS = "FALSE"
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [BRAM_ADDR_WIDTH-1:0]  cfg_data,
+  output wire [BRAM_ADDR_WIDTH-1:0]  sts_data,
+
+  // Master side
+  output wire                        m_axis_tlast,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid,
+  input  wire                        m_axis_tready,
+
+  // BRAM port
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram CLK" *)
+  output wire                        b_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram RST" *)
+  output wire                        b_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram EN" *)
+  output wire                        b_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram ADDR" *)
+  output wire [BRAM_ADDR_WIDTH-1:0]  b_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram DOUT" *)
+  input  wire [BRAM_DATA_WIDTH-1:0]  b_bram_rdata
+);
+
+  reg [BRAM_ADDR_WIDTH-1:0] int_addr_reg, int_addr_next;
+  reg [BRAM_ADDR_WIDTH-1:0] int_data_reg;
+  reg int_enbl_reg, int_enbl_next;
+
+  wire [AXIS_TDATA_WIDTH-1:0] int_data_wire;
+  wire [2:0] int_last_wire, int_valid_wire, int_ready_wire;
+  wire int_comp_wire;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_addr_reg <= {(BRAM_ADDR_WIDTH){1'b0}};
+      int_data_reg <= {(BRAM_ADDR_WIDTH){1'b0}};
+      int_enbl_reg <= 1'b0;
+    end
+    else
+    begin
+      int_addr_reg <= int_addr_next;
+      int_data_reg <= cfg_data;
+      int_enbl_reg <= int_enbl_next;
+    end
+  end
+
+  assign int_comp_wire = int_addr_reg < int_data_reg;
+
+  assign int_last_wire[0] = ~int_comp_wire;
+  assign int_valid_wire[0] = int_enbl_reg;
+
+  generate
+    if(CONTINUOUS == "TRUE")
+    begin : CONTINUE
+      always @*
+      begin
+        int_addr_next = int_addr_reg;
+        int_enbl_next = int_enbl_reg;
+
+        if(~int_enbl_reg & int_comp_wire)
+        begin
+          int_enbl_next = 1'b1;
+        end
+
+        if(int_ready_wire[0] & int_enbl_reg & int_comp_wire)
+        begin
+          int_addr_next = int_addr_reg + 1'b1;
+        end
+
+        if(int_ready_wire[0] & int_enbl_reg & int_last_wire[0])
+        begin
+          int_addr_next = {(BRAM_ADDR_WIDTH){1'b0}};
+        end
+      end
+    end
+    else
+    begin : STOP
+      always @*
+      begin
+        int_addr_next = int_addr_reg;
+        int_enbl_next = int_enbl_reg;
+
+        if(~int_enbl_reg & int_comp_wire)
+        begin
+          int_enbl_next = 1'b1;
+        end
+
+        if(int_ready_wire[0] & int_enbl_reg & int_comp_wire)
+        begin
+          int_addr_next = int_addr_reg + 1'b1;
+        end
+
+        if(int_ready_wire[0] & int_enbl_reg & int_last_wire[0])
+        begin
+          int_enbl_next = 1'b0;
+        end
+      end
+    end
+  endgenerate
+
+  output_buffer #(
+    .DATA_WIDTH(1)
+  ) buf_0 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_last_wire[0]), .in_valid(int_valid_wire[0]), .in_ready(int_ready_wire[0]),
+    .out_data(int_last_wire[1]), .out_valid(int_valid_wire[1]), .out_ready(int_ready_wire[1])
+  );
+
+  input_buffer #(
+    .DATA_WIDTH(AXIS_TDATA_WIDTH + 1)
+  ) buf_1 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data({int_last_wire[1], b_bram_rdata}),
+    .in_valid(int_valid_wire[1]), .in_ready(int_ready_wire[1]),
+    .out_data({int_last_wire[2], int_data_wire}),
+    .out_valid(int_valid_wire[2]), .out_ready(int_ready_wire[2])
+  );
+
+  output_buffer #(
+    .DATA_WIDTH(AXIS_TDATA_WIDTH + 1)
+  ) buf_2 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data({int_last_wire[2], int_data_wire}),
+    .in_valid(int_valid_wire[2]), .in_ready(int_ready_wire[2]),
+    .out_data({m_axis_tlast, m_axis_tdata}),
+    .out_valid(m_axis_tvalid), .out_ready(m_axis_tready)
+  );
+
+  assign sts_data = int_addr_reg - int_valid_wire[1] - int_valid_wire[2] - m_axis_tvalid;
+
+  assign b_bram_clk = aclk;
+  assign b_bram_rst = ~aresetn;
+  assign b_bram_en = int_ready_wire[0];
+  assign b_bram_addr = int_addr_reg;
+
+endmodule

+ 62 - 0
cores/axis_bram_writer.v

@@ -0,0 +1,62 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_bram_writer #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter integer BRAM_DATA_WIDTH = 32,
+  parameter integer BRAM_ADDR_WIDTH = 10
+)
+(
+  // System signals
+  input  wire                         aclk,
+  input  wire                         aresetn,
+
+  output wire [BRAM_ADDR_WIDTH-1:0]   sts_data,
+
+  // Slave side
+  input  wire [AXIS_TDATA_WIDTH-1:0]  s_axis_tdata,
+  input  wire                         s_axis_tvalid,
+  output wire                         s_axis_tready,
+
+  // BRAM port
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram CLK" *)
+  output wire                         b_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram RST" *)
+  output wire                         b_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram EN" *)
+  output wire                         b_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram WE" *)
+  output wire [BRAM_DATA_WIDTH/8-1:0] b_bram_we,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram ADDR" *)
+  output wire [BRAM_ADDR_WIDTH-1:0]   b_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram DIN" *)
+  output wire [BRAM_DATA_WIDTH-1:0]   b_bram_wdata
+);
+
+  reg [BRAM_ADDR_WIDTH-1:0] int_addr_reg;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_addr_reg <= {(BRAM_ADDR_WIDTH){1'b0}};
+    end
+    else if(s_axis_tvalid)
+    begin
+      int_addr_reg <= int_addr_reg + 1'b1;
+    end
+  end
+
+  assign sts_data = int_addr_reg;
+
+  assign s_axis_tready = 1'b1;
+
+  assign b_bram_clk = aclk;
+  assign b_bram_rst = ~aresetn;
+  assign b_bram_en = s_axis_tvalid;
+  assign b_bram_we = {(BRAM_DATA_WIDTH/8){s_axis_tvalid}};
+  assign b_bram_addr = int_addr_reg;
+  assign b_bram_wdata = s_axis_tdata;
+
+endmodule

+ 22 - 0
cores/axis_constant.v

@@ -0,0 +1,22 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_constant #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+
+  input  wire [AXIS_TDATA_WIDTH-1:0] cfg_data,
+
+  // Master side
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  assign m_axis_tdata = cfg_data;
+  assign m_axis_tvalid = 1'b1;
+
+endmodule

+ 100 - 0
cores/axis_counter.v

@@ -0,0 +1,100 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_counter #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter integer CNTR_WIDTH = 32,
+  parameter         CONTINUOUS = "FALSE"
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [CNTR_WIDTH-1:0]       cfg_data,
+
+  // Master side
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid,
+  input  wire                        m_axis_tready
+);
+
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg [CNTR_WIDTH-1:0] int_data_reg;
+  reg int_enbl_reg, int_enbl_next;
+
+  wire int_comp_wire, int_last_wire;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_data_reg <= {(CNTR_WIDTH){1'b0}};
+      int_enbl_reg <= 1'b0;
+    end
+    else
+    begin
+      int_cntr_reg <= int_cntr_next;
+      int_data_reg <= cfg_data;
+      int_enbl_reg <= int_enbl_next;
+    end
+  end
+
+  assign int_comp_wire = int_cntr_reg < int_data_reg;
+  assign int_last_wire = ~int_comp_wire;
+
+  generate
+    if(CONTINUOUS == "TRUE")
+    begin : CONTINUE
+      always @*
+      begin
+        int_cntr_next = int_cntr_reg;
+        int_enbl_next = int_enbl_reg;
+
+        if(~int_enbl_reg & int_comp_wire)
+        begin
+          int_enbl_next = 1'b1;
+        end
+
+        if(m_axis_tready & int_enbl_reg & int_comp_wire)
+        begin
+          int_cntr_next = int_cntr_reg + 1'b1;
+        end
+
+        if(m_axis_tready & int_enbl_reg & int_last_wire)
+        begin
+          int_cntr_next = {(CNTR_WIDTH){1'b0}};
+        end
+      end
+    end
+    else
+    begin : STOP
+      always @*
+      begin
+        int_cntr_next = int_cntr_reg;
+        int_enbl_next = int_enbl_reg;
+
+        if(~int_enbl_reg & int_comp_wire)
+        begin
+          int_enbl_next = 1'b1;
+        end
+
+        if(m_axis_tready & int_enbl_reg & int_comp_wire)
+        begin
+          int_cntr_next = int_cntr_reg + 1'b1;
+        end
+
+        if(m_axis_tready & int_enbl_reg & int_last_wire)
+        begin
+          int_enbl_next = 1'b0;
+        end
+      end
+    end
+  endgenerate
+
+  assign m_axis_tdata = int_cntr_reg;
+  assign m_axis_tvalid = int_enbl_reg;
+
+endmodule

+ 89 - 0
cores/axis_decimator.v

@@ -0,0 +1,89 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_decimator #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter integer CNTR_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [CNTR_WIDTH-1:0]       cfg_data,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  reg [AXIS_TDATA_WIDTH-1:0] int_tdata_reg, int_tdata_next;
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg int_tvalid_reg, int_tvalid_next;
+  reg int_tready_reg, int_tready_next;
+
+  wire int_comp_wire, int_tvalid_wire;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_tdata_reg <= {(AXIS_TDATA_WIDTH){1'b0}};
+      int_tvalid_reg <= 1'b0;
+      int_tready_reg <= 1'b0;
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+    end
+    else
+    begin
+      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
+  end
+
+  assign int_comp_wire = int_cntr_reg < cfg_data;
+  assign int_tvalid_wire = int_tready_reg & s_axis_tvalid;
+
+  always @*
+  begin
+    int_tdata_next = int_tdata_reg;
+    int_tvalid_next = int_tvalid_reg;
+    int_tready_next = int_tready_reg;
+    int_cntr_next = int_cntr_reg;
+
+    if(~int_tready_reg & int_comp_wire)
+    begin
+      int_tready_next = 1'b1;
+    end
+
+    if(int_tvalid_wire & int_comp_wire)
+    begin
+      int_cntr_next = int_cntr_reg + 1'b1;
+    end
+
+    if(int_tvalid_wire & ~int_comp_wire)
+    begin
+      int_cntr_next = {(CNTR_WIDTH){1'b0}};
+      int_tdata_next = s_axis_tdata;
+      int_tvalid_next = 1'b1;
+    end
+
+    if(m_axis_tready & int_tvalid_reg)
+    begin
+      int_tvalid_next = 1'b0;
+    end
+  end
+
+  assign s_axis_tready = int_tready_reg;
+  assign m_axis_tdata = int_tdata_reg;
+  assign m_axis_tvalid = int_tvalid_reg;
+
+endmodule

+ 85 - 0
cores/axis_fifo.v

@@ -0,0 +1,85 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_fifo #
+(
+  parameter integer S_AXIS_TDATA_WIDTH = 32,
+  parameter integer M_AXIS_TDATA_WIDTH = 32,
+  parameter integer WRITE_DEPTH = 512,
+  parameter         ALWAYS_READY = "FALSE",
+  parameter         ALWAYS_VALID = "FALSE"
+)
+(
+  // System signals
+  input  wire                          aclk,
+  input  wire                          aresetn,
+
+  // FIFO status
+  output wire [15:0]                   write_count,
+  output wire [15:0]                   read_count,
+
+  // Slave side
+  input  wire [S_AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                          s_axis_tvalid,
+  output wire                          s_axis_tready,
+
+  // Master side
+  output wire [M_AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                          m_axis_tvalid,
+  input  wire                          m_axis_tready
+);
+
+  localparam integer WRITE_COUNT_WIDTH = $clog2(WRITE_DEPTH) + 1;
+  localparam integer READ_COUNT_WIDTH = $clog2(WRITE_DEPTH * S_AXIS_TDATA_WIDTH / M_AXIS_TDATA_WIDTH) + 1;
+
+  wire [M_AXIS_TDATA_WIDTH-1:0] int_data_wire;
+  wire int_empty_wire, int_full_wire;
+
+  xpm_fifo_sync #(
+    .WRITE_DATA_WIDTH(S_AXIS_TDATA_WIDTH),
+    .FIFO_WRITE_DEPTH(WRITE_DEPTH),
+    .READ_DATA_WIDTH(M_AXIS_TDATA_WIDTH),
+    .READ_MODE("fwft"),
+    .FIFO_READ_LATENCY(0),
+    .FIFO_MEMORY_TYPE("block"),
+    .USE_ADV_FEATURES("0404"),
+    .WR_DATA_COUNT_WIDTH(WRITE_COUNT_WIDTH),
+    .RD_DATA_COUNT_WIDTH(READ_COUNT_WIDTH)
+  ) fifo_0 (
+    .empty(int_empty_wire),
+    .full(int_full_wire),
+    .wr_data_count(write_count),
+    .rd_data_count(read_count),
+    .rst(~aresetn),
+    .wr_clk(aclk),
+    .wr_en(s_axis_tvalid),
+    .din(s_axis_tdata),
+    .rd_en(m_axis_tready),
+    .dout(int_data_wire)
+  );
+
+  generate
+    if(ALWAYS_READY == "TRUE")
+    begin : READY_INPUT
+      assign s_axis_tready = 1'b1;
+    end
+    else
+    begin : BLOCKING_INPUT
+      assign s_axis_tready = ~int_full_wire;
+    end
+  endgenerate
+
+  generate
+    if(ALWAYS_VALID == "TRUE")
+    begin : VALID_OUTPUT
+      assign m_axis_tdata = int_empty_wire ? {(M_AXIS_TDATA_WIDTH){1'b0}} : int_data_wire;
+      assign m_axis_tvalid = 1'b1;
+    end
+    else
+    begin : BLOCKING_OUTPUT
+      assign m_axis_tdata = int_data_wire;
+      assign m_axis_tvalid = ~int_empty_wire;
+    end
+  endgenerate
+
+endmodule

+ 64 - 0
cores/axis_gate_controller.v

@@ -0,0 +1,64 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_gate_controller
+(
+  input  wire         aclk,
+  input  wire         aresetn,
+
+  // Slave side
+  output wire         s_axis_tready,
+  input  wire [127:0] s_axis_tdata,
+  input  wire         s_axis_tvalid,
+
+  output wire [31:0]  poff,
+  output wire [15:0]  level,
+  output wire         dout
+);
+
+  reg [63:0] int_cntr_reg;
+  reg [48:0] int_data_reg;
+  reg [31:0] int_poff_reg;
+  reg [15:0] int_level_reg;
+  reg int_dout_reg;
+
+  wire [48:0] int_data_wire;
+  wire int_enbl_wire;
+
+  assign int_data_wire = int_enbl_wire ? int_data_reg : s_axis_tdata[112:64];
+  assign int_enbl_wire = |int_cntr_reg;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_cntr_reg <= 64'd0;
+      int_data_reg <= 49'd0;
+      int_poff_reg <= 32'd0;
+      int_level_reg <= 16'd0;
+      int_dout_reg <= 1'b0;
+    end
+    else
+    begin
+      if(int_enbl_wire)
+      begin
+        int_cntr_reg <= int_cntr_reg - 1'b1;
+      end
+      else if(s_axis_tvalid)
+      begin
+        int_cntr_reg <= s_axis_tdata[63:0];
+        int_data_reg <= s_axis_tdata[112:64];
+      end
+      int_poff_reg <= int_data_wire[31:0];
+      int_level_reg <= int_data_wire[47:32];
+      int_dout_reg <= int_data_wire[48] & (int_enbl_wire | s_axis_tvalid);
+    end
+  end
+
+  assign s_axis_tready = ~int_enbl_wire & aresetn;
+
+  assign poff = int_poff_reg;
+  assign level = int_level_reg;
+  assign dout = int_dout_reg;
+
+endmodule

+ 40 - 0
cores/axis_gpio_reader.v

@@ -0,0 +1,40 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_gpio_reader #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+
+  inout  wire [AXIS_TDATA_WIDTH-1:0] gpio_data,
+
+  // Master side
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  reg  [AXIS_TDATA_WIDTH-1:0] int_data_reg [1:0];
+  wire [AXIS_TDATA_WIDTH-1:0] int_data_wire;
+
+  genvar j;
+
+  generate
+  for(j = 0; j < AXIS_TDATA_WIDTH; j = j + 1)
+  begin : GPIO
+    IOBUF gpio_iobuf (.O(int_data_wire[j]), .IO(gpio_data[j]), .I(1'b0), .T(1'b1));
+  end
+  endgenerate
+
+  always @(posedge aclk)
+  begin
+    int_data_reg[0] <= int_data_wire;
+    int_data_reg[1] <= int_data_reg[0];
+  end
+
+  assign m_axis_tdata = int_data_reg[1];
+  assign m_axis_tvalid = 1'b1;
+
+endmodule

+ 105 - 0
cores/axis_histogram.v

@@ -0,0 +1,105 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_histogram #
+(
+  parameter integer AXIS_TDATA_WIDTH = 16,
+  parameter integer BRAM_DATA_WIDTH = 32,
+  parameter integer BRAM_ADDR_WIDTH = 14
+)
+(
+  // System signals
+  input  wire                         aclk,
+  input  wire                         aresetn,
+
+  // Slave side
+  input  wire [AXIS_TDATA_WIDTH-1:0]  s_axis_tdata,
+  input  wire                         s_axis_tvalid,
+  output wire                         s_axis_tready,
+
+  // BRAM port
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram CLK" *)
+  output wire                         b_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram RST" *)
+  output wire                         b_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram EN" *)
+  output wire                         b_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram WE" *)
+  output wire [BRAM_DATA_WIDTH/8-1:0] b_bram_we,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram ADDR" *)
+  output wire [BRAM_ADDR_WIDTH-1:0]   b_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram DIN" *)
+  output wire [BRAM_DATA_WIDTH-1:0]   b_bram_wdata,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram DOUT" *)
+  input  wire [BRAM_DATA_WIDTH-1:0]   b_bram_rdata
+);
+
+  reg [BRAM_ADDR_WIDTH-1:0] int_addr_reg, int_addr_next;
+  reg [BRAM_DATA_WIDTH-1:0] int_data_reg, int_data_next;
+  reg [1:0] int_case_reg, int_case_next;
+  reg int_tready_reg, int_tready_next;
+  reg int_we_reg, int_we_next;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_addr_reg <= {(BRAM_ADDR_WIDTH){1'b0}};
+      int_data_reg <= {(BRAM_DATA_WIDTH){1'b0}};
+      int_case_reg <= 2'd0;
+      int_tready_reg <= 1'b1;
+      int_we_reg <= 1'b0;
+    end
+    else
+    begin
+      int_addr_reg <= int_addr_next;
+      int_data_reg <= int_data_next;
+      int_case_reg <= int_case_next;
+      int_tready_reg <= int_tready_next;
+      int_we_reg <= int_we_next;
+    end
+  end
+
+  always @*
+  begin
+    int_addr_next = int_addr_reg;
+    int_data_next = int_data_reg;
+    int_case_next = int_case_reg;
+    int_tready_next = int_tready_reg;
+    int_we_next = int_we_reg;
+
+    case(int_case_reg)
+      2'd0:
+      begin
+        if(s_axis_tvalid)
+        begin
+          int_addr_next = s_axis_tdata[BRAM_ADDR_WIDTH-1:0];
+          int_tready_next = 1'b0;
+          int_case_next = 2'd1;
+        end
+      end
+      2'd1:
+      begin
+        int_data_next = b_bram_rdata + 1'b1;
+        int_we_next = ~&b_bram_rdata;
+        int_case_next = 2'd2;
+      end
+      2'd2:
+      begin
+        int_tready_next = 1'b1;
+        int_we_next = 1'b0;
+        int_case_next = 2'd0;
+      end
+    endcase
+  end
+
+  assign s_axis_tready = int_tready_reg;
+
+  assign b_bram_clk = aclk;
+  assign b_bram_rst = ~aresetn;
+  assign b_bram_en = int_we_reg | s_axis_tvalid;
+  assign b_bram_we = {(BRAM_DATA_WIDTH/8){int_we_reg}};
+  assign b_bram_addr = int_we_reg ? int_addr_reg : s_axis_tdata[BRAM_ADDR_WIDTH-1:0];
+  assign b_bram_wdata = int_data_reg;
+
+endmodule

+ 188 - 0
cores/axis_i2s.v

@@ -0,0 +1,188 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_i2s #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  // I2S signals
+  inout  wire [3:0]                  gpio_data,
+
+  // ALEX signals
+  input wire                         alex_flag,
+  input wire [3:0]                   alex_data,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  localparam I2S_DATA_WIDTH = AXIS_TDATA_WIDTH / 2;
+  localparam CNTR_WIDTH = 6;
+
+  reg [2:0] int_bclk_reg, int_lrclk_reg;
+  reg [1:0] int_data_reg;
+
+  reg [1:0] adc_case_reg, adc_case_next;
+  reg [CNTR_WIDTH-1:0] adc_cntr_reg, adc_cntr_next;
+  reg [I2S_DATA_WIDTH-1:0] adc_data_reg, adc_data_next;
+  reg [AXIS_TDATA_WIDTH-1:0] adc_tdata_reg, adc_tdata_next;
+  reg adc_tvalid_reg, adc_tvalid_next;
+
+  reg [1:0] dac_case_reg, dac_case_next;
+  reg [I2S_DATA_WIDTH-1:0] dac_data_reg, dac_data_next;
+  reg [AXIS_TDATA_WIDTH-1:0] dac_tdata_reg, dac_tdata_next;
+
+  wire i2s_bclk, i2s_lrclk, i2s_adc_data, i2s_dac_data;
+
+  wire int_bclk_posedge, int_bclk_negedge, int_lrclk_negedge;
+
+  wire not_alex_flag = ~alex_flag;
+
+  IOBUF buf_bclk (.O(i2s_bclk), .IO(gpio_data[0]), .I(alex_data[0]), .T(not_alex_flag));
+  IOBUF buf_adc_data (.O(i2s_adc_data), .IO(gpio_data[1]), .I(alex_data[1]), .T(not_alex_flag));
+  IOBUF buf_dac_data (.O(), .IO(gpio_data[2]), .I(alex_flag ? alex_data[2] : i2s_dac_data), .T(1'b0));
+  IOBUF buf_lrclk (.O(i2s_lrclk), .IO(gpio_data[3]), .I(alex_data[3]), .T(not_alex_flag));
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_bclk_reg <= 3'd0;
+      int_lrclk_reg <= 3'd0;
+      int_data_reg <= 2'd0;
+      adc_case_reg <= 2'd0;
+      adc_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      adc_data_reg <= {(I2S_DATA_WIDTH){1'b0}};
+      adc_tdata_reg <= {(AXIS_TDATA_WIDTH){1'b0}};
+      adc_tvalid_reg <= 1'b0;
+      dac_case_reg <= 2'd0;
+      dac_data_reg <= {(I2S_DATA_WIDTH){1'b0}};
+      dac_tdata_reg <= {(AXIS_TDATA_WIDTH){1'b0}};
+    end
+    else
+    begin
+      int_bclk_reg <= {int_bclk_reg[1:0], i2s_bclk};
+      int_lrclk_reg <= {int_lrclk_reg[1:0], i2s_lrclk};
+      int_data_reg <= {int_data_reg[0], i2s_adc_data};
+      adc_case_reg <= adc_case_next;
+      adc_cntr_reg <= adc_cntr_next;
+      adc_data_reg <= adc_data_next;
+      adc_tdata_reg <= adc_tdata_next;
+      adc_tvalid_reg <= adc_tvalid_next;
+      dac_case_reg <= dac_case_next;
+      dac_data_reg <= dac_data_next;
+      dac_tdata_reg <= dac_tdata_next;
+    end
+  end
+
+  assign int_bclk_posedge = int_bclk_reg[1] & ~int_bclk_reg[2];
+  assign int_bclk_negedge = ~int_bclk_reg[1] & int_bclk_reg[2];
+  assign int_lrclk_negedge = ~int_lrclk_reg[1] & int_lrclk_reg[2];
+
+  always @*
+  begin
+    adc_case_next = adc_case_reg;
+    adc_cntr_next = adc_cntr_reg;
+    adc_data_next = adc_data_reg;
+    adc_tdata_next = adc_tdata_reg;
+    adc_tvalid_next = adc_tvalid_reg;
+
+    if(int_bclk_posedge & (adc_cntr_reg < I2S_DATA_WIDTH))
+    begin
+      adc_data_next = {adc_data_reg[I2S_DATA_WIDTH-2:0], int_data_reg[1]};
+      adc_cntr_next = adc_cntr_reg + 1'b1;
+    end
+
+    if(m_axis_tready & adc_tvalid_reg)
+    begin
+      adc_tvalid_next = 1'b0;
+    end
+
+    case(adc_case_reg)
+      2'd0:
+      begin
+        if(int_lrclk_reg[1] ^ int_lrclk_reg[2])
+        begin
+          adc_case_next = 2'd1;
+        end
+      end
+      2'd1:
+      begin
+        if(int_bclk_posedge)
+        begin
+          adc_cntr_next = {(CNTR_WIDTH){1'b0}};
+          adc_case_next = 2'd2;
+        end
+      end
+      2'd2:
+      begin
+        if(int_bclk_posedge)
+        begin
+          adc_tvalid_next = ~int_lrclk_reg[1];
+          adc_tdata_next = {adc_tdata_reg[I2S_DATA_WIDTH-1:0], adc_data_reg};
+          adc_case_next = 2'd0;
+        end
+      end
+    endcase
+  end
+
+  always @*
+  begin
+    dac_case_next = dac_case_reg;
+    dac_data_next = dac_data_reg;
+    dac_tdata_next = dac_tdata_reg;
+
+    if(int_bclk_negedge)
+    begin
+      dac_data_next = {dac_data_reg[I2S_DATA_WIDTH-2:0], 1'b0};
+    end
+
+    if(int_lrclk_negedge)
+    begin
+      dac_tdata_next = s_axis_tvalid ? s_axis_tdata : {(AXIS_TDATA_WIDTH){1'b0}};
+    end
+
+    case(dac_case_reg)
+      2'd0:
+      begin
+        if(int_lrclk_reg[1] ^ int_lrclk_reg[2])
+        begin
+          dac_case_next = 2'd1;
+        end
+      end
+      2'd1:
+      begin
+        if(int_bclk_posedge)
+        begin
+          dac_case_next = 2'd2;
+        end
+      end
+      2'd2:
+      begin
+        if(int_bclk_negedge)
+        begin
+          dac_data_next = int_lrclk_reg[1] ? dac_tdata_reg[I2S_DATA_WIDTH-1:0] : dac_tdata_reg[AXIS_TDATA_WIDTH-1:I2S_DATA_WIDTH];
+          dac_case_next = 2'd0;
+        end
+      end
+    endcase
+  end
+
+  assign i2s_dac_data = dac_data_reg[I2S_DATA_WIDTH-1];
+  assign s_axis_tready = int_lrclk_negedge;
+  assign m_axis_tdata = adc_tdata_reg;
+  assign m_axis_tvalid = adc_tvalid_reg;
+
+endmodule

+ 107 - 0
cores/axis_iir_filter.v

@@ -0,0 +1,107 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_iir_filter
+(
+  // System signals
+  input  wire        aclk,
+  input  wire        aresetn,
+
+  input  wire [79:0] cfg_data,
+
+  // Slave side
+  input  wire [15:0] s_axis_tdata,
+  input  wire        s_axis_tvalid,
+  output wire        s_axis_tready,
+
+  // Master side
+  output wire [15:0] m_axis_tdata,
+  output wire        m_axis_tvalid,
+  input  wire        m_axis_tready
+);
+
+  wire [47:0] int_p_wire [2:0];
+
+  wire [15:0] int_data_wire;
+  wire [5:0] int_valid_wire, int_ready_wire;
+
+  genvar j;
+
+  assign int_valid_wire[0] = s_axis_tvalid;
+  assign s_axis_tready = int_ready_wire[0];
+
+  assign int_data_wire = $signed(int_p_wire[2][47:25]) < $signed(cfg_data[63:48]) ? cfg_data[63:48] : $signed(int_p_wire[2][47:25]) > $signed(cfg_data[79:64]) ? cfg_data[79:64] : int_p_wire[2][40:25];
+
+  generate
+    for(j = 0; j < 5; j = j + 1)
+    begin : BUFFERS
+      output_buffer #(
+        .DATA_WIDTH(0)
+      ) output_buffer_inst (
+        .aclk(aclk), .aresetn(aresetn),
+        .in_valid(int_valid_wire[j]), .in_ready(int_ready_wire[j]),
+        .out_valid(int_valid_wire[j+1]), .out_ready(int_ready_wire[j+1])
+      );
+    end
+  endgenerate
+
+  inout_buffer #(
+    .DATA_WIDTH(16)
+  ) buf_0 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_data_wire), .in_valid(int_valid_wire[5]), .in_ready(int_ready_wire[5]),
+    .out_data(m_axis_tdata), .out_valid(m_axis_tvalid), .out_ready(m_axis_tready)
+  );
+
+  DSP48E1 #(
+    .ALUMODEREG(0), .CARRYINSELREG(0), .INMODEREG(0), .OPMODEREG(0),
+    .CREG(0), .CARRYINREG(0), .MREG(1), .PREG(1)
+  ) dsp_0 (
+    .CLK(aclk),
+    .RSTA(1'b0), .RSTB(1'b0),
+    .RSTM(1'b0), .RSTP(1'b0),
+    .CEA2(int_ready_wire[0]), .CEB2(int_ready_wire[0]),
+    .CED(1'b0), .CEAD(1'b0),
+    .CEM(int_ready_wire[1]), .CEP(int_ready_wire[2]),
+    .ALUMODE(4'b0000), .CARRYINSEL(3'b000), .INMODE(5'b00000), .OPMODE(7'b0000101),
+    .A({{(5){s_axis_tdata[15]}}, s_axis_tdata, 9'd0}),
+    .B(cfg_data[15:0]),
+    .CARRYIN(1'b0),
+    .P(int_p_wire[0])
+  );
+
+  DSP48E1 #(
+    .ALUMODEREG(0), .CARRYINSELREG(0), .INMODEREG(0), .OPMODEREG(0),
+    .AREG(0), .ACASCREG(0), .BREG(0), .BCASCREG(0),
+    .CREG(0), .CARRYINREG(0), .MREG(0), .PREG(1)
+  ) dsp_1 (
+    .CLK(aclk),
+    .RSTP(1'b0),
+    .CED(1'b0), .CEAD(1'b0),
+    .CEP(int_ready_wire[3]),
+    .ALUMODE(4'b0000), .CARRYINSEL(3'b000), .INMODE(5'b00000), .OPMODE(7'b0110101),
+    .A(int_p_wire[1][45:16]),
+    .B(cfg_data[31:16]),
+    .C(int_p_wire[0]),
+    .CARRYIN(1'b0),
+    .P(int_p_wire[1])
+  );
+
+  DSP48E1 #(
+    .ALUMODEREG(0), .CARRYINSELREG(0), .INMODEREG(0), .OPMODEREG(0),
+    .AREG(0), .ACASCREG(0), .BREG(0), .BCASCREG(0),
+    .CREG(0), .CARRYINREG(0), .MREG(0), .PREG(1)
+  ) dsp_2 (
+    .CLK(aclk),
+    .RSTP(1'b0),
+    .CED(1'b0), .CEAD(1'b0),
+    .CEP(int_ready_wire[4]),
+    .ALUMODE(4'b0000), .CARRYINSEL(3'b000), .INMODE(5'b00000), .OPMODE(7'b0110101),
+    .A(int_p_wire[2][45:16]),
+    .B(cfg_data[47:32]),
+    .C(int_p_wire[1]),
+    .CARRYIN(1'b0),
+    .P(int_p_wire[2])
+  );
+
+endmodule

+ 89 - 0
cores/axis_interpolator.v

@@ -0,0 +1,89 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_interpolator #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter integer CNTR_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [CNTR_WIDTH-1:0]       cfg_data,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  reg [AXIS_TDATA_WIDTH-1:0] int_tdata_reg, int_tdata_next;
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg int_tvalid_reg, int_tvalid_next;
+  reg int_tready_reg, int_tready_next;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_tdata_reg <= {(AXIS_TDATA_WIDTH){1'b0}};
+      int_tvalid_reg <= 1'b0;
+      int_tready_reg <= 1'b0;
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+    end
+    else
+    begin
+      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
+  end
+
+  always @*
+  begin
+    int_tdata_next = int_tdata_reg;
+    int_tvalid_next = int_tvalid_reg;
+    int_tready_next = int_tready_reg;
+    int_cntr_next = int_cntr_reg;
+
+    if(s_axis_tvalid & ~int_tvalid_reg)
+    begin
+      int_tdata_next = s_axis_tdata;
+      int_tvalid_next = 1'b1;
+      int_tready_next = 1'b1;
+    end
+
+    if(m_axis_tready & int_tvalid_reg)
+    begin
+      if(int_cntr_reg < cfg_data)
+      begin
+        int_cntr_next = int_cntr_reg + 1'b1;
+      end
+      else
+      begin
+        int_cntr_next = {(CNTR_WIDTH){1'b0}};
+        int_tdata_next = s_axis_tdata;
+        int_tvalid_next = s_axis_tvalid;
+        int_tready_next = s_axis_tvalid;
+      end
+    end
+
+    if(s_axis_tvalid & int_tready_reg)
+    begin
+      int_tready_next = 1'b0;
+    end
+  end
+
+  assign s_axis_tready = int_tready_reg;
+  assign m_axis_tdata = int_tdata_reg;
+  assign m_axis_tvalid = int_tvalid_reg;
+
+endmodule

+ 111 - 0
cores/axis_keyer.v

@@ -0,0 +1,111 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_keyer #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter integer BRAM_DATA_WIDTH = 32,
+  parameter integer BRAM_ADDR_WIDTH = 10
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [BRAM_ADDR_WIDTH-1:0]  cfg_data,
+  input  wire                        key_flag,
+
+  // Master side
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid,
+  input  wire                        m_axis_tready,
+
+  // BRAM port
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram CLK" *)
+  output wire                        b_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram RST" *)
+  output wire                        b_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram EN" *)
+  output wire                        b_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram ADDR" *)
+  output wire [BRAM_ADDR_WIDTH-1:0]  b_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram DOUT" *)
+  input  wire [BRAM_DATA_WIDTH-1:0]  b_bram_rdata
+);
+
+  reg [BRAM_ADDR_WIDTH-1:0] int_addr_reg, int_addr_next;
+  reg [BRAM_ADDR_WIDTH-1:0] int_data_reg;
+  reg int_enbl_reg, int_enbl_next;
+
+  wire [1:0] int_valid_wire, int_ready_wire;
+  wire [1:0] int_comp_wire;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_addr_reg <= {(BRAM_ADDR_WIDTH){1'b0}};
+      int_data_reg <= {(BRAM_ADDR_WIDTH){1'b0}};
+      int_enbl_reg <= 1'b0;
+    end
+    else
+    begin
+      int_addr_reg <= int_addr_next;
+      int_data_reg <= cfg_data;
+      int_enbl_reg <= int_enbl_next;
+    end
+  end
+
+
+  assign int_comp_wire = {|int_addr_reg, int_addr_reg < int_data_reg};
+
+  assign int_valid_wire[0] = 1'b1;
+
+  always @*
+  begin
+    int_addr_next = int_addr_reg;
+    int_enbl_next = int_enbl_reg;
+
+    if(~int_enbl_reg & ~int_comp_wire[1] & key_flag)
+    begin
+      int_enbl_next = 1'b1;
+    end
+
+    if(int_ready_wire[0] & int_enbl_reg & int_comp_wire[0])
+    begin
+      int_addr_next = int_addr_reg + 1'b1;
+    end
+
+    if(int_ready_wire[0] & int_enbl_reg & ~int_comp_wire[0] & ~key_flag)
+    begin
+      int_enbl_next = 1'b0;
+    end
+
+    if(int_ready_wire[0] & ~int_enbl_reg & int_comp_wire[1])
+    begin
+      int_addr_next = int_addr_reg - 1'b1;
+    end
+  end
+
+  output_buffer #(
+    .DATA_WIDTH(0)
+  ) buf_0 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_valid(int_valid_wire[0]), .in_ready(int_ready_wire[0]),
+    .out_valid(int_valid_wire[1]), .out_ready(int_ready_wire[1])
+  );
+
+  inout_buffer #(
+    .DATA_WIDTH(AXIS_TDATA_WIDTH)
+  ) buf_1 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(b_bram_rdata), .in_valid(int_valid_wire[1]), .in_ready(int_ready_wire[1]),
+    .out_data(m_axis_tdata), .out_valid(m_axis_tvalid), .out_ready(m_axis_tready)
+  );
+
+  assign b_bram_clk = aclk;
+  assign b_bram_rst = ~aresetn;
+  assign b_bram_en = int_ready_wire[0];
+  assign b_bram_addr = int_addr_reg;
+
+endmodule

+ 79 - 0
cores/axis_lfsr.v

@@ -0,0 +1,79 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_lfsr #
+(
+  parameter integer AXIS_TDATA_WIDTH = 64,
+  parameter         HAS_TREADY = "FALSE"
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  reg [AXIS_TDATA_WIDTH-1:0] int_lfsr_reg, int_lfsr_next;
+  reg int_enbl_reg, int_enbl_next;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_lfsr_reg <= 64'h85fac8a1658d6f0d;
+      int_enbl_reg <= 1'b0;
+    end
+    else
+    begin
+      int_lfsr_reg <= int_lfsr_next;
+      int_enbl_reg <= int_enbl_next;
+    end
+  end
+
+  generate
+    if(HAS_TREADY == "TRUE")
+    begin : HAS_TREADY
+      always @*
+      begin
+        int_lfsr_next = int_lfsr_reg;
+        int_enbl_next = int_enbl_reg;
+
+        if(~int_enbl_reg)
+        begin
+          int_enbl_next = 1'b1;
+        end
+
+        if(int_enbl_reg & m_axis_tready)
+        begin
+          int_lfsr_next = {int_lfsr_reg[62:0], int_lfsr_reg[62] ~^ int_lfsr_reg[61]};
+        end
+      end
+    end
+    else
+    begin : NO_TREADY
+      always @*
+      begin
+        int_lfsr_next = int_lfsr_reg;
+        int_enbl_next = int_enbl_reg;
+
+        if(~int_enbl_reg)
+        begin
+          int_enbl_next = 1'b1;
+        end
+
+        if(int_enbl_reg)
+        begin
+          int_lfsr_next = {int_lfsr_reg[62:0], int_lfsr_reg[62] ~^ int_lfsr_reg[61]};
+        end
+      end
+    end
+  endgenerate
+
+  assign m_axis_tdata = int_lfsr_reg;
+  assign m_axis_tvalid = int_enbl_reg;
+
+endmodule

+ 87 - 0
cores/axis_maxabs_finder.v

@@ -0,0 +1,87 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_maxabs_finder #
+(
+  parameter integer AXIS_TDATA_WIDTH = 16,
+  parameter integer CNTR_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [CNTR_WIDTH-1:0]       cfg_data,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  reg [AXIS_TDATA_WIDTH-1:0] int_max_reg, int_max_next;
+  reg [AXIS_TDATA_WIDTH-1:0] int_tdata_reg, int_tdata_next;
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg int_tvalid_reg, int_tvalid_next;
+
+  wire [AXIS_TDATA_WIDTH-1:0] int_abs_wire;
+  wire int_comp_wire;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_max_reg <= {(AXIS_TDATA_WIDTH){1'b0}};
+      int_tdata_reg <= {(AXIS_TDATA_WIDTH){1'b0}};
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_tvalid_reg <= 1'b0;
+    end
+    else
+    begin
+      int_max_reg <= int_max_next;
+      int_tdata_reg <= int_tdata_next;
+      int_cntr_reg <= int_cntr_next;
+      int_tvalid_reg <= int_tvalid_next;
+    end
+  end
+
+  assign int_comp_wire = int_cntr_reg < cfg_data;
+  assign int_abs_wire = s_axis_tdata[AXIS_TDATA_WIDTH-1] ? ~s_axis_tdata : s_axis_tdata;
+
+  always @*
+  begin
+    int_max_next = int_max_reg;
+    int_tdata_next = int_tdata_reg;
+    int_cntr_next = int_cntr_reg;
+    int_tvalid_next = int_tvalid_reg;
+
+    if(s_axis_tvalid & int_comp_wire)
+    begin
+      int_max_next = int_abs_wire > int_max_reg ? int_abs_wire : int_max_reg;
+      int_cntr_next = int_cntr_reg + 1'b1;
+    end
+
+    if(s_axis_tvalid & ~int_comp_wire)
+    begin
+      int_max_next = {(AXIS_TDATA_WIDTH){1'b0}};
+      int_tdata_next = int_max_reg;
+      int_cntr_next = {(CNTR_WIDTH){1'b0}};
+      int_tvalid_next = 1'b1;
+    end
+
+    if(m_axis_tready & int_tvalid_reg)
+    begin
+      int_tvalid_next = 1'b0;
+    end
+  end
+
+  assign s_axis_tready = 1'b1;
+  assign m_axis_tdata = int_tdata_reg;
+  assign m_axis_tvalid = int_tvalid_reg;
+
+endmodule

+ 133 - 0
cores/axis_misc_reader.v

@@ -0,0 +1,133 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_misc_reader #
+(
+  parameter integer S_AXIS_TDATA_WIDTH = 40,
+  parameter integer M_AXIS_TDATA_WIDTH = 32,
+  parameter integer MISC_WIDTH = 8
+)
+(
+  // System signals
+  input  wire                          aclk,
+  input  wire                          aresetn,
+
+  output wire [MISC_WIDTH-1:0]         misc_data,
+
+  // Slave side
+  output wire                          s_axis_tready,
+  input  wire [S_AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                          s_axis_tvalid,
+
+  // Master side
+  input  wire                          m_axis_tready,
+  output wire [M_AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                          m_axis_tvalid
+);
+
+  reg int_enbl_reg;
+  reg [MISC_WIDTH-1:0] int_misc_reg;
+
+  reg [39:0] pulse_counter;
+  reg key_latch;
+  reg [53:0] uart_buffer;
+  reg [7:0] uart_pos;
+  reg [5:0] uart_prescaler;
+
+  reg [39:0] reflect_buffer;
+  reg [7:0] reflect_pos;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_enbl_reg <= 1'b0;
+      pulse_counter <= 40'd0;
+      key_latch <= 1'b0;
+      uart_pos <= 8'd0;
+      uart_buffer <= 54'd0;
+      uart_prescaler <= 6'd0;
+      reflect_pos <= 8'd0;
+    end
+    else
+    begin
+      int_enbl_reg <= 1'b1;
+      if(s_axis_tvalid & s_axis_tready)
+      begin
+        int_misc_reg[MISC_WIDTH-1:3] <= s_axis_tdata[S_AXIS_TDATA_WIDTH-1:S_AXIS_TDATA_WIDTH-MISC_WIDTH+3];
+
+        int_misc_reg[0] <= uart_buffer[uart_pos];
+        int_misc_reg[1] <= reflect_buffer[reflect_pos];
+        int_misc_reg[2] <= reflect_pos != 0;
+
+        // fast metadata reflect
+        if(s_axis_tdata[S_AXIS_TDATA_WIDTH-1] & (~key_latch))
+        begin
+          // every pulse
+          reflect_pos <= 8'd0;
+          reflect_buffer <= pulse_counter;
+
+          // increment pulse counter
+          pulse_counter <= pulse_counter + 1'b1;
+        end
+        else
+        begin
+          reflect_pos <= reflect_pos < 39 ? reflect_pos + 1'b1 : reflect_pos;
+        end
+
+        if(s_axis_tdata[S_AXIS_TDATA_WIDTH-1] & (~key_latch) & (pulse_counter[3:0] == 4'h0))
+        begin
+          // beginning of every 16th pulse
+          // copy data to uart buffer
+
+          uart_buffer[0] <= 1'b0; // start bit
+          uart_buffer[7:1] <= pulse_counter[10:4];
+          uart_buffer[8] <= 1'b1; // protocol signalization - first byte
+          uart_buffer[9] <= 1'b1; // stop bit
+          uart_buffer[10] <= 1'b1; // pad bit
+          uart_buffer[11] <= 1'b0; // start bit
+          uart_buffer[18:12] <= pulse_counter[17:11];
+          uart_buffer[20] <= 1'b1; // stop bit
+          uart_buffer[21] <= 1'b1; // pad bit
+          uart_buffer[22] <= 1'b0; // start bit
+          uart_buffer[29:23] <= pulse_counter[24:18];
+          uart_buffer[31] <= 1'b1; // stop bit
+          uart_buffer[32] <= 1'b1; // pad bit
+          uart_buffer[33] <= 1'b0; // start bit
+          uart_buffer[40:34] <= pulse_counter[32:25];
+          uart_buffer[42] <= 1'b1; // stop bit
+          uart_buffer[43] <= 1'b1; // pad bit
+          uart_buffer[44] <= 1'b0; // start bit
+          uart_buffer[51:45] <= pulse_counter[39:33];
+          uart_buffer[53] <= 1'b1; // stop bit
+
+          // reset uart transmitter position
+          uart_pos <= 8'd0;
+          uart_prescaler <= 6'd0;
+        end
+        else
+        begin
+          // not the beginning of pulse - advance UART.
+          // This will truncate the transmission if the next pulse is received too early;
+          // the caller is responsible to sanitize this.
+          if(uart_prescaler == 62)
+          begin
+            uart_pos <= uart_pos < 53 ? uart_pos + 1'b1 : uart_pos; // transmit stop bit forever after the end of the transmission
+          end
+
+          uart_prescaler <= uart_prescaler < 62 ? uart_prescaler + 1'b1 : 6'd0;
+        end
+
+        key_latch <= s_axis_tdata[S_AXIS_TDATA_WIDTH-1];
+      end
+    end
+  end
+
+  assign s_axis_tready = int_enbl_reg & m_axis_tready;
+
+  assign misc_data = int_misc_reg;
+
+  assign m_axis_tdata = s_axis_tdata[M_AXIS_TDATA_WIDTH-1:0];
+  assign m_axis_tvalid = int_enbl_reg & s_axis_tvalid;
+
+endmodule

+ 82 - 0
cores/axis_misc_writer.v

@@ -0,0 +1,82 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_misc_writer #
+(
+  parameter integer S_AXIS_TDATA_WIDTH = 32,
+  parameter integer M_AXIS_TDATA_WIDTH = 64,
+  parameter integer CNTR_WIDTH = 16,
+  parameter integer MISC_WIDTH = 16
+)
+(
+  // System signals
+  input  wire                          aclk,
+  input  wire                          aresetn,
+
+  input  wire [CNTR_WIDTH-1:0]         cfg_data,
+  input  wire [MISC_WIDTH-1:0]         misc_data,
+
+  // Slave side
+  output wire                          s_axis_tready,
+  input  wire [S_AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                          s_axis_tvalid,
+
+  // Master side
+  input  wire                          m_axis_tready,
+  output wire [M_AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                          m_axis_tvalid
+);
+
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg [CNTR_WIDTH-1:0] int_data_reg;
+  reg int_enbl_reg, int_enbl_next;
+
+  wire int_comp_wire, int_tvalid_wire, int_last_wire;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_data_reg <= {(CNTR_WIDTH){1'b0}};
+      int_enbl_reg <= 1'b0;
+    end
+    else
+    begin
+      int_cntr_reg <= int_cntr_next;
+      int_data_reg <= cfg_data;
+      int_enbl_reg <= int_enbl_next;
+    end
+  end
+
+  assign int_comp_wire = int_cntr_reg < int_data_reg;
+  assign int_tvalid_wire = int_enbl_reg & s_axis_tvalid;
+  assign int_last_wire = ~int_comp_wire;
+
+  always @*
+  begin
+    int_cntr_next = int_cntr_reg;
+    int_enbl_next = int_enbl_reg;
+
+    if(~int_enbl_reg & int_comp_wire)
+    begin
+      int_enbl_next = 1'b1;
+    end
+
+    if(m_axis_tready & int_tvalid_wire & int_comp_wire)
+    begin
+      int_cntr_next = int_cntr_reg + 1'b1;
+    end
+
+    if(m_axis_tready & int_tvalid_wire & int_last_wire)
+    begin
+      int_cntr_next = {(CNTR_WIDTH){1'b0}};
+    end
+  end
+
+  assign s_axis_tready = int_enbl_reg & m_axis_tready;
+
+  assign m_axis_tdata = {misc_data, int_cntr_reg, s_axis_tdata};
+  assign m_axis_tvalid = int_tvalid_wire;
+
+endmodule

+ 29 - 0
cores/axis_negator.v

@@ -0,0 +1,29 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_negator #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+
+  input  wire                        cfg_flag,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  assign s_axis_tready = m_axis_tready;
+  assign m_axis_tdata = cfg_flag ? -$signed(s_axis_tdata) : s_axis_tdata;
+  assign m_axis_tvalid = s_axis_tvalid;
+
+endmodule

+ 93 - 0
cores/axis_oscilloscope.v

@@ -0,0 +1,93 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_oscilloscope #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter integer CNTR_WIDTH = 12
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire                        run_flag,
+  input  wire                        trg_flag,
+
+  input  wire [CNTR_WIDTH-1:0]       pre_data,
+  input  wire [CNTR_WIDTH-1:0]       tot_data,
+
+  output wire [CNTR_WIDTH:0]         sts_data,
+
+  // Slave side
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+  output wire                        s_axis_tready,
+
+  // Master side
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  reg [CNTR_WIDTH-1:0] int_addr_reg, int_cntr_reg;
+  reg int_run_reg, int_pre_reg, int_trg_reg, int_tot_reg;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_addr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_run_reg <= 1'b0;
+      int_pre_reg <= 1'b0;
+      int_trg_reg <= 1'b0;
+      int_tot_reg <= 1'b0;
+    end
+    else if(int_run_reg)
+    begin
+      if(int_pre_reg & trg_flag)
+      begin
+        int_trg_reg <= 1'b1;
+      end
+
+      if(s_axis_tvalid)
+      begin
+        int_cntr_reg <= int_cntr_reg + 1'b1;
+
+        if(int_cntr_reg == pre_data)
+        begin
+          int_pre_reg <= 1'b1;
+        end
+
+        if(~int_tot_reg & int_trg_reg)
+        begin
+          int_addr_reg <= int_cntr_reg;
+          int_cntr_reg <= pre_data + int_cntr_reg[5:0];
+          int_tot_reg <= 1'b1;
+        end
+
+        if(int_tot_reg & (int_cntr_reg == tot_data))
+        begin
+          int_run_reg <= 1'b0;
+        end
+      end
+    end
+    else if(run_flag)
+    begin
+      int_addr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_run_reg <= 1'b1;
+      int_pre_reg <= 1'b0;
+      int_trg_reg <= 1'b0;
+      int_tot_reg <= 1'b0;
+    end
+  end
+
+  assign sts_data = {int_addr_reg, int_run_reg};
+
+  assign s_axis_tready = 1'b1;
+
+  assign m_axis_tdata = s_axis_tdata;
+  assign m_axis_tvalid = int_run_reg & s_axis_tvalid;
+
+endmodule

+ 120 - 0
cores/axis_packetizer.v

@@ -0,0 +1,120 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_packetizer #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter integer CNTR_WIDTH = 32,
+  parameter         CONTINUOUS = "FALSE",
+  parameter         ALWAYS_READY = "FALSE"
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [CNTR_WIDTH-1:0]       cfg_data,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid,
+  output wire                        m_axis_tlast
+);
+
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg [CNTR_WIDTH-1:0] int_data_reg;
+  reg int_enbl_reg, int_enbl_next;
+
+  wire int_comp_wire, int_tvalid_wire, int_tlast_wire;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_data_reg <= {(CNTR_WIDTH){1'b0}};
+      int_enbl_reg <= 1'b0;
+    end
+    else
+    begin
+      int_cntr_reg <= int_cntr_next;
+      int_data_reg <= cfg_data;
+      int_enbl_reg <= int_enbl_next;
+    end
+  end
+
+  assign int_comp_wire = int_cntr_reg < int_data_reg;
+  assign int_tvalid_wire = int_enbl_reg & s_axis_tvalid;
+  assign int_tlast_wire = ~int_comp_wire;
+
+  generate
+    if(CONTINUOUS == "TRUE")
+    begin : CONTINUE
+      always @*
+      begin
+        int_cntr_next = int_cntr_reg;
+        int_enbl_next = int_enbl_reg;
+
+        if(~int_enbl_reg & int_comp_wire)
+        begin
+          int_enbl_next = 1'b1;
+        end
+
+        if(m_axis_tready & int_tvalid_wire & int_comp_wire)
+        begin
+          int_cntr_next = int_cntr_reg + 1'b1;
+        end
+
+        if(m_axis_tready & int_tvalid_wire & int_tlast_wire)
+        begin
+          int_cntr_next = {(CNTR_WIDTH){1'b0}};
+        end
+      end
+    end
+    else
+    begin : STOP
+      always @*
+      begin
+        int_cntr_next = int_cntr_reg;
+        int_enbl_next = int_enbl_reg;
+
+        if(~int_enbl_reg & int_comp_wire)
+        begin
+          int_enbl_next = 1'b1;
+        end
+
+        if(m_axis_tready & int_tvalid_wire & int_comp_wire)
+        begin
+          int_cntr_next = int_cntr_reg + 1'b1;
+        end
+
+        if(m_axis_tready & int_tvalid_wire & int_tlast_wire)
+        begin
+          int_enbl_next = 1'b0;
+        end
+      end
+    end
+  endgenerate
+
+  generate
+    if(ALWAYS_READY == "TRUE")
+    begin : READY
+      assign s_axis_tready = 1'b1;
+    end
+    else
+    begin : BLOCKING
+      assign s_axis_tready = int_enbl_reg & m_axis_tready;
+    end
+  endgenerate
+
+  assign m_axis_tdata = s_axis_tdata;
+  assign m_axis_tvalid = int_tvalid_wire;
+  assign m_axis_tlast = int_enbl_reg & int_tlast_wire;
+
+endmodule

+ 80 - 0
cores/axis_pdm.v

@@ -0,0 +1,80 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_pdm #
+(
+  parameter integer AXIS_TDATA_WIDTH = 16,
+  parameter integer CNTR_WIDTH = 8
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [CNTR_WIDTH-1:0]       cfg_data,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  output wire                        dout
+);
+
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg [AXIS_TDATA_WIDTH-1:0] int_data_reg, int_data_next;
+  reg [AXIS_TDATA_WIDTH:0] int_acc_reg, int_acc_next;
+  reg int_tready_reg, int_tready_next;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_data_reg <= {(AXIS_TDATA_WIDTH){1'b0}};
+      int_acc_reg <= {(AXIS_TDATA_WIDTH+1){1'b0}};
+      int_tready_reg <= 1'b0;
+    end
+    else
+    begin
+      int_cntr_reg <= int_cntr_next;
+      int_data_reg <= int_data_next;
+      int_acc_reg <= int_acc_next;
+      int_tready_reg <= int_tready_next;
+    end
+  end
+
+  always @*
+  begin
+    int_cntr_next = int_cntr_reg;
+    int_data_next = int_data_reg;
+    int_acc_next = int_acc_reg;
+    int_tready_next = int_tready_reg;
+
+    if(int_cntr_reg < cfg_data)
+    begin
+      int_cntr_next = int_cntr_reg + 1'b1;
+    end
+    else
+    begin
+      int_cntr_next = {(CNTR_WIDTH){1'b0}};
+      int_tready_next = 1'b1;
+    end
+
+    if(int_tready_reg)
+    begin
+      int_tready_next = 1'b0;
+    end
+
+    if(int_tready_reg & s_axis_tvalid)
+    begin
+      int_data_next = {~s_axis_tdata[AXIS_TDATA_WIDTH-1], s_axis_tdata[AXIS_TDATA_WIDTH-2:0]};
+      int_acc_next = int_acc_reg[AXIS_TDATA_WIDTH-1:0] + int_data_reg;
+    end
+  end
+
+  assign s_axis_tready = int_tready_reg;
+
+  assign dout = int_acc_reg[AXIS_TDATA_WIDTH];
+
+endmodule

+ 58 - 0
cores/axis_phase_generator.v

@@ -0,0 +1,58 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_phase_generator #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter integer PHASE_WIDTH = 30
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [PHASE_WIDTH-1:0]      cfg_data,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  reg [PHASE_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg int_enbl_reg, int_enbl_next;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_cntr_reg <= {(PHASE_WIDTH){1'b0}};
+      int_enbl_reg <= 1'b0;
+    end
+    else
+    begin
+      int_cntr_reg <= int_cntr_next;
+      int_enbl_reg <= int_enbl_next;
+    end
+  end
+
+  always @*
+  begin
+    int_cntr_next = int_cntr_reg;
+    int_enbl_next = int_enbl_reg;
+
+    if(~int_enbl_reg)
+    begin
+      int_enbl_next = 1'b1;
+    end
+
+    if(int_enbl_reg & m_axis_tready)
+    begin
+      int_cntr_next = int_cntr_reg + cfg_data;
+    end
+  end
+
+  assign m_axis_tdata = {{(AXIS_TDATA_WIDTH-PHASE_WIDTH){int_cntr_reg[PHASE_WIDTH-1]}}, int_cntr_reg};
+  assign m_axis_tvalid = int_enbl_reg;
+
+endmodule

+ 59 - 0
cores/axis_pps_counter.v

@@ -0,0 +1,59 @@
+`timescale 1 ns / 1 ps
+
+module axis_pps_counter #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter integer CNTR_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input wire                         pps_data,
+
+  // Master side
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  reg [CNTR_WIDTH-1:0] int_cntr_reg;
+  reg int_enbl_reg;
+  reg [1:0] int_data_reg;
+
+  wire int_edge_wire, int_pps_wire;
+
+  xpm_cdc_single #(
+    .DEST_SYNC_FF(4),
+    .INIT_SYNC_FF(0),
+    .SRC_INPUT_REG(0),
+    .SIM_ASSERT_CHK(0)
+  ) cdc_0 (
+    .src_in(pps_data),
+    .src_clk(),
+    .dest_out(int_pps_wire),
+    .dest_clk(aclk)
+  );
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_enbl_reg <= 1'b0;
+      int_data_reg <= 2'd0;
+    end
+    else
+    begin
+      int_cntr_reg <= int_edge_wire ? {(CNTR_WIDTH){1'b0}} : int_cntr_reg + 1'b1;
+      int_enbl_reg <= int_edge_wire ? 1'b1 : int_enbl_reg;
+      int_data_reg <= {int_data_reg[0], ~int_pps_wire};
+    end
+  end
+
+  assign int_edge_wire = int_data_reg[1] & ~int_data_reg[0];
+
+  assign m_axis_tdata = {{(AXIS_TDATA_WIDTH-CNTR_WIDTH){1'b0}}, int_cntr_reg};
+  assign m_axis_tvalid = int_enbl_reg & int_edge_wire;
+
+endmodule

+ 48 - 0
cores/axis_pulse_generator.v

@@ -0,0 +1,48 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_pulse_generator
+(
+  input  wire        aclk,
+  input  wire        aresetn,
+
+  // Slave side
+  input  wire [63:0] s_axis_tdata,
+  input  wire        s_axis_tvalid,
+  output wire        s_axis_tready,
+
+  // Master side
+  output wire [15:0] m_axis_tdata,
+  output wire        m_axis_tvalid,
+  input  wire        m_axis_tready
+);
+
+  reg [31:0] int_cntr_reg;
+
+  wire int_enbl_wire, int_tready_wire;
+
+  assign int_enbl_wire = |int_cntr_reg;
+  assign int_tready_wire = ~int_enbl_wire;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_cntr_reg <= 32'd0;
+    end
+    else if(int_enbl_wire)
+    begin
+      int_cntr_reg <= int_cntr_reg - 1'b1;
+    end
+    else if(s_axis_tvalid)
+    begin
+      int_cntr_reg <= s_axis_tdata[63:32];
+    end
+  end
+
+  assign s_axis_tready = int_tready_wire;
+
+  assign m_axis_tdata = s_axis_tdata[15:0];
+  assign m_axis_tvalid = int_tready_wire & s_axis_tvalid;
+
+endmodule

+ 135 - 0
cores/axis_pulse_height_analyzer.v

@@ -0,0 +1,135 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_pulse_height_analyzer #
+(
+  parameter integer AXIS_TDATA_WIDTH = 16,
+  parameter         AXIS_TDATA_SIGNED = "FALSE",
+  parameter integer CNTR_WIDTH = 16
+)
+(
+  // System signals
+  input  wire                           aclk,
+  input  wire                           aresetn,
+
+  input  wire [CNTR_WIDTH-1:0]          cfg_data,
+  input  wire [AXIS_TDATA_WIDTH-1:0]    min_data,
+  input  wire [AXIS_TDATA_WIDTH-1:0]    max_data,
+
+  // Slave side
+  output wire                           s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0]    s_axis_tdata,
+  input  wire                           s_axis_tvalid,
+
+  // Master side
+  input  wire                           m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0]    m_axis_tdata,
+  output wire                           m_axis_tvalid
+);
+  reg [AXIS_TDATA_WIDTH-1:0] int_data_reg[1:0], int_data_next[1:0];
+  reg [AXIS_TDATA_WIDTH-1:0] int_min_reg, int_min_next;
+  reg [AXIS_TDATA_WIDTH-1:0] int_tdata_reg, int_tdata_next;
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg int_enbl_reg, int_enbl_next;
+  reg int_rising_reg, int_rising_next;
+  reg int_tvalid_reg, int_tvalid_next;
+
+  wire [AXIS_TDATA_WIDTH-1:0] int_tdata_wire;
+  wire int_mincut_wire, int_maxcut_wire, int_rising_wire, int_delay_wire;
+
+  assign int_delay_wire = int_cntr_reg < cfg_data;
+
+  generate
+    if(AXIS_TDATA_SIGNED == "TRUE")
+    begin : SIGNED
+      assign int_rising_wire = $signed(int_data_reg[1]) < $signed(s_axis_tdata);
+      assign int_tdata_wire = $signed(int_data_reg[0]) - $signed(int_min_reg);
+      assign int_mincut_wire = $signed(int_tdata_wire) > $signed(min_data);
+      assign int_maxcut_wire = $signed(int_tdata_wire) < $signed(max_data);
+    end
+    else
+    begin : UNSIGNED
+      assign int_rising_wire = int_data_reg[1] < s_axis_tdata;
+      assign int_tdata_wire = int_data_reg[0] - int_min_reg;
+      assign int_mincut_wire = int_tdata_wire > min_data;
+      assign int_maxcut_wire = int_tdata_wire < max_data;
+    end
+  endgenerate
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_data_reg[0] <= {(AXIS_TDATA_WIDTH){1'b0}};
+      int_data_reg[1] <= {(AXIS_TDATA_WIDTH){1'b0}};
+      int_tdata_reg <= {(AXIS_TDATA_WIDTH){1'b0}};
+      int_min_reg <= {(AXIS_TDATA_WIDTH){1'b0}};
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_enbl_reg <= 1'b0;
+      int_rising_reg <= 1'b0;
+      int_tvalid_reg <= 1'b0;
+    end
+    else
+    begin
+      int_data_reg[0] <= int_data_next[0];
+      int_data_reg[1] <= int_data_next[1];
+      int_tdata_reg <= int_tdata_next;
+      int_min_reg <= int_min_next;
+      int_cntr_reg <= int_cntr_next;
+      int_enbl_reg <= int_enbl_next;
+      int_rising_reg <= int_rising_next;
+      int_tvalid_reg <= int_tvalid_next;
+    end
+  end
+
+  always @*
+  begin
+    int_data_next[0] = int_data_reg[0];
+    int_data_next[1] = int_data_reg[1];
+    int_tdata_next = int_tdata_reg;
+    int_min_next = int_min_reg;
+    int_cntr_next = int_cntr_reg;
+    int_enbl_next = int_enbl_reg;
+    int_rising_next = int_rising_reg;
+    int_tvalid_next = int_tvalid_reg;
+
+    if(s_axis_tvalid)
+    begin
+      int_data_next[0] = s_axis_tdata;
+      int_data_next[1] = int_data_reg[0];
+      int_rising_next = int_rising_wire;
+    end
+
+    if(s_axis_tvalid & int_delay_wire)
+    begin
+      int_cntr_next = int_cntr_reg + 1'b1;
+    end
+
+    // minimum after delay
+    if(s_axis_tvalid & ~int_delay_wire & ~int_rising_reg & int_rising_wire)
+    begin
+      int_min_next = int_data_reg[1];
+      int_enbl_next = 1'b1;
+    end
+
+    // maximum after minimum
+    if(s_axis_tvalid & int_enbl_reg & int_rising_reg & ~int_rising_wire & int_mincut_wire)
+    begin
+      int_tdata_next = int_maxcut_wire ? int_tdata_wire : {(AXIS_TDATA_WIDTH){1'b0}};
+      int_tvalid_next = int_maxcut_wire;
+      int_cntr_next = {(CNTR_WIDTH){1'b0}};
+      int_enbl_next = 1'b0;
+    end
+
+    if(m_axis_tready & int_tvalid_reg)
+    begin
+      int_tdata_next = {(AXIS_TDATA_WIDTH){1'b0}};
+      int_tvalid_next = 1'b0;
+    end
+  end
+
+  assign s_axis_tready = 1'b1;
+  assign m_axis_tdata = int_tdata_reg;
+  assign m_axis_tvalid = int_tvalid_reg;
+
+endmodule

+ 125 - 0
cores/axis_ram_reader.v

@@ -0,0 +1,125 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_ram_reader #
+(
+  parameter integer ADDR_WIDTH = 16,
+  parameter integer AXI_ID_WIDTH = 6,
+  parameter integer AXI_ADDR_WIDTH = 32,
+  parameter integer AXI_DATA_WIDTH = 64,
+  parameter integer AXIS_TDATA_WIDTH = 64,
+  parameter integer FIFO_WRITE_DEPTH = 512
+)
+(
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [AXI_ADDR_WIDTH-1:0]   min_addr,
+  input  wire [ADDR_WIDTH-1:0]       cfg_data,
+  output wire [ADDR_WIDTH-1:0]       sts_data,
+
+  output wire [AXI_ID_WIDTH-1:0]     m_axi_arid,
+  output wire [3:0]                  m_axi_arlen,
+  output wire [2:0]                  m_axi_arsize,
+  output wire [1:0]                  m_axi_arburst,
+  output wire [3:0]                  m_axi_arcache,
+  output wire [AXI_ADDR_WIDTH-1:0]   m_axi_araddr,
+  output wire                        m_axi_arvalid,
+  input  wire                        m_axi_arready,
+
+  input  wire [AXI_ID_WIDTH-1:0]     m_axi_rid,
+  input  wire                        m_axi_rlast,
+  input  wire [AXI_DATA_WIDTH-1:0]   m_axi_rdata,
+  input  wire                        m_axi_rvalid,
+  output wire                        m_axi_rready,
+
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid,
+  input  wire                        m_axis_tready
+);
+
+  localparam integer ADDR_SIZE = $clog2(AXI_DATA_WIDTH / 8);
+  localparam integer COUNT_WIDTH = $clog2(FIFO_WRITE_DEPTH) + 1;
+
+  reg int_arvalid_reg, int_rvalid_reg;
+  reg [ADDR_WIDTH-1:0] int_addr_reg;
+
+  wire int_empty_wire, int_valid_wire;
+  wire int_arvalid_wire, int_arready_wire;
+  wire [COUNT_WIDTH-1:0] int_count_wire;
+
+  assign int_valid_wire = (int_count_wire < FIFO_WRITE_DEPTH - 15) & ~int_rvalid_reg;
+  assign int_arvalid_wire = int_valid_wire | int_arvalid_reg;
+
+  xpm_fifo_sync #(
+    .WRITE_DATA_WIDTH(AXI_DATA_WIDTH),
+    .FIFO_WRITE_DEPTH(FIFO_WRITE_DEPTH),
+    .READ_DATA_WIDTH(AXIS_TDATA_WIDTH),
+    .READ_MODE("fwft"),
+    .FIFO_READ_LATENCY(0),
+    .FIFO_MEMORY_TYPE("block"),
+    .USE_ADV_FEATURES("0004"),
+    .WR_DATA_COUNT_WIDTH(COUNT_WIDTH)
+  ) fifo_0 (
+    .empty(int_empty_wire),
+    .wr_data_count(int_count_wire),
+    .rst(~aresetn),
+    .wr_clk(aclk),
+    .wr_en(m_axi_rvalid),
+    .din(m_axi_rdata),
+    .rd_en(m_axis_tready),
+    .dout(m_axis_tdata)
+  );
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_arvalid_reg <= 1'b0;
+      int_rvalid_reg <= 1'b0;
+      int_addr_reg <= {(ADDR_WIDTH){1'b0}};
+    end
+    else
+    begin
+      if(int_valid_wire)
+      begin
+        int_arvalid_reg <= 1'b1;
+        int_rvalid_reg <= 1'b1;
+      end
+
+      if(int_arvalid_wire & int_arready_wire)
+      begin
+        int_arvalid_reg <= 1'b0;
+        int_addr_reg <= int_addr_reg < cfg_data ? int_addr_reg + 1'b1 : {(ADDR_WIDTH){1'b0}};
+      end
+
+      if(m_axi_rvalid & m_axi_rlast)
+      begin
+        int_rvalid_reg <= 1'b0;
+      end
+    end
+  end
+
+  output_buffer #(
+    .DATA_WIDTH(AXI_ADDR_WIDTH)
+  ) buf_0 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(min_addr + {int_addr_reg, 4'd0, {(ADDR_SIZE){1'b0}}}),
+    .in_valid(int_arvalid_wire), .in_ready(int_arready_wire),
+    .out_data(m_axi_araddr),
+    .out_valid(m_axi_arvalid), .out_ready(m_axi_arready)
+  );
+
+  assign sts_data = int_addr_reg;
+
+  assign m_axi_arid = {(AXI_ID_WIDTH){1'b0}};
+  assign m_axi_arlen = 4'd15;
+  assign m_axi_arsize = ADDR_SIZE;
+  assign m_axi_arburst = 2'b01;
+  assign m_axi_arcache = 4'b1111;
+
+  assign m_axi_rready = 1'b1;
+
+  assign m_axis_tvalid = ~int_empty_wire;
+
+endmodule

+ 133 - 0
cores/axis_ram_reader_radar.v

@@ -0,0 +1,133 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_ram_reader #
+(
+  parameter integer ADDR_WIDTH = 16,
+  parameter integer AXI_ID_WIDTH = 6,
+  parameter integer AXI_ADDR_WIDTH = 32,
+  parameter integer AXI_DATA_WIDTH = 64,
+  parameter integer AXIS_TDATA_WIDTH = 64,
+  parameter integer FIFO_WRITE_DEPTH = 512
+)
+(
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [AXI_ADDR_WIDTH-1:0]   min_addr,
+  input  wire [ADDR_WIDTH-1:0]       cfg_data,
+  output wire [ADDR_WIDTH-1:0]       sts_data,
+
+  output wire [AXI_ID_WIDTH-1:0]     m_axi_arid,
+  output wire [3:0]                  m_axi_arlen,
+  output wire [2:0]                  m_axi_arsize,
+  output wire [1:0]                  m_axi_arburst,
+  output wire [3:0]                  m_axi_arcache,
+  output wire [AXI_ADDR_WIDTH-1:0]   m_axi_araddr,
+  output wire                        m_axi_arvalid,
+  input  wire                        m_axi_arready,
+
+  input  wire [AXI_ID_WIDTH-1:0]     m_axi_rid,
+  input  wire                        m_axi_rlast,
+  input  wire [AXI_DATA_WIDTH-1:0]   m_axi_rdata,
+  input  wire                        m_axi_rvalid,
+  output wire                        m_axi_rready,
+
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid,
+  input  wire                        m_axis_tready
+);
+
+  localparam integer ADDR_SIZE = $clog2(AXI_DATA_WIDTH / 8);
+  localparam integer COUNT_WIDTH = $clog2(FIFO_WRITE_DEPTH) + 1;
+
+  reg int_arvalid_reg, int_rvalid_reg;
+  reg [ADDR_WIDTH-1:0] int_addr_reg, int_data_reg;
+
+  wire int_empty_wire, int_valid_wire;
+  wire int_arvalid_wire, int_arready_wire;
+  wire [COUNT_WIDTH-1:0] int_count_wire;
+
+  assign int_valid_wire = (int_count_wire < FIFO_WRITE_DEPTH - 15) & ~int_rvalid_reg;
+  assign int_arvalid_wire = int_valid_wire | int_arvalid_reg;
+
+  xpm_fifo_sync #(
+    .WRITE_DATA_WIDTH(AXI_DATA_WIDTH),
+    .FIFO_WRITE_DEPTH(FIFO_WRITE_DEPTH),
+    .READ_DATA_WIDTH(AXIS_TDATA_WIDTH),
+    .READ_MODE("fwft"),
+    .FIFO_READ_LATENCY(0),
+    .FIFO_MEMORY_TYPE("block"),
+    .USE_ADV_FEATURES("0004"),
+    .WR_DATA_COUNT_WIDTH(COUNT_WIDTH)
+  ) fifo_0 (
+    .empty(int_empty_wire),
+    .wr_data_count(int_count_wire),
+    .rst(~aresetn),
+    .wr_clk(aclk),
+    .wr_en(m_axi_rvalid),
+    .din(m_axi_rdata),
+    .rd_en(m_axis_tready),
+    .dout(m_axis_tdata)
+  );
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_arvalid_reg <= 1'b0;
+      int_rvalid_reg <= 1'b0;
+      int_addr_reg <= {(ADDR_WIDTH){1'b0}};
+    end
+    else
+    begin
+      if(int_valid_wire)
+      begin
+        int_arvalid_reg <= 1'b1;
+        int_rvalid_reg <= 1'b1;
+      end
+
+      if(int_arvalid_wire & int_arready_wire) // when we need to produce next sample
+      begin
+        int_arvalid_reg <= 1'b0;
+        if(int_addr_reg < int_data_reg)
+        begin
+          int_addr_reg <= int_addr_reg + 1'b1;
+        end
+        else
+        begin
+          int_addr_reg <= {cfg_data[15:14], 14'd0}; // bits 15:14 = at which quarter of the buffer to start; then start with the low 14 bits zero - the beginning of the quarter
+          int_data_reg <= cfg_data;
+        end
+      end
+
+      if(m_axi_rlast)
+      begin
+        int_rvalid_reg <= 1'b0;
+      end
+    end
+  end
+
+  output_buffer #(
+    .DATA_WIDTH(AXI_ADDR_WIDTH)
+  ) buf_0 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(min_addr + {int_addr_reg, 4'd0, {(ADDR_SIZE){1'b0}}}),
+    .in_valid(int_arvalid_wire), .in_ready(int_arready_wire),
+    .out_data(m_axi_araddr),
+    .out_valid(m_axi_arvalid), .out_ready(m_axi_arready)
+  );
+
+  assign sts_data = int_addr_reg;
+
+  assign m_axi_arid = {(AXI_ID_WIDTH){1'b0}};
+  assign m_axi_arlen = 4'd15;
+  assign m_axi_arsize = ADDR_SIZE;
+  assign m_axi_arburst = 2'b01;
+  assign m_axi_arcache = 4'b0110;
+
+  assign m_axi_rready = 1'b1;
+
+  assign m_axis_tvalid = ~int_empty_wire;
+
+endmodule

+ 158 - 0
cores/axis_ram_writer.v

@@ -0,0 +1,158 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_ram_writer #
+(
+  parameter integer ADDR_WIDTH = 16,
+  parameter integer AXI_ID_WIDTH = 6,
+  parameter integer AXI_ADDR_WIDTH = 32,
+  parameter integer AXI_DATA_WIDTH = 64,
+  parameter integer AXIS_TDATA_WIDTH = 64,
+  parameter integer FIFO_WRITE_DEPTH = 512
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [AXI_ADDR_WIDTH-1:0]   min_addr,
+  input  wire [ADDR_WIDTH-1:0]       cfg_data,
+  output wire [ADDR_WIDTH-1:0]       sts_data,
+
+  // Master side
+  output wire [AXI_ID_WIDTH-1:0]     m_axi_awid,    // AXI master: Write address ID
+  output wire [3:0]                  m_axi_awlen,   // AXI master: Write burst length
+  output wire [2:0]                  m_axi_awsize,  // AXI master: Write burst size
+  output wire [1:0]                  m_axi_awburst, // AXI master: Write burst type
+  output wire [3:0]                  m_axi_awcache, // AXI master: Write memory type
+  output wire [AXI_ADDR_WIDTH-1:0]   m_axi_awaddr,  // AXI master: Write address
+  output wire                        m_axi_awvalid, // AXI master: Write address valid
+  input  wire                        m_axi_awready, // AXI master: Write address ready
+
+  output wire [AXI_ID_WIDTH-1:0]     m_axi_wid,     // AXI master: Write data ID
+  output wire [AXI_DATA_WIDTH/8-1:0] m_axi_wstrb,   // AXI master: Write strobes
+  output wire                        m_axi_wlast,   // AXI master: Write last
+  output wire [AXI_DATA_WIDTH-1:0]   m_axi_wdata,   // AXI master: Write data
+  output wire                        m_axi_wvalid,  // AXI master: Write valid
+  input  wire                        m_axi_wready,  // AXI master: Write ready
+
+  input  wire                        m_axi_bvalid,  // AXI master: Write response valid
+  output wire                        m_axi_bready,  // AXI master: Write response ready
+
+  // Slave side
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+  output wire                        s_axis_tready
+);
+
+  localparam integer ADDR_SIZE = $clog2(AXI_DATA_WIDTH / 8);
+  localparam integer COUNT_WIDTH = $clog2(FIFO_WRITE_DEPTH * AXIS_TDATA_WIDTH / AXI_DATA_WIDTH) + 1;
+
+  reg int_awvalid_reg, int_wvalid_reg;
+  reg [3:0] int_cntr_reg;
+  reg [ADDR_WIDTH-1:0] int_addr_reg;
+
+  wire int_full_wire, int_valid_wire;
+  wire int_awvalid_wire, int_awready_wire;
+  wire int_wlast_wire, int_wvalid_wire, int_wready_wire, int_rden_wire;
+  wire [COUNT_WIDTH-1:0] int_count_wire;
+  wire [AXI_DATA_WIDTH-1:0] int_wdata_wire;
+
+  assign int_valid_wire = (int_count_wire > 15) & ~int_wvalid_reg;
+  assign int_awvalid_wire = int_valid_wire | int_awvalid_reg;
+  assign int_wvalid_wire = int_valid_wire | int_wvalid_reg;
+
+  assign int_rden_wire = int_wvalid_wire & int_wready_wire;
+  assign int_wlast_wire = &int_cntr_reg;
+
+  xpm_fifo_sync #(
+    .WRITE_DATA_WIDTH(AXIS_TDATA_WIDTH),
+    .FIFO_WRITE_DEPTH(FIFO_WRITE_DEPTH),
+    .READ_DATA_WIDTH(AXI_DATA_WIDTH),
+    .READ_MODE("fwft"),
+    .FIFO_READ_LATENCY(0),
+    .FIFO_MEMORY_TYPE("block"),
+    .USE_ADV_FEATURES("0400"),
+    .RD_DATA_COUNT_WIDTH(COUNT_WIDTH)
+  ) fifo_0 (
+    .full(int_full_wire),
+    .rd_data_count(int_count_wire),
+    .rst(~aresetn),
+    .wr_clk(aclk),
+    .wr_en(s_axis_tvalid),
+    .din(s_axis_tdata),
+    .rd_en(int_rden_wire),
+    .dout(int_wdata_wire)
+  );
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_awvalid_reg <= 1'b0;
+      int_wvalid_reg <= 1'b0;
+      int_cntr_reg <= 4'd0;
+      int_addr_reg <= {(ADDR_WIDTH){1'b0}};
+    end
+    else
+    begin
+      if(int_valid_wire)
+      begin
+        int_awvalid_reg <= 1'b1;
+        int_wvalid_reg <= 1'b1;
+      end
+
+      if(int_awvalid_wire & int_awready_wire)
+      begin
+        int_awvalid_reg <= 1'b0;
+        int_addr_reg <= int_addr_reg < cfg_data ? int_addr_reg + 1'b1 : {(ADDR_WIDTH){1'b0}};
+      end
+
+      if(int_rden_wire)
+      begin
+        int_cntr_reg <= int_cntr_reg + 1'b1;
+      end
+
+      if(int_wready_wire & int_wlast_wire)
+      begin
+        int_wvalid_reg <= 1'b0;
+      end
+    end
+  end
+
+  output_buffer #(
+    .DATA_WIDTH(AXI_ADDR_WIDTH)
+  ) buf_0 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(min_addr + {int_addr_reg, 4'd0, {(ADDR_SIZE){1'b0}}}),
+    .in_valid(int_awvalid_wire), .in_ready(int_awready_wire),
+    .out_data(m_axi_awaddr),
+    .out_valid(m_axi_awvalid), .out_ready(m_axi_awready)
+  );
+
+  output_buffer #(
+    .DATA_WIDTH(AXI_DATA_WIDTH+1)
+  ) buf_1 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data({int_wlast_wire, int_wdata_wire}),
+    .in_valid(int_wvalid_wire), .in_ready(int_wready_wire),
+    .out_data({m_axi_wlast, m_axi_wdata}),
+    .out_valid(m_axi_wvalid), .out_ready(m_axi_wready)
+  );
+
+  assign sts_data = int_addr_reg;
+
+  assign m_axi_awid = {(AXI_ID_WIDTH){1'b0}};
+  assign m_axi_awlen = 4'd15;
+  assign m_axi_awsize = ADDR_SIZE;
+  assign m_axi_awburst = 2'b01;
+  assign m_axi_awcache = 4'b1111;
+
+  assign m_axi_wid = {(AXI_ID_WIDTH){1'b0}};
+  assign m_axi_wstrb = {(AXI_DATA_WIDTH/8){1'b1}};
+
+  assign m_axi_bready = 1'b1;
+
+  assign s_axis_tready = ~int_full_wire;
+
+endmodule

+ 40 - 0
cores/axis_red_pitaya_adc.v

@@ -0,0 +1,40 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_red_pitaya_adc #
+(
+  parameter integer ADC_DATA_WIDTH = 14
+)
+(
+  // System signals
+  input  wire        aclk,
+
+  // ADC signals
+  output wire        adc_csn,
+  input  wire [15:0] adc_dat_a,
+  input  wire [15:0] adc_dat_b,
+
+  // Master side
+  output wire        m_axis_tvalid,
+  output wire [31:0] m_axis_tdata
+);
+  localparam PADDING_WIDTH = 16 - ADC_DATA_WIDTH;
+
+  reg  [ADC_DATA_WIDTH-1:0] int_dat_a_reg;
+  reg  [ADC_DATA_WIDTH-1:0] int_dat_b_reg;
+
+  always @(posedge aclk)
+  begin
+    int_dat_a_reg <= adc_dat_a[15:PADDING_WIDTH];
+    int_dat_b_reg <= adc_dat_b[15:PADDING_WIDTH];
+  end
+
+  assign adc_csn = 1'b1;
+
+  assign m_axis_tvalid = 1'b1;
+
+  assign m_axis_tdata = {
+    {(PADDING_WIDTH+1){int_dat_b_reg[ADC_DATA_WIDTH-1]}}, ~int_dat_b_reg[ADC_DATA_WIDTH-2:0],
+    {(PADDING_WIDTH+1){int_dat_a_reg[ADC_DATA_WIDTH-1]}}, ~int_dat_a_reg[ADC_DATA_WIDTH-2:0]};
+
+endmodule

+ 128 - 0
cores/axis_red_pitaya_dac.v

@@ -0,0 +1,128 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_red_pitaya_dac #
+(
+  parameter integer DAC_DATA_WIDTH = 14,
+  parameter integer AXIS_TDATA_WIDTH = 32
+)
+(
+  // PLL signals
+  input  wire                        aclk,
+  input  wire                        ddr_clk,
+  input  wire                        wrt_clk,
+  input  wire                        locked,
+
+  // DAC signals
+  output wire                        dac_clk,
+  output wire                        dac_rst,
+  output wire                        dac_sel,
+  output wire                        dac_wrt,
+  output wire [DAC_DATA_WIDTH-1:0]   dac_dat,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid
+);
+
+  reg [DAC_DATA_WIDTH-1:0] int_dat_a_reg;
+  reg [DAC_DATA_WIDTH-1:0] int_dat_b_reg;
+  reg [1:0] int_rst_reg;
+
+  wire [DAC_DATA_WIDTH-1:0] int_dat_a_wire;
+  wire [DAC_DATA_WIDTH-1:0] int_dat_b_wire;
+
+  assign int_dat_a_wire = s_axis_tdata[DAC_DATA_WIDTH-1:0];
+  assign int_dat_b_wire = s_axis_tdata[AXIS_TDATA_WIDTH/2+DAC_DATA_WIDTH-1:AXIS_TDATA_WIDTH/2];
+
+  genvar j;
+
+  always @(posedge aclk)
+  begin
+    if(~locked | ~s_axis_tvalid)
+    begin
+      int_dat_a_reg <= {(DAC_DATA_WIDTH){1'b0}};
+      int_dat_b_reg <= {(DAC_DATA_WIDTH){1'b0}};
+    end
+    else
+    begin
+      int_dat_a_reg <= {int_dat_a_wire[DAC_DATA_WIDTH-1], ~int_dat_a_wire[DAC_DATA_WIDTH-2:0]};
+      int_dat_b_reg <= {int_dat_b_wire[DAC_DATA_WIDTH-1], ~int_dat_b_wire[DAC_DATA_WIDTH-2:0]};
+    end
+    int_rst_reg <= {int_rst_reg[0], ~locked | ~s_axis_tvalid};
+  end
+
+  ODDR #(
+    .DDR_CLK_EDGE("SAME_EDGE"),
+    .INIT(1'b0)
+  ) ODDR_rst (
+    .Q(dac_rst),
+    .D1(int_rst_reg[1]),
+    .D2(int_rst_reg[1]),
+    .C(aclk),
+    .CE(1'b1),
+    .R(1'b0),
+    .S(1'b0)
+  );
+
+  ODDR #(
+    .DDR_CLK_EDGE("SAME_EDGE"),
+    .INIT(1'b0)
+  ) ODDR_sel (
+    .Q(dac_sel),
+    .D1(1'b1),
+    .D2(1'b0),
+    .C(aclk),
+    .CE(1'b1),
+    .R(1'b0),
+    .S(1'b0)
+  );
+
+  ODDR #(
+    .DDR_CLK_EDGE("SAME_EDGE"),
+    .INIT(1'b0)
+  ) ODDR_wrt (
+    .Q(dac_wrt),
+    .D1(1'b1),
+    .D2(1'b0),
+    .C(wrt_clk),
+    .CE(1'b1),
+    .R(1'b0),
+    .S(1'b0)
+  );
+
+  ODDR #(
+    .DDR_CLK_EDGE("SAME_EDGE"),
+    .INIT(1'b0)
+  ) ODDR_clk (
+    .Q(dac_clk),
+    .D1(1'b1),
+    .D2(1'b0),
+    .C(ddr_clk),
+    .CE(1'b1),
+    .R(1'b0),
+    .S(1'b0)
+  );
+
+  generate
+    for(j = 0; j < DAC_DATA_WIDTH; j = j + 1)
+    begin : DAC_DAT
+      ODDR #(
+        .DDR_CLK_EDGE("SAME_EDGE"),
+        .INIT(1'b0)
+      ) ODDR_inst (
+        .Q(dac_dat[j]),
+        .D1(int_dat_b_reg[j]),
+        .D2(int_dat_a_reg[j]),
+        .C(aclk),
+        .CE(1'b1),
+        .R(1'b0),
+        .S(1'b0)
+      );
+    end
+  endgenerate
+
+  assign s_axis_tready = 1'b1;
+
+endmodule

+ 47 - 0
cores/axis_selector.v

@@ -0,0 +1,47 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_selector #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire                        cfg_data,
+
+  // Slave side
+  input  wire [AXIS_TDATA_WIDTH-1:0] s00_axis_tdata,
+  input  wire                        s00_axis_tvalid,
+  output wire                        s00_axis_tready,
+
+  input  wire [AXIS_TDATA_WIDTH-1:0] s01_axis_tdata,
+  input  wire                        s01_axis_tvalid,
+  output wire                        s01_axis_tready,
+
+  // Master side
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid,
+  input  wire                        m_axis_tready
+);
+
+  wire [AXIS_TDATA_WIDTH-1:0] int_data_wire;
+  wire int_valid_wire, int_ready_wire;
+
+  assign int_data_wire = cfg_data ? s01_axis_tdata : s00_axis_tdata;
+  assign int_valid_wire = cfg_data ? s01_axis_tvalid : s00_axis_tvalid;
+
+  assign s00_axis_tready = ~cfg_data & int_ready_wire;
+  assign s01_axis_tready = cfg_data & int_ready_wire;
+
+  inout_buffer #(
+    .DATA_WIDTH(AXIS_TDATA_WIDTH)
+  ) buf_0 (
+    .aclk(aclk), .aresetn(aresetn),
+    .in_data(int_data_wire), .in_valid(int_valid_wire), .in_ready(int_ready_wire),
+    .out_data(m_axis_tdata), .out_valid(m_axis_tvalid), .out_ready(m_axis_tready)
+  );
+
+endmodule

+ 29 - 0
cores/axis_stepper.v

@@ -0,0 +1,29 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_stepper #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+
+  input  wire                        trg_flag,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  assign s_axis_tready = trg_flag;
+  assign m_axis_tdata = s_axis_tdata;
+  assign m_axis_tvalid = s_axis_tvalid;
+
+endmodule

+ 44 - 0
cores/axis_tagger.v

@@ -0,0 +1,44 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_tagger #
+(
+  parameter integer AXIS_TDATA_WIDTH = 256
+)
+(
+  // System signals
+  input  wire                        aclk,
+
+  input  wire                        tag_data,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  reg int_data_reg, int_flag_reg;
+
+  always @(posedge aclk)
+  begin
+    int_data_reg <= tag_data;
+    if(tag_data & ~int_data_reg)
+    begin
+      int_flag_reg <= 1'b1;
+    end
+    else if(s_axis_tvalid)
+    begin
+      int_flag_reg <= 1'b0;
+    end
+  end
+
+  assign s_axis_tready = m_axis_tready;
+  assign m_axis_tdata = {s_axis_tdata[255:209], int_flag_reg, s_axis_tdata[207:0]};
+  assign m_axis_tvalid = s_axis_tvalid;
+
+endmodule

+ 71 - 0
cores/axis_timer.v

@@ -0,0 +1,71 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_timer #
+(
+  parameter integer CNTR_WIDTH = 64
+)
+(
+  // System signals
+  input  wire                  aclk,
+  input  wire                  aresetn,
+
+  input  wire                  run_flag,
+  input  wire [CNTR_WIDTH-1:0] cfg_data,
+
+  output wire                  trg_flag,
+  output wire [CNTR_WIDTH-1:0] sts_data,
+
+  // Slave side
+  output wire                  s_axis_tready,
+  input  wire                  s_axis_tvalid
+);
+
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg int_enbl_reg, int_enbl_next;
+
+  wire int_comp_wire;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_enbl_reg <= 1'b0;
+    end
+    else
+    begin
+      int_cntr_reg <= int_cntr_next;
+      int_enbl_reg <= int_enbl_next;
+    end
+  end
+
+  assign int_comp_wire = run_flag & (int_cntr_reg < cfg_data);
+
+  always @*
+  begin
+    int_cntr_next = int_cntr_reg;
+    int_enbl_next = int_enbl_reg;
+
+    if(~int_enbl_reg & int_comp_wire & s_axis_tvalid)
+    begin
+      int_enbl_next = 1'b1;
+    end
+
+    if(int_enbl_reg & int_comp_wire & s_axis_tvalid)
+    begin
+      int_cntr_next = int_cntr_reg + 1'b1;
+    end
+
+    if(int_enbl_reg & ~int_comp_wire & s_axis_tvalid)
+    begin
+      int_enbl_next = 1'b0;
+    end
+  end
+
+  assign trg_flag = int_enbl_reg;
+  assign sts_data = int_cntr_reg;
+
+  assign s_axis_tready = 1'b1;
+
+endmodule

+ 51 - 0
cores/axis_trigger.v

@@ -0,0 +1,51 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_trigger #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32,
+  parameter         AXIS_TDATA_SIGNED = "FALSE"
+)
+(
+  // System signals
+  input  wire                        aclk,
+
+  input  wire                        pol_data,
+  input  wire [AXIS_TDATA_WIDTH-1:0] msk_data,
+  input  wire [AXIS_TDATA_WIDTH-1:0] lvl_data,
+
+  output wire                        trg_flag,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid
+);
+
+  reg [1:0] int_comp_reg;
+  wire int_comp_wire;
+
+  generate
+    if(AXIS_TDATA_SIGNED == "TRUE")
+    begin : SIGNED
+      assign int_comp_wire = $signed(s_axis_tdata & msk_data) >= $signed(lvl_data);
+    end
+    else
+    begin : UNSIGNED
+      assign int_comp_wire = (s_axis_tdata & msk_data) >= lvl_data;
+    end
+  endgenerate
+
+  always @(posedge aclk)
+  begin
+    if(s_axis_tvalid)
+    begin
+      int_comp_reg <= {int_comp_reg[0], int_comp_wire};
+    end
+  end
+
+  assign s_axis_tready = 1'b1;
+
+  assign trg_flag = s_axis_tvalid & (pol_data ^ int_comp_reg[0]) & (pol_data ^ ~int_comp_reg[1]);
+
+endmodule

+ 29 - 0
cores/axis_validator.v

@@ -0,0 +1,29 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_validator #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+
+  input  wire                        trg_flag,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  assign s_axis_tready = m_axis_tready;
+  assign m_axis_tdata = s_axis_tdata;
+  assign m_axis_tvalid = s_axis_tvalid & trg_flag;
+
+endmodule

+ 41 - 0
cores/axis_variable.v

@@ -0,0 +1,41 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_variable #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire [AXIS_TDATA_WIDTH-1:0] cfg_data,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  reg [AXIS_TDATA_WIDTH-1:0] int_tdata_reg;
+  reg int_tvalid_reg;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_tdata_reg <= {(AXIS_TDATA_WIDTH){1'b0}};
+      int_tvalid_reg <= 1'b0;
+    end
+    else
+    begin
+      int_tdata_reg <= cfg_data;
+      int_tvalid_reg <= (int_tdata_reg != cfg_data) | (int_tvalid_reg & ~m_axis_tready);
+    end
+  end
+
+  assign m_axis_tdata = int_tdata_reg;
+  assign m_axis_tvalid = int_tvalid_reg;
+
+endmodule

+ 62 - 0
cores/axis_variant.v

@@ -0,0 +1,62 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_variant #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+  input  wire                        aresetn,
+
+  input  wire                        cfg_flag,
+
+  input  wire [AXIS_TDATA_WIDTH-1:0] cfg_data0,
+  input  wire [AXIS_TDATA_WIDTH-1:0] cfg_data1,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  reg [AXIS_TDATA_WIDTH-1:0] int_tdata_reg;
+  reg int_tvalid_reg, int_tvalid_next;
+  wire [AXIS_TDATA_WIDTH-1:0] int_tdata_wire;
+
+  assign int_tdata_wire = cfg_flag ? cfg_data1 : cfg_data0;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_tdata_reg <= {(AXIS_TDATA_WIDTH){1'b0}};
+      int_tvalid_reg <= 1'b0;
+    end
+    else
+    begin
+      int_tdata_reg <= int_tdata_wire;
+      int_tvalid_reg <= int_tvalid_next;
+    end
+  end
+
+  always @*
+  begin
+    int_tvalid_next = int_tvalid_reg;
+
+    if(int_tdata_reg != int_tdata_wire)
+    begin
+      int_tvalid_next = 1'b1;
+    end
+
+    if(m_axis_tready & int_tvalid_reg)
+    begin
+      int_tvalid_next = 1'b0;
+    end
+  end
+
+  assign m_axis_tdata = int_tdata_reg;
+  assign m_axis_tvalid = int_tvalid_reg;
+
+endmodule

+ 27 - 0
cores/axis_zeroer.v

@@ -0,0 +1,27 @@
+
+`timescale 1 ns / 1 ps
+
+module axis_zeroer #
+(
+  parameter integer AXIS_TDATA_WIDTH = 32
+)
+(
+  // System signals
+  input  wire                        aclk,
+
+  // Slave side
+  output wire                        s_axis_tready,
+  input  wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata,
+  input  wire                        s_axis_tvalid,
+
+  // Master side
+  input  wire                        m_axis_tready,
+  output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata,
+  output wire                        m_axis_tvalid
+);
+
+  assign s_axis_tready = m_axis_tready;
+  assign m_axis_tdata = s_axis_tvalid ? s_axis_tdata : {(AXIS_TDATA_WIDTH){1'b0}};
+  assign m_axis_tvalid = 1'b1;
+
+endmodule

+ 148 - 0
cores/dds.v

@@ -0,0 +1,148 @@
+
+`timescale 1 ns / 1 ps
+
+module dds #
+(
+  parameter NEGATIVE_SINE = "FALSE"
+)
+(
+  input  wire        aclk,
+  input  wire        aresetn,
+
+  input  wire [31:0] pinc,
+
+  output wire [47:0] dout
+);
+
+  reg [31:0] int_cntr_reg;
+  reg [23:0] int_cos_reg, int_sin_reg;
+  reg [10:0] int_addr_reg;
+  reg [1:0] int_sign_reg [2:0];
+
+  wire [47:0] int_p_wire [2:0];
+  wire [31:0] int_cntr_wire;
+  wire [29:0] int_cos_wire, int_sin_wire;
+  wire [22:0] int_lut_wire [1:0];
+  wire [17:0] int_corr_wire;
+  wire [2:0] int_pbd_wire;
+
+  assign int_cos_wire = int_sign_reg[2][0] ? {7'h7f, -int_lut_wire[0]} : {7'h00, int_lut_wire[0]};
+  assign int_sin_wire = int_sign_reg[2][1] ? {7'h7f, -int_lut_wire[1]} : {7'h00, int_lut_wire[1]};
+
+  assign int_corr_wire = {int_p_wire[0][34:18], int_p_wire[0][17] | int_pbd_wire[0]};
+
+  generate
+    if(NEGATIVE_SINE == "TRUE")
+    begin : NEGATIVE
+      assign int_cntr_wire = int_cntr_reg - pinc;
+    end
+    else
+    begin : POSITIVE
+      assign int_cntr_wire = int_cntr_reg + pinc;
+    end
+  endgenerate
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_cntr_reg <= 32'd0;
+      int_cos_reg <= 24'd0;
+      int_sin_reg <= 24'd0;
+      int_addr_reg <= 11'd0;
+      int_sign_reg[0] <= 2'd0;
+      int_sign_reg[1] <= 2'd0;
+      int_sign_reg[2] <= 2'd0;
+    end
+    else
+    begin
+      int_cntr_reg <= int_cntr_wire;
+      int_cos_reg <= int_cos_wire[23:0];
+      int_sin_reg <= int_sin_wire[23:0];
+      int_addr_reg <= int_cntr_reg[29:19];
+      int_sign_reg[0] <= {int_cntr_reg[31], int_cntr_reg[30]};
+      int_sign_reg[1] <= {int_sign_reg[0][1], int_sign_reg[0][1] ^ int_sign_reg[0][0]};
+      int_sign_reg[2] <= int_sign_reg[1];
+    end
+  end
+
+  xpm_memory_dprom #(
+    .MEMORY_PRIMITIVE("block"),
+    .MEMORY_SIZE(47104),
+    .ADDR_WIDTH_A(11),
+    .ADDR_WIDTH_B(11),
+    .READ_DATA_WIDTH_A(23),
+    .READ_DATA_WIDTH_B(23),
+    .READ_LATENCY_A(2),
+    .READ_LATENCY_B(2),
+    .MEMORY_INIT_PARAM(""),
+    .MEMORY_INIT_FILE("dds.mem")
+  ) rom_0 (
+    .clka(aclk),
+    .clkb(aclk),
+    .rsta(1'b0),
+    .rstb(1'b0),
+    .ena(1'b1),
+    .enb(1'b1),
+    .regcea(1'b1),
+    .regceb(1'b1),
+    .addra(int_sign_reg[0][0] ? ~int_addr_reg : int_addr_reg),
+    .addrb(int_sign_reg[0][0] ? int_addr_reg : ~int_addr_reg),
+    .douta(int_lut_wire[0]),
+    .doutb(int_lut_wire[1])
+  );
+
+  DSP48E1 #(
+    .ALUMODEREG(0), .CARRYINSELREG(0), .INMODEREG(0), .OPMODEREG(0),
+    .BREG(0), .BCASCREG(0), .CREG(0), .CARRYINREG(0),
+    .USE_PATTERN_DETECT("PATDET"), .MASK(48'hfffffffe0000)
+  ) dsp_0 (
+    .CLK(aclk),
+    .RSTA(1'b0), .RSTM(1'b0), .RSTP(1'b0),
+    .CEA2(1'b1), .CED(1'b0), .CEAD(1'b0), .CEM(1'b1), .CEP(1'b1),
+    .ALUMODE(4'b0000), .CARRYINSEL(3'b000), .INMODE(5'b00000), .OPMODE(7'b0110101),
+    .A({{(12){~int_cntr_reg[18]}}, int_cntr_reg[17:0]}),
+    .B(18'd3217),
+    .C(48'hffff),
+    .CARRYIN(1'b0),
+    .PATTERNBDETECT(int_pbd_wire[0]),
+    .P(int_p_wire[0])
+  );
+
+  DSP48E1 #(
+    .ALUMODEREG(0), .CARRYINSELREG(0), .INMODEREG(0), .OPMODEREG(0),
+    .CARRYINREG(0),
+    .USE_PATTERN_DETECT("PATDET"), .MASK(48'hffffff000000)
+  ) dsp_1 (
+    .CLK(aclk),
+    .RSTA(1'b0), .RSTB(1'b0), .RSTC(1'b0), .RSTM(1'b0), .RSTP(1'b0),
+    .CEA2(1'b1), .CEB2(1'b1), .CEC(1'b1), .CED(1'b0), .CEAD(1'b0), .CEM(1'b1), .CEP(1'b1),
+    .ALUMODE(4'b0011), .CARRYINSEL(3'b000), .INMODE(5'b00000), .OPMODE(7'b0110101),
+    .A(int_sin_wire),
+    .B(int_corr_wire),
+    .C({int_cos_reg, 24'h7fffff}),
+    .CARRYIN(1'b0),
+    .PATTERNBDETECT(int_pbd_wire[1]),
+    .P(int_p_wire[1])
+  );
+
+  DSP48E1 #(
+    .ALUMODEREG(0), .CARRYINSELREG(0), .INMODEREG(0), .OPMODEREG(0),
+    .CARRYINREG(0),
+    .USE_PATTERN_DETECT("PATDET"), .MASK(48'hffffff000000)
+  ) dsp_2 (
+    .CLK(aclk),
+    .RSTA(1'b0), .RSTB(1'b0), .RSTC(1'b0), .RSTM(1'b0), .RSTP(1'b0),
+    .CEA2(1'b1), .CEB2(1'b1), .CEC(1'b1), .CED(1'b0), .CEAD(1'b0), .CEM(1'b1), .CEP(1'b1),
+    .ALUMODE(4'b0000), .CARRYINSEL(3'b000), .INMODE(5'b00000), .OPMODE(7'b0110101),
+    .A(int_cos_wire),
+    .B(int_corr_wire),
+    .C({int_sin_reg, 24'h7fffff}),
+    .CARRYIN(1'b0),
+    .PATTERNBDETECT(int_pbd_wire[2]),
+    .P(int_p_wire[2])
+  );
+
+  assign dout = {int_p_wire[2][47:25], int_p_wire[2][24] | int_pbd_wire[2], int_p_wire[1][47:25], int_p_wire[1][24] | int_pbd_wire[1]};
+
+endmodule

+ 88 - 0
cores/dna_reader.v

@@ -0,0 +1,88 @@
+
+`timescale 1 ns / 1 ps
+
+module dna_reader
+(
+  input  wire        aclk,
+  input  wire        aresetn,
+
+  output wire [56:0] dna_data
+);
+
+  localparam integer CNTR_WIDTH = 16;
+  localparam integer DATA_WIDTH = 57;
+
+  reg int_enbl_reg, int_enbl_next;
+  reg int_read_reg, int_read_next;
+  reg int_shift_reg, int_shift_next;
+  reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next;
+  reg [DATA_WIDTH-1:0] int_data_reg, int_data_next;
+
+  wire int_comp_wire, int_data_wire;
+
+  assign int_comp_wire = int_cntr_reg < 64*DATA_WIDTH;
+
+  DNA_PORT dna_0 (
+    .DOUT(int_data_wire),
+    .CLK(int_cntr_reg[5]),
+    .DIN(1'b0),
+    .READ(int_read_reg),
+    .SHIFT(int_shift_reg)
+  );
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_enbl_reg <= 1'b0;
+      int_read_reg <= 1'b0;
+      int_shift_reg <= 1'b0;
+      int_cntr_reg <= {(CNTR_WIDTH){1'b0}};
+      int_data_reg <= {(DATA_WIDTH){1'b0}};
+    end
+    else
+    begin
+      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
+  end
+
+  always @*
+  begin
+    int_enbl_next = int_enbl_reg;
+    int_read_next = int_read_reg;
+    int_shift_next = int_shift_reg;
+    int_cntr_next = int_cntr_reg;
+    int_data_next = int_data_reg;
+
+    if(~int_enbl_reg & int_comp_wire)
+    begin
+      int_enbl_next = 1'b1;
+      int_read_next = 1'b1;
+    end
+
+    if(int_enbl_reg)
+    begin
+      int_cntr_next = int_cntr_reg + 1'b1;
+    end
+
+    if(&int_cntr_reg[5:0])
+    begin
+      int_read_next = 1'b0;
+      int_shift_next = 1'b1;
+      int_data_next = {int_data_reg[DATA_WIDTH-2:0], int_data_wire};
+    end
+
+    if(~int_comp_wire)
+    begin
+      int_enbl_next = 1'b0;
+      int_shift_next = 1'b0;
+    end
+  end
+
+  assign dna_data = int_data_reg;
+
+endmodule

+ 44 - 0
cores/dsp48.v

@@ -0,0 +1,44 @@
+
+`timescale 1 ns / 1 ps
+
+module dsp48 #
+(
+  parameter integer A_WIDTH = 24,
+  parameter integer B_WIDTH = 16,
+  parameter integer P_WIDTH = 24
+)
+(
+  input  wire               CLK,
+
+  input  wire [A_WIDTH-1:0] A,
+  input  wire [B_WIDTH-1:0] B,
+
+  output wire [P_WIDTH-1:0] P
+);
+
+  localparam integer SHIFT = A_WIDTH + B_WIDTH - P_WIDTH - 1;
+  localparam integer ONES = SHIFT - 1;
+
+  wire [47:0] int_p_wire;
+  wire int_pbd_wire;
+
+  DSP48E1 #(
+    .ALUMODEREG(0), .CARRYINSELREG(0), .INMODEREG(0), .OPMODEREG(0),
+    .CREG(0), .CARRYINREG(0), .MREG(1), .PREG(1),
+    .USE_PATTERN_DETECT("PATDET"), .SEL_MASK("ROUNDING_MODE1")
+  ) dsp_0 (
+    .CLK(CLK),
+    .RSTA(1'b0), .RSTB(1'b0), .RSTM(1'b0), .RSTP(1'b0),
+    .CEA2(1'b1), .CEB2(1'b1), .CED(1'b0), .CEAD(1'b0), .CEM(1'b1), .CEP(1'b1),
+    .ALUMODE(4'b0000), .CARRYINSEL(3'b000), .INMODE(5'b00000), .OPMODE(7'b0110101),
+    .A({{(30-A_WIDTH){A[A_WIDTH-1]}}, A}),
+    .B({{(18-B_WIDTH){B[B_WIDTH-1]}}, B}),
+    .C({{(48-ONES){1'b0}}, {(ONES){1'b1}}}),
+    .CARRYIN(1'b0),
+    .PATTERNBDETECT(int_pbd_wire),
+    .P(int_p_wire)
+  );
+
+  assign P = {int_p_wire[SHIFT+P_WIDTH-1:SHIFT+1], int_p_wire[SHIFT] | int_pbd_wire};
+
+endmodule

+ 22 - 0
cores/edge_detector.v

@@ -0,0 +1,22 @@
+
+`timescale 1 ns / 1 ps
+
+module edge_detector
+(
+  input  wire aclk,
+
+  input  wire din,
+
+  output wire dout
+);
+
+  reg [1:0] int_data_reg;
+
+  always @(posedge aclk)
+  begin
+    int_data_reg <= {int_data_reg[0], din};
+  end
+
+  assign dout = ^int_data_reg;
+
+endmodule

+ 52 - 0
cores/gpio_debouncer.v

@@ -0,0 +1,52 @@
+
+`timescale 1 ns / 1 ps
+
+module gpio_debouncer #
+(
+  parameter integer DATA_WIDTH = 8,
+  parameter integer CNTR_WIDTH = 22
+)
+(
+  input  wire                  aclk,
+
+  inout  wire [DATA_WIDTH-1:0] gpio_data,
+
+  output wire [DATA_WIDTH-1:0] deb_data,
+  output wire [DATA_WIDTH-1:0] raw_data
+);
+
+  reg [DATA_WIDTH-1:0] int_data_reg [2:0];
+  reg [CNTR_WIDTH-1:0] int_cntr_reg [DATA_WIDTH-1:0];
+  wire [DATA_WIDTH-1:0] int_data_wire;
+
+  genvar j;
+
+  generate
+    for(j = 0; j < DATA_WIDTH; j = j + 1)
+    begin : GPIO
+      IOBUF gpio_iobuf (.O(int_data_wire[j]), .IO(gpio_data[j]), .I(1'b0), .T(1'b1));
+      always @(posedge aclk)
+      begin
+        if(int_data_reg[2][j] == int_data_reg[1][j])
+        begin
+          int_cntr_reg[j] <= {(CNTR_WIDTH){1'b0}};
+        end
+        else
+        begin
+          int_cntr_reg[j] <= int_cntr_reg[j] + 1'b1;
+          if(&int_cntr_reg[j]) int_data_reg[2][j] <= ~int_data_reg[2][j];
+        end
+      end
+    end
+  endgenerate
+
+  always @(posedge aclk)
+  begin
+    int_data_reg[0] <= int_data_wire;
+    int_data_reg[1] <= int_data_reg[0];
+  end
+
+  assign deb_data = int_data_reg[2];
+  assign raw_data = int_data_reg[1];
+
+endmodule

+ 16 - 0
cores/port_selector.v

@@ -0,0 +1,16 @@
+
+`timescale 1 ns / 1 ps
+
+module port_selector #
+(
+  parameter integer DOUT_WIDTH = 32
+)
+(
+  input  wire                    cfg,
+  input  wire [2*DOUT_WIDTH-1:0] din,
+  output wire [DOUT_WIDTH-1:0]   dout
+);
+
+  assign dout = cfg ? din[2*DOUT_WIDTH-1:DOUT_WIDTH] : din[DOUT_WIDTH-1:0];
+
+endmodule

+ 17 - 0
cores/port_slicer.v

@@ -0,0 +1,17 @@
+
+`timescale 1 ns / 1 ps
+
+module port_slicer #
+(
+  parameter integer DIN_WIDTH = 32,
+  parameter integer DIN_FROM = 31,
+  parameter integer DIN_TO = 0
+)
+(
+  input  wire [DIN_WIDTH-1:0]     din,
+  output wire [DIN_FROM-DIN_TO:0] dout
+);
+
+  assign dout = din[DIN_FROM:DIN_TO];
+
+endmodule

+ 82 - 0
cores/pulse_generator.v

@@ -0,0 +1,82 @@
+
+`timescale 1 ns / 1 ps
+
+module pulse_generator #
+(
+  parameter         CONTINUOUS = "FALSE"
+)
+(
+  input  wire        aclk,
+  input  wire        aresetn,
+
+  input  wire [95:0] cfg,
+
+  output wire        dout
+);
+
+  reg int_dout_reg, int_dout_next;
+  reg [31:0] int_cntr_reg, int_cntr_next;
+
+  always @(posedge aclk)
+  begin
+    if(~aresetn)
+    begin
+      int_dout_reg <= 1'b0;
+      int_cntr_reg <= 32'd0;
+    end
+    else
+    begin
+      int_dout_reg <= int_dout_next;
+      int_cntr_reg <= int_cntr_next;
+    end
+  end
+
+  always @*
+  begin
+    int_dout_next = int_dout_reg;
+
+    if(int_cntr_reg == cfg[31:0])
+    begin
+      int_dout_next = 1'b1;
+    end
+
+    if(int_cntr_reg == cfg[63:32])
+    begin
+      int_dout_next = 1'b0;
+    end
+  end
+
+  generate
+    if(CONTINUOUS == "TRUE")
+    begin : CONTINUE
+      always @*
+      begin
+        int_cntr_next = int_cntr_reg;
+
+        if(int_cntr_reg < cfg[95:64])
+        begin
+          int_cntr_next = int_cntr_reg + 1'b1;
+        end
+        else
+        begin
+          int_cntr_next = 32'd0;
+        end
+      end
+    end
+    else
+    begin : STOP
+      always @*
+      begin
+        int_cntr_next = int_cntr_reg;
+
+        if(int_cntr_reg < cfg[95:64])
+        begin
+          int_cntr_next = int_cntr_reg + 1'b1;
+        end
+      end
+    end
+  endgenerate
+
+  assign dout = int_dout_reg;
+
+endmodule

+ 26 - 0
cores/shift_register.v

@@ -0,0 +1,26 @@
+
+`timescale 1 ns / 1 ps
+
+module shift_register #
+(
+  parameter integer DATA_WIDTH = 8
+)
+(
+  input  wire                  aclk,
+
+  input  wire [DATA_WIDTH-1:0] din,
+
+  output wire [DATA_WIDTH-1:0] dout
+);
+
+  reg [DATA_WIDTH-1:0] int_data_reg [1:0];
+
+  always @(posedge aclk)
+  begin
+    int_data_reg[0] <= din;
+    int_data_reg[1] <= int_data_reg[0];
+  end
+
+  assign dout = int_data_reg[1];
+
+endmodule

+ 113 - 0
cores/xadc_bram.v

@@ -0,0 +1,113 @@
+
+`timescale 1 ns / 1 ps
+
+module xadc_bram
+(
+  // XADC inputs
+  (* X_INTERFACE_INFO = "xilinx.com:interface:diff_analog_io:1.0 Vp_Vn V_P" *)
+  input  wire        Vp_Vn_p,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:diff_analog_io:1.0 Vp_Vn V_N" *)
+  input  wire        Vp_Vn_n,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:diff_analog_io:1.0 Vaux0 V_P" *)
+  input  wire        Vaux0_p,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:diff_analog_io:1.0 Vaux0 V_N" *)
+  input  wire        Vaux0_n,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:diff_analog_io:1.0 Vaux1 V_P" *)
+  input  wire        Vaux1_p,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:diff_analog_io:1.0 Vaux1 V_N" *)
+  input  wire        Vaux1_n,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:diff_analog_io:1.0 Vaux8 V_P" *)
+  input  wire        Vaux8_p,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:diff_analog_io:1.0 Vaux8 V_N" *)
+  input  wire        Vaux8_n,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:diff_analog_io:1.0 Vaux9 V_P" *)
+  input  wire        Vaux9_p,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:diff_analog_io:1.0 Vaux9 V_N" *)
+  input  wire        Vaux9_n,
+
+  // BRAM port
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram CLK" *)
+  input  wire        b_bram_clk,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram RST" *)
+  input  wire        b_bram_rst,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram EN" *)
+  input  wire        b_bram_en,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram ADDR" *)
+  input  wire [4:0]  b_bram_addr,
+  (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b_bram DOUT" *)
+  output wire [15:0] b_bram_rdata
+);
+
+  wire [15:0] int_data_wire;
+  wire [4:0] int_addr_wire;
+  wire int_eoc_wire, int_we_wire;
+
+  XADC #(
+    .INIT_40(16'h0000),
+    .INIT_41(16'h8100),
+    .INIT_42(16'h1900),
+    .INIT_48(16'h0800),
+    .INIT_49(16'h0303),
+    .INIT_4A(16'h0000),
+    .INIT_4B(16'h0000),
+    .INIT_4C(16'h0000),
+    .INIT_4D(16'h0000),
+    .INIT_4E(16'h0000),
+    .INIT_4F(16'h0000),
+    .INIT_50(16'hb5ed),
+    .INIT_51(16'h57e4),
+    .INIT_52(16'ha147),
+    .INIT_53(16'hca33),
+    .INIT_54(16'ha93a),
+    .INIT_55(16'h52c6),
+    .INIT_56(16'h9555),
+    .INIT_57(16'hae4e),
+    .INIT_58(16'h5999),
+    .INIT_5C(16'h5111),
+    .INIT_59(16'h5555),
+    .INIT_5D(16'h5111),
+    .INIT_5A(16'h9999),
+    .INIT_5E(16'h91eb),
+    .INIT_5B(16'h6aaa),
+    .INIT_5F(16'h6666)
+  ) xadc_0 (
+    .DCLK(b_bram_clk),
+    .RESET(b_bram_rst),
+    .DEN(int_eoc_wire),
+    .DADDR({2'd0, int_addr_wire}),
+    .CHANNEL(int_addr_wire),
+    .DO(int_data_wire),
+    .DRDY(int_we_wire),
+    .EOC(int_eoc_wire),
+    .VN(Vp_Vn_n),
+    .VP(Vp_Vn_p),
+    .VAUXN({6'd0,Vaux9_n,Vaux8_n,6'd0,Vaux1_n,Vaux0_n}),
+    .VAUXP({6'd0,Vaux9_p,Vaux8_p,6'd0,Vaux1_p,Vaux0_p})
+  );
+
+  xpm_memory_dpdistram #(
+    .ADDR_WIDTH_A(5),
+    .ADDR_WIDTH_B(5),
+    .MEMORY_SIZE(512),
+    .BYTE_WRITE_WIDTH_A(16),
+    .WRITE_DATA_WIDTH_A(16),
+    .READ_DATA_WIDTH_A(16),
+    .READ_DATA_WIDTH_B(16),
+    .READ_LATENCY_A(1),
+    .READ_LATENCY_B(1)
+  ) ram_0 (
+    .clka(b_bram_clk),
+    .rsta(b_bram_rst),
+    .rstb(b_bram_rst),
+    .addra(int_addr_wire),
+    .dina(int_data_wire),
+    .ena(int_we_wire),
+    .wea(int_we_wire),
+    .regcea(1'b0),
+    .addrb(b_bram_addr),
+    .doutb(b_bram_rdata),
+    .enb(b_bram_en),
+    .regceb(b_bram_en)
+  );
+
+endmodule

+ 11 - 0
debian/etc/apt/sources.list.d/debian.sources

@@ -0,0 +1,11 @@
+Types: deb deb-src
+URIs: http://deb.debian.org/debian/
+Suites: trixie trixie-updates
+Components: main contrib non-free-firmware
+Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
+
+Types: deb deb-src
+URIs: http://security.debian.org/debian-security/
+Suites: trixie-security
+Components: main contrib non-free-firmware
+Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

+ 61 - 0
debian/etc/dhcpcd.conf

@@ -0,0 +1,61 @@
+# Inform the DHCP server of our hostname for DDNS.
+hostname
+
+# Use the hardware address of the interface for the Client ID.
+clientid
+
+# Rapid commit support.
+# Safe to enable by default because it requires the equivalent option set
+# on the server to actually work.
+option rapid_commit
+
+# A list of options to request from the DHCP server.
+option domain_name_servers, domain_name, domain_search, host_name
+option classless_static_routes
+# Most distributions have NTP support.
+option ntp_servers
+# Respect the network MTU. This is applied to DHCP routes.
+option interface_mtu
+
+# A ServerID is required by RFC2131.
+require dhcp_server_identifier
+
+# Generate Stable Private IPv6 Addresses instead of hardware based ones.
+slaac private
+
+# Don't send any ARP requests.
+noarp
+
+# Only configure IPv4.
+ipv4only
+
+# Wait 20 seconds before falling back to static profile.
+reboot 20
+
+# Configure loopback interface.
+interface lo
+static ip_address=127.0.0.1/8
+
+# Define static profile for eth0.
+profile static_eth0
+static ip_address=192.168.1.100/24
+static routers=192.168.1.1
+static domain_name_servers=192.168.1.1
+
+# Fallback to static profile on eth0.
+interface eth0
+fallback static_eth0
+
+# Define static profile for mvl0.
+profile static_mvl0
+static ip_address=192.168.1.101/24
+static routers=192.168.1.1
+static domain_name_servers=192.168.1.1
+
+# Fallback to static profile on mvl0.
+interface mvl0
+fallback static_mvl0
+
+# Static IP address for Wi-Fi access point.
+interface wlan0
+static ip_address=192.168.42.1/24

+ 22 - 0
debian/etc/dhcpcd.exit-hook

@@ -0,0 +1,22 @@
+ap_start () {
+  service hostapd restart
+  service dnsmasq restart
+  iptables-restore < /etc/iptables.ipv4.nat
+}
+
+ap_stop () {
+  service hostapd stop
+  service dnsmasq stop
+  iptables-restore < /etc/iptables.ipv4.nonat
+}
+
+if [ "$interface" = wlan0 ]; then
+  case "$reason" in
+    PREINIT) (sleep 3; ap_start > /dev/null 2>&1) & ;;
+    DEPARTED) (sleep 3; ap_stop > /dev/null 2>&1) & ;;
+  esac
+fi
+
+if $if_up; then
+  (sleep 3; chronyc online > /dev/null 2>&1) &
+fi

+ 2 - 0
debian/etc/dnsmasq.d/ap.conf

@@ -0,0 +1,2 @@
+interface=wlan0
+dhcp-range=192.168.42.20,192.168.42.254,12h

+ 4 - 0
debian/etc/fstab

@@ -0,0 +1,4 @@
+# /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

+ 2 - 0
debian/etc/fw_env.config

@@ -0,0 +1,2 @@
+# MTD device name                       Device offset   Environment size
+/sys/bus/i2c/devices/0-0050/eeprom      0x1800          0x0400

+ 11 - 0
debian/etc/hostapd/hostapd.conf

@@ -0,0 +1,11 @@
+interface=wlan0
+ssid=RedPitaya
+driver=nl80211
+hw_mode=g
+channel=6
+auth_algs=1
+wpa=2
+wpa_passphrase=RedPitaya
+wpa_key_mgmt=WPA-PSK
+wpa_pairwise=CCMP
+rsn_pairwise=CCMP

+ 1 - 0
debian/etc/hostname

@@ -0,0 +1 @@
+red-pitaya

+ 21 - 0
debian/etc/iptables.ipv4.nat

@@ -0,0 +1,21 @@
+*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

+ 18 - 0
debian/etc/iptables.ipv4.nonat

@@ -0,0 +1,18 @@
+*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

+ 2 - 0
debian/etc/securetty

@@ -0,0 +1,2 @@
+# Serial Console for Xilinx Zynq-7000
+ttyPS0

+ 1 - 0
debian/etc/sysctl.d/99-net.conf

@@ -0,0 +1 @@
+net.ipv4.ip_forward = 1

+ 14 - 0
debian/etc/systemd/system/dhcpcd.service

@@ -0,0 +1,14 @@
+[Unit]
+Description=DHCP Client Daemon on all interfaces
+Wants=network.target
+Before=network.target
+
+[Service]
+Type=forking
+PIDFile=/run/dhcpcd/pid
+ExecStart=/usr/sbin/dhcpcd -q -b
+ExecStop=/usr/sbin/dhcpcd -x
+Restart=always
+
+[Install]
+WantedBy=multi-user.target

+ 0 - 0
debian/etc/udev/rules.d/80-net-setup-link.rules


+ 5 - 0
debian/etc/wpa_supplicant/wpa_supplicant.conf

@@ -0,0 +1,5 @@
+network={
+	ssid="RedPitaya"
+	#psk="RedPitaya"
+	psk=b9a64d92624634bd901c554a22794567fd6a9e6c6e686d475d6aea6c2f13fdf3
+}

+ 161 - 0
scripts/alpine-project.sh

@@ -0,0 +1,161 @@
+alpine_url=http://dl-cdn.alpinelinux.org/alpine/v3.22
+
+tools_tar=apk-tools-static-2.14.9-r3.apk
+tools_url=$alpine_url/main/armv7/$tools_tar
+
+firmware_tar=linux-firmware-other-20250509-r0.apk
+firmware_url=$alpine_url/main/armv7/$firmware_tar
+
+linux_dir=tmp/linux-6.12
+linux_ver=6.12.52-xilinx
+
+modules_dir=alpine-modloop/lib/modules/$linux_ver
+
+passwd=changeme
+
+project=$1
+
+test -f $tools_tar || curl -L $tools_url -o $tools_tar
+
+test -f $firmware_tar || curl -L $firmware_url -o $firmware_tar
+
+for tar in linux-firmware-ath9k_htc-20250509-r0.apk linux-firmware-brcm-20250509-r0.apk linux-firmware-cypress-20250509-r0.apk linux-firmware-rtlwifi-20250509-r0.apk
+do
+  url=$alpine_url/main/armv7/$tar
+  test -f $tar || curl -L $url -o $tar
+done
+
+mkdir alpine-apk
+tar -zxf $tools_tar --directory=alpine-apk --warning=no-unknown-keyword
+
+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 alpine-modloop $linux_ver
+
+tar -zxf $firmware_tar --directory=alpine-modloop/lib/modules --warning=no-unknown-keyword --strip-components=1 --wildcards lib/firmware/ar* lib/firmware/rt*
+
+for tar in linux-firmware-ath9k_htc-20250509-r0.apk linux-firmware-brcm-20250509-r0.apk linux-firmware-cypress-20250509-r0.apk linux-firmware-rtlwifi-20250509-r0.apk
+do
+  tar -zxf $tar --directory=alpine-modloop/lib/modules --warning=no-unknown-keyword --strip-components=1
+done
+
+mksquashfs alpine-modloop/lib modloop -b 1048576 -comp xz -Xdict-size 100%
+
+rm -rf alpine-modloop
+
+root_dir=alpine-root
+
+mkdir -p $root_dir/usr/bin
+cp /usr/bin/qemu-arm-static $root_dir/usr/bin/
+
+mkdir -p $root_dir/etc
+cp /etc/resolv.conf $root_dir/etc/
+
+mkdir -p $root_dir/etc/apk
+mkdir -p $root_dir/media/mmcblk0p1/cache
+ln -s /media/mmcblk0p1/cache $root_dir/etc/apk/cache
+
+cp -r alpine/etc $root_dir/
+sed -i '1,2d' $root_dir/etc/local.d/apps.start
+mkdir $root_dir/media/mmcblk0p1/apps
+
+mkdir -p $root_dir/media/mmcblk0p1/apps/$project
+cp -r projects/$project/server/* $root_dir/media/mmcblk0p1/apps/$project/
+cp -r projects/$project/app/* $root_dir/media/mmcblk0p1/apps/$project/
+cp tmp/$project.bit $root_dir/media/mmcblk0p1/apps/$project/
+
+cp -r alpine-apk/sbin $root_dir/
+
+chroot $root_dir /sbin/apk.static --repository $alpine_url/main --update-cache --allow-untrusted --initdb add alpine-base
+
+echo $alpine_url/main > $root_dir/etc/apk/repositories
+echo $alpine_url/community >> $root_dir/etc/apk/repositories
+
+chroot $root_dir /bin/sh <<- EOF_CHROOT
+
+apk update
+apk add openssh u-boot-tools iw wpa_supplicant dhcpcd dnsmasq hostapd iptables avahi dbus dcron chrony musl-dev curl wget less nano bc
+
+rc-update add bootmisc boot
+rc-update add hostname boot
+rc-update add swclock boot
+rc-update add sysctl boot
+rc-update add syslog boot
+rc-update add seedrng boot
+
+rc-update add killprocs shutdown
+rc-update add mount-ro shutdown
+rc-update add savecache shutdown
+
+rc-update add devfs sysinit
+rc-update add dmesg sysinit
+rc-update add mdev sysinit
+rc-update add hwdrivers sysinit
+rc-update add modloop sysinit
+
+rc-update add avahi-daemon default
+rc-update add chronyd default
+rc-update add dhcpcd default
+rc-update add local default
+rc-update add dcron default
+rc-update add sshd default
+
+mkdir -p etc/runlevels/wifi
+rc-update -s add default wifi
+
+rc-update add iptables wifi
+rc-update add dnsmasq wifi
+rc-update add hostapd wifi
+
+sed -i 's/^SAVE_ON_STOP=.*/SAVE_ON_STOP="no"/;s/^IPFORWARD=.*/IPFORWARD="yes"/' etc/conf.d/iptables
+
+sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' etc/ssh/sshd_config
+
+echo root:$passwd | chpasswd
+
+hostname red-pitaya
+
+sed -i 's/^# LBU_MEDIA=.*/LBU_MEDIA=mmcblk0p1/' etc/lbu/lbu.conf
+
+cat <<- EOF_CAT > root/.profile
+alias rw='mount -o rw,remount /media/mmcblk0p1'
+alias ro='mount -o ro,remount /media/mmcblk0p1'
+EOF_CAT
+
+ln -s /media/mmcblk0p1/apps root/apps
+ln -s /media/mmcblk0p1/wifi root/wifi
+
+lbu add root
+lbu delete etc/resolv.conf
+lbu delete root/.ash_history
+
+lbu commit -d
+
+apk add make gcc
+
+make -C /media/mmcblk0p1/apps/$project clean
+make -C /media/mmcblk0p1/apps/$project
+
+EOF_CHROOT
+
+cp -r $root_dir/media/mmcblk0p1/apps .
+cp -r $root_dir/media/mmcblk0p1/cache .
+cp $root_dir/media/mmcblk0p1/red-pitaya.apkovl.tar.gz .
+
+sed -i '5,6d' apps/$project/start.sh
+rm -f apps/$project/index.html
+cp apps/$project/start.sh .
+
+cp -r alpine/wifi .
+
+hostname -F /etc/hostname
+
+rm -rf $root_dir alpine-apk
+
+zip -r red-pitaya-alpine-3.22-armv7-`date +%Y%m%d`-$project.zip apps boot.bin cache modloop red-pitaya.apkovl.tar.gz start.sh wifi
+
+rm -rf apps cache modloop red-pitaya.apkovl.tar.gz start.sh wifi

+ 188 - 0
scripts/alpine.sh

@@ -0,0 +1,188 @@
+alpine_url=http://dl-cdn.alpinelinux.org/alpine/v3.22
+
+tools_tar=apk-tools-static-2.14.9-r3.apk
+tools_url=$alpine_url/main/armv7/$tools_tar
+
+firmware_tar=linux-firmware-other-20250509-r0.apk
+firmware_url=$alpine_url/main/armv7/$firmware_tar
+
+linux_dir=tmp/linux-6.12
+linux_ver=6.12.52-xilinx
+
+modules_dir=alpine-modloop/lib/modules/$linux_ver
+
+passwd=changeme
+
+test -f $tools_tar || curl -L $tools_url -o $tools_tar
+
+test -f $firmware_tar || curl -L $firmware_url -o $firmware_tar
+
+for tar in linux-firmware-ath9k_htc-20250509-r0.apk linux-firmware-brcm-20250509-r0.apk linux-firmware-cypress-20250509-r0.apk linux-firmware-rtlwifi-20250509-r0.apk
+do
+  url=$alpine_url/main/armv7/$tar
+  test -f $tar || curl -L $url -o $tar
+done
+
+mkdir alpine-apk
+tar -zxf $tools_tar --directory=alpine-apk --warning=no-unknown-keyword
+
+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 alpine-modloop $linux_ver
+
+tar -zxf $firmware_tar --directory=alpine-modloop/lib/modules --warning=no-unknown-keyword --strip-components=1 --wildcards lib/firmware/ar* lib/firmware/rt*
+
+for tar in linux-firmware-ath9k_htc-20250509-r0.apk linux-firmware-brcm-20250509-r0.apk linux-firmware-cypress-20250509-r0.apk linux-firmware-rtlwifi-20250509-r0.apk
+do
+  tar -zxf $tar --directory=alpine-modloop/lib/modules --warning=no-unknown-keyword --strip-components=1
+done
+
+mksquashfs alpine-modloop/lib modloop -b 1048576 -comp xz -Xdict-size 100%
+
+rm -rf alpine-modloop
+
+root_dir=alpine-root
+
+mkdir -p $root_dir/usr/bin
+cp /usr/bin/qemu-arm-static $root_dir/usr/bin/
+
+mkdir -p $root_dir/etc
+cp /etc/resolv.conf $root_dir/etc/
+
+mkdir -p $root_dir/etc/apk
+mkdir -p $root_dir/media/mmcblk0p1/cache
+ln -s /media/mmcblk0p1/cache $root_dir/etc/apk/cache
+
+cp -r alpine/etc $root_dir/
+cp -r alpine/apps $root_dir/media/mmcblk0p1/
+
+projects="common_tools led_blinker mcpha playground pulsed_nmr sdr_receiver sdr_receiver_hpsdr sdr_receiver_wide sdr_transceiver sdr_transceiver_ft8 sdr_transceiver_hpsdr sdr_transceiver_wide sdr_transceiver_wspr vna"
+
+projects_122_88="led_blinker_122_88 pulsed_nmr_122_88 sdr_receiver_122_88 sdr_receiver_hpsdr_122_88 sdr_receiver_wide_122_88 sdr_transceiver_122_88 sdr_transceiver_ft8_122_88 sdr_transceiver_hpsdr_122_88 sdr_transceiver_wspr_122_88 vna_122_88"
+
+for p in $projects $projects_122_88
+do
+  mkdir -p $root_dir/media/mmcblk0p1/apps/$p
+  cp -r projects/$p/server/* $root_dir/media/mmcblk0p1/apps/$p/
+  cp -r projects/$p/app/* $root_dir/media/mmcblk0p1/apps/$p/
+  cp tmp/$p.bit $root_dir/media/mmcblk0p1/apps/$p/
+done
+
+cp -r alpine-apk/sbin $root_dir/
+
+chroot $root_dir /sbin/apk.static --repository $alpine_url/main --update-cache --allow-untrusted --initdb add alpine-base
+
+echo $alpine_url/main > $root_dir/etc/apk/repositories
+echo $alpine_url/community >> $root_dir/etc/apk/repositories
+
+chroot $root_dir /bin/sh <<- EOF_CHROOT
+
+apk update
+apk add openssh u-boot-tools ucspi-tcp6 iw wpa_supplicant dhcpcd dnsmasq hostapd iptables avahi dbus dcron chrony gpsd libgfortran musl-dev libconfig-dev alsa-lib-dev alsa-utils curl wget less nano bc dos2unix
+
+rc-update add bootmisc boot
+rc-update add hostname boot
+rc-update add swclock boot
+rc-update add sysctl boot
+rc-update add syslog boot
+rc-update add seedrng boot
+
+rc-update add killprocs shutdown
+rc-update add mount-ro shutdown
+rc-update add savecache shutdown
+
+rc-update add devfs sysinit
+rc-update add dmesg sysinit
+rc-update add mdev sysinit
+rc-update add hwdrivers sysinit
+rc-update add modloop sysinit
+
+rc-update add avahi-daemon default
+rc-update add chronyd default
+rc-update add dhcpcd default
+rc-update add local default
+rc-update add dcron default
+rc-update add sshd default
+
+mkdir -p etc/runlevels/wifi
+rc-update -s add default wifi
+
+rc-update add iptables wifi
+rc-update add dnsmasq wifi
+rc-update add hostapd wifi
+
+sed -i 's/^SAVE_ON_STOP=.*/SAVE_ON_STOP="no"/;s/^IPFORWARD=.*/IPFORWARD="yes"/' etc/conf.d/iptables
+
+sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' etc/ssh/sshd_config
+
+echo root:$passwd | chpasswd
+
+hostname red-pitaya
+
+sed -i 's/^# LBU_MEDIA=.*/LBU_MEDIA=mmcblk0p1/' etc/lbu/lbu.conf
+
+cat <<- EOF_CAT > root/.profile
+alias rw='mount -o rw,remount /media/mmcblk0p1'
+alias ro='mount -o ro,remount /media/mmcblk0p1'
+EOF_CAT
+
+ln -s /media/mmcblk0p1/apps root/apps
+ln -s /media/mmcblk0p1/wifi root/wifi
+
+lbu add root
+lbu delete etc/resolv.conf
+lbu delete etc/cron.d/ft8
+lbu delete etc/cron.d/ft8_122_88
+lbu delete etc/cron.d/wspr
+lbu delete etc/cron.d/wspr_122_88
+lbu delete root/.ash_history
+
+lbu commit -d
+
+apk add make gcc gfortran linux-headers
+
+ft8d_dir=/media/mmcblk0p1/apps/ft8d
+ft8d_tar=/media/mmcblk0p1/apps/ft8d.tar.gz
+ft8d_url=https://github.com/pavel-demin/ft8d/archive/master.tar.gz
+
+curl -L \$ft8d_url -o \$ft8d_tar
+mkdir -p \$ft8d_dir
+tar -zxf \$ft8d_tar --strip-components=1 --directory=\$ft8d_dir
+rm \$ft8d_tar
+make -C \$ft8d_dir
+
+wsprd_dir=/media/mmcblk0p1/apps/wsprd
+wsprd_tar=/media/mmcblk0p1/apps/wsprd.tar.gz
+wsprd_url=https://github.com/pavel-demin/wsprd/archive/master.tar.gz
+
+curl -L \$wsprd_url -o \$wsprd_tar
+mkdir -p \$wsprd_dir
+tar -zxf \$wsprd_tar --strip-components=1 --directory=\$wsprd_dir
+rm \$wsprd_tar
+make -C \$wsprd_dir
+
+for p in server $projects $projects_122_88
+do
+  make -C /media/mmcblk0p1/apps/\$p clean
+  make -C /media/mmcblk0p1/apps/\$p
+done
+
+EOF_CHROOT
+
+cp -r $root_dir/media/mmcblk0p1/apps .
+cp -r $root_dir/media/mmcblk0p1/cache .
+cp $root_dir/media/mmcblk0p1/red-pitaya.apkovl.tar.gz .
+
+cp -r alpine/wifi .
+
+hostname -F /etc/hostname
+
+rm -rf $root_dir alpine-apk
+
+zip -r red-pitaya-alpine-3.22-armv7-`date +%Y%m%d`.zip apps boot.bin cache modloop red-pitaya.apkovl.tar.gz wifi
+
+rm -rf apps cache modloop red-pitaya.apkovl.tar.gz wifi

+ 22 - 0
scripts/app_cpu1.tcl

@@ -0,0 +1,22 @@
+
+set project_name [lindex $argv 0]
+
+set proc_name ps7_cortexa9_1
+
+set hard_path tmp/$project_name.hard
+set cpu1_path tmp/$project_name.cpu1
+
+file mkdir $hard_path
+file copy -force tmp/$project_name.hwdef $hard_path/$project_name.hdf
+
+open_hw_design $hard_path/$project_name.hdf
+create_sw_design -proc $proc_name -os standalone system
+
+set_property CONFIG.stdin {none} [get_os]
+set_property CONFIG.stdout {none} [get_os]
+
+set_property CONFIG.extra_compiler_flags { -g -DUSE_AMP=1 -DSTDOUT_REDIR=1} [get_sw_processor]
+
+generate_bsp -proc $proc_name -dir $cpu1_path/app_cpu1_bsp
+
+close_hw_design [current_hw_design]

+ 17 - 0
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
+  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

+ 35 - 0
scripts/core.tcl

@@ -0,0 +1,35 @@
+
+set core_name [lindex $argv 0]
+
+set part_name [lindex $argv 1]
+
+file delete -force tmp/cores/$core_name tmp/cores/$core_name.cache tmp/cores/$core_name.hw tmp/cores/$core_name.ip_user_files tmp/cores/$core_name.sim tmp/cores/$core_name.xpr
+
+create_project -part $part_name $core_name tmp/cores
+
+add_files -norecurse cores/$core_name.v
+
+set_property TOP $core_name [current_fileset]
+
+set files [glob -nocomplain modules/*.v]
+if {[llength $files] > 0} {
+  add_files -norecurse $files
+}
+
+ipx::package_project -root_dir tmp/cores/$core_name
+
+set core [ipx::current_core]
+
+set_property VERSION {1.0} $core
+set_property NAME $core_name $core
+set_property LIBRARY {user} $core
+set_property VENDOR {pavel-demin} $core
+set_property VENDOR_DISPLAY_NAME {Pavel Demin} $core
+set_property COMPANY_URL {https://github.com/pavel-demin/red-pitaya-notes} $core
+set_property SUPPORTED_FAMILIES {zynq Production} $core
+
+ipx::create_xgui_files $core
+ipx::update_checksums $core
+ipx::save_core $core
+
+close_project

+ 124 - 0
scripts/debian.sh

@@ -0,0 +1,124 @@
+device=$1
+
+boot_dir=`mktemp -d /tmp/BOOT.XXXXXXXXXX`
+root_dir=`mktemp -d /tmp/ROOT.XXXXXXXXXX`
+
+linux_dir=tmp/linux-6.12
+linux_ver=6.12.52-xilinx
+
+# Choose mirror automatically, depending the geographic and network location
+mirror=http://deb.debian.org/debian
+
+distro=trixie
+arch=armhf
+
+passwd=changeme
+timezone=Europe/Brussels
+
+# 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-rootfs.bin $boot_dir/boot.bin
+
+# 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/
+
+rm $root_dir/etc/apt/sources.list
+
+cp -r debian/etc/apt $root_dir/etc/
+cp -r debian/etc/systemd $root_dir/etc/
+
+chroot $root_dir <<- EOF_CHROOT
+export LANG=C
+export LC_ALL=C
+export DEBIAN_FRONTEND=noninteractive
+export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+
+/debootstrap/debootstrap --second-stage
+
+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 tzdata
+
+apt-get -y install openssh-server ca-certificates chrony fake-hwclock \
+  usbutils psmisc lsof parted curl vim wpasupplicant hostapd dnsmasq \
+  firmware-atheros firmware-brcm80211 firmware-mediatek firmware-realtek \
+  iw iptables dhcpcd-base ntfs-3g libubootenv-tool
+
+systemctl enable dhcpcd
+
+systemctl disable hostapd
+systemctl disable dnsmasq
+systemctl disable nftables
+systemctl disable wpa_supplicant
+
+sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' etc/ssh/sshd_config
+
+echo root:$passwd | chpasswd
+
+apt-get clean
+
+service chrony stop
+service ssh stop
+
+history -c
+
+sync
+EOF_CHROOT
+
+cp -r debian/etc $root_dir/
+
+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

+ 22 - 0
scripts/devicetree.tcl

@@ -0,0 +1,22 @@
+
+set project_name [lindex $argv 0]
+
+set proc_name [lindex $argv 1]
+
+set repo_path [lindex $argv 2]
+
+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 generate_target -dir $tree_path
+
+hsi close_sw_design [hsi current_sw_design]
+hsi close_hw_design [hsi current_hw_design]

+ 20 - 0
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]

+ 8 - 0
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

+ 19 - 0
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
+
+device=`losetup -f`
+
+losetup $device $image
+
+sh $script $device
+
+losetup -d $device

+ 133 - 0
scripts/project.tcl

@@ -0,0 +1,133 @@
+
+package require fileutil
+
+set project_name [lindex $argv 0]
+
+set part_name [lindex $argv 1]
+
+file delete -force tmp/$project_name.cache tmp/$project_name.gen tmp/$project_name.hw tmp/$project_name.ip_user_files tmp/$project_name.runs tmp/$project_name.sim tmp/$project_name.srcs tmp/$project_name.xpr
+
+create_project -part $part_name $project_name tmp
+
+set_property IP_REPO_PATHS tmp/cores [current_project]
+
+update_ip_catalog
+
+proc wire {name1 name2} {
+  set port1 [get_bd_pins $name1]
+  set port2 [get_bd_pins $name2]
+  if {[llength $port1] == 1 && [llength $port2] == 1} {
+    connect_bd_net $port1 $port2
+    return
+  }
+  set port1 [get_bd_intf_pins $name1]
+  set port2 [get_bd_intf_pins $name2]
+  if {[llength $port1] == 1 && [llength $port2] == 1} {
+    connect_bd_intf_net $port1 $port2
+    return
+  }
+  error "** ERROR: can't connect $name1 and $name2"
+}
+
+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]] {
+    wire $cell_name/$local_name $remote_name
+  }
+}
+
+proc module {module_name module_body {module_ports {}}} {
+  set instance [current_bd_instance .]
+  current_bd_instance [create_bd_cell -type hier $module_name]
+  eval $module_body
+  current_bd_instance $instance
+  foreach {local_name remote_name} [uplevel 1 [list subst $module_ports]] {
+    wire $module_name/$local_name $remote_name
+  }
+}
+
+proc design {design_name design_body} {
+  set design [current_bd_design]
+  create_bd_design $design_name
+  eval $design_body
+  validate_bd_design
+  save_bd_design
+  current_bd_design $design
+}
+
+proc container {container_name container_designs {container_ports {}}} {
+  set reference [lindex $container_designs 0]
+  set container [create_bd_cell -type container -reference $reference $container_name]
+  foreach {local_name remote_name} [uplevel 1 [list subst $container_ports]] {
+    wire $container_name/$local_name $remote_name
+  }
+  set list {}
+  foreach item $container_designs {
+    lappend list $item.bd
+  }
+  set list [join $list :]
+  set_property CONFIG.ENABLE_DFX true $container
+  set_property CONFIG.LIST_SYNTH_BD $list $container
+  set_property CONFIG.LIST_SIM_BD $list $container
+}
+
+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
+}
+
+create_bd_design system
+
+source cfg/ports.tcl
+source projects/$project_name/block_design.tcl
+
+rename wire {}
+rename cell {}
+rename module {}
+rename design {}
+rename container {}
+rename addr {}
+
+set system [get_files system.bd]
+
+set_property SYNTH_CHECKPOINT_MODE None $system
+
+generate_target all $system
+make_wrapper -files $system -top
+
+foreach ext {srcs gen} {
+  set files [fileutil::findByPattern tmp/$project_name.$ext system_wrapper.v]
+  if {[llength $files] > 0} {
+    add_files -norecurse $files
+    break
+  }
+}
+
+set_property TOP system_wrapper [current_fileset]
+
+set files [glob -nocomplain cfg/*.mem projects/$project_name/*.v projects/$project_name/*.sv]
+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 VERILOG_DEFINE {TOOL_VIVADO} [current_fileset]
+
+set_property STRATEGY Flow_PerfOptimized_high [get_runs synth_1]
+set_property STRATEGY Performance_ExploreWithRemap [get_runs impl_1]
+
+close_project