├── LICENSE ├── Makefile ├── README ├── alpine ├── apps │ ├── css │ │ ├── main.css │ │ └── pygments.css │ ├── index.html │ ├── server │ │ ├── Makefile │ │ └── server.c │ └── stop.sh ├── etc │ ├── avahi │ │ └── services │ │ │ ├── http.service │ │ │ ├── sftp-ssh.service │ │ │ └── ssh.service │ ├── chrony │ │ └── chrony.conf │ ├── conf.d │ │ ├── gpsd │ │ ├── hostname │ │ ├── modloop │ │ └── syslog │ ├── dhcpcd.conf │ ├── dhcpcd.exit-hook │ ├── dnsmasq.d │ │ └── ap.conf │ ├── hostapd │ │ └── hostapd.conf │ ├── iptables │ │ └── rules-save │ ├── local.d │ │ └── apps.start │ └── wpa_supplicant │ │ └── wpa_supplicant.conf └── wifi │ ├── client.sh │ └── hotspot.sh ├── cfg ├── clocks.xdc ├── dds.mem ├── ports.tcl ├── ports.xdc └── qmtech_xc7z020.xml ├── cores ├── axi_hub.py ├── axi_hub.v ├── axis_adc_ddr.v ├── axis_fifo.v ├── axis_maxabs_finder.v ├── axis_pps_counter.v ├── axis_variable.v ├── dds.v ├── dsp48.v └── port_slicer.v ├── dts ├── common.dts └── initrd.dts ├── helpers ├── build-all.sh ├── build-cores.tcl └── dds-mem.py ├── mac.txt ├── modules ├── inout_buffer.v ├── input_buffer.v └── output_buffer.v ├── patches ├── cma.c ├── fsbl.patch ├── initramfs.patch ├── linux-6.6.patch ├── qmtech_xc7z020_fsbl_hooks.c ├── xilinx_devcfg.c └── xilinx_zynq_defconfig ├── projects ├── common_tools │ ├── app │ │ ├── Makefile │ │ ├── enable-adc.sh │ │ ├── measure-corr.c │ │ ├── measure-level.c │ │ ├── setup-adc.c │ │ ├── sleep-rand.c │ │ ├── sleep-to-59.c │ │ └── update-corr.sh │ └── block_design.tcl ├── led_blinker_77_76 │ ├── app │ │ ├── index.html │ │ └── start.sh │ ├── block_design.tcl │ └── ports.xdc ├── sdr_receiver_77_76 │ ├── app │ │ ├── index.html │ │ ├── start.sh │ │ └── stop.sh │ ├── block_design.tcl │ ├── client │ │ ├── convert.py │ │ └── record.py │ ├── filters │ │ └── rx_fir_0.r │ ├── ports.xdc │ ├── rx.tcl │ └── server │ │ ├── Makefile │ │ └── sdr-receiver.c ├── sdr_receiver_ft8_77_76 │ ├── app │ │ ├── Makefile │ │ ├── decode-ft8.sh │ │ ├── ft8.cron │ │ ├── index.html │ │ ├── start.sh │ │ ├── stop.sh │ │ ├── upload-ft8.sh │ │ ├── upload-to-pskreporter.c │ │ ├── write-c2-files.c │ │ └── write-c2-files.cfg │ ├── block_design.tcl │ ├── filters │ │ └── rx_fir_0.r │ ├── ports.xdc │ └── rx.tcl ├── sdr_receiver_hpsdr_77_76 │ ├── app │ │ ├── index.html │ │ ├── start.sh │ │ └── stop.sh │ ├── block_design.tcl │ ├── filters │ │ └── rx_fir_0.r │ ├── ports.xdc │ ├── rx.tcl │ └── server │ │ ├── Makefile │ │ └── sdr-receiver-hpsdr.c └── sdr_receiver_wspr_77_76 │ ├── app │ ├── Makefile │ ├── decode-wspr.sh │ ├── index.html │ ├── start.sh │ ├── stop.sh │ ├── write-c2-files.c │ ├── write-c2-files.cfg │ └── wspr.cron │ ├── block_design.tcl │ ├── filters │ └── rx_fir_0.r │ ├── ports.xdc │ └── rx.tcl └── scripts ├── alpine.sh ├── bitstream.tcl ├── core.tcl ├── devicetree.tcl ├── fsbl.tcl ├── hwdef.tcl └── project.tcl /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2024 Pavel Demin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 'make' builds everything 2 | # 'make clean' deletes everything except source files and Makefile 3 | # 4 | # You need to set NAME, PART and PROC for your project. 5 | # NAME is the base name for most of the generated files. 6 | 7 | NAME = led_blinker 8 | PART = xc7z020clg484-1 9 | PROC = ps7_cortexa9_0 10 | 11 | FILES = $(wildcard cores/*.v) 12 | CORES = $(FILES:.v=) 13 | 14 | VIVADO = vivado -nolog -nojournal -mode batch 15 | XSCT = xsct 16 | RM = rm -rf 17 | 18 | INITRAMFS_TAG = 3.20 19 | LINUX_TAG = 6.6 20 | DTREE_TAG = xilinx_v2023.1 21 | 22 | INITRAMFS_DIR = tmp/initramfs-$(INITRAMFS_TAG) 23 | LINUX_DIR = tmp/linux-$(LINUX_TAG) 24 | DTREE_DIR = tmp/device-tree-xlnx-$(DTREE_TAG) 25 | 26 | LINUX_TAR = tmp/linux-$(LINUX_TAG).tar.xz 27 | DTREE_TAR = tmp/device-tree-xlnx-$(DTREE_TAG).tar.gz 28 | 29 | INITRAMFS_URL = https://dl-cdn.alpinelinux.org/alpine/v$(INITRAMFS_TAG)/releases/armv7/netboot/initramfs-lts 30 | LINUX_URL = https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-$(LINUX_TAG).44.tar.xz 31 | DTREE_URL = https://github.com/Xilinx/device-tree-xlnx/archive/$(DTREE_TAG).tar.gz 32 | 33 | SSBL_URL = https://github.com/pavel-demin/ssbl/releases/latest/download/ssbl.elf 34 | 35 | RTL8188_TAR = tmp/rtl8188eu-main.tar.gz 36 | RTL8188_URL = https://github.com/pavel-demin/rtl8188eu/archive/main.tar.gz 37 | 38 | .PRECIOUS: tmp/cores/% tmp/%.xpr tmp/%.xsa tmp/%.bit tmp/%.fsbl/executable.elf tmp/%.tree/system-top.dts 39 | 40 | all: tmp/$(NAME).bit boot.bin 41 | 42 | cores: $(addprefix tmp/, $(CORES)) 43 | 44 | xpr: tmp/$(NAME).xpr 45 | 46 | bit: tmp/$(NAME).bit 47 | 48 | $(LINUX_TAR): 49 | mkdir -p $(@D) 50 | curl -L $(LINUX_URL) -o $@ 51 | 52 | $(DTREE_TAR): 53 | mkdir -p $(@D) 54 | curl -L $(DTREE_URL) -o $@ 55 | 56 | $(RTL8188_TAR): 57 | mkdir -p $(@D) 58 | curl -L $(RTL8188_URL) -o $@ 59 | 60 | $(INITRAMFS_DIR): 61 | mkdir -p $@ 62 | curl -L $(INITRAMFS_URL) | gunzip | cpio -id --directory=$@ 63 | patch -d $@ -p 0 < patches/initramfs.patch 64 | rm -rf $@/etc/modprobe.d $@/lib/firmware $@/lib/modules $@/var 65 | 66 | $(LINUX_DIR): $(LINUX_TAR) $(RTL8188_TAR) 67 | mkdir -p $@ 68 | tar -Jxf $< --strip-components=1 --directory=$@ 69 | mkdir -p $@/drivers/net/wireless/realtek/rtl8188eu 70 | tar -zxf $(RTL8188_TAR) --strip-components=1 --directory=$@/drivers/net/wireless/realtek/rtl8188eu 71 | patch -d tmp -p 0 < patches/linux-$(LINUX_TAG).patch 72 | cp patches/cma.c $@/drivers/char 73 | cp patches/xilinx_devcfg.c $@/drivers/char 74 | cp patches/xilinx_zynq_defconfig $@/arch/arm/configs 75 | 76 | $(DTREE_DIR): $(DTREE_TAR) 77 | mkdir -p $@ 78 | tar -zxf $< --strip-components=1 --directory=$@ 79 | 80 | tmp/ssbl.elf: 81 | mkdir -p $(@D) 82 | curl -L $(SSBL_URL) -o $@ 83 | 84 | zImage.bin: $(LINUX_DIR) 85 | make -C $< mrproper 86 | make -C $< ARCH=arm -j $(shell nproc 2> /dev/null || echo 1) \ 87 | CROSS_COMPILE=arm-linux-gnueabihf- LOADADDR=0x8000 \ 88 | xilinx_zynq_defconfig zImage modules 89 | cp $ ../../$@ 93 | truncate -s 4M $@ 94 | 95 | boot.bin: tmp/$(NAME).fsbl/executable.elf tmp/ssbl.elf initrd.dtb zImage.bin initrd.bin 96 | echo "img:{[bootloader] tmp/$(NAME).fsbl/executable.elf tmp/ssbl.elf [load=0x2000000] initrd.dtb [load=0x2008000] zImage.bin [load=0x3000000] initrd.bin}" > tmp/boot.bif 97 | bootgen -image tmp/boot.bif -w -o $@ 98 | 99 | initrd.dtb: tmp/$(NAME).tree/system-top.dts 100 | dtc -I dts -O dtb -o $@ -i tmp/$(NAME).tree -i dts dts/initrd.dts 101 | 102 | tmp/cores/%: cores/%.v 103 | mkdir -p $(@D) 104 | $(VIVADO) -source scripts/core.tcl -tclargs $* $(PART) 105 | 106 | tmp/%.xpr: projects/% $(addprefix tmp/, $(CORES)) 107 | mkdir -p $(@D) 108 | $(VIVADO) -source scripts/project.tcl -tclargs $* $(PART) 109 | 110 | tmp/%.xsa: tmp/%.xpr 111 | mkdir -p $(@D) 112 | $(VIVADO) -source scripts/hwdef.tcl -tclargs $* 113 | 114 | tmp/%.bit: tmp/%.xpr 115 | mkdir -p $(@D) 116 | $(VIVADO) -source scripts/bitstream.tcl -tclargs $* 117 | 118 | tmp/%.fsbl/executable.elf: tmp/%.xsa 119 | mkdir -p $(@D) 120 | $(XSCT) scripts/fsbl.tcl $* $(PROC) 121 | cp patches/qmtech_xc7z020_fsbl_hooks.c $(@D) 122 | patch $(@D)/fsbl_hooks.c patches/fsbl.patch 123 | make -C $(@D) 124 | 125 | tmp/%.tree/system-top.dts: tmp/%.xsa $(DTREE_DIR) 126 | mkdir -p $(@D) 127 | $(XSCT) scripts/devicetree.tcl $* $(PROC) $(DTREE_DIR) 128 | sed -i 's|#include|/include/|' $@ 129 | 130 | clean: 131 | $(RM) zImage.bin initrd.bin boot.bin initrd.dtb tmp 132 | $(RM) .Xil usage_statistics_webtalk.html usage_statistics_webtalk.xml 133 | $(RM) vivado*.jou vivado*.log 134 | $(RM) webtalk*.jou webtalk*.log 135 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Notes on the QMTECH ZYNQ XC7Z020 starter kit 2 | 3 | https://pavel-demin.github.io/qmtech-xc7z020-notes/ 4 | -------------------------------------------------------------------------------- /alpine/apps/css/main.css: -------------------------------------------------------------------------------- 1 | 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; } 2 | h1, h2, h3, h4 { font-weight: normal; } 3 | a { color: #bf2334; text-decoration: none; } 4 | a:hover { text-decoration: underline; } 5 | pre, code { font-family: Consolas, Menlo, Liberation Mono, DejaVu Sans Mono, monospace; background: #f5f5f5; border-radius: 0.3em } 6 | code { padding: 0 0.3em; white-space: nowrap; } 7 | pre { padding: 0.1em 0.3em; overflow-x: auto; } 8 | pre > code { padding: 0; background: 0; white-space: pre } 9 | td, th { border: 1px solid #d3d3d3; padding: 0.1em 0.3em; } 10 | th { text-align: left; background-color: #f5f5f5; } 11 | tr.even td { background-color: #f5f5f5; } 12 | img { max-width: 100%; } 13 | 14 | #header { color: #bf2334; padding: 0 1em; } 15 | #header a { color: #bf2334; text-decoration: none; } 16 | #logo { margin-bottom: -1.4em; } 17 | #menu { padding-bottom: 0.3em; text-align: right; } 18 | #menu a { padding-left: 1em; } 19 | #content { background-color: #fff; padding: 1em 1em; border-radius: 0.6em; } 20 | 21 | @media print { #header { display: none; } } 22 | -------------------------------------------------------------------------------- /alpine/apps/css/pygments.css: -------------------------------------------------------------------------------- 1 | .highlight .c { color: #008800; font-style: italic } 2 | .highlight .err { color: #a61717; background-color: #e3d2d2 } 3 | .highlight .k { color: #000080; font-weight: bold } 4 | .highlight .cm { color: #008800; font-style: italic } 5 | .highlight .cp { color: #008080 } 6 | .highlight .c1 { color: #008800; font-style: italic } 7 | .highlight .cs { color: #008800; font-weight: bold } 8 | .highlight .gd { color: #000000; background-color: #ffdddd } 9 | .highlight .ge { font-style: italic } 10 | .highlight .gr { color: #aa0000 } 11 | .highlight .gh { color: #999999 } 12 | .highlight .gi { color: #000000; background-color: #ddffdd } 13 | .highlight .go { color: #888888 } 14 | .highlight .gp { color: #555555 } 15 | .highlight .gs { font-weight: bold } 16 | .highlight .gu { color: #aaaaaa } 17 | .highlight .gt { color: #aa0000 } 18 | .highlight .kc { color: #000080; font-weight: bold } 19 | .highlight .kd { color: #000080; font-weight: bold } 20 | .highlight .kn { color: #000080; font-weight: bold } 21 | .highlight .kp { color: #000080; font-weight: bold } 22 | .highlight .kr { color: #000080; font-weight: bold } 23 | .highlight .kt { color: #000080; font-weight: bold } 24 | .highlight .m { color: #0000ff } 25 | .highlight .s { color: #0000ff } 26 | .highlight .na { color: #ff0000 } 27 | .highlight .nt { color: #000080; font-weight: bold } 28 | .highlight .ow { font-weight: bold } 29 | .highlight .w { color: #bbbbbb } 30 | .highlight .mf { color: #0000ff } 31 | .highlight .mh { color: #0000ff } 32 | .highlight .mi { color: #0000ff } 33 | .highlight .mo { color: #0000ff } 34 | .highlight .sb { color: #0000ff } 35 | .highlight .sc { color: #800080 } 36 | .highlight .sd { color: #0000ff } 37 | .highlight .s2 { color: #0000ff } 38 | .highlight .se { color: #0000ff } 39 | .highlight .sh { color: #0000ff } 40 | .highlight .si { color: #0000ff } 41 | .highlight .sx { color: #0000ff } 42 | .highlight .sr { color: #0000ff } 43 | .highlight .s1 { color: #0000ff } 44 | .highlight .ss { color: #0000ff } 45 | .highlight .il { color: #0000ff } 46 | -------------------------------------------------------------------------------- /alpine/apps/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QMTECH XC7Z020 Apps 6 | 7 | 8 | 9 | 18 |
19 |
    20 |
  1. LED blinker
  2. 21 |
  3. SDR receiver
  4. 22 |
  5. SDR receiver compatible with HPSDR
  6. 23 |
  7. Multiband FT8 receiver
  8. 24 |
  9. Multiband WSPR receiver
  10. 25 |
26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /alpine/apps/server/Makefile: -------------------------------------------------------------------------------- 1 | all: server 2 | 3 | server: server.c 4 | gcc -o $@ $^ 5 | 6 | clean: 7 | rm -f server 8 | -------------------------------------------------------------------------------- /alpine/apps/server/server.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define DIR "/sys/bus/iio/devices/iio:device0/" 8 | 9 | const char *directory = "/media/mmcblk0p1/apps"; 10 | const char *forbidden = "HTTP/1.0 403 Forbidden\n\n"; 11 | const char *redirect = "HTTP/1.0 302 Found\nLocation: /\n\n"; 12 | const char *okheader = "HTTP/1.0 200 OK\n\n"; 13 | 14 | void detach(char *path) 15 | { 16 | int pid = fork(); 17 | if(pid != 0) return; 18 | close(STDIN_FILENO); 19 | close(STDOUT_FILENO); 20 | close(STDERR_FILENO); 21 | execlp(path, path, NULL); 22 | exit(0); 23 | } 24 | 25 | float read_value(char *name) 26 | { 27 | FILE *fp; 28 | char buffer[64]; 29 | 30 | if((fp = fopen(name, "r")) == NULL) 31 | { 32 | printf("Cannot open %s.\n", name); 33 | exit(1); 34 | } 35 | 36 | fgets(buffer, sizeof(buffer), fp); 37 | fclose(fp); 38 | 39 | return atof(buffer); 40 | } 41 | 42 | int main() 43 | { 44 | FILE *fp; 45 | int i, j; 46 | float off, raw, scl; 47 | struct stat sb; 48 | size_t size; 49 | char buffer[256]; 50 | char path[284]; 51 | 52 | if(fgets(buffer, 256, stdin) == NULL) 53 | { 54 | fwrite(forbidden, 24, 1, stdout); 55 | return 1; 56 | } 57 | 58 | if(buffer[4] != '/') 59 | { 60 | fwrite(forbidden, 24, 1, stdout); 61 | return 1; 62 | } 63 | 64 | if(strncmp(buffer, "GET ", 4) && strncmp(buffer, "get ", 4)) 65 | { 66 | fwrite(forbidden, 24, 1, stdout); 67 | return 1; 68 | } 69 | 70 | for(i = 5; i < 255; ++i) 71 | { 72 | if(buffer[i] == ' ') 73 | { 74 | buffer[i] = 0; 75 | break; 76 | } 77 | } 78 | 79 | for(j = 5; j < i - 1; ++j) 80 | { 81 | if(buffer[j] == '.' && buffer[j + 1] == '.') 82 | { 83 | fwrite(forbidden, 24, 1, stdout); 84 | return 1; 85 | } 86 | } 87 | 88 | if(i == 10 && strncmp(buffer + 5, "temp0", 5) == 0) 89 | { 90 | fwrite(okheader, 17, 1, stdout); 91 | off = read_value(DIR "in_temp0_offset"); 92 | raw = read_value(DIR "in_temp0_raw"); 93 | scl = read_value(DIR "in_temp0_scale"); 94 | printf("%.1f\n", (off + raw) * scl / 1000); 95 | return 0; 96 | } 97 | 98 | memcpy(path, directory, 21); 99 | memcpy(path + 21, buffer + 4, i - 3); 100 | 101 | if(stat(path, &sb) < 0) 102 | { 103 | fwrite(redirect, 32, 1, stdout); 104 | return 1; 105 | } 106 | 107 | if(S_ISDIR(sb.st_mode)) 108 | { 109 | memcpy(path + 21 + i - 4, "/start.sh", 10); 110 | detach(path); 111 | memcpy(path + 21 + i - 4, "/index.html", 12); 112 | } 113 | 114 | fp = fopen(path, "r"); 115 | 116 | if(fp == NULL) 117 | { 118 | fwrite(redirect, 32, 1, stdout); 119 | return 1; 120 | } 121 | 122 | fwrite(okheader, 17, 1, stdout); 123 | 124 | while((size = fread(buffer, 1, 256, fp)) > 0) 125 | { 126 | if(!fwrite(buffer, size, 1, stdout)) break; 127 | } 128 | 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /alpine/apps/stop.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | for script in /media/mmcblk0p1/apps/*/stop.sh 4 | do 5 | $script & 6 | done 7 | 8 | wait 9 | -------------------------------------------------------------------------------- /alpine/etc/avahi/services/http.service: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %h HTTP 7 | 8 | 9 | _http._tcp 10 | 80 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /alpine/etc/avahi/services/sftp-ssh.service: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %h SFTP-SSH 7 | 8 | 9 | _sftp-ssh._tcp 10 | 22 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /alpine/etc/avahi/services/ssh.service: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %h SSH 7 | 8 | 9 | _ssh._tcp 10 | 22 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /alpine/etc/chrony/chrony.conf: -------------------------------------------------------------------------------- 1 | refclock SHM 2 refid PPS precision 1e-9 2 | pool pool.ntp.org iburst offline 3 | makestep 1 -1 4 | driftfile /var/lib/chrony/chrony.drift 5 | -------------------------------------------------------------------------------- /alpine/etc/conf.d/gpsd: -------------------------------------------------------------------------------- 1 | GPSD_OPTIONS="-n" 2 | DEVICES="/dev/ttyPS1 /dev/pps0" 3 | GPSD_SOCKET="/var/run/gpsd.sock" 4 | -------------------------------------------------------------------------------- /alpine/etc/conf.d/hostname: -------------------------------------------------------------------------------- 1 | awk -F : '{print "sdr-"$4$5$6}' /sys/class/net/eth0/address > /etc/hostname 2 | -------------------------------------------------------------------------------- /alpine/etc/conf.d/modloop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pavel-demin/qmtech-xc7z020-notes/1b255b7624033c0004926dea01875e07adcc5587/alpine/etc/conf.d/modloop -------------------------------------------------------------------------------- /alpine/etc/conf.d/syslog: -------------------------------------------------------------------------------- 1 | SYSLOGD_OPTS="" 2 | -------------------------------------------------------------------------------- /alpine/etc/dhcpcd.conf: -------------------------------------------------------------------------------- 1 | # Inform the DHCP server of our hostname for DDNS. 2 | hostname 3 | 4 | # Use the hardware address of the interface for the Client ID. 5 | clientid 6 | 7 | # Rapid commit support. 8 | # Safe to enable by default because it requires the equivalent option set 9 | # on the server to actually work. 10 | option rapid_commit 11 | 12 | # A list of options to request from the DHCP server. 13 | option domain_name_servers, domain_name, domain_search, host_name 14 | option classless_static_routes 15 | # Most distributions have NTP support. 16 | option ntp_servers 17 | # Respect the network MTU. This is applied to DHCP routes. 18 | option interface_mtu 19 | 20 | # A ServerID is required by RFC2131. 21 | require dhcp_server_identifier 22 | 23 | # Generate Stable Private IPv6 Addresses instead of hardware based ones. 24 | slaac private 25 | 26 | # Don't send any ARP requests. 27 | noarp 28 | 29 | # Only configure IPv4. 30 | ipv4only 31 | 32 | # Wait 20 seconds before falling back to static profile. 33 | reboot 20 34 | 35 | # Configure loopback interface. 36 | interface lo 37 | static ip_address=127.0.0.1/8 38 | 39 | # Define static profile for eth0. 40 | profile static_eth0 41 | static ip_address=192.168.1.100/24 42 | static routers=192.168.1.1 43 | static domain_name_servers=192.168.1.1 44 | 45 | # Fallback to static profile on eth0. 46 | interface eth0 47 | fallback static_eth0 48 | 49 | # Define static profile for mvl0. 50 | profile static_mvl0 51 | static ip_address=192.168.1.101/24 52 | static routers=192.168.1.1 53 | static domain_name_servers=192.168.1.1 54 | 55 | # Fallback to static profile on mvl0. 56 | interface mvl0 57 | fallback static_mvl0 58 | 59 | # Static IP address for Wi-Fi access point. 60 | interface wlan0 61 | static ip_address=192.168.42.1/24 62 | -------------------------------------------------------------------------------- /alpine/etc/dhcpcd.exit-hook: -------------------------------------------------------------------------------- 1 | if [ "$interface" = wlan0 ]; then 2 | case "$reason" in 3 | PREINIT) (sleep 3; openrc wifi > /dev/null 2>&1) & ;; 4 | DEPARTED) (sleep 3; openrc default > /dev/null 2>&1) & ;; 5 | esac 6 | fi 7 | 8 | if [ "$interface" = eth0 ] && [ "$reason" = PREINIT ]; then 9 | addr=`cat /media/mmcblk0p1/mac.txt` 10 | name=`echo $addr | awk -F : '{print "sdr-" tolower($4$5$6)}'` 11 | ip link set dev eth0 down 12 | ip link set dev eth0 address $addr 13 | ip link set dev eth0 up 14 | hostname $name 15 | fi 16 | 17 | if $if_up; then 18 | (sleep 3; chronyc online > /dev/null 2>&1) & 19 | fi 20 | -------------------------------------------------------------------------------- /alpine/etc/dnsmasq.d/ap.conf: -------------------------------------------------------------------------------- 1 | interface=wlan0 2 | dhcp-range=192.168.42.20,192.168.42.254,12h 3 | -------------------------------------------------------------------------------- /alpine/etc/hostapd/hostapd.conf: -------------------------------------------------------------------------------- 1 | interface=wlan0 2 | ssid=QMTECH XC7Z020 3 | driver=nl80211 4 | hw_mode=g 5 | channel=6 6 | auth_algs=1 7 | wpa=2 8 | wpa_passphrase=QMTECH XC7Z020 9 | wpa_key_mgmt=WPA-PSK 10 | wpa_pairwise=CCMP 11 | rsn_pairwise=CCMP 12 | -------------------------------------------------------------------------------- /alpine/etc/iptables/rules-save: -------------------------------------------------------------------------------- 1 | *nat 2 | :PREROUTING ACCEPT [0:0] 3 | :INPUT ACCEPT [0:0] 4 | :OUTPUT ACCEPT [0:0] 5 | :POSTROUTING ACCEPT [0:0] 6 | -A POSTROUTING -o eth0 -j MASQUERADE 7 | COMMIT 8 | *mangle 9 | :PREROUTING ACCEPT [0:0] 10 | :INPUT ACCEPT [0:0] 11 | :FORWARD ACCEPT [0:0] 12 | :OUTPUT ACCEPT [0:0] 13 | :POSTROUTING ACCEPT [0:0] 14 | COMMIT 15 | *filter 16 | :INPUT ACCEPT [0:0] 17 | :FORWARD ACCEPT [0:0] 18 | :OUTPUT ACCEPT [0:0] 19 | -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT 20 | -A FORWARD -i wlan0 -o eth0 -j ACCEPT 21 | COMMIT 22 | -------------------------------------------------------------------------------- /alpine/etc/local.d/apps.start: -------------------------------------------------------------------------------- 1 | tcpserver -H -l 0 0 80 /media/mmcblk0p1/apps/server/server & 2 | /media/mmcblk0p1/start.sh & 3 | -------------------------------------------------------------------------------- /alpine/etc/wpa_supplicant/wpa_supplicant.conf: -------------------------------------------------------------------------------- 1 | network={ 2 | ssid="QMTECH XC7Z020" 3 | #psk="QMTECH XC7Z020" 4 | psk=965fa13b638ffb1f275132c897b923339b4aaa9b913afa5670c15e1173eaf9d1 5 | } 6 | -------------------------------------------------------------------------------- /alpine/wifi/client.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | openrc default 4 | 5 | rc-update del iptables wifi 6 | rc-update del dnsmasq wifi 7 | rc-update del hostapd wifi 8 | 9 | rc-update add wpa_supplicant wifi 10 | 11 | sed -i '/^interface wlan0/{s/^interface/#interface/;n;s/^static/#static/}' /etc/dhcpcd.conf 12 | 13 | service dhcpcd restart 14 | -------------------------------------------------------------------------------- /alpine/wifi/hotspot.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | openrc default 4 | 5 | rc-update del wpa_supplicant wifi 6 | 7 | rc-update add iptables wifi 8 | rc-update add dnsmasq wifi 9 | rc-update add hostapd wifi 10 | 11 | sed -i '/^#interface wlan0/{s/^#interface/interface/;n;s/^#static/static/}' /etc/dhcpcd.conf 12 | 13 | service dhcpcd restart 14 | -------------------------------------------------------------------------------- /cfg/clocks.xdc: -------------------------------------------------------------------------------- 1 | create_clock -period 20 -waveform {0 10} [get_ports clk_i] 2 | -------------------------------------------------------------------------------- /cfg/ports.tcl: -------------------------------------------------------------------------------- 1 | ### clock input 2 | 3 | create_bd_port -dir I clk_i 4 | 5 | ### LED 6 | 7 | create_bd_port -dir O led_o 8 | 9 | ### PPS 10 | 11 | create_bd_port -dir I pps_i 12 | -------------------------------------------------------------------------------- /cfg/ports.xdc: -------------------------------------------------------------------------------- 1 | ### clock input 2 | 3 | set_property IOSTANDARD LVCMOS33 [get_ports clk_i] 4 | set_property PACKAGE_PIN M19 [get_ports clk_i] 5 | 6 | ### LED 7 | 8 | set_property IOSTANDARD LVCMOS33 [get_ports led_o] 9 | set_property SLEW SLOW [get_ports led_o] 10 | set_property DRIVE 4 [get_ports led_o] 11 | 12 | set_property PACKAGE_PIN P22 [get_ports led_o] 13 | 14 | ### PPS 15 | 16 | set_property IOSTANDARD LVCMOS33 [get_ports pps_i] 17 | set_property PACKAGE_PIN L22 [get_ports pps_i] 18 | -------------------------------------------------------------------------------- /cfg/qmtech_xc7z020.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /cores/axi_hub.py: -------------------------------------------------------------------------------- 1 | hub_size = 6 2 | source = """ 3 | `timescale 1 ns / 1 ps 4 | 5 | module axi_hub # 6 | ( 7 | parameter integer CFG_DATA_WIDTH = 1024, 8 | parameter integer STS_DATA_WIDTH = 1024 9 | ) 10 | ( 11 | input wire aclk, 12 | input wire aresetn, 13 | 14 | input wire [11:0] s_axi_awid, 15 | input wire [31:0] s_axi_awaddr, 16 | input wire s_axi_awvalid, 17 | output wire s_axi_awready, 18 | 19 | input wire [3:0] s_axi_wstrb, 20 | input wire s_axi_wlast, 21 | input wire [31:0] s_axi_wdata, 22 | input wire s_axi_wvalid, 23 | output wire s_axi_wready, 24 | 25 | output wire [11:0] s_axi_bid, 26 | output wire s_axi_bvalid, 27 | input wire s_axi_bready, 28 | 29 | input wire [11:0] s_axi_arid, 30 | input wire [3:0] s_axi_arlen, 31 | input wire [31:0] s_axi_araddr, 32 | input wire s_axi_arvalid, 33 | output wire s_axi_arready, 34 | 35 | output wire [11:0] s_axi_rid, 36 | output wire s_axi_rlast, 37 | output wire [31:0] s_axi_rdata, 38 | output wire s_axi_rvalid, 39 | input wire s_axi_rready, 40 | 41 | output wire [CFG_DATA_WIDTH-1:0] cfg_data, 42 | 43 | input wire [STS_DATA_WIDTH-1:0] sts_data, 44 | {% for i in range(hub_size) -%} 45 | {% set index = "%02d" % i %} 46 | (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram CLK" *) 47 | output wire b{{index}}_bram_clk, 48 | (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram RST" *) 49 | output wire b{{index}}_bram_rst, 50 | (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram EN" *) 51 | output wire b{{index}}_bram_en, 52 | (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram WE" *) 53 | output wire [3:0] b{{index}}_bram_we, 54 | (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram ADDR" *) 55 | output wire [21:0] b{{index}}_bram_addr, 56 | (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram DIN" *) 57 | output wire [31:0] b{{index}}_bram_wdata, 58 | (* X_INTERFACE_INFO = "xilinx.com:interface:bram:1.0 b{{index}}_bram DOUT" *) 59 | input wire [31:0] b{{index}}_bram_rdata, 60 | 61 | input wire [31:0] s{{index}}_axis_tdata, 62 | input wire s{{index}}_axis_tvalid, 63 | output wire s{{index}}_axis_tready, 64 | 65 | output wire [31:0] m{{index}}_axis_tdata, 66 | output wire m{{index}}_axis_tvalid, 67 | input wire m{{index}}_axis_tready{% if not loop.last %},{% endif %} 68 | {% endfor -%} 69 | ); 70 | 71 | localparam integer HUB_SIZE = {{hub_size}}; 72 | localparam integer MUX_SIZE = HUB_SIZE + 2; 73 | localparam integer CFG_SIZE = CFG_DATA_WIDTH / 32; 74 | localparam integer CFG_WIDTH = CFG_SIZE > 1 ? $clog2(CFG_SIZE) : 1; 75 | localparam integer STS_SIZE = STS_DATA_WIDTH / 32; 76 | localparam integer STS_WIDTH = STS_SIZE > 1 ? $clog2(STS_SIZE) : 1; 77 | 78 | reg [3:0] int_awcntr_reg, int_awcntr_next; 79 | reg [3:0] int_arcntr_reg, int_arcntr_next; 80 | 81 | wire int_awvalid_wire, int_awready_wire; 82 | wire int_wvalid_wire, int_wready_wire; 83 | wire int_bvalid_wire, int_bready_wire; 84 | wire int_arvalid_wire, int_arready_wire; 85 | wire int_rvalid_wire, int_rready_wire; 86 | 87 | wire [11:0] int_awid_wire; 88 | wire [31:0] int_awaddr_wire; 89 | 90 | wire [3:0] int_wstrb_wire; 91 | wire int_wlast_wire; 92 | wire [31:0] int_wdata_wire; 93 | 94 | wire [11:0] int_arid_wire; 95 | wire [3:0] int_arlen_wire; 96 | wire [31:0] int_araddr_wire; 97 | 98 | wire [11:0] int_rid_wire; 99 | wire int_rlast_wire; 100 | wire [31:0] int_rdata_wire [MUX_SIZE-1:0]; 101 | 102 | wire [31:0] int_sdata_wire [HUB_SIZE-1:0]; 103 | wire [31:0] int_mdata_wire [HUB_SIZE-1:0]; 104 | wire [HUB_SIZE-1:0] int_svalid_wire, int_sready_wire; 105 | wire [HUB_SIZE-1:0] int_mvalid_wire, int_mready_wire; 106 | 107 | wire [31:0] int_bdata_wire [HUB_SIZE-1:0]; 108 | 109 | wire [21:0] int_waddr_wire; 110 | wire [21:0] int_raddr_wire; 111 | 112 | wire [31:0] int_cfg_mux [CFG_SIZE-1:0]; 113 | wire [31:0] int_sts_mux [STS_SIZE-1:0]; 114 | 115 | wire [31:0] int_rdata_mux [MUX_SIZE-1:0]; 116 | wire [MUX_SIZE-1:0] int_wsel_wire, int_rsel_wire; 117 | 118 | wire [HUB_SIZE-1:0] int_bsel_wire; 119 | 120 | wire [CFG_SIZE-1:0] int_ce_wire; 121 | wire int_we_wire, int_re_wire; 122 | 123 | genvar j, k; 124 | 125 | assign int_awready_wire = int_bready_wire & int_wvalid_wire & int_wlast_wire; 126 | assign int_wready_wire = int_bready_wire & int_awvalid_wire; 127 | assign int_bvalid_wire = int_awvalid_wire & int_wvalid_wire & int_wlast_wire; 128 | 129 | assign int_arready_wire = int_rready_wire & int_rlast_wire; 130 | assign int_rvalid_wire = int_arvalid_wire; 131 | assign int_rlast_wire = int_arcntr_reg == int_arlen_wire; 132 | 133 | assign int_we_wire = int_bready_wire & int_awvalid_wire & int_wvalid_wire; 134 | assign int_re_wire = int_rready_wire & int_arvalid_wire; 135 | 136 | assign int_waddr_wire = int_awaddr_wire[23:2] + int_awcntr_reg; 137 | assign int_raddr_wire = int_araddr_wire[23:2] + int_arcntr_reg; 138 | 139 | assign int_rdata_wire[0] = int_rdata_mux[int_araddr_wire[27:24]]; 140 | 141 | assign int_rdata_mux[0] = int_cfg_mux[int_raddr_wire[CFG_WIDTH-1:0]]; 142 | assign int_rdata_mux[1] = int_sts_mux[int_raddr_wire[STS_WIDTH-1:0]]; 143 | 144 | generate 145 | for(j = 0; j < HUB_SIZE; j = j + 1) 146 | begin : MUXES 147 | assign int_rdata_mux[j+2] = int_svalid_wire[j] ? int_sdata_wire[j] : 32'd0; 148 | assign int_rdata_wire[j+2] = int_bsel_wire[j] ? int_bdata_wire[j] : 32'd0; 149 | assign int_mdata_wire[j] = int_wdata_wire; 150 | assign int_mvalid_wire[j] = int_wsel_wire[j+2]; 151 | assign int_sready_wire[j] = int_rsel_wire[j+2]; 152 | end 153 | endgenerate 154 | 155 | generate 156 | for(j = 0; j < MUX_SIZE; j = j + 1) 157 | begin : SELECTS 158 | assign int_wsel_wire[j] = int_we_wire & (int_awaddr_wire[27:24] == j); 159 | assign int_rsel_wire[j] = int_re_wire & (int_araddr_wire[27:24] == j); 160 | end 161 | endgenerate 162 | 163 | generate 164 | for(j = 0; j < CFG_SIZE; j = j + 1) 165 | begin : CFG_WORDS 166 | assign int_cfg_mux[j] = cfg_data[j*32+31:j*32]; 167 | assign int_ce_wire[j] = int_wsel_wire[0] & (int_waddr_wire[CFG_WIDTH-1:0] == j); 168 | for(k = 0; k < 32; k = k + 1) 169 | begin : CFG_BITS 170 | FDRE #( 171 | .INIT(1'b0) 172 | ) FDRE_inst ( 173 | .CE(int_ce_wire[j] & int_wstrb_wire[k/8]), 174 | .C(aclk), 175 | .R(~aresetn), 176 | .D(int_wdata_wire[k]), 177 | .Q(cfg_data[j*32 + k]) 178 | ); 179 | end 180 | end 181 | endgenerate 182 | 183 | generate 184 | for(j = 0; j < STS_SIZE; j = j + 1) 185 | begin : STS_WORDS 186 | assign int_sts_mux[j] = sts_data[j*32+31:j*32]; 187 | end 188 | endgenerate 189 | 190 | always @(posedge aclk) 191 | begin 192 | if(~aresetn) 193 | begin 194 | int_awcntr_reg <= 4'd0; 195 | int_arcntr_reg <= 4'd0; 196 | end 197 | else 198 | begin 199 | int_awcntr_reg <= int_awcntr_next; 200 | int_arcntr_reg <= int_arcntr_next; 201 | end 202 | end 203 | 204 | always @* 205 | begin 206 | int_awcntr_next = int_awcntr_reg; 207 | int_arcntr_next = int_arcntr_reg; 208 | 209 | if(int_awvalid_wire & int_awready_wire) 210 | begin 211 | int_awcntr_next = 4'd0; 212 | end 213 | 214 | if(int_arvalid_wire & int_arready_wire) 215 | begin 216 | int_arcntr_next = 4'd0; 217 | end 218 | 219 | if(~int_wlast_wire & int_we_wire) 220 | begin 221 | int_awcntr_next = int_awcntr_reg + 1'b1; 222 | end 223 | 224 | if(~int_rlast_wire & int_re_wire) 225 | begin 226 | int_arcntr_next = int_arcntr_reg + 1'b1; 227 | end 228 | end 229 | 230 | inout_buffer #( 231 | .DATA_WIDTH(44) 232 | ) buf_0 ( 233 | .aclk(aclk), .aresetn(aresetn), 234 | .in_data({s_axi_awid, s_axi_awaddr}), 235 | .in_valid(s_axi_awvalid), .in_ready(s_axi_awready), 236 | .out_data({int_awid_wire, int_awaddr_wire}), 237 | .out_valid(int_awvalid_wire), .out_ready(int_awready_wire) 238 | ); 239 | 240 | inout_buffer #( 241 | .DATA_WIDTH(37) 242 | ) buf_1 ( 243 | .aclk(aclk), .aresetn(aresetn), 244 | .in_data({s_axi_wstrb, s_axi_wlast, s_axi_wdata}), 245 | .in_valid(s_axi_wvalid), .in_ready(s_axi_wready), 246 | .out_data({int_wstrb_wire, int_wlast_wire, int_wdata_wire}), 247 | .out_valid(int_wvalid_wire), .out_ready(int_wready_wire) 248 | ); 249 | 250 | output_buffer #( 251 | .DATA_WIDTH(12) 252 | ) buf_2 ( 253 | .aclk(aclk), .aresetn(aresetn), 254 | .in_data(int_awid_wire), .in_valid(int_bvalid_wire), .in_ready(int_bready_wire), 255 | .out_data(s_axi_bid), .out_valid(s_axi_bvalid), .out_ready(s_axi_bready) 256 | ); 257 | 258 | inout_buffer #( 259 | .DATA_WIDTH(48) 260 | ) buf_3 ( 261 | .aclk(aclk), .aresetn(aresetn), 262 | .in_data({s_axi_arid, s_axi_arlen, s_axi_araddr}), 263 | .in_valid(s_axi_arvalid), .in_ready(s_axi_arready), 264 | .out_data({int_arid_wire, int_arlen_wire, int_araddr_wire}), 265 | .out_valid(int_arvalid_wire), .out_ready(int_arready_wire) 266 | ); 267 | 268 | output_buffer #( 269 | .DATA_WIDTH(HUB_SIZE + 45) 270 | ) buf_4 ( 271 | .aclk(aclk), .aresetn(aresetn), 272 | .in_data({int_rsel_wire[MUX_SIZE-1:2] & ~int_svalid_wire, int_arid_wire, int_rlast_wire, int_rdata_wire[0]}), 273 | .in_valid(int_rvalid_wire), .in_ready(int_rready_wire), 274 | .out_data({int_bsel_wire, s_axi_rid, s_axi_rlast, int_rdata_wire[1]}), 275 | .out_valid(s_axi_rvalid), .out_ready(s_axi_rready) 276 | ); 277 | 278 | assign s_axi_rdata = {{s_axi_rdata(hub_size)}}; 279 | {% for i in range(hub_size) -%} 280 | {% set index = "%02d" % i %} 281 | assign int_bdata_wire[{{i}}] = b{{index}}_bram_rdata; 282 | assign b{{index}}_bram_clk = aclk; 283 | assign b{{index}}_bram_rst = ~aresetn; 284 | assign b{{index}}_bram_en = int_rsel_wire[{{i+2}}] | int_wsel_wire[{{i+2}}]; 285 | assign b{{index}}_bram_we = int_wsel_wire[{{i+2}}] ? int_wstrb_wire : 4'd0; 286 | assign b{{index}}_bram_addr = int_we_wire ? int_waddr_wire : int_raddr_wire; 287 | assign b{{index}}_bram_wdata = int_wdata_wire; 288 | 289 | assign int_sdata_wire[{{i}}] = s{{index}}_axis_tdata; 290 | assign int_svalid_wire[{{i}}] = s{{index}}_axis_tvalid; 291 | assign s{{index}}_axis_tready = int_sready_wire[{{i}}]; 292 | 293 | inout_buffer #( 294 | .DATA_WIDTH(32) 295 | ) mbuf_{{i}} ( 296 | .aclk(aclk), .aresetn(aresetn), 297 | .in_data(int_mdata_wire[{{i}}]), .in_valid(int_mvalid_wire[{{i}}]), .in_ready(int_mready_wire[{{i}}]), 298 | .out_data(m{{index}}_axis_tdata), .out_valid(m{{index}}_axis_tvalid), .out_ready(m{{index}}_axis_tready) 299 | ); 300 | {% endfor %} 301 | endmodule 302 | """ 303 | 304 | import jinja2 305 | 306 | 307 | def s_axi_rdata(n): 308 | return " | ".join(map(lambda i: "int_rdata_wire[%d]" % i, range(1, n + 2))) 309 | 310 | 311 | print(jinja2.Template(source).render(hub_size=hub_size, s_axi_rdata=s_axi_rdata)) 312 | -------------------------------------------------------------------------------- /cores/axis_adc_ddr.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1 ns / 1 ps 3 | 4 | module axis_adc_ddr # 5 | ( 6 | parameter integer ADC_DATA_WIDTH = 7, 7 | parameter integer AXIS_TDATA_WIDTH = 16 8 | ) 9 | ( 10 | // System signals 11 | input wire aclk, 12 | 13 | // ADC signals 14 | input wire [ADC_DATA_WIDTH-1:0] adc_data, 15 | 16 | // Master side 17 | output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata, 18 | output wire m_axis_tvalid 19 | ); 20 | localparam PADDING_WIDTH = AXIS_TDATA_WIDTH - ADC_DATA_WIDTH*2; 21 | 22 | wire [ADC_DATA_WIDTH*2-1:0] int_data_wire; 23 | 24 | genvar j; 25 | 26 | generate 27 | for(j = 0; j < ADC_DATA_WIDTH; j = j + 1) 28 | begin : ADC_DATA 29 | IDDR #( 30 | .DDR_CLK_EDGE("SAME_EDGE_PIPELINED") 31 | ) IDDR_inst ( 32 | .Q1(int_data_wire[j*2+0]), 33 | .Q2(int_data_wire[j*2+1]), 34 | .D(adc_data[j]), 35 | .C(aclk), 36 | .CE(1'b1), 37 | .R(1'b0), 38 | .S(1'b0) 39 | ); 40 | end 41 | endgenerate 42 | 43 | assign m_axis_tvalid = 1'b1; 44 | 45 | assign m_axis_tdata = {{(PADDING_WIDTH+1){int_data_wire[ADC_DATA_WIDTH*2-1]}}, int_data_wire[ADC_DATA_WIDTH*2-2:0]}; 46 | 47 | endmodule 48 | -------------------------------------------------------------------------------- /cores/axis_fifo.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1 ns / 1 ps 3 | 4 | module axis_fifo # 5 | ( 6 | parameter integer S_AXIS_TDATA_WIDTH = 32, 7 | parameter integer M_AXIS_TDATA_WIDTH = 32, 8 | parameter integer WRITE_DEPTH = 512, 9 | parameter ALWAYS_READY = "FALSE", 10 | parameter ALWAYS_VALID = "FALSE" 11 | ) 12 | ( 13 | // System signals 14 | input wire aclk, 15 | input wire aresetn, 16 | 17 | // FIFO status 18 | output wire [15:0] write_count, 19 | output wire [15:0] read_count, 20 | 21 | // Slave side 22 | input wire [S_AXIS_TDATA_WIDTH-1:0] s_axis_tdata, 23 | input wire s_axis_tvalid, 24 | output wire s_axis_tready, 25 | 26 | // Master side 27 | output wire [M_AXIS_TDATA_WIDTH-1:0] m_axis_tdata, 28 | output wire m_axis_tvalid, 29 | input wire m_axis_tready 30 | ); 31 | 32 | localparam integer WRITE_COUNT_WIDTH = $clog2(WRITE_DEPTH) + 1; 33 | localparam integer READ_COUNT_WIDTH = $clog2(WRITE_DEPTH * S_AXIS_TDATA_WIDTH / M_AXIS_TDATA_WIDTH) + 1; 34 | 35 | wire [M_AXIS_TDATA_WIDTH-1:0] int_data_wire; 36 | wire int_empty_wire, int_full_wire; 37 | 38 | xpm_fifo_sync #( 39 | .WRITE_DATA_WIDTH(S_AXIS_TDATA_WIDTH), 40 | .FIFO_WRITE_DEPTH(WRITE_DEPTH), 41 | .READ_DATA_WIDTH(M_AXIS_TDATA_WIDTH), 42 | .READ_MODE("fwft"), 43 | .FIFO_READ_LATENCY(0), 44 | .FIFO_MEMORY_TYPE("block"), 45 | .USE_ADV_FEATURES("0404"), 46 | .WR_DATA_COUNT_WIDTH(WRITE_COUNT_WIDTH), 47 | .RD_DATA_COUNT_WIDTH(READ_COUNT_WIDTH) 48 | ) fifo_0 ( 49 | .empty(int_empty_wire), 50 | .full(int_full_wire), 51 | .wr_data_count(write_count), 52 | .rd_data_count(read_count), 53 | .rst(~aresetn), 54 | .wr_clk(aclk), 55 | .wr_en(s_axis_tvalid), 56 | .din(s_axis_tdata), 57 | .rd_en(m_axis_tready), 58 | .dout(int_data_wire) 59 | ); 60 | 61 | generate 62 | if(ALWAYS_READY == "TRUE") 63 | begin : READY_INPUT 64 | assign s_axis_tready = 1'b1; 65 | end 66 | else 67 | begin : BLOCKING_INPUT 68 | assign s_axis_tready = ~int_full_wire; 69 | end 70 | endgenerate 71 | 72 | generate 73 | if(ALWAYS_VALID == "TRUE") 74 | begin : VALID_OUTPUT 75 | assign m_axis_tdata = int_empty_wire ? {(M_AXIS_TDATA_WIDTH){1'b0}} : int_data_wire; 76 | assign m_axis_tvalid = 1'b1; 77 | end 78 | else 79 | begin : BLOCKING_OUTPUT 80 | assign m_axis_tdata = int_data_wire; 81 | assign m_axis_tvalid = ~int_empty_wire; 82 | end 83 | endgenerate 84 | 85 | endmodule 86 | -------------------------------------------------------------------------------- /cores/axis_maxabs_finder.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1 ns / 1 ps 3 | 4 | module axis_maxabs_finder # 5 | ( 6 | parameter integer AXIS_TDATA_WIDTH = 16, 7 | parameter integer CNTR_WIDTH = 32 8 | ) 9 | ( 10 | // System signals 11 | input wire aclk, 12 | input wire aresetn, 13 | 14 | input wire [CNTR_WIDTH-1:0] cfg_data, 15 | 16 | // Slave side 17 | output wire s_axis_tready, 18 | input wire [AXIS_TDATA_WIDTH-1:0] s_axis_tdata, 19 | input wire s_axis_tvalid, 20 | 21 | // Master side 22 | input wire m_axis_tready, 23 | output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata, 24 | output wire m_axis_tvalid 25 | ); 26 | 27 | reg [AXIS_TDATA_WIDTH-1:0] int_max_reg, int_max_next; 28 | reg [AXIS_TDATA_WIDTH-1:0] int_tdata_reg, int_tdata_next; 29 | reg [CNTR_WIDTH-1:0] int_cntr_reg, int_cntr_next; 30 | reg int_tvalid_reg, int_tvalid_next; 31 | 32 | wire [AXIS_TDATA_WIDTH-1:0] int_abs_wire; 33 | wire int_comp_wire; 34 | 35 | always @(posedge aclk) 36 | begin 37 | if(~aresetn) 38 | begin 39 | int_max_reg <= {(AXIS_TDATA_WIDTH){1'b0}}; 40 | int_tdata_reg <= {(AXIS_TDATA_WIDTH){1'b0}}; 41 | int_cntr_reg <= {(CNTR_WIDTH){1'b0}}; 42 | int_tvalid_reg <= 1'b0; 43 | end 44 | else 45 | begin 46 | int_max_reg <= int_max_next; 47 | int_tdata_reg <= int_tdata_next; 48 | int_cntr_reg <= int_cntr_next; 49 | int_tvalid_reg <= int_tvalid_next; 50 | end 51 | end 52 | 53 | assign int_comp_wire = int_cntr_reg < cfg_data; 54 | assign int_abs_wire = s_axis_tdata[AXIS_TDATA_WIDTH-1] ? ~s_axis_tdata : s_axis_tdata; 55 | 56 | always @* 57 | begin 58 | int_max_next = int_max_reg; 59 | int_tdata_next = int_tdata_reg; 60 | int_cntr_next = int_cntr_reg; 61 | int_tvalid_next = int_tvalid_reg; 62 | 63 | if(s_axis_tvalid & int_comp_wire) 64 | begin 65 | int_max_next = int_abs_wire > int_max_reg ? int_abs_wire : int_max_reg; 66 | int_cntr_next = int_cntr_reg + 1'b1; 67 | end 68 | 69 | if(s_axis_tvalid & ~int_comp_wire) 70 | begin 71 | int_max_next = {(AXIS_TDATA_WIDTH){1'b0}}; 72 | int_tdata_next = int_max_reg; 73 | int_cntr_next = {(CNTR_WIDTH){1'b0}}; 74 | int_tvalid_next = 1'b1; 75 | end 76 | 77 | if(m_axis_tready & int_tvalid_reg) 78 | begin 79 | int_tvalid_next = 1'b0; 80 | end 81 | end 82 | 83 | assign s_axis_tready = 1'b1; 84 | assign m_axis_tdata = int_tdata_reg; 85 | assign m_axis_tvalid = int_tvalid_reg; 86 | 87 | endmodule 88 | -------------------------------------------------------------------------------- /cores/axis_pps_counter.v: -------------------------------------------------------------------------------- 1 | `timescale 1 ns / 1 ps 2 | 3 | module axis_pps_counter # 4 | ( 5 | parameter integer AXIS_TDATA_WIDTH = 32, 6 | parameter integer CNTR_WIDTH = 32 7 | ) 8 | ( 9 | // System signals 10 | input wire aclk, 11 | input wire aresetn, 12 | 13 | input wire pps_data, 14 | 15 | // Master side 16 | output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata, 17 | output wire m_axis_tvalid 18 | ); 19 | 20 | reg [CNTR_WIDTH-1:0] int_cntr_reg; 21 | reg int_enbl_reg; 22 | reg [1:0] int_data_reg; 23 | 24 | wire int_edge_wire, int_pps_wire; 25 | 26 | xpm_cdc_single #( 27 | .DEST_SYNC_FF(4), 28 | .INIT_SYNC_FF(0), 29 | .SRC_INPUT_REG(0), 30 | .SIM_ASSERT_CHK(0) 31 | ) cdc_0 ( 32 | .src_in(pps_data), 33 | .src_clk(), 34 | .dest_out(int_pps_wire), 35 | .dest_clk(aclk) 36 | ); 37 | 38 | always @(posedge aclk) 39 | begin 40 | if(~aresetn) 41 | begin 42 | int_cntr_reg <= {(CNTR_WIDTH){1'b0}}; 43 | int_enbl_reg <= 1'b0; 44 | int_data_reg <= 2'd0; 45 | end 46 | else 47 | begin 48 | int_cntr_reg <= int_edge_wire ? {(CNTR_WIDTH){1'b0}} : int_cntr_reg + 1'b1; 49 | int_enbl_reg <= int_edge_wire ? 1'b1 : int_enbl_reg; 50 | int_data_reg <= {int_data_reg[0], ~int_pps_wire}; 51 | end 52 | end 53 | 54 | assign int_edge_wire = int_data_reg[1] & ~int_data_reg[0]; 55 | 56 | assign m_axis_tdata = {{(AXIS_TDATA_WIDTH-CNTR_WIDTH){1'b0}}, int_cntr_reg}; 57 | assign m_axis_tvalid = int_enbl_reg & int_edge_wire; 58 | 59 | endmodule 60 | -------------------------------------------------------------------------------- /cores/axis_variable.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1 ns / 1 ps 3 | 4 | module axis_variable # 5 | ( 6 | parameter integer AXIS_TDATA_WIDTH = 32 7 | ) 8 | ( 9 | // System signals 10 | input wire aclk, 11 | input wire aresetn, 12 | 13 | input wire [AXIS_TDATA_WIDTH-1:0] cfg_data, 14 | 15 | // Master side 16 | input wire m_axis_tready, 17 | output wire [AXIS_TDATA_WIDTH-1:0] m_axis_tdata, 18 | output wire m_axis_tvalid 19 | ); 20 | 21 | reg [AXIS_TDATA_WIDTH-1:0] int_tdata_reg; 22 | reg int_tvalid_reg; 23 | 24 | always @(posedge aclk) 25 | begin 26 | if(~aresetn) 27 | begin 28 | int_tdata_reg <= {(AXIS_TDATA_WIDTH){1'b0}}; 29 | int_tvalid_reg <= 1'b0; 30 | end 31 | else 32 | begin 33 | int_tdata_reg <= cfg_data; 34 | int_tvalid_reg <= (int_tdata_reg != cfg_data) | (int_tvalid_reg & ~m_axis_tready); 35 | end 36 | end 37 | 38 | assign m_axis_tdata = int_tdata_reg; 39 | assign m_axis_tvalid = int_tvalid_reg; 40 | 41 | endmodule 42 | -------------------------------------------------------------------------------- /cores/dds.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1 ns / 1 ps 3 | 4 | module dds # 5 | ( 6 | parameter NEGATIVE_SINE = "FALSE" 7 | ) 8 | ( 9 | input wire aclk, 10 | input wire aresetn, 11 | 12 | input wire [31:0] pinc, 13 | 14 | output wire [47:0] dout 15 | ); 16 | 17 | reg [31:0] int_cntr_reg; 18 | reg [23:0] int_cos_reg, int_sin_reg; 19 | reg [10:0] int_addr_reg; 20 | reg [1:0] int_sign_reg [2:0]; 21 | 22 | wire [47:0] int_p_wire [2:0]; 23 | wire [31:0] int_cntr_wire; 24 | wire [29:0] int_cos_wire, int_sin_wire; 25 | wire [22:0] int_lut_wire [1:0]; 26 | wire [17:0] int_corr_wire; 27 | wire [2:0] int_pbd_wire; 28 | 29 | assign int_cos_wire = int_sign_reg[2][0] ? {7'h7f, -int_lut_wire[0]} : {7'h00, int_lut_wire[0]}; 30 | assign int_sin_wire = int_sign_reg[2][1] ? {7'h7f, -int_lut_wire[1]} : {7'h00, int_lut_wire[1]}; 31 | 32 | assign int_corr_wire = {int_p_wire[0][34:18], int_p_wire[0][17] | int_pbd_wire[0]}; 33 | 34 | generate 35 | if(NEGATIVE_SINE == "TRUE") 36 | begin : NEGATIVE 37 | assign int_cntr_wire = int_cntr_reg - pinc; 38 | end 39 | else 40 | begin : POSITIVE 41 | assign int_cntr_wire = int_cntr_reg + pinc; 42 | end 43 | endgenerate 44 | 45 | always @(posedge aclk) 46 | begin 47 | if(~aresetn) 48 | begin 49 | int_cntr_reg <= 32'd0; 50 | int_cos_reg <= 24'd0; 51 | int_sin_reg <= 24'd0; 52 | int_addr_reg <= 11'd0; 53 | int_sign_reg[0] <= 2'd0; 54 | int_sign_reg[1] <= 2'd0; 55 | int_sign_reg[2] <= 2'd0; 56 | end 57 | else 58 | begin 59 | int_cntr_reg <= int_cntr_wire; 60 | int_cos_reg <= int_cos_wire[23:0]; 61 | int_sin_reg <= int_sin_wire[23:0]; 62 | int_addr_reg <= int_cntr_reg[29:19]; 63 | int_sign_reg[0] <= {int_cntr_reg[31], int_cntr_reg[30]}; 64 | int_sign_reg[1] <= {int_sign_reg[0][1], int_sign_reg[0][1] ^ int_sign_reg[0][0]}; 65 | int_sign_reg[2] <= int_sign_reg[1]; 66 | end 67 | end 68 | 69 | xpm_memory_dprom #( 70 | .MEMORY_PRIMITIVE("block"), 71 | .MEMORY_SIZE(47104), 72 | .ADDR_WIDTH_A(11), 73 | .ADDR_WIDTH_B(11), 74 | .READ_DATA_WIDTH_A(23), 75 | .READ_DATA_WIDTH_B(23), 76 | .READ_LATENCY_A(2), 77 | .READ_LATENCY_B(2), 78 | .MEMORY_INIT_PARAM(""), 79 | .MEMORY_INIT_FILE("dds.mem") 80 | ) rom_0 ( 81 | .clka(aclk), 82 | .clkb(aclk), 83 | .rsta(1'b0), 84 | .rstb(1'b0), 85 | .ena(1'b1), 86 | .enb(1'b1), 87 | .regcea(1'b1), 88 | .regceb(1'b1), 89 | .addra(int_sign_reg[0][0] ? ~int_addr_reg : int_addr_reg), 90 | .addrb(int_sign_reg[0][0] ? int_addr_reg : ~int_addr_reg), 91 | .douta(int_lut_wire[0]), 92 | .doutb(int_lut_wire[1]) 93 | ); 94 | 95 | DSP48E1 #( 96 | .ALUMODEREG(0), .CARRYINSELREG(0), .INMODEREG(0), .OPMODEREG(0), 97 | .BREG(0), .BCASCREG(0), .CREG(0), .CARRYINREG(0), 98 | .USE_PATTERN_DETECT("PATDET"), .MASK(48'hfffffffe0000) 99 | ) dsp_0 ( 100 | .CLK(aclk), 101 | .RSTA(1'b0), .RSTM(1'b0), .RSTP(1'b0), 102 | .CEA2(1'b1), .CED(1'b0), .CEAD(1'b0), .CEM(1'b1), .CEP(1'b1), 103 | .ALUMODE(4'b0000), .CARRYINSEL(3'b000), .INMODE(5'b00000), .OPMODE(7'b0110101), 104 | .A({{(12){~int_cntr_reg[18]}}, int_cntr_reg[17:0]}), 105 | .B(18'd3217), 106 | .C(48'hffff), 107 | .CARRYIN(1'b0), 108 | .PATTERNBDETECT(int_pbd_wire[0]), 109 | .P(int_p_wire[0]) 110 | ); 111 | 112 | DSP48E1 #( 113 | .ALUMODEREG(0), .CARRYINSELREG(0), .INMODEREG(0), .OPMODEREG(0), 114 | .CARRYINREG(0), 115 | .USE_PATTERN_DETECT("PATDET"), .MASK(48'hffffff000000) 116 | ) dsp_1 ( 117 | .CLK(aclk), 118 | .RSTA(1'b0), .RSTB(1'b0), .RSTC(1'b0), .RSTM(1'b0), .RSTP(1'b0), 119 | .CEA2(1'b1), .CEB2(1'b1), .CEC(1'b1), .CED(1'b0), .CEAD(1'b0), .CEM(1'b1), .CEP(1'b1), 120 | .ALUMODE(4'b0011), .CARRYINSEL(3'b000), .INMODE(5'b00000), .OPMODE(7'b0110101), 121 | .A(int_sin_wire), 122 | .B(int_corr_wire), 123 | .C({int_cos_reg, 24'h7fffff}), 124 | .CARRYIN(1'b0), 125 | .PATTERNBDETECT(int_pbd_wire[1]), 126 | .P(int_p_wire[1]) 127 | ); 128 | 129 | DSP48E1 #( 130 | .ALUMODEREG(0), .CARRYINSELREG(0), .INMODEREG(0), .OPMODEREG(0), 131 | .CARRYINREG(0), 132 | .USE_PATTERN_DETECT("PATDET"), .MASK(48'hffffff000000) 133 | ) dsp_2 ( 134 | .CLK(aclk), 135 | .RSTA(1'b0), .RSTB(1'b0), .RSTC(1'b0), .RSTM(1'b0), .RSTP(1'b0), 136 | .CEA2(1'b1), .CEB2(1'b1), .CEC(1'b1), .CED(1'b0), .CEAD(1'b0), .CEM(1'b1), .CEP(1'b1), 137 | .ALUMODE(4'b0000), .CARRYINSEL(3'b000), .INMODE(5'b00000), .OPMODE(7'b0110101), 138 | .A(int_cos_wire), 139 | .B(int_corr_wire), 140 | .C({int_sin_reg, 24'h7fffff}), 141 | .CARRYIN(1'b0), 142 | .PATTERNBDETECT(int_pbd_wire[2]), 143 | .P(int_p_wire[2]) 144 | ); 145 | 146 | 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]}; 147 | 148 | endmodule 149 | -------------------------------------------------------------------------------- /cores/dsp48.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1 ns / 1 ps 3 | 4 | module dsp48 # 5 | ( 6 | parameter integer A_WIDTH = 24, 7 | parameter integer B_WIDTH = 16, 8 | parameter integer P_WIDTH = 24 9 | ) 10 | ( 11 | input wire CLK, 12 | 13 | input wire [A_WIDTH-1:0] A, 14 | input wire [B_WIDTH-1:0] B, 15 | 16 | output wire [P_WIDTH-1:0] P 17 | ); 18 | 19 | localparam integer SHIFT = A_WIDTH + B_WIDTH - P_WIDTH - 1; 20 | localparam integer ONES = SHIFT - 1; 21 | 22 | wire [47:0] int_p_wire; 23 | wire int_pbd_wire; 24 | 25 | DSP48E1 #( 26 | .ALUMODEREG(0), .CARRYINSELREG(0), .INMODEREG(0), .OPMODEREG(0), 27 | .CREG(0), .CARRYINREG(0), .MREG(1), .PREG(1), 28 | .USE_PATTERN_DETECT("PATDET"), .SEL_MASK("ROUNDING_MODE1") 29 | ) dsp_0 ( 30 | .CLK(CLK), 31 | .RSTA(1'b0), .RSTB(1'b0), .RSTM(1'b0), .RSTP(1'b0), 32 | .CEA2(1'b1), .CEB2(1'b1), .CED(1'b0), .CEAD(1'b0), .CEM(1'b1), .CEP(1'b1), 33 | .ALUMODE(4'b0000), .CARRYINSEL(3'b000), .INMODE(5'b00000), .OPMODE(7'b0110101), 34 | .A({{(30-A_WIDTH){A[A_WIDTH-1]}}, A}), 35 | .B({{(18-B_WIDTH){B[B_WIDTH-1]}}, B}), 36 | .C({{(48-ONES){1'b0}}, {(ONES){1'b1}}}), 37 | .CARRYIN(1'b0), 38 | .PATTERNBDETECT(int_pbd_wire), 39 | .P(int_p_wire) 40 | ); 41 | 42 | assign P = {int_p_wire[SHIFT+P_WIDTH-1:SHIFT+1], int_p_wire[SHIFT] | int_pbd_wire}; 43 | 44 | endmodule 45 | -------------------------------------------------------------------------------- /cores/port_slicer.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1 ns / 1 ps 3 | 4 | module port_slicer # 5 | ( 6 | parameter integer DIN_WIDTH = 32, 7 | parameter integer DIN_FROM = 31, 8 | parameter integer DIN_TO = 0 9 | ) 10 | ( 11 | input wire [DIN_WIDTH-1:0] din, 12 | output wire [DIN_FROM-DIN_TO:0] dout 13 | ); 14 | 15 | assign dout = din[DIN_FROM:DIN_TO]; 16 | 17 | endmodule 18 | -------------------------------------------------------------------------------- /dts/common.dts: -------------------------------------------------------------------------------- 1 | / { 2 | usb_phy0: phy0 { 3 | #phy-cells = <0>; 4 | compatible = "ulpi-phy"; 5 | reg = <0xe0002000 0x1000>; 6 | view-port = <0x0170>; 7 | drv-vbus; 8 | }; 9 | pps { 10 | compatible = "pps-gpio"; 11 | gpios = <&gpio0 54 0>; 12 | capture-clear; 13 | }; 14 | }; 15 | 16 | &gem0 { 17 | phy-handle = <ðernet_phy>; 18 | ethernet_phy: ethernet-phy@1 { 19 | reg = <1>; 20 | }; 21 | }; 22 | 23 | &usb0 { 24 | dr_mode = "host"; 25 | usb-phy = <&usb_phy0>; 26 | xlnx,phy-reset-gpio = <&gpio0 46 0>; 27 | }; 28 | 29 | &spi0 { 30 | spidev@0 { 31 | compatible = "ltc2488"; 32 | reg = <0x0>; 33 | spi-max-frequency = <10000000>; 34 | }; 35 | spidev@1 { 36 | compatible = "ltc2488"; 37 | reg = <0x1>; 38 | spi-max-frequency = <10000000>; 39 | }; 40 | spidev@2 { 41 | compatible = "ltc2488"; 42 | reg = <0x2>; 43 | spi-max-frequency = <10000000>; 44 | }; 45 | }; 46 | -------------------------------------------------------------------------------- /dts/initrd.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | 3 | /include/ "system-top.dts" 4 | /include/ "common.dts" 5 | 6 | / { 7 | chosen { 8 | bootargs = "console=ttyPS0,115200 earlycon earlyprintk initrd=0x3000000,4M modloop=modloop cma=36M"; 9 | }; 10 | }; 11 | -------------------------------------------------------------------------------- /helpers/build-all.sh: -------------------------------------------------------------------------------- 1 | source /opt/Xilinx/Vitis/2023.1/settings64.sh 2 | 3 | JOBS=`nproc 2> /dev/null || echo 1` 4 | 5 | make -j $JOBS cores 6 | 7 | make NAME=led_blinker_77_76 all 8 | 9 | PRJS="sdr_receiver_77_76 sdr_receiver_ft8_77_76 sdr_receiver_hpsdr_77_76 sdr_receiver_wspr_77_76" 10 | 11 | printf "%s\n" $PRJS | xargs -n 1 -P $JOBS -I {} make NAME={} bit 12 | 13 | sudo sh scripts/alpine.sh 14 | -------------------------------------------------------------------------------- /helpers/build-cores.tcl: -------------------------------------------------------------------------------- 1 | set files [glob -nocomplain cores/*.v] 2 | 3 | set part_name xc7z020clg484-1 4 | 5 | foreach file_name $files { 6 | set core_name [file rootname [file tail $file_name]] 7 | set argv [list $core_name $part_name] 8 | source scripts/core.tcl 9 | } 10 | -------------------------------------------------------------------------------- /helpers/dds-mem.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | a = 2**23 - 2 4 | 5 | x = (np.arange(2048) + 0.5) / 4096 6 | lut = np.round(a * np.cos(np.pi * x)).astype(np.uint32) 7 | 8 | print("\n".join([format(v, "06x") for v in lut])) 9 | -------------------------------------------------------------------------------- /mac.txt: -------------------------------------------------------------------------------- 1 | 52:54:C0:A8:01:64 2 | -------------------------------------------------------------------------------- /modules/inout_buffer.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1 ns / 1 ps 3 | 4 | module inout_buffer # 5 | ( 6 | parameter integer DATA_WIDTH = 32 7 | ) 8 | ( 9 | input wire aclk, 10 | input wire aresetn, 11 | 12 | input wire [DATA_WIDTH-1:0] in_data, 13 | input wire in_valid, 14 | output wire in_ready, 15 | 16 | output wire [DATA_WIDTH-1:0] out_data, 17 | output wire out_valid, 18 | input wire out_ready 19 | ); 20 | 21 | wire [DATA_WIDTH-1:0] int_data_wire; 22 | wire int_valid_wire, int_ready_wire; 23 | 24 | input_buffer #( 25 | .DATA_WIDTH(DATA_WIDTH) 26 | ) buf_0 ( 27 | .aclk(aclk), .aresetn(aresetn), 28 | .in_data(in_data), .in_valid(in_valid), .in_ready(in_ready), 29 | .out_data(int_data_wire), .out_valid(int_valid_wire), .out_ready(int_ready_wire) 30 | ); 31 | 32 | output_buffer #( 33 | .DATA_WIDTH(DATA_WIDTH) 34 | ) buf_1 ( 35 | .aclk(aclk), .aresetn(aresetn), 36 | .in_data(int_data_wire), .in_valid(int_valid_wire), .in_ready(int_ready_wire), 37 | .out_data(out_data), .out_valid(out_valid), .out_ready(out_ready) 38 | ); 39 | 40 | endmodule 41 | -------------------------------------------------------------------------------- /modules/input_buffer.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1 ns / 1 ps 3 | 4 | module input_buffer # 5 | ( 6 | parameter integer DATA_WIDTH = 32 7 | ) 8 | ( 9 | input wire aclk, 10 | input wire aresetn, 11 | 12 | input wire [DATA_WIDTH-1:0] in_data, 13 | input wire in_valid, 14 | output wire in_ready, 15 | 16 | output wire [DATA_WIDTH-1:0] out_data, 17 | output wire out_valid, 18 | input wire out_ready 19 | ); 20 | 21 | reg [DATA_WIDTH-1:0] int_data_reg; 22 | reg int_ready_reg = 1'b1; 23 | 24 | wire int_valid_wire = ~int_ready_reg | in_valid; 25 | 26 | always @(posedge aclk) 27 | begin 28 | if(~aresetn) 29 | begin 30 | int_ready_reg <= 1'b1; 31 | end 32 | else if(int_valid_wire) 33 | begin 34 | int_ready_reg <= out_ready; 35 | end 36 | 37 | if(int_ready_reg) 38 | begin 39 | int_data_reg <= in_data; 40 | end 41 | end 42 | 43 | assign in_ready = int_ready_reg; 44 | 45 | assign out_data = int_ready_reg ? in_data : int_data_reg; 46 | assign out_valid = int_valid_wire; 47 | 48 | endmodule 49 | -------------------------------------------------------------------------------- /modules/output_buffer.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1 ns / 1 ps 3 | 4 | module output_buffer # 5 | ( 6 | parameter integer DATA_WIDTH = 32 7 | ) 8 | ( 9 | input wire aclk, 10 | input wire aresetn, 11 | 12 | input wire [DATA_WIDTH-1:0] in_data, 13 | input wire in_valid, 14 | output wire in_ready, 15 | 16 | output wire [DATA_WIDTH-1:0] out_data, 17 | output wire out_valid, 18 | input wire out_ready 19 | ); 20 | 21 | reg [DATA_WIDTH-1:0] int_data_reg; 22 | reg int_valid_reg = 1'b0; 23 | 24 | wire int_ready_wire = ~int_valid_reg | out_ready; 25 | 26 | always @(posedge aclk) 27 | begin 28 | if(~aresetn) 29 | begin 30 | int_valid_reg <= 1'b0; 31 | end 32 | else if(int_ready_wire) 33 | begin 34 | int_valid_reg <= in_valid; 35 | end 36 | 37 | if(int_ready_wire) 38 | begin 39 | int_data_reg <= in_data; 40 | end 41 | end 42 | 43 | assign in_ready = int_ready_wire; 44 | 45 | assign out_data = int_data_reg; 46 | assign out_valid = int_valid_reg; 47 | 48 | endmodule 49 | -------------------------------------------------------------------------------- /patches/cma.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define CMA_ALLOC _IOWR('Z', 0, u32) 8 | 9 | static struct device *dma_device = NULL; 10 | static size_t dma_size = 0; 11 | static void *cpu_addr = NULL; 12 | static dma_addr_t dma_addr; 13 | 14 | static void cma_free(void) 15 | { 16 | if(!cpu_addr) return; 17 | dma_free_coherent(dma_device, dma_size, cpu_addr, dma_addr); 18 | cpu_addr = NULL; 19 | } 20 | 21 | static long cma_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 22 | { 23 | long rc; 24 | u32 buffer; 25 | 26 | if(cmd != CMA_ALLOC) return -ENOTTY; 27 | 28 | rc = copy_from_user(&buffer, (void __user *)arg, sizeof(buffer)); 29 | if(rc) return rc; 30 | 31 | cma_free(); 32 | 33 | dma_size = buffer; 34 | cpu_addr = dma_alloc_coherent(dma_device, dma_size, &dma_addr, GFP_KERNEL); 35 | 36 | if(IS_ERR_OR_NULL(cpu_addr)) 37 | { 38 | rc = PTR_ERR(cpu_addr); 39 | if(rc == 0) rc = -ENOMEM; 40 | cpu_addr = NULL; 41 | return rc; 42 | } 43 | 44 | buffer = dma_addr; 45 | return copy_to_user((void __user *)arg, &buffer, sizeof(buffer)); 46 | } 47 | 48 | static int cma_mmap(struct file *file, struct vm_area_struct *vma) 49 | { 50 | return dma_mmap_coherent(dma_device, vma, cpu_addr, dma_addr, dma_size); 51 | } 52 | 53 | static int cma_release(struct inode *inode, struct file *file) 54 | { 55 | cma_free(); 56 | return 0; 57 | } 58 | 59 | static struct file_operations cma_fops = 60 | { 61 | .unlocked_ioctl = cma_ioctl, 62 | .mmap = cma_mmap, 63 | .release = cma_release 64 | }; 65 | 66 | struct miscdevice cma_device = 67 | { 68 | .minor = MISC_DYNAMIC_MINOR, 69 | .name = "cma", 70 | .fops = &cma_fops 71 | }; 72 | 73 | static int __init cma_init(void) 74 | { 75 | int rc; 76 | 77 | rc = misc_register(&cma_device); 78 | if(rc) return rc; 79 | 80 | dma_device = cma_device.this_device; 81 | 82 | dma_device->dma_coherent = true; 83 | dma_device->coherent_dma_mask = DMA_BIT_MASK(32); 84 | 85 | return 0; 86 | } 87 | 88 | static void __exit cma_exit(void) 89 | { 90 | cma_free(); 91 | misc_deregister(&cma_device); 92 | } 93 | 94 | module_init(cma_init); 95 | module_exit(cma_exit); 96 | MODULE_LICENSE("MIT"); 97 | -------------------------------------------------------------------------------- /patches/fsbl.patch: -------------------------------------------------------------------------------- 1 | --- fsbl_hooks.c.old 2 | +++ fsbl_hooks.c 3 | @@ -34,6 +34,7 @@ 4 | 5 | /************************** Function Prototypes ******************************/ 6 | 7 | +u32 SetMacAddress(); 8 | 9 | /****************************************************************************** 10 | * This function is the hook which will be called before the bitstream download. 11 | @@ -112,6 +113,7 @@ u32 FsblHookBeforeHandoff(void) 12 | * Errors to be stored in the status variable and returned 13 | */ 14 | fsbl_printf(DEBUG_INFO,"In FsblHookBeforeHandoff function \r\n"); 15 | + Status = SetMacAddress(); 16 | 17 | return (Status); 18 | } 19 | -------------------------------------------------------------------------------- /patches/initramfs.patch: -------------------------------------------------------------------------------- 1 | --- init.old 2 | +++ init 3 | @@ -715,10 +715,9 @@ fi 4 | 5 | # locate boot media and mount it 6 | ebegin "Mounting boot media" 7 | -$MOCK nlplug-findfs $cryptopts -p /sbin/mdev ${KOPT_debug_init:+-d} \ 8 | - ${KOPT_usbdelay:+-t $(( $KOPT_usbdelay * 1000 ))} \ 9 | - ${KOPT_uevent_buf_size:+-U $KOPT_uevent_buf_size} \ 10 | - $repoopts -a "$ROOT"/tmp/apkovls 11 | +mkdir -p /media/mmcblk0p1 12 | +mount -o ro /dev/mmcblk0p1 /media/mmcblk0p1 13 | +ls /media/mmcblk0p1/*.apkovl.tar.gz > /tmp/apkovls 14 | eend $? 15 | 16 | # Setup network interfaces 17 | -------------------------------------------------------------------------------- /patches/linux-6.6.patch: -------------------------------------------------------------------------------- 1 | diff -rupN old/linux-6.6/drivers/char/Kconfig linux-6.6/drivers/char/Kconfig 2 | --- old/linux-6.6/drivers/char/Kconfig 3 | +++ linux-6.6/drivers/char/Kconfig 4 | @@ -422,4 +422,12 @@ config ADI 5 | and SSM (Silicon Secured Memory). Intended consumers of this 6 | driver include crash and makedumpfile. 7 | 8 | +config DEVCMA 9 | + bool "/dev/cma virtual device support" 10 | + default y 11 | + 12 | +config XILINX_DEVCFG 13 | + tristate "Xilinx Device Configuration" 14 | + depends on ARCH_ZYNQ 15 | + 16 | endmenu 17 | diff -rupN old/linux-6.6/drivers/char/Makefile linux-6.6/drivers/char/Makefile 18 | --- old/linux-6.6/drivers/char/Makefile 19 | +++ linux-6.6/drivers/char/Makefile 20 | @@ -44,3 +44,5 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o 21 | obj-$(CONFIG_XILLYBUS_CLASS) += xillybus/ 22 | obj-$(CONFIG_POWERNV_OP_PANEL) += powernv-op-panel.o 23 | obj-$(CONFIG_ADI) += adi.o 24 | +obj-$(CONFIG_DEVCMA) += cma.o 25 | +obj-$(CONFIG_XILINX_DEVCFG) += xilinx_devcfg.o 26 | diff -rupN old/linux-6.6/drivers/net/wireless/realtek/Kconfig linux-6.6/drivers/net/wireless/realtek/Kconfig 27 | --- old/linux-6.6/drivers/net/wireless/realtek/Kconfig 28 | +++ linux-6.6/drivers/net/wireless/realtek/Kconfig 29 | @@ -13,9 +13,9 @@ config WLAN_VENDOR_REALTEK 30 | if WLAN_VENDOR_REALTEK 31 | 32 | source "drivers/net/wireless/realtek/rtl818x/Kconfig" 33 | -source "drivers/net/wireless/realtek/rtlwifi/Kconfig" 34 | source "drivers/net/wireless/realtek/rtl8xxxu/Kconfig" 35 | source "drivers/net/wireless/realtek/rtw88/Kconfig" 36 | source "drivers/net/wireless/realtek/rtw89/Kconfig" 37 | +source "drivers/net/wireless/realtek/rtl8188eu/Kconfig" 38 | 39 | endif # WLAN_VENDOR_REALTEK 40 | diff -rupN old/linux-6.6/drivers/net/wireless/realtek/Makefile linux-6.6/drivers/net/wireless/realtek/Makefile 41 | --- old/linux-6.6/drivers/net/wireless/realtek/Makefile 42 | +++ linux-6.6/drivers/net/wireless/realtek/Makefile 43 | @@ -5,8 +5,8 @@ 44 | 45 | obj-$(CONFIG_RTL8180) += rtl818x/ 46 | obj-$(CONFIG_RTL8187) += rtl818x/ 47 | -obj-$(CONFIG_RTLWIFI) += rtlwifi/ 48 | obj-$(CONFIG_RTL8XXXU) += rtl8xxxu/ 49 | obj-$(CONFIG_RTW88) += rtw88/ 50 | obj-$(CONFIG_RTW89) += rtw89/ 51 | +obj-$(CONFIG_RTL8188EU) += rtl8188eu/ 52 | 53 | diff -rupN old/linux-6.6/drivers/pps/clients/pps-gpio.c linux-6.6/drivers/pps/clients/pps-gpio.c 54 | --- old/linux-6.6/drivers/pps/clients/pps-gpio.c 55 | +++ linux-6.6/drivers/pps/clients/pps-gpio.c 56 | @@ -113,6 +113,9 @@ static int pps_gpio_setup(struct device 57 | data->assert_falling_edge = 58 | device_property_read_bool(dev, "assert-falling-edge"); 59 | 60 | + data->capture_clear = 61 | + device_property_read_bool(dev, "capture-clear"); 62 | + 63 | data->echo_pin = devm_gpiod_get_optional(dev, "echo", GPIOD_OUT_LOW); 64 | if (IS_ERR(data->echo_pin)) 65 | return dev_err_probe(dev, PTR_ERR(data->echo_pin), 66 | diff -rupN old/linux-6.6/drivers/usb/chipidea/ci_hdrc_usb2.c linux-6.6/drivers/usb/chipidea/ci_hdrc_usb2.c 67 | --- old/linux-6.6/drivers/usb/chipidea/ci_hdrc_usb2.c 68 | +++ linux-6.6/drivers/usb/chipidea/ci_hdrc_usb2.c 69 | @@ -65,6 +65,14 @@ static int ci_hdrc_usb2_probe(struct pla 70 | if (match && match->data) { 71 | /* struct copy */ 72 | *ci_pdata = *(struct ci_hdrc_platform_data *)match->data; 73 | + if (of_device_is_compatible(pdev->dev.of_node, 74 | + "xlnx,zynq-usb-2.20a")) { 75 | + ci_pdata->usb_phy = devm_usb_get_phy_by_phandle(dev, 76 | + "usb-phy", 77 | + 0); 78 | + if (IS_ERR(ci_pdata->usb_phy)) 79 | + return PTR_ERR(ci_pdata->usb_phy); 80 | + } 81 | } 82 | 83 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 84 | diff -rupN old/linux-6.6/drivers/usb/chipidea/udc.c linux-6.6/drivers/usb/chipidea/udc.c 85 | --- old/linux-6.6/drivers/usb/chipidea/udc.c 86 | +++ linux-6.6/drivers/usb/chipidea/udc.c 87 | @@ -688,7 +688,8 @@ static int _hardware_dequeue(struct ci_h 88 | if ((TD_STATUS_ACTIVE & tmptoken) != 0) { 89 | int n = hw_ep_bit(hwep->num, hwep->dir); 90 | 91 | - if (ci->rev == CI_REVISION_24) 92 | + if (ci->rev == CI_REVISION_24 || 93 | + ci->rev == CI_REVISION_22) 94 | if (!hw_read(ci, OP_ENDPTSTAT, BIT(n))) 95 | reprime_dtd(ci, hwep, node); 96 | hwreq->req.status = -EALREADY; 97 | diff -rupN old/linux-6.6/drivers/usb/phy/Kconfig linux-6.6/drivers/usb/phy/Kconfig 98 | --- old/linux-6.6/drivers/usb/phy/Kconfig 99 | +++ linux-6.6/drivers/usb/phy/Kconfig 100 | @@ -160,7 +160,7 @@ config USB_TEGRA_PHY 101 | 102 | config USB_ULPI 103 | bool "Generic ULPI Transceiver Driver" 104 | - depends on ARM || ARM64 || COMPILE_TEST 105 | + depends on ARM || ARM64 || COMPILE_TEST || USB_PHY 106 | select USB_ULPI_VIEWPORT 107 | help 108 | Enable this to support ULPI connected USB OTG transceivers which 109 | diff -rupN old/linux-6.6/drivers/usb/phy/phy-ulpi.c linux-6.6/drivers/usb/phy/phy-ulpi.c 110 | --- old/linux-6.6/drivers/usb/phy/phy-ulpi.c 111 | +++ linux-6.6/drivers/usb/phy/phy-ulpi.c 112 | @@ -13,9 +13,16 @@ 113 | #include 114 | #include 115 | #include 116 | +#include 117 | +#include 118 | +#include 119 | +#include 120 | +#include 121 | +#include 122 | #include 123 | #include 124 | #include 125 | +#include 126 | 127 | 128 | struct ulpi_info { 129 | @@ -39,6 +46,13 @@ static struct ulpi_info ulpi_ids[] = { 130 | ULPI_INFO(ULPI_ID(0x0451, 0x1507), "TI TUSB1210"), 131 | }; 132 | 133 | +struct ulpi_phy { 134 | + struct usb_phy *usb_phy; 135 | + void __iomem *regs; 136 | + unsigned int vp_offset; 137 | + unsigned int flags; 138 | +}; 139 | + 140 | static int ulpi_set_otg_flags(struct usb_phy *phy) 141 | { 142 | unsigned int flags = ULPI_OTG_CTRL_DP_PULLDOWN | 143 | @@ -240,6 +254,23 @@ static int ulpi_set_vbus(struct usb_otg 144 | return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL); 145 | } 146 | 147 | +static int usbphy_set_vbus(struct usb_phy *phy, int on) 148 | +{ 149 | + unsigned int flags = usb_phy_io_read(phy, ULPI_OTG_CTRL); 150 | + 151 | + flags &= ~(ULPI_OTG_CTRL_DRVVBUS | ULPI_OTG_CTRL_DRVVBUS_EXT); 152 | + 153 | + if (on) { 154 | + if (phy->flags & ULPI_OTG_DRVVBUS) 155 | + flags |= ULPI_OTG_CTRL_DRVVBUS; 156 | + 157 | + if (phy->flags & ULPI_OTG_DRVVBUS_EXT) 158 | + flags |= ULPI_OTG_CTRL_DRVVBUS_EXT; 159 | + } 160 | + 161 | + return usb_phy_io_write(phy, flags, ULPI_OTG_CTRL); 162 | +} 163 | + 164 | static void otg_ulpi_init(struct usb_phy *phy, struct usb_otg *otg, 165 | struct usb_phy_io_ops *ops, 166 | unsigned int flags) 167 | @@ -249,6 +280,7 @@ static void otg_ulpi_init(struct usb_phy 168 | phy->io_ops = ops; 169 | phy->otg = otg; 170 | phy->init = ulpi_init; 171 | + phy->set_vbus = usbphy_set_vbus; 172 | 173 | otg->usb_phy = phy; 174 | otg->set_host = ulpi_set_host; 175 | @@ -301,3 +333,69 @@ devm_otg_ulpi_create(struct device *dev, 176 | return phy; 177 | } 178 | EXPORT_SYMBOL_GPL(devm_otg_ulpi_create); 179 | + 180 | +static int ulpi_phy_probe(struct platform_device *pdev) 181 | +{ 182 | + struct device_node *np = pdev->dev.of_node; 183 | + struct resource *res; 184 | + struct ulpi_phy *uphy; 185 | + int ret; 186 | + 187 | + uphy = devm_kzalloc(&pdev->dev, sizeof(*uphy), GFP_KERNEL); 188 | + if (!uphy) 189 | + return -ENOMEM; 190 | + 191 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 192 | + if (!res) { 193 | + dev_err(&pdev->dev, "no phy I/O memory resource defined\n"); 194 | + return -ENODEV; 195 | + } 196 | + 197 | + uphy->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 198 | + if (IS_ERR(uphy->regs)) 199 | + return PTR_ERR(uphy->regs); 200 | + 201 | + if (of_property_read_bool(np, "external-drv-vbus") || 202 | + of_property_read_bool(np, "drv-vbus")) 203 | + uphy->flags |= ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT; 204 | + 205 | + ret = of_property_read_u32(np, "view-port", &uphy->vp_offset); 206 | + if (ret) 207 | + return ret; 208 | + 209 | + uphy->usb_phy = otg_ulpi_create(&ulpi_viewport_access_ops, uphy->flags); 210 | + if (!uphy->usb_phy) { 211 | + dev_err(&pdev->dev, "Failed to create ULPI OTG\n"); 212 | + return -ENOMEM; 213 | + } 214 | + 215 | + uphy->usb_phy->dev = &pdev->dev; 216 | + uphy->usb_phy->io_priv = uphy->regs + uphy->vp_offset; 217 | + return usb_add_phy_dev(uphy->usb_phy); 218 | +} 219 | + 220 | +static void ulpi_phy_remove(struct platform_device *pdev) 221 | +{ 222 | + struct ulpi_phy *uphy = platform_get_drvdata(pdev); 223 | + 224 | + usb_remove_phy(uphy->usb_phy); 225 | +} 226 | + 227 | +static const struct of_device_id ulpi_phy_table[] = { 228 | + { .compatible = "ulpi-phy" }, 229 | + { }, 230 | +}; 231 | +MODULE_DEVICE_TABLE(of, ulpi_phy_table); 232 | + 233 | +static struct platform_driver ulpi_phy_driver = { 234 | + .probe = ulpi_phy_probe, 235 | + .remove_new = ulpi_phy_remove, 236 | + .driver = { 237 | + .name = "ulpi-phy", 238 | + .of_match_table = ulpi_phy_table, 239 | + }, 240 | +}; 241 | +module_platform_driver(ulpi_phy_driver); 242 | + 243 | +MODULE_DESCRIPTION("ULPI PHY driver"); 244 | +MODULE_LICENSE("GPL"); 245 | -------------------------------------------------------------------------------- /patches/qmtech_xc7z020_fsbl_hooks.c: -------------------------------------------------------------------------------- 1 | #include "xemacps.h" 2 | 3 | u32 SetMacAddress() 4 | { 5 | XEmacPs Emac; 6 | XEmacPs_Config *EmacConfig; 7 | u32 Status; 8 | u8 Buffer[6] = {0x52, 0x54, 0xC0, 0xA8, 0x01, 0x64}; 9 | 10 | EmacConfig = XEmacPs_LookupConfig(XPAR_PS7_ETHERNET_0_DEVICE_ID); 11 | if(EmacConfig == NULL) return XST_FAILURE; 12 | 13 | Status = XEmacPs_CfgInitialize(&Emac, EmacConfig, EmacConfig->BaseAddress); 14 | if(Status != XST_SUCCESS) return XST_FAILURE; 15 | 16 | Status = XEmacPs_SetMacAddress(&Emac, Buffer, 1); 17 | if(Status != XST_SUCCESS) return XST_FAILURE; 18 | 19 | return Status; 20 | } 21 | -------------------------------------------------------------------------------- /patches/xilinx_zynq_defconfig: -------------------------------------------------------------------------------- 1 | CONFIG_LOCALVERSION="-xilinx" 2 | CONFIG_SYSVIPC=y 3 | CONFIG_NO_HZ=y 4 | CONFIG_HIGH_RES_TIMERS=y 5 | CONFIG_PREEMPT=y 6 | CONFIG_IKCONFIG=y 7 | CONFIG_IKCONFIG_PROC=y 8 | CONFIG_LOG_BUF_SHIFT=14 9 | CONFIG_CGROUPS=y 10 | CONFIG_BLK_DEV_INITRD=y 11 | CONFIG_BPF_SYSCALL=y 12 | CONFIG_EXPERT=y 13 | # CONFIG_BUG is not set 14 | CONFIG_PERF_EVENTS=y 15 | CONFIG_ARCH_VEXPRESS=y 16 | CONFIG_ARCH_ZYNQ=y 17 | CONFIG_PL310_ERRATA_588369=y 18 | CONFIG_PL310_ERRATA_727915=y 19 | CONFIG_PL310_ERRATA_769419=y 20 | CONFIG_ARM_ERRATA_754322=y 21 | CONFIG_ARM_ERRATA_754327=y 22 | CONFIG_ARM_ERRATA_764369=y 23 | CONFIG_ARM_ERRATA_775420=y 24 | CONFIG_SMP=y 25 | CONFIG_SCHED_MC=y 26 | CONFIG_SCHED_SMT=y 27 | CONFIG_BIG_LITTLE=y 28 | CONFIG_BL_SWITCHER=y 29 | CONFIG_HIGHMEM=y 30 | CONFIG_CPU_FREQ=y 31 | CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y 32 | CONFIG_CPU_FREQ_GOV_PERFORMANCE=y 33 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y 34 | CONFIG_CPU_FREQ_GOV_ONDEMAND=y 35 | CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y 36 | CONFIG_CPU_IDLE=y 37 | CONFIG_ARM_ZYNQ_CPUIDLE=y 38 | CONFIG_VFP=y 39 | CONFIG_NEON=y 40 | CONFIG_MODULES=y 41 | CONFIG_MODULE_UNLOAD=y 42 | CONFIG_MODULE_FORCE_UNLOAD=y 43 | CONFIG_MODVERSIONS=y 44 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set 45 | # CONFIG_COMPACTION is not set 46 | CONFIG_CMA=y 47 | CONFIG_NET=y 48 | CONFIG_PACKET=y 49 | CONFIG_UNIX=y 50 | CONFIG_INET=y 51 | CONFIG_IP_MULTICAST=y 52 | CONFIG_IP_PNP=y 53 | CONFIG_IP_PNP_DHCP=y 54 | CONFIG_IP_PNP_BOOTP=y 55 | CONFIG_IP_PNP_RARP=y 56 | CONFIG_NET_IPIP=m 57 | CONFIG_SYN_COOKIES=y 58 | CONFIG_BRIDGE=m 59 | CONFIG_VLAN_8021Q=m 60 | CONFIG_CAN=y 61 | CONFIG_PCI=y 62 | CONFIG_PCI_MSI=y 63 | CONFIG_PCIE_XILINX=y 64 | CONFIG_UEVENT_HELPER=y 65 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" 66 | CONFIG_DEVTMPFS=y 67 | CONFIG_DEVTMPFS_MOUNT=y 68 | CONFIG_CONNECTOR=y 69 | CONFIG_MTD=y 70 | CONFIG_MTD_CMDLINE_PARTS=y 71 | CONFIG_MTD_BLOCK=y 72 | CONFIG_MTD_CFI=y 73 | CONFIG_MTD_CFI_AMDSTD=y 74 | CONFIG_MTD_PHYSMAP=y 75 | CONFIG_MTD_PHYSMAP_OF=y 76 | CONFIG_MTD_RAW_NAND=y 77 | CONFIG_MTD_NAND_PL35X=y 78 | CONFIG_MTD_SPI_NOR=y 79 | CONFIG_OF_OVERLAY=y 80 | CONFIG_BLK_DEV_LOOP=y 81 | CONFIG_BLK_DEV_RAM=y 82 | CONFIG_BLK_DEV_RAM_SIZE=16384 83 | CONFIG_EEPROM_AT24=y 84 | CONFIG_EEPROM_AT25=y 85 | CONFIG_SCSI=y 86 | CONFIG_BLK_DEV_SD=y 87 | CONFIG_CHR_DEV_SG=y 88 | CONFIG_NETDEVICES=y 89 | CONFIG_MACB=y 90 | # CONFIG_NET_VENDOR_CIRRUS is not set 91 | # CONFIG_NET_VENDOR_FARADAY is not set 92 | CONFIG_E1000E=y 93 | # CONFIG_NET_VENDOR_MARVELL is not set 94 | # CONFIG_NET_VENDOR_MICREL is not set 95 | # CONFIG_NET_VENDOR_MICROCHIP is not set 96 | # CONFIG_NET_VENDOR_NATSEMI is not set 97 | CONFIG_R8169=y 98 | # CONFIG_NET_VENDOR_SEEQ is not set 99 | # CONFIG_NET_VENDOR_SMSC is not set 100 | # CONFIG_NET_VENDOR_STMICRO is not set 101 | # CONFIG_NET_VENDOR_VIA is not set 102 | # CONFIG_NET_VENDOR_WIZNET is not set 103 | CONFIG_XILINX_EMACLITE=y 104 | CONFIG_XILINX_AXI_EMAC=y 105 | CONFIG_MARVELL_PHY=y 106 | CONFIG_VITESSE_PHY=y 107 | CONFIG_REALTEK_PHY=y 108 | CONFIG_CAN_XILINXCAN=y 109 | CONFIG_MDIO_BITBANG=y 110 | CONFIG_INPUT_SPARSEKMAP=y 111 | CONFIG_INPUT_EVDEV=y 112 | CONFIG_KEYBOARD_GPIO=y 113 | CONFIG_KEYBOARD_GPIO_POLLED=y 114 | # CONFIG_LEGACY_PTYS is not set 115 | CONFIG_SERIAL_XILINX_PS_UART=y 116 | CONFIG_SERIAL_XILINX_PS_UART_CONSOLE=y 117 | # CONFIG_HW_RANDOM is not set 118 | CONFIG_XILINX_DEVCFG=y 119 | CONFIG_I2C_CHARDEV=y 120 | CONFIG_I2C_MUX=y 121 | CONFIG_I2C_MUX_PCA954x=y 122 | CONFIG_I2C_CADENCE=y 123 | CONFIG_I2C_XILINX=y 124 | CONFIG_SPI=y 125 | CONFIG_SPI_CADENCE=y 126 | CONFIG_SPI_XILINX=y 127 | CONFIG_SPI_ZYNQ_QSPI=y 128 | CONFIG_GPIO_SYSFS=y 129 | CONFIG_GPIO_XILINX=y 130 | CONFIG_GPIO_ZYNQ=y 131 | CONFIG_PMBUS=y 132 | CONFIG_SENSORS_UCD9000=y 133 | CONFIG_SENSORS_UCD9200=y 134 | CONFIG_THERMAL=y 135 | CONFIG_CPU_THERMAL=y 136 | CONFIG_WATCHDOG=y 137 | CONFIG_XILINX_WATCHDOG=y 138 | CONFIG_CADENCE_WATCHDOG=y 139 | CONFIG_REGULATOR=y 140 | CONFIG_MEDIA_SUPPORT=y 141 | CONFIG_V4L_PLATFORM_DRIVERS=y 142 | CONFIG_VIDEO_XILINX=y 143 | CONFIG_VIDEO_XILINX_TPG=y 144 | CONFIG_VIDEO_ADV7604=y 145 | CONFIG_DRM=y 146 | CONFIG_SOUND=y 147 | CONFIG_SND=y 148 | CONFIG_SND_SOC=y 149 | CONFIG_SND_SOC_ADI=y 150 | CONFIG_SND_SOC_ADI_AXI_I2S=y 151 | CONFIG_SND_SOC_ADI_AXI_SPDIF=y 152 | CONFIG_HID_MICROSOFT=y 153 | CONFIG_USB=y 154 | CONFIG_USB_EHCI_HCD=y 155 | CONFIG_USB_EHCI_TT_NEWSCHED=y 156 | CONFIG_USB_STORAGE=y 157 | CONFIG_USB_UAS=m 158 | CONFIG_USB_CHIPIDEA=y 159 | CONFIG_USB_CHIPIDEA_UDC=y 160 | CONFIG_USB_CHIPIDEA_HOST=y 161 | CONFIG_NOP_USB_XCEIV=y 162 | CONFIG_USB_ULPI=y 163 | CONFIG_USB_GADGET=y 164 | CONFIG_USB_GADGET_XILINX=y 165 | CONFIG_USB_CONFIGFS=m 166 | CONFIG_USB_CONFIGFS_MASS_STORAGE=y 167 | CONFIG_USB_ZERO=m 168 | CONFIG_MMC=y 169 | CONFIG_MMC_SDHCI=y 170 | CONFIG_MMC_SDHCI_PLTFM=y 171 | CONFIG_MMC_SDHCI_OF_ARASAN=y 172 | CONFIG_NEW_LEDS=y 173 | CONFIG_LEDS_CLASS=y 174 | CONFIG_LEDS_GPIO=y 175 | CONFIG_LEDS_TRIGGERS=y 176 | CONFIG_LEDS_TRIGGER_TIMER=y 177 | CONFIG_LEDS_TRIGGER_ONESHOT=y 178 | CONFIG_LEDS_TRIGGER_HEARTBEAT=y 179 | CONFIG_LEDS_TRIGGER_BACKLIGHT=y 180 | CONFIG_LEDS_TRIGGER_CPU=y 181 | CONFIG_LEDS_TRIGGER_GPIO=y 182 | CONFIG_LEDS_TRIGGER_DEFAULT_ON=y 183 | CONFIG_LEDS_TRIGGER_TRANSIENT=y 184 | CONFIG_LEDS_TRIGGER_CAMERA=y 185 | CONFIG_EDAC=y 186 | CONFIG_EDAC_SYNOPSYS=y 187 | CONFIG_RTC_CLASS=y 188 | CONFIG_RTC_DRV_PCF8563=y 189 | CONFIG_DMADEVICES=y 190 | CONFIG_PL330_DMA=y 191 | CONFIG_XILINX_DMA=y 192 | CONFIG_UIO=y 193 | CONFIG_UIO_PDRV_GENIRQ=y 194 | CONFIG_COMMON_CLK_SI570=y 195 | CONFIG_REMOTEPROC=y 196 | CONFIG_MEMORY=y 197 | CONFIG_IIO=y 198 | CONFIG_XILINX_XADC=y 199 | CONFIG_XILINX_INTC=y 200 | CONFIG_RAS=y 201 | CONFIG_EXT3_FS=y 202 | # CONFIG_DNOTIFY is not set 203 | CONFIG_MSDOS_FS=y 204 | CONFIG_VFAT_FS=y 205 | CONFIG_TMPFS=y 206 | CONFIG_JFFS2_FS=y 207 | CONFIG_JFFS2_SUMMARY=y 208 | CONFIG_NFS_FS=y 209 | CONFIG_ROOT_NFS=y 210 | CONFIG_NLS_CODEPAGE_437=y 211 | CONFIG_NLS_ASCII=y 212 | CONFIG_NLS_ISO8859_1=y 213 | CONFIG_DMA_CMA=y 214 | CONFIG_RCU_CPU_STALL_TIMEOUT=60 215 | # CONFIG_FTRACE is not set 216 | CONFIG_OVERLAY_FS=y 217 | CONFIG_SQUASHFS=y 218 | CONFIG_SQUASHFS_XZ=y 219 | CONFIG_WIRELESS=y 220 | CONFIG_CFG80211=m 221 | CONFIG_MAC80211=m 222 | CONFIG_RTL8188EU=m 223 | CONFIG_RT2X00=m 224 | CONFIG_RT2800USB=m 225 | CONFIG_RT2800USB_RT3573=y 226 | CONFIG_RT2800USB_RT53XX=y 227 | CONFIG_RT2800USB_RT55XX=y 228 | CONFIG_RT2800USB_UNKNOWN=y 229 | CONFIG_MT7601U=m 230 | CONFIG_ATH9K_HTC=m 231 | CONFIG_B43=m 232 | CONFIG_BRCMFMAC=m 233 | CONFIG_BRCMFMAC_USB=y 234 | CONFIG_PPP=m 235 | CONFIG_PPP_ASYNC=m 236 | CONFIG_PPP_BSDCOMP=m 237 | CONFIG_PPP_DEFLATE=m 238 | CONFIG_PPP_FILTER=y 239 | CONFIG_PPP_MULTILINK=y 240 | CONFIG_PPP_SYNC_TTY=m 241 | CONFIG_USB_USBNET=m 242 | CONFIG_USB_NET_CDC_EEM=m 243 | CONFIG_USB_NET_CDC_MBIM=m 244 | CONFIG_USB_NET_HUAWEI_CDC_NCM=m 245 | CONFIG_USB_NET_QMI_WWAN=m 246 | CONFIG_NAMESPACES=y 247 | CONFIG_NETFILTER=y 248 | CONFIG_NETFILTER_NETLINK=m 249 | CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m 250 | CONFIG_NETFILTER_XT_MATCH_STATE=m 251 | CONFIG_NF_CONNTRACK=m 252 | CONFIG_NF_TABLES=m 253 | CONFIG_NF_TABLES_IPV4=y 254 | CONFIG_NFT_CT=m 255 | CONFIG_NFT_MASQ=m 256 | CONFIG_NFT_NAT=m 257 | CONFIG_NFT_COMPAT=m 258 | CONFIG_IP_NF_IPTABLES=m 259 | CONFIG_IP_NF_NAT=m 260 | CONFIG_IP_NF_TARGET_MASQUERADE=m 261 | CONFIG_IP_NF_FILTER=m 262 | CONFIG_IP_NF_MANGLE=m 263 | CONFIG_MACVLAN=m 264 | CONFIG_TUN=m 265 | CONFIG_FUSE_FS=m 266 | CONFIG_SPI_SPIDEV=m 267 | CONFIG_PPS_CLIENT_GPIO=m 268 | CONFIG_PPS_CLIENT_LDISC=m 269 | CONFIG_USB_GPIO_VBUS=y 270 | CONFIG_USB_ULPI_BUS=y 271 | CONFIG_SND_USB_AUDIO=m 272 | CONFIG_USB_SERIAL=m 273 | CONFIG_USB_SERIAL_GENERIC=y 274 | CONFIG_USB_SERIAL_OPTION=m 275 | CONFIG_USB_SERIAL_FTDI_SIO=m 276 | CONFIG_CIFS=m 277 | CONFIG_CIFS_STATS2=y 278 | CONFIG_CIFS_UPCALL=y 279 | CONFIG_CIFS_XATTR=y 280 | CONFIG_CIFS_POSIX=y 281 | CONFIG_CIFS_DFS_UPCALL=y 282 | CONFIG_USB_ACM=m 283 | CONFIG_USB_TMC=m 284 | CONFIG_VIDEOBUF2_VMALLOC=m 285 | CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=8 286 | CONFIG_U_SERIAL_CONSOLE=y 287 | CONFIG_USB_F_ACM=m 288 | CONFIG_USB_U_SERIAL=m 289 | CONFIG_USB_U_ETHER=m 290 | CONFIG_USB_F_SERIAL=m 291 | CONFIG_USB_F_OBEX=m 292 | CONFIG_USB_F_NCM=m 293 | CONFIG_USB_F_ECM=m 294 | CONFIG_USB_F_EEM=m 295 | CONFIG_USB_F_SUBSET=m 296 | CONFIG_USB_F_RNDIS=m 297 | CONFIG_USB_F_FS=m 298 | CONFIG_USB_F_UAC1=m 299 | CONFIG_USB_F_UAC2=m 300 | CONFIG_USB_F_UVC=m 301 | CONFIG_USB_F_MIDI=m 302 | CONFIG_USB_F_HID=m 303 | CONFIG_USB_F_PRINTER=m 304 | CONFIG_USB_CONFIGFS_SERIAL=y 305 | CONFIG_USB_CONFIGFS_ACM=y 306 | CONFIG_USB_CONFIGFS_OBEX=y 307 | CONFIG_USB_CONFIGFS_NCM=y 308 | CONFIG_USB_CONFIGFS_ECM=y 309 | CONFIG_USB_CONFIGFS_ECM_SUBSET=y 310 | CONFIG_USB_CONFIGFS_RNDIS=y 311 | CONFIG_USB_CONFIGFS_EEM=y 312 | CONFIG_USB_CONFIGFS_F_LB_SS=y 313 | CONFIG_USB_CONFIGFS_F_FS=y 314 | CONFIG_USB_CONFIGFS_F_UAC1=y 315 | CONFIG_USB_CONFIGFS_F_UAC2=y 316 | CONFIG_USB_CONFIGFS_F_MIDI=y 317 | CONFIG_USB_CONFIGFS_F_HID=y 318 | CONFIG_USB_CONFIGFS_F_UVC=y 319 | CONFIG_USB_CONFIGFS_F_PRINTER=y 320 | CONFIG_USB_AUDIO=m 321 | CONFIG_GADGET_UAC1=y 322 | CONFIG_USB_ETH=m 323 | CONFIG_USB_ETH_RNDIS=y 324 | CONFIG_USB_ETH_EEM=y 325 | CONFIG_USB_G_NCM=m 326 | CONFIG_USB_GADGETFS=m 327 | CONFIG_USB_FUNCTIONFS=m 328 | CONFIG_USB_FUNCTIONFS_ETH=y 329 | CONFIG_USB_FUNCTIONFS_RNDIS=y 330 | CONFIG_USB_FUNCTIONFS_GENERIC=y 331 | CONFIG_USB_MASS_STORAGE=m 332 | CONFIG_USB_G_SERIAL=m 333 | CONFIG_USB_MIDI_GADGET=m 334 | CONFIG_USB_G_PRINTER=m 335 | CONFIG_USB_CDC_COMPOSITE=m 336 | CONFIG_USB_G_ACM_MS=m 337 | CONFIG_USB_G_MULTI=m 338 | CONFIG_USB_G_MULTI_RNDIS=y 339 | CONFIG_USB_G_MULTI_CDC=y 340 | CONFIG_USB_G_HID=m 341 | CONFIG_USB_G_WEBCAM=m 342 | -------------------------------------------------------------------------------- /projects/common_tools/app/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -O3 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard 2 | 3 | all: measure-corr measure-level setup-adc sleep-rand sleep-to-59 4 | 5 | measure-corr: measure-corr.c 6 | gcc $(CFLAGS) -o $@ $^ 7 | 8 | measure-level: measure-level.c 9 | gcc $(CFLAGS) -o $@ $^ -lm 10 | 11 | setup-adc: setup-adc.c 12 | gcc $(CFLAGS) -o $@ $^ 13 | 14 | sleep-rand: sleep-rand.c 15 | gcc $(CFLAGS) -o $@ $^ 16 | 17 | sleep-to-59: sleep-to-59.c 18 | gcc $(CFLAGS) -o $@ $^ 19 | 20 | clean: 21 | rm -f measure-corr measure-level setup-adc sleep-rand sleep-to-59 22 | -------------------------------------------------------------------------------- /projects/common_tools/app/enable-adc.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | echo 567 > /sys/class/gpio/export 4 | echo out > /sys/class/gpio/gpio567/direction 5 | echo 1 > /sys/class/gpio/gpio567/value 6 | -------------------------------------------------------------------------------- /projects/common_tools/app/measure-corr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | void usage() 11 | { 12 | fprintf(stderr, "Usage: measure-corr freq time\n"); 13 | fprintf(stderr, " freq - frequency expressed in MHz (77.76, 100, 122.88 or 125),\n"); 14 | fprintf(stderr, " time - measurement time expressed in seconds (from 1 to 30).\n"); 15 | } 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | int fd, i; 20 | char *end; 21 | volatile void *cfg, *sts; 22 | volatile uint32_t *fifo; 23 | volatile uint8_t *rst; 24 | volatile uint32_t *cntr; 25 | double freq; 26 | long time; 27 | uint32_t buffer; 28 | float corr; 29 | 30 | if(argc != 3) 31 | { 32 | usage(); 33 | return EXIT_FAILURE; 34 | } 35 | 36 | errno = 0; 37 | freq = strtod(argv[1], &end); 38 | if(errno != 0 || end == argv[1] || (freq != 77.76 && freq != 100.0 && freq != 122.88 && freq != 125.0)) 39 | { 40 | usage(); 41 | return EXIT_FAILURE; 42 | } 43 | 44 | time = strtol(argv[2], &end, 10); 45 | if(errno != 0 || end == argv[2] || time < 1 || time > 30) 46 | { 47 | usage(); 48 | return EXIT_FAILURE; 49 | } 50 | 51 | if((fd = open("/dev/mem", O_RDWR)) < 0) 52 | { 53 | fprintf(stderr, "Cannot open /dev/mem.\n"); 54 | return EXIT_FAILURE; 55 | } 56 | 57 | cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x80000000); 58 | sts = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x81000000); 59 | fifo = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x82000000); 60 | 61 | rst = (uint8_t *)(cfg + 0); 62 | cntr = (uint32_t *)(sts + 0); 63 | 64 | *rst &= ~1; 65 | *rst |= 1; 66 | 67 | sleep(time + 1); 68 | 69 | if(*cntr < time) 70 | { 71 | fprintf(stderr, "Not enough PPS pulses.\n"); 72 | return EXIT_FAILURE; 73 | } 74 | 75 | buffer = 0; 76 | 77 | for(i = 0; i < time; ++i) 78 | { 79 | buffer += *fifo + 1; 80 | } 81 | 82 | corr = (freq * 1.0e6 * time / buffer - 1.0) * 1.0e6; 83 | 84 | if(corr < -100.0 || corr > 100.0) 85 | { 86 | fprintf(stderr, "Correction value is out of range.\n"); 87 | return EXIT_FAILURE; 88 | } 89 | 90 | printf("%.2f\n", corr); 91 | 92 | return EXIT_SUCCESS; 93 | } 94 | -------------------------------------------------------------------------------- /projects/common_tools/app/measure-level.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int interrupted = 0; 13 | 14 | void signal_handler(int sig) 15 | { 16 | interrupted = 1; 17 | } 18 | 19 | void usage() 20 | { 21 | fprintf(stderr, "Usage: measure-level freq time\n"); 22 | fprintf(stderr, " freq - frequency expressed in MHz (77.76, 100, 122.88 or 125),\n"); 23 | fprintf(stderr, " time - measurement time expressed in seconds (from 1 to 30).\n"); 24 | } 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | int fd; 29 | char *end; 30 | volatile void *cfg, *sts; 31 | volatile uint8_t *rst; 32 | volatile uint16_t *cntr, *fifo; 33 | double freq, dbfs; 34 | long time; 35 | uint16_t level; 36 | 37 | if(argc != 3) 38 | { 39 | usage(); 40 | return EXIT_FAILURE; 41 | } 42 | 43 | errno = 0; 44 | freq = strtod(argv[1], &end); 45 | if(errno != 0 || end == argv[1] || (freq != 77.76 && freq != 100.0 && freq != 122.88 && freq != 125.0)) 46 | { 47 | usage(); 48 | return EXIT_FAILURE; 49 | } 50 | 51 | errno = 0; 52 | time = strtol(argv[2], &end, 10); 53 | if(errno != 0 || end == argv[2] || time < 1 || time > 30) 54 | { 55 | usage(); 56 | return EXIT_FAILURE; 57 | } 58 | 59 | if((fd = open("/dev/mem", O_RDWR)) < 0) 60 | { 61 | fprintf(stderr, "Cannot open /dev/mem.\n"); 62 | return EXIT_FAILURE; 63 | } 64 | 65 | cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x80000000); 66 | sts = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x81000000); 67 | fifo = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x83000000); 68 | 69 | rst = (uint8_t *)(cfg + 1); 70 | cntr = (uint16_t *)(sts + 2); 71 | 72 | *(uint32_t *)(cfg + 4) = (uint32_t)floor(freq * 1.0e6 * time + 0.5) - 1; 73 | 74 | *rst &= ~1; 75 | *rst |= 1; 76 | 77 | signal(SIGINT, signal_handler); 78 | 79 | while(!interrupted) 80 | { 81 | if(*cntr < 1) 82 | { 83 | usleep(1000); 84 | continue; 85 | } 86 | 87 | level = *fifo; 88 | 89 | dbfs = 20.0 * log10(1.0 * level / 8192); 90 | 91 | printf("%5.1f dBFS\n", dbfs); 92 | } 93 | 94 | *rst &= ~1; 95 | 96 | return EXIT_SUCCESS; 97 | } 98 | -------------------------------------------------------------------------------- /projects/common_tools/app/setup-adc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main() 10 | { 11 | int i, fd, value; 12 | 13 | uint8_t data[9] = 14 | { 15 | 0x00, 0x0B, 0x01, 16 | 0x00, 0x14, 0x41, 17 | 0x00, 0xFF, 0x01 18 | }; 19 | 20 | fd = open("/dev/spidev0.0", O_RDWR); 21 | 22 | value = SPI_MODE_0; 23 | ioctl(fd, SPI_IOC_WR_MODE, &value); 24 | 25 | value = 8; 26 | ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &value); 27 | 28 | value = 1000000; 29 | ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &value); 30 | 31 | write(fd, data, 9); 32 | 33 | close(fd); 34 | 35 | return EXIT_SUCCESS; 36 | } 37 | -------------------------------------------------------------------------------- /projects/common_tools/app/sleep-rand.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int argc, char *argv[]) 7 | { 8 | char *end; 9 | long number; 10 | struct timespec t; 11 | 12 | errno = 0; 13 | number = (argc == 2) ? strtol(argv[1], &end, 10) : -1; 14 | if(errno != 0 || end == argv[1] || number < 1 || number > 3600) 15 | { 16 | fprintf(stderr, "Usage: sleep-rand [1-3600]\n"); 17 | return EXIT_FAILURE; 18 | } 19 | 20 | clock_gettime(CLOCK_REALTIME, &t); 21 | srand(t.tv_nsec / 1000); 22 | t.tv_sec = rand() % number; 23 | t.tv_nsec = rand() % 1000 * 1000000L; 24 | nanosleep(&t, NULL); 25 | return EXIT_SUCCESS; 26 | } 27 | -------------------------------------------------------------------------------- /projects/common_tools/app/sleep-to-59.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | struct timespec t; 8 | clock_gettime(CLOCK_REALTIME, &t); 9 | t.tv_sec = 58 - t.tv_sec % 60; 10 | t.tv_nsec = 999999999L - t.tv_nsec; 11 | nanosleep(&t, NULL); 12 | return EXIT_SUCCESS; 13 | } 14 | -------------------------------------------------------------------------------- /projects/common_tools/app/update-corr.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | DIR=`readlink -f $0` 4 | DIR=`dirname $DIR` 5 | 6 | date 7 | 8 | CORR=`$DIR/measure-corr $1 30` || exit 9 | 10 | for file in *.cfg 11 | do 12 | sed -i "/^corr/s/=.*/= $CORR;/" $file 13 | done 14 | -------------------------------------------------------------------------------- /projects/common_tools/block_design.tcl: -------------------------------------------------------------------------------- 1 | # HUB 2 | 3 | # Create axi_hub 4 | cell pavel-demin:user:axi_hub hub_0 { 5 | CFG_DATA_WIDTH 64 6 | STS_DATA_WIDTH 32 7 | } { 8 | S_AXI /ps_0/M_AXI_GP1 9 | aclk /pll_0/clk_out1 10 | aresetn /rst_0/peripheral_aresetn 11 | } 12 | 13 | cell pavel-demin:user:port_slicer rst_slice_0 { 14 | DIN_WIDTH 64 DIN_FROM 0 DIN_TO 0 15 | } { 16 | din hub_0/cfg_data 17 | } 18 | 19 | # Create port_slicer 20 | cell pavel-demin:user:port_slicer rst_slice_1 { 21 | DIN_WIDTH 64 DIN_FROM 8 DIN_TO 8 22 | } { 23 | din hub_0/cfg_data 24 | } 25 | 26 | # Create port_slicer 27 | cell pavel-demin:user:port_slicer cfg_slice_0 { 28 | DIN_WIDTH 64 DIN_FROM 63 DIN_TO 32 29 | } { 30 | din hub_0/cfg_data 31 | } 32 | 33 | # Create port_slicer 34 | cell pavel-demin:user:port_slicer pps_slice_0 { 35 | DIN_WIDTH 1 DIN_FROM 0 DIN_TO 0 36 | } { 37 | din /pps_i 38 | dout /ps_0/GPIO_I 39 | } 40 | 41 | # PPS 42 | 43 | # Create axis_pps_counter 44 | cell pavel-demin:user:axis_pps_counter cntr_0 { 45 | AXIS_TDATA_WIDTH 32 46 | CNTR_WIDTH 32 47 | } { 48 | pps_data pps_slice_0/dout 49 | aclk /pll_0/clk_out1 50 | aresetn rst_slice_0/dout 51 | } 52 | 53 | # Create axis_fifo 54 | cell pavel-demin:user:axis_fifo fifo_0 { 55 | S_AXIS_TDATA_WIDTH 32 56 | M_AXIS_TDATA_WIDTH 32 57 | WRITE_DEPTH 1024 58 | } { 59 | S_AXIS cntr_0/M_AXIS 60 | M_AXIS hub_0/S00_AXIS 61 | aclk /pll_0/clk_out1 62 | aresetn rst_slice_0/dout 63 | } 64 | 65 | # Level measurement 66 | 67 | # Create xlconstant 68 | cell xilinx.com:ip:xlconstant const_0 69 | 70 | # Create axis_decimator 71 | cell pavel-demin:user:axis_maxabs_finder maxabs_0 { 72 | AXIS_TDATA_WIDTH 16 73 | CNTR_WIDTH 32 74 | } { 75 | s_axis_tdata /adc_0/m_axis_tdata 76 | s_axis_tvalid const_0/dout 77 | cfg_data cfg_slice_0/dout 78 | aclk /pll_0/clk_out1 79 | aresetn rst_slice_1/dout 80 | } 81 | 82 | # Create axis_fifo 83 | cell pavel-demin:user:axis_fifo fifo_1 { 84 | S_AXIS_TDATA_WIDTH 16 85 | M_AXIS_TDATA_WIDTH 32 86 | WRITE_DEPTH 1024 87 | } { 88 | S_AXIS maxabs_0/M_AXIS 89 | M_AXIS hub_0/S01_AXIS 90 | aclk /pll_0/clk_out1 91 | aresetn rst_slice_1/dout 92 | } 93 | 94 | # Create xlconcat 95 | cell xilinx.com:ip:xlconcat concat_0 { 96 | NUM_PORTS 2 97 | IN0_WIDTH 16 98 | IN1_WIDTH 16 99 | } { 100 | In0 fifo_0/read_count 101 | In1 fifo_1/read_count 102 | dout hub_0/sts_data 103 | } 104 | -------------------------------------------------------------------------------- /projects/led_blinker_77_76/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LED blinker 6 | 7 | 8 | 9 | 10 | 19 |
20 |

LED blinker

21 |

The LED blinker application is ready.

22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /projects/led_blinker_77_76/app/start.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | apps_dir=/media/mmcblk0p1/apps 4 | 5 | source $apps_dir/stop.sh 6 | 7 | cat $apps_dir/led_blinker_77_76/led_blinker_77_76.bit > /dev/xdevcfg 8 | 9 | $apps_dir/common_tools/setup-adc 10 | $apps_dir/common_tools/enable-adc.sh 11 | -------------------------------------------------------------------------------- /projects/led_blinker_77_76/block_design.tcl: -------------------------------------------------------------------------------- 1 | # Create ports 2 | create_bd_port -dir I adc_clk_p_i 3 | create_bd_port -dir I adc_clk_n_i 4 | 5 | create_bd_port -dir O adc_spi_sclk 6 | create_bd_port -dir O adc_spi_sdio 7 | create_bd_port -dir O adc_spi_cs 8 | 9 | create_bd_port -dir O adc_oe 10 | 11 | # Create xlconstant 12 | cell xilinx.com:ip:xlconstant const_0 13 | 14 | # Create clk_wiz 15 | cell xilinx.com:ip:clk_wiz pll_0 { 16 | PRIMITIVE PLL 17 | PRIM_IN_FREQ.VALUE_SRC USER 18 | PRIM_IN_FREQ 77.76 19 | PRIM_SOURCE Differential_clock_capable_pin 20 | CLKOUT1_USED true 21 | CLKOUT1_REQUESTED_OUT_FREQ 77.76 22 | USE_RESET false 23 | } { 24 | clk_in1_p adc_clk_p_i 25 | clk_in1_n adc_clk_n_i 26 | } 27 | 28 | # Create processing_system7 29 | cell xilinx.com:ip:processing_system7 ps_0 { 30 | PCW_IMPORT_BOARD_PRESET cfg/qmtech_xc7z020.xml 31 | } { 32 | M_AXI_GP0_ACLK pll_0/clk_out1 33 | SPI0_SCLK_O adc_spi_sclk 34 | SPI0_MOSI_O adc_spi_sdio 35 | SPI0_SS_I const_0/dout 36 | SPI0_SS_O adc_spi_cs 37 | } 38 | 39 | # Create port_slicer 40 | cell pavel-demin:user:port_slicer slice_0 { 41 | DIN_WIDTH 64 DIN_FROM 1 DIN_TO 1 42 | } { 43 | din ps_0/GPIO_O 44 | dout adc_oe 45 | } 46 | 47 | # Create all required interconnections 48 | apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config { 49 | make_external {FIXED_IO, DDR} 50 | Master Disable 51 | Slave Disable 52 | } [get_bd_cells ps_0] 53 | 54 | # LED 55 | 56 | # Create c_counter_binary 57 | cell xilinx.com:ip:c_counter_binary cntr_0 { 58 | Output_Width 32 59 | } { 60 | CLK pll_0/clk_out1 61 | } 62 | 63 | # Create xlslice 64 | cell xilinx.com:ip:xlslice slice_1 { 65 | DIN_WIDTH 32 DIN_FROM 25 DIN_TO 25 DOUT_WIDTH 1 66 | } { 67 | Din cntr_0/Q 68 | Dout led_o 69 | } 70 | -------------------------------------------------------------------------------- /projects/led_blinker_77_76/ports.xdc: -------------------------------------------------------------------------------- 1 | # clock 2 | 3 | set_property IOSTANDARD LVDS_25 [get_ports adc_clk_p_i] 4 | set_property IOSTANDARD LVDS_25 [get_ports adc_clk_n_i] 5 | 6 | set_property DIFF_TERM TRUE [get_ports adc_clk_p_i] 7 | set_property DIFF_TERM TRUE [get_ports adc_clk_n_i] 8 | 9 | set_property PACKAGE_PIN Y19 [get_ports adc_clk_p_i] 10 | set_property PACKAGE_PIN AA19 [get_ports adc_clk_n_i] 11 | 12 | # SPI 13 | 14 | set_property IOSTANDARD LVCMOS25 [get_ports adc_spi_*] 15 | 16 | set_property PACKAGE_PIN AA13 [get_ports adc_spi_sclk] 17 | set_property PACKAGE_PIN Y13 [get_ports adc_spi_sdio] 18 | set_property PACKAGE_PIN U15 [get_ports adc_spi_cs] 19 | 20 | # output enable 21 | 22 | set_property IOSTANDARD LVCMOS25 [get_ports adc_oe] 23 | 24 | set_property PACKAGE_PIN Y20 [get_ports adc_oe] 25 | -------------------------------------------------------------------------------- /projects/sdr_receiver_77_76/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SDR receiver compatible with HPSDR 6 | 7 | 8 | 9 | 10 | 19 |
20 |

SDR receiver

21 |

The SDR receiver is ready.

22 |

Now you can run the SDR programs such as SDR#, HDSDR.

23 |

More details about this application can be found at this link.

24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /projects/sdr_receiver_77_76/app/start.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | apps_dir=/media/mmcblk0p1/apps 4 | 5 | source $apps_dir/stop.sh 6 | 7 | cat $apps_dir/sdr_receiver_77_76/sdr_receiver_77_76.bit > /dev/xdevcfg 8 | 9 | $apps_dir/common_tools/setup-adc 10 | $apps_dir/common_tools/enable-adc.sh 11 | 12 | address=`awk -F : '$5="FF"' OFS=: /sys/class/net/eth0/address` 13 | 14 | echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce 15 | echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore 16 | echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter 17 | 18 | ip link add mvl0 link eth0 address $address type macvlan mode passthru 19 | 20 | $apps_dir/sdr_receiver_77_76/sdr-receiver eth0 & 21 | $apps_dir/sdr_receiver_77_76/sdr-receiver mvl0 & 22 | -------------------------------------------------------------------------------- /projects/sdr_receiver_77_76/app/stop.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | killall -q sdr-receiver 4 | 5 | ip link del mvl0 6 | 7 | echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce 8 | echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore 9 | echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter 10 | -------------------------------------------------------------------------------- /projects/sdr_receiver_77_76/block_design.tcl: -------------------------------------------------------------------------------- 1 | # Create ports 2 | create_bd_port -dir I adc_clk_p_i 3 | create_bd_port -dir I adc_clk_n_i 4 | 5 | create_bd_port -dir I adc_ovr_p_i 6 | create_bd_port -dir I adc_ovr_n_i 7 | 8 | create_bd_port -dir I -from 6 -to 0 adc_dat_p_i 9 | create_bd_port -dir I -from 6 -to 0 adc_dat_n_i 10 | 11 | create_bd_port -dir O adc_spi_sclk 12 | create_bd_port -dir O adc_spi_sdio 13 | create_bd_port -dir O adc_spi_cs 14 | 15 | create_bd_port -dir O adc_oe 16 | 17 | # Create xlconstant 18 | cell xilinx.com:ip:xlconstant const_0 19 | 20 | # Create clk_wiz 21 | cell xilinx.com:ip:clk_wiz pll_0 { 22 | PRIMITIVE PLL 23 | PRIM_IN_FREQ.VALUE_SRC USER 24 | PRIM_IN_FREQ 77.76 25 | PRIM_SOURCE Differential_clock_capable_pin 26 | CLKOUT1_USED true 27 | CLKOUT1_REQUESTED_OUT_FREQ 77.76 28 | USE_RESET false 29 | } { 30 | clk_in1_p adc_clk_p_i 31 | clk_in1_n adc_clk_n_i 32 | } 33 | 34 | # Create processing_system7 35 | cell xilinx.com:ip:processing_system7 ps_0 { 36 | PCW_IMPORT_BOARD_PRESET cfg/qmtech_xc7z020.xml 37 | PCW_USE_M_AXI_GP1 1 38 | } { 39 | M_AXI_GP0_ACLK pll_0/clk_out1 40 | M_AXI_GP1_ACLK pll_0/clk_out1 41 | SPI0_SCLK_O adc_spi_sclk 42 | SPI0_MOSI_O adc_spi_sdio 43 | SPI0_SS_I const_0/dout 44 | SPI0_SS_O adc_spi_cs 45 | } 46 | 47 | # Create port_slicer 48 | cell pavel-demin:user:port_slicer slice_0 { 49 | DIN_WIDTH 64 DIN_FROM 1 DIN_TO 1 50 | } { 51 | din ps_0/GPIO_O 52 | dout adc_oe 53 | } 54 | 55 | # Create all required interconnections 56 | apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config { 57 | make_external {FIXED_IO, DDR} 58 | Master Disable 59 | Slave Disable 60 | } [get_bd_cells ps_0] 61 | 62 | # Create proc_sys_reset 63 | cell xilinx.com:ip:proc_sys_reset rst_0 {} { 64 | ext_reset_in const_0/dout 65 | dcm_locked pll_0/locked 66 | slowest_sync_clk pll_0/clk_out1 67 | } 68 | 69 | # ADC 70 | 71 | # Create util_ds_buf 72 | cell xilinx.com:ip:util_ds_buf buf_0 { 73 | C_SIZE 7 74 | C_BUF_TYPE IBUFDS 75 | } { 76 | IBUF_DS_P adc_dat_p_i 77 | IBUF_DS_N adc_dat_n_i 78 | } 79 | 80 | # Create axis_adc_ddr 81 | cell pavel-demin:user:axis_adc_ddr adc_0 { 82 | ADC_DATA_WIDTH 7 83 | } { 84 | aclk pll_0/clk_out1 85 | adc_data buf_0/IBUF_OUT 86 | } 87 | 88 | # RX 0 89 | 90 | module rx_0 { 91 | source projects/sdr_receiver_77_76/rx.tcl 92 | } { 93 | hub_0/S_AXI ps_0/M_AXI_GP0 94 | } 95 | 96 | # RX 1 97 | 98 | module rx_1 { 99 | source projects/sdr_receiver_77_76/rx.tcl 100 | } { 101 | hub_0/S_AXI ps_0/M_AXI_GP1 102 | } 103 | 104 | -------------------------------------------------------------------------------- /projects/sdr_receiver_77_76/client/convert.py: -------------------------------------------------------------------------------- 1 | from argparse import ArgumentParser 2 | import numpy as np 3 | import scipy.io.wavfile as wf 4 | 5 | rates = [48000, 96000, 192000, 384000] 6 | 7 | parser = ArgumentParser() 8 | 9 | parser.add_argument("--file", help="input file", required=True) 10 | parser.add_argument("--rate", help="sample rate %s" % rates, type=int, required=True) 11 | 12 | args = parser.parse_args() 13 | 14 | if args.rate not in rates: 15 | parser.print_help() 16 | exit(1) 17 | 18 | data = np.fromfile(args.file, dtype=np.complex64) 19 | 20 | for i in range(8): 21 | channel = data[i::8].view("(2,)float32") 22 | wf.write("%d.wav" % i, args.rate, channel) 23 | -------------------------------------------------------------------------------- /projects/sdr_receiver_77_76/client/record.py: -------------------------------------------------------------------------------- 1 | from argparse import ArgumentParser 2 | from socket import socket, AF_INET, SOCK_STREAM 3 | from signal import signal, SIGINT 4 | from struct import pack 5 | from sys import exit 6 | 7 | rates = {48000: 0, 96000: 1, 192000: 2, 384000: 3} 8 | 9 | parser = ArgumentParser() 10 | 11 | parser.add_argument("--addr", help="IP address of the QMTECH XC7Z020 board", required=True) 12 | parser.add_argument("--freq", help="8 center frequencies in Hz [0 - 490000000]", nargs=8, type=int, required=True) 13 | parser.add_argument("--rate", help="sample rate %s" % list(rates.keys()), type=int, required=True) 14 | parser.add_argument("--corr", help="frequency correction in ppm [-100 - 100]", type=float, required=True) 15 | parser.add_argument("--file", help="output file", required=True) 16 | 17 | args = parser.parse_args() 18 | 19 | for f in args.freq: 20 | if f < 0 or f > 490000000: 21 | parser.print_help() 22 | exit(1) 23 | 24 | if args.rate not in rates: 25 | parser.print_help() 26 | exit(1) 27 | 28 | if args.corr < -100 or args.corr > 100: 29 | parser.print_help() 30 | exit(1) 31 | 32 | sock = socket(AF_INET, SOCK_STREAM) 33 | sock.settimeout(5) 34 | try: 35 | sock.connect((args.addr, 1001)) 36 | except: 37 | print("error: could not connect to", args.addr) 38 | exit(1) 39 | sock.settimeout(None) 40 | 41 | sock.send(pack("<10I", 0, rates[args.rate], *[int((1.0 + 1e-6 * args.corr) * f) for f in args.freq])) 42 | 43 | interrupted = False 44 | 45 | 46 | def signal_handler(signal, frame): 47 | global interrupted 48 | interrupted = True 49 | 50 | 51 | signal(SIGINT, signal_handler) 52 | 53 | try: 54 | f = open(args.file, "wb") 55 | except: 56 | print("error: could not open", args.file) 57 | exit(1) 58 | 59 | data = sock.recv(4096) 60 | while data and not interrupted: 61 | f.write(data) 62 | data = sock.recv(4096) 63 | -------------------------------------------------------------------------------- /projects/sdr_receiver_77_76/filters/rx_fir_0.r: -------------------------------------------------------------------------------- 1 | library(signal) 2 | 3 | # CIC filter parameters 4 | R <- 81 # Decimation factor 5 | M <- 1 # Differential delay 6 | N <- 6 # Number of stages 7 | 8 | Fc <- 0.097 # cutoff frequency 9 | htbw <- 0.005 # half transition bandwidth 10 | 11 | # fir2 parameters 12 | k <- kaiserord(c(Fc-htbw, Fc+htbw), c(1, 0), 1/(2^16), 1) 13 | L <- k$n # Filter order 14 | Beta <- k$beta # Kaiser window parameter 15 | 16 | # FIR filter design using fir2 17 | s <- 0.001 # Step size 18 | fp <- seq(0.0, Fc-htbw, by=s) # Pass band frequency samples 19 | fs <- seq(Fc+htbw, 0.5, by=s) # Stop band frequency samples 20 | f <- c(fp, fs)*2 # Normalized frequency samples; 0<=f<=1 21 | 22 | Mp <- matrix(1, 1, length(fp)) # Pass band response; Mp[1]=1 23 | Mp[-1] <- abs(M*R*sin(pi*fp[-1]*2/R)/sin(pi*M*fp[-1]*2))^N 24 | Mf <- c(Mp, matrix(0, 1, length(fs))) 25 | 26 | h <- fir2(L, f, Mf, window=kaiser(L+1, Beta)) 27 | 28 | h <- h / sum(h) 29 | 30 | # Print filter coefficients 31 | paste(sprintf("%.10e", h), collapse=", ") 32 | 33 | fh <- freqz(h) 34 | 35 | op <- par(mfrow = c(2, 1)) 36 | 37 | plot(f, 20*log10(Mf), type = "b", ylab = "dB", xlab = "Frequency", xlim = c(0.20, 0.22), ylim = c(-125, 5)) 38 | lines(fh$f / pi, 20*log10(abs(fh$h)), col = "blue") 39 | grid() 40 | 41 | plot(f, 20*log10(Mf), type = "b", ylab = "dB", xlab = "Frequency", xlim = c(0.18, 0.20), ylim = c(-5, 5)) 42 | lines(fh$f / pi, 20*log10(abs(fh$h)), col = "blue") 43 | grid() 44 | 45 | par(op) 46 | -------------------------------------------------------------------------------- /projects/sdr_receiver_77_76/ports.xdc: -------------------------------------------------------------------------------- 1 | # clock 2 | 3 | set_property IOSTANDARD LVDS_25 [get_ports adc_clk_p_i] 4 | set_property IOSTANDARD LVDS_25 [get_ports adc_clk_n_i] 5 | 6 | set_property DIFF_TERM TRUE [get_ports adc_clk_p_i] 7 | set_property DIFF_TERM TRUE [get_ports adc_clk_n_i] 8 | 9 | set_property PACKAGE_PIN Y19 [get_ports adc_clk_p_i] 10 | set_property PACKAGE_PIN AA19 [get_ports adc_clk_n_i] 11 | 12 | # overrange 13 | 14 | set_property IOSTANDARD LVDS_25 [get_ports {adc_ovr_p_i}] 15 | set_property IOSTANDARD LVDS_25 [get_ports {adc_ovr_n_i}] 16 | 17 | set_property DIFF_TERM TRUE [get_ports {adc_ovr_p_i]}] 18 | set_property DIFF_TERM TRUE [get_ports {adc_ovr_n_i}] 19 | 20 | set_property PACKAGE_PIN U17 [get_ports {adc_ovr_p_i}] 21 | set_property PACKAGE_PIN V17 [get_ports {adc_ovr_n_i}] 22 | 23 | # data 24 | 25 | set_property IOSTANDARD LVDS_25 [get_ports {adc_dat_p_i[*]}] 26 | set_property IOSTANDARD LVDS_25 [get_ports {adc_dat_n_i[*]}] 27 | 28 | set_property DIFF_TERM TRUE [get_ports {adc_dat_p_i[*]}] 29 | set_property DIFF_TERM TRUE [get_ports {adc_dat_n_i[*]}] 30 | 31 | set_property PACKAGE_PIN AA17 [get_ports {adc_dat_p_i[0]}] 32 | set_property PACKAGE_PIN AB17 [get_ports {adc_dat_n_i[0]}] 33 | 34 | set_property PACKAGE_PIN AA16 [get_ports {adc_dat_p_i[1]}] 35 | set_property PACKAGE_PIN AB16 [get_ports {adc_dat_n_i[1]}] 36 | 37 | set_property PACKAGE_PIN AB14 [get_ports {adc_dat_p_i[2]}] 38 | set_property PACKAGE_PIN AB15 [get_ports {adc_dat_n_i[2]}] 39 | 40 | set_property PACKAGE_PIN Y18 [get_ports {adc_dat_p_i[3]}] 41 | set_property PACKAGE_PIN AA18 [get_ports {adc_dat_n_i[3]}] 42 | 43 | set_property PACKAGE_PIN W17 [get_ports {adc_dat_p_i[4]}] 44 | set_property PACKAGE_PIN W18 [get_ports {adc_dat_n_i[4]}] 45 | 46 | set_property PACKAGE_PIN W16 [get_ports {adc_dat_p_i[5]}] 47 | set_property PACKAGE_PIN Y16 [get_ports {adc_dat_n_i[5]}] 48 | 49 | set_property PACKAGE_PIN Y14 [get_ports {adc_dat_p_i[6]}] 50 | set_property PACKAGE_PIN AA14 [get_ports {adc_dat_n_i[6]}] 51 | 52 | # SPI 53 | 54 | set_property IOSTANDARD LVCMOS25 [get_ports adc_spi_*] 55 | 56 | set_property PACKAGE_PIN AA13 [get_ports adc_spi_sclk] 57 | set_property PACKAGE_PIN Y13 [get_ports adc_spi_sdio] 58 | set_property PACKAGE_PIN U15 [get_ports adc_spi_cs] 59 | 60 | # output enable 61 | 62 | set_property IOSTANDARD LVCMOS25 [get_ports adc_oe] 63 | 64 | set_property PACKAGE_PIN Y20 [get_ports adc_oe] 65 | -------------------------------------------------------------------------------- /projects/sdr_receiver_77_76/rx.tcl: -------------------------------------------------------------------------------- 1 | # Create axi_hub 2 | cell pavel-demin:user:axi_hub hub_0 { 3 | CFG_DATA_WIDTH 288 4 | STS_DATA_WIDTH 32 5 | } { 6 | aclk /pll_0/clk_out1 7 | aresetn /rst_0/peripheral_aresetn 8 | } 9 | 10 | # Create port_slicer 11 | cell pavel-demin:user:port_slicer slice_0 { 12 | DIN_WIDTH 288 DIN_FROM 0 DIN_TO 0 13 | } { 14 | din hub_0/cfg_data 15 | } 16 | 17 | # Create port_slicer 18 | cell pavel-demin:user:port_slicer slice_1 { 19 | DIN_WIDTH 288 DIN_FROM 31 DIN_TO 16 20 | } { 21 | din hub_0/cfg_data 22 | } 23 | 24 | for {set i 0} {$i <= 7} {incr i} { 25 | 26 | # Create port_slicer 27 | cell pavel-demin:user:port_slicer slice_[expr $i + 2] { 28 | DIN_WIDTH 288 DIN_FROM [expr 32 * $i + 63] DIN_TO [expr 32 * $i + 32] 29 | } { 30 | din hub_0/cfg_data 31 | } 32 | 33 | # Create dds 34 | cell pavel-demin:user:dds dds_$i { 35 | NEGATIVE_SINE TRUE 36 | } { 37 | pinc slice_[expr $i + 2]/dout 38 | aclk /pll_0/clk_out1 39 | aresetn /rst_0/peripheral_aresetn 40 | } 41 | 42 | } 43 | 44 | # Create xlconstant 45 | cell xilinx.com:ip:xlconstant const_0 46 | 47 | for {set i 0} {$i <= 15} {incr i} { 48 | 49 | # Create port_slicer 50 | cell pavel-demin:user:port_slicer dds_slice_$i { 51 | DIN_WIDTH 48 DIN_FROM [expr 24 * ($i % 2) + 23] DIN_TO [expr 24 * ($i % 2)] 52 | } { 53 | din dds_[expr $i / 2]/dout 54 | } 55 | 56 | # Create dsp48 57 | cell pavel-demin:user:dsp48 mult_$i { 58 | A_WIDTH 24 59 | B_WIDTH 14 60 | P_WIDTH 24 61 | } { 62 | A dds_slice_$i/dout 63 | B /adc_0/m_axis_tdata 64 | CLK /pll_0/clk_out1 65 | } 66 | 67 | # Create axis_variable 68 | cell pavel-demin:user:axis_variable rate_$i { 69 | AXIS_TDATA_WIDTH 16 70 | } { 71 | cfg_data slice_1/dout 72 | aclk /pll_0/clk_out1 73 | aresetn /rst_0/peripheral_aresetn 74 | } 75 | 76 | # Create cic_compiler 77 | cell xilinx.com:ip:cic_compiler cic_$i { 78 | INPUT_DATA_WIDTH.VALUE_SRC USER 79 | FILTER_TYPE Decimation 80 | NUMBER_OF_STAGES 6 81 | SAMPLE_RATE_CHANGES Programmable 82 | MINIMUM_RATE 81 83 | MAXIMUM_RATE 1296 84 | FIXED_OR_INITIAL_RATE 648 85 | INPUT_SAMPLE_FREQUENCY 77.76 86 | CLOCK_FREQUENCY 77.76 87 | INPUT_DATA_WIDTH 24 88 | QUANTIZATION Truncation 89 | OUTPUT_DATA_WIDTH 32 90 | USE_XTREME_DSP_SLICE false 91 | HAS_ARESETN true 92 | } { 93 | s_axis_data_tdata mult_$i/P 94 | s_axis_data_tvalid const_0/dout 95 | S_AXIS_CONFIG rate_$i/M_AXIS 96 | aclk /pll_0/clk_out1 97 | aresetn /rst_0/peripheral_aresetn 98 | } 99 | 100 | } 101 | 102 | # Create axis_combiner 103 | cell xilinx.com:ip:axis_combiner comb_0 { 104 | TDATA_NUM_BYTES.VALUE_SRC USER 105 | TDATA_NUM_BYTES 4 106 | NUM_SI 16 107 | } { 108 | S00_AXIS cic_0/M_AXIS_DATA 109 | S01_AXIS cic_1/M_AXIS_DATA 110 | S02_AXIS cic_2/M_AXIS_DATA 111 | S03_AXIS cic_3/M_AXIS_DATA 112 | S04_AXIS cic_4/M_AXIS_DATA 113 | S05_AXIS cic_5/M_AXIS_DATA 114 | S06_AXIS cic_6/M_AXIS_DATA 115 | S07_AXIS cic_7/M_AXIS_DATA 116 | S08_AXIS cic_8/M_AXIS_DATA 117 | S09_AXIS cic_9/M_AXIS_DATA 118 | S10_AXIS cic_10/M_AXIS_DATA 119 | S11_AXIS cic_11/M_AXIS_DATA 120 | S12_AXIS cic_12/M_AXIS_DATA 121 | S13_AXIS cic_13/M_AXIS_DATA 122 | S14_AXIS cic_14/M_AXIS_DATA 123 | S15_AXIS cic_15/M_AXIS_DATA 124 | aclk /pll_0/clk_out1 125 | aresetn /rst_0/peripheral_aresetn 126 | } 127 | 128 | # Create axis_dwidth_converter 129 | cell xilinx.com:ip:axis_dwidth_converter conv_0 { 130 | S_TDATA_NUM_BYTES.VALUE_SRC USER 131 | S_TDATA_NUM_BYTES 64 132 | M_TDATA_NUM_BYTES 4 133 | } { 134 | S_AXIS comb_0/M_AXIS 135 | aclk /pll_0/clk_out1 136 | aresetn /rst_0/peripheral_aresetn 137 | } 138 | 139 | # Create fir_compiler 140 | cell xilinx.com:ip:fir_compiler fir_0 { 141 | DATA_WIDTH.VALUE_SRC USER 142 | DATA_WIDTH 32 143 | COEFFICIENTVECTOR {8.6416634255e-09, 1.9787522479e-08, 2.5521203789e-08, 2.3638357357e-08, 1.4790149581e-08, 1.9719648224e-09, -1.1032338549e-08, -2.1355862813e-08, -2.7914377238e-08, -3.0931374243e-08, -3.0470610650e-08, -2.5069790691e-08, -1.1732378562e-08, 1.2106227398e-08, 4.5256582454e-08, 7.9934220054e-08, 1.0168998967e-07, 9.3590856156e-08, 4.4144966037e-08, -4.3922671719e-08, -1.4852200249e-07, -2.3083384546e-07, -2.4726320140e-07, -1.6800994993e-07, 4.5912166862e-09, 2.2678122505e-07, 4.2020376983e-07, 4.9631671575e-07, 3.9210438758e-07, 1.0401511886e-07, -2.9540946982e-07, -6.6974601177e-07, -8.6118574256e-07, -7.5179544934e-07, -3.2135153633e-07, 3.2363684057e-07, 9.6792135313e-07, 1.3542946906e-06, 1.2805958992e-06, 6.9217855668e-07, -2.6932495334e-07, -1.2887872597e-06, -1.9748299670e-06, -2.0041416687e-06, -1.2616531622e-06, 8.1045970371e-08, 1.5902969896e-06, 2.7034505382e-06, 2.9326808171e-06, 2.0677893719e-06, 2.9671782990e-07, -1.8153799542e-06, -3.4986916001e-06, -4.0537458905e-06, -3.1326541017e-06, -9.1621545700e-07, 1.8951789437e-06, 4.2945533398e-06, 5.3243068872e-06, 4.4510966031e-06, 1.8150145648e-06, -1.7570418369e-06, -5.0023771924e-06, -6.6656492920e-06, -5.9799678791e-06, -3.0028313096e-06, 1.3358282157e-06, 5.5163795673e-06, 7.9608658936e-06, 7.6277789306e-06, 4.4461154951e-06, -5.8984164425e-07, -5.7251392145e-06, -9.0581314802e-06, -9.2484912704e-06, -6.0541412073e-06, -4.8199458599e-07, 5.5262501707e-06, 9.7774958316e-06, 1.0637326831e-05, 7.6640662304e-06, 1.8181526672e-06, -4.8491693605e-06, -9.9277893079e-06, -1.1536455496e-05, -9.0334291964e-06, -3.2759450427e-06, 3.6790473433e-06, 9.3279777293e-06, 1.1646532779e-05, 9.8373152541e-06, 4.6141546613e-06, -2.0841283602e-06, -7.8366295707e-06, -1.0649202562e-05, -9.6766597871e-06, -5.4841491162e-06, 2.3935387332e-07, 5.3827746410e-06, 8.2348658276e-06, 8.0928618642e-06, 5.4248153015e-06, 1.5482305844e-06, -2.0058806216e-06, -4.1464815041e-06, -4.6028386086e-06, -3.8783946363e-06, -2.8311981110e-06, -2.1143317814e-06, -1.7787125841e-06, -1.2613202098e-06, 2.1404336279e-07, 3.0196794545e-06, 6.6285446608e-06, 9.5597769186e-06, 9.8970858249e-06, 6.2280706793e-06, -1.3999300558e-06, -1.1004079038e-05, -1.9029472380e-05, -2.1573387839e-05, -1.6082598930e-05, -2.8350137599e-06, 1.4518712779e-05, 2.9788917181e-05, 3.6356227405e-05, 2.9875585364e-05, 1.0516808093e-05, -1.6294026764e-05, -4.1195968302e-05, -5.4056581743e-05, -4.7949938310e-05, -2.2431204012e-05, 1.5335680685e-05, 5.2357533492e-05, 7.4172234233e-05, 7.0371097114e-05, 3.9214909546e-05, -1.0613325355e-05, -6.2159982313e-05, -9.5857297703e-05, -9.6843895010e-05, -6.1246116434e-05, 1.1596087820e-06, 6.9321939920e-05, 1.1790595196e-04, 1.2662552441e-04, 8.8507777460e-05, 1.3781498407e-05, -7.2510875641e-05, -1.3880280100e-04, -1.5849588836e-04, -1.2049046521e-04, -3.4625933141e-05, 7.0455194291e-05, 1.5677318467e-04, 1.9071963279e-04, 1.5606818885e-04, 6.1270662098e-05, -6.2125794971e-05, -1.6991125582e-04, -2.2107906371e-04, -1.9342374961e-04, -9.2934134104e-05, 4.6928443366e-05, 1.7633944720e-04, 2.4694245575e-04, 2.2999478843e-04, 1.2798765460e-04, -2.4941664121e-05, -1.7444600564e-04, -2.6542975109e-04, -2.6251833556e-04, -1.6386926905e-04, -2.9017345509e-06, 1.6309186966e-04, 2.7356222115e-04, 2.8705580527e-04, 1.9695561615e-04, 3.4555670489e-05, -1.4193230722e-04, -2.6855336886e-04, -2.9916488047e-04, -2.2256165500e-04, -6.6689937029e-05, 1.1170007522e-04, 2.4810655924e-04, 2.9410546207e-04, 2.3497584277e-04, 9.4530201531e-05, -7.4520222202e-05, -2.1079107961e-04, -2.6716055532e-04, -2.2762585917e-04, -1.1182026094e-04, 3.4129098118e-05, 1.5635447302e-04, 2.1391598199e-04, 1.9320383872e-04, 1.1071751871e-04, 3.7908910630e-06, -8.6209631786e-05, -1.3076687946e-04, -1.2404753376e-04, -8.1941203532e-05, -3.1493984650e-05, 3.7618482978e-06, 1.5327191471e-05, 1.2475457050e-05, 1.4900403573e-05, 3.9029838255e-05, 8.5212216095e-05, 1.3306952296e-04, 1.4875133947e-04, 1.0203253711e-04, -1.4244728473e-05, -1.7230750533e-04, -3.1296479335e-04, -3.6604545253e-04, -2.8133052368e-04, -5.7330371892e-05, 2.4606492228e-04, 5.2013232626e-04, 6.4430392795e-04, 5.3576204832e-04, 1.9220436978e-04, -2.9193714506e-04, -7.4731044440e-04, -9.8656619314e-04, -8.7815597539e-04, -4.0893233116e-04, 2.9200492514e-04, 9.8371803137e-04, 1.3934897225e-03, 1.3210162624e-03, 7.2799464557e-04, -2.2481558671e-04, -1.2147116076e-03, -1.8630079096e-03, -1.8763709734e-03, -1.1719555546e-03, 6.4921935546e-05, 1.4211556881e-03, 2.3897382217e-03, 2.5554049165e-03, 1.7653955158e-03, 2.1726375791e-04, -1.5792901757e-03, -2.9651397494e-03, -3.3691024975e-03, -2.5360356113e-03, -6.5682663411e-04, 1.6595757982e-03, 3.5770214428e-03, 4.3286963968e-03, 3.5160483017e-03, 1.2960357442e-03, -1.6254062809e-03, -4.2094376163e-03, -5.4471917717e-03, -4.7450324797e-03, -2.1878913494e-03, 1.4303547141e-03, 4.8420974952e-03, 6.7417004048e-03, 6.2749186441e-03, 3.4019773004e-03, -1.0139113090e-03, -5.4502911147e-03, -8.2390953251e-03, -8.1808578202e-03, -5.0376756147e-03, 2.9071387529e-04, 6.0016792136e-03, 9.9836955649e-03, 1.0579354406e-02, 7.2475257605e-03, 8.6880057823e-04, -6.4514589167e-03, -1.2054494720e-02, -1.3667770498e-02, -1.0289159644e-02, -2.6835541906e-03, 6.7274828446e-03, 1.4599435427e-02, 1.7811581265e-02, 1.4646249040e-02, 5.5728291554e-03, -6.6881265746e-03, -1.7916290000e-02, -2.3770141281e-02, -2.1362115622e-02, -1.0487921502e-02, 5.9634682621e-03, 2.2652378162e-02, 3.3374547837e-02, 3.3147252075e-02, 2.0139686562e-02, -3.2170050718e-03, -3.0392681085e-02, -5.2269158542e-02, -5.9644704750e-02, -4.6033325214e-02, -9.9174346067e-03, 4.4272248035e-02, 1.0682708940e-01, 1.6497706887e-01, 2.0608084740e-01, 2.2090784056e-01, 2.0608084740e-01, 1.6497706887e-01, 1.0682708940e-01, 4.4272248035e-02, -9.9174346067e-03, -4.6033325214e-02, -5.9644704750e-02, -5.2269158542e-02, -3.0392681085e-02, -3.2170050718e-03, 2.0139686562e-02, 3.3147252075e-02, 3.3374547837e-02, 2.2652378162e-02, 5.9634682621e-03, -1.0487921502e-02, -2.1362115622e-02, -2.3770141281e-02, -1.7916290000e-02, -6.6881265746e-03, 5.5728291554e-03, 1.4646249040e-02, 1.7811581265e-02, 1.4599435427e-02, 6.7274828446e-03, -2.6835541906e-03, -1.0289159644e-02, -1.3667770498e-02, -1.2054494720e-02, -6.4514589167e-03, 8.6880057823e-04, 7.2475257605e-03, 1.0579354406e-02, 9.9836955649e-03, 6.0016792136e-03, 2.9071387529e-04, -5.0376756147e-03, -8.1808578202e-03, -8.2390953251e-03, -5.4502911147e-03, -1.0139113090e-03, 3.4019773004e-03, 6.2749186441e-03, 6.7417004048e-03, 4.8420974952e-03, 1.4303547141e-03, -2.1878913494e-03, -4.7450324797e-03, -5.4471917717e-03, -4.2094376163e-03, -1.6254062809e-03, 1.2960357442e-03, 3.5160483017e-03, 4.3286963968e-03, 3.5770214428e-03, 1.6595757982e-03, -6.5682663411e-04, -2.5360356113e-03, -3.3691024975e-03, -2.9651397494e-03, -1.5792901757e-03, 2.1726375791e-04, 1.7653955158e-03, 2.5554049165e-03, 2.3897382217e-03, 1.4211556881e-03, 6.4921935546e-05, -1.1719555546e-03, -1.8763709734e-03, -1.8630079096e-03, -1.2147116076e-03, -2.2481558671e-04, 7.2799464557e-04, 1.3210162624e-03, 1.3934897225e-03, 9.8371803137e-04, 2.9200492514e-04, -4.0893233116e-04, -8.7815597539e-04, -9.8656619314e-04, -7.4731044440e-04, -2.9193714506e-04, 1.9220436978e-04, 5.3576204832e-04, 6.4430392795e-04, 5.2013232626e-04, 2.4606492228e-04, -5.7330371892e-05, -2.8133052368e-04, -3.6604545253e-04, -3.1296479335e-04, -1.7230750533e-04, -1.4244728473e-05, 1.0203253711e-04, 1.4875133947e-04, 1.3306952296e-04, 8.5212216095e-05, 3.9029838255e-05, 1.4900403573e-05, 1.2475457050e-05, 1.5327191471e-05, 3.7618482978e-06, -3.1493984650e-05, -8.1941203532e-05, -1.2404753376e-04, -1.3076687946e-04, -8.6209631786e-05, 3.7908910630e-06, 1.1071751871e-04, 1.9320383872e-04, 2.1391598199e-04, 1.5635447302e-04, 3.4129098118e-05, -1.1182026094e-04, -2.2762585917e-04, -2.6716055532e-04, -2.1079107961e-04, -7.4520222202e-05, 9.4530201531e-05, 2.3497584277e-04, 2.9410546207e-04, 2.4810655924e-04, 1.1170007522e-04, -6.6689937029e-05, -2.2256165500e-04, -2.9916488047e-04, -2.6855336886e-04, -1.4193230722e-04, 3.4555670489e-05, 1.9695561615e-04, 2.8705580527e-04, 2.7356222115e-04, 1.6309186966e-04, -2.9017345509e-06, -1.6386926905e-04, -2.6251833556e-04, -2.6542975109e-04, -1.7444600564e-04, -2.4941664121e-05, 1.2798765460e-04, 2.2999478843e-04, 2.4694245575e-04, 1.7633944720e-04, 4.6928443366e-05, -9.2934134104e-05, -1.9342374961e-04, -2.2107906371e-04, -1.6991125582e-04, -6.2125794971e-05, 6.1270662098e-05, 1.5606818885e-04, 1.9071963279e-04, 1.5677318467e-04, 7.0455194291e-05, -3.4625933141e-05, -1.2049046521e-04, -1.5849588836e-04, -1.3880280100e-04, -7.2510875641e-05, 1.3781498407e-05, 8.8507777460e-05, 1.2662552441e-04, 1.1790595196e-04, 6.9321939920e-05, 1.1596087820e-06, -6.1246116434e-05, -9.6843895010e-05, -9.5857297703e-05, -6.2159982313e-05, -1.0613325355e-05, 3.9214909546e-05, 7.0371097114e-05, 7.4172234233e-05, 5.2357533492e-05, 1.5335680685e-05, -2.2431204012e-05, -4.7949938310e-05, -5.4056581743e-05, -4.1195968302e-05, -1.6294026764e-05, 1.0516808093e-05, 2.9875585364e-05, 3.6356227405e-05, 2.9788917181e-05, 1.4518712779e-05, -2.8350137599e-06, -1.6082598930e-05, -2.1573387839e-05, -1.9029472380e-05, -1.1004079038e-05, -1.3999300558e-06, 6.2280706793e-06, 9.8970858249e-06, 9.5597769186e-06, 6.6285446608e-06, 3.0196794545e-06, 2.1404336279e-07, -1.2613202098e-06, -1.7787125841e-06, -2.1143317814e-06, -2.8311981110e-06, -3.8783946363e-06, -4.6028386086e-06, -4.1464815041e-06, -2.0058806216e-06, 1.5482305844e-06, 5.4248153015e-06, 8.0928618642e-06, 8.2348658276e-06, 5.3827746410e-06, 2.3935387332e-07, -5.4841491162e-06, -9.6766597871e-06, -1.0649202562e-05, -7.8366295707e-06, -2.0841283602e-06, 4.6141546613e-06, 9.8373152541e-06, 1.1646532779e-05, 9.3279777293e-06, 3.6790473433e-06, -3.2759450427e-06, -9.0334291964e-06, -1.1536455496e-05, -9.9277893079e-06, -4.8491693605e-06, 1.8181526672e-06, 7.6640662304e-06, 1.0637326831e-05, 9.7774958316e-06, 5.5262501707e-06, -4.8199458599e-07, -6.0541412073e-06, -9.2484912704e-06, -9.0581314802e-06, -5.7251392145e-06, -5.8984164425e-07, 4.4461154951e-06, 7.6277789306e-06, 7.9608658936e-06, 5.5163795673e-06, 1.3358282157e-06, -3.0028313096e-06, -5.9799678791e-06, -6.6656492920e-06, -5.0023771924e-06, -1.7570418369e-06, 1.8150145648e-06, 4.4510966031e-06, 5.3243068872e-06, 4.2945533398e-06, 1.8951789437e-06, -9.1621545700e-07, -3.1326541017e-06, -4.0537458905e-06, -3.4986916001e-06, -1.8153799542e-06, 2.9671782990e-07, 2.0677893719e-06, 2.9326808171e-06, 2.7034505382e-06, 1.5902969896e-06, 8.1045970371e-08, -1.2616531622e-06, -2.0041416687e-06, -1.9748299670e-06, -1.2887872597e-06, -2.6932495334e-07, 6.9217855668e-07, 1.2805958992e-06, 1.3542946906e-06, 9.6792135313e-07, 3.2363684057e-07, -3.2135153633e-07, -7.5179544934e-07, -8.6118574256e-07, -6.6974601177e-07, -2.9540946982e-07, 1.0401511886e-07, 3.9210438758e-07, 4.9631671575e-07, 4.2020376983e-07, 2.2678122505e-07, 4.5912166862e-09, -1.6800994993e-07, -2.4726320140e-07, -2.3083384546e-07, -1.4852200249e-07, -4.3922671719e-08, 4.4144966037e-08, 9.3590856156e-08, 1.0168998967e-07, 7.9934220054e-08, 4.5256582454e-08, 1.2106227398e-08, -1.1732378562e-08, -2.5069790691e-08, -3.0470610650e-08, -3.0931374243e-08, -2.7914377238e-08, -2.1355862813e-08, -1.1032338549e-08, 1.9719648224e-09, 1.4790149581e-08, 2.3638357357e-08, 2.5521203789e-08, 1.9787522478e-08, 8.6416634255e-09} 144 | COEFFICIENT_WIDTH 24 145 | QUANTIZATION Quantize_Only 146 | BESTPRECISION true 147 | FILTER_TYPE Decimation 148 | RATE_CHANGE_TYPE Fixed_Fractional 149 | INTERPOLATION_RATE 2 150 | DECIMATION_RATE 5 151 | NUMBER_CHANNELS 16 152 | NUMBER_PATHS 1 153 | SAMPLE_FREQUENCY 0.96 154 | CLOCK_FREQUENCY 77.76 155 | OUTPUT_ROUNDING_MODE Convergent_Rounding_to_Even 156 | OUTPUT_WIDTH 35 157 | HAS_ARESETN true 158 | } { 159 | S_AXIS_DATA conv_0/M_AXIS 160 | aclk /pll_0/clk_out1 161 | aresetn /rst_0/peripheral_aresetn 162 | } 163 | 164 | # Create axis_subset_converter 165 | cell xilinx.com:ip:axis_subset_converter subset_0 { 166 | S_TDATA_NUM_BYTES.VALUE_SRC USER 167 | M_TDATA_NUM_BYTES.VALUE_SRC USER 168 | S_TDATA_NUM_BYTES 5 169 | M_TDATA_NUM_BYTES 4 170 | TDATA_REMAP {tdata[31:0]} 171 | } { 172 | S_AXIS fir_0/M_AXIS_DATA 173 | aclk /pll_0/clk_out1 174 | aresetn /rst_0/peripheral_aresetn 175 | } 176 | 177 | # Create floating_point 178 | cell xilinx.com:ip:floating_point fp_0 { 179 | OPERATION_TYPE Fixed_to_float 180 | A_PRECISION_TYPE.VALUE_SRC USER 181 | C_A_EXPONENT_WIDTH.VALUE_SRC USER 182 | C_A_FRACTION_WIDTH.VALUE_SRC USER 183 | A_PRECISION_TYPE Custom 184 | C_A_EXPONENT_WIDTH 2 185 | C_A_FRACTION_WIDTH 30 186 | RESULT_PRECISION_TYPE Single 187 | HAS_ARESETN true 188 | } { 189 | S_AXIS_A subset_0/M_AXIS 190 | aclk /pll_0/clk_out1 191 | aresetn /rst_0/peripheral_aresetn 192 | } 193 | 194 | # Create axis_dwidth_converter 195 | cell xilinx.com:ip:axis_dwidth_converter conv_1 { 196 | S_TDATA_NUM_BYTES.VALUE_SRC USER 197 | S_TDATA_NUM_BYTES 4 198 | M_TDATA_NUM_BYTES 64 199 | } { 200 | S_AXIS fp_0/M_AXIS_RESULT 201 | aclk /pll_0/clk_out1 202 | aresetn /rst_0/peripheral_aresetn 203 | } 204 | 205 | # Create axis_fifo 206 | cell pavel-demin:user:axis_fifo fifo_0 { 207 | S_AXIS_TDATA_WIDTH 512 208 | M_AXIS_TDATA_WIDTH 512 209 | WRITE_DEPTH 2048 210 | ALWAYS_READY TRUE 211 | } { 212 | S_AXIS conv_1/M_AXIS 213 | read_count hub_0/sts_data 214 | aclk /pll_0/clk_out1 215 | aresetn slice_0/dout 216 | } 217 | 218 | # Create axis_dwidth_converter 219 | cell xilinx.com:ip:axis_dwidth_converter conv_2 { 220 | S_TDATA_NUM_BYTES.VALUE_SRC USER 221 | S_TDATA_NUM_BYTES 64 222 | M_TDATA_NUM_BYTES 4 223 | } { 224 | S_AXIS fifo_0/M_AXIS 225 | M_AXIS hub_0/S00_AXIS 226 | aclk /pll_0/clk_out1 227 | aresetn slice_0/dout 228 | } 229 | -------------------------------------------------------------------------------- /projects/sdr_receiver_77_76/server/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -O3 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -D_GNU_SOURCE 2 | 3 | all: sdr-receiver 4 | 5 | sdr-receiver: sdr-receiver.c 6 | gcc $(CFLAGS) -o $@ $^ -lm 7 | 8 | clean: 9 | rm -f sdr-receiver 10 | -------------------------------------------------------------------------------- /projects/sdr_receiver_77_76/server/sdr-receiver.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define TCP_PORT 1001 16 | 17 | struct control 18 | { 19 | int32_t inps, rate; 20 | int32_t freq[8]; 21 | }; 22 | 23 | const int rates[4] = {648, 324, 162, 81}; 24 | 25 | int interrupted = 0; 26 | 27 | void signal_handler(int sig) 28 | { 29 | interrupted = 1; 30 | } 31 | 32 | int main(int argc, char *argv[]) 33 | { 34 | int fd, i; 35 | int sock_server, sock_client; 36 | volatile void *cfg, *sts, *fifo; 37 | volatile uint8_t *rx_rst; 38 | volatile uint16_t *rx_rate, *rx_cntr; 39 | volatile uint32_t *rx_freq; 40 | struct sockaddr_in addr; 41 | struct control ctrl; 42 | uint32_t size, n; 43 | double integral; 44 | void *buffer; 45 | int yes = 1; 46 | 47 | if(argc != 2) 48 | { 49 | fprintf(stderr, "Usage: sdr-receiver interface\n"); 50 | return EXIT_FAILURE; 51 | } 52 | 53 | if((buffer = malloc(65536)) == NULL) 54 | { 55 | perror("malloc"); 56 | return EXIT_FAILURE; 57 | } 58 | 59 | if((fd = open("/dev/mem", O_RDWR)) < 0) 60 | { 61 | perror("open"); 62 | return EXIT_FAILURE; 63 | } 64 | 65 | if(strcmp(argv[1], "eth0") == 0) 66 | { 67 | cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x40000000); 68 | sts = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x41000000); 69 | fifo = mmap(NULL, 32*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x42000000); 70 | } 71 | else 72 | { 73 | cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x80000000); 74 | sts = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x81000000); 75 | fifo = mmap(NULL, 32*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x82000000); 76 | } 77 | 78 | rx_rst = (uint8_t *)(cfg + 0); 79 | rx_rate = (uint16_t *)(cfg + 2); 80 | rx_freq = (uint32_t *)(cfg + 4); 81 | 82 | rx_cntr = (uint16_t *)(sts + 0); 83 | 84 | if((sock_server = socket(AF_INET, SOCK_STREAM, 0)) < 0) 85 | { 86 | perror("socket"); 87 | return EXIT_FAILURE; 88 | } 89 | 90 | setsockopt(sock_server, SOL_SOCKET, SO_REUSEADDR, (void *)&yes , sizeof(yes)); 91 | 92 | if(setsockopt(sock_server, SOL_SOCKET, SO_BINDTODEVICE, argv[1], strlen(argv[1]) + 1) < 0) 93 | { 94 | perror("SO_BINDTODEVICE"); 95 | return EXIT_FAILURE; 96 | } 97 | 98 | /* setup listening address */ 99 | memset(&addr, 0, sizeof(addr)); 100 | addr.sin_family = AF_INET; 101 | addr.sin_addr.s_addr = htonl(INADDR_ANY); 102 | addr.sin_port = htons(TCP_PORT); 103 | 104 | if(bind(sock_server, (struct sockaddr *)&addr, sizeof(addr)) < 0) 105 | { 106 | perror("bind"); 107 | return EXIT_FAILURE; 108 | } 109 | 110 | listen(sock_server, 1024); 111 | 112 | while(!interrupted) 113 | { 114 | *rx_rst &= ~1; 115 | *rx_rate = 648; 116 | for(i = 0; i < 8; ++i) 117 | { 118 | rx_freq[i] = (uint32_t)floor(1000000 / 77.76e6 * 0xffffffff + 0.5); 119 | } 120 | 121 | if((sock_client = accept(sock_server, NULL, NULL)) < 0) 122 | { 123 | perror("accept"); 124 | return EXIT_FAILURE; 125 | } 126 | 127 | signal(SIGINT, signal_handler); 128 | 129 | *rx_rst |= 1; 130 | 131 | while(!interrupted) 132 | { 133 | if(ioctl(sock_client, FIONREAD, &size) < 0) break; 134 | 135 | if(size >= sizeof(struct control)) 136 | { 137 | if(recv(sock_client, (char *)&ctrl, sizeof(struct control), MSG_WAITALL) < 0) break; 138 | 139 | /* set rx sample rate */ 140 | *rx_rate = rates[ctrl.rate & 3]; 141 | 142 | /* set rx phase increments */ 143 | for(i = 0; i < 8; ++i) 144 | { 145 | rx_freq[i] = (uint32_t)floor(modf(ctrl.freq[i] / 77.76e6, &integral) * 0xffffffff + 0.5); 146 | } 147 | } 148 | 149 | if(*rx_cntr >= 2048) 150 | { 151 | *rx_rst &= ~1; 152 | *rx_rst |= 1; 153 | } 154 | 155 | if(*rx_cntr >= 1024) 156 | { 157 | memcpy(buffer, fifo, 65536); 158 | if(send(sock_client, buffer, 65536, MSG_NOSIGNAL) < 0) break; 159 | } 160 | else 161 | { 162 | usleep(500); 163 | } 164 | } 165 | 166 | signal(SIGINT, SIG_DFL); 167 | close(sock_client); 168 | } 169 | 170 | *rx_rst &= ~1; 171 | 172 | close(sock_server); 173 | 174 | return EXIT_SUCCESS; 175 | } 176 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/app/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -O3 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -ffast-math -fsingle-precision-constant -mvectorize-with-neon-quad 2 | 3 | all: write-c2-files upload-to-pskreporter 4 | 5 | write-c2-files: write-c2-files.c 6 | gcc $(CFLAGS) -o $@ $^ -lm -lconfig 7 | 8 | upload-to-pskreporter: upload-to-pskreporter.c 9 | gcc $(CFLAGS) -D_GNU_SOURCE -o $@ $^ 10 | 11 | clean: 12 | rm -rf write-c2-files upload-to-pskreporter 13 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/app/decode-ft8.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | JOBS=4 4 | NICE=10 5 | 6 | DIR=`readlink -f $0` 7 | DIR=`dirname $DIR` 8 | 9 | RECORDER=$DIR/write-c2-files 10 | CONFIG=write-c2-files.cfg 11 | 12 | DECODER=/media/mmcblk0p1/apps/ft8d/ft8d 13 | ALLMEPT=ALL_FT8.TXT 14 | 15 | SLEEP=/media/mmcblk0p1/apps/common_tools/sleep-to-59 16 | 17 | date 18 | 19 | test $DIR/$CONFIG -ot $CONFIG || cp $DIR/$CONFIG $CONFIG 20 | 21 | echo "Sleeping ..." 22 | 23 | $SLEEP 24 | 25 | sleep 1 26 | 27 | date 28 | TIMESTAMP=`date --utc +'%y%m%d_%H%M'` 29 | 30 | echo "Recording ..." 31 | 32 | killall -q $RECORDER 33 | $RECORDER $CONFIG 34 | 35 | echo "Decoding ..." 36 | 37 | for file in ft8_*_$TIMESTAMP.c2 38 | do 39 | while [ `pgrep $DECODER | wc -l` -ge $JOBS ] 40 | do 41 | sleep 1 42 | done 43 | nice -n $NICE $DECODER $file & 44 | done > decodes_$TIMESTAMP.txt 45 | 46 | wait 47 | 48 | rm -f ft8_*_$TIMESTAMP.c2 49 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/app/ft8.cron: -------------------------------------------------------------------------------- 1 | * * * * * cd /dev/shm && /media/mmcblk0p1/apps/sdr_receiver_ft8_77_76/decode-ft8.sh >> decode-ft8.log 2>&1 & 2 | */6 * * * * cd /dev/shm && /media/mmcblk0p1/apps/sdr_receiver_ft8_77_76/upload-ft8.sh >> upload-ft8.log 2>&1 & 3 | #* * * * * cd /dev/shm && /media/mmcblk0p1/apps/common_tools/update-corr.sh 77.76 >> update-corr.log 2>&1 & 4 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Multiband FT8 receiver 6 | 7 | 8 | 9 | 10 | 19 |
20 |

Multiband FT8 receiver

21 |

The multiband FT8 receiver is ready.

22 |

More details about this application can be found at this link.

23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/app/start.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | apps_dir=/media/mmcblk0p1/apps 4 | 5 | source $apps_dir/stop.sh 6 | 7 | if grep -q ' ' $apps_dir/sdr_receiver_ft8_77_76/upload-ft8.sh 8 | then 9 | mount -o rw,remount /media/mmcblk0p1 10 | dos2unix $apps_dir/sdr_receiver_ft8_77_76/upload-ft8.sh 11 | mount -o ro,remount /media/mmcblk0p1 12 | fi 13 | 14 | rm -rf /dev/shm/* 15 | 16 | cat $apps_dir/sdr_receiver_ft8_77_76/sdr_receiver_ft8_77_76.bit > /dev/xdevcfg 17 | 18 | $apps_dir/common_tools/setup-adc 19 | $apps_dir/common_tools/enable-adc.sh 20 | 21 | ln -sf $apps_dir/sdr_receiver_ft8_77_76/ft8.cron /etc/cron.d/ft8_77_76 22 | 23 | service dcron restart 24 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/app/stop.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | if test -e /etc/cron.d/ft8_77_76 4 | then 5 | rm -f /etc/cron.d/ft8_77_76 6 | service dcron restart 7 | killall -q decode-ft8.sh sleep-to-59 write-c2-files ft8d 8 | killall -q upload-ft8.sh sleep-rand 9 | killall -q update-corr.sh measure-corr measure-level 10 | fi 11 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/app/upload-ft8.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # CALL and GRID should be specified to enable uploads 4 | CALL= 5 | GRID= 6 | 7 | # optional antenna description 8 | ANTENNA="" 9 | 10 | DIR=`readlink -f $0` 11 | DIR=`dirname $DIR` 12 | 13 | UPLOADER=$DIR/upload-to-pskreporter 14 | 15 | SLEEP=/media/mmcblk0p1/apps/common_tools/sleep-rand 16 | 17 | date 18 | 19 | echo "Sleeping ..." 20 | 21 | $SLEEP 60 22 | 23 | date 24 | TIMESTAMP=`date --utc +'%y%m%d_%H%M'` 25 | 26 | echo "Processing ..." 27 | 28 | REPORT=report_$TIMESTAMP.txt 29 | 30 | for file in `find . -name decodes_\*.txt -mmin +1` 31 | do 32 | cat $file >> $REPORT 33 | rm -f $file 34 | done 35 | 36 | test -f $REPORT || exit 37 | 38 | # sort by highest SNR, then print unique band/call combinations, 39 | # and then sort them by date/time/frequency 40 | sort -nr -k 4,4 $REPORT | awk '!seen[int($6/1e6)"_"$7]{print} {++seen[int($6/1e6)"_"$7]}' | sort -n -k 1,1 -k 2,2 -k 6,6 -o $REPORT 41 | 42 | test -n "$CALL" -a -n "$GRID" || exit 43 | 44 | echo "Uploading ..." 45 | 46 | $UPLOADER $CALL $GRID "$ANTENNA" $REPORT 47 | 48 | rm -f $REPORT 49 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/app/upload-to-pskreporter.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | const char name[] = "report.pskreporter.info"; 12 | const char soft[] = "QMTECH FT8 RX 1.0"; 13 | 14 | int32_t read_int(char **pointer, int32_t *value) 15 | { 16 | char *start = *pointer; 17 | *value = strtol(start, pointer, 10); 18 | return start != *pointer; 19 | } 20 | 21 | int32_t read_dbl(char **pointer, double *value) 22 | { 23 | char *start = *pointer; 24 | *value = strtod(start, pointer); 25 | return start != *pointer; 26 | } 27 | 28 | int32_t read_time(char **pointer, struct tm *value) 29 | { 30 | *pointer = strptime(*pointer, "%y%m%d %H%M%S", value); 31 | return *pointer != NULL; 32 | } 33 | 34 | void copy_char(char **pointer, const char *value) 35 | { 36 | int8_t size = strlen(value); 37 | memcpy(*pointer, &size, 1); 38 | *pointer += 1; 39 | memcpy(*pointer, value, size); 40 | *pointer += size; 41 | } 42 | 43 | void copy_int1(char **pointer, int8_t value) 44 | { 45 | memcpy(*pointer, &value, 1); 46 | *pointer += 1; 47 | } 48 | 49 | void copy_int2(char **pointer, int16_t value) 50 | { 51 | value = htons(value); 52 | memcpy(*pointer, &value, 2); 53 | *pointer += 2; 54 | } 55 | 56 | void copy_int4(char **pointer, int32_t value) 57 | { 58 | value = htonl(value); 59 | memcpy(*pointer, &value, 4); 60 | *pointer += 4; 61 | } 62 | 63 | int main(int argc, char *argv[]) 64 | { 65 | FILE *fp; 66 | int sock; 67 | struct hostent *host; 68 | struct sockaddr_in addr; 69 | struct tm tm; 70 | struct timespec ts; 71 | double sync, dt; 72 | int32_t snr, freq, counter, rc, padding, sequence, size; 73 | char buffer[512], line[64], call[16], grid[8], *src, *dst, *start; 74 | char header[] = 75 | { 76 | 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 77 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 78 | 79 | 0x00, 0x03, 0x00, 0x2C, 0x99, 0x92, 0x00, 0x04, 80 | 0x00, 0x00, 81 | 0x80, 0x02, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F, 82 | 0x80, 0x04, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F, 83 | 0x80, 0x08, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F, 84 | 0x80, 0x09, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F, 85 | 0x00, 0x00, 86 | 87 | 0x00, 0x02, 0x00, 0x3C, 0x99, 0x93, 0x00, 0x07, 88 | 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F, 89 | 0x80, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F, 90 | 0x80, 0x05, 0x00, 0x04, 0x00, 0x00, 0x76, 0x8F, 91 | 0x80, 0x06, 0x00, 0x01, 0x00, 0x00, 0x76, 0x8F, 92 | 0x80, 0x0A, 0xFF, 0xFF, 0x00, 0x00, 0x76, 0x8F, 93 | 0x80, 0x0B, 0x00, 0x01, 0x00, 0x00, 0x76, 0x8F, 94 | 0x00, 0x96, 0x00, 0x04 95 | }; 96 | 97 | if(argc != 5) 98 | { 99 | fprintf(stderr, "Usage: upload-to-pskreporter call grid antenna file\n"); 100 | return EXIT_FAILURE; 101 | } 102 | 103 | if(strlen(argv[1]) > 16) 104 | { 105 | fprintf(stderr, "Call sign is too long.\n"); 106 | return EXIT_FAILURE; 107 | } 108 | 109 | if(strlen(argv[2]) > 6) 110 | { 111 | fprintf(stderr, "Grid locator is too long.\n"); 112 | return EXIT_FAILURE; 113 | } 114 | 115 | if(strlen(argv[3]) > 64) 116 | { 117 | fprintf(stderr, "Antenna description is too long.\n"); 118 | return EXIT_FAILURE; 119 | } 120 | 121 | if((fp = fopen(argv[4], "r")) == NULL) 122 | { 123 | fprintf(stderr, "Cannot open input file.\n"); 124 | return EXIT_FAILURE; 125 | } 126 | 127 | if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 128 | { 129 | fprintf(stderr, "Cannot open socket.\n"); 130 | return EXIT_FAILURE; 131 | } 132 | 133 | if((host = gethostbyname(name)) == NULL) 134 | { 135 | fprintf(stderr, "Cannot find remote host address.\n"); 136 | return EXIT_FAILURE; 137 | } 138 | 139 | memset(&addr, 0, sizeof(addr)); 140 | addr.sin_family = AF_INET; 141 | memcpy(&addr.sin_addr.s_addr, host->h_addr, host->h_length); 142 | addr.sin_port = htons(4739); 143 | 144 | clock_gettime(CLOCK_REALTIME, &ts); 145 | srand(ts.tv_nsec / 1000); 146 | 147 | dst = header + 12; 148 | copy_int4(&dst, rand()); 149 | 150 | memcpy(buffer, header, sizeof(header)); 151 | 152 | start = buffer + sizeof(header); 153 | 154 | dst = start + 4; 155 | copy_char(&dst, argv[1]); 156 | copy_char(&dst, argv[2]); 157 | copy_char(&dst, soft); 158 | copy_char(&dst, argv[3]); 159 | 160 | size = dst - start; 161 | padding = (4 - size % 4) % 4; 162 | size += padding; 163 | memset(dst, 0, padding); 164 | 165 | dst = start; 166 | copy_int2(&dst, 0x9992); 167 | copy_int2(&dst, size); 168 | 169 | start += size; 170 | 171 | counter = 0; 172 | sequence = 0; 173 | dst = start + 4; 174 | for(;;) 175 | { 176 | src = fgets(line, 64, fp); 177 | 178 | if(src != NULL) 179 | { 180 | call[0] = 0; 181 | grid[0] = 0; 182 | rc = read_time(&src, &tm) 183 | && read_dbl(&src, &sync) 184 | && read_int(&src, &snr) 185 | && read_dbl(&src, &dt) 186 | && read_int(&src, &freq) 187 | && sscanf(src, "%13s %4s", call, grid); 188 | 189 | if(!rc) continue; 190 | 191 | copy_char(&dst, call); 192 | copy_char(&dst, grid); 193 | copy_int4(&dst, freq); 194 | copy_int1(&dst, snr); 195 | copy_char(&dst, "FT8"); 196 | copy_int1(&dst, 1); 197 | copy_int4(&dst, timegm(&tm) + 15); 198 | 199 | ++counter; 200 | 201 | if(counter < 10) continue; 202 | } 203 | 204 | if(counter > 0) 205 | { 206 | size = dst - start; 207 | padding = (4 - size % 4) % 4; 208 | size += padding; 209 | memset(dst, 0, padding); 210 | 211 | dst = start; 212 | copy_int2(&dst, 0x9993); 213 | copy_int2(&dst, size); 214 | 215 | dst = buffer + 2; 216 | size += start - buffer; 217 | copy_int2(&dst, size); 218 | copy_int4(&dst, time(NULL)); 219 | copy_int4(&dst, sequence); 220 | 221 | sendto(sock, buffer, size, 0, (struct sockaddr *)&addr, sizeof(addr)); 222 | 223 | counter = 0; 224 | ++sequence; 225 | dst = start + 4; 226 | } 227 | 228 | if(src == NULL) break; 229 | } 230 | 231 | return EXIT_SUCCESS; 232 | } 233 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/app/write-c2-files.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | FILE *fp; 15 | int fd, offset, length, i, j; 16 | time_t t; 17 | struct tm *gmt; 18 | volatile void *cfg, *sts; 19 | volatile uint64_t *fifo; 20 | volatile uint8_t *rst; 21 | volatile uint16_t *sel, *cntr; 22 | uint64_t *buffer; 23 | config_t config; 24 | config_setting_t *setting, *element; 25 | char date[12]; 26 | char name[64]; 27 | double corr, dialfreq, integral; 28 | double freq[16] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; 29 | 30 | if(argc != 2) 31 | { 32 | fprintf(stderr, "Usage: write-c2-files config_file.cfg\n"); 33 | return EXIT_FAILURE; 34 | } 35 | 36 | config_init(&config); 37 | 38 | if(!config_read_file(&config, argv[1])) 39 | { 40 | fprintf(stderr, "Error on line %d in configuration file.\n", config_error_line(&config)); 41 | return EXIT_FAILURE; 42 | } 43 | 44 | if(!config_lookup_float(&config, "corr", &corr)) 45 | { 46 | fprintf(stderr, "No 'corr' setting in configuration file.\n"); 47 | return EXIT_FAILURE; 48 | } 49 | 50 | if(corr < -100.0 || corr > 100.0) 51 | { 52 | fprintf(stderr, "Wrong 'corr' setting in configuration file.\n"); 53 | return EXIT_FAILURE; 54 | } 55 | 56 | setting = config_lookup(&config, "bands"); 57 | if(setting == NULL) 58 | { 59 | fprintf(stderr, "No 'bands' setting in configuration file.\n"); 60 | return EXIT_FAILURE; 61 | } 62 | 63 | length = config_setting_length(setting); 64 | 65 | if(length > 16) 66 | { 67 | fprintf(stderr, "More than 16 bands in configuration file.\n"); 68 | return EXIT_FAILURE; 69 | } 70 | 71 | if(length < 1) 72 | { 73 | fprintf(stderr, "Less than 1 band in configuration file.\n"); 74 | return EXIT_FAILURE; 75 | } 76 | 77 | for(i = 0; i < length; ++i) 78 | { 79 | element = config_setting_get_elem(setting, i); 80 | 81 | if(!config_setting_lookup_float(element, "freq", &freq[i])) 82 | { 83 | fprintf(stderr, "No 'freq' setting in element %d.\n", i); 84 | return EXIT_FAILURE; 85 | } 86 | } 87 | 88 | t = time(NULL); 89 | if((gmt = gmtime(&t)) == NULL) 90 | { 91 | fprintf(stderr, "Cannot convert time.\n"); 92 | return EXIT_FAILURE; 93 | } 94 | 95 | if((fd = open("/dev/mem", O_RDWR)) < 0) 96 | { 97 | fprintf(stderr, "Cannot open /dev/mem.\n"); 98 | return EXIT_FAILURE; 99 | } 100 | 101 | cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x40000000); 102 | sts = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x41000000); 103 | fifo = mmap(NULL, 32*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x42000000); 104 | 105 | for(i = 0; i < 16; ++i) 106 | { 107 | *(uint32_t *)(cfg + 4 + i * 4) = (uint32_t)floor(modf((1.0 + 1.0e-6 * corr) * freq[i] / 77.76, &integral) * 0xffffffff + 0.5); 108 | } 109 | 110 | rst = (uint8_t *)(cfg + 0); 111 | cntr = (uint16_t *)(sts + 0); 112 | 113 | *rst &= ~1; 114 | *rst |= 1; 115 | 116 | offset = 0; 117 | buffer = malloc(240000 * 8 * 16); 118 | memset(buffer, 0, 240000 * 8 * 16); 119 | 120 | while(offset < 236000) 121 | { 122 | while(*cntr < 500) usleep(10000); 123 | 124 | for(i = 0; i < 250; ++i) 125 | { 126 | for(j = 0; j < 16; ++j) 127 | { 128 | buffer[j * 240000 + offset + i] = *fifo; 129 | } 130 | } 131 | 132 | offset += 250; 133 | } 134 | 135 | for(i = 0; i < length; ++i) 136 | { 137 | dialfreq = freq[i] * 1.0e6; 138 | strftime(date, 12, "%y%m%d_%H%M", gmt); 139 | sprintf(name, "ft8_%d_%d_%s.c2", i, (uint32_t)dialfreq, date); 140 | if((fp = fopen(name, "wb")) == NULL) 141 | { 142 | fprintf(stderr, "Cannot open output file %s.\n", name); 143 | return EXIT_FAILURE; 144 | } 145 | fwrite(&dialfreq, 1, 8, fp); 146 | fwrite(&buffer[i * 240000], 1, 240000 * 8, fp); 147 | fclose(fp); 148 | } 149 | 150 | return EXIT_SUCCESS; 151 | } 152 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/app/write-c2-files.cfg: -------------------------------------------------------------------------------- 1 | // frequency correction, from -100.0 ppm to +100.0 ppm 2 | corr = 0.0; 3 | 4 | // comma separated list of bands 5 | // trailing commas are not allowed 6 | bands = ( 7 | { freq = 1.841500; }, 8 | { freq = 3.574500; }, 9 | { freq = 5.358500; }, 10 | { freq = 7.075500; }, 11 | { freq = 10.137500; }, 12 | { freq = 14.075500; }, 13 | { freq = 18.101500; }, 14 | { freq = 21.075500; }, 15 | { freq = 24.916500; }, 16 | { freq = 28.075500; }, 17 | { freq = 50.314500; } 18 | ); 19 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/block_design.tcl: -------------------------------------------------------------------------------- 1 | # Create ports 2 | create_bd_port -dir I adc_clk_p_i 3 | create_bd_port -dir I adc_clk_n_i 4 | 5 | create_bd_port -dir I adc_ovr_p_i 6 | create_bd_port -dir I adc_ovr_n_i 7 | 8 | create_bd_port -dir I -from 6 -to 0 adc_dat_p_i 9 | create_bd_port -dir I -from 6 -to 0 adc_dat_n_i 10 | 11 | create_bd_port -dir O adc_spi_sclk 12 | create_bd_port -dir O adc_spi_sdio 13 | create_bd_port -dir O adc_spi_cs 14 | 15 | create_bd_port -dir O adc_oe 16 | 17 | # Create xlconstant 18 | cell xilinx.com:ip:xlconstant const_0 19 | 20 | # Create clk_wiz 21 | cell xilinx.com:ip:clk_wiz pll_0 { 22 | PRIMITIVE PLL 23 | PRIM_IN_FREQ.VALUE_SRC USER 24 | PRIM_IN_FREQ 77.76 25 | PRIM_SOURCE Differential_clock_capable_pin 26 | CLKOUT1_USED true 27 | CLKOUT1_REQUESTED_OUT_FREQ 77.76 28 | USE_RESET false 29 | } { 30 | clk_in1_p adc_clk_p_i 31 | clk_in1_n adc_clk_n_i 32 | } 33 | 34 | # Create processing_system7 35 | cell xilinx.com:ip:processing_system7 ps_0 { 36 | PCW_IMPORT_BOARD_PRESET cfg/qmtech_xc7z020.xml 37 | PCW_USE_M_AXI_GP1 1 38 | } { 39 | M_AXI_GP0_ACLK pll_0/clk_out1 40 | M_AXI_GP1_ACLK pll_0/clk_out1 41 | SPI0_SCLK_O adc_spi_sclk 42 | SPI0_MOSI_O adc_spi_sdio 43 | SPI0_SS_I const_0/dout 44 | SPI0_SS_O adc_spi_cs 45 | } 46 | 47 | # Create port_slicer 48 | cell pavel-demin:user:port_slicer slice_0 { 49 | DIN_WIDTH 64 DIN_FROM 1 DIN_TO 1 50 | } { 51 | din ps_0/GPIO_O 52 | dout adc_oe 53 | } 54 | 55 | # Create all required interconnections 56 | apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config { 57 | make_external {FIXED_IO, DDR} 58 | Master Disable 59 | Slave Disable 60 | } [get_bd_cells ps_0] 61 | 62 | # Create proc_sys_reset 63 | cell xilinx.com:ip:proc_sys_reset rst_0 {} { 64 | ext_reset_in const_0/dout 65 | dcm_locked pll_0/locked 66 | slowest_sync_clk pll_0/clk_out1 67 | } 68 | 69 | # ADC 70 | 71 | # Create util_ds_buf 72 | cell xilinx.com:ip:util_ds_buf buf_0 { 73 | C_SIZE 7 74 | C_BUF_TYPE IBUFDS 75 | } { 76 | IBUF_DS_P adc_dat_p_i 77 | IBUF_DS_N adc_dat_n_i 78 | } 79 | 80 | # Create axis_adc_ddr 81 | cell pavel-demin:user:axis_adc_ddr adc_0 { 82 | ADC_DATA_WIDTH 7 83 | } { 84 | aclk pll_0/clk_out1 85 | adc_data buf_0/IBUF_OUT 86 | } 87 | 88 | # HUB 89 | 90 | # Create axi_hub 91 | cell pavel-demin:user:axi_hub hub_0 { 92 | CFG_DATA_WIDTH 544 93 | STS_DATA_WIDTH 32 94 | } { 95 | S_AXI ps_0/M_AXI_GP0 96 | aclk pll_0/clk_out1 97 | aresetn rst_0/peripheral_aresetn 98 | } 99 | 100 | # RX 0 101 | 102 | # Create port_slicer 103 | cell pavel-demin:user:port_slicer rst_slice_0 { 104 | DIN_WIDTH 544 DIN_FROM 7 DIN_TO 0 105 | } { 106 | din hub_0/cfg_data 107 | } 108 | 109 | # Create port_slicer 110 | cell pavel-demin:user:port_slicer cfg_slice_0 { 111 | DIN_WIDTH 544 DIN_FROM 543 DIN_TO 32 112 | } { 113 | din hub_0/cfg_data 114 | } 115 | 116 | module rx_0 { 117 | source projects/sdr_receiver_ft8_77_76/rx.tcl 118 | } { 119 | slice_0/din rst_slice_0/dout 120 | slice_1/din cfg_slice_0/dout 121 | slice_2/din cfg_slice_0/dout 122 | slice_3/din cfg_slice_0/dout 123 | slice_4/din cfg_slice_0/dout 124 | slice_5/din cfg_slice_0/dout 125 | slice_6/din cfg_slice_0/dout 126 | slice_7/din cfg_slice_0/dout 127 | slice_8/din cfg_slice_0/dout 128 | slice_9/din cfg_slice_0/dout 129 | slice_10/din cfg_slice_0/dout 130 | slice_11/din cfg_slice_0/dout 131 | slice_12/din cfg_slice_0/dout 132 | slice_13/din cfg_slice_0/dout 133 | slice_14/din cfg_slice_0/dout 134 | slice_15/din cfg_slice_0/dout 135 | slice_16/din cfg_slice_0/dout 136 | fifo_0/read_count hub_0/sts_data 137 | conv_2/M_AXIS hub_0/S00_AXIS 138 | } 139 | 140 | # PPS and level measurement 141 | 142 | module common_0 { 143 | source projects/common_tools/block_design.tcl 144 | } 145 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/filters/rx_fir_0.r: -------------------------------------------------------------------------------- 1 | library(signal) 2 | 3 | # CIC filter parameters 4 | R <- 120 # Decimation factor 5 | M <- 1 # Differential delay 6 | N <- 6 # Number of stages 7 | 8 | Fc <- 0.247 # cutoff frequency 9 | htbw <- 0.005 # half transition bandwidth 10 | 11 | # fir2 parameters 12 | k <- kaiserord(c(Fc-htbw, Fc+htbw), c(1, 0), 1/(2^16), 1) 13 | L <- k$n # Filter order 14 | Beta <- k$beta # Kaiser window parameter 15 | 16 | # FIR filter design using fir2 17 | s <- 0.001 # Step size 18 | fp <- seq(0.0, Fc-htbw, by=s) # Pass band frequency samples 19 | fs <- seq(Fc+htbw, 0.5, by=s) # Stop band frequency samples 20 | f <- c(fp, fs)*2 # Normalized frequency samples; 0<=f<=1 21 | 22 | Mp <- matrix(1, 1, length(fp)) # Pass band response; Mp[1]=1 23 | Mp[-1] <- abs(M*R*sin(pi*fp[-1]/R)/sin(pi*M*fp[-1]))^N 24 | Mf <- c(Mp, matrix(0, 1, length(fs))) 25 | 26 | h <- fir2(L, f, Mf, window=kaiser(L+1, Beta)) 27 | 28 | h <- h / sum(h) 29 | 30 | # Print filter coefficients 31 | paste(sprintf("%.10e", h), collapse=", ") 32 | 33 | fh <- freqz(h) 34 | 35 | op <- par(mfrow = c(2, 1)) 36 | 37 | plot(f, 20*log10(Mf), type = "b", ylab = "dB", xlab = "Frequency", xlim = c(0.51, 0.54), ylim = c(-125, 5)) 38 | lines(fh$f / pi, 20*log10(abs(fh$h)), col = "blue") 39 | grid() 40 | 41 | plot(f, 20*log10(Mf), type = "b", ylab = "dB", xlab = "Frequency", xlim = c(0.46, 0.49), ylim = c(-5, 5)) 42 | lines(fh$f / pi, 20*log10(abs(fh$h)), col = "blue") 43 | grid() 44 | 45 | par(op) 46 | -------------------------------------------------------------------------------- /projects/sdr_receiver_ft8_77_76/ports.xdc: -------------------------------------------------------------------------------- 1 | # clock 2 | 3 | set_property IOSTANDARD LVDS_25 [get_ports adc_clk_p_i] 4 | set_property IOSTANDARD LVDS_25 [get_ports adc_clk_n_i] 5 | 6 | set_property DIFF_TERM TRUE [get_ports adc_clk_p_i] 7 | set_property DIFF_TERM TRUE [get_ports adc_clk_n_i] 8 | 9 | set_property PACKAGE_PIN Y19 [get_ports adc_clk_p_i] 10 | set_property PACKAGE_PIN AA19 [get_ports adc_clk_n_i] 11 | 12 | # overrange 13 | 14 | set_property IOSTANDARD LVDS_25 [get_ports {adc_ovr_p_i}] 15 | set_property IOSTANDARD LVDS_25 [get_ports {adc_ovr_n_i}] 16 | 17 | set_property DIFF_TERM TRUE [get_ports {adc_ovr_p_i]}] 18 | set_property DIFF_TERM TRUE [get_ports {adc_ovr_n_i}] 19 | 20 | set_property PACKAGE_PIN U17 [get_ports {adc_ovr_p_i}] 21 | set_property PACKAGE_PIN V17 [get_ports {adc_ovr_n_i}] 22 | 23 | # data 24 | 25 | set_property IOSTANDARD LVDS_25 [get_ports {adc_dat_p_i[*]}] 26 | set_property IOSTANDARD LVDS_25 [get_ports {adc_dat_n_i[*]}] 27 | 28 | set_property DIFF_TERM TRUE [get_ports {adc_dat_p_i[*]}] 29 | set_property DIFF_TERM TRUE [get_ports {adc_dat_n_i[*]}] 30 | 31 | set_property PACKAGE_PIN AA17 [get_ports {adc_dat_p_i[0]}] 32 | set_property PACKAGE_PIN AB17 [get_ports {adc_dat_n_i[0]}] 33 | 34 | set_property PACKAGE_PIN AA16 [get_ports {adc_dat_p_i[1]}] 35 | set_property PACKAGE_PIN AB16 [get_ports {adc_dat_n_i[1]}] 36 | 37 | set_property PACKAGE_PIN AB14 [get_ports {adc_dat_p_i[2]}] 38 | set_property PACKAGE_PIN AB15 [get_ports {adc_dat_n_i[2]}] 39 | 40 | set_property PACKAGE_PIN Y18 [get_ports {adc_dat_p_i[3]}] 41 | set_property PACKAGE_PIN AA18 [get_ports {adc_dat_n_i[3]}] 42 | 43 | set_property PACKAGE_PIN W17 [get_ports {adc_dat_p_i[4]}] 44 | set_property PACKAGE_PIN W18 [get_ports {adc_dat_n_i[4]}] 45 | 46 | set_property PACKAGE_PIN W16 [get_ports {adc_dat_p_i[5]}] 47 | set_property PACKAGE_PIN Y16 [get_ports {adc_dat_n_i[5]}] 48 | 49 | set_property PACKAGE_PIN Y14 [get_ports {adc_dat_p_i[6]}] 50 | set_property PACKAGE_PIN AA14 [get_ports {adc_dat_n_i[6]}] 51 | 52 | # SPI 53 | 54 | set_property IOSTANDARD LVCMOS25 [get_ports adc_spi_*] 55 | 56 | set_property PACKAGE_PIN AA13 [get_ports adc_spi_sclk] 57 | set_property PACKAGE_PIN Y13 [get_ports adc_spi_sdio] 58 | set_property PACKAGE_PIN U15 [get_ports adc_spi_cs] 59 | 60 | # output enable 61 | 62 | set_property IOSTANDARD LVCMOS25 [get_ports adc_oe] 63 | 64 | set_property PACKAGE_PIN Y20 [get_ports adc_oe] 65 | -------------------------------------------------------------------------------- /projects/sdr_receiver_hpsdr_77_76/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SDR receiver compatible with HPSDR 6 | 7 | 8 | 9 | 10 | 19 |
20 |

SDR receiver compatible with HPSDR

21 |

The SDR receiver compatible with HPSDR is ready.

22 |

Now you can run the SDR programs that support the HPSDR/Metis protocol.

23 |

More details about this application can be found at this link.

24 |

SDR programs

25 |

Here is a list of the SDR programs that are known to work with this SDR receiver:

26 | 33 |

Running CW Skimmer Server

34 |
    35 |
  • Install CW Skimmer Server.
  • 36 |
  • Copy HermesIntf.dll to the CW Skimmer Server program directory (C:\Program Files (x86)\Afreet\SkimSrv).
  • 37 |
  • In the SkimSrv directory, rename HermesIntf.dll to HermestIntf_XXXX.dll where XXXX are the last four digits of the MAC address of the QMTECH XC7Z020 board.
  • 38 |
  • Make a copy of the SkimSrv directory and rename the copy to SkimSrv2.
  • 39 |
  • In the SkimSrv2 directory, rename SkimSrv.exe to SkimSrv2.exe and rename HermestIntf_XXXX.dll to HermestIntf_FFXX.dll.
  • 40 |
  • Install Reverse Beacon Network Aggregator.
  • 41 |
  • Start SkimSrv.exe and SkimSrv2.exe, configure frequencies and your call sign.
  • 42 |
  • Start Reverse Beacon Network Aggregator.
  • 43 |
44 |
45 | 46 | 47 | -------------------------------------------------------------------------------- /projects/sdr_receiver_hpsdr_77_76/app/start.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | apps_dir=/media/mmcblk0p1/apps 4 | 5 | source $apps_dir/stop.sh 6 | 7 | cat $apps_dir/sdr_receiver_hpsdr_77_76/sdr_receiver_hpsdr_77_76.bit > /dev/xdevcfg 8 | 9 | $apps_dir/common_tools/setup-adc 10 | $apps_dir/common_tools/enable-adc.sh 11 | 12 | address=`awk -F : '$5="FF"' OFS=: /sys/class/net/eth0/address` 13 | 14 | echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce 15 | echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore 16 | echo 2 > /proc/sys/net/ipv4/conf/all/rp_filter 17 | 18 | ip link add mvl0 link eth0 address $address type macvlan mode passthru 19 | 20 | $apps_dir/sdr_receiver_hpsdr_77_76/sdr-receiver-hpsdr eth0 & 21 | $apps_dir/sdr_receiver_hpsdr_77_76/sdr-receiver-hpsdr mvl0 & 22 | -------------------------------------------------------------------------------- /projects/sdr_receiver_hpsdr_77_76/app/stop.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | killall -q sdr-receiver-hpsdr 4 | 5 | ip link del mvl0 6 | 7 | echo 0 > /proc/sys/net/ipv4/conf/all/arp_announce 8 | echo 0 > /proc/sys/net/ipv4/conf/all/arp_ignore 9 | echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter 10 | -------------------------------------------------------------------------------- /projects/sdr_receiver_hpsdr_77_76/block_design.tcl: -------------------------------------------------------------------------------- 1 | # Create ports 2 | create_bd_port -dir I adc_clk_p_i 3 | create_bd_port -dir I adc_clk_n_i 4 | 5 | create_bd_port -dir I adc_ovr_p_i 6 | create_bd_port -dir I adc_ovr_n_i 7 | 8 | create_bd_port -dir I -from 6 -to 0 adc_dat_p_i 9 | create_bd_port -dir I -from 6 -to 0 adc_dat_n_i 10 | 11 | create_bd_port -dir O adc_spi_sclk 12 | create_bd_port -dir O adc_spi_sdio 13 | create_bd_port -dir O adc_spi_cs 14 | 15 | create_bd_port -dir O adc_oe 16 | 17 | # Create xlconstant 18 | cell xilinx.com:ip:xlconstant const_0 19 | 20 | # Create clk_wiz 21 | cell xilinx.com:ip:clk_wiz pll_0 { 22 | PRIMITIVE PLL 23 | PRIM_IN_FREQ.VALUE_SRC USER 24 | PRIM_IN_FREQ 77.76 25 | PRIM_SOURCE Differential_clock_capable_pin 26 | CLKOUT1_USED true 27 | CLKOUT1_REQUESTED_OUT_FREQ 77.76 28 | USE_RESET false 29 | } { 30 | clk_in1_p adc_clk_p_i 31 | clk_in1_n adc_clk_n_i 32 | } 33 | 34 | # Create processing_system7 35 | cell xilinx.com:ip:processing_system7 ps_0 { 36 | PCW_IMPORT_BOARD_PRESET cfg/qmtech_xc7z020.xml 37 | PCW_USE_M_AXI_GP1 1 38 | } { 39 | M_AXI_GP0_ACLK pll_0/clk_out1 40 | M_AXI_GP1_ACLK pll_0/clk_out1 41 | SPI0_SCLK_O adc_spi_sclk 42 | SPI0_MOSI_O adc_spi_sdio 43 | SPI0_SS_I const_0/dout 44 | SPI0_SS_O adc_spi_cs 45 | } 46 | 47 | # Create port_slicer 48 | cell pavel-demin:user:port_slicer slice_0 { 49 | DIN_WIDTH 64 DIN_FROM 1 DIN_TO 1 50 | } { 51 | din ps_0/GPIO_O 52 | dout adc_oe 53 | } 54 | 55 | # Create all required interconnections 56 | apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config { 57 | make_external {FIXED_IO, DDR} 58 | Master Disable 59 | Slave Disable 60 | } [get_bd_cells ps_0] 61 | 62 | # Create proc_sys_reset 63 | cell xilinx.com:ip:proc_sys_reset rst_0 {} { 64 | ext_reset_in const_0/dout 65 | dcm_locked pll_0/locked 66 | slowest_sync_clk pll_0/clk_out1 67 | } 68 | 69 | # ADC 70 | 71 | # Create util_ds_buf 72 | cell xilinx.com:ip:util_ds_buf buf_0 { 73 | C_SIZE 7 74 | C_BUF_TYPE IBUFDS 75 | } { 76 | IBUF_DS_P adc_dat_p_i 77 | IBUF_DS_N adc_dat_n_i 78 | } 79 | 80 | # Create axis_adc_ddr 81 | cell pavel-demin:user:axis_adc_ddr adc_0 { 82 | ADC_DATA_WIDTH 7 83 | } { 84 | aclk pll_0/clk_out1 85 | adc_data buf_0/IBUF_OUT 86 | } 87 | 88 | # RX 0 89 | 90 | module rx_0 { 91 | source projects/sdr_receiver_hpsdr_77_76/rx.tcl 92 | } { 93 | hub_0/S_AXI ps_0/M_AXI_GP0 94 | } 95 | 96 | # RX 1 97 | 98 | module rx_1 { 99 | source projects/sdr_receiver_hpsdr_77_76/rx.tcl 100 | } { 101 | hub_0/S_AXI ps_0/M_AXI_GP1 102 | } 103 | 104 | -------------------------------------------------------------------------------- /projects/sdr_receiver_hpsdr_77_76/filters/rx_fir_0.r: -------------------------------------------------------------------------------- 1 | library(signal) 2 | 3 | # CIC filter parameters 4 | R <- 81 # Decimation factor 5 | M <- 1 # Differential delay 6 | N <- 6 # Number of stages 7 | 8 | Fc <- 0.097 # cutoff frequency 9 | htbw <- 0.005 # half transition bandwidth 10 | 11 | # fir2 parameters 12 | k <- kaiserord(c(Fc-htbw, Fc+htbw), c(1, 0), 1/(2^16), 1) 13 | L <- k$n # Filter order 14 | Beta <- k$beta # Kaiser window parameter 15 | 16 | # FIR filter design using fir2 17 | s <- 0.001 # Step size 18 | fp <- seq(0.0, Fc-htbw, by=s) # Pass band frequency samples 19 | fs <- seq(Fc+htbw, 0.5, by=s) # Stop band frequency samples 20 | f <- c(fp, fs)*2 # Normalized frequency samples; 0<=f<=1 21 | 22 | Mp <- matrix(1, 1, length(fp)) # Pass band response; Mp[1]=1 23 | Mp[-1] <- abs(M*R*sin(pi*fp[-1]*2/R)/sin(pi*M*fp[-1]*2))^N 24 | Mf <- c(Mp, matrix(0, 1, length(fs))) 25 | 26 | h <- fir2(L, f, Mf, window=kaiser(L+1, Beta)) 27 | 28 | h <- h / sum(h) 29 | 30 | # Print filter coefficients 31 | paste(sprintf("%.10e", h), collapse=", ") 32 | 33 | fh <- freqz(h) 34 | 35 | op <- par(mfrow = c(2, 1)) 36 | 37 | plot(f, 20*log10(Mf), type = "b", ylab = "dB", xlab = "Frequency", xlim = c(0.20, 0.22), ylim = c(-125, 5)) 38 | lines(fh$f / pi, 20*log10(abs(fh$h)), col = "blue") 39 | grid() 40 | 41 | plot(f, 20*log10(Mf), type = "b", ylab = "dB", xlab = "Frequency", xlim = c(0.18, 0.20), ylim = c(-5, 5)) 42 | lines(fh$f / pi, 20*log10(abs(fh$h)), col = "blue") 43 | grid() 44 | 45 | par(op) 46 | -------------------------------------------------------------------------------- /projects/sdr_receiver_hpsdr_77_76/ports.xdc: -------------------------------------------------------------------------------- 1 | # clock 2 | 3 | set_property IOSTANDARD LVDS_25 [get_ports adc_clk_p_i] 4 | set_property IOSTANDARD LVDS_25 [get_ports adc_clk_n_i] 5 | 6 | set_property DIFF_TERM TRUE [get_ports adc_clk_p_i] 7 | set_property DIFF_TERM TRUE [get_ports adc_clk_n_i] 8 | 9 | set_property PACKAGE_PIN Y19 [get_ports adc_clk_p_i] 10 | set_property PACKAGE_PIN AA19 [get_ports adc_clk_n_i] 11 | 12 | # overrange 13 | 14 | set_property IOSTANDARD LVDS_25 [get_ports {adc_ovr_p_i}] 15 | set_property IOSTANDARD LVDS_25 [get_ports {adc_ovr_n_i}] 16 | 17 | set_property DIFF_TERM TRUE [get_ports {adc_ovr_p_i]}] 18 | set_property DIFF_TERM TRUE [get_ports {adc_ovr_n_i}] 19 | 20 | set_property PACKAGE_PIN U17 [get_ports {adc_ovr_p_i}] 21 | set_property PACKAGE_PIN V17 [get_ports {adc_ovr_n_i}] 22 | 23 | # data 24 | 25 | set_property IOSTANDARD LVDS_25 [get_ports {adc_dat_p_i[*]}] 26 | set_property IOSTANDARD LVDS_25 [get_ports {adc_dat_n_i[*]}] 27 | 28 | set_property DIFF_TERM TRUE [get_ports {adc_dat_p_i[*]}] 29 | set_property DIFF_TERM TRUE [get_ports {adc_dat_n_i[*]}] 30 | 31 | set_property PACKAGE_PIN AA17 [get_ports {adc_dat_p_i[0]}] 32 | set_property PACKAGE_PIN AB17 [get_ports {adc_dat_n_i[0]}] 33 | 34 | set_property PACKAGE_PIN AA16 [get_ports {adc_dat_p_i[1]}] 35 | set_property PACKAGE_PIN AB16 [get_ports {adc_dat_n_i[1]}] 36 | 37 | set_property PACKAGE_PIN AB14 [get_ports {adc_dat_p_i[2]}] 38 | set_property PACKAGE_PIN AB15 [get_ports {adc_dat_n_i[2]}] 39 | 40 | set_property PACKAGE_PIN Y18 [get_ports {adc_dat_p_i[3]}] 41 | set_property PACKAGE_PIN AA18 [get_ports {adc_dat_n_i[3]}] 42 | 43 | set_property PACKAGE_PIN W17 [get_ports {adc_dat_p_i[4]}] 44 | set_property PACKAGE_PIN W18 [get_ports {adc_dat_n_i[4]}] 45 | 46 | set_property PACKAGE_PIN W16 [get_ports {adc_dat_p_i[5]}] 47 | set_property PACKAGE_PIN Y16 [get_ports {adc_dat_n_i[5]}] 48 | 49 | set_property PACKAGE_PIN Y14 [get_ports {adc_dat_p_i[6]}] 50 | set_property PACKAGE_PIN AA14 [get_ports {adc_dat_n_i[6]}] 51 | 52 | # SPI 53 | 54 | set_property IOSTANDARD LVCMOS25 [get_ports adc_spi_*] 55 | 56 | set_property PACKAGE_PIN AA13 [get_ports adc_spi_sclk] 57 | set_property PACKAGE_PIN Y13 [get_ports adc_spi_sdio] 58 | set_property PACKAGE_PIN U15 [get_ports adc_spi_cs] 59 | 60 | # output enable 61 | 62 | set_property IOSTANDARD LVCMOS25 [get_ports adc_oe] 63 | 64 | set_property PACKAGE_PIN Y20 [get_ports adc_oe] 65 | -------------------------------------------------------------------------------- /projects/sdr_receiver_hpsdr_77_76/rx.tcl: -------------------------------------------------------------------------------- 1 | # Create axi_hub 2 | cell pavel-demin:user:axi_hub hub_0 { 3 | CFG_DATA_WIDTH 288 4 | STS_DATA_WIDTH 32 5 | } { 6 | aclk /pll_0/clk_out1 7 | aresetn /rst_0/peripheral_aresetn 8 | } 9 | 10 | # Create port_slicer 11 | cell pavel-demin:user:port_slicer slice_0 { 12 | DIN_WIDTH 288 DIN_FROM 0 DIN_TO 0 13 | } { 14 | din hub_0/cfg_data 15 | } 16 | 17 | # Create port_slicer 18 | cell pavel-demin:user:port_slicer slice_1 { 19 | DIN_WIDTH 288 DIN_FROM 31 DIN_TO 16 20 | } { 21 | din hub_0/cfg_data 22 | } 23 | 24 | for {set i 0} {$i <= 7} {incr i} { 25 | 26 | # Create port_slicer 27 | cell pavel-demin:user:port_slicer slice_[expr $i + 2] { 28 | DIN_WIDTH 288 DIN_FROM [expr 32 * $i + 63] DIN_TO [expr 32 * $i + 32] 29 | } { 30 | din hub_0/cfg_data 31 | } 32 | 33 | # Create dds 34 | cell pavel-demin:user:dds dds_$i { 35 | NEGATIVE_SINE TRUE 36 | } { 37 | pinc slice_[expr $i + 2]/dout 38 | aclk /pll_0/clk_out1 39 | aresetn /rst_0/peripheral_aresetn 40 | } 41 | 42 | } 43 | 44 | # Create xlconstant 45 | cell xilinx.com:ip:xlconstant const_0 46 | 47 | for {set i 0} {$i <= 15} {incr i} { 48 | 49 | # Create port_slicer 50 | cell pavel-demin:user:port_slicer dds_slice_$i { 51 | DIN_WIDTH 48 DIN_FROM [expr 24 * ($i % 2) + 23] DIN_TO [expr 24 * ($i % 2)] 52 | } { 53 | din dds_[expr $i / 2]/dout 54 | } 55 | 56 | # Create dsp48 57 | cell pavel-demin:user:dsp48 mult_$i { 58 | A_WIDTH 24 59 | B_WIDTH 14 60 | P_WIDTH 24 61 | } { 62 | A dds_slice_$i/dout 63 | B /adc_0/m_axis_tdata 64 | CLK /pll_0/clk_out1 65 | } 66 | 67 | # Create axis_variable 68 | cell pavel-demin:user:axis_variable rate_$i { 69 | AXIS_TDATA_WIDTH 16 70 | } { 71 | cfg_data slice_1/dout 72 | aclk /pll_0/clk_out1 73 | aresetn /rst_0/peripheral_aresetn 74 | } 75 | 76 | # Create cic_compiler 77 | cell xilinx.com:ip:cic_compiler cic_$i { 78 | INPUT_DATA_WIDTH.VALUE_SRC USER 79 | FILTER_TYPE Decimation 80 | NUMBER_OF_STAGES 6 81 | SAMPLE_RATE_CHANGES Programmable 82 | MINIMUM_RATE 81 83 | MAXIMUM_RATE 1296 84 | FIXED_OR_INITIAL_RATE 648 85 | INPUT_SAMPLE_FREQUENCY 77.76 86 | CLOCK_FREQUENCY 77.76 87 | INPUT_DATA_WIDTH 24 88 | QUANTIZATION Truncation 89 | OUTPUT_DATA_WIDTH 32 90 | USE_XTREME_DSP_SLICE false 91 | HAS_ARESETN true 92 | } { 93 | s_axis_data_tdata mult_$i/P 94 | s_axis_data_tvalid const_0/dout 95 | S_AXIS_CONFIG rate_$i/M_AXIS 96 | aclk /pll_0/clk_out1 97 | aresetn /rst_0/peripheral_aresetn 98 | } 99 | 100 | } 101 | 102 | # Create axis_combiner 103 | cell xilinx.com:ip:axis_combiner comb_0 { 104 | TDATA_NUM_BYTES.VALUE_SRC USER 105 | TDATA_NUM_BYTES 4 106 | NUM_SI 16 107 | } { 108 | S00_AXIS cic_0/M_AXIS_DATA 109 | S01_AXIS cic_1/M_AXIS_DATA 110 | S02_AXIS cic_2/M_AXIS_DATA 111 | S03_AXIS cic_3/M_AXIS_DATA 112 | S04_AXIS cic_4/M_AXIS_DATA 113 | S05_AXIS cic_5/M_AXIS_DATA 114 | S06_AXIS cic_6/M_AXIS_DATA 115 | S07_AXIS cic_7/M_AXIS_DATA 116 | S08_AXIS cic_8/M_AXIS_DATA 117 | S09_AXIS cic_9/M_AXIS_DATA 118 | S10_AXIS cic_10/M_AXIS_DATA 119 | S11_AXIS cic_11/M_AXIS_DATA 120 | S12_AXIS cic_12/M_AXIS_DATA 121 | S13_AXIS cic_13/M_AXIS_DATA 122 | S14_AXIS cic_14/M_AXIS_DATA 123 | S15_AXIS cic_15/M_AXIS_DATA 124 | aclk /pll_0/clk_out1 125 | aresetn /rst_0/peripheral_aresetn 126 | } 127 | 128 | # Create axis_dwidth_converter 129 | cell xilinx.com:ip:axis_dwidth_converter conv_0 { 130 | S_TDATA_NUM_BYTES.VALUE_SRC USER 131 | S_TDATA_NUM_BYTES 64 132 | M_TDATA_NUM_BYTES 4 133 | } { 134 | S_AXIS comb_0/M_AXIS 135 | aclk /pll_0/clk_out1 136 | aresetn /rst_0/peripheral_aresetn 137 | } 138 | 139 | # Create fir_compiler 140 | cell xilinx.com:ip:fir_compiler fir_0 { 141 | DATA_WIDTH.VALUE_SRC USER 142 | DATA_WIDTH 32 143 | COEFFICIENTVECTOR {8.6416634255e-09, 1.9787522479e-08, 2.5521203789e-08, 2.3638357357e-08, 1.4790149581e-08, 1.9719648224e-09, -1.1032338549e-08, -2.1355862813e-08, -2.7914377238e-08, -3.0931374243e-08, -3.0470610650e-08, -2.5069790691e-08, -1.1732378562e-08, 1.2106227398e-08, 4.5256582454e-08, 7.9934220054e-08, 1.0168998967e-07, 9.3590856156e-08, 4.4144966037e-08, -4.3922671719e-08, -1.4852200249e-07, -2.3083384546e-07, -2.4726320140e-07, -1.6800994993e-07, 4.5912166862e-09, 2.2678122505e-07, 4.2020376983e-07, 4.9631671575e-07, 3.9210438758e-07, 1.0401511886e-07, -2.9540946982e-07, -6.6974601177e-07, -8.6118574256e-07, -7.5179544934e-07, -3.2135153633e-07, 3.2363684057e-07, 9.6792135313e-07, 1.3542946906e-06, 1.2805958992e-06, 6.9217855668e-07, -2.6932495334e-07, -1.2887872597e-06, -1.9748299670e-06, -2.0041416687e-06, -1.2616531622e-06, 8.1045970371e-08, 1.5902969896e-06, 2.7034505382e-06, 2.9326808171e-06, 2.0677893719e-06, 2.9671782990e-07, -1.8153799542e-06, -3.4986916001e-06, -4.0537458905e-06, -3.1326541017e-06, -9.1621545700e-07, 1.8951789437e-06, 4.2945533398e-06, 5.3243068872e-06, 4.4510966031e-06, 1.8150145648e-06, -1.7570418369e-06, -5.0023771924e-06, -6.6656492920e-06, -5.9799678791e-06, -3.0028313096e-06, 1.3358282157e-06, 5.5163795673e-06, 7.9608658936e-06, 7.6277789306e-06, 4.4461154951e-06, -5.8984164425e-07, -5.7251392145e-06, -9.0581314802e-06, -9.2484912704e-06, -6.0541412073e-06, -4.8199458599e-07, 5.5262501707e-06, 9.7774958316e-06, 1.0637326831e-05, 7.6640662304e-06, 1.8181526672e-06, -4.8491693605e-06, -9.9277893079e-06, -1.1536455496e-05, -9.0334291964e-06, -3.2759450427e-06, 3.6790473433e-06, 9.3279777293e-06, 1.1646532779e-05, 9.8373152541e-06, 4.6141546613e-06, -2.0841283602e-06, -7.8366295707e-06, -1.0649202562e-05, -9.6766597871e-06, -5.4841491162e-06, 2.3935387332e-07, 5.3827746410e-06, 8.2348658276e-06, 8.0928618642e-06, 5.4248153015e-06, 1.5482305844e-06, -2.0058806216e-06, -4.1464815041e-06, -4.6028386086e-06, -3.8783946363e-06, -2.8311981110e-06, -2.1143317814e-06, -1.7787125841e-06, -1.2613202098e-06, 2.1404336279e-07, 3.0196794545e-06, 6.6285446608e-06, 9.5597769186e-06, 9.8970858249e-06, 6.2280706793e-06, -1.3999300558e-06, -1.1004079038e-05, -1.9029472380e-05, -2.1573387839e-05, -1.6082598930e-05, -2.8350137599e-06, 1.4518712779e-05, 2.9788917181e-05, 3.6356227405e-05, 2.9875585364e-05, 1.0516808093e-05, -1.6294026764e-05, -4.1195968302e-05, -5.4056581743e-05, -4.7949938310e-05, -2.2431204012e-05, 1.5335680685e-05, 5.2357533492e-05, 7.4172234233e-05, 7.0371097114e-05, 3.9214909546e-05, -1.0613325355e-05, -6.2159982313e-05, -9.5857297703e-05, -9.6843895010e-05, -6.1246116434e-05, 1.1596087820e-06, 6.9321939920e-05, 1.1790595196e-04, 1.2662552441e-04, 8.8507777460e-05, 1.3781498407e-05, -7.2510875641e-05, -1.3880280100e-04, -1.5849588836e-04, -1.2049046521e-04, -3.4625933141e-05, 7.0455194291e-05, 1.5677318467e-04, 1.9071963279e-04, 1.5606818885e-04, 6.1270662098e-05, -6.2125794971e-05, -1.6991125582e-04, -2.2107906371e-04, -1.9342374961e-04, -9.2934134104e-05, 4.6928443366e-05, 1.7633944720e-04, 2.4694245575e-04, 2.2999478843e-04, 1.2798765460e-04, -2.4941664121e-05, -1.7444600564e-04, -2.6542975109e-04, -2.6251833556e-04, -1.6386926905e-04, -2.9017345509e-06, 1.6309186966e-04, 2.7356222115e-04, 2.8705580527e-04, 1.9695561615e-04, 3.4555670489e-05, -1.4193230722e-04, -2.6855336886e-04, -2.9916488047e-04, -2.2256165500e-04, -6.6689937029e-05, 1.1170007522e-04, 2.4810655924e-04, 2.9410546207e-04, 2.3497584277e-04, 9.4530201531e-05, -7.4520222202e-05, -2.1079107961e-04, -2.6716055532e-04, -2.2762585917e-04, -1.1182026094e-04, 3.4129098118e-05, 1.5635447302e-04, 2.1391598199e-04, 1.9320383872e-04, 1.1071751871e-04, 3.7908910630e-06, -8.6209631786e-05, -1.3076687946e-04, -1.2404753376e-04, -8.1941203532e-05, -3.1493984650e-05, 3.7618482978e-06, 1.5327191471e-05, 1.2475457050e-05, 1.4900403573e-05, 3.9029838255e-05, 8.5212216095e-05, 1.3306952296e-04, 1.4875133947e-04, 1.0203253711e-04, -1.4244728473e-05, -1.7230750533e-04, -3.1296479335e-04, -3.6604545253e-04, -2.8133052368e-04, -5.7330371892e-05, 2.4606492228e-04, 5.2013232626e-04, 6.4430392795e-04, 5.3576204832e-04, 1.9220436978e-04, -2.9193714506e-04, -7.4731044440e-04, -9.8656619314e-04, -8.7815597539e-04, -4.0893233116e-04, 2.9200492514e-04, 9.8371803137e-04, 1.3934897225e-03, 1.3210162624e-03, 7.2799464557e-04, -2.2481558671e-04, -1.2147116076e-03, -1.8630079096e-03, -1.8763709734e-03, -1.1719555546e-03, 6.4921935546e-05, 1.4211556881e-03, 2.3897382217e-03, 2.5554049165e-03, 1.7653955158e-03, 2.1726375791e-04, -1.5792901757e-03, -2.9651397494e-03, -3.3691024975e-03, -2.5360356113e-03, -6.5682663411e-04, 1.6595757982e-03, 3.5770214428e-03, 4.3286963968e-03, 3.5160483017e-03, 1.2960357442e-03, -1.6254062809e-03, -4.2094376163e-03, -5.4471917717e-03, -4.7450324797e-03, -2.1878913494e-03, 1.4303547141e-03, 4.8420974952e-03, 6.7417004048e-03, 6.2749186441e-03, 3.4019773004e-03, -1.0139113090e-03, -5.4502911147e-03, -8.2390953251e-03, -8.1808578202e-03, -5.0376756147e-03, 2.9071387529e-04, 6.0016792136e-03, 9.9836955649e-03, 1.0579354406e-02, 7.2475257605e-03, 8.6880057823e-04, -6.4514589167e-03, -1.2054494720e-02, -1.3667770498e-02, -1.0289159644e-02, -2.6835541906e-03, 6.7274828446e-03, 1.4599435427e-02, 1.7811581265e-02, 1.4646249040e-02, 5.5728291554e-03, -6.6881265746e-03, -1.7916290000e-02, -2.3770141281e-02, -2.1362115622e-02, -1.0487921502e-02, 5.9634682621e-03, 2.2652378162e-02, 3.3374547837e-02, 3.3147252075e-02, 2.0139686562e-02, -3.2170050718e-03, -3.0392681085e-02, -5.2269158542e-02, -5.9644704750e-02, -4.6033325214e-02, -9.9174346067e-03, 4.4272248035e-02, 1.0682708940e-01, 1.6497706887e-01, 2.0608084740e-01, 2.2090784056e-01, 2.0608084740e-01, 1.6497706887e-01, 1.0682708940e-01, 4.4272248035e-02, -9.9174346067e-03, -4.6033325214e-02, -5.9644704750e-02, -5.2269158542e-02, -3.0392681085e-02, -3.2170050718e-03, 2.0139686562e-02, 3.3147252075e-02, 3.3374547837e-02, 2.2652378162e-02, 5.9634682621e-03, -1.0487921502e-02, -2.1362115622e-02, -2.3770141281e-02, -1.7916290000e-02, -6.6881265746e-03, 5.5728291554e-03, 1.4646249040e-02, 1.7811581265e-02, 1.4599435427e-02, 6.7274828446e-03, -2.6835541906e-03, -1.0289159644e-02, -1.3667770498e-02, -1.2054494720e-02, -6.4514589167e-03, 8.6880057823e-04, 7.2475257605e-03, 1.0579354406e-02, 9.9836955649e-03, 6.0016792136e-03, 2.9071387529e-04, -5.0376756147e-03, -8.1808578202e-03, -8.2390953251e-03, -5.4502911147e-03, -1.0139113090e-03, 3.4019773004e-03, 6.2749186441e-03, 6.7417004048e-03, 4.8420974952e-03, 1.4303547141e-03, -2.1878913494e-03, -4.7450324797e-03, -5.4471917717e-03, -4.2094376163e-03, -1.6254062809e-03, 1.2960357442e-03, 3.5160483017e-03, 4.3286963968e-03, 3.5770214428e-03, 1.6595757982e-03, -6.5682663411e-04, -2.5360356113e-03, -3.3691024975e-03, -2.9651397494e-03, -1.5792901757e-03, 2.1726375791e-04, 1.7653955158e-03, 2.5554049165e-03, 2.3897382217e-03, 1.4211556881e-03, 6.4921935546e-05, -1.1719555546e-03, -1.8763709734e-03, -1.8630079096e-03, -1.2147116076e-03, -2.2481558671e-04, 7.2799464557e-04, 1.3210162624e-03, 1.3934897225e-03, 9.8371803137e-04, 2.9200492514e-04, -4.0893233116e-04, -8.7815597539e-04, -9.8656619314e-04, -7.4731044440e-04, -2.9193714506e-04, 1.9220436978e-04, 5.3576204832e-04, 6.4430392795e-04, 5.2013232626e-04, 2.4606492228e-04, -5.7330371892e-05, -2.8133052368e-04, -3.6604545253e-04, -3.1296479335e-04, -1.7230750533e-04, -1.4244728473e-05, 1.0203253711e-04, 1.4875133947e-04, 1.3306952296e-04, 8.5212216095e-05, 3.9029838255e-05, 1.4900403573e-05, 1.2475457050e-05, 1.5327191471e-05, 3.7618482978e-06, -3.1493984650e-05, -8.1941203532e-05, -1.2404753376e-04, -1.3076687946e-04, -8.6209631786e-05, 3.7908910630e-06, 1.1071751871e-04, 1.9320383872e-04, 2.1391598199e-04, 1.5635447302e-04, 3.4129098118e-05, -1.1182026094e-04, -2.2762585917e-04, -2.6716055532e-04, -2.1079107961e-04, -7.4520222202e-05, 9.4530201531e-05, 2.3497584277e-04, 2.9410546207e-04, 2.4810655924e-04, 1.1170007522e-04, -6.6689937029e-05, -2.2256165500e-04, -2.9916488047e-04, -2.6855336886e-04, -1.4193230722e-04, 3.4555670489e-05, 1.9695561615e-04, 2.8705580527e-04, 2.7356222115e-04, 1.6309186966e-04, -2.9017345509e-06, -1.6386926905e-04, -2.6251833556e-04, -2.6542975109e-04, -1.7444600564e-04, -2.4941664121e-05, 1.2798765460e-04, 2.2999478843e-04, 2.4694245575e-04, 1.7633944720e-04, 4.6928443366e-05, -9.2934134104e-05, -1.9342374961e-04, -2.2107906371e-04, -1.6991125582e-04, -6.2125794971e-05, 6.1270662098e-05, 1.5606818885e-04, 1.9071963279e-04, 1.5677318467e-04, 7.0455194291e-05, -3.4625933141e-05, -1.2049046521e-04, -1.5849588836e-04, -1.3880280100e-04, -7.2510875641e-05, 1.3781498407e-05, 8.8507777460e-05, 1.2662552441e-04, 1.1790595196e-04, 6.9321939920e-05, 1.1596087820e-06, -6.1246116434e-05, -9.6843895010e-05, -9.5857297703e-05, -6.2159982313e-05, -1.0613325355e-05, 3.9214909546e-05, 7.0371097114e-05, 7.4172234233e-05, 5.2357533492e-05, 1.5335680685e-05, -2.2431204012e-05, -4.7949938310e-05, -5.4056581743e-05, -4.1195968302e-05, -1.6294026764e-05, 1.0516808093e-05, 2.9875585364e-05, 3.6356227405e-05, 2.9788917181e-05, 1.4518712779e-05, -2.8350137599e-06, -1.6082598930e-05, -2.1573387839e-05, -1.9029472380e-05, -1.1004079038e-05, -1.3999300558e-06, 6.2280706793e-06, 9.8970858249e-06, 9.5597769186e-06, 6.6285446608e-06, 3.0196794545e-06, 2.1404336279e-07, -1.2613202098e-06, -1.7787125841e-06, -2.1143317814e-06, -2.8311981110e-06, -3.8783946363e-06, -4.6028386086e-06, -4.1464815041e-06, -2.0058806216e-06, 1.5482305844e-06, 5.4248153015e-06, 8.0928618642e-06, 8.2348658276e-06, 5.3827746410e-06, 2.3935387332e-07, -5.4841491162e-06, -9.6766597871e-06, -1.0649202562e-05, -7.8366295707e-06, -2.0841283602e-06, 4.6141546613e-06, 9.8373152541e-06, 1.1646532779e-05, 9.3279777293e-06, 3.6790473433e-06, -3.2759450427e-06, -9.0334291964e-06, -1.1536455496e-05, -9.9277893079e-06, -4.8491693605e-06, 1.8181526672e-06, 7.6640662304e-06, 1.0637326831e-05, 9.7774958316e-06, 5.5262501707e-06, -4.8199458599e-07, -6.0541412073e-06, -9.2484912704e-06, -9.0581314802e-06, -5.7251392145e-06, -5.8984164425e-07, 4.4461154951e-06, 7.6277789306e-06, 7.9608658936e-06, 5.5163795673e-06, 1.3358282157e-06, -3.0028313096e-06, -5.9799678791e-06, -6.6656492920e-06, -5.0023771924e-06, -1.7570418369e-06, 1.8150145648e-06, 4.4510966031e-06, 5.3243068872e-06, 4.2945533398e-06, 1.8951789437e-06, -9.1621545700e-07, -3.1326541017e-06, -4.0537458905e-06, -3.4986916001e-06, -1.8153799542e-06, 2.9671782990e-07, 2.0677893719e-06, 2.9326808171e-06, 2.7034505382e-06, 1.5902969896e-06, 8.1045970371e-08, -1.2616531622e-06, -2.0041416687e-06, -1.9748299670e-06, -1.2887872597e-06, -2.6932495334e-07, 6.9217855668e-07, 1.2805958992e-06, 1.3542946906e-06, 9.6792135313e-07, 3.2363684057e-07, -3.2135153633e-07, -7.5179544934e-07, -8.6118574256e-07, -6.6974601177e-07, -2.9540946982e-07, 1.0401511886e-07, 3.9210438758e-07, 4.9631671575e-07, 4.2020376983e-07, 2.2678122505e-07, 4.5912166862e-09, -1.6800994993e-07, -2.4726320140e-07, -2.3083384546e-07, -1.4852200249e-07, -4.3922671719e-08, 4.4144966037e-08, 9.3590856156e-08, 1.0168998967e-07, 7.9934220054e-08, 4.5256582454e-08, 1.2106227398e-08, -1.1732378562e-08, -2.5069790691e-08, -3.0470610650e-08, -3.0931374243e-08, -2.7914377238e-08, -2.1355862813e-08, -1.1032338549e-08, 1.9719648224e-09, 1.4790149581e-08, 2.3638357357e-08, 2.5521203789e-08, 1.9787522478e-08, 8.6416634255e-09} 144 | COEFFICIENT_WIDTH 24 145 | QUANTIZATION Quantize_Only 146 | BESTPRECISION true 147 | FILTER_TYPE Decimation 148 | RATE_CHANGE_TYPE Fixed_Fractional 149 | INTERPOLATION_RATE 2 150 | DECIMATION_RATE 5 151 | NUMBER_CHANNELS 16 152 | NUMBER_PATHS 1 153 | SAMPLE_FREQUENCY 0.96 154 | CLOCK_FREQUENCY 77.76 155 | OUTPUT_ROUNDING_MODE Convergent_Rounding_to_Even 156 | OUTPUT_WIDTH 27 157 | HAS_ARESETN true 158 | } { 159 | S_AXIS_DATA conv_0/M_AXIS 160 | aclk /pll_0/clk_out1 161 | aresetn /rst_0/peripheral_aresetn 162 | } 163 | 164 | # Create axis_dwidth_converter 165 | cell xilinx.com:ip:axis_dwidth_converter conv_1 { 166 | S_TDATA_NUM_BYTES.VALUE_SRC USER 167 | S_TDATA_NUM_BYTES 4 168 | M_TDATA_NUM_BYTES 64 169 | } { 170 | S_AXIS fir_0/M_AXIS_DATA 171 | aclk /pll_0/clk_out1 172 | aresetn /rst_0/peripheral_aresetn 173 | } 174 | 175 | # Create axis_subset_converter 176 | cell xilinx.com:ip:axis_subset_converter subset_0 { 177 | S_TDATA_NUM_BYTES.VALUE_SRC USER 178 | M_TDATA_NUM_BYTES.VALUE_SRC USER 179 | S_TDATA_NUM_BYTES 64 180 | M_TDATA_NUM_BYTES 48 181 | TDATA_REMAP {tdata[455:448],tdata[463:456],tdata[471:464],tdata[487:480],tdata[495:488],tdata[503:496],tdata[391:384],tdata[399:392],tdata[407:400],tdata[423:416],tdata[431:424],tdata[439:432],tdata[327:320],tdata[335:328],tdata[343:336],tdata[359:352],tdata[367:360],tdata[375:368],tdata[263:256],tdata[271:264],tdata[279:272],tdata[295:288],tdata[303:296],tdata[311:304],tdata[199:192],tdata[207:200],tdata[215:208],tdata[231:224],tdata[239:232],tdata[247:240],tdata[135:128],tdata[143:136],tdata[151:144],tdata[167:160],tdata[175:168],tdata[183:176],tdata[71:64],tdata[79:72],tdata[87:80],tdata[103:96],tdata[111:104],tdata[119:112],tdata[7:0],tdata[15:8],tdata[23:16],tdata[39:32],tdata[47:40],tdata[55:48]} 182 | } { 183 | S_AXIS conv_1/M_AXIS 184 | aclk /pll_0/clk_out1 185 | aresetn /rst_0/peripheral_aresetn 186 | } 187 | 188 | # Create axis_fifo 189 | cell pavel-demin:user:axis_fifo fifo_0 { 190 | S_AXIS_TDATA_WIDTH 384 191 | M_AXIS_TDATA_WIDTH 384 192 | WRITE_DEPTH 2048 193 | ALWAYS_READY TRUE 194 | } { 195 | S_AXIS subset_0/M_AXIS 196 | read_count hub_0/sts_data 197 | aclk /pll_0/clk_out1 198 | aresetn slice_0/dout 199 | } 200 | 201 | # Create axis_dwidth_converter 202 | cell xilinx.com:ip:axis_dwidth_converter conv_2 { 203 | S_TDATA_NUM_BYTES.VALUE_SRC USER 204 | S_TDATA_NUM_BYTES 48 205 | M_TDATA_NUM_BYTES 4 206 | } { 207 | S_AXIS fifo_0/M_AXIS 208 | M_AXIS hub_0/S00_AXIS 209 | aclk /pll_0/clk_out1 210 | aresetn slice_0/dout 211 | } 212 | -------------------------------------------------------------------------------- /projects/sdr_receiver_hpsdr_77_76/server/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -O3 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -D_GNU_SOURCE 2 | 3 | all: sdr-receiver-hpsdr 4 | 5 | sdr-receiver-hpsdr: sdr-receiver-hpsdr.c 6 | gcc $(CFLAGS) -o $@ $^ -lm -lpthread 7 | 8 | clean: 9 | rm -f sdr-receiver-hpsdr 10 | -------------------------------------------------------------------------------- /projects/sdr_receiver_hpsdr_77_76/server/sdr-receiver-hpsdr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | volatile uint32_t *rx_freq; 19 | volatile uint16_t *rx_rate, *rx_cntr; 20 | volatile uint8_t *rx_rst; 21 | volatile uint8_t *rx_data; 22 | 23 | int receivers = 1; 24 | 25 | int sock_ep2; 26 | struct sockaddr_in addr_ep6; 27 | 28 | int enable_thread = 0; 29 | int active_thread = 0; 30 | 31 | void process_ep2(uint8_t *frame); 32 | void *handler_ep6(void *arg); 33 | 34 | int main(int argc, char *argv[]) 35 | { 36 | int fd, i; 37 | ssize_t size; 38 | pthread_t thread; 39 | volatile void *cfg, *sts; 40 | uint8_t buffer[1032]; 41 | uint8_t reply[20] = {0xef, 0xfe, 2, 0, 0, 0, 0, 0, 0, 25, 1, 'R', '_', 'P', 'I', 'T', 'A', 'Y', 'A', 8}; 42 | uint32_t code; 43 | struct ifreq hwaddr; 44 | struct sockaddr_in addr_ep2, addr_from; 45 | socklen_t size_from; 46 | int yes = 1; 47 | 48 | if(argc != 2) 49 | { 50 | fprintf(stderr, "Usage: sdr-receiver-hpsdr interface\n"); 51 | return EXIT_FAILURE; 52 | } 53 | 54 | if((fd = open("/dev/mem", O_RDWR)) < 0) 55 | { 56 | perror("open"); 57 | return EXIT_FAILURE; 58 | } 59 | 60 | if(strcmp(argv[1], "eth0") == 0) 61 | { 62 | cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x40000000); 63 | sts = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x41000000); 64 | rx_data = mmap(NULL, 32*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x42000000); 65 | } 66 | else 67 | { 68 | cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x80000000); 69 | sts = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x81000000); 70 | rx_data = mmap(NULL, 32*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x82000000); 71 | } 72 | 73 | rx_rst = (uint8_t *)(cfg + 0); 74 | rx_rate = (uint16_t *)(cfg + 2); 75 | rx_freq = (uint32_t *)(cfg + 4); 76 | 77 | rx_cntr = (uint16_t *)(sts + 0); 78 | 79 | /* set default rx phase increment */ 80 | for(i = 0; i < 8; ++i) 81 | { 82 | rx_freq[i] = (uint32_t)floor(1000000 / 77.76e6 * 0xffffffff + 0.5); 83 | } 84 | 85 | /* set default rx sample rate */ 86 | *rx_rate = 648; 87 | 88 | if((sock_ep2 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 89 | { 90 | perror("socket"); 91 | return EXIT_FAILURE; 92 | } 93 | 94 | memset(&hwaddr, 0, sizeof(hwaddr)); 95 | strncpy(hwaddr.ifr_name, argv[1], IFNAMSIZ - 1); 96 | ioctl(sock_ep2, SIOCGIFHWADDR, &hwaddr); 97 | for(i = 0; i < 6; ++i) reply[i + 3] = hwaddr.ifr_addr.sa_data[i]; 98 | 99 | setsockopt(sock_ep2, SOL_SOCKET, SO_REUSEADDR, (void *)&yes , sizeof(yes)); 100 | 101 | if(setsockopt(sock_ep2, SOL_SOCKET, SO_BINDTODEVICE, argv[1], strlen(argv[1]) + 1) < 0) 102 | { 103 | perror("SO_BINDTODEVICE"); 104 | return EXIT_FAILURE; 105 | } 106 | 107 | memset(&addr_ep2, 0, sizeof(addr_ep2)); 108 | addr_ep2.sin_family = AF_INET; 109 | addr_ep2.sin_addr.s_addr = htonl(INADDR_ANY); 110 | addr_ep2.sin_port = htons(1024); 111 | 112 | if(bind(sock_ep2, (struct sockaddr *)&addr_ep2, sizeof(addr_ep2)) < 0) 113 | { 114 | perror("bind"); 115 | return EXIT_FAILURE; 116 | } 117 | 118 | while(1) 119 | { 120 | size_from = sizeof(addr_from); 121 | size = recvfrom(sock_ep2, buffer, 1032, 0, (struct sockaddr *)&addr_from, &size_from); 122 | if(size < 0) 123 | { 124 | perror("recvfrom"); 125 | return EXIT_FAILURE; 126 | } 127 | 128 | memcpy(&code, buffer, 4); 129 | switch(code) 130 | { 131 | case 0x0201feef: 132 | process_ep2(buffer + 11); 133 | process_ep2(buffer + 523); 134 | break; 135 | case 0x0002feef: 136 | reply[2] = 2 + active_thread; 137 | memset(buffer, 0, 60); 138 | memcpy(buffer, reply, 20); 139 | sendto(sock_ep2, buffer, 60, 0, (struct sockaddr *)&addr_from, size_from); 140 | break; 141 | case 0x0004feef: 142 | enable_thread = 0; 143 | while(active_thread) usleep(1000); 144 | break; 145 | case 0x0104feef: 146 | case 0x0204feef: 147 | case 0x0304feef: 148 | enable_thread = 0; 149 | while(active_thread) usleep(1000); 150 | memset(&addr_ep6, 0, sizeof(addr_ep6)); 151 | addr_ep6.sin_family = AF_INET; 152 | addr_ep6.sin_addr.s_addr = addr_from.sin_addr.s_addr; 153 | addr_ep6.sin_port = addr_from.sin_port; 154 | enable_thread = 1; 155 | active_thread = 1; 156 | if(pthread_create(&thread, NULL, handler_ep6, NULL) < 0) 157 | { 158 | perror("pthread_create"); 159 | return EXIT_FAILURE; 160 | } 161 | pthread_detach(thread); 162 | break; 163 | } 164 | } 165 | 166 | close(sock_ep2); 167 | 168 | return EXIT_SUCCESS; 169 | } 170 | 171 | void process_ep2(uint8_t *frame) 172 | { 173 | uint32_t freq; 174 | double integral; 175 | 176 | switch(frame[0]) 177 | { 178 | case 0: 179 | case 1: 180 | receivers = ((frame[4] >> 3) & 7) + 1; 181 | 182 | /* set rx sample rate */ 183 | switch(frame[1] & 3) 184 | { 185 | case 0: 186 | *rx_rate = 648; 187 | break; 188 | case 1: 189 | *rx_rate = 324; 190 | break; 191 | case 2: 192 | *rx_rate = 162; 193 | break; 194 | case 3: 195 | *rx_rate = 81; 196 | break; 197 | } 198 | break; 199 | case 4: 200 | case 5: 201 | /* set rx phase increment */ 202 | freq = ntohl(*(uint32_t *)(frame + 1)); 203 | rx_freq[0] = (uint32_t)floor(modf(freq / 77.76e6, &integral) * 0xffffffff + 0.5); 204 | break; 205 | case 6: 206 | case 7: 207 | /* set rx phase increment */ 208 | freq = ntohl(*(uint32_t *)(frame + 1)); 209 | rx_freq[1] = (uint32_t)floor(modf(freq / 77.76e6, &integral) * 0xffffffff + 0.5); 210 | break; 211 | case 8: 212 | case 9: 213 | /* set rx phase increment */ 214 | freq = ntohl(*(uint32_t *)(frame + 1)); 215 | rx_freq[2] = (uint32_t)floor(modf(freq / 77.76e6, &integral) * 0xffffffff + 0.5); 216 | break; 217 | case 10: 218 | case 11: 219 | /* set rx phase increment */ 220 | freq = ntohl(*(uint32_t *)(frame + 1)); 221 | rx_freq[3] = (uint32_t)floor(modf(freq / 77.76e6, &integral) * 0xffffffff + 0.5); 222 | break; 223 | case 12: 224 | case 13: 225 | /* set rx phase increment */ 226 | freq = ntohl(*(uint32_t *)(frame + 1)); 227 | rx_freq[4] = (uint32_t)floor(modf(freq / 77.76e6, &integral) * 0xffffffff + 0.5); 228 | break; 229 | case 14: 230 | case 15: 231 | /* set rx phase increment */ 232 | freq = ntohl(*(uint32_t *)(frame + 1)); 233 | rx_freq[5] = (uint32_t)floor(modf(freq / 77.76e6, &integral) * 0xffffffff + 0.5); 234 | break; 235 | case 16: 236 | case 17: 237 | /* set rx phase increment */ 238 | freq = ntohl(*(uint32_t *)(frame + 1)); 239 | rx_freq[6] = (uint32_t)floor(modf(freq / 77.76e6, &integral) * 0xffffffff + 0.5); 240 | break; 241 | case 36: 242 | case 37: 243 | /* set rx phase increment */ 244 | freq = ntohl(*(uint32_t *)(frame + 1)); 245 | rx_freq[7] = (uint32_t)floor(modf(freq / 77.76e6, &integral) * 0xffffffff + 0.5); 246 | break; 247 | } 248 | } 249 | 250 | void *handler_ep6(void *arg) 251 | { 252 | int i, j, n, m, size; 253 | int data_offset, header_offset; 254 | uint32_t counter; 255 | uint8_t data[6 * 4096]; 256 | uint8_t buffer[25 * 1032]; 257 | uint8_t *pointer; 258 | struct iovec iovec[25][1]; 259 | struct mmsghdr datagram[25]; 260 | uint8_t header[40] = 261 | { 262 | 127, 127, 127, 0, 0, 33, 17, 25, 263 | 127, 127, 127, 8, 0, 0, 0, 0, 264 | 127, 127, 127, 16, 0, 0, 0, 0, 265 | 127, 127, 127, 24, 0, 0, 0, 0, 266 | 127, 127, 127, 32, 66, 66, 66, 66 267 | }; 268 | 269 | memset(iovec, 0, sizeof(iovec)); 270 | memset(datagram, 0, sizeof(datagram)); 271 | 272 | for(i = 0; i < 25; ++i) 273 | { 274 | *(uint32_t *)(buffer + i * 1032 + 0) = 0x0601feef; 275 | iovec[i][0].iov_base = buffer + i * 1032; 276 | iovec[i][0].iov_len = 1032; 277 | datagram[i].msg_hdr.msg_iov = iovec[i]; 278 | datagram[i].msg_hdr.msg_iovlen = 1; 279 | datagram[i].msg_hdr.msg_name = &addr_ep6; 280 | datagram[i].msg_hdr.msg_namelen = sizeof(addr_ep6); 281 | } 282 | 283 | header_offset = 0; 284 | counter = 0; 285 | 286 | *rx_rst &= ~1; 287 | *rx_rst |= 1; 288 | 289 | while(1) 290 | { 291 | if(!enable_thread) break; 292 | 293 | size = receivers * 6 + 2; 294 | n = 504 / size; 295 | m = 256 / n; 296 | 297 | if(*rx_cntr >= 2048) 298 | { 299 | *rx_rst &= ~1; 300 | *rx_rst |= 1; 301 | } 302 | 303 | while(*rx_cntr < m * n * 2) usleep(1000); 304 | 305 | memcpy(data, rx_data, m * n * 96); 306 | 307 | data_offset = 0; 308 | for(i = 0; i < m; ++i) 309 | { 310 | *(uint32_t *)(buffer + i * 1032 + 4) = htonl(counter); 311 | ++counter; 312 | } 313 | 314 | for(i = 0; i < m * 2; ++i) 315 | { 316 | pointer = buffer + i * 516 - i % 2 * 4 + 8; 317 | memcpy(pointer, header + header_offset, 8); 318 | header_offset = header_offset >= 32 ? 0 : header_offset + 8; 319 | 320 | pointer += 8; 321 | memset(pointer, 0, 504); 322 | for(j = 0; j < n; ++j) 323 | { 324 | memcpy(pointer, data + data_offset, size - 2); 325 | data_offset += 48; 326 | pointer += size; 327 | } 328 | } 329 | 330 | sendmmsg(sock_ep2, datagram, m, 0); 331 | } 332 | 333 | active_thread = 0; 334 | 335 | return NULL; 336 | } 337 | -------------------------------------------------------------------------------- /projects/sdr_receiver_wspr_77_76/app/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -O3 -march=armv7-a -mtune=cortex-a9 -mfpu=neon -mfloat-abi=hard -ffast-math -fsingle-precision-constant -mvectorize-with-neon-quad 2 | 3 | all: write-c2-files 4 | 5 | write-c2-files: write-c2-files.c 6 | gcc $(CFLAGS) -o $@ $^ -lm -lconfig 7 | 8 | clean: 9 | rm -f write-c2-files 10 | -------------------------------------------------------------------------------- /projects/sdr_receiver_wspr_77_76/app/decode-wspr.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # CALL and GRID should be specified to enable uploads 4 | CALL= 5 | GRID= 6 | 7 | # version information 8 | VERSION=QMTECH 9 | 10 | JOBS=4 11 | NICE=10 12 | 13 | DIR=`readlink -f $0` 14 | DIR=`dirname $DIR` 15 | 16 | RECORDER=$DIR/write-c2-files 17 | CONFIG=write-c2-files.cfg 18 | 19 | DECODER=/media/mmcblk0p1/apps/wsprd/wsprd 20 | ALLMEPT=ALL_WSPR.TXT 21 | 22 | SLEEP=/media/mmcblk0p1/apps/common_tools/sleep-to-59 23 | 24 | date 25 | 26 | test $DIR/$CONFIG -ot $CONFIG || cp $DIR/$CONFIG $CONFIG 27 | 28 | echo "Sleeping ..." 29 | 30 | $SLEEP 31 | 32 | sleep 1 33 | 34 | date 35 | TIMESTAMP=`date --utc +'%y%m%d_%H%M'` 36 | 37 | echo "Recording ..." 38 | 39 | killall -q $RECORDER 40 | $RECORDER $CONFIG 41 | 42 | echo "Decoding ..." 43 | 44 | for file in wspr_*_$TIMESTAMP.c2 45 | do 46 | while [ `pgrep $DECODER | wc -l` -ge $JOBS ] 47 | do 48 | sleep 1 49 | done 50 | nice -n $NICE $DECODER -JC 2000 $file & 51 | done 52 | 53 | wait 54 | 55 | rm -f wspr_*_$TIMESTAMP.c2 56 | 57 | test -n "$CALL" -a -n "$GRID" -a -s $ALLMEPT || exit 58 | 59 | echo "Uploading ..." 60 | 61 | # sort by highest SNR, then print unique date/time/band/call combinations, 62 | # and then sort them by date/time/frequency 63 | sort -nr -k 3,3 $ALLMEPT | awk '!seen[$1"_"$2"_"int($5)"_"$7] {print} {++seen[$1"_"$2"_"int($5)"_"$7]}' | sort -n -k 1,1 -k 2,2 -k 5,5 -o $ALLMEPT 64 | 65 | curl -sS -m 30 -F allmept=@$ALLMEPT -F call=$CALL -F grid=$GRID -F version=$VERSION http://wsprnet.org/post > /dev/null 66 | 67 | rm -f $ALLMEPT 68 | -------------------------------------------------------------------------------- /projects/sdr_receiver_wspr_77_76/app/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Multiband WSPR receiver 6 | 7 | 8 | 9 | 10 | 19 |
20 |

Multiband WSPR receiver

21 |

The multiband WSPR receiver is ready.

22 |

More details about this application can be found at this link.

23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /projects/sdr_receiver_wspr_77_76/app/start.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | apps_dir=/media/mmcblk0p1/apps 4 | 5 | source $apps_dir/stop.sh 6 | 7 | if grep -q ' ' $apps_dir/sdr_receiver_wspr_77_76/decode-wspr.sh 8 | then 9 | mount -o rw,remount /media/mmcblk0p1 10 | dos2unix $apps_dir/sdr_receiver_wspr_77_76/decode-wspr.sh 11 | mount -o ro,remount /media/mmcblk0p1 12 | fi 13 | 14 | rm -rf /dev/shm/* 15 | 16 | cat $apps_dir/sdr_receiver_wspr_77_76/sdr_receiver_wspr_77_76.bit > /dev/xdevcfg 17 | 18 | $apps_dir/common_tools/setup-adc 19 | $apps_dir/common_tools/enable-adc.sh 20 | 21 | ln -sf $apps_dir/sdr_receiver_wspr_77_76/wspr.cron /etc/cron.d/wspr_77_76 22 | 23 | service dcron restart 24 | -------------------------------------------------------------------------------- /projects/sdr_receiver_wspr_77_76/app/stop.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | if test -e /etc/cron.d/wspr_77_76 4 | then 5 | rm -f /etc/cron.d/wspr_77_76 6 | service dcron restart 7 | killall -q decode-wspr.sh sleep-to-59 write-c2-files wsprd 8 | killall -q update-corr.sh measure-corr measure-level 9 | fi 10 | -------------------------------------------------------------------------------- /projects/sdr_receiver_wspr_77_76/app/write-c2-files.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | FILE *fp; 15 | int fd, offset, length, i, j; 16 | time_t t; 17 | struct tm *gmt; 18 | volatile void *cfg, *sts; 19 | volatile uint64_t *fifo; 20 | volatile uint8_t *rst; 21 | volatile uint16_t *sel, *cntr; 22 | int32_t type = 2; 23 | uint64_t *buffer; 24 | config_t config; 25 | config_setting_t *setting, *element; 26 | char date[12]; 27 | char name[64]; 28 | char zeros[15] = "000000_0000.c2"; 29 | double corr, dialfreq, integral; 30 | double freq[16] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; 31 | 32 | if(argc != 2) 33 | { 34 | fprintf(stderr, "Usage: write-c2-files config_file.cfg\n"); 35 | return EXIT_FAILURE; 36 | } 37 | 38 | config_init(&config); 39 | 40 | if(!config_read_file(&config, argv[1])) 41 | { 42 | fprintf(stderr, "Error on line %d in configuration file.\n", config_error_line(&config)); 43 | return EXIT_FAILURE; 44 | } 45 | 46 | if(!config_lookup_float(&config, "corr", &corr)) 47 | { 48 | fprintf(stderr, "No 'corr' setting in configuration file.\n"); 49 | return EXIT_FAILURE; 50 | } 51 | 52 | if(corr < -100.0 || corr > 100.0) 53 | { 54 | fprintf(stderr, "Wrong 'corr' setting in configuration file.\n"); 55 | return EXIT_FAILURE; 56 | } 57 | 58 | setting = config_lookup(&config, "bands"); 59 | if(setting == NULL) 60 | { 61 | fprintf(stderr, "No 'bands' setting in configuration file.\n"); 62 | return EXIT_FAILURE; 63 | } 64 | 65 | length = config_setting_length(setting); 66 | 67 | if(length > 16) 68 | { 69 | fprintf(stderr, "More than 16 bands in configuration file.\n"); 70 | return EXIT_FAILURE; 71 | } 72 | 73 | if(length < 1) 74 | { 75 | fprintf(stderr, "Less than 1 band in configuration file.\n"); 76 | return EXIT_FAILURE; 77 | } 78 | 79 | for(i = 0; i < length; ++i) 80 | { 81 | element = config_setting_get_elem(setting, i); 82 | 83 | if(!config_setting_lookup_float(element, "freq", &freq[i])) 84 | { 85 | fprintf(stderr, "No 'freq' setting in element %d.\n", i); 86 | return EXIT_FAILURE; 87 | } 88 | } 89 | 90 | t = time(NULL); 91 | if((gmt = gmtime(&t)) == NULL) 92 | { 93 | fprintf(stderr, "Cannot convert time.\n"); 94 | return EXIT_FAILURE; 95 | } 96 | 97 | if((fd = open("/dev/mem", O_RDWR)) < 0) 98 | { 99 | fprintf(stderr, "Cannot open /dev/mem.\n"); 100 | return EXIT_FAILURE; 101 | } 102 | 103 | cfg = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x40000000); 104 | sts = mmap(NULL, sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x41000000); 105 | fifo = mmap(NULL, 32*sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x42000000); 106 | 107 | for(i = 0; i < 16; ++i) 108 | { 109 | *(uint32_t *)(cfg + 4 + i * 4) = (uint32_t)floor(modf((1.0 + 1.0e-6 * corr) * freq[i] / 77.76, &integral) * 0xffffffff + 0.5); 110 | } 111 | 112 | rst = (uint8_t *)(cfg + 0); 113 | cntr = (uint16_t *)(sts + 0); 114 | 115 | *rst &= ~1; 116 | *rst |= 1; 117 | 118 | offset = 0; 119 | buffer = malloc(45000 * 8 * 16); 120 | memset(buffer, 0, 45000 * 8 * 16); 121 | 122 | while(offset < 42000) 123 | { 124 | while(*cntr < 500) usleep(300000); 125 | 126 | for(i = 0; i < 250; ++i) 127 | { 128 | for(j = 0; j < 16; ++j) 129 | { 130 | buffer[j * 45000 + offset + i] = *fifo; 131 | } 132 | } 133 | 134 | offset += 250; 135 | } 136 | 137 | for(i = 0; i < length; ++i) 138 | { 139 | dialfreq = freq[i] - 0.0015; 140 | strftime(date, 12, "%y%m%d_%H%M", gmt); 141 | sprintf(name, "wspr_%d_%d_%s.c2", i, (uint32_t)(dialfreq * 1.0e6), date); 142 | if((fp = fopen(name, "wb")) == NULL) 143 | { 144 | fprintf(stderr, "Cannot open output file %s.\n", name); 145 | return EXIT_FAILURE; 146 | } 147 | fwrite(zeros, 1, 14, fp); 148 | fwrite(&type, 1, 4, fp); 149 | fwrite(&dialfreq, 1, 8, fp); 150 | fwrite(&buffer[i * 45000], 1, 45000 * 8, fp); 151 | fclose(fp); 152 | } 153 | 154 | return EXIT_SUCCESS; 155 | } 156 | -------------------------------------------------------------------------------- /projects/sdr_receiver_wspr_77_76/app/write-c2-files.cfg: -------------------------------------------------------------------------------- 1 | // frequency correction, from -100.0 ppm to +100.0 ppm 2 | corr = 0.0; 3 | 4 | // comma separated list of bands 5 | // trailing commas are not allowed 6 | bands = ( 7 | { freq = 0.137500; }, 8 | { freq = 0.475700; }, 9 | { freq = 1.838100; }, 10 | { freq = 3.570100; }, 11 | { freq = 5.288700; }, 12 | { freq = 5.366200; }, 13 | { freq = 7.040100; }, 14 | { freq = 10.140200; }, 15 | { freq = 14.097100; }, 16 | { freq = 18.106100; }, 17 | { freq = 21.096100; }, 18 | { freq = 24.926100; }, 19 | { freq = 28.126100; }, 20 | { freq = 50.294500; } 21 | ); 22 | -------------------------------------------------------------------------------- /projects/sdr_receiver_wspr_77_76/app/wspr.cron: -------------------------------------------------------------------------------- 1 | 1-59/2 * * * * cd /dev/shm && /media/mmcblk0p1/apps/sdr_receiver_wspr_77_76/decode-wspr.sh >> decode-wspr.log 2>&1 & 2 | #1-59/2 * * * * cd /dev/shm && /media/mmcblk0p1/apps/common_tools/update-corr.sh 77.76 >> update-corr.log 2>&1 & 3 | -------------------------------------------------------------------------------- /projects/sdr_receiver_wspr_77_76/block_design.tcl: -------------------------------------------------------------------------------- 1 | # Create ports 2 | create_bd_port -dir I adc_clk_p_i 3 | create_bd_port -dir I adc_clk_n_i 4 | 5 | create_bd_port -dir I adc_ovr_p_i 6 | create_bd_port -dir I adc_ovr_n_i 7 | 8 | create_bd_port -dir I -from 6 -to 0 adc_dat_p_i 9 | create_bd_port -dir I -from 6 -to 0 adc_dat_n_i 10 | 11 | create_bd_port -dir O adc_spi_sclk 12 | create_bd_port -dir O adc_spi_sdio 13 | create_bd_port -dir O adc_spi_cs 14 | 15 | create_bd_port -dir O adc_oe 16 | 17 | # Create xlconstant 18 | cell xilinx.com:ip:xlconstant const_0 19 | 20 | # Create clk_wiz 21 | cell xilinx.com:ip:clk_wiz pll_0 { 22 | PRIMITIVE PLL 23 | PRIM_IN_FREQ.VALUE_SRC USER 24 | PRIM_IN_FREQ 77.76 25 | PRIM_SOURCE Differential_clock_capable_pin 26 | CLKOUT1_USED true 27 | CLKOUT1_REQUESTED_OUT_FREQ 77.76 28 | USE_RESET false 29 | } { 30 | clk_in1_p adc_clk_p_i 31 | clk_in1_n adc_clk_n_i 32 | } 33 | 34 | # Create processing_system7 35 | cell xilinx.com:ip:processing_system7 ps_0 { 36 | PCW_IMPORT_BOARD_PRESET cfg/qmtech_xc7z020.xml 37 | PCW_USE_M_AXI_GP1 1 38 | } { 39 | M_AXI_GP0_ACLK pll_0/clk_out1 40 | M_AXI_GP1_ACLK pll_0/clk_out1 41 | SPI0_SCLK_O adc_spi_sclk 42 | SPI0_MOSI_O adc_spi_sdio 43 | SPI0_SS_I const_0/dout 44 | SPI0_SS_O adc_spi_cs 45 | } 46 | 47 | # Create port_slicer 48 | cell pavel-demin:user:port_slicer slice_0 { 49 | DIN_WIDTH 64 DIN_FROM 1 DIN_TO 1 50 | } { 51 | din ps_0/GPIO_O 52 | dout adc_oe 53 | } 54 | 55 | # Create all required interconnections 56 | apply_bd_automation -rule xilinx.com:bd_rule:processing_system7 -config { 57 | make_external {FIXED_IO, DDR} 58 | Master Disable 59 | Slave Disable 60 | } [get_bd_cells ps_0] 61 | 62 | # Create proc_sys_reset 63 | cell xilinx.com:ip:proc_sys_reset rst_0 {} { 64 | ext_reset_in const_0/dout 65 | dcm_locked pll_0/locked 66 | slowest_sync_clk pll_0/clk_out1 67 | } 68 | 69 | # ADC 70 | 71 | # Create util_ds_buf 72 | cell xilinx.com:ip:util_ds_buf buf_0 { 73 | C_SIZE 7 74 | C_BUF_TYPE IBUFDS 75 | } { 76 | IBUF_DS_P adc_dat_p_i 77 | IBUF_DS_N adc_dat_n_i 78 | } 79 | 80 | # Create axis_adc_ddr 81 | cell pavel-demin:user:axis_adc_ddr adc_0 { 82 | ADC_DATA_WIDTH 7 83 | } { 84 | aclk pll_0/clk_out1 85 | adc_data buf_0/IBUF_OUT 86 | } 87 | 88 | # HUB 89 | 90 | # Create axi_hub 91 | cell pavel-demin:user:axi_hub hub_0 { 92 | CFG_DATA_WIDTH 544 93 | STS_DATA_WIDTH 32 94 | } { 95 | S_AXI ps_0/M_AXI_GP0 96 | aclk pll_0/clk_out1 97 | aresetn rst_0/peripheral_aresetn 98 | } 99 | 100 | # RX 0 101 | 102 | # Create port_slicer 103 | cell pavel-demin:user:port_slicer rst_slice_0 { 104 | DIN_WIDTH 544 DIN_FROM 7 DIN_TO 0 105 | } { 106 | din hub_0/cfg_data 107 | } 108 | 109 | # Create port_slicer 110 | cell pavel-demin:user:port_slicer cfg_slice_0 { 111 | DIN_WIDTH 544 DIN_FROM 543 DIN_TO 32 112 | } { 113 | din hub_0/cfg_data 114 | } 115 | 116 | module rx_0 { 117 | source projects/sdr_receiver_wspr_77_76/rx.tcl 118 | } { 119 | slice_0/din rst_slice_0/dout 120 | slice_1/din cfg_slice_0/dout 121 | slice_2/din cfg_slice_0/dout 122 | slice_3/din cfg_slice_0/dout 123 | slice_4/din cfg_slice_0/dout 124 | slice_5/din cfg_slice_0/dout 125 | slice_6/din cfg_slice_0/dout 126 | slice_7/din cfg_slice_0/dout 127 | slice_8/din cfg_slice_0/dout 128 | slice_9/din cfg_slice_0/dout 129 | slice_10/din cfg_slice_0/dout 130 | slice_11/din cfg_slice_0/dout 131 | slice_12/din cfg_slice_0/dout 132 | slice_13/din cfg_slice_0/dout 133 | slice_14/din cfg_slice_0/dout 134 | slice_15/din cfg_slice_0/dout 135 | slice_16/din cfg_slice_0/dout 136 | fifo_0/read_count hub_0/sts_data 137 | conv_2/M_AXIS hub_0/S00_AXIS 138 | } 139 | 140 | # PPS and level measurement 141 | 142 | module common_0 { 143 | source projects/common_tools/block_design.tcl 144 | } 145 | -------------------------------------------------------------------------------- /projects/sdr_receiver_wspr_77_76/filters/rx_fir_0.r: -------------------------------------------------------------------------------- 1 | library(signal) 2 | 3 | # CIC filter parameters 4 | R <- 320 # Decimation factor 5 | M <- 1 # Differential delay 6 | N <- 6 # Number of stages 7 | 8 | Fc <- 0.247 # cutoff frequency 9 | htbw <- 0.005 # half transition bandwidth 10 | 11 | # fir2 parameters 12 | k <- kaiserord(c(Fc-htbw, Fc+htbw), c(1, 0), 1/(2^16), 1) 13 | L <- k$n # Filter order 14 | Beta <- k$beta # Kaiser window parameter 15 | 16 | # FIR filter design using fir2 17 | s <- 0.001 # Step size 18 | fp <- seq(0.0, Fc-htbw, by=s) # Pass band frequency samples 19 | fs <- seq(Fc+htbw, 0.5, by=s) # Stop band frequency samples 20 | f <- c(fp, fs)*2 # Normalized frequency samples; 0<=f<=1 21 | 22 | Mp <- matrix(1, 1, length(fp)) # Pass band response; Mp[1]=1 23 | Mp[-1] <- abs(M*R*sin(pi*fp[-1]/R)/sin(pi*M*fp[-1]))^N 24 | Mf <- c(Mp, matrix(0, 1, length(fs))) 25 | 26 | h <- fir2(L, f, Mf, window=kaiser(L+1, Beta)) 27 | 28 | h <- h / sum(h) 29 | 30 | # Print filter coefficients 31 | paste(sprintf("%.10e", h), collapse=", ") 32 | 33 | fh <- freqz(h) 34 | 35 | op <- par(mfrow = c(2, 1)) 36 | 37 | plot(f, 20*log10(Mf), type = "b", ylab = "dB", xlab = "Frequency", xlim = c(0.51, 0.54), ylim = c(-125, 5)) 38 | lines(fh$f / pi, 20*log10(abs(fh$h)), col = "blue") 39 | grid() 40 | 41 | plot(f, 20*log10(Mf), type = "b", ylab = "dB", xlab = "Frequency", xlim = c(0.46, 0.49), ylim = c(-5, 5)) 42 | lines(fh$f / pi, 20*log10(abs(fh$h)), col = "blue") 43 | grid() 44 | 45 | par(op) 46 | -------------------------------------------------------------------------------- /projects/sdr_receiver_wspr_77_76/ports.xdc: -------------------------------------------------------------------------------- 1 | # clock 2 | 3 | set_property IOSTANDARD LVDS_25 [get_ports adc_clk_p_i] 4 | set_property IOSTANDARD LVDS_25 [get_ports adc_clk_n_i] 5 | 6 | set_property DIFF_TERM TRUE [get_ports adc_clk_p_i] 7 | set_property DIFF_TERM TRUE [get_ports adc_clk_n_i] 8 | 9 | set_property PACKAGE_PIN Y19 [get_ports adc_clk_p_i] 10 | set_property PACKAGE_PIN AA19 [get_ports adc_clk_n_i] 11 | 12 | # overrange 13 | 14 | set_property IOSTANDARD LVDS_25 [get_ports {adc_ovr_p_i}] 15 | set_property IOSTANDARD LVDS_25 [get_ports {adc_ovr_n_i}] 16 | 17 | set_property DIFF_TERM TRUE [get_ports {adc_ovr_p_i]}] 18 | set_property DIFF_TERM TRUE [get_ports {adc_ovr_n_i}] 19 | 20 | set_property PACKAGE_PIN U17 [get_ports {adc_ovr_p_i}] 21 | set_property PACKAGE_PIN V17 [get_ports {adc_ovr_n_i}] 22 | 23 | # data 24 | 25 | set_property IOSTANDARD LVDS_25 [get_ports {adc_dat_p_i[*]}] 26 | set_property IOSTANDARD LVDS_25 [get_ports {adc_dat_n_i[*]}] 27 | 28 | set_property DIFF_TERM TRUE [get_ports {adc_dat_p_i[*]}] 29 | set_property DIFF_TERM TRUE [get_ports {adc_dat_n_i[*]}] 30 | 31 | set_property PACKAGE_PIN AA17 [get_ports {adc_dat_p_i[0]}] 32 | set_property PACKAGE_PIN AB17 [get_ports {adc_dat_n_i[0]}] 33 | 34 | set_property PACKAGE_PIN AA16 [get_ports {adc_dat_p_i[1]}] 35 | set_property PACKAGE_PIN AB16 [get_ports {adc_dat_n_i[1]}] 36 | 37 | set_property PACKAGE_PIN AB14 [get_ports {adc_dat_p_i[2]}] 38 | set_property PACKAGE_PIN AB15 [get_ports {adc_dat_n_i[2]}] 39 | 40 | set_property PACKAGE_PIN Y18 [get_ports {adc_dat_p_i[3]}] 41 | set_property PACKAGE_PIN AA18 [get_ports {adc_dat_n_i[3]}] 42 | 43 | set_property PACKAGE_PIN W17 [get_ports {adc_dat_p_i[4]}] 44 | set_property PACKAGE_PIN W18 [get_ports {adc_dat_n_i[4]}] 45 | 46 | set_property PACKAGE_PIN W16 [get_ports {adc_dat_p_i[5]}] 47 | set_property PACKAGE_PIN Y16 [get_ports {adc_dat_n_i[5]}] 48 | 49 | set_property PACKAGE_PIN Y14 [get_ports {adc_dat_p_i[6]}] 50 | set_property PACKAGE_PIN AA14 [get_ports {adc_dat_n_i[6]}] 51 | 52 | # SPI 53 | 54 | set_property IOSTANDARD LVCMOS25 [get_ports adc_spi_*] 55 | 56 | set_property PACKAGE_PIN AA13 [get_ports adc_spi_sclk] 57 | set_property PACKAGE_PIN Y13 [get_ports adc_spi_sdio] 58 | set_property PACKAGE_PIN U15 [get_ports adc_spi_cs] 59 | 60 | # output enable 61 | 62 | set_property IOSTANDARD LVCMOS25 [get_ports adc_oe] 63 | 64 | set_property PACKAGE_PIN Y20 [get_ports adc_oe] 65 | -------------------------------------------------------------------------------- /scripts/alpine.sh: -------------------------------------------------------------------------------- 1 | alpine_url=http://dl-cdn.alpinelinux.org/alpine/v3.20 2 | 3 | tools_tar=apk-tools-static-2.14.4-r1.apk 4 | tools_url=$alpine_url/main/armv7/$tools_tar 5 | 6 | firmware_tar=linux-firmware-other-20240811-r0.apk 7 | firmware_url=$alpine_url/main/armv7/$firmware_tar 8 | 9 | linux_dir=tmp/linux-6.6 10 | linux_ver=6.6.44-xilinx 11 | 12 | modules_dir=alpine-modloop/lib/modules/$linux_ver 13 | 14 | passwd=changeme 15 | 16 | test -f $tools_tar || curl -L $tools_url -o $tools_tar 17 | 18 | test -f $firmware_tar || curl -L $firmware_url -o $firmware_tar 19 | 20 | for tar in linux-firmware-ath9k_htc-20240811-r0.apk linux-firmware-brcm-20240811-r0.apk linux-firmware-cypress-20240811-r0.apk linux-firmware-rtlwifi-20240811-r0.apk 21 | do 22 | url=$alpine_url/main/armv7/$tar 23 | test -f $tar || curl -L $url -o $tar 24 | done 25 | 26 | mkdir alpine-apk 27 | tar -zxf $tools_tar --directory=alpine-apk --warning=no-unknown-keyword 28 | 29 | mkdir -p $modules_dir/kernel 30 | 31 | 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 32 | 33 | cp $linux_dir/modules.order $linux_dir/modules.builtin $modules_dir/ 34 | 35 | depmod -a -b alpine-modloop $linux_ver 36 | 37 | tar -zxf $firmware_tar --directory=alpine-modloop/lib/modules --warning=no-unknown-keyword --strip-components=1 --wildcards lib/firmware/ar* lib/firmware/rt* 38 | 39 | for tar in linux-firmware-ath9k_htc-20240811-r0.apk linux-firmware-brcm-20240811-r0.apk linux-firmware-cypress-20240811-r0.apk linux-firmware-rtlwifi-20240811-r0.apk 40 | do 41 | tar -zxf $tar --directory=alpine-modloop/lib/modules --warning=no-unknown-keyword --strip-components=1 42 | done 43 | 44 | mksquashfs alpine-modloop/lib modloop -b 1048576 -comp xz -Xdict-size 100% 45 | 46 | rm -rf alpine-modloop 47 | 48 | root_dir=alpine-root 49 | 50 | mkdir -p $root_dir/usr/bin 51 | cp /usr/bin/qemu-arm-static $root_dir/usr/bin/ 52 | 53 | mkdir -p $root_dir/etc 54 | cp /etc/resolv.conf $root_dir/etc/ 55 | 56 | mkdir -p $root_dir/etc/apk 57 | mkdir -p $root_dir/media/mmcblk0p1/cache 58 | ln -s /media/mmcblk0p1/cache $root_dir/etc/apk/cache 59 | 60 | cp -r alpine/etc $root_dir/ 61 | cp -r alpine/apps $root_dir/media/mmcblk0p1/ 62 | 63 | projects="common_tools led_blinker_77_76 sdr_receiver_77_76 sdr_receiver_ft8_77_76 sdr_receiver_hpsdr_77_76 sdr_receiver_wspr_77_76" 64 | 65 | for p in $projects 66 | do 67 | mkdir -p $root_dir/media/mmcblk0p1/apps/$p 68 | cp -r projects/$p/server/* $root_dir/media/mmcblk0p1/apps/$p/ 69 | cp -r projects/$p/app/* $root_dir/media/mmcblk0p1/apps/$p/ 70 | cp tmp/$p.bit $root_dir/media/mmcblk0p1/apps/$p/ 71 | done 72 | 73 | cp -r alpine-apk/sbin $root_dir/ 74 | 75 | chroot $root_dir /sbin/apk.static --repository $alpine_url/main --update-cache --allow-untrusted --initdb add alpine-base 76 | 77 | echo $alpine_url/main > $root_dir/etc/apk/repositories 78 | echo $alpine_url/community >> $root_dir/etc/apk/repositories 79 | 80 | chroot $root_dir /bin/sh <<- EOF_CHROOT 81 | 82 | apk update 83 | apk add openssh 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 screen 84 | 85 | rc-update add bootmisc boot 86 | rc-update add hostname boot 87 | rc-update add swclock boot 88 | rc-update add sysctl boot 89 | rc-update add syslog boot 90 | rc-update add seedrng boot 91 | 92 | rc-update add killprocs shutdown 93 | rc-update add mount-ro shutdown 94 | rc-update add savecache shutdown 95 | 96 | rc-update add devfs sysinit 97 | rc-update add dmesg sysinit 98 | rc-update add mdev sysinit 99 | rc-update add hwdrivers sysinit 100 | rc-update add modloop sysinit 101 | 102 | rc-update add avahi-daemon default 103 | rc-update add chronyd default 104 | rc-update add dhcpcd default 105 | rc-update add local default 106 | rc-update add dcron default 107 | rc-update add sshd default 108 | 109 | mkdir -p etc/runlevels/wifi 110 | rc-update -s add default wifi 111 | 112 | rc-update add iptables wifi 113 | rc-update add dnsmasq wifi 114 | rc-update add hostapd wifi 115 | 116 | sed -i 's/^SAVE_ON_STOP=.*/SAVE_ON_STOP="no"/;s/^IPFORWARD=.*/IPFORWARD="yes"/' etc/conf.d/iptables 117 | 118 | sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' etc/ssh/sshd_config 119 | 120 | echo root:$passwd | chpasswd 121 | 122 | hostname qmtech-xc7z020 123 | 124 | sed -i 's/^# LBU_MEDIA=.*/LBU_MEDIA=mmcblk0p1/' etc/lbu/lbu.conf 125 | 126 | cat <<- EOF_CAT > root/.profile 127 | alias rw='mount -o rw,remount /media/mmcblk0p1' 128 | alias ro='mount -o ro,remount /media/mmcblk0p1' 129 | EOF_CAT 130 | 131 | ln -s /media/mmcblk0p1/apps root/apps 132 | ln -s /media/mmcblk0p1/wifi root/wifi 133 | 134 | lbu add root 135 | lbu delete etc/resolv.conf 136 | lbu delete etc/cron.d/ft8_77_76 137 | lbu delete etc/cron.d/wspr_77_76 138 | lbu delete root/.ash_history 139 | 140 | lbu commit -d 141 | 142 | apk add make gcc gfortran linux-headers 143 | 144 | ft8d_dir=/media/mmcblk0p1/apps/ft8d 145 | ft8d_tar=/media/mmcblk0p1/apps/ft8d.tar.gz 146 | ft8d_url=https://github.com/pavel-demin/ft8d/archive/master.tar.gz 147 | 148 | curl -L \$ft8d_url -o \$ft8d_tar 149 | mkdir -p \$ft8d_dir 150 | tar -zxf \$ft8d_tar --strip-components=1 --directory=\$ft8d_dir 151 | rm \$ft8d_tar 152 | make -C \$ft8d_dir 153 | 154 | wsprd_dir=/media/mmcblk0p1/apps/wsprd 155 | wsprd_tar=/media/mmcblk0p1/apps/wsprd.tar.gz 156 | wsprd_url=https://github.com/pavel-demin/wsprd/archive/master.tar.gz 157 | 158 | curl -L \$wsprd_url -o \$wsprd_tar 159 | mkdir -p \$wsprd_dir 160 | tar -zxf \$wsprd_tar --strip-components=1 --directory=\$wsprd_dir 161 | rm \$wsprd_tar 162 | make -C \$wsprd_dir 163 | 164 | for p in server $projects 165 | do 166 | make -C /media/mmcblk0p1/apps/\$p clean 167 | make -C /media/mmcblk0p1/apps/\$p 168 | done 169 | 170 | EOF_CHROOT 171 | 172 | cp -r $root_dir/media/mmcblk0p1/apps . 173 | cp -r $root_dir/media/mmcblk0p1/cache . 174 | cp $root_dir/media/mmcblk0p1/qmtech-xc7z020.apkovl.tar.gz . 175 | 176 | cp -r alpine/wifi . 177 | 178 | hostname -F /etc/hostname 179 | 180 | rm -rf $root_dir alpine-apk 181 | 182 | zip -r qmtech-xc7z020-alpine-3.20-armv7-`date +%Y%m%d`.zip apps boot.bin cache mac.txt modloop qmtech-xc7z020.apkovl.tar.gz wifi 183 | 184 | rm -rf apps cache modloop qmtech-xc7z020.apkovl.tar.gz wifi 185 | -------------------------------------------------------------------------------- /scripts/bitstream.tcl: -------------------------------------------------------------------------------- 1 | 2 | set project_name [lindex $argv 0] 3 | 4 | open_project tmp/$project_name.xpr 5 | 6 | if {[get_property PROGRESS [get_runs impl_1]] != "100%"} { 7 | launch_runs impl_1 8 | wait_on_run impl_1 9 | } 10 | 11 | open_run [get_runs impl_1] 12 | 13 | set_property BITSTREAM.GENERAL.COMPRESS TRUE [current_design] 14 | 15 | write_bitstream -force -file tmp/$project_name.bit 16 | 17 | close_project 18 | -------------------------------------------------------------------------------- /scripts/core.tcl: -------------------------------------------------------------------------------- 1 | 2 | set core_name [lindex $argv 0] 3 | 4 | set part_name [lindex $argv 1] 5 | 6 | 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 7 | 8 | create_project -part $part_name $core_name tmp/cores 9 | 10 | add_files -norecurse cores/$core_name.v 11 | 12 | set_property TOP $core_name [current_fileset] 13 | 14 | set files [glob -nocomplain modules/*.v] 15 | if {[llength $files] > 0} { 16 | add_files -norecurse $files 17 | } 18 | 19 | ipx::package_project -root_dir tmp/cores/$core_name 20 | 21 | set core [ipx::current_core] 22 | 23 | set_property VERSION {1.0} $core 24 | set_property NAME $core_name $core 25 | set_property LIBRARY {user} $core 26 | set_property VENDOR {pavel-demin} $core 27 | set_property VENDOR_DISPLAY_NAME {Pavel Demin} $core 28 | set_property COMPANY_URL {https://github.com/pavel-demin/qmtech-xc7z020-notes} $core 29 | set_property SUPPORTED_FAMILIES {zynq Production} $core 30 | 31 | ipx::create_xgui_files $core 32 | ipx::update_checksums $core 33 | ipx::save_core $core 34 | 35 | close_project 36 | -------------------------------------------------------------------------------- /scripts/devicetree.tcl: -------------------------------------------------------------------------------- 1 | 2 | set project_name [lindex $argv 0] 3 | 4 | set proc_name [lindex $argv 1] 5 | 6 | set repo_path [lindex $argv 2] 7 | 8 | set hard_path tmp/$project_name.hard 9 | set tree_path tmp/$project_name.tree 10 | 11 | file mkdir $hard_path 12 | file copy -force tmp/$project_name.xsa $hard_path/$project_name.xsa 13 | 14 | hsi set_repo_path $repo_path 15 | 16 | hsi open_hw_design $hard_path/$project_name.xsa 17 | hsi create_sw_design -proc $proc_name -os device_tree devicetree 18 | 19 | hsi generate_target -dir $tree_path 20 | 21 | hsi close_sw_design [hsi current_sw_design] 22 | hsi close_hw_design [hsi current_hw_design] 23 | -------------------------------------------------------------------------------- /scripts/fsbl.tcl: -------------------------------------------------------------------------------- 1 | 2 | set project_name [lindex $argv 0] 3 | 4 | set proc_name [lindex $argv 1] 5 | 6 | set hard_path tmp/$project_name.hard 7 | set fsbl_path tmp/$project_name.fsbl 8 | 9 | file mkdir $hard_path 10 | file copy -force tmp/$project_name.xsa $hard_path/$project_name.xsa 11 | 12 | hsi open_hw_design $hard_path/$project_name.xsa 13 | hsi create_sw_design -proc $proc_name -os standalone fsbl 14 | 15 | hsi add_library xilffs 16 | hsi add_library xilrsa 17 | 18 | hsi generate_app -proc $proc_name -app zynq_fsbl -dir $fsbl_path -compile 19 | 20 | hsi close_hw_design [hsi current_hw_design] 21 | -------------------------------------------------------------------------------- /scripts/hwdef.tcl: -------------------------------------------------------------------------------- 1 | 2 | set project_name [lindex $argv 0] 3 | 4 | open_project tmp/$project_name.xpr 5 | 6 | write_hw_platform -fixed -force -file tmp/$project_name.xsa 7 | 8 | close_project 9 | -------------------------------------------------------------------------------- /scripts/project.tcl: -------------------------------------------------------------------------------- 1 | 2 | package require fileutil 3 | 4 | set project_name [lindex $argv 0] 5 | 6 | set part_name [lindex $argv 1] 7 | 8 | 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 9 | 10 | create_project -part $part_name $project_name tmp 11 | 12 | set_property IP_REPO_PATHS tmp/cores [current_project] 13 | 14 | update_ip_catalog 15 | 16 | proc wire {name1 name2} { 17 | set port1 [get_bd_pins $name1] 18 | set port2 [get_bd_pins $name2] 19 | if {[llength $port1] == 1 && [llength $port2] == 1} { 20 | connect_bd_net $port1 $port2 21 | return 22 | } 23 | set port1 [get_bd_intf_pins $name1] 24 | set port2 [get_bd_intf_pins $name2] 25 | if {[llength $port1] == 1 && [llength $port2] == 1} { 26 | connect_bd_intf_net $port1 $port2 27 | return 28 | } 29 | error "** ERROR: can't connect $name1 and $name2" 30 | } 31 | 32 | proc cell {cell_vlnv cell_name {cell_props {}} {cell_ports {}}} { 33 | set cell [create_bd_cell -type ip -vlnv $cell_vlnv $cell_name] 34 | set prop_list {} 35 | foreach {prop_name prop_value} [uplevel 1 [list subst $cell_props]] { 36 | lappend prop_list CONFIG.$prop_name $prop_value 37 | } 38 | if {[llength $prop_list] > 1} { 39 | set_property -dict $prop_list $cell 40 | } 41 | foreach {local_name remote_name} [uplevel 1 [list subst $cell_ports]] { 42 | wire $cell_name/$local_name $remote_name 43 | } 44 | } 45 | 46 | proc module {module_name module_body {module_ports {}}} { 47 | set instance [current_bd_instance .] 48 | current_bd_instance [create_bd_cell -type hier $module_name] 49 | eval $module_body 50 | current_bd_instance $instance 51 | foreach {local_name remote_name} [uplevel 1 [list subst $module_ports]] { 52 | wire $module_name/$local_name $remote_name 53 | } 54 | } 55 | 56 | proc design {design_name design_body} { 57 | set design [current_bd_design] 58 | create_bd_design $design_name 59 | eval $design_body 60 | validate_bd_design 61 | save_bd_design 62 | current_bd_design $design 63 | } 64 | 65 | proc container {container_name container_designs {container_ports {}}} { 66 | set reference [lindex $container_designs 0] 67 | set container [create_bd_cell -type container -reference $reference $container_name] 68 | foreach {local_name remote_name} [uplevel 1 [list subst $container_ports]] { 69 | wire $container_name/$local_name $remote_name 70 | } 71 | set list {} 72 | foreach item $container_designs { 73 | lappend list $item.bd 74 | } 75 | set list [join $list :] 76 | set_property CONFIG.ENABLE_DFX true $container 77 | set_property CONFIG.LIST_SYNTH_BD $list $container 78 | set_property CONFIG.LIST_SIM_BD $list $container 79 | } 80 | 81 | proc addr {offset range port master} { 82 | set object [get_bd_intf_pins $port] 83 | set segment [get_bd_addr_segs -of_objects $object] 84 | set config [list Master $master Clk Auto] 85 | apply_bd_automation -rule xilinx.com:bd_rule:axi4 -config $config $object 86 | assign_bd_address -offset $offset -range $range $segment 87 | } 88 | 89 | create_bd_design system 90 | 91 | source cfg/ports.tcl 92 | source projects/$project_name/block_design.tcl 93 | 94 | rename wire {} 95 | rename cell {} 96 | rename module {} 97 | rename design {} 98 | rename container {} 99 | rename addr {} 100 | 101 | set system [get_files system.bd] 102 | 103 | set_property SYNTH_CHECKPOINT_MODE None $system 104 | 105 | generate_target all $system 106 | make_wrapper -files $system -top 107 | 108 | foreach ext {srcs gen} { 109 | set files [fileutil::findByPattern tmp/$project_name.$ext system_wrapper.v] 110 | if {[llength $files] > 0} { 111 | add_files -norecurse $files 112 | break 113 | } 114 | } 115 | 116 | set_property TOP system_wrapper [current_fileset] 117 | 118 | set files [glob -nocomplain cfg/*.mem projects/$project_name/*.v projects/$project_name/*.sv] 119 | if {[llength $files] > 0} { 120 | add_files -norecurse $files 121 | } 122 | 123 | set files [glob -nocomplain cfg/*.xdc projects/$project_name/*.xdc] 124 | if {[llength $files] > 0} { 125 | add_files -norecurse -fileset constrs_1 $files 126 | } 127 | 128 | set_property STRATEGY Flow_PerfOptimized_high [get_runs synth_1] 129 | set_property STRATEGY Performance_ExploreWithRemap [get_runs impl_1] 130 | 131 | close_project 132 | --------------------------------------------------------------------------------