From c59bdec4f20070b2e7ae55c519833e3255615915 Mon Sep 17 00:00:00 2001 From: d18c7db Date: Tue, 30 May 2023 19:47:27 +0200 Subject: [PATCH] Unified fpga folders --- .gitignore | 12 +- armsrc/Makefile | 3 - armsrc/fpgaloader.c | 20 +- common_arm/Makefile.common | 2 +- common_arm/Makefile.hal | 9 + fpga-xc2s30/Makefile | 60 -- fpga-xc2s30/fpga.ucf | 54 -- fpga-xc2s30/fpga_felica.bit | Bin 42179 -> 0 bytes fpga-xc2s30/fpga_felica.v | 240 ------- fpga-xc2s30/fpga_hf.bit | Bin 42175 -> 0 bytes fpga-xc2s30/fpga_hf.v | 255 -------- fpga-xc2s30/fpga_hf_15.bit | Bin 42178 -> 0 bytes fpga-xc2s30/fpga_hf_15.v | 233 ------- fpga-xc2s30/fpga_lf.bit | Bin 42175 -> 0 bytes fpga-xc2s30/fpga_lf.v | 245 -------- fpga-xc2s30/go.bat | 68 -- fpga-xc2s30/xst_felica.scr | 1 - fpga-xc2s30/xst_hf.scr | 1 - fpga-xc2s30/xst_hf_15.scr | 1 - fpga-xc2s30/xst_lf.scr | 1 - fpga-xc3s100e/.gitignore | 68 -- fpga-xc3s100e/clk_divider.v | 25 - fpga-xc3s100e/compile.sh | 9 - fpga-xc3s100e/define.v | 49 -- fpga-xc3s100e/fpga.ucf | 56 -- fpga-xc3s100e/fpga_hf.bit | Bin 72742 -> 0 bytes fpga-xc3s100e/fpga_hfmod.v | 193 ------ fpga-xc3s100e/fpga_lfmod.v | 236 ------- fpga-xc3s100e/hi_flite.v | 368 ----------- fpga-xc3s100e/hi_get_trace.v | 164 ----- fpga-xc3s100e/hi_iso14443a.v | 584 ------------------ fpga-xc3s100e/hi_reader.v | 335 ---------- fpga-xc3s100e/hi_simulate.v | 152 ----- fpga-xc3s100e/hi_sniffer.v | 50 -- fpga-xc3s100e/iseproj/fpga_hf/fpga_hf.ise | Bin 257463 -> 0 bytes fpga-xc3s100e/iseproj/fpga_hf/fpga_hf.tcl | 479 -------------- fpga-xc3s100e/lf_edge_detect.v | 77 --- fpga-xc3s100e/lo_adc.v | 91 --- fpga-xc3s100e/lo_edge_detect.v | 70 --- fpga-xc3s100e/lo_passthru.v | 29 - fpga-xc3s100e/lo_read.v | 74 --- fpga-xc3s100e/lp20khz_1MSa_iir_filter.v | 81 --- fpga-xc3s100e/min_max_tracker.v | 65 -- fpga-xc3s100e/util.v | 27 - fpga/Makefile | 221 +++++++ {fpga-xc2s30 => fpga}/clk_divider.v | 7 +- fpga/define.v | 155 +++++ .../fpga_icopyx_felica.bit | 0 fpga/fpga_icopyx_hf.bit | Bin 0 -> 72749 bytes fpga/fpga_icopyx_hf.v | 227 +++++++ .../fpga_lf.bit => fpga/fpga_icopyx_hf_15.bit | 0 fpga/fpga_icopyx_lf.bit | 0 fpga/fpga_icopyx_lf.v | 218 +++++++ .../fpga_allinone.v => fpga/fpga_icopyx_top.v | 80 ++- fpga/fpga_pm3_felica.bit | Bin 0 -> 42176 bytes fpga/fpga_pm3_hf.bit | Bin 0 -> 42172 bytes fpga/fpga_pm3_hf_15.bit | Bin 0 -> 42175 bytes fpga/fpga_pm3_lf.bit | Bin 0 -> 42172 bytes fpga/fpga_pm3_top.v | 438 +++++++++++++ {fpga-xc2s30 => fpga}/hi_flite.v | 70 +-- {fpga-xc2s30 => fpga}/hi_get_trace.v | 40 +- {fpga-xc2s30 => fpga}/hi_iso14443a.v | 55 +- {fpga-xc2s30 => fpga}/hi_reader.v | 42 +- {fpga-xc2s30 => fpga}/hi_reader_15.v | 43 +- {fpga-xc2s30 => fpga}/hi_simulate.v | 37 +- {fpga-xc2s30 => fpga}/hi_sniffer.v | 49 +- {fpga-xc2s30 => fpga}/lf_edge_detect.v | 49 +- {fpga-xc2s30 => fpga}/lo_adc.v | 50 +- {fpga-xc2s30 => fpga}/lo_edge_detect.v | 56 +- {fpga-xc2s30 => fpga}/lo_passthru.v | 29 +- {fpga-xc2s30 => fpga}/lo_read.v | 36 +- {fpga-xc2s30 => fpga}/lo_simulate.v | 42 +- .../lp20khz_1MSa_iir_filter.v | 7 +- {fpga-xc2s30 => fpga}/min_max_tracker.v | 9 +- fpga/mux16.v | 50 ++ {fpga-xc3s100e => fpga}/mux2_onein.v | 13 +- {fpga-xc3s100e => fpga}/mux2_oneout.v | 13 +- fpga-xc2s30/util.v => fpga/mux8.v | 30 +- {fpga-xc2s30 => fpga}/tests/Makefile | 0 .../tests/plot_edgedetect.py | 0 {fpga-xc2s30 => fpga/tests}/sim.tcl | 0 .../pcf7931_read_1MSA_data.filtered.gold | 0 .../tb_data/pcf7931_read_1MSA_data.high.gold | 0 .../tb_data/pcf7931_read_1MSA_data.highz.gold | 0 .../tests/tb_data/pcf7931_read_1MSA_data.in | 0 .../tb_data/pcf7931_read_1MSA_data.low.gold | 0 .../tb_data/pcf7931_read_1MSA_data.lowz.gold | 0 .../tb_data/pcf7931_read_1MSA_data.max.gold | Bin .../tb_data/pcf7931_read_1MSA_data.min.gold | 0 .../tb_data/pcf7931_read_1MSA_data.state.gold | Bin .../tests/tb_data/pcf7931_read_1MSA_data.time | Bin .../pcf7931_read_1MSA_data.toggle.gold | Bin ...pcf7931_write1byte_1MSA_data.filtered.gold | 0 .../pcf7931_write1byte_1MSA_data.high.gold | 0 .../pcf7931_write1byte_1MSA_data.highz.gold | 0 .../tb_data/pcf7931_write1byte_1MSA_data.in | 0 .../pcf7931_write1byte_1MSA_data.low.gold | 0 .../pcf7931_write1byte_1MSA_data.lowz.gold | 0 .../pcf7931_write1byte_1MSA_data.max.gold | Bin .../pcf7931_write1byte_1MSA_data.min.gold | 0 .../pcf7931_write1byte_1MSA_data.state.gold | Bin .../tb_data/pcf7931_write1byte_1MSA_data.time | Bin .../pcf7931_write1byte_1MSA_data.toggle.gold | Bin .../tests/tb_lf_edge_detect.v | 0 .../tests/tb_lp20khz_1MSa_iir_filter.v | 0 .../tests/tb_min_max_tracker.v | 0 {fpga-xc2s30 => fpga/tests}/testbed_fpga.v | 0 .../tests}/testbed_hi_read_tx.v | 0 .../tests}/testbed_hi_simulate.v | 0 {fpga-xc2s30 => fpga/tests}/testbed_lo_read.v | 0 .../tests}/testbed_lo_simulate.v | 0 fpga/xc2s30-5-vq100.ucf | 45 ++ fpga/xc3s100e-4-vq100.ucf | 48 ++ tools/fpga_compress/fpga_compress.c | 24 +- 114 files changed, 1854 insertions(+), 4816 deletions(-) delete mode 100644 fpga-xc2s30/Makefile delete mode 100644 fpga-xc2s30/fpga.ucf delete mode 100644 fpga-xc2s30/fpga_felica.bit delete mode 100644 fpga-xc2s30/fpga_felica.v delete mode 100644 fpga-xc2s30/fpga_hf.bit delete mode 100644 fpga-xc2s30/fpga_hf.v delete mode 100644 fpga-xc2s30/fpga_hf_15.bit delete mode 100644 fpga-xc2s30/fpga_hf_15.v delete mode 100644 fpga-xc2s30/fpga_lf.bit delete mode 100644 fpga-xc2s30/fpga_lf.v delete mode 100644 fpga-xc2s30/go.bat delete mode 100644 fpga-xc2s30/xst_felica.scr delete mode 100644 fpga-xc2s30/xst_hf.scr delete mode 100644 fpga-xc2s30/xst_hf_15.scr delete mode 100644 fpga-xc2s30/xst_lf.scr delete mode 100644 fpga-xc3s100e/.gitignore delete mode 100644 fpga-xc3s100e/clk_divider.v delete mode 100755 fpga-xc3s100e/compile.sh delete mode 100644 fpga-xc3s100e/define.v delete mode 100644 fpga-xc3s100e/fpga.ucf delete mode 100644 fpga-xc3s100e/fpga_hf.bit delete mode 100644 fpga-xc3s100e/fpga_hfmod.v delete mode 100644 fpga-xc3s100e/fpga_lfmod.v delete mode 100644 fpga-xc3s100e/hi_flite.v delete mode 100644 fpga-xc3s100e/hi_get_trace.v delete mode 100644 fpga-xc3s100e/hi_iso14443a.v delete mode 100644 fpga-xc3s100e/hi_reader.v delete mode 100644 fpga-xc3s100e/hi_simulate.v delete mode 100644 fpga-xc3s100e/hi_sniffer.v delete mode 100644 fpga-xc3s100e/iseproj/fpga_hf/fpga_hf.ise delete mode 100644 fpga-xc3s100e/iseproj/fpga_hf/fpga_hf.tcl delete mode 100644 fpga-xc3s100e/lf_edge_detect.v delete mode 100644 fpga-xc3s100e/lo_adc.v delete mode 100644 fpga-xc3s100e/lo_edge_detect.v delete mode 100644 fpga-xc3s100e/lo_passthru.v delete mode 100644 fpga-xc3s100e/lo_read.v delete mode 100644 fpga-xc3s100e/lp20khz_1MSa_iir_filter.v delete mode 100644 fpga-xc3s100e/min_max_tracker.v delete mode 100644 fpga-xc3s100e/util.v create mode 100644 fpga/Makefile rename {fpga-xc2s30 => fpga}/clk_divider.v (91%) create mode 100644 fpga/define.v rename fpga-xc3s100e/fpga_felica.bit => fpga/fpga_icopyx_felica.bit (100%) create mode 100644 fpga/fpga_icopyx_hf.bit create mode 100644 fpga/fpga_icopyx_hf.v rename fpga-xc3s100e/fpga_lf.bit => fpga/fpga_icopyx_hf_15.bit (100%) create mode 100644 fpga/fpga_icopyx_lf.bit create mode 100644 fpga/fpga_icopyx_lf.v rename fpga-xc3s100e/fpga_allinone.v => fpga/fpga_icopyx_top.v (61%) create mode 100644 fpga/fpga_pm3_felica.bit create mode 100644 fpga/fpga_pm3_hf.bit create mode 100644 fpga/fpga_pm3_hf_15.bit create mode 100644 fpga/fpga_pm3_lf.bit create mode 100644 fpga/fpga_pm3_top.v rename {fpga-xc2s30 => fpga}/hi_flite.v (92%) rename {fpga-xc2s30 => fpga}/hi_get_trace.v (86%) rename {fpga-xc2s30 => fpga}/hi_iso14443a.v (97%) rename {fpga-xc2s30 => fpga}/hi_reader.v (95%) rename {fpga-xc2s30 => fpga}/hi_reader_15.v (96%) rename {fpga-xc2s30 => fpga}/hi_simulate.v (91%) rename {fpga-xc2s30 => fpga}/hi_sniffer.v (69%) rename {fpga-xc2s30 => fpga}/lf_edge_detect.v (72%) rename {fpga-xc2s30 => fpga}/lo_adc.v (74%) rename {fpga-xc2s30 => fpga}/lo_edge_detect.v (67%) rename {fpga-xc2s30 => fpga}/lo_passthru.v (82%) rename {fpga-xc2s30 => fpga}/lo_read.v (80%) rename {fpga-xc2s30 => fpga}/lo_simulate.v (79%) rename {fpga-xc2s30 => fpga}/lp20khz_1MSa_iir_filter.v (96%) rename {fpga-xc2s30 => fpga}/min_max_tracker.v (95%) create mode 100644 fpga/mux16.v rename {fpga-xc3s100e => fpga}/mux2_onein.v (70%) rename {fpga-xc3s100e => fpga}/mux2_oneout.v (68%) rename fpga-xc2s30/util.v => fpga/mux8.v (68%) rename {fpga-xc2s30 => fpga}/tests/Makefile (100%) rename {fpga-xc2s30 => fpga}/tests/plot_edgedetect.py (100%) mode change 100755 => 100644 rename {fpga-xc2s30 => fpga/tests}/sim.tcl (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_read_1MSA_data.filtered.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_read_1MSA_data.high.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_read_1MSA_data.highz.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_read_1MSA_data.in (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_read_1MSA_data.low.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_read_1MSA_data.lowz.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_read_1MSA_data.max.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_read_1MSA_data.min.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_read_1MSA_data.state.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_read_1MSA_data.time (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_read_1MSA_data.toggle.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_write1byte_1MSA_data.filtered.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_write1byte_1MSA_data.high.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_write1byte_1MSA_data.highz.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_write1byte_1MSA_data.in (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_write1byte_1MSA_data.low.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_write1byte_1MSA_data.lowz.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_write1byte_1MSA_data.max.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_write1byte_1MSA_data.min.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_write1byte_1MSA_data.state.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_write1byte_1MSA_data.time (100%) rename {fpga-xc2s30 => fpga}/tests/tb_data/pcf7931_write1byte_1MSA_data.toggle.gold (100%) rename {fpga-xc2s30 => fpga}/tests/tb_lf_edge_detect.v (100%) rename {fpga-xc2s30 => fpga}/tests/tb_lp20khz_1MSa_iir_filter.v (100%) rename {fpga-xc2s30 => fpga}/tests/tb_min_max_tracker.v (100%) rename {fpga-xc2s30 => fpga/tests}/testbed_fpga.v (100%) rename {fpga-xc2s30 => fpga/tests}/testbed_hi_read_tx.v (100%) rename {fpga-xc2s30 => fpga/tests}/testbed_hi_simulate.v (100%) rename {fpga-xc2s30 => fpga/tests}/testbed_lo_read.v (100%) rename {fpga-xc2s30 => fpga/tests}/testbed_lo_simulate.v (100%) create mode 100644 fpga/xc2s30-5-vq100.ucf create mode 100644 fpga/xc3s100e-4-vq100.ucf diff --git a/.gitignore b/.gitignore index 8469c84493..30cc1020af 100644 --- a/.gitignore +++ b/.gitignore @@ -80,17 +80,7 @@ tools/mfd_aes_brute/mfd_aes_brute tools/mfd_aes_brute/mfd_multi_brute tools/mfd_aes_brute/brute_key -fpga/* -!fpga/tests -!fpga/fpga_lf.bit -!fpga/fpga_hf.bit -!fpga/*.v -!fpga/Makefile -!fpga/fpga.ucf -!fpga/xst_lf.scr -!fpga/xst_hf.scr -!fpga/go.bat -!fpga/sim.tcl +fpga/__build* # offcial dumps folder dumps/* diff --git a/armsrc/Makefile b/armsrc/Makefile index 5203b02927..c481a6f225 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -103,9 +103,6 @@ endif # Generic standalone Mode injection of source code include Standalone/Makefile.inc -#the FPGA bitstream files. Note: order matters! -FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit fpga_felica.bit fpga_hf_15.bit - #the lz4 source files required for decompressing the fpga config at run time SRC_LZ4 = lz4.c #additional defines required to compile lz4 diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 6f8dd7a0b6..6715aa9628 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -404,16 +404,22 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3 /* Four byte length field */ current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16; - numbytes += 2; - default: /* Fall through, two byte length field */ + current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8; + current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0; + numbytes += 4; + if (current_length > 300*1024) { + /* section e should never exceed about 300KB, if the length is too big limit it but still send the bitstream just in case */ + current_length = 300*1024; + } + break; + default: /* Two byte length field */ current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0; numbytes += 2; - } - - if (current_name != 'e' && current_length > 255) { - /* Maybe a parse error */ - break; + if (current_length > 64) { + /* if text field is too long, keep it but truncate it */ + current_length = 64; + } } if (current_name == section_name) { diff --git a/common_arm/Makefile.common b/common_arm/Makefile.common index 99f4d9ecdb..18d931b465 100644 --- a/common_arm/Makefile.common +++ b/common_arm/Makefile.common @@ -44,7 +44,7 @@ OBJDIR = obj INCLUDE = -I../include -I../common_arm -I../common_fpga -I../common -I. # Also search prerequisites in the common directory (for usb.c), the fpga directory (for fpga.bit), and the lz4 directory -VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/lz4 ../fpga-$(PLATFORM_FPGA) ../armsrc/Standalone +VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/lz4 ../fpga ../armsrc/Standalone INCLUDES = ../include/proxmark3_arm.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/pm3_cmd.h diff --git a/common_arm/Makefile.hal b/common_arm/Makefile.hal index a65514784b..9679382ce7 100644 --- a/common_arm/Makefile.hal +++ b/common_arm/Makefile.hal @@ -92,18 +92,26 @@ PLTNAME = Unknown Platform PLATFORM_FPGA = fpga-undefined ifeq ($(PLATFORM),PM3RDV4) + # FPGA bitstream files, the order matters! + FPGA_BITSTREAMS = fpga_pm3_lf.bit fpga_pm3_hf.bit fpga_pm3_felica.bit fpga_pm3_hf_15.bit PLATFORM_DEFS = -DWITH_SMARTCARD -DWITH_FLASH -DRDV4 PLTNAME = Proxmark3 RDV4 PLATFORM_FPGA = xc2s30 RDV4 = yes else ifeq ($(PLATFORM),PM3OTHER) $(warning PLATFORM=PM3OTHER is deprecated, please use PLATFORM=PM3GENERIC) + # FPGA bitstream files, the order matters! + FPGA_BITSTREAMS = fpga_pm3_lf.bit fpga_pm3_hf.bit fpga_pm3_felica.bit fpga_pm3_hf_15.bit PLTNAME = Proxmark3 generic target PLATFORM_FPGA = xc2s30 else ifeq ($(PLATFORM),PM3GENERIC) + # FPGA bitstream files, the order matters! + FPGA_BITSTREAMS = fpga_pm3_lf.bit fpga_pm3_hf.bit fpga_pm3_felica.bit fpga_pm3_hf_15.bit PLTNAME = Proxmark3 generic target PLATFORM_FPGA = xc2s30 else ifeq ($(PLATFORM),PM3ICOPYX) + # FPGA bitstream files, the order matters - only hf has a bitstream, the other 3 files are 0 bytes + FPGA_BITSTREAMS = fpga_icopyx_lf.bit fpga_icopyx_hf.bit fpga_icopyx_felica.bit fpga_icopyx_hf_15.bit PLATFORM_DEFS = -DWITH_FLASH -DICOPYX -DXC3 PLTNAME = iCopy-X with XC3S100E PLATFORM_FPGA = xc3s100e @@ -246,6 +254,7 @@ export PLATFORM_DEFS export PLATFORM_DEFS_INFO export PLATFORM_DEFS_INFO_STANDALONE export PLATFORM_CHANGED +export FPGA_BITSTREAMS $(info ===================================================================) $(info Version info: $(shell tools/mkversion.sh --short 2>/dev/null || ../tools/mkversion.sh --short 2>/dev/null)) diff --git a/fpga-xc2s30/Makefile b/fpga-xc2s30/Makefile deleted file mode 100644 index 2bf9273ba6..0000000000 --- a/fpga-xc2s30/Makefile +++ /dev/null @@ -1,60 +0,0 @@ -# -# FPGA Makefile -# -RMDIR = rm -rf -# rmdir only if dir is empty, tolerate failure -RMDIR_SOFT = -rmdir -# -all: fpga_lf.bit fpga_hf.bit fpga_felica.bit fpga_hf_15.bit -clean: - $(Q)$(RM) *.bgn *.drc *.ncd *.ngd *_par.xrpt *-placed.* *-placed_pad.* *_usage.xml xst_hf.srp xst_lf.srp xst_felica.srp xst_hf_15.srp - $(Q)$(RM) *.map *.ngc *.xrpt *.pcf *.rbt *.bld *.mrp *.ngm *.unroutes *_summary.xml netlist.lst - $(Q)$(RMDIR) *_auto_* xst - -#fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_reader.v hi_iso14443a.v hi_sniffer.v hi_flite.v hi_get_trace.v -fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_reader.v hi_iso14443a.v hi_sniffer.v hi_get_trace.v - $(Q)$(RM) $@ - $(info [-] XST $@) - $(Q)$(XILINX_TOOLS_PREFIX)xst -ifn xst_hf.scr - -fpga_felica.ngc: fpga_felica.v fpga.ucf xst_felica.scr util.v hi_simulate.v hi_reader.v hi_sniffer.v hi_flite.v hi_get_trace.v - $(Q)$(RM) $@ - $(info [-] XST $@) - $(Q)$(XILINX_TOOLS_PREFIX)xst -ifn xst_felica.scr - -fpga_hf_15.ngc: fpga_hf_15.v fpga.ucf xst_hf_15.scr util.v hi_simulate.v hi_reader_15.v hi_sniffer.v hi_get_trace.v - $(Q)$(RM) $@ - $(info [-] XST $@) - $(Q)$(XILINX_TOOLS_PREFIX)xst -ifn xst_hf_15.scr - -fpga_lf.ngc: fpga_lf.v fpga.ucf xst_lf.scr util.v clk_divider.v lo_edge_detect.v lo_read.v lo_passthru.v lp20khz_1MSa_iir_filter.v min_max_tracker.v lf_edge_detect.v - $(Q)$(RM) $@ - $(info [-] XST $@) - $(Q)$(XILINX_TOOLS_PREFIX)xst -ifn xst_lf.scr - -%.ngd: %.ngc - $(Q)$(RM) $@ - $(info [-] NGD $@) - $(Q)$(XILINX_TOOLS_PREFIX)ngdbuild -aul -p xc2s30-5-vq100 -nt timestamp -uc fpga.ucf $< $@ - -%.ncd: %.ngd - $(Q)$(RM) $@ - $(info [-] MAP $@) - $(Q)$(XILINX_TOOLS_PREFIX)map -p xc2s30-5-vq100 $< - -%-placed.ncd: %.ncd - $(Q)$(RM) $@ - $(info [-] PAR $@) - $(Q)$(XILINX_TOOLS_PREFIX)par $< $@ - -%.bit: %-placed.ncd - $(Q)$(RM) $@ $*.drc $*.rbt - $(info [=] BITGEN $@) - $(Q)$(XILINX_TOOLS_PREFIX)bitgen $< $@ - -.PHONY: all clean help -help: - @echo Possible targets: - @echo + all - Make fpga.bit, the FPGA bitstream - @echo + clean - Clean intermediate files, does not clean fpga.bit - diff --git a/fpga-xc2s30/fpga.ucf b/fpga-xc2s30/fpga.ucf deleted file mode 100644 index f20e2da025..0000000000 --- a/fpga-xc2s30/fpga.ucf +++ /dev/null @@ -1,54 +0,0 @@ -# See the schematic for the pin assignment. - -NET "adc_d<0>" LOC = "P62" ; -NET "adc_d<1>" LOC = "P60" ; -NET "adc_d<2>" LOC = "P58" ; -NET "adc_d<3>" LOC = "P57" ; -NET "adc_d<4>" LOC = "P56" ; -NET "adc_d<5>" LOC = "P55" ; -NET "adc_d<6>" LOC = "P54" ; -NET "adc_d<7>" LOC = "P53" ; -#NET "cross_hi" LOC = "P88" ; -#NET "miso" LOC = "P40" ; -#PACE: Start of Constraints generated by PACE - -#PACE: Start of PACE I/O Pin Assignments -NET "adc_clk" LOC = "P46" ; -NET "adc_noe" LOC = "P47" ; -NET "ck_1356meg" LOC = "P91" ; -NET "ck_1356megb" LOC = "P93" ; -NET "cross_lo" LOC = "P87" ; -NET "dbg" LOC = "P22" ; -NET "mosi" LOC = "P43" ; -NET "ncs" LOC = "P44" ; -NET "pck0" LOC = "P36" ; -NET "pwr_hi" LOC = "P80" ; -NET "pwr_lo" LOC = "P81" ; -NET "pwr_oe1" LOC = "P82" ; -NET "pwr_oe2" LOC = "P83" ; -NET "pwr_oe3" LOC = "P84" ; -NET "pwr_oe4" LOC = "P86" ; -NET "spck" LOC = "P39" ; -NET "ssp_clk" LOC = "P71" ; -NET "ssp_din" LOC = "P32" ; -NET "ssp_dout" LOC = "P34" ; -NET "ssp_frame" LOC = "P31" ; - -#PACE: Start of PACE Area Constraints - -#PACE: Start of PACE Prohibit Constraints - -#PACE: End of Constraints generated by PACE - -# definition of Clock nets: -NET "ck_1356meg" TNM_NET = "clk_net_1356" ; -NET "ck_1356megb" TNM_NET = "clk_net_1356b" ; -NET "pck0" TNM_NET = "clk_net_pck0" ; -NET "spck" TNM_NET = "clk_net_spck" ; - -# Timing specs of clock nets: -TIMEGRP "clk_net_1356_all" = "clk_net_1356" "clk_net_1356b" ; -TIMESPEC "TS_1356MHz" = PERIOD "clk_net_1356_all" 74 ns HIGH 37 ns ; -TIMESPEC "TS_24MHz" = PERIOD "clk_net_pck0" 42 ns HIGH 21 ns ; -TIMESPEC "TS_4MHz" = PERIOD "clk_net_spck" 250 ns HIGH 125 ns ; - diff --git a/fpga-xc2s30/fpga_felica.bit b/fpga-xc2s30/fpga_felica.bit deleted file mode 100644 index 30ea16e332b8d28b03a80605bc0531fd5864d0c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42179 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 VbcHV;&EOOomiOv8^Q~Kd`@ho-u|5C* diff --git a/fpga-xc2s30/fpga_felica.v b/fpga-xc2s30/fpga_felica.v deleted file mode 100644 index 6fb53927c1..0000000000 --- a/fpga-xc2s30/fpga_felica.v +++ /dev/null @@ -1,240 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// -// The FPGA is responsible for interfacing between the A/D, the coil drivers, -// and the ARM. In the low-frequency modes it passes the data straight -// through, so that the ARM gets raw A/D samples over the SSP. In the high- -// frequency modes, the FPGA might perform some demodulation first, to -// reduce the amount of data that we must send to the ARM. -// -// I am not really an FPGA/ASIC designer, so I am sure that a lot of this -// could be improved. -// -// Jonathan Westhues, March 2006 -// -// Added ISO14443-A support -// - - -// Defining commands, modes and options. This must be aligned to the definitions in fpgaloader.h -// Note: the definitions here are without shifts - -// Commands: -`define FPGA_CMD_SET_CONFREG 1 -`define FPGA_CMD_TRACE_ENABLE 2 - -// Major modes: -`define FPGA_MAJOR_MODE_HF_READER 0 -`define FPGA_MAJOR_MODE_HF_SIMULATOR 1 -`define FPGA_MAJOR_MODE_HF_ISO14443A 2 -`define FPGA_MAJOR_MODE_HF_SNIFF 3 -`define FPGA_MAJOR_MODE_HF_ISO18092 4 -`define FPGA_MAJOR_MODE_HF_GET_TRACE 5 -`define FPGA_MAJOR_MODE_OFF 7 - -// Options for the generic HF reader -`define FPGA_HF_READER_MODE_RECEIVE_IQ 0 -`define FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE 1 -`define FPGA_HF_READER_MODE_RECEIVE_PHASE 2 -`define FPGA_HF_READER_MODE_SEND_FULL_MOD 3 -`define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD 4 -`define FPGA_HF_READER_MODE_SNIFF_IQ 5 -`define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE 6 -`define FPGA_HF_READER_MODE_SNIFF_PHASE 7 -`define FPGA_HF_READER_MODE_SEND_JAM 8 - -`define FPGA_HF_READER_SUBCARRIER_848_KHZ 0 -`define FPGA_HF_READER_SUBCARRIER_424_KHZ 1 -`define FPGA_HF_READER_SUBCARRIER_212_KHZ 2 - -// Options for the HF simulated tag, how to modulate -`define FPGA_HF_SIMULATOR_NO_MODULATION 0 -`define FPGA_HF_SIMULATOR_MODULATE_BPSK 1 -`define FPGA_HF_SIMULATOR_MODULATE_212K 2 -`define FPGA_HF_SIMULATOR_MODULATE_424K 4 -`define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 5 - -// Options for ISO14443A -`define FPGA_HF_ISO14443A_SNIFFER 0 -`define FPGA_HF_ISO14443A_TAGSIM_LISTEN 1 -`define FPGA_HF_ISO14443A_TAGSIM_MOD 2 -`define FPGA_HF_ISO14443A_READER_LISTEN 3 -`define FPGA_HF_ISO14443A_READER_MOD 4 - -//options for ISO18092 / Felica -`define FPGA_HF_ISO18092_FLAG_NOMOD 1 // 0001 disable modulation module -`define FPGA_HF_ISO18092_FLAG_424K 2 // 0010 should enable 414k mode (untested). No autodetect -`define FPGA_HF_ISO18092_FLAG_READER 4 // 0100 enables antenna power, to act as a reader instead of tag - -`include "hi_reader.v" -`include "hi_simulate.v" -//`include "hi_iso14443a.v" -`include "hi_sniffer.v" -`include "util.v" -`include "hi_flite.v" -`include "hi_get_trace.v" - -module fpga_felica( - input spck, output miso, input mosi, input ncs, - input pck0, input ck_1356meg, input ck_1356megb, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, output adc_noe, - output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk, - input cross_hi, input cross_lo, - output dbg -); - -//----------------------------------------------------------------------------- -// The SPI receiver. This sets up the configuration word, which the rest of -// the logic looks at to determine how to connect the A/D and the coil -// drivers (i.e., which section gets it). Also assign some symbolic names -// to the configuration bits, for use below. -//----------------------------------------------------------------------------- - -/* - Attempt to write up how its hooked up. Iceman 2020. - - Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand() - Send 16 bit command / data pair to FPGA - The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 - where - C is 4bit command - D is 12bit data - - shift_reg receive this 16bit frame - - ------+--------- frame layout -------------------- -bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ------+------------------------------------------- -cmd | x x x x -major| x x x -opt | x x x -divi | x x x x x x x x -thres| x x x x x x x x ------+------------------------------------------- -*/ - -reg [15:0] shift_reg; -reg [8:0] conf_word; -reg trace_enable; - -// We switch modes between transmitting to the 13.56 MHz tag and receiving -// from it, which means that we must make sure that we can do so without -// glitching, or else we will glitch the transmitted carrier. -always @(posedge ncs) -begin - case(shift_reg[15:12]) - `FPGA_CMD_SET_CONFREG: conf_word <= shift_reg[8:0]; - `FPGA_CMD_TRACE_ENABLE: trace_enable <= shift_reg[0]; - endcase -end - -always @(posedge spck) -begin - if(~ncs) - begin - shift_reg[15:1] <= shift_reg[14:0]; - shift_reg[0] <= mosi; - end -end - -// select module (outputs) based on major mode -wire [2:0] major_mode = conf_word[8:6]; - -// configuring the HF reader -wire [1:0] subcarrier_frequency = conf_word[5:4]; -wire [3:0] minor_mode = conf_word[3:0]; - -//----------------------------------------------------------------------------- -// And then we instantiate the modules corresponding to each of the FPGA's -// major modes, and use muxes to connect the outputs of the active mode to -// the output pins. -//----------------------------------------------------------------------------- - -// 000 - HF reader -hi_reader hr( - ck_1356megb, - hr_pwr_lo, hr_pwr_hi, hr_pwr_oe1, hr_pwr_oe2, hr_pwr_oe3, hr_pwr_oe4, - adc_d, hr_adc_clk, - hr_ssp_frame, hr_ssp_din, ssp_dout, hr_ssp_clk, - hr_dbg, - subcarrier_frequency, minor_mode -); - -// 001 - HF simulated tag -hi_simulate hs( - ck_1356meg, - hs_pwr_lo, hs_pwr_hi, hs_pwr_oe1, hs_pwr_oe2, hs_pwr_oe3, hs_pwr_oe4, - adc_d, hs_adc_clk, - hs_ssp_frame, hs_ssp_din, ssp_dout, hs_ssp_clk, - hs_dbg, - minor_mode -); - -// 011 - HF sniff -hi_sniffer he( - ck_1356megb, - he_pwr_lo, he_pwr_hi, he_pwr_oe1, he_pwr_oe2, he_pwr_oe3, he_pwr_oe4, - adc_d, he_adc_clk, - he_ssp_frame, he_ssp_din, he_ssp_clk -); - -// 100 - HF ISO18092 FeliCa -hi_flite hfl( - ck_1356megb, - hfl_pwr_lo, hfl_pwr_hi, hfl_pwr_oe1, hfl_pwr_oe2, hfl_pwr_oe3, hfl_pwr_oe4, - adc_d, hfl_adc_clk, - hfl_ssp_frame, hfl_ssp_din, ssp_dout, hfl_ssp_clk, - hfl_dbg, - minor_mode -); - -// 101 - HF get trace -hi_get_trace gt( - ck_1356megb, - adc_d, trace_enable, major_mode, - gt_ssp_frame, gt_ssp_din, gt_ssp_clk -); - -// Major modes: -// 000 -- HF reader; subcarrier frequency and modulation depth selectable -// 001 -- HF simulated tag -// 010 -- HF ISO14443-A - removed for space... -// 011 -- HF sniff -// 100 -- HF ISO18092 FeliCa -// 101 -- HF get trace -// 110 -- unused -// 111 -- FPGA_MAJOR_MODE_OFF - -// 000 001 010 011 100 101 110 111 -mux8 mux_ssp_clk (major_mode, ssp_clk, hr_ssp_clk, hs_ssp_clk, 1'b0, he_ssp_clk, hfl_ssp_clk, gt_ssp_clk, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, hr_ssp_din, hs_ssp_din, 1'b0, he_ssp_din, hfl_ssp_din, gt_ssp_din, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, hr_ssp_frame, hs_ssp_frame, 1'b0, he_ssp_frame, hfl_ssp_frame, gt_ssp_frame, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, hr_pwr_oe1, hs_pwr_oe1, 1'b0, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, hr_pwr_oe2, hs_pwr_oe2, 1'b0, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, hr_pwr_oe3, hs_pwr_oe3, 1'b0, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, hr_pwr_oe4, hs_pwr_oe4, 1'b0, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, hr_pwr_lo, hs_pwr_lo, 1'b0, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, hr_pwr_hi, hs_pwr_hi, 1'b0, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, hr_adc_clk, hs_adc_clk, 1'b0, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, hr_dbg, hs_dbg, 1'b0, he_dbg, hfl_dbg, 1'b0, 1'b0, 1'b0); - -// In all modes, let the ADC's outputs be enabled. -assign adc_noe = 1'b0; - -endmodule diff --git a/fpga-xc2s30/fpga_hf.bit b/fpga-xc2s30/fpga_hf.bit deleted file mode 100644 index 72f3d619e974e6aac2968b4524a055684934eb18..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42175 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 z 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 ZMfoGYeNB>b{Cn`F_&uYQw3OfS{{^O35heft diff --git a/fpga-xc2s30/fpga_lf.v b/fpga-xc2s30/fpga_lf.v deleted file mode 100644 index bb9116f101..0000000000 --- a/fpga-xc2s30/fpga_lf.v +++ /dev/null @@ -1,245 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// See LICENSE.txt for the text of the license. -//----------------------------------------------------------------------------- -// - - -// Defining commands, modes and options. This must be aligned to the definitions in fpgaloader.h -// Note: the definitions here are without shifts - -// Commands: -`define FPGA_CMD_SET_CONFREG 1 -`define FPGA_CMD_SET_DIVISOR 2 -`define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD 3 - -// Major modes: -`define FPGA_MAJOR_MODE_LF_READER 0 -`define FPGA_MAJOR_MODE_LF_EDGE_DETECT 1 -`define FPGA_MAJOR_MODE_LF_PASSTHRU 2 -`define FPGA_MAJOR_MODE_LF_ADC 3 - -// Options for LF_READER -`define FPGA_LF_ADC_READER_FIELD 1 - -// Options for LF_EDGE_DETECT -`define FPGA_LF_EDGE_DETECT_READER_FIELD 1 -`define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 2 - -`include "lo_read.v" -`include "lo_passthru.v" -`include "lo_edge_detect.v" -`include "lo_adc.v" -`include "util.v" -`include "clk_divider.v" - -module fpga_lf( - input spck, output miso, input mosi, input ncs, - input pck0, input ck_1356meg, input ck_1356megb, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, output adc_noe, - output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk, - input cross_hi, input cross_lo, - output dbg -); - -//----------------------------------------------------------------------------- -// The SPI receiver. This sets up the configuration word, which the rest of -// the logic looks at to determine how to connect the A/D and the coil -// drivers (i.e., which section gets it). Also assign some symbolic names -// to the configuration bits, for use below. -//----------------------------------------------------------------------------- - -/* - Attempt to write up how its hooked up. Iceman 2020. - - Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand() - Send 16 bit command / data pair to FPGA - The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 - where - C is 4bit command - D is 12bit data - - shift_reg receive this 16bit frame - - LF command - ---------- - shift_reg[15:12] == 4bit command - LF has three commands (FPGA_CMD_SET_CONFREG, FPGA_CMD_SET_DIVISOR, FPGA_CMD_SET_EDGE_DETECT_THRESHOLD) - Current commands uses only 2bits. We have room for up to 4bits of commands total (7). - - LF data - ------- - shift_reg[11:0] == 12bit data - lf data is divided into MAJOR MODES and configuration values. - - The major modes uses 3bits (0,1,2,3,7 | 000, 001, 010, 011, 111) - 000 FPGA_MAJOR_MODE_LF_READER = Act as LF reader (modulate) - 001 FPGA_MAJOR_MODE_LF_EDGE_DETECT = Simulate LF - 010 FPGA_MAJOR_MODE_LF_PASSTHRU = Passthrough mode, CROSS_LO line connected to SSP_DIN. SSP_DOUT logic level controls if we modulate / listening - 011 FPGA_MAJOR_MODE_LF_ADC = refactor hitag2, clear ADC sampling - 111 FPGA_MAJOR_MODE_OFF = turn off sampling. - - Each one of this major modes can have options. Currently these two major modes uses options. - - FPGA_MAJOR_MODE_LF_READER - - FPGA_MAJOR_MODE_LF_EDGE_DETECT - - FPGA_MAJOR_MODE_LF_READER - ------------------------------------- - lf_field = 1bit (FPGA_LF_ADC_READER_FIELD) - - You can send FPGA_CMD_SET_DIVISOR to set with FREQUENCY the fpga should sample at - divisor = 8bits shift_reg[7:0] - - FPGA_MAJOR_MODE_LF_EDGE_DETECT - ------------------------------------------ - lf_ed_toggle_mode = 1bits - lf_ed_threshold = 8bits threshold defaults to 127 - - You can send FPGA_CMD_SET_EDGE_DETECT_THRESHOLD to set a custom threshold - lf_ed_threshold = 8bits threshold value. - - conf_word 12bits - conf_word[8:6] = 3bit major mode. - conf_word[0] = 1bit lf_field - conf_word[1] = 1bit lf_ed_toggle_mode - conf_word[7:0] = 8bit divisor - conf_word[7:0] = 8bit threshold - ------+--------- frame layout -------------------- -bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ------+------------------------------------------- -cmd | x x x x -major| x x x -opt | x x -divi | x x x x x x x x -thres| x x x x x x x x ------+------------------------------------------- -*/ - -reg [15:0] shift_reg; -reg [7:0] divisor; -reg [7:0] lf_ed_threshold; -reg [11:0] conf_word; - -wire [2:0] major_mode = conf_word[8:6]; -wire lf_field = conf_word[0]; -wire lf_ed_toggle_mode = conf_word[1]; - -// Handles cmd / data frame from ARM -always @(posedge ncs) -begin - // 4 bit command - case (shift_reg[15:12]) - `FPGA_CMD_SET_CONFREG: - begin - // 12 bit data - conf_word <= shift_reg[11:0]; - if (shift_reg[8:6] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT) - begin - lf_ed_threshold <= 127; // default threshold - end - end - - `FPGA_CMD_SET_DIVISOR: - divisor <= shift_reg[7:0]; // 8bits - - `FPGA_CMD_SET_EDGE_DETECT_THRESHOLD: - lf_ed_threshold <= shift_reg[7:0]; // 8 bits - endcase -end - -// Receive 16bits of data from ARM here. -always @(posedge spck) -begin - if (~ncs) - begin - shift_reg[15:1] <= shift_reg[14:0]; - shift_reg[0] <= mosi; - end -end - -//----------------------------------------------------------------------------- -// And then we instantiate the modules corresponding to each of the FPGA's -// major modes, and use muxes to connect the outputs of the active mode to -// the output pins. -//----------------------------------------------------------------------------- -wire [7:0] pck_cnt; -wire pck_divclk; -clk_divider div_clk(pck0, divisor, pck_cnt, pck_divclk); - -lo_read lr( - pck0, pck_cnt, pck_divclk, - lr_pwr_lo, lr_pwr_hi, lr_pwr_oe1, lr_pwr_oe2, lr_pwr_oe3, lr_pwr_oe4, - adc_d, lr_adc_clk, - lr_ssp_frame, lr_ssp_din, lr_ssp_clk, - lr_dbg, lf_field -); - -lo_passthru lp( - pck_divclk, - lp_pwr_lo, lp_pwr_hi, lp_pwr_oe1, lp_pwr_oe2, lp_pwr_oe3, lp_pwr_oe4, - lp_adc_clk, - lp_ssp_din, ssp_dout, - cross_lo, - lp_dbg -); - -lo_edge_detect le( - pck0, pck_divclk, - le_pwr_lo, le_pwr_hi, le_pwr_oe1, le_pwr_oe2, le_pwr_oe3, le_pwr_oe4, - adc_d, le_adc_clk, - le_ssp_frame, ssp_dout, le_ssp_clk, - cross_lo, - le_dbg, - lf_field, - lf_ed_toggle_mode, lf_ed_threshold -); - -lo_adc la( - pck0, - la_pwr_lo, la_pwr_hi, la_pwr_oe1, la_pwr_oe2, la_pwr_oe3, la_pwr_oe4, - adc_d, la_adc_clk, - la_ssp_frame, la_ssp_din, ssp_dout, la_ssp_clk, - la_dbg, divisor, - lf_field -); - -// Major modes: -// 000 -- LF reader (generic) -// 001 -- LF edge detect (generic) -// 010 -- LF passthrough -// 011 -- LF ADC (read/write) -// 100 -- unused -// 101 -- unused -// 110 -- unused -// 111 -- FPGA_MAJOR_MODE_OFF -// 000 001 010 011 100 101 110 111 -mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, la_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, la_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, le_ssp_frame, 1'b0, la_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, le_pwr_oe1, lp_pwr_oe1, la_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, le_pwr_oe2, lp_pwr_oe2, la_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, le_pwr_oe3, lp_pwr_oe3, la_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, le_pwr_oe4, lp_pwr_oe4, la_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, la_pwr_lo, 1'b0, 1'b0, 1'b1, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, le_pwr_hi, lp_pwr_hi, la_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, le_adc_clk, lp_adc_clk, la_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, lr_dbg, le_dbg, lp_dbg, la_dbg, 1'b0, 1'b0, 1'b0, 1'b0); - -// In all modes, let the ADC's outputs be enabled. -assign adc_noe = 1'b0; - -endmodule diff --git a/fpga-xc2s30/go.bat b/fpga-xc2s30/go.bat deleted file mode 100644 index d9704e08d6..0000000000 --- a/fpga-xc2s30/go.bat +++ /dev/null @@ -1,68 +0,0 @@ -@echo off - -rmdir/s/q xst - -del fpga_lf.ngc -xst -ifn xst_lf.scr -if errorlevel 0 goto ok1 -goto done -:ok1 - -del fpga_lf.ngd -ngdbuild -aul -p xc2s30-6vq100 -nt timestamp -uc fpga.ucf fpga_lf.ngc fpga_lf.ngd -if errorlevel 0 goto ok2 -goto done -:ok2 - -del fpga_lf.ncd -map -p xc2s30-6vq100 fpga_lf.ngd -if errorlevel 0 goto ok3 -goto done -:ok3 - -del fpga_lf-placed.ncd -par fpga_lf.ncd fpga_lf-placed.ncd -if errorlevel 0 goto ok4 -goto done -:ok4 - -del fpga_lf.bit fpga_lf.drc fpga_lf.rbt -bitgen -b fpga_lf-placed.ncd fpga_lf.bit -if errorlevel 0 goto ok5 -goto done -:ok5 - -del fpga_hf.ngc -xst -ifn xst_hf.scr -if errorlevel 0 goto ok6 -goto done -:ok6 - -del fpga_hf.ngd -ngdbuild -aul -p xc2s30-6vq100 -nt timestamp -uc fpga.ucf fpga_hf.ngc fpga_hf.ngd -if errorlevel 0 goto ok7 -goto done -:ok7 - -del fpga_hf.ncd -map -p xc2s30-6vq100 fpga_hf.ngd -if errorlevel 0 goto ok8 -goto done -:ok8 - -del fpga_hf-placed.ncd -par fpga_hf.ncd fpga_hf-placed.ncd -if errorlevel 0 goto ok9 -goto done -:ok9 - -del fpga_hf.bit fpga_hf.drc fpga_hf.rbt -bitgen -b fpga_hf-placed.ncd fpga_hf.bit -if errorlevel 0 goto ok10 -goto done -:ok10 - -echo okay -perl ..\tools\rbt2c.pl fpga_lf.rbt > ..\armsrc\fpgaimg.c - -:done diff --git a/fpga-xc2s30/xst_felica.scr b/fpga-xc2s30/xst_felica.scr deleted file mode 100644 index b069fab13c..0000000000 --- a/fpga-xc2s30/xst_felica.scr +++ /dev/null @@ -1 +0,0 @@ -run -ifn fpga_felica.v -ifmt Verilog -ofn fpga_felica.ngc -ofmt NGC -p xc2s30-5-vq100 -top fpga_felica -opt_mode area -opt_level 2 -resource_sharing yes -fsm_style bram -fsm_encoding compact diff --git a/fpga-xc2s30/xst_hf.scr b/fpga-xc2s30/xst_hf.scr deleted file mode 100644 index dd2fdc859f..0000000000 --- a/fpga-xc2s30/xst_hf.scr +++ /dev/null @@ -1 +0,0 @@ -run -ifn fpga_hf.v -ifmt Verilog -ofn fpga_hf.ngc -ofmt NGC -p xc2s30-5-vq100 -top fpga_hf -opt_mode area -opt_level 2 -resource_sharing yes -fsm_style bram -fsm_encoding compact diff --git a/fpga-xc2s30/xst_hf_15.scr b/fpga-xc2s30/xst_hf_15.scr deleted file mode 100644 index d8bb5ae7c3..0000000000 --- a/fpga-xc2s30/xst_hf_15.scr +++ /dev/null @@ -1 +0,0 @@ -run -ifn fpga_hf_15.v -ifmt Verilog -ofn fpga_hf_15.ngc -ofmt NGC -p xc2s30-5-vq100 -top fpga_hf_15 -opt_mode area -opt_level 2 -resource_sharing yes -fsm_style bram -fsm_encoding compact diff --git a/fpga-xc2s30/xst_lf.scr b/fpga-xc2s30/xst_lf.scr deleted file mode 100644 index 2d6c7e951c..0000000000 --- a/fpga-xc2s30/xst_lf.scr +++ /dev/null @@ -1 +0,0 @@ -run -ifn fpga_lf.v -ifmt Verilog -ofn fpga_lf.ngc -ofmt NGC -p xc2s30-5-vq100 -top fpga_lf -opt_mode area -opt_level 2 -resource_sharing yes -fsm_style bram -fsm_encoding compact diff --git a/fpga-xc3s100e/.gitignore b/fpga-xc3s100e/.gitignore deleted file mode 100644 index b21d41545c..0000000000 --- a/fpga-xc3s100e/.gitignore +++ /dev/null @@ -1,68 +0,0 @@ -# intermediate build files -*.bgn -*.bit -*.bld -*.cmd_log -*.drc -*.ll -*.lso -*.msd -*.msk -*.ncd -*.ngc -*.ngd -*.ngr -*.pad -*.par -*.pcf -*.prj -*.ptwx -*.rbb -*.rbd -*.stx -*.syr -*.twr -*.twx -*.unroutes -*.ut -*.xpi -*.xst -*_bitgen.xwbt -*_envsettings.html -*_map.map -*_map.mrp -*_map.ngm -*_map.xrpt -*_ngdbuild.xrpt -*_pad.csv -*_pad.txt -*_par.xrpt -*_summary.html -*_summary.xml -*_usage.xml -*_xst.xrpt - -# iMPACT generated files -_impactbatch.log -impact.xsl -impact_impact.xwbt -ise_impact.cmd -webtalk_impact.xml - -# Core Generator generated files -xaw2verilog.log - -# project-wide generated files -*.gise -par_usage_statistics.html -usage_statistics_webtalk.html -webtalk.log -webtalk_pn.xml - -# generated folders -iseconfig/ -xlnx_auto_0_xdb/ -xst/ -_ngo/ -_xmsgs/ -fpga_hf_xdb/tmp/ diff --git a/fpga-xc3s100e/clk_divider.v b/fpga-xc3s100e/clk_divider.v deleted file mode 100644 index 9a57879b0d..0000000000 --- a/fpga-xc3s100e/clk_divider.v +++ /dev/null @@ -1,25 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2014 iZsh -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -module clk_divider(input clk, input [7:0] divisor, output [7:0] div_cnt, output div_clk); - - reg [7:0] div_cnt_ = 0; - reg div_clk_; - assign div_cnt = div_cnt_; - assign div_clk = div_clk_; - - always @(posedge clk) - begin - if(div_cnt == divisor) begin - div_cnt_ <= 8'd0; - div_clk_ = !div_clk_; - end else - div_cnt_ <= div_cnt_ + 1; - end - -endmodule - diff --git a/fpga-xc3s100e/compile.sh b/fpga-xc3s100e/compile.sh deleted file mode 100755 index 741ed0bb87..0000000000 --- a/fpga-xc3s100e/compile.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -( - cd iseproj/fpga_hf - xtclsh fpga_hf.tcl run_process - mv fpga_hf.bit ../.. - git checkout fpga_hf.ise - git clean -dfx . -) diff --git a/fpga-xc3s100e/define.v b/fpga-xc3s100e/define.v deleted file mode 100644 index adced90039..0000000000 --- a/fpga-xc3s100e/define.v +++ /dev/null @@ -1,49 +0,0 @@ -// Defining commands, modes and options. This must be aligned to the definitions in fpgaloader.h -// Note: the definitions here are without shifts - -// Commands: -`define FPGA_CMD_SET_CONFREG 1 -`define FPGA_CMD_TRACE_ENABLE 2 - -// Major modes: -`define FPGA_MAJOR_MODE_HF_READER 0 -`define FPGA_MAJOR_MODE_HF_SIMULATOR 1 -`define FPGA_MAJOR_MODE_HF_ISO14443A 2 -`define FPGA_MAJOR_MODE_HF_SNIFF 3 -`define FPGA_MAJOR_MODE_HF_ISO18092 4 -`define FPGA_MAJOR_MODE_HF_GET_TRACE 5 -`define FPGA_MAJOR_MODE_OFF 7 - -// Options for the generic HF reader -`define FPGA_HF_READER_MODE_RECEIVE_IQ 0 -`define FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE 1 -`define FPGA_HF_READER_MODE_RECEIVE_PHASE 2 -`define FPGA_HF_READER_MODE_SEND_FULL_MOD 3 -`define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD 4 -`define FPGA_HF_READER_MODE_SNIFF_IQ 5 -`define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE 6 -`define FPGA_HF_READER_MODE_SNIFF_PHASE 7 -`define FPGA_HF_READER_MODE_SEND_JAM 8 - -`define FPGA_HF_READER_SUBCARRIER_848_KHZ 0 -`define FPGA_HF_READER_SUBCARRIER_424_KHZ 1 -`define FPGA_HF_READER_SUBCARRIER_212_KHZ 2 - -// Options for the HF simulated tag, how to modulate -`define FPGA_HF_SIMULATOR_NO_MODULATION 0 -`define FPGA_HF_SIMULATOR_MODULATE_BPSK 1 -`define FPGA_HF_SIMULATOR_MODULATE_212K 2 -`define FPGA_HF_SIMULATOR_MODULATE_424K 4 -`define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 5 - -// Options for ISO14443A -`define FPGA_HF_ISO14443A_SNIFFER 0 -`define FPGA_HF_ISO14443A_TAGSIM_LISTEN 1 -`define FPGA_HF_ISO14443A_TAGSIM_MOD 2 -`define FPGA_HF_ISO14443A_READER_LISTEN 3 -`define FPGA_HF_ISO14443A_READER_MOD 4 - -//options for ISO18092 / Felica -`define FPGA_HF_ISO18092_FLAG_NOMOD 1 // 0001 disable modulation module -`define FPGA_HF_ISO18092_FLAG_424K 2 // 0010 should enable 414k mode (untested). No autodetect -`define FPGA_HF_ISO18092_FLAG_READER 4 // 0100 enables antenna power, to act as a reader instead of tag diff --git a/fpga-xc3s100e/fpga.ucf b/fpga-xc3s100e/fpga.ucf deleted file mode 100644 index 4cb06a9d63..0000000000 --- a/fpga-xc3s100e/fpga.ucf +++ /dev/null @@ -1,56 +0,0 @@ -# See the schematic for the pin assignment. - -#NET "cross_hi" LOC = "P88" ; -#NET "miso" LOC = "P40" ; - -# definition of Clock nets: -NET "ck_1356meg" TNM_NET = "clk_net_1356" ; -NET "ck_1356megb" TNM_NET = "clk_net_1356b" ; -NET "pck0" TNM_NET = "clk_net_pck0" ; -NET "spck" TNM_NET = "clk_net_spck" ; - -# Timing specs of clock nets: -TIMEGRP "clk_net_1356_all" = "clk_net_1356" "clk_net_1356b" ; -TIMESPEC "TS_1356MHz" = PERIOD "clk_net_1356_all" 74 ns HIGH 37 ns ; -TIMESPEC "TS_24MHz" = PERIOD "clk_net_pck0" 42 ns HIGH 21 ns ; -TIMESPEC "TS_4MHz" = PERIOD "clk_net_spck" 250 ns HIGH 125 ns ; -NET "FPGA_SWITCH" CLOCK_DEDICATED_ROUTE = FALSE ; -#PACE: Start of Constraints generated by PACE - -#PACE: Start of PACE I/O Pin Assignments -NET "adc_clk" LOC = "P65" ; -NET "adc_d<0>" LOC = "P79" ; -NET "adc_d<1>" LOC = "P78" ; -NET "adc_d<2>" LOC = "P71" ; -NET "adc_d<3>" LOC = "P70" ; -NET "adc_d<4>" LOC = "P69" ; -NET "adc_d<5>" LOC = "P68" ; -NET "adc_d<6>" LOC = "P67" ; -NET "adc_d<7>" LOC = "P66" ; -NET "adc_noe" LOC = "P62" ; -NET "ck_1356meg" LOC = "p88" ; -NET "ck_1356megb" LOC = "p89" ; -NET "cross_lo" LOC = "P90" ; -NET "dbg" LOC = "P22" ; -NET "FPGA_SWITCH" LOC = "P38" ; -NET "mosi" LOC = "P43" ; -NET "ncs" LOC = "P40" ; -NET "pck0" LOC = "P36" ; -NET "pwr_hi" LOC = "P85" ; -NET "pwr_lo" LOC = "P83" ; -NET "PWR_LO_EN" LOC = "P94" ; -NET "pwr_oe1" LOC = "P84" ; -NET "pwr_oe2" LOC = "P91" ; -NET "pwr_oe3" LOC = "P92" ; -NET "pwr_oe4" LOC = "P86" ; -NET "spck" LOC = "P39" ; -NET "ssp_clk" LOC = "P33" ; -NET "ssp_din" LOC = "P32" ; -NET "ssp_dout" LOC = "P34" ; -NET "ssp_frame" LOC = "P27" ; - -#PACE: Start of PACE Area Constraints - -#PACE: Start of PACE Prohibit Constraints - -#PACE: End of Constraints generated by PACE diff --git a/fpga-xc3s100e/fpga_hf.bit b/fpga-xc3s100e/fpga_hf.bit deleted file mode 100644 index df1fb45f68487469f520ec7b21916ebd11098bc3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72742 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 diff --git a/fpga-xc3s100e/fpga_hfmod.v b/fpga-xc3s100e/fpga_hfmod.v deleted file mode 100644 index 53040aead2..0000000000 --- a/fpga-xc3s100e/fpga_hfmod.v +++ /dev/null @@ -1,193 +0,0 @@ -//----------------------------------------------------------------------------- -// The FPGA is responsible for interfacing between the A/D, the coil drivers, -// and the ARM. In the low-frequency modes it passes the data straight -// through, so that the ARM gets raw A/D samples over the SSP. In the high- -// frequency modes, the FPGA might perform some demodulation first, to -// reduce the amount of data that we must send to the ARM. -// -// I am not really an FPGA/ASIC designer, so I am sure that a lot of this -// could be improved. -// -// Jonathan Westhues, March 2006 -// Added ISO14443-A support by Gerhard de Koning Gans, April 2008 -// iZsh , June 2014 -// Piwi, Feb 2019 -//----------------------------------------------------------------------------- - -//For ISE 10.1 PROJ,IDE cannot apply definition to all files -`include "define.v" - - -//For ISE 10.1 PROJ,IDE auto include -//`include "hi_reader.v" -//`include "hi_simulate.v" -//`include "hi_iso14443a.v" -//`include "hi_sniffer.v" -//`include "util.v" -//`include "hi_flite.v" -//`include "hi_get_trace.v" - -module fpga_hfmod( - input spck, output miso, input mosi, input ncs, - input pck0, input ck_1356meg, input ck_1356megb, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, output adc_noe, - output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk, - input cross_hi, input cross_lo, - output dbg -); - -//----------------------------------------------------------------------------- -// The SPI receiver. This sets up the configuration word, which the rest of -// the logic looks at to determine how to connect the A/D and the coil -// drivers (i.e., which section gets it). Also assign some symbolic names -// to the configuration bits, for use below. -//----------------------------------------------------------------------------- - -/* - Attempt to write up how its hooked up. Iceman 2020. - - Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand() - Send 16 bit command / data pair to FPGA - The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 - where - C is 4bit command - D is 12bit data - - shift_reg receive this 16bit frame - - ------+--------- frame layout -------------------- -bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ------+------------------------------------------- -cmd | x x x x -major| x x x -opt | x x x -divi | x x x x x x x x -thres| x x x x x x x x ------+------------------------------------------- -*/ - -reg [15:0] shift_reg; -reg [8:0] conf_word; -reg trace_enable; - -// We switch modes between transmitting to the 13.56 MHz tag and receiving -// from it, which means that we must make sure that we can do so without -// glitching, or else we will glitch the transmitted carrier. -always @(posedge ncs) -begin - case(shift_reg[15:12]) - `FPGA_CMD_SET_CONFREG: conf_word <= shift_reg[8:0]; - `FPGA_CMD_TRACE_ENABLE: trace_enable <= shift_reg[0]; - endcase -end - -always @(posedge spck) -begin - if(~ncs) - begin - shift_reg[15:1] <= shift_reg[14:0]; - shift_reg[0] <= mosi; - end -end - -// select module (outputs) based on major mode -wire [2:0] major_mode = conf_word[8:6]; - -// configuring the HF reader -wire [1:0] subcarrier_frequency = conf_word[5:4]; -wire [3:0] minor_mode = conf_word[3:0]; - -//----------------------------------------------------------------------------- -// And then we instantiate the modules corresponding to each of the FPGA's -// major modes, and use muxes to connect the outputs of the active mode to -// the output pins. -//----------------------------------------------------------------------------- - -// 000 - HF reader -hi_reader hr( - ck_1356megb, - hr_pwr_lo, hr_pwr_hi, hr_pwr_oe1, hr_pwr_oe2, hr_pwr_oe3, hr_pwr_oe4, - adc_d, hr_adc_clk, - hr_ssp_frame, hr_ssp_din, ssp_dout, hr_ssp_clk, - hr_dbg, - subcarrier_frequency, minor_mode -); - -// 001 - HF simulated tag -hi_simulate hs( - ck_1356meg, - hs_pwr_lo, hs_pwr_hi, hs_pwr_oe1, hs_pwr_oe2, hs_pwr_oe3, hs_pwr_oe4, - adc_d, hs_adc_clk, - hs_ssp_frame, hs_ssp_din, ssp_dout, hs_ssp_clk, - hs_dbg, - minor_mode -); - -// 010 - HF ISO14443-A -hi_iso14443a hisn( - ck_1356meg, - hisn_pwr_lo, hisn_pwr_hi, hisn_pwr_oe1, hisn_pwr_oe2, hisn_pwr_oe3, hisn_pwr_oe4, - adc_d, hisn_adc_clk, - hisn_ssp_frame, hisn_ssp_din, ssp_dout, hisn_ssp_clk, - hisn_dbg, - minor_mode -); - -// 011 - HF sniff -hi_sniffer he( - ck_1356megb, - he_pwr_lo, he_pwr_hi, he_pwr_oe1, he_pwr_oe2, he_pwr_oe3, he_pwr_oe4, - adc_d, he_adc_clk, - he_ssp_frame, he_ssp_din, he_ssp_clk -); - -// 100 - HF ISO18092 FeliCa - -hi_flite hfl( - ck_1356megb, - hfl_pwr_lo, hfl_pwr_hi, hfl_pwr_oe1, hfl_pwr_oe2, hfl_pwr_oe3, hfl_pwr_oe4, - adc_d, hfl_adc_clk, - hfl_ssp_frame, hfl_ssp_din, ssp_dout, hfl_ssp_clk, - hfl_dbg, - minor_mode -); - - -// 101 - HF get trace -hi_get_trace gt( - ck_1356megb, - adc_d, trace_enable, major_mode, - gt_ssp_frame, gt_ssp_din, gt_ssp_clk -); - -// Major modes: -// 000 -- HF reader; subcarrier frequency and modulation depth selectable -// 001 -- HF simulated tag -// 010 -- HF ISO14443-A -// 011 -- HF sniff -// 100 -- HF ISO18092 FeliCa -// 101 -- HF get trace -// 110 -- unused -// 111 -- FPGA_MAJOR_MODE_OFF - -// 000 001 010 011 100 101 110 111 - -mux8 mux_ssp_clk (major_mode, ssp_clk, hr_ssp_clk, hs_ssp_clk, hisn_ssp_clk, he_ssp_clk, hfl_ssp_clk, gt_ssp_clk, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, hr_ssp_din, hs_ssp_din, hisn_ssp_din, he_ssp_din, hfl_ssp_din, gt_ssp_din, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, hr_ssp_frame, hs_ssp_frame, hisn_ssp_frame, he_ssp_frame, hfl_ssp_frame, gt_ssp_frame, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, hr_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, he_pwr_oe1, hfl_pwr_oe1, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, hr_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, he_pwr_oe2, hfl_pwr_oe2, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, hr_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, he_pwr_oe3, hfl_pwr_oe3, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, hr_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, he_pwr_oe4, hfl_pwr_oe4, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, hr_pwr_lo, hs_pwr_lo, hisn_pwr_lo, he_pwr_lo, hfl_pwr_lo, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, hr_pwr_hi, hs_pwr_hi, hisn_pwr_hi, he_pwr_hi, hfl_pwr_hi, 1'b0, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, hr_adc_clk, hs_adc_clk, hisn_adc_clk, he_adc_clk, hfl_adc_clk, 1'b0, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, hr_dbg, hs_dbg, hisn_dbg, he_dbg, hfl_dbg, 1'b0, 1'b0, 1'b0); - -// In all modes, let the ADC's outputs be enabled. -assign adc_noe = 1'b0; - -endmodule diff --git a/fpga-xc3s100e/fpga_lfmod.v b/fpga-xc3s100e/fpga_lfmod.v deleted file mode 100644 index 5982a74e82..0000000000 --- a/fpga-xc3s100e/fpga_lfmod.v +++ /dev/null @@ -1,236 +0,0 @@ -//----------------------------------------------------------------------------- -// Jonathan Westhues, March 2006 -// iZsh , June 2014 -// Piwi, Feb 2019 -// Anon, 2019 -//----------------------------------------------------------------------------- -// Defining commands, modes and options. This must be aligned to the definitions in fpgaloader.h -// Note: the definitions here are without shifts - -// Commands: -`define FPGA_CMD_SET_CONFREG 1 -`define FPGA_CMD_SET_DIVISOR 2 -`define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD 3 - -// Major modes: -`define FPGA_MAJOR_MODE_LF_READER 0 -`define FPGA_MAJOR_MODE_LF_EDGE_DETECT 1 -`define FPGA_MAJOR_MODE_LF_PASSTHRU 2 -`define FPGA_MAJOR_MODE_LF_ADC 3 - -// Options for LF_READER -`define FPGA_LF_ADC_READER_FIELD 1 - -// Options for LF_EDGE_DETECT -`define FPGA_LF_EDGE_DETECT_READER_FIELD 1 -`define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 2 - -//For ISE 10.1 PROJ,IDE auto include -//`include "lo_read.v" -//`include "lo_passthru.v" -//`include "lo_edge_detect.v" -//`include "lo_adc.v" -//`include "util.v" -//`include "clk_divider.v" - -module fpga_lfmod( - input spck, output miso, input mosi, input ncs, - input pck0, input ck_1356meg, input ck_1356megb, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, output adc_noe, - output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk, - input cross_hi, input cross_lo, - output dbg, - output PWR_LO_EN -); - -//----------------------------------------------------------------------------- -// The SPI receiver. This sets up the configuration word, which the rest of -// the logic looks at to determine how to connect the A/D and the coil -// drivers (i.e., which section gets it). Also assign some symbolic names -// to the configuration bits, for use below. -//----------------------------------------------------------------------------- - -/* - Attempt to write up how its hooked up. Iceman 2020. - - Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand() - Send 16 bit command / data pair to FPGA - The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 - where - C is 4bit command - D is 12bit data - - shift_reg receive this 16bit frame - - LF command - ---------- - shift_reg[15:12] == 4bit command - LF has three commands (FPGA_CMD_SET_CONFREG, FPGA_CMD_SET_DIVISOR, FPGA_CMD_SET_EDGE_DETECT_THRESHOLD) - Current commands uses only 2bits. We have room for up to 4bits of commands total (7). - - LF data - ------- - shift_reg[11:0] == 12bit data - lf data is divided into MAJOR MODES and configuration values. - - The major modes uses 3bits (0,1,2,3,7 | 000, 001, 010, 011, 111) - 000 FPGA_MAJOR_MODE_LF_READER = Act as LF reader (modulate) - 001 FPGA_MAJOR_MODE_LF_EDGE_DETECT = Simulate LF - 010 FPGA_MAJOR_MODE_LF_PASSTHRU = Passthrough mode, CROSS_LO line connected to SSP_DIN. SSP_DOUT logic level controls if we modulate / listening - 011 FPGA_MAJOR_MODE_LF_ADC = refactor hitag2, clear ADC sampling - 111 FPGA_MAJOR_MODE_OFF = turn off sampling. - - Each one of this major modes can have options. Currently these two major modes uses options. - - FPGA_MAJOR_MODE_LF_READER - - FPGA_MAJOR_MODE_LF_EDGE_DETECT - - FPGA_MAJOR_MODE_LF_READER - ------------------------------------- - lf_field = 1bit (FPGA_LF_ADC_READER_FIELD) - - You can send FPGA_CMD_SET_DIVISOR to set with FREQUENCY the fpga should sample at - divisor = 8bits shift_reg[7:0] - - FPGA_MAJOR_MODE_LF_EDGE_DETECT - ------------------------------------------ - lf_ed_toggle_mode = 1bits - lf_ed_threshold = 8bits threshold defaults to 127 - - You can send FPGA_CMD_SET_EDGE_DETECT_THRESHOLD to set a custom threshold - lf_ed_threshold = 8bits threshold value. - - conf_word 12bits - conf_word[7:5] = 3bit major mode. - conf_word[0] = 1bit lf_field - conf_word[1] = 1bit lf_ed_toggle_mode - conf_word[7:0] = 8bit divisor - conf_word[7:0] = 8bit threshold - ------+--------- frame layout -------------------- -bit | 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ------+------------------------------------------- -cmd | x x x x -major| x x x -opt | x x -divi | x x x x x x x x -thres| x x x x x x x x ------+------------------------------------------- -*/ - -reg [15:0] shift_reg; -reg [7:0] divisor; -reg [7:0] lf_ed_threshold; -reg [11:0] conf_word; - -wire [2:0] major_mode = conf_word[8:6]; -wire lf_field = conf_word[0]; -wire lf_ed_toggle_mode = conf_word[1]; - -// Handles cmd / data frame from ARM -always @(posedge ncs) -begin - // 4 bit command - case (shift_reg[15:12]) - `FPGA_CMD_SET_CONFREG: - begin - // 12 bit data - conf_word <= shift_reg[11:0]; - if (shift_reg[8:6] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT) - begin - lf_ed_threshold <= 127; // default threshold - end - end - - `FPGA_CMD_SET_DIVISOR: - divisor <= shift_reg[7:0]; // 8bits - - `FPGA_CMD_SET_EDGE_DETECT_THRESHOLD: - lf_ed_threshold <= shift_reg[7:0]; // 8 bits - endcase -end - -// Receive 16bits of data from ARM here. -always @(posedge spck) -begin - if (~ncs) - begin - shift_reg[15:1] <= shift_reg[14:0]; - shift_reg[0] <= mosi; - end -end - -//----------------------------------------------------------------------------- -// And then we instantiate the modules corresponding to each of the FPGA's -// major modes, and use muxes to connect the outputs of the active mode to -// the output pins. -//----------------------------------------------------------------------------- -wire [7:0] pck_cnt; -wire pck_divclk; -clk_divider div_clk(pck0, divisor, pck_cnt, pck_divclk); - -lo_read lr( - pck0, pck_cnt, pck_divclk, - lr_pwr_lo, lr_pwr_hi, lr_pwr_oe1, lr_pwr_oe2, lr_pwr_oe3, lr_pwr_oe4, - adc_d, lr_adc_clk, - lr_ssp_frame, lr_ssp_din, lr_ssp_clk, - lr_dbg, lf_field -); - -lo_passthru lp( - pck_divclk, - lp_pwr_lo, lp_pwr_hi, lp_pwr_oe1, lp_pwr_oe2, lp_pwr_oe3, lp_pwr_oe4, - lp_adc_clk, - lp_ssp_din, ssp_dout, - cross_lo, - lp_dbg -); - -lo_edge_detect le( - pck0, pck_divclk, - le_pwr_lo, le_pwr_hi, le_pwr_oe1, le_pwr_oe2, le_pwr_oe3, le_pwr_oe4, - adc_d, le_adc_clk, - le_ssp_frame, ssp_dout, le_ssp_clk, - cross_lo, - le_dbg, - lf_field, - lf_ed_toggle_mode, lf_ed_threshold -); - -lo_adc la( - pck0, - la_pwr_lo, la_pwr_hi, la_pwr_oe1, la_pwr_oe2, la_pwr_oe3, la_pwr_oe4, - adc_d, la_adc_clk, - la_ssp_frame, la_ssp_din, ssp_dout, la_ssp_clk, - la_dbg, divisor, - lf_field -); - -// Major modes: -// 000 -- LF reader (generic) -// 001 -- LF edge detect (generic) -// 010 -- LF passthrough -// 011 -- LF ADC (read/write) -// 100 -- unused -// 101 -- unused -// 110 -- unused -// 111 -- FPGA_MAJOR_MODE_OFF -// 000 001 010 011 100 101 110 111 -mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, la_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, la_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, le_ssp_frame, 1'b0, la_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, le_pwr_oe1, lp_pwr_oe1, la_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, le_pwr_oe2, lp_pwr_oe2, la_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, le_pwr_oe3, lp_pwr_oe3, la_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, le_pwr_oe4, lp_pwr_oe4, la_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, la_pwr_lo, 1'b0, 1'b0, 1'b1, 1'b0); -mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, le_pwr_hi, lp_pwr_hi, la_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, le_adc_clk, lp_adc_clk, la_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_dbg (major_mode, dbg, lr_dbg, le_dbg, lp_dbg, la_dbg, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ant (major_mode, PWR_LO_EN, 1'b1, 1'b1, 1'b1, 1'b1, 1'b0, 1'b0, 1'b0, 1'b0); - -// In all modes, let the ADC's outputs be enabled. -assign adc_noe = 1'b0; - -endmodule diff --git a/fpga-xc3s100e/hi_flite.v b/fpga-xc3s100e/hi_flite.v deleted file mode 100644 index 6cb87825e6..0000000000 --- a/fpga-xc3s100e/hi_flite.v +++ /dev/null @@ -1,368 +0,0 @@ -/* - This code demodulates and modulates signal as described in ISO/IEC 18092. - That includes packets used for Felica, NFC Tag 3, etc. (which do overlap) - simple envelope following algorithm is used (modification of fail0verflow LF one) - is used to combat some nasty aliasing effect with testing phone (envelope looked like sine wave) - - Speeds supported: only 212 kbps (fc/64) for now. Todo: 414 kbps - though for reader, the selection has to come from ARM. modulation waits for market sprocket -doesn't really mean anything - - mod_type: bits 210: - bit 2 : reader drive/power on/off - bit 1 : speed bit, 0 : 212, 1 :424 - bit 0 : listen or modulate -*/ - -module hi_flite( - ck_1356meg, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - dbg, - mod_type -); - input ck_1356meg; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - output dbg; - input [3:0] mod_type; - -assign dbg = 0; - -wire power = mod_type[2]; -wire speed = mod_type[1]; -wire disabl = mod_type[0]; - -// Most off, oe4 for modulation; -// Trying reader emulation (would presumably just require switching power on, but I am not sure) -assign pwr_lo = 1'b0; - -// 512x64/fc -wait before ts0, 32768 ticks -// tslot: 256*64/fc -assign adc_clk = ck_1356meg; - -///heuristic values for initial thresholds. seem to work OK -`define imin 70 // (13'd256) -`define imax 180 // (-13'd256) -`define ithrmin 91 // -13'd8 -`define ithrmax 160 // 13'd8 - -`define min_bitdelay_212 8 -//minimum values and corresponding thresholds -reg [8:0] curmin=`imin; -reg [8:0] curminthres=`ithrmin; -reg [8:0] curmaxthres=`ithrmax; -reg [8:0] curmax=`imax; - -//signal state, 1-not modulated, 0 -modulated -reg after_hysteresis = 1'b1; - -//state machine for envelope tracking -reg [1:0] state=1'd0; - -//lower edge detected, trying to detect first bit of SYNC (b24d, 1011001001001101) -reg try_sync=1'b0; - -//detected first sync bit, phase frozen -reg did_sync=0; - -`define bithalf_212 32 // half-bit length for 212 kbit -`define bitmlen_212 63 // bit transition edge - -`define bithalf_424 16 // half-bit length for 212 kbit -`define bitmlen_424 31 // bit transition edge - -wire [7:0] bithalf = speed ? `bithalf_424 : `bithalf_212; -wire [7:0] bitmlen = speed ? `bitmlen_424 : `bitmlen_212; - - -//ssp clock and current values -reg ssp_clk; -reg ssp_frame; -reg curbit = 1'b0; - -reg [7:0] fccount = 8'd0; // in-bit tick counter. Counts carrier cycles from the first lower edge detected, reset on every manchester bit detected - -reg [7:0] tsinceedge = 8'd0;// ticks from last edge, desync if the valye is too large - -reg zero = 1'b0; // Manchester first halfbit low second high corresponds to this value. It has been known to change. SYNC is used to set it - -//ssp counter for transfer and framing -reg [8:0] ssp_cnt = 9'd0; - -always @(posedge adc_clk) - ssp_cnt <= (ssp_cnt + 1); - -//maybe change it so that ARM sends preamble as well. -//then: ready bits sent to ARM, 8 bits sent from ARM (all ones), then preamble (all zeros, presumably) - which starts modulation - -always @(negedge adc_clk) -begin - //count fc/64 - transfer bits to ARM at the rate they are received - if( ((~speed) && (ssp_cnt[5:0] == 6'b000000)) || (speed && (ssp_cnt[4:0] == 5'b00000))) - begin - ssp_clk <= 1'b1; - ssp_din <= curbit; - end - if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000)) - ssp_clk <= 1'b0; - //create frame pulses. TBH, I still don't know what they do exactly, but they are crucial for ARM->FPGA transfer. If the frame is in the beginning of the byte, transfer slows to a crawl for some reason - // took me a day to figure THAT out. - if(( (~speed) && (ssp_cnt[8:0] == 9'd31)) || (speed && ssp_cnt[7:0] == 8'd15)) - begin - ssp_frame <= 1'b1; - end - if(( (~speed) && (ssp_cnt[8:0] == 9'b1011111)) || (speed &&ssp_cnt[7:0] == 8'b101111) ) - begin - ssp_frame <= 1'b0; - end -end - -//send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise) -reg ssp_din; - -//previous signal value, mostly to detect SYNC -reg prv = 1'b1; - -// for simple error correction in mod/demod detection, use maximum of modded/demodded in given interval. Maybe 1 bit is extra? but better safe than sorry. -reg[7:0] mid = 8'd128; - -// set TAGSIM__MODULATE on ARM if we want to write... (frame would get lost if done mid-frame...) -// start sending over 1s on ssp->arm when we start sending preamble -// reg sending = 1'b0; // are we actively modulating? -reg [11:0] bit_counts = 12'd0; // for timeslots. only support ts=0 for now, at 212 speed -512 fullbits from end of frame. One hopes. might remove those? - - -//we need some way to flush bit_counts triggers on mod_type changes don't compile -reg dlay; -always @(negedge adc_clk) // every data ping? -begin - //envelope follow code... - //////////// - if (fccount == bitmlen) - begin - if ((~try_sync) && (adc_d < curminthres) && disabl ) - begin - fccount <= 1; - end - else - begin - fccount <= 0; - end - dlay <= ssp_dout; - if (bit_counts > 768) // should be over ts0 now, without ARM interference... stop counting... - begin - bit_counts <= 0; - end - else - if (power) - bit_counts <= 0; - else - bit_counts <= bit_counts + 1; - end - else - begin - if((~try_sync) && (adc_d < curminthres) && disabl) - begin - fccount <= 1; - end - else - begin - fccount <= fccount + 1; - end - end - - // rising edge - if (adc_d > curmaxthres) - begin - case (state) - 0: begin - curmax <= adc_d > `imax? adc_d : `imax; - state <= 2; - end - 1: begin - curminthres <= ((curmin >> 1) + (curmin >> 2) + (curmin >> 4) + (curmax >> 3) + (curmax >> 4)); //threshold: 0.1875 max + 0.8125 min - curmaxthres <= ((curmax >> 1) + (curmax >> 2) + (curmax >> 4) + (curmin >> 3) + (curmin >> 4)); - curmax <= adc_d > 155 ? adc_d : 155; // to hopefully prevent overflow from spikes going up to 255 - state <= 2; - end - 2: begin - if (adc_d > curmax) - curmax <= adc_d; - end - default: - begin - end - endcase - after_hysteresis <= 1'b1; - if(try_sync) - tsinceedge <= 0; - end - else if (adc_d> 1) + (curmin >> 2) + (curmin >> 4) + (curmax >> 3) + (curmax >> 4)); - curmaxthres <= ( (curmax >> 1) + (curmax >> 2) + (curmax >> 4) + (curmin >> 3) + (curmin >> 4)); - curmin <= adc_d < `imin ? adc_d : `imin; - state <= 1; - end - default: - begin - end - endcase - after_hysteresis <= 0; - if (~try_sync ) //begin modulation, lower edge... - begin - try_sync <= 1; - fccount <= 1; - did_sync <= 0; - curbit <= 0; - mid <= 8'd127; - tsinceedge <= 0; - prv <= 1; - end - else - begin - tsinceedge <= 0; - end - end - else //stable state, low or high - begin - curminthres <= ( (curmin >> 1) + (curmin >> 2) + (curmin >> 4) + (curmax >> 3) + (curmax >> 4)); - curmaxthres <= ( (curmax >> 1) + (curmax >> 2) + (curmax >> 4) + (curmin >> 3) + (curmin >> 4)); - state <= 0; - - if (try_sync ) - begin - if (tsinceedge >= (128)) - begin - //we might need to start counting... assuming ARM wants to reply to the frame. - bit_counts <= 1;// i think? 128 is about 2 bits passed... but 1 also works - try_sync <= 0; - did_sync <= 0;//desync - curmin <= `imin; //reset envelope - curmax <= `imax; - curminthres <= `ithrmin; - curmaxthres <= `ithrmax; - prv <= 1; - tsinceedge <= 0; - after_hysteresis <= 1'b1; - curbit <= 0; - mid <= 8'd128; - end - else - tsinceedge <= (tsinceedge + 1); - end - end - - - if (try_sync && tsinceedge < 128) - begin - //detect bits in their middle ssp sampling is in sync, so it would sample all bits in order - if (fccount == bithalf) - begin - if ((~did_sync) && ((prv == 1 && (mid > 128))||(prv == 0 && (mid <= 128)))) - begin - //sync the Zero, and set curbit roperly - did_sync <= 1'b1; - zero <= ~prv;// 1-prv - curbit <= 1; - end - else - curbit <= (mid > 128) ? (~zero) : zero; - - prv <= (mid > 128) ? 1 : 0; - - if (adc_d > curmaxthres) - mid <= 8'd129; - else if (adc_d < curminthres) - mid <= 8'd127; - else - begin - if (after_hysteresis) - begin - mid <= 8'd129; - end - else - begin - mid <= 8'd127; - end - end - - end - else - begin - if (fccount==bitmlen) - begin - // fccount <= 0; - prv <= (mid > 128) ? 1 : 0; - mid <= 128; - end - else - begin - // minimum-maximum calc - if(adc_d > curmaxthres) - mid <= mid + 1; - else if (adc_d < curminthres) - mid <= mid - 1; - else - begin - if (after_hysteresis) - begin - mid <= mid + 1; - end - else - begin - mid <= mid - 1; - end - end - end - end - end - else - begin - end -// sending <= 0; -end -//put modulation here to maintain the correct clock. Seems that some readers are sensitive to that -reg pwr_hi; -reg pwr_oe1; -reg pwr_oe2; -reg pwr_oe3; -reg pwr_oe4; - -wire mod = ((fccount >= bithalf) ^ dlay) & (~disabl); - -always @(ck_1356meg or ssp_dout or power or disabl or mod) -begin - if (power) - begin - pwr_hi <= ck_1356meg; - pwr_oe1 <= 1'b0;//mod; - pwr_oe2 <= 1'b0;//mod; - pwr_oe3 <= 1'b0;//mod; - pwr_oe4 <= mod;//1'b0; - end - else - begin - pwr_hi <= 1'b0; - pwr_oe1 <= 1'b0; - pwr_oe2 <= 1'b0; - pwr_oe3 <= 1'b0; - pwr_oe4 <= mod; - end -end - -endmodule diff --git a/fpga-xc3s100e/hi_get_trace.v b/fpga-xc3s100e/hi_get_trace.v deleted file mode 100644 index 2b1cf393b3..0000000000 --- a/fpga-xc3s100e/hi_get_trace.v +++ /dev/null @@ -1,164 +0,0 @@ -//----------------------------------------------------------------------------- -// -// piwi, Feb 2019 -//----------------------------------------------------------------------------- -//For ISE 10.1 PROJ,IDE cannot apply definition to all files -`include "define.v" - -module hi_get_trace( - ck_1356megb, - adc_d, trace_enable, major_mode, - ssp_frame, ssp_din, ssp_clk -); - input ck_1356megb; - input [7:0] adc_d; - input trace_enable; - input [2:0] major_mode; - output ssp_frame, ssp_din, ssp_clk; - -// clock divider -reg [6:0] clock_cnt; -always @(negedge ck_1356megb) -begin - clock_cnt <= clock_cnt + 1; -end - -// sample at 13,56MHz / 8. The highest signal frequency (subcarrier) is 848,5kHz, i.e. in this case we oversample by a factor of 2 -reg [2:0] sample_clock; -always @(negedge ck_1356megb) -begin - if (sample_clock == 3'd7) - sample_clock <= 3'd0; - else - sample_clock <= sample_clock + 1; -end - - -reg [11:0] addr; -reg [11:0] start_addr; -reg [2:0] previous_major_mode; -reg write_enable1; -reg write_enable2; -always @(negedge ck_1356megb) -begin - previous_major_mode <= major_mode; - if (major_mode == `FPGA_MAJOR_MODE_HF_GET_TRACE) - begin - write_enable1 <= 1'b0; - write_enable2 <= 1'b0; - if (previous_major_mode != `FPGA_MAJOR_MODE_HF_GET_TRACE) // just switched into GET_TRACE mode - addr <= start_addr; - if (clock_cnt == 7'd0) - begin - if (addr == 12'd3071) - addr <= 12'd0; - else - addr <= addr + 1; - end - end - else if (major_mode != `FPGA_MAJOR_MODE_OFF) - begin - if (trace_enable) - begin - if (addr[11] == 1'b0) - begin - write_enable1 <= 1'b1; - write_enable2 <= 1'b0; - end - else - begin - write_enable1 <= 1'b0; - write_enable2 <= 1'b1; - end - if (sample_clock == 3'b000) - begin - if (addr == 12'd3071) - begin - addr <= 12'd0; - write_enable1 <= 1'b1; - write_enable2 <= 1'b0; - end - else - begin - addr <= addr + 1; - end - end - end - else - begin - write_enable1 <= 1'b0; - write_enable2 <= 1'b0; - start_addr <= addr; - end - end - else // major_mode == `FPGA_MAJOR_MODE_OFF - begin - write_enable1 <= 1'b0; - write_enable2 <= 1'b0; - if (previous_major_mode != `FPGA_MAJOR_MODE_OFF && previous_major_mode != `FPGA_MAJOR_MODE_HF_GET_TRACE) // just switched off - begin - start_addr <= addr; - end - end -end - - -// (2+1)k RAM -reg [7:0] D_out1, D_out2; -reg [7:0] ram1 [2047:0]; // 2048 u8 -reg [7:0] ram2 [1023:0]; // 1024 u8 - -always @(negedge ck_1356megb) -begin - if (write_enable1) - begin - ram1[addr[10:0]] <= adc_d; - D_out1 <= adc_d; - end - else - D_out1 <= ram1[addr[10:0]]; - if (write_enable2) -begin - ram2[addr[9:0]] <= adc_d; - D_out2 <= adc_d; - end - else - D_out2 <= ram2[addr[9:0]]; -end - - -// SSC communication to ARM -reg ssp_clk; -reg ssp_frame; -reg [7:0] shift_out; - -always @(negedge ck_1356megb) -begin - if (clock_cnt[3:0] == 4'd0) // update shift register every 16 clock cycles - begin - if (clock_cnt[6:4] == 3'd0) // either load new value - begin - if (addr[11] == 1'b0) - shift_out <= D_out1; - else - shift_out <= D_out2; - end - else - begin - // or shift left - shift_out[7:1] <= shift_out[6:0]; - end - end - - ssp_clk <= ~clock_cnt[3]; // ssp_clk frequency = 13,56MHz / 16 = 847,5 kHz - - if (clock_cnt[6:4] == 3'b000) // set ssp_frame for 0...31 - ssp_frame <= 1'b1; - else - ssp_frame <= 1'b0; - -end - -assign ssp_din = shift_out[7]; - -endmodule diff --git a/fpga-xc3s100e/hi_iso14443a.v b/fpga-xc3s100e/hi_iso14443a.v deleted file mode 100644 index 26ab0f9d95..0000000000 --- a/fpga-xc3s100e/hi_iso14443a.v +++ /dev/null @@ -1,584 +0,0 @@ -//----------------------------------------------------------------------------- -// ISO14443-A support for the Proxmark III -// Gerhard de Koning Gans, April 2008 -//----------------------------------------------------------------------------- - -module hi_iso14443a( - ck_1356meg, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - dbg, - mod_type -); - input ck_1356meg; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - output dbg; - input [3:0] mod_type; - - -wire adc_clk = ck_1356meg; - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Reader -> PM3: -// detecting and shaping the reader's signal. Reader will modulate the carrier by 100% (signal is either on or off). Use a -// hysteresis (Schmitt Trigger) to avoid false triggers during slowly increasing or decreasing carrier amplitudes -reg after_hysteresis; -reg [11:0] has_been_low_for; - -always @(negedge adc_clk) -begin - if(adc_d >= 16) after_hysteresis <= 1'b1; // U >= 1,14V -> after_hysteresis = 1 - else if(adc_d < 8) after_hysteresis <= 1'b0; // U < 1,04V -> after_hysteresis = 0 - // Note: was >= 3,53V and <= 1,19V. The new trigger values allow more reliable detection of the first bit - // (it might not reach 3,53V due to the high time constant of the high pass filter in the analogue RF part). - // In addition, the new values are more in line with ISO14443-2: "The PICC shall detect the ”End of Pause” after the field exceeds - // 5% of H_INITIAL and before it exceeds 60% of H_INITIAL." Depending on the signal strength, 60% might well be less than 3,53V. - - - // detecting a loss of reader's field (adc_d < 192 for 4096 clock cycles). If this is the case, - // set the detected reader signal (after_hysteresis) to '1' (unmodulated) - if(adc_d >= 192) - begin - has_been_low_for <= 12'd0; - end - else - begin - if(has_been_low_for == 12'd4095) - begin - has_been_low_for <= 12'd0; - after_hysteresis <= 1'b1; - end - else - begin - has_been_low_for <= has_been_low_for + 1; - end - end - -end - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Reader -> PM3 -// detect when a reader is active (modulating). We assume that the reader is active, if we see the carrier off for at least 8 -// carrier cycles. We assume that the reader is inactive, if the carrier stayed high for at least 256 carrier cycles. -reg deep_modulation; -reg [2:0] deep_counter; -reg [8:0] saw_deep_modulation; - -always @(negedge adc_clk) -begin - if(~(| adc_d[7:0])) // if adc_d == 0 (U <= 0,94V) - begin - if(deep_counter == 3'd7) // adc_d == 0 for 8 adc_clk ticks -> deep_modulation (by reader) - begin - deep_modulation <= 1'b1; - saw_deep_modulation <= 8'd0; - end - else - deep_counter <= deep_counter + 1; - end - else - begin - deep_counter <= 3'd0; - if(saw_deep_modulation == 8'd255) // adc_d != 0 for 256 adc_clk ticks -> deep_modulation is over, probably waiting for tag's response - deep_modulation <= 1'b0; - else - saw_deep_modulation <= saw_deep_modulation + 1; - end -end - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Tag -> PM3 -// filter the input for a tag's signal. The filter box needs the 4 previous input values and is a gaussian derivative filter -// for noise reduction and edge detection. -// store 4 previous samples: -reg [7:0] input_prev_4, input_prev_3, input_prev_2, input_prev_1; - -always @(negedge adc_clk) -begin - input_prev_4 <= input_prev_3; - input_prev_3 <= input_prev_2; - input_prev_2 <= input_prev_1; - input_prev_1 <= adc_d; -end - -// adc_d_filtered = 2*input_prev4 + 1*input_prev3 + 0*input_prev2 - 1*input_prev1 - 2*input -// = (2*input_prev4 + input_prev3) - (2*input + input_prev1) -wire [8:0] input_prev_4_times_2 = input_prev_4 << 1; -wire [8:0] adc_d_times_2 = adc_d << 1; - -wire [9:0] tmp1 = input_prev_4_times_2 + input_prev_3; -wire [9:0] tmp2 = adc_d_times_2 + input_prev_1; - -// convert intermediate signals to signed and calculate the filter output -wire signed [10:0] adc_d_filtered = {1'b0, tmp1} - {1'b0, tmp2}; - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// internal FPGA timing. Maximum required period is 128 carrier clock cycles for a full 8 Bit transfer to ARM. (i.e. we need a -// 7 bit counter). Adjust its frequency to external reader's clock when simulating a tag or sniffing. -reg pre_after_hysteresis; -reg [3:0] reader_falling_edge_time; -reg [6:0] negedge_cnt; - -always @(negedge adc_clk) -begin - // detect a reader signal's falling edge and remember its timing: - pre_after_hysteresis <= after_hysteresis; - if (pre_after_hysteresis && ~after_hysteresis) - begin - reader_falling_edge_time[3:0] <= negedge_cnt[3:0]; - end - - // adjust internal timer counter if necessary: - if (negedge_cnt[3:0] == 4'd13 && (mod_type == `FPGA_HF_ISO14443A_SNIFFER || mod_type == `FPGA_HF_ISO14443A_TAGSIM_LISTEN) && deep_modulation) - begin - if (reader_falling_edge_time == 4'd1) // reader signal changes right after sampling. Better sample earlier next time. - begin - negedge_cnt <= negedge_cnt + 2; // time warp - end - else if (reader_falling_edge_time == 4'd0) // reader signal changes right before sampling. Better sample later next time. - begin - negedge_cnt <= negedge_cnt; // freeze time - end - else - begin - negedge_cnt <= negedge_cnt + 1; // Continue as usual - end - reader_falling_edge_time[3:0] <= 4'd8; // adjust only once per detected edge - end - else if (negedge_cnt == 7'd127) // normal operation: count from 0 to 127 - begin - negedge_cnt <= 0; - end - else - begin - negedge_cnt <= negedge_cnt + 1; - end -end - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Tag -> PM3: -// determine best possible time for starting/resetting the modulation detector. -reg [3:0] mod_detect_reset_time; - -always @(negedge adc_clk) -begin - if (mod_type == `FPGA_HF_ISO14443A_READER_LISTEN) - // (our) reader signal changes at negedge_cnt[3:0]=9, tag response expected to start n*16+4 ticks later, further delayed by - // 3 ticks ADC conversion. The maximum filter output (edge detected) will be detected after subcarrier zero crossing (+7 ticks). - // To allow some timing variances, we want to have the maximum filter outputs well within the detection window, i.e. - // at mod_detect_reset_time+4 and mod_detect_reset_time+12 (-4 ticks). - // 9 + 4 + 3 + 7 - 4 = 19. 19 mod 16 = 3 - begin - mod_detect_reset_time <= 4'd4; - end - else - if (mod_type == `FPGA_HF_ISO14443A_SNIFFER) - begin - // detect a rising edge of reader's signal and sync modulation detector to the tag's answer: - if (~pre_after_hysteresis && after_hysteresis && deep_modulation) - // reader signal rising edge detected at negedge_cnt[3:0]. This signal had been delayed - // 9 ticks by the RF part + 3 ticks by the A/D converter + 1 tick to assign to after_hysteresis. - // Then the same as above. - // - 9 - 3 - 1 + 4 + 3 + 7 - 4 = -3 - begin - mod_detect_reset_time <= negedge_cnt[3:0] - 4'd3; - end - end -end - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Tag -> PM3: -// modulation detector. Looks for the steepest falling and rising edges within a 16 clock period. If there is both a significant -// falling and rising edge (in any order), a modulation is detected. -reg signed [10:0] rx_mod_falling_edge_max; -reg signed [10:0] rx_mod_rising_edge_max; -reg curbit; - -`define EDGE_DETECT_THRESHOLD 3 -`define EDGE_DETECT_THRESHOLDHIGH 20 - -always @(negedge adc_clk) -begin - if(negedge_cnt[3:0] == mod_detect_reset_time) - begin - if (mod_type == `FPGA_HF_ISO14443A_SNIFFER) - begin - // detect modulation signal: if modulating, there must have been a falling AND a rising edge - if ((rx_mod_falling_edge_max > `EDGE_DETECT_THRESHOLDHIGH) && (rx_mod_rising_edge_max < -`EDGE_DETECT_THRESHOLDHIGH)) - curbit <= 1'b1; // modulation - else - curbit <= 1'b0; // no modulation - end - else - begin - // detect modulation signal: if modulating, there must have been a falling AND a rising edge - if ((rx_mod_falling_edge_max > `EDGE_DETECT_THRESHOLD) && (rx_mod_rising_edge_max < -`EDGE_DETECT_THRESHOLD)) - curbit <= 1'b1; // modulation - else - curbit <= 1'b0; // no modulation - end - // reset modulation detector - rx_mod_rising_edge_max <= 0; - rx_mod_falling_edge_max <= 0; - end - else // look for steepest edges (slopes) - begin - if (adc_d_filtered > 0) - begin - if (adc_d_filtered > rx_mod_falling_edge_max) - rx_mod_falling_edge_max <= adc_d_filtered; - end - else - begin - if (adc_d_filtered < rx_mod_rising_edge_max) - rx_mod_rising_edge_max <= adc_d_filtered; - end - end - -end - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// Tag+Reader -> PM3 -// sample 4 bits reader data and 4 bits tag data for sniffing -reg [3:0] reader_data; -reg [3:0] tag_data; - -always @(negedge adc_clk) -begin - if(negedge_cnt[3:0] == 4'd0) - begin - reader_data[3:0] <= {reader_data[2:0], after_hysteresis}; - tag_data[3:0] <= {tag_data[2:0], curbit}; - end -end - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// PM3 -> Reader: -// a delay line to ensure that we send the (emulated) tag's answer at the correct time according to ISO14443-3 -reg [31:0] mod_sig_buf; -reg [4:0] mod_sig_ptr; -reg mod_sig; - -always @(negedge adc_clk) -begin - if(negedge_cnt[3:0] == 4'd0) // sample data at rising edge of ssp_clk - ssp_dout changes at the falling edge. - begin - mod_sig_buf[31:2] <= mod_sig_buf[30:1]; // shift - if (~ssp_dout && ~mod_sig_buf[1]) - mod_sig_buf[1] <= 1'b0; // delete the correction bit (a single 1 preceded and succeeded by 0) - else - mod_sig_buf[1] <= mod_sig_buf[0]; - mod_sig_buf[0] <= ssp_dout; // add new data to the delay line - - mod_sig = mod_sig_buf[mod_sig_ptr]; // the delayed signal. - end -end - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// PM3 -> Reader, internal timing: -// a timer for the 1172 cycles fdt (Frame Delay Time). Start the timer with a rising edge of the reader's signal. -// set fdt_elapsed when we no longer need to delay data. Set fdt_indicator when we can start sending data. -// Note: the FPGA only takes care for the 1172 delay. To achieve an additional 1236-1172=64 ticks delay, the ARM must send -// a correction bit (before the start bit). The correction bit will be coded as 00010000, i.e. it adds 4 bits to the -// transmission stream, causing the required additional delay. -reg [10:0] fdt_counter; -reg fdt_indicator, fdt_elapsed; -reg [3:0] mod_sig_flip; -reg [3:0] sub_carrier_cnt; - -// we want to achieve a delay of 1172. The RF part already has delayed the reader signals's rising edge -// by 9 ticks, the ADC took 3 ticks and there is always a delay of 32 ticks by the mod_sig_buf. Therefore need to -// count to 1172 - 9 - 3 - 32 = 1128 -`define FDT_COUNT 11'd1128 - -// The ARM must not send too early, otherwise the mod_sig_buf will overflow, therefore signal that we are ready -// with fdt_indicator. The mod_sig_buf can buffer 29 excess data bits, i.e. a maximum delay of 29 * 16 = 464 adc_clk ticks. -// fdt_indicator is assigned to sendbit after at least 1 tick, the transfer to ARM needs minimum 8 ticks. Response from -// ARM could appear at ssp_dout 8 ticks later. -// 1128 - 464 - 1 - 8 - 8 = 647 -`define FDT_INDICATOR_COUNT 11'd647 -// Note: worst case, assignment to sendbit takes 15 ticks more, and transfer to ARM needs 7*16 = 112 ticks more. -// When the ARM's response then appears, the fdt_count is already 647 + 15 + 112 = 774, which still allows the ARM a possible -// response window of 1128 - 774 = 354 ticks. - -// reset on a pause in listen mode. I.e. the counter starts when the pause is over: -assign fdt_reset = ~after_hysteresis && mod_type == `FPGA_HF_ISO14443A_TAGSIM_LISTEN; - -always @(negedge adc_clk) -begin - if (fdt_reset) - begin - fdt_counter <= 11'd0; - fdt_elapsed <= 1'b0; - fdt_indicator <= 1'b0; - end - else - begin - if(fdt_counter == `FDT_COUNT) - begin - if(~fdt_elapsed) // just reached fdt. - begin - mod_sig_flip <= negedge_cnt[3:0]; // start modulation at this time - sub_carrier_cnt <= 4'd0; // subcarrier phase in sync with start of modulation - fdt_elapsed <= 1'b1; - end - else - begin - sub_carrier_cnt <= sub_carrier_cnt + 1; - end - end - else - begin - fdt_counter <= fdt_counter + 1; - end - end - - if(fdt_counter == `FDT_INDICATOR_COUNT) fdt_indicator <= 1'b1; -end - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// PM3 -> Reader or Tag -// assign a modulation signal to the antenna. This signal is either a delayed signal (to achieve fdt when sending to a reader) -// or undelayed when sending to a tag -reg mod_sig_coil; - -always @(negedge adc_clk) -begin - if (mod_type == `FPGA_HF_ISO14443A_TAGSIM_MOD) // need to take care of proper fdt timing - begin - if(fdt_counter == `FDT_COUNT) - begin - if(fdt_elapsed) - begin - if(negedge_cnt[3:0] == mod_sig_flip) mod_sig_coil <= mod_sig; - end - else - begin - mod_sig_coil <= mod_sig; // just reached fdt. Immediately assign signal to coil - end - end - end - else // other modes: don't delay - begin - mod_sig_coil <= ssp_dout; - end -end - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// PM3 -> Reader -// determine the required delay in the mod_sig_buf (set mod_sig_ptr). -reg temp_buffer_reset; - -always @(negedge adc_clk) -begin - if(fdt_reset) - begin - mod_sig_ptr <= 5'd0; - temp_buffer_reset = 1'b0; - end - else - begin - if(fdt_counter == `FDT_COUNT && ~fdt_elapsed) // if we just reached fdt - if(~(| mod_sig_ptr[4:0])) - mod_sig_ptr <= 5'd8; // ... but didn't buffer a 1 yet, delay next 1 by n*128 ticks. - else - temp_buffer_reset = 1'b1; // else no need for further delays. - - if(negedge_cnt[3:0] == 4'd0) // at rising edge of ssp_clk - ssp_dout changes at the falling edge. - begin - if((ssp_dout || (| mod_sig_ptr[4:0])) && ~fdt_elapsed) // buffer a 1 (and all subsequent data) until fdt is reached. - if (mod_sig_ptr == 5'd31) - mod_sig_ptr <= 5'd0; // buffer overflow - data loss. - else - mod_sig_ptr <= mod_sig_ptr + 1; // increase buffer (= increase delay by 16 adc_clk ticks). mod_sig_ptr always points ahead of first 1. - else if(fdt_elapsed && ~temp_buffer_reset) - begin - // wait for the next 1 after fdt_elapsed before fixing the delay and starting modulation. This ensures that the response can only happen - // at intervals of 8 * 16 = 128 adc_clk ticks (as defined in ISO14443-3) - if(ssp_dout) - temp_buffer_reset = 1'b1; - if(mod_sig_ptr == 5'd1) - mod_sig_ptr <= 5'd8; // still nothing received, need to go for the next interval - else - mod_sig_ptr <= mod_sig_ptr - 1; // decrease buffer. - end - end - end -end - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// FPGA -> ARM communication: -// buffer 8 bits data to be sent to ARM. Shift them out bit by bit. -reg [7:0] to_arm; - -always @(negedge adc_clk) -begin - if (negedge_cnt[5:0] == 6'd63) // fill the buffer - begin - if (mod_type == `FPGA_HF_ISO14443A_SNIFFER) - begin - if(deep_modulation) // a reader is sending (or there's no field at all) - begin - to_arm <= {reader_data[3:0], 4'b0000}; // don't send tag data - end - else - begin - to_arm <= {reader_data[3:0], tag_data[3:0]}; - end - end - else - begin - to_arm[7:0] <= {mod_sig_ptr[4:0], mod_sig_flip[3:1]}; // feedback timing information - end - end - - if(negedge_cnt[2:0] == 3'b000 && mod_type == `FPGA_HF_ISO14443A_SNIFFER) // shift at double speed - begin - // Don't shift if we just loaded new data, obviously. - if(negedge_cnt[5:0] != 6'd0) - begin - to_arm[7:1] <= to_arm[6:0]; - end - end - - if(negedge_cnt[3:0] == 4'b0000 && mod_type != `FPGA_HF_ISO14443A_SNIFFER) - begin - // Don't shift if we just loaded new data, obviously. - if(negedge_cnt[6:0] != 7'd0) - begin - to_arm[7:1] <= to_arm[6:0]; - end - end - -end - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// FPGA <-> ARM communication: -// generate a ssp clock and ssp frame signal for the synchronous transfer from/to the ARM -reg ssp_clk; -reg ssp_frame; - -always @(negedge adc_clk) -begin - if(mod_type == `FPGA_HF_ISO14443A_SNIFFER) - // FPGA_HF_ISO14443A_SNIFFER mode (ssp_clk = adc_clk / 8, ssp_frame clock = adc_clk / 64)): - begin - if(negedge_cnt[2:0] == 3'd0) - ssp_clk <= 1'b1; - if(negedge_cnt[2:0] == 3'd4) - ssp_clk <= 1'b0; - - if(negedge_cnt[5:0] == 6'd0) // ssp_frame rising edge indicates start of frame - ssp_frame <= 1'b1; - if(negedge_cnt[5:0] == 6'd8) - ssp_frame <= 1'b0; - end - else - // all other modes (ssp_clk = adc_clk / 16, ssp_frame clock = adc_clk / 128): - begin - if(negedge_cnt[3:0] == 4'd0) - ssp_clk <= 1'b1; - if(negedge_cnt[3:0] == 4'd8) - ssp_clk <= 1'b0; - - if(negedge_cnt[6:0] == 7'd7) // ssp_frame rising edge indicates start of frame, sampled on falling edge of ssp_clk - ssp_frame <= 1'b1; - if(negedge_cnt[6:0] == 7'd23) - ssp_frame <= 1'b0; - end -end - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// FPGA -> ARM communication: -// select the data to be sent to ARM -reg bit_to_arm; -reg sendbit; - -always @(negedge adc_clk) -begin - if(negedge_cnt[3:0] == 4'd0) - begin - // What do we communicate to the ARM - if(mod_type == `FPGA_HF_ISO14443A_TAGSIM_LISTEN) - sendbit = after_hysteresis; - else if(mod_type == `FPGA_HF_ISO14443A_TAGSIM_MOD) - /* if(fdt_counter > 11'd772) sendbit = mod_sig_coil; // huh? - else */ - sendbit = fdt_indicator; - else if (mod_type == `FPGA_HF_ISO14443A_READER_LISTEN) - sendbit = curbit; - else - sendbit = 1'b0; - end - - - if(mod_type == `FPGA_HF_ISO14443A_SNIFFER) - // send sampled reader and tag data: - bit_to_arm = to_arm[7]; - else if (mod_type == `FPGA_HF_ISO14443A_TAGSIM_MOD && fdt_elapsed && temp_buffer_reset) - // send timing information: - bit_to_arm = to_arm[7]; - else - // send data or fdt_indicator - bit_to_arm = sendbit; -end - - - - -assign ssp_din = bit_to_arm; - -// Subcarrier (adc_clk/16, for FPGA_HF_ISO14443A_TAGSIM_MOD only). -wire sub_carrier; -assign sub_carrier = ~sub_carrier_cnt[3]; - -// in FPGA_HF_ISO14443A_READER_MOD: drop carrier for mod_sig_coil==1 (pause); in FPGA_HF_ISO14443A_READER_LISTEN: carrier always on; in other modes: carrier always off -assign pwr_hi = (ck_1356meg & (((mod_type == `FPGA_HF_ISO14443A_READER_MOD) & ~mod_sig_coil) || (mod_type == `FPGA_HF_ISO14443A_READER_LISTEN))); - - -// Enable HF antenna drivers: -assign pwr_oe1 = 1'b0; -assign pwr_oe3 = 1'b0; - -// FPGA_HF_ISO14443A_TAGSIM_MOD: short circuit antenna with different resistances (modulated by sub_carrier modulated by mod_sig_coil) -// for pwr_oe4 = 1 (tristate): antenna load = 10k || 33 = 32,9 Ohms -// for pwr_oe4 = 0 (active): antenna load = 10k || 33 || 33 = 16,5 Ohms -assign pwr_oe4 = mod_sig_coil & sub_carrier & (mod_type == `FPGA_HF_ISO14443A_TAGSIM_MOD); - -// This is all LF, so doesn't matter. -assign pwr_oe2 = 1'b0; -assign pwr_lo = 1'b0; - - -assign dbg = negedge_cnt[3]; - -endmodule diff --git a/fpga-xc3s100e/hi_reader.v b/fpga-xc3s100e/hi_reader.v deleted file mode 100644 index c5ffa7b85b..0000000000 --- a/fpga-xc3s100e/hi_reader.v +++ /dev/null @@ -1,335 +0,0 @@ -//----------------------------------------------------------------------------- -// -// Jonathan Westhues, April 2006 -//----------------------------------------------------------------------------- - -module hi_reader( - ck_1356meg, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - dbg, - subcarrier_frequency, minor_mode -); - input ck_1356meg; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - output dbg; - input [1:0] subcarrier_frequency; - input [3:0] minor_mode; - -assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz - -// When we're a reader, we just need to do the BPSK demod; but when we're an -// eavesdropper, we also need to pick out the commands sent by the reader, -// using AM. Do this the same way that we do it for the simulated tag. -reg after_hysteresis, after_hysteresis_prev, after_hysteresis_prev_prev; -reg [11:0] has_been_low_for; -always @(negedge adc_clk) -begin - if (& adc_d[7:0]) after_hysteresis <= 1'b1; - else if (~(| adc_d[7:0])) after_hysteresis <= 1'b0; - - if (after_hysteresis) - begin - has_been_low_for <= 12'd0; - end - else - begin - if (has_been_low_for == 12'd4095) - begin - has_been_low_for <= 12'd0; - after_hysteresis <= 1'b1; - end - else - has_been_low_for <= has_been_low_for + 1; - end -end - - -// Let us report a correlation every 64 samples. I.e. -// one Q/I pair after 4 subcarrier cycles for the 848kHz subcarrier, -// one Q/I pair after 2 subcarrier cycles for the 424kHz subcarriers, -// one Q/I pair for each subcarrier cyle for the 212kHz subcarrier. -// We need a 6-bit counter for the timing. -reg [5:0] corr_i_cnt; -always @(negedge adc_clk) -begin - corr_i_cnt <= corr_i_cnt + 1; -end - - -// A couple of registers in which to accumulate the correlations. From the 64 samples -// we would add at most 32 times the difference between unmodulated and modulated signal. It should -// be safe to assume that a tag will not be able to modulate the carrier signal by more than 25%. -// 32 * 255 * 0,25 = 2040, which can be held in 11 bits. Add 1 bit for sign. -// Temporary we might need more bits. For the 212kHz subcarrier we could possible add 32 times the -// maximum signal value before a first subtraction would occur. 32 * 255 = 8160 can be held in 13 bits. -// Add one bit for sign -> need 14 bit registers but final result will fit into 12 bits. -reg signed [13:0] corr_i_accum; -reg signed [13:0] corr_q_accum; -// we will report maximum 8 significant bits -reg signed [7:0] corr_i_out; -reg signed [7:0] corr_q_out; - - -// the amplitude of the subcarrier is sqrt(ci^2 + cq^2). -// approximate by amplitude = max(|ci|,|cq|) + 1/2*min(|ci|,|cq|) -reg [13:0] corr_amplitude, abs_ci, abs_cq, max_ci_cq; -reg [12:0] min_ci_cq_2; // min_ci_cq / 2 - -always @(*) -begin - if (corr_i_accum[13] == 1'b0) - abs_ci <= corr_i_accum; - else - abs_ci <= -corr_i_accum; - - if (corr_q_accum[13] == 1'b0) - abs_cq <= corr_q_accum; - else - abs_cq <= -corr_q_accum; - - if (abs_ci > abs_cq) - begin - max_ci_cq <= abs_ci; - min_ci_cq_2 <= abs_cq / 2; - end - else - begin - max_ci_cq <= abs_cq; - min_ci_cq_2 <= abs_ci / 2; - end - - corr_amplitude <= max_ci_cq + min_ci_cq_2; - -end - - -// The subcarrier reference signals -reg subcarrier_I; -reg subcarrier_Q; - -always @(*) -begin - if (subcarrier_frequency == `FPGA_HF_READER_SUBCARRIER_848_KHZ) - begin - subcarrier_I = ~corr_i_cnt[3]; - subcarrier_Q = ~(corr_i_cnt[3] ^ corr_i_cnt[2]); - end - else if (subcarrier_frequency == `FPGA_HF_READER_SUBCARRIER_212_KHZ) - begin - subcarrier_I = ~corr_i_cnt[5]; - subcarrier_Q = ~(corr_i_cnt[5] ^ corr_i_cnt[4]); - end - else - begin // 424 kHz - subcarrier_I = ~corr_i_cnt[4]; - subcarrier_Q = ~(corr_i_cnt[4] ^ corr_i_cnt[3]); - end -end - - -// ADC data appears on the rising edge, so sample it on the falling edge -always @(negedge adc_clk) -begin - // These are the correlators: we correlate against in-phase and quadrature - // versions of our reference signal, and keep the (signed) results or the - // resulting amplitude to send out later over the SSP. - if (corr_i_cnt == 6'd0) - begin - if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_AMPLITUDE) - begin - // send amplitude plus 2 bits reader signal - corr_i_out <= corr_amplitude[13:6]; - corr_q_out <= {corr_amplitude[5:0], after_hysteresis_prev_prev, after_hysteresis_prev}; - end - else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ) - begin - - // Send 7 most significant bits of in phase tag signal (signed), plus 1 bit reader signal - if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111) - corr_i_out <= {corr_i_accum[11:5], after_hysteresis_prev_prev}; - else // truncate to maximum value - if (corr_i_accum[13] == 1'b0) - corr_i_out <= {7'b0111111, after_hysteresis_prev_prev}; - else - corr_i_out <= {7'b1000000, after_hysteresis_prev_prev}; - - // Send 7 most significant bits of quadrature phase tag signal (signed), plus 1 bit reader signal - if (corr_q_accum[13:11] == 3'b000 || corr_q_accum[13:11] == 3'b111) - corr_q_out <= {corr_q_accum[11:5], after_hysteresis_prev}; - else // truncate to maximum value - if (corr_q_accum[13] == 1'b0) - corr_q_out <= {7'b0111111, after_hysteresis_prev}; - else - corr_q_out <= {7'b1000000, after_hysteresis_prev}; - end - else if (minor_mode == `FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE) - begin - // send amplitude - corr_i_out <= {2'b00, corr_amplitude[13:8]}; - corr_q_out <= corr_amplitude[7:0]; - end - else if (minor_mode == `FPGA_HF_READER_MODE_RECEIVE_IQ) - begin - - // Send 8 bits of in phase tag signal - if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111) - corr_i_out <= corr_i_accum[11:4]; - else // truncate to maximum value - if (corr_i_accum[13] == 1'b0) - corr_i_out <= 8'b01111111; - else - corr_i_out <= 8'b10000000; - - // Send 8 bits of quadrature phase tag signal - if (corr_q_accum[13:11] == 3'b000 || corr_q_accum[13:11] == 3'b111) - corr_q_out <= corr_q_accum[11:4]; - else // truncate to maximum value - if (corr_q_accum[13] == 1'b0) - corr_q_out <= 8'b01111111; - else - corr_q_out <= 8'b10000000; - end - - // for each Q/I pair report two reader signal samples when sniffing. Store the 1st. - after_hysteresis_prev_prev <= after_hysteresis; - - // Initialize next correlation. - // Both I and Q reference signals are high when corr_i_nct == 0. Therefore need to accumulate. - corr_i_accum <= $signed({1'b0, adc_d}); - corr_q_accum <= $signed({1'b0, adc_d}); - end - else - begin - if (subcarrier_I) - corr_i_accum <= corr_i_accum + $signed({1'b0, adc_d}); - else - corr_i_accum <= corr_i_accum - $signed({1'b0, adc_d}); - - if (subcarrier_Q) - corr_q_accum <= corr_q_accum + $signed({1'b0, adc_d}); - else - corr_q_accum <= corr_q_accum - $signed({1'b0, adc_d}); - end - - // for each Q/I pair report two reader signal samples when sniffing. Store the 2nd. - if (corr_i_cnt == 6'd32) - after_hysteresis_prev <= after_hysteresis; - - // Then the result from last time is serialized and send out to the ARM. - // We get one report each cycle, and each report is 16 bits, so the - // ssp_clk should be the adc_clk divided by 64/16 = 4. - // ssp_clk frequency = 13,56MHz / 4 = 3.39MHz - - if (corr_i_cnt[1:0] == 2'b00) - begin - // Don't shift if we just loaded new data, obviously. - if (corr_i_cnt != 6'd0) - begin - corr_i_out[7:0] <= {corr_i_out[6:0], corr_q_out[7]}; - corr_q_out[7:1] <= corr_q_out[6:0]; - end - end - -end - - -// ssp clock and frame signal for communication to and from ARM -// _____ _____ _____ _ -// ssp_clk | |_____| |_____| |_____| -// _____ -// ssp_frame ___| |____________________________ -// ___________ ___________ ___________ _ -// ssp_d_in X___________X___________X___________X_ -// -// corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ... -// - -reg ssp_clk; -reg ssp_frame; - -always @(negedge adc_clk) -begin - if (corr_i_cnt[1:0] == 2'b00) - ssp_clk <= 1'b1; - - if (corr_i_cnt[1:0] == 2'b10) - ssp_clk <= 1'b0; - - // set ssp_frame signal for corr_i_cnt = 1..3 - // (send one frame with 16 Bits) - if (corr_i_cnt == 6'd1) - ssp_frame <= 1'b1; - - if (corr_i_cnt == 6'd3) - ssp_frame <= 1'b0; -end - - -assign ssp_din = corr_i_out[7]; - - -// a jamming signal -reg jam_signal; -reg [3:0] jam_counter; - -always @(negedge adc_clk) -begin - if (corr_i_cnt == 6'd0) - begin - jam_counter <= jam_counter + 1; - jam_signal <= jam_counter[1] ^ jam_counter[3]; - end -end - -// Antenna drivers -reg pwr_hi, pwr_oe4; - -always @(*) -begin - if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD) - begin - pwr_hi = ck_1356meg; - pwr_oe4 = ssp_dout; - end - else if (minor_mode == `FPGA_HF_READER_MODE_SEND_FULL_MOD) - begin - pwr_hi = ck_1356meg & ~ssp_dout; - pwr_oe4 = 1'b0; - end - else if (minor_mode == `FPGA_HF_READER_MODE_SEND_JAM) - begin - pwr_hi = ck_1356meg & jam_signal; - pwr_oe4 = 1'b0; - end - else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ - || minor_mode == `FPGA_HF_READER_MODE_SNIFF_AMPLITUDE - || minor_mode == `FPGA_HF_READER_MODE_SNIFF_PHASE) - begin // all off - pwr_hi = 1'b0; - pwr_oe4 = 1'b0; - end - else // receiving from tag - begin - pwr_hi = ck_1356meg; - pwr_oe4 = 1'b0; - end -end - -// always on -assign pwr_oe1 = 1'b0; -assign pwr_oe3 = 1'b0; - -// Unused. -assign pwr_lo = 1'b0; -assign pwr_oe2 = 1'b0; - -// Debug Output -assign dbg = corr_i_cnt[3]; - -endmodule diff --git a/fpga-xc3s100e/hi_simulate.v b/fpga-xc3s100e/hi_simulate.v deleted file mode 100644 index cf951279a2..0000000000 --- a/fpga-xc3s100e/hi_simulate.v +++ /dev/null @@ -1,152 +0,0 @@ -//----------------------------------------------------------------------------- -// Pretend to be an ISO 14443 tag. We will do this by alternately short- -// circuiting and open-circuiting the antenna coil, with the tri-state -// pins. -// -// We communicate over the SSP, as a bitstream (i.e., might as well be -// unframed, though we still generate the word sync signal). The output -// (ARM -> FPGA) tells us whether to modulate or not. The input (FPGA -// -> ARM) is us using the A/D as a fancy comparator; this is with -// (software-added) hysteresis, to undo the high-pass filter. -// -// At this point only Type A is implemented. This means that we are using a -// bit rate of 106 kbit/s, or fc/128. Oversample by 4, which ought to make -// things practical for the ARM (fc/32, 423.8 kbits/s, ~50 kbytes/s) -// -// Jonathan Westhues, October 2006 -//----------------------------------------------------------------------------- - -//For ISE 10.1 PROJ,IDE cannot apply definition to all files -`include "define.v" - - -module hi_simulate( - ck_1356meg, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - dbg, - mod_type -); - input ck_1356meg; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - output dbg; - input [3:0] mod_type; - -// Power amp goes between LOW and tri-state, so pwr_hi (and pwr_lo) can -// always be low. -assign pwr_hi = 1'b0; // HF antenna connected to GND -assign pwr_lo = 1'b0; // LF antenna connected to GND - -// This one is all LF, so doesn't matter -assign pwr_oe2 = 1'b0; - -assign adc_clk = ck_1356meg; -assign dbg = ssp_frame; - -// The comparator with hysteresis on the output from the peak detector. -reg after_hysteresis; -reg [11:0] has_been_low_for; - -always @(negedge adc_clk) -begin - if (& adc_d[7:5]) after_hysteresis <= 1'b1; // if (adc_d >= 224) - else if (~(| adc_d[7:5])) after_hysteresis <= 1'b0; // if (adc_d <= 31) - - if (adc_d >= 224) - begin - has_been_low_for <= 12'd0; - end - else - begin - if (has_been_low_for == 12'd4095) - begin - has_been_low_for <= 12'd0; - after_hysteresis <= 1'b1; - end - else - begin - has_been_low_for <= has_been_low_for + 1; - end - end -end - - -// Divide 13.56 MHz to produce various frequencies for SSP_CLK -// and modulation. -reg [8:0] ssp_clk_divider; - -always @(negedge adc_clk) - ssp_clk_divider <= (ssp_clk_divider + 1); - -reg ssp_clk; - -always @(negedge adc_clk) -begin - if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT) - // Get bit every at 53KHz (every 8th carrier bit of 424kHz) - ssp_clk <= ~ssp_clk_divider[7]; - else if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K) - // Get next bit at 212kHz - ssp_clk <= ~ssp_clk_divider[5]; - else - // Get next bit at 424kHz - ssp_clk <= ~ssp_clk_divider[4]; -end - - -// Produce the byte framing signal; the phase of this signal -// is arbitrary, because it's just a bit stream in this module. -reg ssp_frame; -always @(negedge adc_clk) -begin - if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K) - begin - if (ssp_clk_divider[8:5] == 4'd1) - ssp_frame <= 1'b1; - if (ssp_clk_divider[8:5] == 4'd5) - ssp_frame <= 1'b0; - end - else - begin - if (ssp_clk_divider[7:4] == 4'd1) - ssp_frame <= 1'b1; - if (ssp_clk_divider[7:4] == 4'd5) - ssp_frame <= 1'b0; - end -end - - -// Synchronize up the after-hysteresis signal, to produce DIN. -reg ssp_din; -always @(posedge ssp_clk) - ssp_din = after_hysteresis; - -// Modulating carrier frequency is fc/64 (212kHz) to fc/16 (848kHz). Reuse ssp_clk divider for that. -reg modulating_carrier; -always @(*) - if(mod_type == `FPGA_HF_SIMULATOR_NO_MODULATION) - modulating_carrier <= 1'b0; // no modulation - else if(mod_type == `FPGA_HF_SIMULATOR_MODULATE_BPSK) - modulating_carrier <= ssp_dout ^ ssp_clk_divider[3]; // XOR means BPSK - else if(mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K) - modulating_carrier <= ssp_dout & ssp_clk_divider[5]; // switch 212kHz subcarrier on/off - else if(mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K || mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT) - modulating_carrier <= ssp_dout & ssp_clk_divider[4]; // switch 424kHz modulation on/off - else - modulating_carrier <= 1'b0; // yet unused - - - -// Load modulation. Toggle only one of these, since we are already producing much deeper -// modulation than a real tag would. -assign pwr_oe1 = 1'b0; // 33 Ohms Load -assign pwr_oe4 = modulating_carrier; // 33 Ohms Load -// This one is always on, so that we can watch the carrier. -assign pwr_oe3 = 1'b0; // 10k Load - -endmodule diff --git a/fpga-xc3s100e/hi_sniffer.v b/fpga-xc3s100e/hi_sniffer.v deleted file mode 100644 index c2dc844a72..0000000000 --- a/fpga-xc3s100e/hi_sniffer.v +++ /dev/null @@ -1,50 +0,0 @@ -module hi_sniffer( - ck_1356meg, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_clk -); - input ck_1356meg; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - output ssp_frame, ssp_din, ssp_clk; - -// We are only snooping, all off. -assign pwr_hi = 1'b0; -assign pwr_lo = 1'b0; -assign pwr_oe1 = 1'b0; -assign pwr_oe2 = 1'b0; -assign pwr_oe3 = 1'b0; -assign pwr_oe4 = 1'b0; - -reg ssp_frame; -reg [7:0] adc_d_out = 8'd0; -reg [2:0] ssp_cnt = 3'd0; - -assign adc_clk = ck_1356meg; -assign ssp_clk = ~ck_1356meg; - -always @(posedge ssp_clk) -begin - if(ssp_cnt[2:0] == 3'd7) - ssp_cnt[2:0] <= 3'd0; - else - ssp_cnt <= ssp_cnt + 1; - - if(ssp_cnt[2:0] == 3'b000) // set frame length - begin - adc_d_out[7:0] <= adc_d; - ssp_frame <= 1'b1; - end - else - begin - adc_d_out[7:0] <= {1'b0, adc_d_out[7:1]}; - ssp_frame <= 1'b0; - end - -end - -assign ssp_din = adc_d_out[0]; - -endmodule diff --git a/fpga-xc3s100e/iseproj/fpga_hf/fpga_hf.ise b/fpga-xc3s100e/iseproj/fpga_hf/fpga_hf.ise deleted file mode 100644 index 40e5eeffdff1dad9e67d8e59ede83f95cc6f6c8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 257463 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 diff --git a/fpga-xc3s100e/iseproj/fpga_hf/fpga_hf.tcl b/fpga-xc3s100e/iseproj/fpga_hf/fpga_hf.tcl deleted file mode 100644 index 114f0df18b..0000000000 --- a/fpga-xc3s100e/iseproj/fpga_hf/fpga_hf.tcl +++ /dev/null @@ -1,479 +0,0 @@ -# -# Project automation script for fpga_hf -# -# Created for ISE version 10.1 -# -# This file contains several Tcl procedures (procs) that you can use to automate -# your project by running from xtclsh or the Project Navigator Tcl console. -# If you load this file (using the Tcl command: source fpga_hf.tcl, then you can -# run any of the procs included here. -# You may also edit any of these procs to customize them. See comments in each -# proc for more instructions. -# -# This file contains the following procedures: -# -# Top Level procs (meant to be called directly by the user): -# run_process: you can use this top-level procedure to run any processes -# that you choose to by adding and removing comments, or by -# adding new entries. -# rebuild_project: you can alternatively use this top-level procedure -# to recreate your entire project, and the run selected processes. -# -# Lower Level (helper) procs (called under in various cases by the top level procs): -# show_help: print some basic information describing how this script works -# add_source_files: adds the listed source files to your project. -# set_project_props: sets the project properties that were in effect when this -# script was generated. -# create_libraries: creates and adds file to VHDL libraries that were defined when -# this script was generated. -# create_partitions: adds any partitions that were defined when this script was generated. -# set_process_props: set the process properties as they were set for your project -# when this script was generated. -# - -set myProject "fpga_hf.ise" -set myScript "fpga_hf.tcl" - -# -# Main (top-level) routines -# - -# -# run_process -# This procedure is used to run processes on an existing project. You may comment or -# uncomment lines to control which processes are run. This routine is set up to run -# the Implement Design and Generate Programming File processes by default. This proc -# also sets process properties as specified in the "set_process_props" proc. Only -# those properties which have values different from their current settings in the project -# file will be modified in the project. -# -proc run_process {} { - - global myScript - global myProject - - ## put out a 'heartbeat' - so we know something's happening. - puts "\n$myScript: running ($myProject)...\n" - - if { ! [ open_project ] } { - return false - } - - set_process_props - # - # Remove the comment characters (#'s) to enable the following commands - # process run "Synthesize" - # process run "Translate" - # process run "Map" - # process run "Place & Route" - # - puts "Running 'Implement Design'" - if { ! [ process run "Implement Design" ] } { - puts "$myScript: Implementation run failed, check run output for details." - project close - return - } - puts "Running 'Generate Programming File'" - if { ! [ process run "Generate Programming File" ] } { - puts "$myScript: Generate Programming File run failed, check run output for details." - project close - return - } - - puts "Run completed." - project close - -} - -# -# rebuild_project -# -# This procedure renames the project file (if it exists) and recreates the project. -# It then sets project properties and adds project sources as specified by the -# set_project_props and add_source_files support procs. It recreates VHDL libraries -# and partitions as they existed at the time this script was generated. -# -# It then calls run_process to set process properties and run selected processes. -# -proc rebuild_project {} { - - global myScript - global myProject - - ## put out a 'heartbeat' - so we know something's happening. - puts "\n$myScript: rebuilding ($myProject)...\n" - - if { [ file exists $myProject ] } { - puts "$myScript: Removing existing project file." - file delete $myProject - } - - puts "$myScript: Rebuilding project $myProject" - project new $myProject - set_project_props - add_source_files - create_libraries - create_partitions - puts "$myScript: project rebuild completed." - - run_process - -} - -# -# Support Routines -# - -# -# show_help: print information to help users understand the options available when -# running this script. -# -proc show_help {} { - - global myScript - - puts "" - puts "usage: xtclsh $myScript " - puts " or you can run xtclsh and then enter 'source $myScript'." - puts "" - puts "options:" - puts " run_process - set properties and run processes." - puts " rebuild_project - rebuild the project from scratch and run processes." - puts " set_project_props - set project properties (device, speed, etc.)" - puts " add_source_files - add source files" - puts " create_libraries - create vhdl libraries" - puts " create_partitions - create partitions" - puts " set_process_props - set process property values" - puts " show_help - print this message" - puts "" -} - -proc open_project {} { - - global myScript - global myProject - - if { ! [ file exists $myProject ] } { - ## project file isn't there, rebuild it. - puts "Project $myProject not found. Use ${myProject}_rebuild to recreate it." - return false - } - - project open $myProject - - return true - -} -# -# set_project_props -# -# This procedure sets the project properties as they were set in the project -# at the time this script was generated. -# -proc set_project_props {} { - - global myScript - - if { ! [ open_project ] } { - return false - } - - puts "$myScript: Setting project properties..." - - project set family "Spartan3E" - project set device "xc3s100e" - project set package "vq100" - project set speed "-4" - project set top_level_module_type "HDL" - project set synthesis_tool "XST (VHDL/Verilog)" - project set simulator "ISE Simulator (VHDL/Verilog)" - project set "Preferred Language" "Verilog" - project set "Enable Message Filtering" "false" - project set "Display Incremental Messages" "false" - -} - - -# -# add_source_files -# -# This procedure add the source files that were known to the project at the -# time this script was generated. -# -proc add_source_files {} { - - global myScript - - if { ! [ open_project ] } { - return false - } - - puts "$myScript: Adding sources to project..." - - xfile add "../../clk_divider.v" - xfile add "../../define.v" - xfile add "../../fpga.ucf" - xfile add "../../fpga_allinone.v" - xfile add "../../fpga_hfmod.v" - xfile add "../../fpga_lfmod.v" - xfile add "../../hi_flite.v" - xfile add "../../hi_get_trace.v" - xfile add "../../hi_iso14443a.v" - xfile add "../../hi_reader.v" - xfile add "../../hi_simulate.v" - xfile add "../../hi_sniffer.v" - xfile add "../../lf_edge_detect.v" - xfile add "../../lo_adc.v" - xfile add "../../lo_edge_detect.v" - xfile add "../../lo_passthru.v" - xfile add "../../lo_read.v" - xfile add "../../lp20khz_1MSa_iir_filter.v" - xfile add "../../mux2_onein.v" - xfile add "../../mux2_oneout.v" - xfile add "../../util.v" - - # Set the Top Module as well... - project set top "fpga_hf" - - puts "$myScript: project sources reloaded." - -} ; # end add_source_files - -# -# create_libraries -# -# This procedure defines VHDL libraries and associates files with those libraries. -# It is expected to be used when recreating the project. Any libraries defined -# when this script was generated are recreated by this procedure. -# -proc create_libraries {} { - - global myScript - - if { ! [ open_project ] } { - return false - } - - puts "$myScript: Creating libraries..." - - - # must close the project or library definitions aren't saved. - project close - -} ; # end create_libraries - -# -# create_partitions -# -# This procedure creates partitions on instances in your project. -# It is expected to be used when recreating the project. Any partitions -# defined when this script was generated are recreated by this procedure. -# -proc create_partitions {} { - - global myScript - - if { ! [ open_project ] } { - return false - } - - puts "$myScript: Creating Partitions..." - - - # must close the project or partition definitions aren't saved. - project close - -} ; # end create_partitions - -# -# set_process_props -# -# This procedure sets properties as requested during script generation (either -# all of the properties, or only those modified from their defaults). -# -proc set_process_props {} { - - global myScript - - if { ! [ open_project ] } { - return false - } - - puts "$myScript: setting process properties..." - - project set "Compiled Library Directory" "\$XILINX//" - project set "Use SmartGuide" "false" - project set "SmartGuide Filename" "fpga_hf_guide.ncd" - project set "Multiplier Style" "Auto" -process "Synthesize - XST" - project set "Configuration Rate" "Default (1)" -process "Generate Programming File" - project set "Map to Input Functions" "4" -process "Map" - project set "Number of Clock Buffers" "24" -process "Synthesize - XST" - project set "Max Fanout" "500" -process "Synthesize - XST" - project set "Case Implementation Style" "None" -process "Synthesize - XST" - project set "Decoder Extraction" "true" -process "Synthesize - XST" - project set "Priority Encoder Extraction" "Yes" -process "Synthesize - XST" - project set "Mux Extraction" "Yes" -process "Synthesize - XST" - project set "RAM Extraction" "true" -process "Synthesize - XST" - project set "ROM Extraction" "true" -process "Synthesize - XST" - project set "FSM Encoding Algorithm" "Auto" -process "Synthesize - XST" - project set "Logical Shifter Extraction" "true" -process "Synthesize - XST" - project set "Optimization Goal" "Speed" -process "Synthesize - XST" - project set "Optimization Effort" "Normal" -process "Synthesize - XST" - project set "Resource Sharing" "true" -process "Synthesize - XST" - project set "Shift Register Extraction" "true" -process "Synthesize - XST" - project set "XOR Collapsing" "true" -process "Synthesize - XST" - project set "Other Bitgen Command Line Options" "" -process "Generate Programming File" - project set "Show All Models" "false" -process "Generate IBIS Model" - project set "Target UCF File Name" "" -process "Back-annotate Pin Locations" - project set "Ignore User Timing Constraints" "false" -process "Map" - project set "Use RLOC Constraints" "true" -process "Map" - project set "Other Map Command Line Options" "" -process "Map" - project set "Use LOC Constraints" "true" -process "Translate" - project set "Other Ngdbuild Command Line Options" "" -process "Translate" - project set "Ignore User Timing Constraints" "false" -process "Place & Route" - project set "Other Place & Route Command Line Options" "" -process "Place & Route" - project set "UserID Code (8 Digit Hexadecimal)" "0xFFFFFFFF" -process "Generate Programming File" - project set "Reset DCM if SHUTDOWN & AGHIGH performed" "false" -process "Generate Programming File" - project set "Configuration Pin Done" "Pull Up" -process "Generate Programming File" - project set "Create ASCII Configuration File" "false" -process "Generate Programming File" - project set "Create Binary Configuration File" "false" -process "Generate Programming File" - project set "Create Bit File" "true" -process "Generate Programming File" - project set "Enable BitStream Compression" "false" -process "Generate Programming File" - project set "Run Design Rules Checker (DRC)" "true" -process "Generate Programming File" - project set "Enable Cyclic Redundancy Checking (CRC)" "true" -process "Generate Programming File" - project set "Create IEEE 1532 Configuration File" "false" -process "Generate Programming File" - project set "Configuration Pin Program" "Pull Up" -process "Generate Programming File" - project set "JTAG Pin TCK" "Pull Up" -process "Generate Programming File" - project set "JTAG Pin TDI" "Pull Up" -process "Generate Programming File" - project set "JTAG Pin TDO" "Pull Up" -process "Generate Programming File" - project set "JTAG Pin TMS" "Pull Up" -process "Generate Programming File" - project set "Unused IOB Pins" "Pull Down" -process "Generate Programming File" - project set "Security" "Enable Readback and Reconfiguration" -process "Generate Programming File" - project set "FPGA Start-Up Clock" "CCLK" -process "Generate Programming File" - project set "Done (Output Events)" "Default (4)" -process "Generate Programming File" - project set "Drive Done Pin High" "false" -process "Generate Programming File" - project set "Enable Outputs (Output Events)" "Default (5)" -process "Generate Programming File" - project set "Release DLL (Output Events)" "Default (NoWait)" -process "Generate Programming File" - project set "Release Write Enable (Output Events)" "Default (6)" -process "Generate Programming File" - project set "Enable Internal Done Pipe" "false" -process "Generate Programming File" - project set "Allow Logic Optimization Across Hierarchy" "false" -process "Map" - project set "Optimization Strategy (Cover Mode)" "Area" -process "Map" - project set "Disable Register Ordering" "false" -process "Map" - project set "Pack I/O Registers/Latches into IOBs" "Off" -process "Map" - project set "Replicate Logic to Allow Logic Level Reduction" "true" -process "Map" - project set "Generate Detailed MAP Report" "false" -process "Map" - project set "Map Slice Logic into Unused Block RAMs" "false" -process "Map" - project set "Perform Timing-Driven Packing and Placement" "false" -process "Map" - project set "Trim Unconnected Signals" "true" -process "Map" - project set "Create I/O Pads from Ports" "false" -process "Translate" - project set "Macro Search Path" "" -process "Translate" - project set "Netlist Translation Type" "Timestamp" -process "Translate" - project set "User Rules File for Netlister Launcher" "" -process "Translate" - project set "Allow Unexpanded Blocks" "false" -process "Translate" - project set "Allow Unmatched LOC Constraints" "false" -process "Translate" - project set "Starting Placer Cost Table (1-100)" "1" -process "Place & Route" - project set "Placer Effort Level (Overrides Overall Level)" "None" -process "Place & Route" - project set "Router Effort Level (Overrides Overall Level)" "None" -process "Place & Route" - project set "Place And Route Mode" "Normal Place and Route" -process "Place & Route" - project set "Use Bonded I/Os" "false" -process "Place & Route" - project set "Add I/O Buffers" "true" -process "Synthesize - XST" - project set "Global Optimization Goal" "AllClockNets" -process "Synthesize - XST" - project set "Keep Hierarchy" "No" -process "Synthesize - XST" - project set "Register Balancing" "No" -process "Synthesize - XST" - project set "Register Duplication" "true" -process "Synthesize - XST" - project set "Asynchronous To Synchronous" "false" -process "Synthesize - XST" - project set "Automatic BRAM Packing" "false" -process "Synthesize - XST" - project set "BRAM Utilization Ratio" "100" -process "Synthesize - XST" - project set "Bus Delimiter" "<>" -process "Synthesize - XST" - project set "Case" "Maintain" -process "Synthesize - XST" - project set "Cores Search Directories" "" -process "Synthesize - XST" - project set "Cross Clock Analysis" "false" -process "Synthesize - XST" - project set "Equivalent Register Removal" "true" -process "Synthesize - XST" - project set "FSM Style" "LUT" -process "Synthesize - XST" - project set "Generate RTL Schematic" "Yes" -process "Synthesize - XST" - project set "Generics, Parameters" "" -process "Synthesize - XST" - project set "Hierarchy Separator" "/" -process "Synthesize - XST" - project set "HDL INI File" "" -process "Synthesize - XST" - project set "Library Search Order" "" -process "Synthesize - XST" - project set "Netlist Hierarchy" "As Optimized" -process "Synthesize - XST" - project set "Optimize Instantiated Primitives" "false" -process "Synthesize - XST" - project set "Pack I/O Registers into IOBs" "Auto" -process "Synthesize - XST" - project set "Read Cores" "true" -process "Synthesize - XST" - project set "Slice Packing" "true" -process "Synthesize - XST" - project set "Slice Utilization Ratio" "100" -process "Synthesize - XST" - project set "Use Clock Enable" "Yes" -process "Synthesize - XST" - project set "Use Synchronous Reset" "Yes" -process "Synthesize - XST" - project set "Use Synchronous Set" "Yes" -process "Synthesize - XST" - project set "Use Synthesis Constraints File" "true" -process "Synthesize - XST" - project set "Custom Compile File List" "" -process "Synthesize - XST" - project set "Verilog Include Directories" "" -process "Synthesize - XST" - project set "Verilog 2001" "true" -process "Synthesize - XST" - project set "Verilog Macros" "" -process "Synthesize - XST" - project set "Work Directory" "./xst" -process "Synthesize - XST" - project set "Write Timing Constraints" "false" -process "Synthesize - XST" - project set "Other XST Command Line Options" "" -process "Synthesize - XST" - project set "Map Effort Level" "Medium" -process "Map" - project set "Combinatorial Logic Optimization" "false" -process "Map" - project set "Starting Placer Cost Table (1-100)" "1" -process "Map" - project set "Power Reduction" "false" -process "Map" - project set "Register Duplication" "false" -process "Map" - project set "Synthesis Constraints File" "" -process "Synthesize - XST" - project set "Mux Style" "Auto" -process "Synthesize - XST" - project set "RAM Style" "Auto" -process "Synthesize - XST" - project set "Timing Mode" "Non Timing Driven" -process "Map" - project set "Generate Asynchronous Delay Report" "false" -process "Place & Route" - project set "Generate Clock Region Report" "false" -process "Place & Route" - project set "Generate Post-Place & Route Simulation Model" "false" -process "Place & Route" - project set "Generate Post-Place & Route Static Timing Report" "true" -process "Place & Route" - project set "Nodelist File (Unix Only)" "" -process "Place & Route" - project set "Number of PAR Iterations (0-100)" "3" -process "Place & Route" - project set "Save Results in Directory (.dir will be appended)" "" -process "Place & Route" - project set "Number of Results to Save (0-100)" "" -process "Place & Route" - project set "Power Reduction" "false" -process "Place & Route" - project set "Timing Mode" "Performance Evaluation" -process "Place & Route" - project set "Enable Debugging of Serial Mode BitStream" "false" -process "Generate Programming File" - project set "CLB Pack Factor Percentage" "100" -process "Map" - project set "Place & Route Effort Level (Overall)" "Standard" -process "Place & Route" - project set "Move First Flip-Flop Stage" "true" -process "Synthesize - XST" - project set "Move Last Flip-Flop Stage" "true" -process "Synthesize - XST" - project set "ROM Style" "Auto" -process "Synthesize - XST" - project set "Safe Implementation" "No" -process "Synthesize - XST" - project set "Extra Effort" "None" -process "Map" - project set "Power Activity File" "" -process "Map" - project set "Power Activity File" "" -process "Place & Route" - project set "Extra Effort (Highest PAR level only)" "None" -process "Place & Route" - - puts "$myScript: project property values set." - -} ; # end set_process_props - -proc main {} { - - if { [llength $::argv] == 0 } { - show_help - return true - } - - foreach option $::argv { - switch $option { - "show_help" { show_help } - "run_process" { run_process } - "rebuild_project" { rebuild_project } - "set_project_props" { set_project_props } - "add_source_files" { add_source_files } - "create_libraries" { create_libraries } - "create_partitions" { create_partitions } - "set_process_props" { set_process_props } - default { puts "unrecognized option: $option"; show_help } - } - } -} - -if { $tcl_interactive } { - show_help -} else { - if {[catch {main} result]} { - puts "$myScript failed: $result." - } -} - diff --git a/fpga-xc3s100e/lf_edge_detect.v b/fpga-xc3s100e/lf_edge_detect.v deleted file mode 100644 index d086f95fcd..0000000000 --- a/fpga-xc3s100e/lf_edge_detect.v +++ /dev/null @@ -1,77 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2014 iZsh -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// input clk is 24MHz -`include "min_max_tracker.v" - -module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold, - output [7:0] max, output [7:0] min, - output [7:0] high_threshold, output [7:0] highz_threshold, - output [7:0] lowz_threshold, output [7:0] low_threshold, - output edge_state, output edge_toggle); - - min_max_tracker tracker(clk, adc_d, lf_ed_threshold, min, max); - - // auto-tune - assign high_threshold = (max + min) / 2 + (max - min) / 4; - assign highz_threshold = (max + min) / 2 + (max - min) / 8; - assign lowz_threshold = (max + min) / 2 - (max - min) / 8; - assign low_threshold = (max + min) / 2 - (max - min) / 4; - - // heuristic to see if it makes sense to try to detect an edge - wire enabled = - (high_threshold > highz_threshold) - & (highz_threshold > lowz_threshold) - & (lowz_threshold > low_threshold) - & ((high_threshold - highz_threshold) > 8) - & ((highz_threshold - lowz_threshold) > 16) - & ((lowz_threshold - low_threshold) > 8); - - // Toggle the output with hysteresis - // Set to high if the ADC value is above the threshold - // Set to low if the ADC value is below the threshold - reg is_high = 0; - reg is_low = 0; - reg is_zero = 0; - reg trigger_enabled = 1; - reg output_edge = 0; - reg output_state; - - always @(posedge clk) - begin - is_high <= (adc_d >= high_threshold); - is_low <= (adc_d <= low_threshold); - is_zero <= ((adc_d > lowz_threshold) & (adc_d < highz_threshold)); - end - - // all edges detection - always @(posedge clk) - if (enabled) begin - // To enable detecting two consecutive peaks at the same level - // (low or high) we check whether or not we went back near 0 in-between. - // This extra check is necessary to prevent from noise artifacts - // around the threshold values. - if (trigger_enabled & (is_high | is_low)) begin - output_edge <= ~output_edge; - trigger_enabled <= 0; - end else - trigger_enabled <= trigger_enabled | is_zero; - end - - // edge states - always @(posedge clk) - if (enabled) begin - if (is_high) - output_state <= 1'd1; - else if (is_low) - output_state <= 1'd0; - end - - assign edge_state = output_state; - assign edge_toggle = output_edge; - -endmodule diff --git a/fpga-xc3s100e/lo_adc.v b/fpga-xc3s100e/lo_adc.v deleted file mode 100644 index bba090afbc..0000000000 --- a/fpga-xc3s100e/lo_adc.v +++ /dev/null @@ -1,91 +0,0 @@ -//----------------------------------------------------------------------------- -// The way that we connect things in low-frequency simulation mode. In this -// case just pass everything through to the ARM, which can bit-bang this -// (because it is so slow). -// -// Jonathan Westhues, April 2006 -//----------------------------------------------------------------------------- - -module lo_adc( - pck0, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - dbg, divisor, - lf_field -); - input pck0; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - output dbg; - input [7:0] divisor; - input lf_field; - -reg [7:0] to_arm_shiftreg; -reg [7:0] pck_divider; -reg clk_state; - -// Antenna logic, depending on "lf_field" (in arm defined as FPGA_LF_READER_FIELD) -wire tag_modulation = ssp_dout & !lf_field; -wire reader_modulation = !ssp_dout & lf_field & clk_state; - -// always on (High Frequency outputs, unused) -assign pwr_oe1 = 1'b0; -assign pwr_hi = 1'b0; - -// low frequency outputs -assign pwr_lo = reader_modulation; -assign pwr_oe2 = 1'b0; // 33 Ohms -assign pwr_oe3 = tag_modulation; // base antenna load = 33 Ohms -assign pwr_oe4 = 1'b0; // 10k Ohms - -// Debug Output ADC clock -assign dbg = adc_clk; - -// ADC clock out of phase with antenna driver -assign adc_clk = ~clk_state; - -// serialized SSP data is gated by clk_state to suppress unwanted signal -assign ssp_din = to_arm_shiftreg[7] && !clk_state; - -// SSP clock always runs at 24MHz -assign ssp_clk = pck0; - -// SSP frame is gated by clk_state and goes high when pck_divider=8..15 -assign ssp_frame = (pck_divider[7:3] == 5'd1) && !clk_state; - -// divide 24mhz down to 3mhz -always @(posedge pck0) -begin - if (pck_divider == divisor[7:0]) - begin - pck_divider <= 8'd0; - clk_state = !clk_state; - end - else - begin - pck_divider <= pck_divider + 1; - end -end - -// this task also runs at pck0 frequency (24Mhz) and is used to serialize -// the ADC output which is then clocked into the ARM SSP. -always @(posedge pck0) -begin - if ((pck_divider == 8'd7) && !clk_state) - to_arm_shiftreg <= adc_d; - else begin - to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; - // simulation showed a glitch occurring due to the LSB of the shifter - // not being set as we shift bits out - // this ensures the ssp_din remains low after a transfer and suppresses - // the glitch that would occur when the last data shifted out ended in - // a 1 bit and the next data shifted out started with a 0 bit - to_arm_shiftreg[0] <= 1'b0; - end -end - -endmodule diff --git a/fpga-xc3s100e/lo_edge_detect.v b/fpga-xc3s100e/lo_edge_detect.v deleted file mode 100644 index d91bf3845c..0000000000 --- a/fpga-xc3s100e/lo_edge_detect.v +++ /dev/null @@ -1,70 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2014 iZsh -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// -// There are two modes: -// - lf_ed_toggle_mode == 0: the output is set low (resp. high) when a low -// (resp. high) edge/peak is detected, with hysteresis -// - lf_ed_toggle_mode == 1: the output is toggling whenever an edge/peak -// is detected. -// That way you can detect two consecutive edges/peaks at the same level (L/H) -// -// Output: -// - ssp_frame (wired to TIOA1 on the arm) for the edge detection/state -// - ssp_clk: cross_lo - -//For ISE 10.1 PROJ,IDE auto include -//`include "lp20khz_1MSa_iir_filter.v" -//`include "lf_edge_detect.v" - -module lo_edge_detect( - input pck0, input pck_divclk, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, - output ssp_frame, input ssp_dout, output ssp_clk, - input cross_lo, - output dbg, - input lf_field, - input lf_ed_toggle_mode, input [7:0] lf_ed_threshold -); - -wire tag_modulation = ssp_dout & !lf_field; -wire reader_modulation = !ssp_dout & lf_field & pck_divclk; - -// No logic, straight through. -assign pwr_oe1 = 1'b0; // not used in LF mode -assign pwr_oe3 = 1'b0; // base antenna load = 33 Ohms -// when modulating, add another 33 Ohms and 10k Ohms in parallel: -assign pwr_oe2 = tag_modulation; -assign pwr_oe4 = tag_modulation; - -assign ssp_clk = cross_lo; -assign pwr_lo = reader_modulation; -assign pwr_hi = 1'b0; - -// filter the ADC values -wire data_rdy; -wire [7:0] adc_filtered; -assign adc_clk = pck0; -lp20khz_1MSa_iir_filter adc_filter(pck0, adc_d, data_rdy, adc_filtered); - -// detect edges -wire [7:0] high_threshold, highz_threshold, lowz_threshold, low_threshold; -wire [7:0] max, min; -wire edge_state, edge_toggle; -lf_edge_detect lf_ed(pck0, adc_filtered, lf_ed_threshold, - max, min, - high_threshold, highz_threshold, lowz_threshold, low_threshold, - edge_state, edge_toggle); - -assign dbg = lf_ed_toggle_mode ? edge_toggle : edge_state; - -assign ssp_frame = lf_ed_toggle_mode ? edge_toggle : edge_state; - -endmodule - diff --git a/fpga-xc3s100e/lo_passthru.v b/fpga-xc3s100e/lo_passthru.v deleted file mode 100644 index f0f2847a0f..0000000000 --- a/fpga-xc3s100e/lo_passthru.v +++ /dev/null @@ -1,29 +0,0 @@ -//----------------------------------------------------------------------------- -// For reading TI tags, we need to place the FPGA in pass through mode -// and pass everything through to the ARM -//----------------------------------------------------------------------------- -// iZsh , June 2014 - -module lo_passthru( - input pck_divclk, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - output adc_clk, - output ssp_din, input ssp_dout, - input cross_lo, - output dbg -); - -// the antenna is modulated when ssp_dout = 1, when 0 the -// antenna drivers stop modulating and go into listen mode -assign pwr_oe3 = 1'b0; -assign pwr_oe1 = ssp_dout; -assign pwr_oe2 = ssp_dout; -assign pwr_oe4 = ssp_dout; -assign pwr_lo = pck_divclk && ssp_dout; -assign pwr_hi = 1'b0; -assign adc_clk = 1'b0; -assign ssp_din = cross_lo; -assign dbg = cross_lo; - -endmodule diff --git a/fpga-xc3s100e/lo_read.v b/fpga-xc3s100e/lo_read.v deleted file mode 100644 index 8ac58721e5..0000000000 --- a/fpga-xc3s100e/lo_read.v +++ /dev/null @@ -1,74 +0,0 @@ -//----------------------------------------------------------------------------- -// The way that we connect things in low-frequency read mode. In this case -// we are generating the unmodulated low frequency carrier. -// The A/D samples at that same rate and the result is serialized. -// -// Jonathan Westhues, April 2006 -// iZsh , June 2014 -//----------------------------------------------------------------------------- - -module lo_read( - input pck0, input [7:0] pck_cnt, input pck_divclk, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, - output ssp_frame, output ssp_din, output ssp_clk, - output dbg, - input lf_field -); - -reg [7:0] to_arm_shiftreg; - -// this task also runs at pck0 frequency (24MHz) and is used to serialize -// the ADC output which is then clocked into the ARM SSP. - -// because pck_divclk always transitions when pck_cnt = 0 we use the -// pck_div counter to sync our other signals off it -// we read the ADC value when pck_cnt=7 and shift it out on counts 8..15 -always @(posedge pck0) -begin - if((pck_cnt == 8'd7) && !pck_divclk) - to_arm_shiftreg <= adc_d; - else begin - to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; - // simulation showed a glitch occurring due to the LSB of the shifter - // not being set as we shift bits out - // this ensures the ssp_din remains low after a transfer and suppresses - // the glitch that would occur when the last data shifted out ended in - // a 1 bit and the next data shifted out started with a 0 bit - to_arm_shiftreg[0] <= 1'b0; - end -end - -// ADC samples on falling edge of adc_clk, data available on the rising edge - -// example of ssp transfer of binary value 1100101 -// start of transfer is indicated by the rise of the ssp_frame signal -// ssp_din changes on the rising edge of the ssp_clk clock and is clocked into -// the ARM by the falling edge of ssp_clk -// _______________________________ -// ssp_frame__| |__ -// _______ ___ ___ -// ssp_din __| |_______| |___| |______ -// _ _ _ _ _ _ _ _ _ _ -// ssp_clk |_| |_| |_| |_| |_| |_| |_| |_| |_| |_ - -// serialized SSP data is gated by ant_lo to suppress unwanted signal -assign ssp_din = to_arm_shiftreg[7] && !pck_divclk; -// SSP clock always runs at 24MHz -assign ssp_clk = pck0; -// SSP frame is gated by ant_lo and goes high when pck_divider=8..15 -assign ssp_frame = (pck_cnt[7:3] == 5'd1) && !pck_divclk; -// unused signals tied low -assign pwr_hi = 1'b0; -assign pwr_oe1 = 1'b0; -assign pwr_oe2 = 1'b0; -assign pwr_oe3 = 1'b0; -assign pwr_oe4 = 1'b0; -// this is the antenna driver signal -assign pwr_lo = lf_field & pck_divclk; -// ADC clock out of phase with antenna driver -assign adc_clk = ~pck_divclk; -// ADC clock also routed to debug pin -assign dbg = adc_clk; -endmodule diff --git a/fpga-xc3s100e/lp20khz_1MSa_iir_filter.v b/fpga-xc3s100e/lp20khz_1MSa_iir_filter.v deleted file mode 100644 index 2dbfd69452..0000000000 --- a/fpga-xc3s100e/lp20khz_1MSa_iir_filter.v +++ /dev/null @@ -1,81 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2014 iZsh -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Butterworth low pass IIR filter -// input: 8bit ADC signal, 1MS/s -// output: 8bit value, Fc=20khz -// -// coef: (using http://www-users.cs.york.ac.uk/~fisher/mkfilter/trad.html) -// Recurrence relation: -// y[n] = ( 1 * x[n- 2]) -// + ( 2 * x[n- 1]) -// + ( 1 * x[n- 0]) - -// + ( -0.8371816513 * y[n- 2]) -// + ( 1.8226949252 * y[n- 1]) -// -// therefore: -// a = [1,2,1] -// b = [-0.8371816513, 1.8226949252] -// b is approximated to b = [-0xd6/0x100, 0x1d3 / 0x100] (for optimization) -// gain = 2.761139367e2 -// -// See details about its design see -// https://fail0verflow.com/blog/2014/proxmark3-fpga-iir-filter.html -module lp20khz_1MSa_iir_filter(input clk, input [7:0] adc_d, output rdy, output [7:0] out); - - // clk is 24MHz, the IIR filter is designed for 1MS/s - // hence we need to divide it by 24 - // using a shift register takes less area than a counter - reg [23:0] cnt = 1; - assign rdy = cnt[0]; - always @(posedge clk) - cnt <= {cnt[22:0], cnt[23]}; - - reg [7:0] x0 = 0; - reg [7:0] x1 = 0; - reg [16:0] y0 = 0; - reg [16:0] y1 = 0; - - always @(posedge clk) - begin - if (rdy) - begin - x0 <= x1; - x1 <= adc_d; - y0 <= y1; - y1 <= - // center the signal: - // input range is [0; 255] - // We want "128" to be at the center of the 17bit register - // (128+z)*gain = 17bit center - // z = (1<<16)/gain - 128 = 109 - // We could use 9bit x registers for that, but that would be - // a waste, let's just add the constant during the computation - // (x0+109) + 2*(x1+109) + (x2+109) = x0 + 2*x1 + x2 + 436 - x0 + {x1, 1'b0} + adc_d + 436 - // we want "- y0 * 0xd6 / 0x100" using only shift and add - // 0xd6 == 0b11010110 - // so *0xd6/0x100 is equivalent to - // ((x << 1) + (x << 2) + (x << 4) + (x << 6) + (x << 7)) >> 8 - // which is also equivalent to - // (x >> 7) + (x >> 6) + (x >> 4) + (x >> 2) + (x >> 1) - - ((y0 >> 7) + (y0 >> 6) + (y0 >> 4) + (y0 >> 2) + (y0 >> 1)) // - y0 * 0xd6 / 0x100 - // we want "+ y1 * 0x1d3 / 0x100" - // 0x1d3 == 0b111010011 - // so this is equivalent to - // ((x << 0) + (x << 1) + (x << 4) + (x << 6) + (x << 7) + (x << 8)) >> 8 - // which is also equivalent to - // (x >> 8) + (x >> 7) + (x >> 4) + (x >> 2) + (x >> 1) + (x >> 0) - + ((y1 >> 8) + (y1 >> 7) + (y1 >> 4) + (y1 >> 2) + (y1 >> 1) + y1); - end - end - - // output: reduce to 8bit - assign out = y1[16:9]; - -endmodule diff --git a/fpga-xc3s100e/min_max_tracker.v b/fpga-xc3s100e/min_max_tracker.v deleted file mode 100644 index 5e8bbedf1f..0000000000 --- a/fpga-xc3s100e/min_max_tracker.v +++ /dev/null @@ -1,65 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2014 iZsh -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// track min and max peak values (envelope follower) -// -// NB: the min value (resp. max value) is updated only when the next high peak -// (resp. low peak) is reached/detected, since you can't know it isn't a -// local minima (resp. maxima) until then. -// This also means the peaks are detected with an unpredictable delay. -// This algorithm therefore can't be used directly for realtime peak detections, -// but it can be used as a simple envelope follower. -module min_max_tracker(input clk, input [7:0] adc_d, input [7:0] threshold, - output [7:0] min, output [7:0] max); - - reg [7:0] min_val = 255; - reg [7:0] max_val = 0; - reg [7:0] cur_min_val = 255; - reg [7:0] cur_max_val = 0; - reg [1:0] state = 0; - - always @(posedge clk) - begin - case (state) - 0: // initialize - begin - if (cur_max_val >= ({1'b0, adc_d} + threshold)) - state <= 2; - else if (adc_d >= ({1'b0, cur_min_val} + threshold)) - state <= 1; - if (cur_max_val <= adc_d) - cur_max_val <= adc_d; - else if (adc_d <= cur_min_val) - cur_min_val <= adc_d; - end - 1: // high phase - begin - if (cur_max_val <= adc_d) - cur_max_val <= adc_d; - else if (({1'b0, adc_d} + threshold) <= cur_max_val) begin - state <= 2; - cur_min_val <= adc_d; - max_val <= cur_max_val; - end - end - 2: // low phase - begin - if (adc_d <= cur_min_val) - cur_min_val <= adc_d; - else if (adc_d >= ({1'b0, cur_min_val} + threshold)) begin - state <= 1; - cur_max_val <= adc_d; - min_val <= cur_min_val; - end - end - endcase - end - - assign min = min_val; - assign max = max_val; - -endmodule diff --git a/fpga-xc3s100e/util.v b/fpga-xc3s100e/util.v deleted file mode 100644 index 0842ac64f4..0000000000 --- a/fpga-xc3s100e/util.v +++ /dev/null @@ -1,27 +0,0 @@ -//----------------------------------------------------------------------------- -// General-purpose miscellany. -// -// Jonathan Westhues, April 2006. -//----------------------------------------------------------------------------- - -module mux8(sel, y, x0, x1, x2, x3, x4, x5, x6, x7); - input [2:0] sel; - input x0, x1, x2, x3, x4, x5, x6, x7; - output y; - reg y; - -always @(x0 or x1 or x2 or x3 or x4 or x5 or x6 or x7 or sel) -begin - case (sel) - 3'b000: y = x0; - 3'b001: y = x1; - 3'b010: y = x2; - 3'b011: y = x3; - 3'b100: y = x4; - 3'b101: y = x5; - 3'b110: y = x6; - 3'b111: y = x7; - endcase -end - -endmodule diff --git a/fpga/Makefile b/fpga/Makefile new file mode 100644 index 0000000000..e5bca0dfb9 --- /dev/null +++ b/fpga/Makefile @@ -0,0 +1,221 @@ +# +# FPGA Makefile for all targets +# +# The top part of this Makefile is used to define custom options for a number of compilation targets +# To define an additional target simply look at the other defined targets and add a new TARGET entry with a unique number and the custom options required + +XILINX_TOOLS_PREFIX= + +# Copy update (only when destination is older or missing) +CP = cp -u + +# Make directory, no error if already existing +MKDIR = mkdir -p + +# Remove recursive, force +RMDIR = rm -rf + +# Path to make +MAKE = make + +# Custom prefix for build directories, each target is built into its own separate directory name formed by combining the PREFIX and TARGET names. +# This way the source is not polluted with build files and the build directories are left behind after compilation so logs and reports can be +# examined or can be easily deleted with "make clean" +PREFIX = __ + +# Options to be passed to XST +XST_OPTS_BASE = run +XST_OPTS_BASE += -ifn xst.prj +XST_OPTS_BASE += -ifmt mixed +XST_OPTS_BASE += -ofmt NGC +XST_OPTS_BASE += -lso xst.lso +XST_OPTS_BASE += -top fpga_top +XST_OPTS_BASE += -resource_sharing yes + +# Optimizations for speed (default) +XST_OPTS_SPEED = -opt_mode Speed +XST_OPTS_SPEED += -opt_level 1 +XST_OPTS_SPEED += -fsm_style lut +XST_OPTS_SPEED += -fsm_encoding auto + +# Optimization for reduced space +XST_OPTS_AREA = -opt_mode area +XST_OPTS_AREA += -opt_level 2 +XST_OPTS_AREA += -fsm_style bram +XST_OPTS_AREA += -fsm_encoding compact + +# Types of selective module compilation: +# WITH_LF Enables selection of LF modules (and disables all HF) + +# To enable these modules WITH_LF _MUST_ be defined +# WITH_LF0 enable LF reader (generic) +# WITH_LF1 enable LF edge detect (generic) +# WITH_LF2 enable LF passthrough +# WITH_LF3 enable LF ADC (read/write) + +# To enable these modules WITH_LF _MUST_NOT_ be defined +# WITH_HF0 enable HF reader (see also WITH_HF_15 below) +# WITH_HF_15 select "iso15 2sc mode" extensions instead of original +# WITH_HF1 enable HF simulated tag +# WITH_HF2 enable HF ISO14443-A +# WITH_HF3 enable sniff +# WITH_HF4 enable HF ISO18092 FeliCa +# WITH_HF5 enable HF get trace + +# RDV40/Generic - Enable LF and all the LF modules +TARGET1_OPTIONS = -define \{WITH_LF WITH_LF0 WITH_LF1 WITH_LF2 WITH_LF3\} +# RDV40/Generic - Enable all HF modules except Felica +TARGET2_OPTIONS = -define \{WITH_HF0 WITH_HF1 WITH_HF2 WITH_HF3 WITH_HF5\} +# RDV40/Generic - Enable all HF modules except Felica and ISO14443, select HF_15 instead of HF +TARGET3_OPTIONS = -define \{WITH_HF0 WITH_HF1 WITH_HF3 WITH_HF5 WITH_HF_15\} +# RDV40/Generic - Enable all HF modules except ISO14443 +TARGET4_OPTIONS = -define \{WITH_HF0 WITH_HF1 WITH_HF3 WITH_HF4 WITH_HF5\} +# ICOPYX +TARGET5_OPTIONS = -define {PM3ICOPYX} -rtlview Yes + +# Here we list the target names +TARGET1_NAME = fpga_pm3_lf +TARGET2_NAME = fpga_pm3_hf +TARGET3_NAME = fpga_pm3_hf_15 +TARGET4_NAME = fpga_pm3_felica +TARGET5_NAME = fpga_icopyx_hf + +# Targets can be compiled for different FPGA flavours +TARGET1_FPGA = xc2s30-5-vq100 +TARGET2_FPGA = $(TARGET1_FPGA) +TARGET3_FPGA = $(TARGET1_FPGA) +TARGET4_FPGA = $(TARGET1_FPGA) +TARGET5_FPGA = xc3s100e-4-vq100 + +# Assemble the final XST options for each target +TARGET1_XST_OPTS = $(XST_OPTS_BASE) $(XST_OPTS_AREA) -p $(TARGET1_FPGA) -ofn $(TARGET1_NAME) $(TARGET1_OPTIONS) +TARGET2_XST_OPTS = $(XST_OPTS_BASE) $(XST_OPTS_AREA) -p $(TARGET2_FPGA) -ofn $(TARGET2_NAME) $(TARGET2_OPTIONS) +TARGET3_XST_OPTS = $(XST_OPTS_BASE) $(XST_OPTS_AREA) -p $(TARGET3_FPGA) -ofn $(TARGET3_NAME) $(TARGET3_OPTIONS) +TARGET4_XST_OPTS = $(XST_OPTS_BASE) $(XST_OPTS_AREA) -p $(TARGET4_FPGA) -ofn $(TARGET4_NAME) $(TARGET4_OPTIONS) +TARGET5_XST_OPTS = $(XST_OPTS_BASE) $(XST_OPTS_SPEED) -p $(TARGET5_FPGA) -ofn $(TARGET5_NAME) $(TARGET5_OPTIONS) + +# these files are common for all targets +TARGET_COMMON_FILES = define.v +TARGET_COMMON_FILES += mux8.v +TARGET_COMMON_FILES += clk_divider.v +TARGET_COMMON_FILES += lp20khz_1MSa_iir_filter.v +TARGET_COMMON_FILES += min_max_tracker.v +TARGET_COMMON_FILES += hi_flite.v +TARGET_COMMON_FILES += hi_get_trace.v +TARGET_COMMON_FILES += hi_iso14443a.v +TARGET_COMMON_FILES += hi_reader.v +TARGET_COMMON_FILES += hi_reader_15.v +TARGET_COMMON_FILES += hi_simulate.v +TARGET_COMMON_FILES += hi_sniffer.v +TARGET_COMMON_FILES += lf_edge_detect.v +TARGET_COMMON_FILES += lo_adc.v +TARGET_COMMON_FILES += lo_edge_detect.v +TARGET_COMMON_FILES += lo_passthru.v +TARGET_COMMON_FILES += lo_read.v + +# Add the files that are unique per target and all the common files +TARGET1_FILES = $(TARGET_COMMON_FILES) fpga_pm3_top.v +TARGET2_FILES = $(TARGET1_FILES) +TARGET3_FILES = $(TARGET1_FILES) +TARGET4_FILES = $(TARGET1_FILES) +TARGET5_FILES = $(TARGET_COMMON_FILES) mux2_onein.v mux2_oneout.v fpga_icopyx_hf.v fpga_icopyx_lf.v fpga_icopyx_top.v + +# List of all valid target FPGA images to build +TARGETS = $(TARGET1_NAME) $(TARGET2_NAME) $(TARGET3_NAME) $(TARGET4_NAME) $(TARGET5_NAME) + +# Verbosity type for ISE tools ise|xflow|silent +VERBOSITY = -intstyle silent +# Echo (Q=) or not echo (Q=@) build commands to the terminal +Q=@ + +# Pass the custom variables to the lower make rules +$(TARGET1_NAME).bit: TARGET_FPGA = $(TARGET1_FPGA) +$(TARGET1_NAME).bit: TARGET_FILES = $(TARGET1_FILES) +$(TARGET1_NAME).bit: TARGET_XST_OPTS = $(TARGET1_XST_OPTS) + +$(TARGET2_NAME).bit: TARGET_FPGA = $(TARGET2_FPGA) +$(TARGET2_NAME).bit: TARGET_FILES = $(TARGET2_FILES) +$(TARGET2_NAME).bit: TARGET_XST_OPTS = $(TARGET2_XST_OPTS) + +$(TARGET3_NAME).bit: TARGET_FPGA = $(TARGET3_FPGA) +$(TARGET3_NAME).bit: TARGET_FILES = $(TARGET3_FILES) +$(TARGET3_NAME).bit: TARGET_XST_OPTS = $(TARGET3_XST_OPTS) + +$(TARGET4_NAME).bit: TARGET_FPGA = $(TARGET4_FPGA) +$(TARGET4_NAME).bit: TARGET_FILES = $(TARGET4_FILES) +$(TARGET4_NAME).bit: TARGET_XST_OPTS = $(TARGET4_XST_OPTS) + +$(TARGET5_NAME).bit: TARGET_FPGA = $(TARGET5_FPGA) +$(TARGET5_NAME).bit: TARGET_FILES = $(TARGET5_FILES) +$(TARGET5_NAME).bit: TARGET_XST_OPTS = $(TARGET5_XST_OPTS) + +$(TARGETS): + $(Q)$(MKDIR) $(PREFIX)build_$@ + $(Q)$(MAKE) -C $(PREFIX)build_$@ -f ../Makefile $(notdir $@).bit + +work: + $(Q)$(RM) xst.prj + $(Q)for item in $(TARGET_FILES); do echo verilog work ../$$item>>xst.prj; done + $(Q)echo work> xst.lso + +%.xst: work + $(Q)$(RM) $@ + $(Q)echo $(TARGET_XST_OPTS)> $@ + +%.ngc: %.xst + $(Q)$(RM) $@ + $(info [-] XST $@) + $(Q)$(XILINX_TOOLS_PREFIX)xst $(VERBOSITY) -ifn $< + +%.ngd: %.ngc + $(Q)$(RM) $@ + $(info [-] NGD $@) + $(Q)$(XILINX_TOOLS_PREFIX)ngdbuild $(VERBOSITY) -quiet -p $(TARGET_FPGA) -nt timestamp -uc ../$(TARGET_FPGA).ucf $< $@ + +%_map.ncd: %.ngd + $(Q)$(RM) $@ + $(info [-] MAP $@) + $(Q)$(XILINX_TOOLS_PREFIX)map $(VERBOSITY) -p $(TARGET_FPGA) -o $*_map $* + +%.ncd: %_map.ncd + $(Q)$(RM) $@ + $(info [-] PAR $@) + $(Q)$(XILINX_TOOLS_PREFIX)par $(VERBOSITY) -w $< $@ + +%.bit: %.ncd + # Hacky hack, make empty files for icopyx + if echo "$@" | grep -qi "icopyx"; then \ + truncate -s0 ../fpga_icopyx_lf.bit; \ + truncate -s0 ../fpga_icopyx_hf_15.bit; \ + truncate -s0 ../fpga_icopyx_felica.bit; \ + fi + $(Q)$(RM) $@ $*.drc $*.rbt + $(info [=] BITGEN $@) + $(Q)$(XILINX_TOOLS_PREFIX)bitgen $(VERBOSITY) -w $* $@ + $(Q)$(CP) $@ .. + +# Build all targets +all: $(TARGETS) + +# ALWAYS have some hardcoded text after $(PREFIX) to avoid rm -rf * or rm -rf /* situations if PREFIX is incorrectly set to empty "" or just "/" +clean: + $(Q)$(RMDIR) $(PREFIX)build_* + $(info [-] Build files deleted) + +.DEFAULT: + @if [ "$@" != "all" ] && [ ! "$(filter $@,$(TARGETS))" ]; then \ + make help; \ + else \ + make all; \ + fi + +.PHONY: all help clean + +help: + @echo "################################################################" + @echo "# Valid targets are: $(TARGETS)" + @echo "# - Builds only one of the above listed targets" + @echo "# all - Builds the FPGA bitstreams for all targets" + @echo "# clean - Keeps .bit files but cleans intermediate build files for all targets" + @echo "################################################################" + diff --git a/fpga-xc2s30/clk_divider.v b/fpga/clk_divider.v similarity index 91% rename from fpga-xc2s30/clk_divider.v rename to fpga/clk_divider.v index fbb3250f16..0bcc2e608c 100644 --- a/fpga-xc2s30/clk_divider.v +++ b/fpga/clk_divider.v @@ -14,7 +14,12 @@ // See LICENSE.txt for the text of the license. //----------------------------------------------------------------------------- -module clk_divider(input clk, input [7:0] divisor, output [7:0] div_cnt, output div_clk); +module clk_divider( + input clk, + input [7:0] divisor, + output [7:0] div_cnt, + output div_clk +); reg [7:0] div_cnt_ = 0; reg div_clk_; diff --git a/fpga/define.v b/fpga/define.v new file mode 100644 index 0000000000..b7423278be --- /dev/null +++ b/fpga/define.v @@ -0,0 +1,155 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// +// The FPGA is responsible for interfacing between the A/D, the coil drivers, +// and the ARM. In the low-frequency modes it passes the data straight +// through, so that the ARM gets raw A/D samples over the SSP. In the high- +// frequency modes, the FPGA might perform some demodulation first, to +// reduce the amount of data that we must send to the ARM. +//----------------------------------------------------------------------------- + +/* + Communication between ARM / FPGA is done inside armsrc/fpgaloader.c see: function FpgaSendCommand() + Send 16 bit command / data pair to FPGA with the bit format: + ++------ frame layout circa 2020 ------------------+ +| 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 | ++-------------------------------------------------+ +| C C C C M M M M P P P P P P P P | C = FPGA_CMD_SET_CONFREG, M = FPGA_MAJOR_MODE_*, P = FPGA_LF_* or FPGA_HF_* parameter +| C C C C D D D D D D D D | C = FPGA_CMD_SET_DIVISOR, D = divisor +| C C C C T T T T T T T T | C = FPGA_CMD_SET_EDGE_DETECT_THRESHOLD, T = threshold +| C C C C E | C = FPGA_CMD_TRACE_ENABLE, E=0 off, E=1 on ++-------------------------------------------------+ + ++------ frame layout current ---------------------+ +| 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 | ++-------------------------------------------------+ +| C C C C M M M P P P P P P | C = FPGA_CMD_SET_CONFREG, M = FPGA_MAJOR_MODE_*, P = FPGA_LF_* or FPGA_HF_* parameter +| C C C C D D D D D D D D | C = FPGA_CMD_SET_DIVISOR, D = divisor +| C C C C T T T T T T T T | C = FPGA_CMD_SET_EDGE_DETECT_THRESHOLD, T = threshold +| C C C C E | C = FPGA_CMD_TRACE_ENABLE, E=0 off, E=1 on ++-------------------------------------------------+ + + shift_reg receive this 16bit frame + + LF command + ---------- + shift_reg[15:12] == 4bit command + LF has three commands (FPGA_CMD_SET_CONFREG, FPGA_CMD_SET_DIVISOR, FPGA_CMD_SET_EDGE_DETECT_THRESHOLD) + Current commands uses only 2bits. We have room for up to 4bits of commands total (7). + + LF data + ------- + shift_reg[11:0] == 12bit data + lf data is divided into MAJOR MODES and configuration values. + + The major modes uses 3bits (0,1,2,3,7 | 000, 001, 010, 011, 111) + 000 FPGA_MAJOR_MODE_LF_READER = Act as LF reader (modulate) + 001 FPGA_MAJOR_MODE_LF_EDGE_DETECT = Simulate LF + 010 FPGA_MAJOR_MODE_LF_PASSTHRU = Passthrough mode, CROSS_LO line connected to SSP_DIN. SSP_DOUT logic level controls if we modulate / listening + 011 FPGA_MAJOR_MODE_LF_ADC = refactor hitag2, clear ADC sampling + 111 FPGA_MAJOR_MODE_OFF = turn off sampling. + + Each one of this major modes can have options. Currently these two major modes uses options. + - FPGA_MAJOR_MODE_LF_READER + - FPGA_MAJOR_MODE_LF_EDGE_DETECT + + FPGA_MAJOR_MODE_LF_READER + ------------------------------------- + lf_field = 1bit (FPGA_LF_ADC_READER_FIELD) + + You can send FPGA_CMD_SET_DIVISOR to set with FREQUENCY the fpga should sample at + divisor = 8bits shift_reg[7:0] + + FPGA_MAJOR_MODE_LF_EDGE_DETECT + ------------------------------------------ + lf_ed_toggle_mode = 1bits + lf_ed_threshold = 8bits threshold defaults to 127 + + You can send FPGA_CMD_SET_EDGE_DETECT_THRESHOLD to set a custom threshold + lf_ed_threshold = 8bits threshold value. + + conf_word 12bits + conf_word[7:5] = 3bit major mode. + conf_word[0] = 1bit lf_field + conf_word[1] = 1bit lf_ed_toggle_mode + conf_word[7:0] = 8bit divisor + conf_word[7:0] = 8bit threshold + +*/ +// Defining commands, modes and options. This must be aligned to the definitions in armsrc/fpgaloader.h +// Note: the definitions here are without shifts + +// Definitions for the FPGA commands. +`define FPGA_CMD_SET_CONFREG 1 +`define FPGA_CMD_SET_DIVISOR 2 +`define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD 3 +`define FPGA_CMD_TRACE_ENABLE 2 + +// Major modes +`define FPGA_MAJOR_MODE_LF_READER 0 +`define FPGA_MAJOR_MODE_LF_EDGE_DETECT 1 +`define FPGA_MAJOR_MODE_LF_PASSTHRU 2 +`define FPGA_MAJOR_MODE_LF_ADC 3 +`define FPGA_MAJOR_MODE_HF_READER 0 +`define FPGA_MAJOR_MODE_HF_SIMULATOR 1 +`define FPGA_MAJOR_MODE_HF_ISO14443A 2 +`define FPGA_MAJOR_MODE_HF_SNIFF 3 +`define FPGA_MAJOR_MODE_HF_ISO18092 4 +`define FPGA_MAJOR_MODE_HF_GET_TRACE 5 +`define FPGA_MAJOR_MODE_OFF 7 + +// Options for LF_READER +`define FPGA_LF_ADC_READER_FIELD 1 + +// Options for LF_EDGE_DETECT +`define FPGA_LF_EDGE_DETECT_READER_FIELD 1 +`define FPGA_LF_EDGE_DETECT_TOGGLE_MODE 2 + +// Options for the generic HF reader +`define FPGA_HF_READER_MODE_RECEIVE_IQ 0 +`define FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE 1 +`define FPGA_HF_READER_MODE_RECEIVE_PHASE 2 +`define FPGA_HF_READER_MODE_SEND_FULL_MOD 3 +`define FPGA_HF_READER_MODE_SEND_SHALLOW_MOD 4 +`define FPGA_HF_READER_MODE_SNIFF_IQ 5 +`define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE 6 +`define FPGA_HF_READER_MODE_SNIFF_PHASE 7 +`define FPGA_HF_READER_MODE_SEND_JAM 8 + +`define FPGA_HF_READER_SUBCARRIER_848_KHZ 0 +`define FPGA_HF_READER_SUBCARRIER_424_KHZ 1 +`define FPGA_HF_READER_SUBCARRIER_212_KHZ 2 +`define FPGA_HF_READER_2SUBCARRIERS_424_484_KHZ 3 + +// Options for the HF simulated tag, how to modulate +`define FPGA_HF_SIMULATOR_NO_MODULATION 0 +`define FPGA_HF_SIMULATOR_MODULATE_BPSK 1 +`define FPGA_HF_SIMULATOR_MODULATE_212K 2 +`define FPGA_HF_SIMULATOR_MODULATE_424K 4 +`define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 5 + +// Options for ISO14443A +`define FPGA_HF_ISO14443A_SNIFFER 0 +`define FPGA_HF_ISO14443A_TAGSIM_LISTEN 1 +`define FPGA_HF_ISO14443A_TAGSIM_MOD 2 +`define FPGA_HF_ISO14443A_READER_LISTEN 3 +`define FPGA_HF_ISO14443A_READER_MOD 4 + +// Options for ISO18092 / Felica +`define FPGA_HF_ISO18092_FLAG_NOMOD 1 // 0001 disable modulation module +`define FPGA_HF_ISO18092_FLAG_424K 2 // 0010 should enable 414k mode (untested). No autodetect +`define FPGA_HF_ISO18092_FLAG_READER 4 // 0100 enables antenna power, to act as a reader instead of tag diff --git a/fpga-xc3s100e/fpga_felica.bit b/fpga/fpga_icopyx_felica.bit similarity index 100% rename from fpga-xc3s100e/fpga_felica.bit rename to fpga/fpga_icopyx_felica.bit diff --git a/fpga/fpga_icopyx_hf.bit b/fpga/fpga_icopyx_hf.bit new file mode 100644 index 0000000000000000000000000000000000000000..b62cdace60a2f3d95eac23c61b26a334a08dc47a GIT binary patch literal 72749 zcmeFa4SXC&l`nd#yEST!N28WJHcBFUOR^Fs!AaV-$cmtllB~pvF)#@>o9ADENn*S< z%Ps?C7sGN%Nmk-X;)H=XzL-te!C){VY(&WN^Ac{-jvTBcV&f(3-Mq(U8GrDuFYFUa zLiiBI^ZuuLX7p)WW)t?_`{PL6^>ymhsjAa8b?Q`CQ%&7i_(vper1={&e|qD4H{blh z%*VF8chkm8{^I5hbQ8r^d}NvLzwfU;ggf0#^OpO|S6u49@zNDOZJ?TEZ@Rp#?eex| z^ga^j{c900uxs5$pR^#NYG0(;^?f1XF8i@B0wMO(y*>pTPbIt>pE$h|7CtFT(bZqz zxYr6S5MDr}iKvZ^ zo2sy(D?TDt_@;uI8vI{irZ+`fnaUkSr-f$?`m@HqmXQ@*rOe;NY;&SPC$lxPjuUvV zC8Ph@wEs`2rTWiq#Mi3)_3JloTrsk4VB^O1>pMC&Zv5?Uc`fTF1H~c{r*Qnnjhx=m z!6{{+LHFAaJyb_0_MX@~S{NTLo;)eWMpk_D(QL7}3ox)Qy!PzbwJQj2HQ7$sBTotO ztY45vP@|TG5&zb5VvG$aflI?M@ACA->4jLaysmjr57}k(aMUxb9|pB8jxt z5U)Z9^eW{s&ZO{UKjUzDA@0mNGzdy87Z%Dh7s|Bm7FZ1wtqQzY9Og9CWg@--9GB8K zp3`e85}{efxM-CRCZ^(20CKGMop z>)UI}`G}@I-YhTc23TG~sp5WQ7#f<8iIEip>%!P#@ul%#yrYBVj3tb7uNWC0KCyS~ z`&mMd7em<#rF7%Q&6@|-u|y55V|pVi_Uw6KEIX!AkFkM)k%57S@?!%}Km9^>wB?2D z$k=H2^UsgAd}O#(77Yv(X=G$#4FzgrVS#8i>D93VRsEBHQ}lWl3I94?V9j86vPm3=x{ni z*$qP^ruIWA);KMtJ_;sB!f(6CgI}fn{RqG{&EQhE;BpY&>YzT&5JFCG#x)HX&uJ#R zNo6pJ@dlr1ymtskqa~mV-fsBaR8ckygWGQ@_n&mjdm?&jOX3!4Kyj+)qn1J^A#|lC94T>%%Rygtnsb=-#K)ZNNMFFTIGFfGPbTBsZik z3kI;XB5qHclBk1gn%Zi1(a40$gCp5z=RihTo{W(vkl$(cEN(dTBv>qi<_)MrQ49OJZ>3Zs*BUfP*Bh>&z%J*39A71sqCy5gKXd9(1`VM6*lpj~% zGG9@8~A__iE2as?}u+6dXxYHAV?5g_cL}-lrT( zx*wuy1$wHFUWc{`1n|-AoSp~!w6+~L?u&Mzxl*Ft){HU}G+GFfknZ>LETznTUq3e! z_@{qkpO*e0iQ)_^VK~U+M zoOAe_U|(>fhjLNPUhaug^h2K7_F`&8)_%|g4+Z*kl3S5moT}q}Tvo=h&Lvu8We{*x zW)syZ{lx8B+xInfQ`8-_bMIBni97Ypcl{AC2nAy3(h1WDL5ejWYX?!n`sAisiq4~@YUh^s9H5AJjjnl#5L z#e*V`JT7HfB&nxIxhk7fJ=w0+HCB&G5{gyQb+<>O8YQ?{Jh)KD+%-LfF79z+Yx=ZB z{oLQmar(RaMa=DUfzv}h?rIFhD(1MIXlu8IZn18Bml8kQaKoUlKqNry#br6ijqWEcWoCt0aYDIF)A*948!pMy8IF5@F5XT`P zn7iQ&bYf@@5HiH99h}JRj;JbNr@pz~bv}%}DM^|2 zO{o-lsgfjU4^$*f!w`&C*OBl@B=JSAe=f>6*NURRIQm++?s~*}n1!Ig8*p12Ywu`s z-BdeIL;NU6Ae%%@lE}{m@*Uv#euiBZa34~m8@ZF zb5n+3+O-sfA5B|^5QDojgb806gWXd8$x*MSKP=SY0Z*KXZkbU?WEn#4Dmj@-8LN!) z8o85-Db>L=WF@*Ruw}Qz1|+?LGL5qmCLWtpqLg!3s_Z*!m$iV7j!@@heV|C8-Y_)8 zTEnhgW0>eey?`&&D8`46A0ID%`|&X~KFohS*B@DNYjL!DZ0yL9k&z=uiu7_YHum(> zBO~LfB0U?7jIe&NZ{M+Fj5{!L?ASod>_Uw^VS63GgQ*i%I zv3P5-_zn)As$vb$IiWj3ADhre8^rSaphI%pqK9eu9S!0#4nq$M!>n)e!_E39>zB0` ze26%%!P(-R>T=z7%p>rSLnmdI^9$seqH|(KQ?nF$ZfuLgczl_1xGY+xaGQXNkWNIg zP70k7e47jWTD1+rs_2zStDTf)bXFew8(i0^X@wq&i}g_8abDI>jgC4^H#Kn$z!CW%`u^w8-#>eAVD(Vq-x;y;FU1FT>273!rcR)q4!dTKc>)K*ywUBBL} zXShYIZLn{&P%N%n$0;jD)&rQv=FP?8iWL)UBTR22WRqb8dMLZBW%3;o6fL~?(PHt% zfnCK>NT*3>O*Bkrjda~Q!zkZo>4!?%96Y7$+PFEXsn&yziN1$!DMoOy`(Vl49=fL3 zDrzaYX3!EILKqFo&$O}T%_X{aFrQfo8cnJQ3QO}IZNSg+o5JCQ%@ardZp8x zeDY4}mCSqD1@>t`xdBL31)6azOa~AIxbVVP6Xwp~rZ0h1?eZuWM!kcHf2S6eN}R2?c~K{fnj+vqP3^jfG|m;{NRJew?!<~u0l zsL%m)V!d_$@N>#~X87Q9lLcr-Ke*&M3R60g{6mE1wMbjsG}K5MaqwUQCNbymFsfkc zk2chOnyNaxIJ&3sv1(&*)7pfYpFRdakP&Lm8^Ih0D+g(y_B zeo)h{f0&w-rM#|yXeoJ@bOl2ijY01#AOcUIKUnQ%(ID1{624p8S96$p+Bq-7%^HfC z*W@}m9@(3G)=5DXh3`z0NcnbpAJoz(z*r;n6n8-(&9l9x&H}popYFxjx?m%iMK>wW z(8G-xS0aB2Tyz5JGz;WGkfns`CF8rbiYM1nXc9F*k142~mTOU-mUpAWoEs?uiIOPe zkQj`T-`GX*WQ&GSIJJ#cpn!!Aw;4`1rrd;Q$P>~!WdVO;r z+Tzn4^yeDQSnVb~6^r&fbqBqyn=B`w_U5gTsEj23;TAkB&{o7yy6C`dZ#um3Bf{&B0E5IJce?y_JStFbHi=_ zmg>8%M}R?-im=sG3}FGg#+6m>%!$l@ju zT^Pcs#(}0MWBpOdWkc8;M`5sWFxn?#=nDbW4U!#mV{X=|0frNG0nC$e2;dkWG(_WK zc@14|@w02d!X3h9DY(=vTS;l~piPjYCIi|fN0h<^;6`e+VpfE5P)Q?kisbN15r=#^ zSa0VB$ytMbBXR)K$$WwaQ<3x|CC$;hyaU>^FTqNlGO^5Hj`n&KYr{~4cqbOSg{pE9 z=(jOnVJ4TR7~LPXKDZ|t#ZnIb{sQ{rx8k`B@zd@j>*+zESyG2QUL{P)ObW<@idPF6 zP`J~IM;J>%iKPS7%D)o)!;favbuo&eJ?Www+VNxpxZ|--q;(Z}8hu5zE~T&v1+-Wy zcLRn#H}(lcv$89oiE8*YF(OM&=yE-fp%mbF0FWfRj+CqzLxY`CD~+n-FNCsN3Ql)K z7!m&HF?sH2E~Q+e41*kdR$%BLhY@*`vrMro8?%0Tt{r>51g&=oQq^<7%Q?G5u#fkD+eex;l1Q2PoUBc*Z}T-?ei* zKbqw~PCpSC_tr=0jmE|qqu&&1t#bjVmEnc@OD2|9Y1m&1%@dN^mQyp2ecpk3SCIx?AaxCS6aO{&}67`lH9ERe_KIz`P&N3tz_e zShb~W4~4EaVb^3lgIls)mhF_BkK;MadS&@4hbN~^_KP&i1U}=j9?O2#X&FZ#%&xi2 ziu+_gq8Tdk$2|dn{Smq&>!A}mq)8~;a+v)u{40gB z^dposIKJk$uY9lQsz>LsK02YRVr^w$#fp&cNkds0?SNkdQy~oJ_|*xa?3RM3by`cQ z3a&&OCh}|_rMKqbg0L(#m*s@hhiIuhn6}aazh|8}@PMpJLb3y!sb~xqxYz}_GO!#> zvU1Q(fo9_P2FA<4I;C0Y#t*vzr<`&MS0cV^S{j6bfjjlC1cnxnhn>^J;ilP>*Kk{) zIgpT!M!EwX1@0Y)WcN;Wz67s%%N5cBE~fXA0DXyGZibqz)GHm0dF=#LDuKEQn*x)9 zhJcHLDiApA?a5;vX{M4^o@|w;s}D*N&Fe z=09WG3dEKSgIWj(g`fyt1qI3kE5G~YWKtxFtC2U2%vuCl5>pUUHKbaMDX}E$daBt=O|fno(f)5xmONoX_ZvdC=lbkvhs)B}|I@@|z(F*}F_00ZpVFx)}K zaynH{r)IP==t?(e=u=3^p*OOzHhv)NPcc^025~7mRK5Gdg-bff?xxX_caL{ z7W@sC)min0CTJG(w^;e6LmTSuK@SPqBu(Bd-xV#kP^T@_Oi7WB@G?I{uHmII;Jr^V zM%?H77jk*Sn9z$aN3daqUi3y0P^N&nqC~`@I!JlSv+{3P+AdT{Y7t+7D&vFQ5xS4) zG&G?%0AgFj?c7?CErn_hdvti4y90VK6r}79e_mhX;c9oKR1jgLXRM_$88j`Bj7p1L zz8~UDnjana5gWQDMTQmVssc5&e}oZAO2KZ2a_*Np5nRh{4`b7!#C)wH$E$xJ5=v6a z$h`{5pf2Kh38aaImsb?WB!^Jt&E(C`8aw1xH3P z@Us#znh2VB z+(r9Y=+io32ei{3^EGX1T1c)q5Jckbjn0R$-{BA%=rdk{>bHclWMsrD@NlOoosTqG zE(D6iQWVIO=cZ*#!lK~^IQ}PGhwWh)(W3D+K=kcCx_U3EjxpH%8!4rk_eL=W%N)0Z z0dP10(9M%Tf#%ZG4g*>SjRM^e`!6(DQ>^+g5J?gkt{U7#zhV=9+lK07#*&G*w1Q2c z$xTv^1%~#8)BmPYhu^RTmA`3Fpx&TEZB`qa8J_F^K%naI2&6ONDg+y;gNQ?Xg6-lctYJQj9BKL)*D9rw5m# z6=Eq1YDwH&Nv^^K1A69#N^21nF~5sq(P+|zG1I{Xp72y!-nrzXOvnt6p&rvS;N{ry z262;SW#Ky=g9~5;5Qp9vjn%|zC{|k&iLwP0wvMP<+gMABm~*ZjuiycE z{0(CM=6{?+yaog7qUjeiVn-sipQT!hB3v`90C9a_7zQFM-mFVw+^UVygA)A%KmuRi zap`Tj2R`@i2&}_{S1h`M-V?*x^qW$D$wL@GN4+L1nq`t&$InMm&-+ABh={F7NOgU5Vvsw&$uu>T-%^oEGGCshvrf{ZF;r zlmxl!!d@GoNy@yzqEC2!H0F8d0@snPDHMdVT`03?GypFYI9OWL9L*5`O_SytKnY_f z-MOh|2acbDuMvSVrD;-=N1FTO8#l!S=+KKeW)K%UrOpglEEmoR<*XRP0fKL(DC6hw z*#MK~jO8LAg65z1FlfY=K$ktCiyS;Mmdb})5@wE{h!v;>CroLdiR5yMDO!{nFh68S znicptnhE75nMjeL*Cd2FWGSkQGc(UMND7Cg5J#2DvUMeExp26=NCj??)Tu*!+-DN4 zB+c%*@BJr&Jo13%P7RTp(me~4y~IJ|f?`{<*Gw@lVS zr}%g7+QriLI8;s^*vqmsGE%m8vR$*zte3DXjSP(8|3vJBKiV=jGB!gmox#A&2zB-3 zxb)<}f6OmFi?*rs0@K121GYd~3K#orYZ5Ymy|4nBq~btt4mzoc_2i^v6LZR2np3={ zQ>Oop32e`GD>E{l!E%o$b)Um~zpw{4(JP(a3F2AOCU6(q&ETDf4M^cnnu$K+ttOlY zgNhED;0!qex-d_+bOVSx=ETi`BTWvC5J0(5C#$KtFyy&rJ}#ZxNFRLeV6XULpuc$V z=s`VySlGiy>0h=!VKSC)$o||A)3E92GxMRKLP*yK}(flPVGp>#2{_4 zE43yT0!zbIK#tC%wJ~L+fEdsX;b4xsT8;%3gH=Jxks5NQ$k7z-r^%o|Ea<^J4l_9g z@{P!NCeR@Q*qJkYqOlI<%I_~u?|!=3d;JfnVEx>+{_F?ay-wO81`xSokTB4)(V8YshmLR;N5b*D}=d&qf zuE100If5s?OAr1ucfn^K3~m_wNS}J?s_H~d^H$n$&JPma-(r)4q_v*>j5-E-Z#uL< zrH|A7{-1vD^&*dmYK8gl1aKq&{rCUz{w~Y9;O3#9VpGEdCUGy2tUOuC8a;vh>iV)Q zMTej&1k?P1^KzrFM@3#!D#KY#+jevIdWIZANDVJ7Zm zo9ktoXxE0Qk)1ZC52#P^eeS?bGAH=Z!ymlNYwp+L;X)$$)34lf&Sl``-<`O#>=3#C zk3*l3`?dG7jCgio5fva3E3^7d?&FJHA3DFimB+uPcCuq|+Xit9l;dk%?LBhnzkdcI zcnOpawpu~RNVxMP`{oLhyZE$uezkjV!cL|>pWZ#s>)8{ag}sHVUwPthdx-Sq;@Iss z<`WBb^|KdvwvN%y(U=WUf794Dmj-LFPdmUAk2MDBqiu z!_yB>3)V-pg2fXe2jmu`(P@$rSyEmWqY+07OG@^%@WRMxz_3~7wd?{vMP5dGp3db? zomu825`8w~LVI)I=c^3ZE)1{ln{WnOQL)m&@G#{g>_(!#JIKq_>8VBd?XkQI{WHZ# z@pu$oXt9bzr-VU@d7KD(tUNljltVGJ7MY7frvPTTRfmb#r7P)n_+_hu7KO|2Wne)e z-By}BcsAi7#pR(0>3Y(xVqu4llVn2hO6~w}o^RTOe3#V&0EUV1$uObWZ(<@^pr8tH zJI)mh7ixCwuIbT6R3=5vUXV5zMg}M0&hSFHHgP;Slwfvx<<#HF4XKAE83L0U?KA|9 zbWr%Xod&JUaM?W#>a0no81Db@DV!Cj966~D<)~BU3OfqZ7+o5;;GP<$cWa30_J)mc z>U^P%>6f>@nfC15xqjEqog4W&etc)gXqI);o$F5o+qR774=-ljpsu)l{FlX()`=6v zTi^Ibsyks1e05|6r|{dJmCHnwZ$Bx1^JPsxTf*Vg_^J2dPUo>AQ@ztuW`>0f-vQ-^ z@pM<&#>xA38PC`|v46LwWJfLMWxUB3xn>q+;=;YZGkKUbW^R%iX5}?T*eB0Bzh}|R zYxM(#aMa7711ie9dupmfY##fMu;Lq;PvZ zc3hs%3!?=*9b zQ@dHz(?Drpx{Gd;@M_pKo2eN(DfLR$Nw+3?rPG^){ghoGI2v;mvhPTAD=g2>8P1{# ztR~vRwtM#v9ew79LJZl#y+d1{+26ZFJTr9fGe3Ru-uX1NWLO-aZu_7D2ihSxEtq*@ z2d}n=X;onF)(3~_i)7CSv%#M%u@Bx`eZYRM`n%Pf-c6D);a&Oi(N$lhmLZUs6NGD< zb3!G8rjDI$f!!|^=4bsPZ}r=b9XJZ_c_Id45pY8iHA{&*+MWZ(tc9(n1PsT~5-x9T z<8@W)^fY8sD+fF8EJ6}Q35Fuxy-9hRGn|FsMedYs8|q>O=MA#$V=8`)Y)-sk^ONUT z(dYH*TPQ*uHD>@6l4lm^UbLNxlO(9aRX}tt{b~$7i4u=8@bc zuE|+&Wypm$OvlauTWFP{O!d-$-kE6McGY{@ns?Bqqxbcsm1tV_#Oo*{Yw)6`&Ozv~ zQ4zla%l>NRcNJ~`HnyOm4qi~v=n}!}I)bC-0+xmmwA8(4!tW6EK{EZirW;>$-qqgP zh5fGkqw`u<(oNV(OV2HcT;td5*pgm#F;Vad@Vijee zG;bw*-f9ld9k^Xel#CBcf3t(^>Eh{X*LB?Mo_9_vNlJDl8tW}KttJ{%)CSl0J?SlL zz*Cv%m)Hf1(W-}{$sUcZrLe?V_<70UopGy23)yTnKt~l4`5jAV$!q8%`Po*DWsmks zcY)?qP*a0t<}*<0_>YH#iTX^#^?9`my?t>SF6!-VB6>hkOm3ny)UH?qS~f?QVXuS- z9S;j#k9mVBNf+mw#XF#A{6VGW0?c=F-8@yln9e4n=bHeAJ2NxDmpc2WP9}{EnoC=!7)CXSlo(gkjJh%x# zmOZn%3X%AQnjI?bQ}Im2WBc@3LWQe27|v7yS@E61Go=m{oY@~b5VPhmMowDA06|H*LiWs_F*;QIS#j({fZ6`ZqS?=T zBDnVhJom>I%#kbqxcJL~jk^YrlDYEAD=*UY!ikgKi-ltLC{wWw*VP(0y>`zDcR zVC30>8|waj4d)*jfK4m*Xm;Pe(H0KB^PTp~XJ+Vk!3cFr^W@>_6Otc1xFsEvbykZd%qq`F&E>S2;ZS-BJ@awC2d;*-Bsx?}IMIyP>h3S%pNjDyos#f6@v( zxV%S(_0cK1D0EPcYj8pu>>59CIlo9^+<`l1IEy;CZd6<}KHnODX!NI$gs=X|pRBv@ z_;JWV$H2x%yNAY##g|zOir*WqsygY6Jb%&}$YO27DgKgo_Of-9HBvr-XvK>2&TIMT zX!qlTfBkP{kEfmujvX7n+^T->j|_p*ZSHlbjN5a_;%aF4z)Na=Z(QXBMC_`@}Hsac5?}0{;v)J?J;a$=rE#kRn zhE~qkokT;@KGIzcl?fOJ@P}#&T6KVb-{xcIB5qed7d(rsa|N``96>9zpSGR8!0NBk zoJmOBB>tc(^qXmh8M+l>S+4qU*b!kyB!wbOMJ&}^MY@?NAjcu)BaZTnX|X|7f;b17 z`Ip*pG%2{RI%taemo0b)O7LWxJyFbWk=LK?il%-4hJ4o=w5H023CODR?~)W>`17-RWJ-)-Qh~BrvNI+B^rG5 z!%k-*A&fpZ$a*!j*FtL_Xrw>8Ub;#|Yp*DvYaC1!#^`E1mavuQ7p4E{c9^cL#fc|e zSe^A!v^bt$bR9EEe}i{Lsp&GRQ(o1=yJ(BXk2C4ZsJdxP#jW>mF2Gj$`otr1W2uaV zM`@0rASp`vJOFuo({MdVMl$6#q*5tMd3aB;9_f^X%qfA_9)YJFPoScBvyr>Y(H6Pg zr0}!HQq>IgKXKhszaRReR(PnTCA|iyRv`b{07$2Ki?76=`HxF@JnUta0FIJK&b=G* zj7_$D1Or#d!|n^%I$g@3b-Na#c342dJICH&9Ch@ruc-ynz8pVa8CXRBULrfaO>*q% zA!Cx$B_v&PPwS|VNva?-gAgPRe*$$t$pos;f`W54 zje0h?r6P8>MIe z?N+3n!0z3X#lQYHjZ>1sy}7`}Aw>h1&$TLM&pRXc&LxKrB-lomZZWpbvJT2|lP`hO zC_=ktXcH}`@mWNyn;JVQhG;%(x13gX1>y}|qqok5C*Yio1hO8QGnvrDD- zN5lQQ*tdJPV7%#P4nYUy{1D#q^MYY4JoAXT<#^6l(PKGs4#1P+xkC3<#XZHt{BAH6 z>*`hj2qzRRUfeOXzGGXt;NTooPvrw zQvBJYc|HE^pA7u=1(v!{K*y^_o*Eju^2)jL1*7GhQH}0q^iX8st)VX5*+)Yy@W#rT zlKu0$#yy9ghifM;v_vlKeyk+1jtVK3DjbF}RiRMV6=yTjoJBuWbWoOrX4C;X)GN9Eu!A;3ShjMJj>ZJo5fZYzRTBb~1VLE*5ZHd?D2^t<+Wz!IE zk!K{l7b@xsf!28_qRtX$Nf!mE#Se#v>FAQ9@1#NrF+@Mz-8$_sKWok^Aras2NRk>2 z>PRh39TaAB04Q;2&(hC_QyMfJA%sVH>F6wyAVV;VVJ97gC~LXeH*u&sziEX;C7JkH zG%x3x8${(B>Qc>L0c}@8r{qimyLGI>Plr9Rxl5&&1RiaIi*!6Hrbeiapgg1IFqf*k za5H?_7qkC{_e-f0vbbD46lv)Cpj_VksinP=>W6R614B|$Rs;WRp-P=8hhtSI+>dSB zp2o~mRa-r9V{4&btMKGLJ_ z_}T>>oqFkq&gDTQ%ww1BSu*-EaEb4dnM%H(G= zyqW*EWB4>eUaiq<=Y1M|A=2%X*|br~j}3O}3+-)-Z)>&xi+l6Up8{UVT4XQ7)5GUN zp9RcO^l--4@q&%z0F3OSAkuhU6f*vRpQmU~emC_!vheLazx@7Um=5{i8FX%(9-%jw zX+#gb6*^`VO9k`Rd_Yp$zMrc|W&paX{ex?$1+VG;I55I+$sx_ZJ=wSLU^{oHpF1jA z%Ii{Clwsh(fK@s+VM-`4l8i2gRSZA0zNH{y!fgf`8zaeO?Vvlllv*_&9M## zS-ZM>mm-{{7GUD_4Ns;ZfW9=35l5X0{g2516S_)4p8cA#J3xtv|-qJjW_9ogT zZ{U;dc+(kE7R+Ng3y{#GFu2N6DI7UF$QjXUM$GRg!f^ikDe5&V#fZHwlb2=B*}0Lk zL!S+M_O?8uFw8<07mze@Py`o zip%kwK4%bf#;n-JpY?YQ@Oz`LfBuneyhnH6s-a!`R_z)(eDSWKW9NPOzFiwfR*da?YHcMIHVTcFsA|4H2P}Vwyy-`QR%Tm_ESeJ-V1RaZBffgxkq=VhBnu&j5fw zcQ}hWl=tS&m3T=f1;0XKZ?C=8>GyFSuI34$(;Lm20&AkAS|vNI=!3I_>>2uIKt}Zj26lMl$IPt z3NC!E>Id5fxUvEP&I0TtR41^_#)w1|(Xd>=4q)m)3Xidu=Ui~ZLrys`N0@sZEHB!$ zlvI2{w^)!NYmxPhuk}!BX-}Vezq}y? z+o(yM*asc$!wYk+|ATe(lQD{GaOuSuK89Px_aiwS@Je#bn|An=Le7r zE9Q12I#s9TcKUtcl+(MT8$*xc!TN%p{s2+7 z>U6Ysckt^XavfJiyuRfxZjGxaBJZM)4N-R$9s2sm-mk8D z@^iG~!mGCJTas<)cj$typKSYdhxpr7WL?M)9r}jvfl&MD2K^`fN+INtCWS4&-phUN zhC&jZ*Inm*3Gw~&kvwNG%MeDXJX4kyzeW0ZE8W8~BNoRXCm35C*(0IMThKER3y>a0 z8v&!K>t5q6gKd-}g%j(89h4`yvO!{D4NvlCV3h-s&zX^vt0RduQcop`6#Qog{#?-0 z!15@E<=_cO@$ayFOr}*1k=Wl&bh+PxL!Nx;e89oSaNdIWcrJ(404!8&$kFHjiYHUG zBvbf+N=D{-e5^=hD21w+>f(@~OW5-muwDbeDOz|CdH6tkhW)@5;MVgIgAjqkWF&Kuoen@{7l&<5Kbl;A?DD;rQ)gB1y@fR~^(@P&C|~7Jn9u zvnilV+vM@ep;y%vpr%htkuhEckW9lo)2{-t(~yv-NqZHN^aPC`{br>9*_R84mVa*` z`8`;vcy51k;M#YucqfhiL$u>Yvx1*c<5G?z2yi5AUVX!Z3}E;9H}`SB_0^K1r0=7FoKCUdVP! zW1r-Q4SFN?(h3>+Iee;XioF#1r|6sbMhi|}oSAo0*~X@daM`w6;h~IEDH~*_!!(_+ zoIHJhZTP*G${9xGvy1Ru7VB>QM$5zD8NA^cM`Ym$YHI=8Q9m4B=9{ABJ-#9t>ZH^4 zQ6a<9jb1vLud=_)9J`aAtc^GC-uu1p{i^W8AO4j79pC*ajy!v{KZeiq5bvy=_^u~9 zdgQBL{r)3U&Mm^Jx_p+d`RNAj**Y`NY)|C-~Fs-U9u^uD;ZAX34gLnO~f-n%;|gtuA*7xlml zRdN=56NPnF*0qgm@=fCBF1D8z66&5ql*7lR+V6qUPD1-s($nGO%FE0lyFm3hbFY4|U zR;S({h4B;<7>z1(T8=A=ue{jKFv8GT@dM5-;j~Ms;3eI4KubfMLo)%dSS?Y`5JRMoG<~p3V+QS-7YLiaCrwM12`m0;U;0EKxRwB&jjHxSkw?$ z7SC45R=U$^*32UYSj-XeemP8{oU556VtE=05kpp!UBWu4h;$w?5=fI_;(2g?1@;Pm zyNLLl&Luw*Y5VV}Eoosd;ljYmn9}f$TQzpzNf5ZJXK?@R9vwOF+QFx=WpzUzeOo!A zjg;kAU5ZR#xc<(CZJYCP@K%GVu1jCIlw&X1w69LKHTOlV{JbluMa7rzb@blecepeh z|2I1S+4$-)5^t0$?%UsOqIBPyuDtu6wilnQ*^;co3kUDGCOxkp+eBXvh|K^;97yaP zI`DSLX&)`?i>1XuNOIIL?_uX5_*!Hhslx}`63)p(T3>L1=(5IZy?Jm`Eqw_AE5_A! z%W4E8u!lo6=|!h1!X{5d3B#h6WXY(+WJOuAPCPr!cE5w~5&;1wDUyh0Eg+&TPX`1q z?5UrvvXtA!n<=+icM!|9qAt(DH$`Ro4zkktwNTojwB~tyGWGV(XsaggNFb^{CKKm- z*Gh$+>;i4-rrAJy!cU6q!ZsWv-2UQ0+Tv9Ew|MwM23nH99KdhG?Jr+0B>3f2_oe2+ zw!?jH#J%xu@B^)>?-nOE=m&0-#@W}mJki()+4p-;@f!)EDYV?-1&W%go9aER zb)>23=L?-0)|tGIKRSP$KU~UOErPCW`&jjenyv;`8{pkjrloWIoWsBZil;RSms3Z;kJ*w7Z+B={v7n=cadm*7uiu%I(Zk^jGvw{`Hs! z<|hdKCP-=+DY^0aKv!C$SG({-EHr+oaENQYgT*a)9b)lTmI8+oK8#rck@XD;&|t+9 z0b+XK2>_BMkhui3I@#={@Cqr0VIjkWHmIo{b%_g`A;QU}T|IsMF^BrQxA(=UAMc!5 zJuw|(n!B3huXts;;zjAq04id|&`8ElHR*Ufj@|L^hm}8;uK5@qU)VCe%!0>g(8IO? z&+$L==YxLSzW{Gpe~Ug$kwN+v48MaQG?)R6Z!<~kWW7X^qj1zM`q9AWv3!gVfciOV zlyIGI;fNz1PviI{2f!eX({>%4yX*4#yM*t{L?8%IXdxm~z;unD;--gv*|eQ`fS1Zv zgO>rvjwbgO^WoGg6p80Mp`50?a!B9QKsLCJ#s9Tf7WT#=oAE zH2<8(YjIq(+kw?Yytf>aUOTkgrlmgKAN5@)y4K4WN}LTK&3*Qp3Y!PQ;>?aPYcxa# zoNLZ8DIKvhVN&|c#OX2RzG69^JIFHjtPGrr4j!3V@VP@~z$|z(aArpQF1f%I{>f6f zO$ClV9h@osbb0@yY4H~y!(*W6-$xGV|4}S9E^yYKc--0UT-tKwn;l0(@7%e0baWlP zIT|m%aPrY_7f<|T;KYg1pBN=z((R)koqUWb&)Di0OiC_}9Kihl&1Ns}Nh;zaFtCgM z=pUblE_z5`dE&&0ef#iL(pyIcUdewdeq!%1y^ zPSm&jtRV)vUITvF@D*qT`0*)StOJ(fY9#z7Jdtj6RMt~V7w21u53rYYP}XbNU%qOR z*t^R*De%f}rK~AsqKs)}mGRi-IvZebE$ff0TRs5yZs?o~O5t++-8HhuWG&k}Iq=d% zK72>js#y-56S^nzTa)uYFhQ3pdwdah_hed354Kj54`n0IB)cnUPse5a$qyob2Z+Dq z!r!RnFM@{O0}aFL*N3si5gN(<>$$$WHgs34xDuM@tq>pn z0x9pqv9vu(zu)2>v_~6*U$+dO6K6l^!_kQj^zSsPE z#h$udmn^zvRUJN%i-UIujvYJi*z?c7b)qALXR2au7)6Y(#}8$BaN=rqhw&AiG3M&Y z>GWBobKd(ymuZ<%1aTM=ZJ|wAiS3wbzz)jzaCsw8sR<D>1?$c5@C2LP5{UjV9uKD(cT4Y$mXj;>F4y1i&$Axn1CzE;$gineEQQ;P?}>uG zagogN+8`oO0?yA>EW71+i%7D6dVD#(?C$Drfj7LMa4NEJVMnf^iVw3OK)QQg_wM1X zlZQ~tu7?JRX1DDCxQgn{-Lb1|&Wo|hMzT199dq_k9;vFCN%jDi;H}XojUSOhW3e3Z z3L~V^8SChqV%F_Jv|OpN&Oj;RH_rpfZ9?Db%2#a0EHC*%+mX`3do&4SzmgqTQyb04D@Ho($t<|RRCw3%4(vofwK?c(>Q{l)MAsR zpf;l0m`65_;2kE+@4$?})SYbYZio(a(X~IaER=SU_~7=!Me{5-y*Byq`SC>Z$8Wv5 z%GM-O^BVlsSJ$-{R+4C4hz7yu_hx}^DX!T^g-$x|xrtu9w;4og5;fRkD|za8+ZOM@ zwF;TthUV%X8p_owh32n1aB;Z9+4QGa4!UWy)pA=aa)N{^m6L>;=Q)8f$Pv^xU5!r@ z1`&(`wIU-9HrdTjq_BnpePl?|*A67yF~@olwbp678AhapC9B+T^}Jngar4@7BVWf^ zJey0Tr#WsHI>`4t(dpsrOiC`yK~-oKIV)NZ-Jlci5=Zfp>(xud)%tvXLX^dQi}rOt zt9Z>ZM{5yEHRI5ns!k+93W$1o(cnq~0U<3d2o6Mo!J?}|r_V`Vgt>1YX7f1N*pIp` zjr9waSh+AuB2Du4uQth~Z)tSwesp>${auE{^xG!rpia%_yba#Xu}yR!mOd{~RF#El z@RYvX?f0l2Iquc88H&Qgf3D*nS|GINY|o)x1@HV%8-fmP0Em<6R7Ao~q5%?WtR>mp_0bDt8ew-f_AJ~A3(hZJRdJkpSErFaBH1ePEy3rT$# zK;U}UgDddwBqaKyg`1zD4^a>U>mrB*F@}Qu)S>IyirQ&%U`-Zk9O7y$rK4TE%M^>f z7?T*8ynfDw2Vdj2M)_Wg$S!2I0$=RxWiZ+T*yU z?cji+4vnT+arT^~>&GNUa~EXHVBC(+1977vhm;0;&Nt?23g9_8Ey&ZRPEX`I%my=x zoek-CjuVr~OYu9?2{YPNmSo)_yl>pN zd1tuy_R+zyJl^OVFOFskc$4%be~n{cY}7j8KbmD-bKkyW$M)@8wU2G0>(+(u64uob zEMm}H*)Fz%-!PoKg?B<8C+v~1NkRwYtE_{Xrke<*wQ=WW7M{QK={|HXAjgyXqm8+-Wt*h?;%ar zYWZ#C_kDHZZzo{a#_*5**ca~CFJ86pty|V_>@fd)>)6OD@uDNhKQJ;@>4ZsjVEv7C zETdDxtxJUV$+w@vju?-HcFLFsJPh6RS*eVh!*mE^7t?{;B1Xb6;rGSppp47uIpjA3 zf<(D8WNGr47sj0VK4}PJ{#h3-yJb6NXcwJHYU@JSNij!dJZ7agq0Jb@W3ST--IM9D z?%7{*!}yhDU3V+N&Z%*hk%L)8GX#_QNBRFDz(YH&!+7b+^YNSRaG`P33h)0n-6K#swbbQva46M9JTYb3f8Rx zbu*9n?hC(1I&^gCsb)z*_tBvtj<*hqRcH|W77J4S@=lBDtLhc9R3VP2OF9D6b!E6P zG2yNBJV?^WYzd(>*mSr-9ZNVuS{m%7tN^VmIfqtoF>S+U)&%xYrfkvyVP2&XYbwZd z1L@d~gvw#VK5BXiUkb$xQh^u*jVJM%X?a;02!#$%{QVRQ*&Hb)5)|e6WAz#hMxH{@ z0H)|96}|v6X@Mh5nYepNfq-S~qTEjS9^fNXCrR|);?rGgEU(qd-98Vdg4;WsPyY=t z6&iqF&BOa;vd+-SAUi;K8Qk~R^^%=)EfU)|LA#-ruhpUon6BM}>8+=hf1|gTmh>UN zb2rI(Yi_CTjXHLYtcBUw@nd!I?%j7@;T`M81dD1f%s8xZEugj4kxj_VJvl2l2YYr< z{xWwj>}2Q&_wXU%(pRj8svM+!WusfDR#d(1f}8T^k&R zHFe?kA+yS3zYFryKq9Cn*IvAKiGDpDhoP={YrI`-Yx;*31A0f^S^TEuOT0||!KDeI zi4HqA(B^GxtOo<-nK?6wP5LWPeN*IS9!EPXko)=tT+noIA^i;6y-wo;kC<}{k&pTk z6@Y@;)e@s#2|F50#@MNojlW(!7Yk^-Hp11X)5}%c_DfVxh&V zI>)KPcPD`ohb*QchXIeQNG5~%_wOW5c}^(`5DTi*U)U;Rr3?esK1GJ2jI(YNJlWDwAwP=xN@!DU^USm z4I(xj!#$ZceT$I@5W&%;hl#l z$LW*twI8XvdJ|sIbnp7gch2!TKMgI^OMgS-wK*)r2)!^OZCyY^;GMd-mxmo&V)17J zxamTOXfV&shb@ldWYwz0 zdN4`Rg34z0o-5oj%5GS$sg1s<)7E;AQY$0fc+YlI0dnM^B%HZ}`vh>ACM2+#-)p7* zp8i&x8YWGgg`ovYLiZ=uuzu6piZ;j2ZGK#Kv>M?@LveP=t2SsHVRe($0DGrpwOFXV z<*bIzx80P$rAUjE#$&EvnIuKj)@8YCUB~gdJx3FE)u?250*Y*37aAI|SSo3961g?_ zVN_W6xSu2uwcu%##)kkP5<21C2U}^nA%hUk5vs{pgK;d1#Zw&}o*T`iIrc4se?=0R zzU1Y&E@kkl$h`s)8Yp;iHJ6I28nnDmg9^NCpq+o2&Jk$iRsx5jgQyeKQF4$ocQH=0 zt<50uTk_9w|BGnVf;dz^nTEOh!bcRB{a3Ozmmxp$p2u#vDFqw=|LBtyI`HXFKqCjy zHWpY;VsI#vh129nR<0!mZQx6Y4Yjp$I$ql~uX^T7{pQ}{E5vgCR+vyVhI}{fw3!Hw zr#95uzXczgX=@_VEUdu6W6^;z20lo+q%kIwF}X2} zb07pmz8sj7i#5$jd1uLAPOeaMr*wHG`jj5i#HUQ1oDe?K=0TYpeP(}UFqqU7lXK0i z7FInbx7%dov+;9(Oa(g(&M2|M;spAXs3`$R$eH0(I5UbakvbK=Jatj2)QJ;A9b+A1 zbwBMp5x@qT{q-+4?|c~haX0TA>fkV6{8s3%e^Dq77xQ2H?Yexhw^*P*`Dn{UPlx)$ zG>vqYAkLM!m7`DcmpIHmOq_-qo{h@;H*qG-$l}E>2czBl_FcSXtd93*mY}3xl=X~> zns^m&sC#lpo%u3)V?|$O{O~+n)-@|SDfHBGxa>}*ecr{Nyze&`fAWDT*V0cy;3mq4 z{<@&7%Ptqoq3?y)!(zG7^$hdVWVxho0@vu96L^)HPW7k7kF49zMQj{pOwc9uQ()%ooQ`o-B?QM?-sOdF^8T`VoA=CET66YZto+k6;bs zhv7B4X4%CviLmMEFg~fVHy5c%%|8?D z+9o_LA5zLtW)J0bB99K^WjQ%?C(9D^(>yhKwh(9Gsxto$@GD_NI=!TLn1&ms_tMHz zSoJymk_3O#1uppCim=n0JXlI!Rd&l|mgt%M#9xV8L4niDpnhhF}O)1rI1oBP1Fh8F94HgFz7a8==YQ8r6UqKbo(< zA9*a)K?@~8AuJT`6mVYB;QX0IA19d*H}^Hs(Z{Z%|Mzd-(EwG(qqUz(^FFooL%n@+ zHMRd$*XKXB`)S~B!;h z{NX+*aRWLxch&byZSFZW54Yx>Rkl0+Q<(p7!u)Vs+~D|x4E#RSy-W2+Z6 zyNQDNu5@$*3K5NWNMigH4e=YvUCg6J9mQ3N3}%@TRAHX&Ouv-dPk*b(O=(d`lB{CAUN@F(56k6rto z7*)$B$Et&GhXct;TTPNrti%nDTNExQ< zMv^hwuoCC86=KWyyxs|zsLxAo%+J@oNB!h#HJIvm6*BMLfU{$tx*a=ZU}fTF^8Tya zBQH&~S0DO-r)r|fA0PU^R7+GZZ~RJz({I?|ARx-c<#3xa@l zq8r$C3tVRdcnSb7-(><8-X&0IhJ~9@kuhuzwgVI2hPx6F#yr}<(zH-~WvNLBZy4oE zpxI?P#vwcglF&FE{0j9z)57OJ!c;e@*%!s-L>pa?2eQT{+#P8&3d<4}Hf9KnSEi{n z5ETo@B!IAiEQ6J>N(MT(0!R=O$P}wX&}aFS-Ubdj32$x8GT-B5K|Lk-IZi5-3|};d zR=c0#`|!(v4YF|@Fof8Yla7G5L3p7lw&L?8@Uh&>I6Ra}$3Jg8Bqcc-XgNydfX*2h zB7>kJ**BQ}|J%F1*f@?d{_T0~o}Ke$?HuVnMAg_xXv9?k6(VR) zs1FE)bPtF|MbL3ts3}2Mf;WV4LSCAusNw-Zq?}2BAS%cU5>LcYD;^M{=~GZuas0lS zow?n+z4M)8=hkqay*J-{-^}bc-_HJ-`M#Oq-^r zK~2bSqZ~=qCq8D&(+RAC;6$(l!pk@cpsAb@lywPR^S}Ue_$PE&s~s}iyeQa77nNd` z&cmn2p>qPYVB@$7tO1Myz>*9EFBrb&VDt1-4nfVY`c&2h+w96BIz$883DENHL_x_i z`YRUtj)92bz0vm4+vB}+_shk7F))a}b3o=+Q_@%5WQ`O1E-cdtJ-!`c&>oMm210kL zoPJK)-WJ;9{gjcGW~a(YD|4zXAXZDq~C*j(2oX*J}2=XSHlw|NRorm z!^5d!gxsYDcB?JzR=Ias-OOg6Xp?NG^k+I*ZG~??n*4Hi9iKi6#P~r+y>yQ#k-w9Y zU?(DLi5McbzL$6!J_cdhA&{D4JDSCS#{(j$*MZm?vVGG44;2uto4z1_ysxioitY&4 zF-E`Mc^aJnKlL?>VOd^Axo_MFN@=I&6hLRI2#yZg7ff79Bgw>2wjN3%;Twt zgX^{smphK9h}6+gQqsgpgQkz??TMGjU*!b21}{^2f^K2-rWOfbqq()}azp25(z3?% zPfl9gA(k*$*j6rQjz*~lC`Y-p0co5|jX>!zz;DEh=z5gN@f>j*NUL0oQJM!`yp(3M z(O~28=IuY(=VF{aRQ%-0YL(ZqWl)hMc_8g?QXa&^C^eeN>7mM-c5y z_}czoe^zfO>x5cySPQ}P%)1BgmevXT!~Q^+#72_>uWeAu%`B)zw+G2W|(wSFDnj4)>Q1fg&D*dxDZ>U+k7 z^mvr&mebZs_+=CUbIPp$GKJ-F*lIHd4SpKI@0Jcu!WGtn)X!HN!#=Wj@##v1Y=g=g zY{Div_JN|rJWX7X&Q}}c^+-O&V&iJ5DkE8g)pw@zR0__)U@l>KPZO`?{e1?jvVk@8 zn@gLhX~rOToxd`*Ij~x(vr9uK1bWXO7$Loh(vb`P{hcX>OleR7d-Lf2Q|G`aE(?3W zz#JRS0cT{$;-;ToaQo5stAMnrAS3GZ)HIz)O)+$04I0M4ff=kwJpBu7K86t>atgNLom|*SaLiA{njR0(|9`EZz#e0P}2(pDOnr z9)4qSvBk^=_U`q6{I&TXxV3s0U*o<+hg7&f;D?NU+!4$<)gf;GtU(BY%)$Lp2eEq_ z{ZRIM&TL=Q%52v{w()q#D?XY2sPTY~^Rj@$p*r7uubKbzv(4tytLIe~WZJF_UPDMU zAFea^@*WT~sK?gMfv1f3Co{5NzJYdV^ zanvLg9=XA8g~w;i+%5Uj)I>uhK5^i0D)+u0KaN=hUO4{gR7s?`FDzk&@~_{JaPmg4bSexZc6I_tw16f2AW&IoscNC?oMuPLz9f-4 zl_V4Pl_fKY@YvTNqF)p0$e#JJbx0E!-B1k|k2U{|d65l{96OfM*VCzn_rv|qf6>F3 zm1$=FvLsj}LJuC>7cv%-0M*>eW}Tg_C+~-JzB@f z^0E-l!ZBnYW;k(Qw5>ntzA4P=!@R=NDM0qdHLf&$YQ9Kfv-#r9tKW*XbrsVvKWw81 zu5Dj2ZWd6*ZdXr|Xb|SiT7eR>MlWtn%V1{+bG-!GKD|mSB3=hu7ZbJD=rtKnhh!_aAv_y~E4sJFGKKYX8Y{p;HEs0C#_lx}4kIekRYCKIwq{og? z6?|D2ayRA=BVQSe;Y{sXBgM-@%{byTIvrRzO&fn~uPR;tmiK zT6~UV10=+Nm{sSyL}@FQ z`NTjSn4+s-k z|L}pu)9<`#gR>uXXp#}dI`~@@@7VjFZ$5vsNn>~Jy#03bO7o6mBoI4dV8aBn&xj)I z($E98;&;z#Y@t@R#K?xrg!P2=J~*(6vafCi{fwQcZAjqayo#`0nV5Zb9V0^smesy< zv)O$2$`y9}-evHyXJs$&>9Jnyfp|P#xx=7*6gVfk${6ua?C@!AaSg>*(e>ROH5P7E zy48-Y09%Bt@pHyfIPQ!OZF#%`?~;h&77m57LlK*3~rREHCXU`v2bi}3LT zp2RiR=56xA78}mjWTvAihtlN{y!^=tknkq05B3#5^}6 zW!k)mWtd?c1bq_-r5hR7sekw~XUE=AC2v{S#aP>N=QcJ}P`i%~9la)J)Z@n1-j=3E zw76`TISB(3oKTB(z51%lk*^z6r$a@G0b$olT_cyKH!^33l7!=>k`yfQ)iwZ$*!ZOd<6nb-2OWaWA_;vn917;xzKW}j?SZhT9F{cq zv7at4SX}V(1)pXYP>%wpm16c8Ly>W)u`4wS{fY$j5)KV8Jx;Sqr>Mx^P+x?+Ys`o|VC$11_Q(aRg@*LZ!egzOFLd6-k5<0+8V1>v4J0UFiyrb9u_hPvR1I~_xk+|` zTo-yoZn3eCRPUsYo0hI~8g%r0bGhyXk|r6>Yp?JYBJeWa+koxlG8cW2ll81aPv#(J q`QJ+W!cRhM41qdLMd6r0WUn7lUB*LN*G&(P287Q(9nq)T>-S%HmZ13n literal 0 HcmV?d00001 diff --git a/fpga/fpga_icopyx_hf.v b/fpga/fpga_icopyx_hf.v new file mode 100644 index 0000000000..b7730875da --- /dev/null +++ b/fpga/fpga_icopyx_hf.v @@ -0,0 +1,227 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// +// The FPGA is responsible for interfacing between the A/D, the coil drivers, +// and the ARM. In the low-frequency modes it passes the data straight +// through, so that the ARM gets raw A/D samples over the SSP. In the high- +// frequency modes, the FPGA might perform some demodulation first, to +// reduce the amount of data that we must send to the ARM. +//----------------------------------------------------------------------------- +//`include "define.v" + +//`include "hi_reader.v" +//`include "hi_simulate.v" +//`include "hi_iso14443a.v" +//`include "hi_flite.v" +//`include "hi_sniffer.v" +//`include "hi_get_trace.v" + +module fpga_hf( + input spck, + output miso, + input mosi, + input ncs, + input pck0, + input ck_1356meg, + input ck_1356megb, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4, + input [7:0] adc_d, + output adc_clk, + output adc_noe, + output ssp_frame, + output ssp_din, + input ssp_dout, + output ssp_clk, + input cross_hi, + input cross_lo, + output debug +); + +//----------------------------------------------------------------------------- +// The SPI receiver. This sets up the configuration word, which the rest of +// the logic looks at to determine how to connect the A/D and the coil +// drivers (i.e., which section gets it). Also assign some symbolic names +// to the configuration bits, for use below. +//----------------------------------------------------------------------------- + +// Receive 16bits of data from ARM here. +reg [15:0] shift_reg; +always @(posedge spck) if (~ncs) shift_reg <= {shift_reg[14:0], mosi}; + +reg [8:0] conf_word; +reg trace_enable; + +// select module (outputs) based on major mode +wire [2:0] major_mode = conf_word[8:6]; +// parameter to be passed to modules +wire [3:0] minor_mode = conf_word[3:0]; + +// configuring the HF reader +wire [1:0] subcarrier_frequency = conf_word[5:4]; + +// We switch modes between transmitting to the 13.56 MHz tag and receiving +// from it, which means that we must make sure that we can do so without +// glitching, or else we will glitch the transmitted carrier. +always @(posedge ncs) +begin + // 4 bit command + case (shift_reg[15:12]) + `FPGA_CMD_SET_CONFREG: conf_word <= shift_reg[8:0]; + `FPGA_CMD_TRACE_ENABLE: trace_enable <= shift_reg[0]; + endcase +end + +//----------------------------------------------------------------------------- +// And then we instantiate the modules corresponding to each of the FPGA's +// major modes, and use muxes to connect the outputs of the active mode to +// the output pins. +//----------------------------------------------------------------------------- + +// 0 - HF reader +hi_reader hr( + .ck_1356meg (ck_1356megb), + .pwr_lo (hr_pwr_lo), + .pwr_hi (hr_pwr_hi), + .pwr_oe1 (hr_pwr_oe1), + .pwr_oe2 (hr_pwr_oe2), + .pwr_oe3 (hr_pwr_oe3), + .pwr_oe4 (hr_pwr_oe4), + .adc_d (adc_d), + .adc_clk (hr_adc_clk), + .ssp_frame (hr_ssp_frame), + .ssp_din (hr_ssp_din), + .ssp_dout (ssp_dout), + .ssp_clk (hr_ssp_clk), + .debug (hr_debug), + .subcarrier_frequency (subcarrier_frequency), + .minor_mode (minor_mode) +); + +// 1 - HF simulated tag +hi_simulate hs( + .ck_1356meg (ck_1356meg), + .pwr_lo (hs_pwr_lo), + .pwr_hi (hs_pwr_hi), + .pwr_oe1 (hs_pwr_oe1), + .pwr_oe2 (hs_pwr_oe2), + .pwr_oe3 (hs_pwr_oe3), + .pwr_oe4 (hs_pwr_oe4), + .adc_d (adc_d), + .adc_clk (hs_adc_clk), + .ssp_frame (hs_ssp_frame), + .ssp_din (hs_ssp_din), + .ssp_dout (ssp_dout), + .ssp_clk (hs_ssp_clk), + .debug (hs_debug), + .mod_type (minor_mode) +); + +// 2 - HF ISO14443-A +hi_iso14443a hisn( + .ck_1356meg (ck_1356meg), + .pwr_lo (hisn_pwr_lo), + .pwr_hi (hisn_pwr_hi), + .pwr_oe1 (hisn_pwr_oe1), + .pwr_oe2 (hisn_pwr_oe2), + .pwr_oe3 (hisn_pwr_oe3), + .pwr_oe4 (hisn_pwr_oe4), + .adc_d (adc_d), + .adc_clk (hisn_adc_clk), + .ssp_frame (hisn_ssp_frame), + .ssp_din (hisn_ssp_din), + .ssp_dout (ssp_dout), + .ssp_clk (hisn_ssp_clk), + .debug (hisn_debug), + .mod_type (minor_mode) +); + +// 3 - HF sniff +hi_sniffer he( + .ck_1356meg (ck_1356megb), + .pwr_lo (he_pwr_lo), + .pwr_hi (he_pwr_hi), + .pwr_oe1 (he_pwr_oe1), + .pwr_oe2 (he_pwr_oe2), + .pwr_oe3 (he_pwr_oe3), + .pwr_oe4 (he_pwr_oe4), + .adc_d (adc_d), + .adc_clk (he_adc_clk), + .ssp_frame (he_ssp_frame), + .ssp_din (he_ssp_din), + .ssp_clk (he_ssp_clk) +); + +// 4 - HF ISO18092 FeliCa +hi_flite hfl( + .ck_1356meg (ck_1356megb), + .pwr_lo (hfl_pwr_lo), + .pwr_hi (hfl_pwr_hi), + .pwr_oe1 (hfl_pwr_oe1), + .pwr_oe2 (hfl_pwr_oe2), + .pwr_oe3 (hfl_pwr_oe3), + .pwr_oe4 (hfl_pwr_oe4), + .adc_d (adc_d), + .adc_clk (hfl_adc_clk), + .ssp_frame (hfl_ssp_frame), + .ssp_din (hfl_ssp_din), + .ssp_dout (ssp_dout), + .ssp_clk (hfl_ssp_clk), + .debug (hfl_debug), + .mod_type (minor_mode) +); + +// 5 - HF get trace +hi_get_trace gt( + .ck_1356megb (ck_1356megb), + .adc_d (adc_d), + .trace_enable (trace_enable), + .major_mode (major_mode), + .ssp_frame (gt_ssp_frame), + .ssp_din (gt_ssp_din), + .ssp_clk (gt_ssp_clk) +); + +// Major modes: +// x0 = HF reader +// x1 = HF simulated tag +// x2 = HF ISO14443-A +// x3 = HF sniff +// x4 = HF ISO18092 FeliCa +// x5 = HF get trace +// x6 = unused +// x7 = FPGA_MAJOR_MODE_OFF + +mux8 mux_ssp_clk (.sel(major_mode), .y(ssp_clk ), .x0(hr_ssp_clk ), .x1(hs_ssp_clk ), .x2(hisn_ssp_clk ), .x3(he_ssp_clk ), .x4(hfl_ssp_clk ), .x5(gt_ssp_clk ), .x6(1'b0), .x7(1'b0) ); +mux8 mux_ssp_din (.sel(major_mode), .y(ssp_din ), .x0(hr_ssp_din ), .x1(hs_ssp_din ), .x2(hisn_ssp_din ), .x3(he_ssp_din ), .x4(hfl_ssp_din ), .x5(gt_ssp_din ), .x6(1'b0), .x7(1'b0) ); +mux8 mux_ssp_frame (.sel(major_mode), .y(ssp_frame), .x0(hr_ssp_frame ), .x1(hs_ssp_frame), .x2(hisn_ssp_frame), .x3(he_ssp_frame), .x4(hfl_ssp_frame), .x5(gt_ssp_frame), .x6(1'b0), .x7(1'b0) ); +mux8 mux_pwr_oe1 (.sel(major_mode), .y(pwr_oe1 ), .x0(hr_pwr_oe1 ), .x1(hs_pwr_oe1 ), .x2(hisn_pwr_oe1 ), .x3(he_pwr_oe1 ), .x4(hfl_pwr_oe1 ), .x5(1'b0 ), .x6(1'b0), .x7(1'b0) ); +mux8 mux_pwr_oe2 (.sel(major_mode), .y(pwr_oe2 ), .x0(hr_pwr_oe2 ), .x1(hs_pwr_oe2 ), .x2(hisn_pwr_oe2 ), .x3(he_pwr_oe2 ), .x4(hfl_pwr_oe2 ), .x5(1'b0 ), .x6(1'b0), .x7(1'b0) ); +mux8 mux_pwr_oe3 (.sel(major_mode), .y(pwr_oe3 ), .x0(hr_pwr_oe3 ), .x1(hs_pwr_oe3 ), .x2(hisn_pwr_oe3 ), .x3(he_pwr_oe3 ), .x4(hfl_pwr_oe3 ), .x5(1'b0 ), .x6(1'b0), .x7(1'b0) ); +mux8 mux_pwr_oe4 (.sel(major_mode), .y(pwr_oe4 ), .x0(hr_pwr_oe4 ), .x1(hs_pwr_oe4 ), .x2(hisn_pwr_oe4 ), .x3(he_pwr_oe4 ), .x4(hfl_pwr_oe4 ), .x5(1'b0 ), .x6(1'b0), .x7(1'b0) ); +mux8 mux_pwr_lo (.sel(major_mode), .y(pwr_lo ), .x0(hr_pwr_lo ), .x1(hs_pwr_lo ), .x2(hisn_pwr_lo ), .x3(he_pwr_lo ), .x4(hfl_pwr_lo ), .x5(1'b0 ), .x6(1'b0), .x7(1'b0) ); +mux8 mux_pwr_hi (.sel(major_mode), .y(pwr_hi ), .x0(hr_pwr_hi ), .x1(hs_pwr_hi ), .x2(hisn_pwr_hi ), .x3(he_pwr_hi ), .x4(hfl_pwr_hi ), .x5(1'b0 ), .x6(1'b0), .x7(1'b0) ); +mux8 mux_adc_clk (.sel(major_mode), .y(adc_clk ), .x0(hr_adc_clk ), .x1(hs_adc_clk ), .x2(hisn_adc_clk ), .x3(he_adc_clk ), .x4(hfl_adc_clk ), .x5(1'b0 ), .x6(1'b0), .x7(1'b0) ); +mux8 mux_dbg (.sel(major_mode), .y(debug ), .x0(hr_debug ), .x1(hs_debug ), .x2(hisn_debug ), .x3(he_debug ), .x4(hfl_debug ), .x5(1'b0 ), .x6(1'b0), .x7(1'b0) ); + +// In all modes, let the ADC's outputs be enabled. +assign adc_noe = 1'b0; + +endmodule diff --git a/fpga-xc3s100e/fpga_lf.bit b/fpga/fpga_icopyx_hf_15.bit similarity index 100% rename from fpga-xc3s100e/fpga_lf.bit rename to fpga/fpga_icopyx_hf_15.bit diff --git a/fpga/fpga_icopyx_lf.bit b/fpga/fpga_icopyx_lf.bit new file mode 100644 index 0000000000..e69de29bb2 diff --git a/fpga/fpga_icopyx_lf.v b/fpga/fpga_icopyx_lf.v new file mode 100644 index 0000000000..0ca4739b75 --- /dev/null +++ b/fpga/fpga_icopyx_lf.v @@ -0,0 +1,218 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// +// The FPGA is responsible for interfacing between the A/D, the coil drivers, +// and the ARM. In the low-frequency modes it passes the data straight +// through, so that the ARM gets raw A/D samples over the SSP. In the high- +// frequency modes, the FPGA might perform some demodulation first, to +// reduce the amount of data that we must send to the ARM. +//----------------------------------------------------------------------------- +//`include "define.v" + +//`include "lo_read.v" +//`include "lo_passthru.v" +//`include "lo_edge_detect.v" +//`include "lo_adc.v" +//`include "clk_divider.v" + +module fpga_lf( + input spck, + output miso, + input mosi, + input ncs, + input pck0, + input ck_1356meg, + input ck_1356megb, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4, + input [7:0] adc_d, + output adc_clk, + output adc_noe, + output ssp_frame, + output ssp_din, + input ssp_dout, + output ssp_clk, + input cross_hi, + input cross_lo, + output debug, + output PWR_LO_EN +); + +//----------------------------------------------------------------------------- +// The SPI receiver. This sets up the configuration word, which the rest of +// the logic looks at to determine how to connect the A/D and the coil +// drivers (i.e., which section gets it). Also assign some symbolic names +// to the configuration bits, for use below. +//----------------------------------------------------------------------------- + +// Receive 16bits of data from ARM here. +reg [15:0] shift_reg; +always @(posedge spck) if (~ncs) shift_reg <= {shift_reg[14:0], mosi}; + +reg [11:0] conf_word; + +// select module (outputs) based on major mode +wire [2:0] major_mode = conf_word[8:6]; +// parameter to be passed to modules +wire lf_field = conf_word[0]; +wire lf_ed_toggle_mode = conf_word[1]; +reg [7:0] lf_ed_threshold; + +wire [7:0] pck_cnt; +wire pck_divclk; +reg [7:0] divisor; +clk_divider div_clk(pck0, divisor, pck_cnt, pck_divclk); + +// We switch modes between transmitting to the 13.56 MHz tag and receiving +// from it, which means that we must make sure that we can do so without +// glitching, or else we will glitch the transmitted carrier. +always @(posedge ncs) +begin + // 4 bit command + case (shift_reg[15:12]) + `FPGA_CMD_SET_CONFREG: + begin + // 12 bit data + conf_word <= shift_reg[11:0]; + if (shift_reg[8:6] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT) + begin + lf_ed_threshold <= 127; // default threshold + end + end + + `FPGA_CMD_SET_DIVISOR: + divisor <= shift_reg[7:0]; // 8bits + + `FPGA_CMD_SET_EDGE_DETECT_THRESHOLD: + lf_ed_threshold <= shift_reg[7:0]; // 8 bits + endcase +end + +//----------------------------------------------------------------------------- +// And then we instantiate the modules corresponding to each of the FPGA's +// major modes, and use muxes to connect the outputs of the active mode to +// the output pins. +//----------------------------------------------------------------------------- + +// 0 -- LF reader (generic) +lo_read lr( + .pck0 (pck0), + .pck_cnt (pck_cnt), + .pck_divclk (pck_divclk), + .pwr_lo (lr_pwr_lo), + .pwr_hi (lr_pwr_hi), + .pwr_oe1 (lr_pwr_oe1), + .pwr_oe2 (lr_pwr_oe2), + .pwr_oe3 (lr_pwr_oe3), + .pwr_oe4 (lr_pwr_oe4), + .adc_d (adc_d), + .adc_clk (lr_adc_clk), + .ssp_frame (lr_ssp_frame), + .ssp_din (lr_ssp_din), + .ssp_clk (lr_ssp_clk), + .debug (lr_debug), + .lf_field (lf_field) +); + +// 1 -- LF edge detect (generic) +lo_edge_detect le( + .pck0 (pck0), + .pck_divclk (pck_divclk), + .pwr_lo (le_pwr_lo), + .pwr_hi (le_pwr_hi), + .pwr_oe1 (le_pwr_oe1), + .pwr_oe2 (le_pwr_oe2), + .pwr_oe3 (le_pwr_oe3), + .pwr_oe4 (le_pwr_oe4), + .adc_d (adc_d), + .adc_clk (le_adc_clk), + .ssp_frame (le_ssp_frame), + .ssp_dout (ssp_dout), + .ssp_clk (le_ssp_clk), + .cross_lo (cross_lo), + .debug (le_debug), + .lf_field (lf_field), + .lf_ed_toggle_mode (lf_ed_toggle_mode), + .lf_ed_threshold (lf_ed_threshold) +); + +// 2 -- LF passthrough +lo_passthru lp( + .pck_divclk (pck_divclk), + .pwr_lo (lp_pwr_lo), + .pwr_hi (lp_pwr_hi), + .pwr_oe1 (lp_pwr_oe1), + .pwr_oe2 (lp_pwr_oe2), + .pwr_oe3 (lp_pwr_oe3), + .pwr_oe4 (lp_pwr_oe4), + .adc_clk (lp_adc_clk), + .ssp_din (lp_ssp_din), + .ssp_dout (ssp_dout), + .cross_lo (cross_lo), + .debug (lp_debug) +); + +// 3 -- LF ADC (read/write) +lo_adc la( + .pck0 (pck0), + .pwr_lo (la_pwr_lo ), + .pwr_hi (la_pwr_hi ), + .pwr_oe1 (la_pwr_oe1), + .pwr_oe2 (la_pwr_oe2), + .pwr_oe3 (la_pwr_oe3), + .pwr_oe4 (la_pwr_oe4), + .adc_d (adc_d), + .adc_clk (la_adc_clk), + .ssp_frame (la_ssp_frame), + .ssp_din (la_ssp_din), + .ssp_dout (ssp_dout), + .ssp_clk (la_ssp_clk), + .debug (la_debug), + .divisor (divisor), + .lf_field (lf_field) +); + +// Major modes: +// x0 = LF reader (generic) +// x1 = LF edge detect (generic) +// x2 = LF passthrough +// x3 = LF ADC (read/write) +// x4 = SPARE +// x5 = SPARE +// x6 = SPARE +// x7 = FPGA_MAJOR_MODE_OFF + +mux8 mux_ssp_clk (.sel(major_mode), .y(ssp_clk ), .x0(lr_ssp_clk ), .x1(le_ssp_clk ), .x2(1'b0 ), .x3(la_ssp_clk ), .x4(1'b0), .x5(1'b0), .x6(1'b0), .x7(1'b0) ); +mux8 mux_ssp_din (.sel(major_mode), .y(ssp_din ), .x0(lr_ssp_din ), .x1(1'b0 ), .x2(lp_ssp_din), .x3(la_ssp_din ), .x4(1'b0), .x5(1'b0), .x6(1'b0), .x7(1'b0) ); +mux8 mux_ssp_frame (.sel(major_mode), .y(ssp_frame), .x0(lr_ssp_frame), .x1(le_ssp_frame), .x2(1'b0 ), .x3(la_ssp_frame), .x4(1'b0), .x5(1'b0), .x6(1'b0), .x7(1'b0) ); +mux8 mux_pwr_oe1 (.sel(major_mode), .y(pwr_oe1 ), .x0(lr_pwr_oe1 ), .x1(le_pwr_oe1 ), .x2(lp_pwr_oe1), .x3(la_pwr_oe1 ), .x4(1'b0), .x5(1'b0), .x6(1'b0), .x7(1'b0) ); +mux8 mux_pwr_oe2 (.sel(major_mode), .y(pwr_oe2 ), .x0(lr_pwr_oe2 ), .x1(le_pwr_oe2 ), .x2(lp_pwr_oe2), .x3(la_pwr_oe2 ), .x4(1'b0), .x5(1'b0), .x6(1'b0), .x7(1'b0) ); +mux8 mux_pwr_oe3 (.sel(major_mode), .y(pwr_oe3 ), .x0(lr_pwr_oe3 ), .x1(le_pwr_oe3 ), .x2(lp_pwr_oe3), .x3(la_pwr_oe3 ), .x4(1'b0), .x5(1'b0), .x6(1'b0), .x7(1'b0) ); +mux8 mux_pwr_oe4 (.sel(major_mode), .y(pwr_oe4 ), .x0(lr_pwr_oe4 ), .x1(le_pwr_oe4 ), .x2(lp_pwr_oe4), .x3(la_pwr_oe4 ), .x4(1'b0), .x5(1'b0), .x6(1'b0), .x7(1'b0) ); +mux8 mux_pwr_lo (.sel(major_mode), .y(pwr_lo ), .x0(lr_pwr_lo ), .x1(le_pwr_lo ), .x2(lp_pwr_lo ), .x3(la_pwr_lo ), .x4(1'b0), .x5(1'b0), .x6(1'b1), .x7(1'b0) ); +mux8 mux_pwr_hi (.sel(major_mode), .y(pwr_hi ), .x0(lr_pwr_hi ), .x1(le_pwr_hi ), .x2(lp_pwr_hi ), .x3(la_pwr_hi ), .x4(1'b0), .x5(1'b0), .x6(1'b0), .x7(1'b0) ); +mux8 mux_adc_clk (.sel(major_mode), .y(adc_clk ), .x0(lr_adc_clk ), .x1(le_adc_clk ), .x2(lp_adc_clk), .x3(la_adc_clk ), .x4(1'b0), .x5(1'b0), .x6(1'b0), .x7(1'b0) ); +mux8 mux_dbg (.sel(major_mode), .y(debug ), .x0(lr_debug ), .x1(le_debug ), .x2(lp_debug ), .x3(la_debug ), .x4(1'b0), .x5(1'b0), .x6(1'b0), .x7(1'b0) ); +mux8 mux_ant (.sel(major_mode), .y(PWR_LO_EN), .x0(1'b1 ), .x1(1'b1 ), .x2(1'b1 ), .x3(1'b1 ), .x4(1'b0), .x5(1'b0), .x6(1'b0), .x7(1'b0) ); + +// In all modes, let the ADC's outputs be enabled. +assign adc_noe = 1'b0; + +endmodule diff --git a/fpga-xc3s100e/fpga_allinone.v b/fpga/fpga_icopyx_top.v similarity index 61% rename from fpga-xc3s100e/fpga_allinone.v rename to fpga/fpga_icopyx_top.v index e766181f2a..81aacb73cf 100644 --- a/fpga-xc3s100e/fpga_allinone.v +++ b/fpga/fpga_icopyx_top.v @@ -1,37 +1,61 @@ -////////////////////////////////////////////////////////////////////////////////// -// Company: -// Engineer: +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. // -// Create Date: 16:09:14 05/13/2020 -// Design Name: -// Module Name: fpga_all_in_one -// Project Name: -// Target Devices: -// Tool versions: -// Description: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// Dependencies: +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// Revision: -// Revision 0.01 - File Created -// Additional Comments: +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- // -////////////////////////////////////////////////////////////////////////////////// -module fpga_hf( - input spck, output miso, input mosi, input ncs, - input pck0, input ck_1356meg, input ck_1356megb, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, output adc_noe, - output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk, - input cross_hi, input cross_lo, +// The FPGA is responsible for interfacing between the A/D, the coil drivers, +// and the ARM. In the low-frequency modes it passes the data straight +// through, so that the ARM gets raw A/D samples over the SSP. In the high- +// frequency modes, the FPGA might perform some demodulation first, to +// reduce the amount of data that we must send to the ARM. +//----------------------------------------------------------------------------- +//`include "fpga_lf.v" +//`include "fpga_hf.v" +//`include "mux2_onein.v" +//`include "mux2_oneout.v" +//`include "util.v" + +module fpga_top( + input spck, + output miso, + input mosi, + input ncs, + input pck0, + input ck_1356meg, + input ck_1356megb, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4, + input [7:0] adc_d, + output adc_clk, + output adc_noe, + output ssp_frame, + output ssp_din, + input ssp_dout, + output ssp_clk, + input cross_hi, + input cross_lo, output dbg, output PWR_LO_EN, input FPGA_SWITCH ); -fpga_hfmod hfmod( +fpga_hf hfmod( hfspck, hfmiso, hfmosi, hfncs, hfpck0, hfck_1356meg, hfck_1356megb, hfpwr_lo, hfpwr_hi, @@ -39,10 +63,10 @@ fpga_hfmod hfmod( adc_d, hfadc_clk, hfadc_noe, hfssp_frame, hfssp_din, hfssp_dout, hfssp_clk, hfcross_hi, hfcross_lo, - hfdbg + hfdebug ); -fpga_lfmod lfmod( +fpga_lf lfmod( lfspck, lfmiso, lfmosi, lfncs, lfpck0, lfck_1356meg, lfck_1356megb, lfpwr_lo, lfpwr_hi, @@ -50,7 +74,7 @@ fpga_lfmod lfmod( adc_d, lfadc_clk, lfadc_noe, lfssp_frame, lfssp_din, lfssp_dout, lfssp_clk, lfcross_hi, lfcross_lo, - lfdbg, + lfdebug, lfPWR_LO_EN ); @@ -75,7 +99,7 @@ mux2_oneout mux_ssp_dout_all (FPGA_SWITCH, ssp_dout, hfss mux2_one mux_ssp_clk_all (FPGA_SWITCH, ssp_clk, hfssp_clk, lfssp_clk); mux2_oneout mux_cross_hi_all (FPGA_SWITCH, cross_hi, hfcross_hi, lfcross_hi); mux2_oneout mux_cross_lo_all (FPGA_SWITCH, cross_lo, hfcross_lo, lfcross_lo); -mux2_one mux_dbg_all (FPGA_SWITCH, dbg, hfdbg, lfdbg); +mux2_one mux_dbg_all (FPGA_SWITCH, dbg, hfdebug, lfdebug); mux2_one mux_PWR_LO_EN_all (FPGA_SWITCH, PWR_LO_EN, 1'b0, lfPWR_LO_EN); endmodule diff --git a/fpga/fpga_pm3_felica.bit b/fpga/fpga_pm3_felica.bit new file mode 100644 index 0000000000000000000000000000000000000000..a903f180ead332a29b109b75c0bc01e7ce0b6c51 GIT binary patch literal 42176 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 tV6_HTYXCJ+!WAe)UwflO3jb27M6&B3H literal 0 HcmV?d00001 diff --git a/fpga/fpga_pm3_hf.bit b/fpga/fpga_pm3_hf.bit new file mode 100644 index 0000000000000000000000000000000000000000..76dcb8d98b9abed252a733ac03141958baf91129 GIT binary patch literal 42172 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 z�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 literal 0 HcmV?d00001 diff --git a/fpga/fpga_pm3_lf.bit b/fpga/fpga_pm3_lf.bit new file mode 100644 index 0000000000000000000000000000000000000000..593a9031f9bc0765bcbf12e5b1b63a0e88037c42 GIT binary patch literal 42172 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
  • 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 literal 0 HcmV?d00001 diff --git a/fpga/fpga_pm3_top.v b/fpga/fpga_pm3_top.v new file mode 100644 index 0000000000..89bd2e56b0 --- /dev/null +++ b/fpga/fpga_pm3_top.v @@ -0,0 +1,438 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// +// The FPGA is responsible for interfacing between the A/D, the coil drivers, +// and the ARM. In the low-frequency modes it passes the data straight +// through, so that the ARM gets raw A/D samples over the SSP. In the high- +// frequency modes, the FPGA might perform some demodulation first, to +// reduce the amount of data that we must send to the ARM. +//----------------------------------------------------------------------------- +/* +Once upon a time the FPGA had a 16 input mux so we could have all LF and HF modules enabled and selectable +As the functionality grew, we run out of space in the FPGA and we had to split into an "LF only" and an "HF only" FPGA bitstream +But even then after a while it was not possible to fit all the HF functions at the same time so now we have multiple "HF only" bitstreams +For example "Felica but without ISO14443", or "ISO14443 but without Felica" or "HF_15 but without Felica and ISO14443" + +Because of all of the above, you can not enable both HF and LF modes at the same time, because some LF modules outputs +map to the same mux inputs as some HF modules outputs (thanks to reducing the mux from 16 to 8 inputs) and you can not have +multiple outputs connected together therefore leading to a failed compilation +*/ + +// These defines are meant to be passed by the Makefile so do not uncomment them here +// Proxmark3 RDV4 target +//`define PM3RDV4 +// Proxmark3 generic target +//`define PM3GENERIC +// iCopy-X with XC3S100E +//`define PM3ICOPYX + +// Pass desired defines to compiler to enable required modules +// WITH_LF enables Low Frequency mode when defined else HF is enabled +//`define WITH_LF +// WITH_LF0 enables module reader +//`define WITH_LF0 +// WITH_LF1 enables module edge detect +//`define WITH_LF1 +// WITH_LF2 enables module passthrough +//`define WITH_LF2 +// WITH_LF3 enables module ADC +//`define WITH_LF3 + +// WITH_HF0 enables module HF reader +//`define WITH_HF0 +// WITH_HF1 enables module simulated tag +//`define WITH_HF1 +// WITH_HF2 enables module ISO14443-A +//`define WITH_HF2 +// WITH_HF3 enables module sniff +//`define WITH_HF3 +// WITH_HF4 enables module ISO18092 FeliCa +//`define WITH_HF4 +// WITH_HF5 enables module get trace +//`define WITH_HF5 + +//`include "define.v" +//`include "util.v" +// +//`ifdef WITH_LF `include "clk_divider.v" `endif +//`ifdef WITH_LF0 `include "lo_read.v" `endif +//`ifdef WITH_LF1 `include "lo_edge_detect.v" `endif +//`ifdef WITH_LF2 `include "lo_passthru.v" `endif +//`ifdef WITH_LF3 `include "lo_adc.v" `endif +// +//`ifdef WITH_HF_15 +//`ifdef WITH_HF0 `include "hi_reader_15.v" `endif +//`else +//`ifdef WITH_HF0 `include "hi_reader.v" `endif +//`endif +//`ifdef WITH_HF1 `include "hi_simulate.v" `endif +//`ifdef WITH_HF2 `include "hi_iso14443a.v" `endif +//`ifdef WITH_HF3 `include "hi_sniffer.v" `endif +//`ifdef WITH_HF4 `include "hi_flite.v" `endif +//`ifdef WITH_HF5 `include "hi_get_trace.v" `endif + +module fpga_top( + input ck_1356meg, + input ck_1356megb, + input spck, + input pck0, + input ncs, + input [7:0] adc_d, + input cross_hi, + input cross_lo, + input mosi, + input ssp_dout, + + output ssp_din, + output ssp_frame, + output ssp_clk, + output adc_clk, + output adc_noe, + output miso, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4, + output dbg +); + +// In all modes, let the ADC's outputs be enabled. +assign adc_noe = 1'b0; + +//----------------------------------------------------------------------------- +// The SPI receiver. This sets up the configuration word, which the rest of +// the logic looks at to determine how to connect the A/D and the coil +// drivers (i.e., which section gets it). Also assign some symbolic names +// to the configuration bits, for use below. +//----------------------------------------------------------------------------- + +// Receive 16bits of data from ARM here. +reg [15:0] shift_reg; +always @(posedge spck) if (~ncs) shift_reg <= {shift_reg[14:0], mosi}; + +reg trace_enable; + +reg [7:0] lf_ed_threshold; + +// adjustable frequency clock +wire [7:0] pck_cnt; +wire pck_divclk; +reg [7:0] divisor; +clk_divider div_clk(pck0, divisor, pck_cnt, pck_divclk); + +`ifdef WITH_LF +reg [11:0] conf_word; +`else +reg [8:0] conf_word; +`endif + +// We switch modes between transmitting to the 13.56 MHz tag and receiving +// from it, which means that we must make sure that we can do so without +// glitching, or else we will glitch the transmitted carrier. +always @(posedge ncs) +begin + // 4 bit command + case (shift_reg[15:12]) +`ifdef WITH_LF + `FPGA_CMD_SET_CONFREG: + begin + // 12 bit data + conf_word <= shift_reg[11:0]; + if (shift_reg[8:6] == `FPGA_MAJOR_MODE_LF_EDGE_DETECT) lf_ed_threshold <= 127; // default threshold + end + + `FPGA_CMD_SET_DIVISOR: + divisor <= shift_reg[7:0]; // 8bits + + `FPGA_CMD_SET_EDGE_DETECT_THRESHOLD: + lf_ed_threshold <= shift_reg[7:0]; // 8 bits +`else + `FPGA_CMD_SET_CONFREG: conf_word <= shift_reg[8:0]; + `FPGA_CMD_TRACE_ENABLE: trace_enable <= shift_reg[0]; +`endif + endcase +end + +//----------------------------------------------------------------------------- +// And then we instantiate the modules corresponding to each of the FPGA's +// major modes, and use muxes to connect the outputs of the active mode to +// the output pins. +//----------------------------------------------------------------------------- + +// ############################################################################ +// # Enable Low Frequency Modules +`ifdef WITH_LF + +// LF reader (generic) +`ifdef WITH_LF0 +lo_read lr( + .pck0 (pck0), + .pck_divclk (pck_divclk), + .pck_cnt (pck_cnt), + .adc_d (adc_d), + .lf_field (conf_word[0]), + + .ssp_din (mux0_ssp_din), + .ssp_frame (mux0_ssp_frame), + .ssp_clk (mux0_ssp_clk), + .adc_clk (mux0_adc_clk), + .pwr_lo (mux0_pwr_lo), + .pwr_hi (mux0_pwr_hi), + .pwr_oe1 (mux0_pwr_oe1), + .pwr_oe2 (mux0_pwr_oe2), + .pwr_oe3 (mux0_pwr_oe3), + .pwr_oe4 (mux0_pwr_oe4), + .debug (mux0_debug) +); +`endif + +// LF edge detect (generic) +`ifdef WITH_LF1 +lo_edge_detect le( + .pck0 (pck0), + .pck_divclk (pck_divclk), + .adc_d (adc_d), + .cross_lo (cross_lo), + .lf_field (conf_word[0]), + .lf_ed_toggle_mode (conf_word[1]), + .lf_ed_threshold (lf_ed_threshold), + .ssp_dout (ssp_dout), + + .ssp_frame (mux1_ssp_frame), + .ssp_clk (mux1_ssp_clk), + .adc_clk (mux1_adc_clk), + .pwr_lo (mux1_pwr_lo), + .pwr_hi (mux1_pwr_hi), + .pwr_oe1 (mux1_pwr_oe1), + .pwr_oe2 (mux1_pwr_oe2), + .pwr_oe3 (mux1_pwr_oe3), + .pwr_oe4 (mux1_pwr_oe4), + .debug (mux1_debug) +); +`endif + +// LF passthrough +`ifdef WITH_LF2 +lo_passthru lp( + .pck_divclk (pck_divclk), + .cross_lo (cross_lo), + .ssp_dout (ssp_dout), + + .ssp_din (mux2_ssp_din), + .adc_clk (mux2_adc_clk), + .pwr_lo (mux2_pwr_lo), + .pwr_hi (mux2_pwr_hi), + .pwr_oe1 (mux2_pwr_oe1), + .pwr_oe2 (mux2_pwr_oe2), + .pwr_oe3 (mux2_pwr_oe3), + .pwr_oe4 (mux2_pwr_oe4), + .debug (mux2_debug) +); +`endif + +// LF ADC (read/write) +`ifdef WITH_LF3 +lo_adc la( + .pck0 (pck0), + .adc_d (adc_d), + .divisor (divisor), + .lf_field (conf_word[0]), + .ssp_dout (ssp_dout), + + .ssp_din (mux3_ssp_din), + .ssp_frame (mux3_ssp_frame), + .ssp_clk (mux3_ssp_clk), + .adc_clk (mux3_adc_clk), + .pwr_lo (mux3_pwr_lo ), + .pwr_hi (mux3_pwr_hi ), + .pwr_oe1 (mux3_pwr_oe1), + .pwr_oe2 (mux3_pwr_oe2), + .pwr_oe3 (mux3_pwr_oe3), + .pwr_oe4 (mux3_pwr_oe4), + .debug (mux3_debug) +); +`endif // WITH_LF3 + +assign mux6_pwr_lo = 1'b1; +// 7 -- SPARE + +`else // if WITH_LF not defined +// ############################################################################ +// # Enable High Frequency Modules + +// HF reader +`ifdef WITH_HF0 +`ifdef WITH_HF_15 +hi_reader_15 hr( +`else +hi_reader hr( +`endif + .ck_1356meg (ck_1356megb), + .adc_d (adc_d), + .subcarrier_frequency (conf_word[5:4]), + .minor_mode (conf_word[3:0]), + .ssp_dout (ssp_dout), + + .ssp_din (mux0_ssp_din), + .ssp_frame (mux0_ssp_frame), + .ssp_clk (mux0_ssp_clk), + .adc_clk (mux0_adc_clk), + .pwr_lo (mux0_pwr_lo), + .pwr_hi (mux0_pwr_hi), + .pwr_oe1 (mux0_pwr_oe1), + .pwr_oe2 (mux0_pwr_oe2), + .pwr_oe3 (mux0_pwr_oe3), + .pwr_oe4 (mux0_pwr_oe4), + .debug (mux0_debug) +); +`endif // WITH_HF0 + +// HF simulated tag +`ifdef WITH_HF1 +hi_simulate hs( + .ck_1356meg (ck_1356meg), + .adc_d (adc_d), + .mod_type (conf_word[3:0]), + .ssp_dout (ssp_dout), + + .ssp_din (mux1_ssp_din), + .ssp_frame (mux1_ssp_frame), + .ssp_clk (mux1_ssp_clk), + .adc_clk (mux1_adc_clk), + .pwr_lo (mux1_pwr_lo), + .pwr_hi (mux1_pwr_hi), + .pwr_oe1 (mux1_pwr_oe1), + .pwr_oe2 (mux1_pwr_oe2), + .pwr_oe3 (mux1_pwr_oe3), + .pwr_oe4 (mux1_pwr_oe4), + .debug (mux1_debug) +); +`endif // WITH_HF1 + +// HF ISO14443-A +`ifdef WITH_HF2 +hi_iso14443a hisn( + .ck_1356meg (ck_1356meg), + .adc_d (adc_d), + .mod_type (conf_word[3:0]), + .ssp_dout (ssp_dout), + + .ssp_din (mux2_ssp_din), + .ssp_frame (mux2_ssp_frame), + .ssp_clk (mux2_ssp_clk), + .adc_clk (mux2_adc_clk), + .pwr_lo (mux2_pwr_lo), + .pwr_hi (mux2_pwr_hi), + .pwr_oe1 (mux2_pwr_oe1), + .pwr_oe2 (mux2_pwr_oe2), + .pwr_oe3 (mux2_pwr_oe3), + .pwr_oe4 (mux2_pwr_oe4), + .debug (mux2_debug) +); +`endif // WITH_HF2 + +// HF sniff +`ifdef WITH_HF3 +hi_sniffer he( + .ck_1356meg (ck_1356megb), + .adc_d (adc_d), + + .ssp_din (mux3_ssp_din), + .ssp_frame (mux3_ssp_frame), + .ssp_clk (mux3_ssp_clk), + .adc_clk (mux3_adc_clk), + .pwr_lo (mux3_pwr_lo), + .pwr_hi (mux3_pwr_hi), + .pwr_oe1 (mux3_pwr_oe1), + .pwr_oe2 (mux3_pwr_oe2), + .pwr_oe3 (mux3_pwr_oe3), + .pwr_oe4 (mux3_pwr_oe4) +); +`endif //WITH_HF3 + +// HF ISO18092 FeliCa +`ifdef WITH_HF4 +hi_flite hfl( + .ck_1356meg (ck_1356megb), + .adc_d (adc_d), + .mod_type (conf_word[3:0]), + .ssp_dout (ssp_dout), + + .ssp_din (mux4_ssp_din), + .ssp_frame (mux4_ssp_frame), + .ssp_clk (mux4_ssp_clk), + .adc_clk (mux4_adc_clk), + .pwr_lo (mux4_pwr_lo), + .pwr_hi (mux4_pwr_hi), + .pwr_oe1 (mux4_pwr_oe1), + .pwr_oe2 (mux4_pwr_oe2), + .pwr_oe3 (mux4_pwr_oe3), + .pwr_oe4 (mux4_pwr_oe4), + .debug (mux4_debug) +); +`endif // WITH_HF4 + +// HF get trace +`ifdef WITH_HF5 +hi_get_trace gt( + .ck_1356megb (ck_1356megb), + .adc_d (adc_d), + .trace_enable (trace_enable), + .major_mode (conf_word[8:6]), + .ssp_din (mux5_ssp_din), + .ssp_frame (mux5_ssp_frame), + .ssp_clk (mux5_ssp_clk) +); +`endif // WITH_HF5 + +`endif // WITH_LF + +// These assignments must agree with the defines in fpgaloader.h +// Major modes Low Frequency +// mux0 = LF reader (generic) +// mux1 = LF edge detect (generic) +// mux2 = LF passthrough +// mux3 = LF ADC (read/write) +// mux4 = SPARE +// mux5 = SPARE +// mux6 = SPARE +// mux7 = FPGA_MAJOR_MODE_OFF + +// Major modes High Frequency +// mux0 = HF reader +// mux1 = HF simulated tag +// mux2 = HF ISO14443-A +// mux3 = HF sniff +// mux4 = HF ISO18092 FeliCa +// mux5 = HF get trace +// mux6 = unused +// mux7 = FPGA_MAJOR_MODE_OFF + +mux8 mux_ssp_clk (.sel(conf_word[8:6]), .y(ssp_clk ), .x0(mux0_ssp_clk ), .x1(mux1_ssp_clk ), .x2(mux2_ssp_clk ), .x3(mux3_ssp_clk ), .x4(mux4_ssp_clk ), .x5(mux5_ssp_clk ), .x6(mux6_ssp_clk ), .x7(mux7_ssp_clk ) ); +mux8 mux_ssp_din (.sel(conf_word[8:6]), .y(ssp_din ), .x0(mux0_ssp_din ), .x1(mux1_ssp_din ), .x2(mux2_ssp_din ), .x3(mux3_ssp_din ), .x4(mux4_ssp_din ), .x5(mux5_ssp_din ), .x6(mux6_ssp_din ), .x7(mux7_ssp_din ) ); +mux8 mux_ssp_frame (.sel(conf_word[8:6]), .y(ssp_frame), .x0(mux0_ssp_frame), .x1(mux1_ssp_frame), .x2(mux2_ssp_frame), .x3(mux3_ssp_frame), .x4(mux4_ssp_frame), .x5(mux5_ssp_frame), .x6(mux6_ssp_frame), .x7(mux7_ssp_frame) ); +mux8 mux_pwr_oe1 (.sel(conf_word[8:6]), .y(pwr_oe1 ), .x0(mux0_pwr_oe1 ), .x1(mux1_pwr_oe1 ), .x2(mux2_pwr_oe1 ), .x3(mux3_pwr_oe1 ), .x4(mux4_pwr_oe1 ), .x5(mux5_pwr_oe1 ), .x6(mux6_pwr_oe1 ), .x7(mux7_pwr_oe1 ) ); +mux8 mux_pwr_oe2 (.sel(conf_word[8:6]), .y(pwr_oe2 ), .x0(mux0_pwr_oe2 ), .x1(mux1_pwr_oe2 ), .x2(mux2_pwr_oe2 ), .x3(mux3_pwr_oe2 ), .x4(mux4_pwr_oe2 ), .x5(mux5_pwr_oe2 ), .x6(mux6_pwr_oe2 ), .x7(mux7_pwr_oe2 ) ); +mux8 mux_pwr_oe3 (.sel(conf_word[8:6]), .y(pwr_oe3 ), .x0(mux0_pwr_oe3 ), .x1(mux1_pwr_oe3 ), .x2(mux2_pwr_oe3 ), .x3(mux3_pwr_oe3 ), .x4(mux4_pwr_oe3 ), .x5(mux5_pwr_oe3 ), .x6(mux6_pwr_oe3 ), .x7(mux7_pwr_oe3 ) ); +mux8 mux_pwr_oe4 (.sel(conf_word[8:6]), .y(pwr_oe4 ), .x0(mux0_pwr_oe4 ), .x1(mux1_pwr_oe4 ), .x2(mux2_pwr_oe4 ), .x3(mux3_pwr_oe4 ), .x4(mux4_pwr_oe4 ), .x5(mux5_pwr_oe4 ), .x6(mux6_pwr_oe4 ), .x7(mux7_pwr_oe4 ) ); +mux8 mux_pwr_lo (.sel(conf_word[8:6]), .y(pwr_lo ), .x0(mux0_pwr_lo ), .x1(mux1_pwr_lo ), .x2(mux2_pwr_lo ), .x3(mux3_pwr_lo ), .x4(mux4_pwr_lo ), .x5(mux5_pwr_lo ), .x6(mux6_pwr_lo ), .x7(mux7_pwr_lo ) ); +mux8 mux_pwr_hi (.sel(conf_word[8:6]), .y(pwr_hi ), .x0(mux0_pwr_hi ), .x1(mux1_pwr_hi ), .x2(mux2_pwr_hi ), .x3(mux3_pwr_hi ), .x4(mux4_pwr_hi ), .x5(mux5_pwr_hi ), .x6(mux6_pwr_hi ), .x7(mux7_pwr_hi ) ); +mux8 mux_adc_clk (.sel(conf_word[8:6]), .y(adc_clk ), .x0(mux0_adc_clk ), .x1(mux1_adc_clk ), .x2(mux2_adc_clk ), .x3(mux3_adc_clk ), .x4(mux4_adc_clk ), .x5(mux5_adc_clk ), .x6(mux6_adc_clk ), .x7(mux7_adc_clk ) ); +mux8 mux_dbg (.sel(conf_word[8:6]), .y(dbg ), .x0(mux0_debug ), .x1(mux1_debug ), .x2(mux2_debug ), .x3(mux3_debug ), .x4(mux4_debug ), .x5(mux5_debug ), .x6(mux6_debug ), .x7(mux7_debug ) ); + +endmodule diff --git a/fpga-xc2s30/hi_flite.v b/fpga/hi_flite.v similarity index 92% rename from fpga-xc2s30/hi_flite.v rename to fpga/hi_flite.v index 75ffbc9e54..ac9e7e069a 100644 --- a/fpga-xc2s30/hi_flite.v +++ b/fpga/hi_flite.v @@ -30,32 +30,29 @@ */ module hi_flite( - ck_1356meg, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - dbg, - mod_type + input ck_1356meg, + input [7:0] adc_d, + input [3:0] mod_type, + input ssp_dout, + + output reg ssp_din, + output reg ssp_frame, + output reg ssp_clk, + output adc_clk, + output reg pwr_lo, + output reg pwr_hi, + output reg pwr_oe1, + output reg pwr_oe2, + output reg pwr_oe3, + output reg pwr_oe4, + output debug ); - input ck_1356meg; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - output dbg; - input [3:0] mod_type; - -assign dbg = 0; - -wire power = mod_type[2]; -wire speed = mod_type[1]; -wire disabl = mod_type[0]; -// Most off, oe4 for modulation; -// Trying reader emulation (would presumably just require switching power on, but I am not sure) -assign pwr_lo = 1'b0; -assign pwr_oe2 = 1'b0; +assign debug = 0; + +wire power = mod_type[2]; +wire speed = mod_type[1]; +wire disabl = mod_type[0]; // 512x64/fc -wait before ts0, 32768 ticks // tslot: 256*64/fc @@ -95,10 +92,6 @@ reg did_sync=0; wire [7:0] bithalf = speed ? `bithalf_424 : `bithalf_212; wire [7:0] bitmlen = speed ? `bitmlen_424 : `bitmlen_212; - -//ssp clock and current values -reg ssp_clk; -reg ssp_frame; reg curbit = 1'b0; reg [7:0] fccount = 8'd0; // in-bit tick counter. Counts carrier cycles from the first lower edge detected, reset on every manchester bit detected @@ -107,6 +100,7 @@ reg [7:0] tsinceedge = 8'd0;// ticks from last edge, desync if the valye is too reg zero = 1'b0; // Manchester first halfbit low second high corresponds to this value. It has been known to change. SYNC is used to set it +//ssp clock and current values //ssp counter for transfer and framing reg [8:0] ssp_cnt = 9'd0; @@ -122,6 +116,7 @@ begin if( ((~speed) && (ssp_cnt[5:0] == 6'b000000)) || (speed && (ssp_cnt[4:0] == 5'b00000))) begin ssp_clk <= 1'b1; + //send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise) ssp_din <= curbit; end if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000)) @@ -138,9 +133,6 @@ begin end end -//send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise) -reg ssp_din; - //previous signal value, mostly to detect SYNC reg prv = 1'b1; @@ -353,11 +345,8 @@ begin end // sending <= 0; end + //put modulation here to maintain the correct clock. Seems that some readers are sensitive to that -reg pwr_hi; -reg pwr_oe1; -reg pwr_oe3; -reg pwr_oe4; wire mod = ((fccount >= bithalf) ^ dlay) & (~disabl); @@ -365,21 +354,22 @@ always @(ck_1356meg or ssp_dout or power or disabl or mod) begin if (power) begin - pwr_hi <= ck_1356meg; + pwr_hi <= ck_1356meg; + pwr_lo <= 1'b0; pwr_oe1 <= 1'b0;//mod; + pwr_oe2 <= 1'b0;//mod; pwr_oe3 <= 1'b0;//mod; pwr_oe4 <= mod;//1'b0; end else begin - pwr_hi <= 1'b0; + pwr_hi <= 1'b0; + pwr_lo <= 1'b0; pwr_oe1 <= 1'b0; + pwr_oe2 <= 1'b0; pwr_oe3 <= 1'b0; pwr_oe4 <= mod; end end - - - endmodule diff --git a/fpga-xc2s30/hi_get_trace.v b/fpga/hi_get_trace.v similarity index 86% rename from fpga-xc2s30/hi_get_trace.v rename to fpga/hi_get_trace.v index 6e4369e147..9bf32bc643 100644 --- a/fpga-xc2s30/hi_get_trace.v +++ b/fpga/hi_get_trace.v @@ -13,17 +13,18 @@ // // See LICENSE.txt for the text of the license. //----------------------------------------------------------------------------- +//`include "define.v" module hi_get_trace( - ck_1356megb, - adc_d, trace_enable, major_mode, - ssp_frame, ssp_din, ssp_clk + input ck_1356megb, + input [7:0] adc_d, + input trace_enable, + input [2:0] major_mode, + + output ssp_din, + output reg ssp_frame, + output reg ssp_clk ); - input ck_1356megb; - input [7:0] adc_d; - input trace_enable; - input [2:0] major_mode; - output ssp_frame, ssp_din, ssp_clk; // clock divider reg [6:0] clock_cnt; @@ -88,9 +89,9 @@ begin write_enable2 <= 1'b0; end else - begin + begin addr <= addr + 1; - end + end end end else @@ -136,9 +137,6 @@ begin end -// SSC communication to ARM -reg ssp_clk; -reg ssp_frame; reg [7:0] shift_out; always @(negedge ck_1356megb) @@ -147,16 +145,16 @@ begin begin if (clock_cnt[6:4] == 3'd0) // either load new value begin - if (addr[11] == 1'b0) - shift_out <= D_out1; - else - shift_out <= D_out2; + if (addr[11] == 1'b0) + shift_out <= D_out1; + else + shift_out <= D_out2; end else - begin - // or shift left - shift_out[7:1] <= shift_out[6:0]; - end + begin + // or shift left + shift_out[7:1] <= shift_out[6:0]; + end end ssp_clk <= ~clock_cnt[3]; // ssp_clk frequency = 13,56MHz / 16 = 847,5 kHz diff --git a/fpga-xc2s30/hi_iso14443a.v b/fpga/hi_iso14443a.v similarity index 97% rename from fpga-xc2s30/hi_iso14443a.v rename to fpga/hi_iso14443a.v index d52ab40004..7ccd7f610b 100644 --- a/fpga-xc2s30/hi_iso14443a.v +++ b/fpga/hi_iso14443a.v @@ -14,29 +14,28 @@ // See LICENSE.txt for the text of the license. //----------------------------------------------------------------------------- // ISO14443-A support for the Proxmark III -// +//`include "define.v" module hi_iso14443a( - ck_1356meg, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - dbg, - mod_type + input ck_1356meg, + input [7:0] adc_d, + input [3:0] mod_type, + input ssp_dout, + + output ssp_din, + output reg ssp_frame, + output reg ssp_clk, + output adc_clk, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4, + output debug ); - input ck_1356meg; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - output dbg; - input [3:0] mod_type; - - -wire adc_clk = ck_1356meg; - +assign adc_clk = ck_1356meg; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Reader -> PM3: @@ -76,8 +75,6 @@ begin end - - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Reader -> PM3 // detect when a reader is active (modulating). We assume that the reader is active, if we see the carrier off for at least 8 @@ -137,7 +134,6 @@ wire [9:0] tmp2 = adc_d_times_2 + input_prev_1; wire signed [10:0] adc_d_filtered = {1'b0, tmp1} - {1'b0, tmp2}; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // internal FPGA timing. Maximum required period is 128 carrier clock cycles for a full 8 Bit transfer to ARM. (i.e. we need a // 7 bit counter). Adjust its frequency to external reader's clock when simulating a tag or sniffing. @@ -222,7 +218,11 @@ reg signed [10:0] rx_mod_falling_edge_max; reg signed [10:0] rx_mod_rising_edge_max; reg curbit; +`ifdef PM3ICOPYX +`define EDGE_DETECT_THRESHOLD 3 +`else `define EDGE_DETECT_THRESHOLD 5 +`endif `define EDGE_DETECT_THRESHOLDHIGH 20 always @(negedge adc_clk) @@ -266,7 +266,6 @@ begin end - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Tag+Reader -> PM3 // sample 4 bits reader data and 4 bits tag data for sniffing @@ -283,7 +282,6 @@ begin end - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PM3 -> Reader: // a delay line to ensure that we send the (emulated) tag's answer at the correct time according to ISO14443-3 @@ -307,7 +305,6 @@ begin end - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PM3 -> Reader, internal timing: // a timer for the 1172 cycles fdt (Frame Delay Time). Start the timer with a rising edge of the reader's signal. @@ -400,7 +397,6 @@ begin end - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // PM3 -> Reader // determine the required delay in the mod_sig_buf (set mod_sig_ptr). @@ -444,7 +440,6 @@ begin end - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // FPGA -> ARM communication: // buffer 8 bits data to be sent to ARM. Shift them out bit by bit. @@ -495,8 +490,6 @@ end //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // FPGA <-> ARM communication: // generate a ssp clock and ssp frame signal for the synchronous transfer from/to the ARM -reg ssp_clk; -reg ssp_frame; always @(negedge adc_clk) begin @@ -529,7 +522,6 @@ begin end - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // FPGA -> ARM communication: // select the data to be sent to ARM @@ -553,7 +545,6 @@ begin sendbit = 1'b0; end - if(mod_type == `FPGA_HF_ISO14443A_SNIFFER) // send sampled reader and tag data: bit_to_arm = to_arm[7]; @@ -589,6 +580,6 @@ assign pwr_oe4 = mod_sig_coil & sub_carrier & (mod_type == `FPGA_HF_ISO14443A_TA assign pwr_oe2 = 1'b0; assign pwr_lo = 1'b0; -assign dbg = negedge_cnt[3]; +assign debug = negedge_cnt[3]; endmodule diff --git a/fpga-xc2s30/hi_reader.v b/fpga/hi_reader.v similarity index 95% rename from fpga-xc2s30/hi_reader.v rename to fpga/hi_reader.v index dbc38a8a7e..ffa2634d82 100644 --- a/fpga-xc2s30/hi_reader.v +++ b/fpga/hi_reader.v @@ -13,24 +13,27 @@ // // See LICENSE.txt for the text of the license. //----------------------------------------------------------------------------- +//`include "define.v" module hi_reader( - ck_1356meg, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - dbg, - subcarrier_frequency, minor_mode + input ck_1356meg, + input [7:0] adc_d, + input [1:0] subcarrier_frequency, + input [3:0] minor_mode, + input ssp_dout, + + output ssp_din, + output reg ssp_frame, + output reg ssp_clk, + output adc_clk, + output pwr_lo, + output reg pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output reg pwr_oe4, + output debug ); - input ck_1356meg; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - output dbg; - input [1:0] subcarrier_frequency; - input [3:0] minor_mode; assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz @@ -160,7 +163,6 @@ begin end else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ) begin - // Send 7 most significant bits of in phase tag signal (signed), plus 1 bit reader signal if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111) corr_i_out <= {corr_i_accum[11:5], after_hysteresis_prev_prev}; @@ -261,9 +263,6 @@ end // corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ... // -reg ssp_clk; -reg ssp_frame; - always @(negedge adc_clk) begin if (corr_i_cnt[1:0] == 2'b00) @@ -298,9 +297,6 @@ begin end end -// Antenna drivers -reg pwr_hi, pwr_oe4; - always @(*) begin if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD) @@ -341,6 +337,6 @@ assign pwr_lo = 1'b0; assign pwr_oe2 = 1'b0; // Debug Output -assign dbg = corr_i_cnt[3]; +assign debug = corr_i_cnt[3]; endmodule diff --git a/fpga-xc2s30/hi_reader_15.v b/fpga/hi_reader_15.v similarity index 96% rename from fpga-xc2s30/hi_reader_15.v rename to fpga/hi_reader_15.v index 0db4fe2a3a..ad41e771c4 100644 --- a/fpga-xc2s30/hi_reader_15.v +++ b/fpga/hi_reader_15.v @@ -14,25 +14,26 @@ // See LICENSE.txt for the text of the license. //----------------------------------------------------------------------------- // modified to add support for iso15 2sc mode -// -module hi_15_reader( - ck_1356meg, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - dbg, - subcarrier_frequency, minor_mode +module hi_reader_15( + input ck_1356meg, + input [7:0] adc_d, + input [1:0] subcarrier_frequency, + input [3:0] minor_mode, + input ssp_dout, + + output ssp_din, + output reg ssp_frame, + output reg ssp_clk, + output adc_clk, + output pwr_lo, + output reg pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output reg pwr_oe4, + output debug ); - input ck_1356meg; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - output dbg; - input [1:0] subcarrier_frequency; - input [3:0] minor_mode; assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz @@ -379,9 +380,6 @@ end // corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ... // -reg ssp_clk; -reg ssp_frame; - always @(negedge adc_clk) begin if (corr_i_cnt[1:0] == 2'b00) @@ -416,9 +414,6 @@ begin end end -// Antenna drivers -reg pwr_hi, pwr_oe4; - always @(*) begin if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD) @@ -459,6 +454,6 @@ assign pwr_lo = 1'b0; assign pwr_oe2 = 1'b0; // Debug Output -assign dbg = corr_i_cnt[3]; +assign debug = corr_i_cnt[3]; endmodule diff --git a/fpga-xc2s30/hi_simulate.v b/fpga/hi_simulate.v similarity index 91% rename from fpga-xc2s30/hi_simulate.v rename to fpga/hi_simulate.v index 2232aedd96..97346eb9bb 100644 --- a/fpga-xc2s30/hi_simulate.v +++ b/fpga/hi_simulate.v @@ -30,23 +30,26 @@ // // Jonathan Westhues, October 2006 //----------------------------------------------------------------------------- +//`include "define.v" module hi_simulate( - ck_1356meg, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - dbg, - mod_type + input ck_1356meg, + input [7:0] adc_d, + input [3:0] mod_type, + input ssp_dout, + + output reg ssp_din, + output reg ssp_frame, + output reg ssp_clk, + output adc_clk, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4, + output debug ); - input ck_1356meg; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - output dbg; - input [3:0] mod_type; // Power amp goes between LOW and tri-state, so pwr_hi (and pwr_lo) can // always be low. @@ -57,7 +60,7 @@ assign pwr_lo = 1'b0; // LF antenna connected to GND assign pwr_oe2 = 1'b0; assign adc_clk = ck_1356meg; -assign dbg = ssp_frame; +assign debug = ssp_frame; // The comparator with hysteresis on the output from the peak detector. reg after_hysteresis; @@ -94,8 +97,6 @@ reg [8:0] ssp_clk_divider; always @(negedge adc_clk) ssp_clk_divider <= (ssp_clk_divider + 1); -reg ssp_clk; - always @(negedge adc_clk) begin if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT) @@ -112,7 +113,6 @@ end // Produce the byte framing signal; the phase of this signal // is arbitrary, because it's just a bit stream in this module. -reg ssp_frame; always @(negedge adc_clk) begin if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K) @@ -133,7 +133,6 @@ end // Synchronize up the after-hysteresis signal, to produce DIN. -reg ssp_din; always @(posedge ssp_clk) ssp_din = after_hysteresis; diff --git a/fpga-xc2s30/hi_sniffer.v b/fpga/hi_sniffer.v similarity index 69% rename from fpga-xc2s30/hi_sniffer.v rename to fpga/hi_sniffer.v index ed62191f19..11781ca5a6 100644 --- a/fpga-xc2s30/hi_sniffer.v +++ b/fpga/hi_sniffer.v @@ -15,16 +15,20 @@ //----------------------------------------------------------------------------- module hi_sniffer( - ck_1356meg, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_clk + input ck_1356meg, + input [7:0] adc_d, + + output ssp_din, + output reg ssp_frame, + output ssp_clk, + output adc_clk, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4 ); - input ck_1356meg; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - output ssp_frame, ssp_din, ssp_clk; // We are only snooping, all off. assign pwr_hi = 1'b0; @@ -34,12 +38,13 @@ assign pwr_oe2 = 1'b0; assign pwr_oe3 = 1'b0; assign pwr_oe4 = 1'b0; -reg ssp_frame; +//reg ssp_frame; reg [7:0] adc_d_out = 8'd0; -reg [2:0] ssp_cnt = 3'd0; +reg [2:0] ssp_cnt = 3'd0; -assign adc_clk = ck_1356meg; +assign adc_clk = ck_1356meg; assign ssp_clk = ~ck_1356meg; +assign ssp_din = adc_d_out[0]; always @(posedge ssp_clk) begin @@ -49,18 +54,16 @@ begin ssp_cnt <= ssp_cnt + 1; if(ssp_cnt[2:0] == 3'b000) // set frame length - begin - adc_d_out[7:0] <= adc_d; - ssp_frame <= 1'b1; - end + begin + adc_d_out[7:0] <= adc_d; + ssp_frame <= 1'b1; + end else - begin - adc_d_out[7:0] <= {1'b0, adc_d_out[7:1]}; - ssp_frame <= 1'b0; - end + begin + // shift value right one bit + adc_d_out[7:0] <= {1'b0, adc_d_out[7:1]}; + ssp_frame <= 1'b0; + end end - -assign ssp_din = adc_d_out[0]; - endmodule diff --git a/fpga-xc2s30/lf_edge_detect.v b/fpga/lf_edge_detect.v similarity index 72% rename from fpga-xc2s30/lf_edge_detect.v rename to fpga/lf_edge_detect.v index 4b6c0ac017..2a58331d1e 100644 --- a/fpga-xc2s30/lf_edge_detect.v +++ b/fpga/lf_edge_detect.v @@ -15,23 +15,37 @@ // See LICENSE.txt for the text of the license. //----------------------------------------------------------------------------- - // input clk is 24MHz -`include "min_max_tracker.v" +//`include "min_max_tracker.v" + +module lf_edge_detect( + input clk, + input [7:0] adc_d, + input [7:0] lf_ed_threshold, -module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold, - output [7:0] max, output [7:0] min, - output [7:0] high_threshold, output [7:0] highz_threshold, - output [7:0] lowz_threshold, output [7:0] low_threshold, - output edge_state, output edge_toggle); + output [7:0] max, + output [7:0] min, + output [7:0] low_threshold, + output [7:0] high_threshold, + output [7:0] lowz_threshold, + output [7:0] highz_threshold, + output edge_state, + output edge_toggle +); - min_max_tracker tracker(clk, adc_d, lf_ed_threshold, min, max); + min_max_tracker tracker( + .clk (clk), + .adc_d (adc_d), + .threshold (lf_ed_threshold), + .min (min), + .max (max) +); // auto-tune - assign high_threshold = (max + min) / 2 + (max - min) / 4; + assign high_threshold = (max + min) / 2 + (max - min) / 4; assign highz_threshold = (max + min) / 2 + (max - min) / 8; - assign lowz_threshold = (max + min) / 2 - (max - min) / 8; - assign low_threshold = (max + min) / 2 - (max - min) / 4; + assign lowz_threshold = (max + min) / 2 - (max - min) / 8; + assign low_threshold = (max + min) / 2 - (max - min) / 4; // heuristic to see if it makes sense to try to detect an edge wire enabled = @@ -55,18 +69,20 @@ module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold, always @(posedge clk) begin is_high <= (adc_d >= high_threshold); - is_low <= (adc_d <= low_threshold); + is_low <= (adc_d <= low_threshold); is_zero <= ((adc_d > lowz_threshold) & (adc_d < highz_threshold)); end // all edges detection always @(posedge clk) - if (enabled) begin + if (enabled) + begin // To enable detecting two consecutive peaks at the same level // (low or high) we check whether or not we went back near 0 in-between. // This extra check is necessary to prevent from noise artifacts // around the threshold values. - if (trigger_enabled & (is_high | is_low)) begin + if (trigger_enabled & (is_high | is_low)) + begin output_edge <= ~output_edge; trigger_enabled <= 0; end else @@ -75,14 +91,15 @@ module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold, // edge states always @(posedge clk) - if (enabled) begin + if (enabled) + begin if (is_high) output_state <= 1'd1; else if (is_low) output_state <= 1'd0; end - assign edge_state = output_state; + assign edge_state = output_state; assign edge_toggle = output_edge; endmodule diff --git a/fpga-xc2s30/lo_adc.v b/fpga/lo_adc.v similarity index 74% rename from fpga-xc2s30/lo_adc.v rename to fpga/lo_adc.v index 808ec96ed9..475cc869f1 100644 --- a/fpga-xc2s30/lo_adc.v +++ b/fpga/lo_adc.v @@ -22,22 +22,24 @@ //----------------------------------------------------------------------------- module lo_adc( - pck0, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - dbg, divisor, - lf_field + input pck0, + input [7:0] adc_d, + input [7:0] divisor, + input lf_field, + input ssp_dout, + + output ssp_din, + output ssp_frame, + output ssp_clk, + output adc_clk, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4, + output debug ); - input pck0; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - output dbg; - input [7:0] divisor; - input lf_field; reg [7:0] to_arm_shiftreg; reg [7:0] pck_divider; @@ -49,16 +51,16 @@ wire reader_modulation = !ssp_dout & lf_field & clk_state; // always on (High Frequency outputs, unused) assign pwr_oe1 = 1'b0; -assign pwr_hi = 1'b0; +assign pwr_hi = 1'b0; // low frequency outputs -assign pwr_lo = reader_modulation; +assign pwr_lo = reader_modulation; assign pwr_oe2 = 1'b0; // 33 Ohms assign pwr_oe3 = tag_modulation; // base antenna load = 33 Ohms assign pwr_oe4 = 1'b0; // 10k Ohms // Debug Output ADC clock -assign dbg = adc_clk; +assign debug = adc_clk; // ADC clock out of phase with antenna driver assign adc_clk = ~clk_state; @@ -76,10 +78,10 @@ assign ssp_frame = (pck_divider[7:3] == 5'd1) && !clk_state; always @(posedge pck0) begin if (pck_divider == divisor[7:0]) - begin + begin pck_divider <= 8'd0; clk_state = !clk_state; - end + end else begin pck_divider <= pck_divider + 1; @@ -92,13 +94,9 @@ always @(posedge pck0) begin if ((pck_divider == 8'd7) && !clk_state) to_arm_shiftreg <= adc_d; - else begin + else + begin to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; - // simulation showed a glitch occurring due to the LSB of the shifter - // not being set as we shift bits out - // this ensures the ssp_din remains low after a transfer and suppresses - // the glitch that would occur when the last data shifted out ended in - // a 1 bit and the next data shifted out started with a 0 bit to_arm_shiftreg[0] <= 1'b0; end end diff --git a/fpga-xc2s30/lo_edge_detect.v b/fpga/lo_edge_detect.v similarity index 67% rename from fpga-xc2s30/lo_edge_detect.v rename to fpga/lo_edge_detect.v index 462dfcc46f..c820466f7e 100644 --- a/fpga-xc2s30/lo_edge_detect.v +++ b/fpga/lo_edge_detect.v @@ -25,19 +25,29 @@ // - ssp_frame (wired to TIOA1 on the arm) for the edge detection/state // - ssp_clk: cross_lo -`include "lp20khz_1MSa_iir_filter.v" -`include "lf_edge_detect.v" +//`include "lp20khz_1MSa_iir_filter.v" +//`include "lf_edge_detect.v" module lo_edge_detect( - input pck0, input pck_divclk, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, - output ssp_frame, input ssp_dout, output ssp_clk, + input pck0, + input pck_divclk, + input [7:0] adc_d, input cross_lo, - output dbg, input lf_field, - input lf_ed_toggle_mode, input [7:0] lf_ed_threshold + input lf_ed_toggle_mode, + input [7:0] lf_ed_threshold, + input ssp_dout, + + output ssp_frame, + output ssp_clk, + output adc_clk, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4, + output debug ); wire tag_modulation = ssp_dout & !lf_field; @@ -58,18 +68,34 @@ assign pwr_hi = 1'b0; wire data_rdy; wire [7:0] adc_filtered; assign adc_clk = pck0; -lp20khz_1MSa_iir_filter adc_filter(pck0, adc_d, data_rdy, adc_filtered); + +lp20khz_1MSa_iir_filter adc_filter( + .clk (pck0), + .adc_d (adc_d), + .rdy (data_rdy), + .out (adc_filtered) +); // detect edges wire [7:0] high_threshold, highz_threshold, lowz_threshold, low_threshold; wire [7:0] max, min; wire edge_state, edge_toggle; -lf_edge_detect lf_ed(pck0, adc_filtered, lf_ed_threshold, - max, min, - high_threshold, highz_threshold, lowz_threshold, low_threshold, - edge_state, edge_toggle); -assign dbg = lf_ed_toggle_mode ? edge_toggle : edge_state; +lf_edge_detect lf_ed( + .clk (pck0), + .adc_d (adc_filtered), + .lf_ed_threshold (lf_ed_threshold), + .max (max), + .min (min), + .high_threshold (high_threshold), + .highz_threshold (highz_threshold), + .lowz_threshold (lowz_threshold), + .low_threshold (low_threshold), + .edge_state (edge_state), + .edge_toggle (edge_toggle) +); + +assign debug = lf_ed_toggle_mode ? edge_toggle : edge_state; assign ssp_frame = lf_ed_toggle_mode ? edge_toggle : edge_state; diff --git a/fpga-xc2s30/lo_passthru.v b/fpga/lo_passthru.v similarity index 82% rename from fpga-xc2s30/lo_passthru.v rename to fpga/lo_passthru.v index 52e56d4c5c..a5ae1d4e27 100644 --- a/fpga-xc2s30/lo_passthru.v +++ b/fpga/lo_passthru.v @@ -17,27 +17,32 @@ // For reading TI tags, we need to place the FPGA in pass through mode // and pass everything through to the ARM - module lo_passthru( input pck_divclk, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - output adc_clk, - output ssp_din, input ssp_dout, input cross_lo, - output dbg + input ssp_dout, + + output ssp_din, + output adc_clk, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4, + output debug ); // the antenna is modulated when ssp_dout = 1, when 0 the // antenna drivers stop modulating and go into listen mode -assign pwr_oe3 = 1'b0; +assign ssp_din = cross_lo; +assign adc_clk = 1'b0; +assign pwr_lo = pck_divclk && ssp_dout; +assign pwr_hi = 1'b0; assign pwr_oe1 = ssp_dout; assign pwr_oe2 = ssp_dout; +assign pwr_oe3 = 1'b0; assign pwr_oe4 = ssp_dout; -assign pwr_lo = pck_divclk && ssp_dout; -assign pwr_hi = 1'b0; -assign adc_clk = 1'b0; -assign ssp_din = cross_lo; -assign dbg = cross_lo; +assign debug = cross_lo; endmodule diff --git a/fpga-xc2s30/lo_read.v b/fpga/lo_read.v similarity index 80% rename from fpga-xc2s30/lo_read.v rename to fpga/lo_read.v index a7e4816546..06bd0ae5a3 100644 --- a/fpga-xc2s30/lo_read.v +++ b/fpga/lo_read.v @@ -22,13 +22,23 @@ //----------------------------------------------------------------------------- module lo_read( - input pck0, input [7:0] pck_cnt, input pck_divclk, - output pwr_lo, output pwr_hi, - output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, - input [7:0] adc_d, output adc_clk, - output ssp_frame, output ssp_din, output ssp_clk, - output dbg, - input lf_field + input pck0, + input pck_divclk, + input [7:0] pck_cnt, + input [7:0] adc_d, + input lf_field, + + output ssp_din, + output ssp_frame, + output ssp_clk, + output adc_clk, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4, + output debug ); reg [7:0] to_arm_shiftreg; @@ -43,13 +53,9 @@ always @(posedge pck0) begin if((pck_cnt == 8'd7) && !pck_divclk) to_arm_shiftreg <= adc_d; - else begin + else + begin to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; - // simulation showed a glitch occurring due to the LSB of the shifter - // not being set as we shift bits out - // this ensures the ssp_din remains low after a transfer and suppresses - // the glitch that would occur when the last data shifted out ended in - // a 1 bit and the next data shifted out started with a 0 bit to_arm_shiftreg[0] <= 1'b0; end end @@ -74,7 +80,7 @@ assign ssp_clk = pck0; // SSP frame is gated by ant_lo and goes high when pck_divider=8..15 assign ssp_frame = (pck_cnt[7:3] == 5'd1) && !pck_divclk; // unused signals tied low -assign pwr_hi = 1'b0; +assign pwr_hi = 1'b0; assign pwr_oe1 = 1'b0; assign pwr_oe2 = 1'b0; assign pwr_oe3 = 1'b0; @@ -84,5 +90,5 @@ assign pwr_lo = lf_field & pck_divclk; // ADC clock out of phase with antenna driver assign adc_clk = ~pck_divclk; // ADC clock also routed to debug pin -assign dbg = adc_clk; +assign debug = adc_clk; endmodule diff --git a/fpga-xc2s30/lo_simulate.v b/fpga/lo_simulate.v similarity index 79% rename from fpga-xc2s30/lo_simulate.v rename to fpga/lo_simulate.v index 89b548c733..c3f819cd72 100644 --- a/fpga-xc2s30/lo_simulate.v +++ b/fpga/lo_simulate.v @@ -22,23 +22,27 @@ //----------------------------------------------------------------------------- module lo_simulate( - pck0, ck_1356meg, ck_1356megb, - pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, - adc_d, adc_clk, - ssp_frame, ssp_din, ssp_dout, ssp_clk, - cross_hi, cross_lo, - dbg, - divisor + input pck0, + input ck_1356meg, + input ck_1356megb, + input [7:0] adc_d, + input [7:0] divisor, + input cross_hi, + input cross_lo, + input ssp_dout, + + output ssp_din, + output ssp_frame, + output ssp_clk, + output adc_clk, + output pwr_lo, + output pwr_hi, + output pwr_oe1, + output pwr_oe2, + output pwr_oe3, + output pwr_oe4, + output debug ); - input pck0, ck_1356meg, ck_1356megb; - output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; - input [7:0] adc_d; - output adc_clk; - input ssp_dout; - output ssp_frame, ssp_din, ssp_clk; - input cross_hi, cross_lo; - output dbg; - input [7:0] divisor; // No logic, straight through. assign pwr_oe3 = 1'b0; @@ -46,9 +50,9 @@ assign pwr_oe1 = ssp_dout; assign pwr_oe2 = ssp_dout; assign pwr_oe4 = ssp_dout; assign ssp_clk = cross_lo; -assign pwr_lo = 1'b0; -assign pwr_hi = 1'b0; -assign dbg = ssp_frame; +assign pwr_lo = 1'b0; +assign pwr_hi = 1'b0; +assign debug = ssp_frame; // Divide the clock to be used for the ADC reg [7:0] pck_divider; diff --git a/fpga-xc2s30/lp20khz_1MSa_iir_filter.v b/fpga/lp20khz_1MSa_iir_filter.v similarity index 96% rename from fpga-xc2s30/lp20khz_1MSa_iir_filter.v rename to fpga/lp20khz_1MSa_iir_filter.v index 8bc6cca4f4..d4a16cde10 100644 --- a/fpga-xc2s30/lp20khz_1MSa_iir_filter.v +++ b/fpga/lp20khz_1MSa_iir_filter.v @@ -36,7 +36,12 @@ // See details about its design see // https://fail0verflow.com/blog/2014/proxmark3-fpga-iir-filter.html -module lp20khz_1MSa_iir_filter(input clk, input [7:0] adc_d, output rdy, output [7:0] out); +module lp20khz_1MSa_iir_filter( + input clk, + input [7:0] adc_d, + output rdy, + output [7:0] out +); // clk is 24MHz, the IIR filter is designed for 1MS/s // hence we need to divide it by 24 diff --git a/fpga-xc2s30/min_max_tracker.v b/fpga/min_max_tracker.v similarity index 95% rename from fpga-xc2s30/min_max_tracker.v rename to fpga/min_max_tracker.v index 210d3c6668..2f6e06017b 100644 --- a/fpga-xc2s30/min_max_tracker.v +++ b/fpga/min_max_tracker.v @@ -23,8 +23,13 @@ // This algorithm therefore can't be used directly for realtime peak detections, // but it can be used as a simple envelope follower. -module min_max_tracker(input clk, input [7:0] adc_d, input [7:0] threshold, - output [7:0] min, output [7:0] max); +module min_max_tracker( + input clk, + input [7:0] adc_d, + input [7:0] threshold, + output [7:0] min, + output [7:0] max +); reg [7:0] min_val = 255; reg [7:0] max_val = 0; diff --git a/fpga/mux16.v b/fpga/mux16.v new file mode 100644 index 0000000000..1d97777066 --- /dev/null +++ b/fpga/mux16.v @@ -0,0 +1,50 @@ +//----------------------------------------------------------------------------- +// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See LICENSE.txt for the text of the license. +//----------------------------------------------------------------------------- +// +// General-purpose miscellany. +// + +// 16 inputs to 1 output multiplexer +module mux16( + input [3:0] sel, + output reg y, + input x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15 +); + +always @(*) +begin + // y = x[sel]; + case (sel) + 4'd0: y = x0; + 4'd1: y = x1; + 4'd2: y = x2; + 4'd3: y = x3; + 4'd4: y = x4; + 4'd5: y = x5; + 4'd6: y = x6; + 4'd7: y = x7; + 4'd8: y = x8; + 4'd9: y = x9; + 4'd10: y = x10; + 4'd11: y = x11; + 4'd12: y = x12; + 4'd13: y = x13; + 4'd14: y = x14; + 4'd15: y = x15; + endcase +end + +endmodule diff --git a/fpga-xc3s100e/mux2_onein.v b/fpga/mux2_onein.v similarity index 70% rename from fpga-xc3s100e/mux2_onein.v rename to fpga/mux2_onein.v index 86f17a553f..baefa72c8d 100644 --- a/fpga-xc3s100e/mux2_onein.v +++ b/fpga/mux2_onein.v @@ -4,13 +4,14 @@ // kombi, 2020.05 //----------------------------------------------------------------------------- -module mux2_one(sel, y, x0, x1); - input [1:0] sel; - input x0, x1; - output y; - reg y; +module mux2_one( + input [1:0] sel, + output reg y, + input x0, + input x1 +); -always @(x0 or x1 or sel) +always @(*) begin case (sel) 1'b0: y = x1; diff --git a/fpga-xc3s100e/mux2_oneout.v b/fpga/mux2_oneout.v similarity index 68% rename from fpga-xc3s100e/mux2_oneout.v rename to fpga/mux2_oneout.v index 3cbc0fd6ba..fa61205a25 100644 --- a/fpga-xc3s100e/mux2_oneout.v +++ b/fpga/mux2_oneout.v @@ -4,13 +4,14 @@ // kombi, 2020.05 //----------------------------------------------------------------------------- -module mux2_oneout(sel, y, x0, x1); - input [1:0] sel; - output x0, x1; - input y; - reg x0, x1; +module mux2_oneout( + input [1:0] sel, + input y, + output reg x0, + output reg x1 +); -always @(x0 or x1 or sel) +always @(*) begin case (sel) 1'b0: x1 = y; diff --git a/fpga-xc2s30/util.v b/fpga/mux8.v similarity index 68% rename from fpga-xc2s30/util.v rename to fpga/mux8.v index 66361ca594..d9118d243b 100644 --- a/fpga-xc2s30/util.v +++ b/fpga/mux8.v @@ -17,23 +17,25 @@ // General-purpose miscellany. // -module mux8(sel, y, x0, x1, x2, x3, x4, x5, x6, x7); - input [2:0] sel; - input x0, x1, x2, x3, x4, x5, x6, x7; - output y; - reg y; +// 8 inputs to 1 output multiplexer +module mux8( + input [2:0] sel, + output reg y, + input x0, x1, x2, x3, x4, x5, x6, x7 +); -always @(x0 or x1 or x2 or x3 or x4 or x5 or x6 or x7 or sel) +always @(*) begin + // y = x[sel]; case (sel) - 3'b000: y = x0; - 3'b001: y = x1; - 3'b010: y = x2; - 3'b011: y = x3; - 3'b100: y = x4; - 3'b101: y = x5; - 3'b110: y = x6; - 3'b111: y = x7; + 3'd0: y = x0; + 3'd1: y = x1; + 3'd2: y = x2; + 3'd3: y = x3; + 3'd4: y = x4; + 3'd5: y = x5; + 3'd6: y = x6; + 3'd7: y = x7; endcase end diff --git a/fpga-xc2s30/tests/Makefile b/fpga/tests/Makefile similarity index 100% rename from fpga-xc2s30/tests/Makefile rename to fpga/tests/Makefile diff --git a/fpga-xc2s30/tests/plot_edgedetect.py b/fpga/tests/plot_edgedetect.py old mode 100755 new mode 100644 similarity index 100% rename from fpga-xc2s30/tests/plot_edgedetect.py rename to fpga/tests/plot_edgedetect.py diff --git a/fpga-xc2s30/sim.tcl b/fpga/tests/sim.tcl similarity index 100% rename from fpga-xc2s30/sim.tcl rename to fpga/tests/sim.tcl diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.filtered.gold b/fpga/tests/tb_data/pcf7931_read_1MSA_data.filtered.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.filtered.gold rename to fpga/tests/tb_data/pcf7931_read_1MSA_data.filtered.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.high.gold b/fpga/tests/tb_data/pcf7931_read_1MSA_data.high.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.high.gold rename to fpga/tests/tb_data/pcf7931_read_1MSA_data.high.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.highz.gold b/fpga/tests/tb_data/pcf7931_read_1MSA_data.highz.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.highz.gold rename to fpga/tests/tb_data/pcf7931_read_1MSA_data.highz.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.in b/fpga/tests/tb_data/pcf7931_read_1MSA_data.in similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.in rename to fpga/tests/tb_data/pcf7931_read_1MSA_data.in diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.low.gold b/fpga/tests/tb_data/pcf7931_read_1MSA_data.low.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.low.gold rename to fpga/tests/tb_data/pcf7931_read_1MSA_data.low.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.lowz.gold b/fpga/tests/tb_data/pcf7931_read_1MSA_data.lowz.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.lowz.gold rename to fpga/tests/tb_data/pcf7931_read_1MSA_data.lowz.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.max.gold b/fpga/tests/tb_data/pcf7931_read_1MSA_data.max.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.max.gold rename to fpga/tests/tb_data/pcf7931_read_1MSA_data.max.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.min.gold b/fpga/tests/tb_data/pcf7931_read_1MSA_data.min.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.min.gold rename to fpga/tests/tb_data/pcf7931_read_1MSA_data.min.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.state.gold b/fpga/tests/tb_data/pcf7931_read_1MSA_data.state.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.state.gold rename to fpga/tests/tb_data/pcf7931_read_1MSA_data.state.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.time b/fpga/tests/tb_data/pcf7931_read_1MSA_data.time similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.time rename to fpga/tests/tb_data/pcf7931_read_1MSA_data.time diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.toggle.gold b/fpga/tests/tb_data/pcf7931_read_1MSA_data.toggle.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_read_1MSA_data.toggle.gold rename to fpga/tests/tb_data/pcf7931_read_1MSA_data.toggle.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.filtered.gold b/fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.filtered.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.filtered.gold rename to fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.filtered.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.high.gold b/fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.high.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.high.gold rename to fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.high.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.highz.gold b/fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.highz.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.highz.gold rename to fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.highz.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.in b/fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.in similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.in rename to fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.in diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.low.gold b/fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.low.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.low.gold rename to fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.low.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.lowz.gold b/fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.lowz.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.lowz.gold rename to fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.lowz.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.max.gold b/fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.max.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.max.gold rename to fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.max.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.min.gold b/fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.min.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.min.gold rename to fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.min.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.state.gold b/fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.state.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.state.gold rename to fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.state.gold diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.time b/fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.time similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.time rename to fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.time diff --git a/fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.toggle.gold b/fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.toggle.gold similarity index 100% rename from fpga-xc2s30/tests/tb_data/pcf7931_write1byte_1MSA_data.toggle.gold rename to fpga/tests/tb_data/pcf7931_write1byte_1MSA_data.toggle.gold diff --git a/fpga-xc2s30/tests/tb_lf_edge_detect.v b/fpga/tests/tb_lf_edge_detect.v similarity index 100% rename from fpga-xc2s30/tests/tb_lf_edge_detect.v rename to fpga/tests/tb_lf_edge_detect.v diff --git a/fpga-xc2s30/tests/tb_lp20khz_1MSa_iir_filter.v b/fpga/tests/tb_lp20khz_1MSa_iir_filter.v similarity index 100% rename from fpga-xc2s30/tests/tb_lp20khz_1MSa_iir_filter.v rename to fpga/tests/tb_lp20khz_1MSa_iir_filter.v diff --git a/fpga-xc2s30/tests/tb_min_max_tracker.v b/fpga/tests/tb_min_max_tracker.v similarity index 100% rename from fpga-xc2s30/tests/tb_min_max_tracker.v rename to fpga/tests/tb_min_max_tracker.v diff --git a/fpga-xc2s30/testbed_fpga.v b/fpga/tests/testbed_fpga.v similarity index 100% rename from fpga-xc2s30/testbed_fpga.v rename to fpga/tests/testbed_fpga.v diff --git a/fpga-xc2s30/testbed_hi_read_tx.v b/fpga/tests/testbed_hi_read_tx.v similarity index 100% rename from fpga-xc2s30/testbed_hi_read_tx.v rename to fpga/tests/testbed_hi_read_tx.v diff --git a/fpga-xc2s30/testbed_hi_simulate.v b/fpga/tests/testbed_hi_simulate.v similarity index 100% rename from fpga-xc2s30/testbed_hi_simulate.v rename to fpga/tests/testbed_hi_simulate.v diff --git a/fpga-xc2s30/testbed_lo_read.v b/fpga/tests/testbed_lo_read.v similarity index 100% rename from fpga-xc2s30/testbed_lo_read.v rename to fpga/tests/testbed_lo_read.v diff --git a/fpga-xc2s30/testbed_lo_simulate.v b/fpga/tests/testbed_lo_simulate.v similarity index 100% rename from fpga-xc2s30/testbed_lo_simulate.v rename to fpga/tests/testbed_lo_simulate.v diff --git a/fpga/xc2s30-5-vq100.ucf b/fpga/xc2s30-5-vq100.ucf new file mode 100644 index 0000000000..e42ce0d88d --- /dev/null +++ b/fpga/xc2s30-5-vq100.ucf @@ -0,0 +1,45 @@ +# See the schematic for the pin assignment. + +NET "adc_d<0>" LOC = "P62" ; +NET "adc_d<1>" LOC = "P60" ; +NET "adc_d<2>" LOC = "P58" ; +NET "adc_d<3>" LOC = "P57" ; +NET "adc_d<4>" LOC = "P56" ; +NET "adc_d<5>" LOC = "P55" ; +NET "adc_d<6>" LOC = "P54" ; +NET "adc_d<7>" LOC = "P53" ; +#NET "cross_hi" LOC = "P88" ; +#NET "miso" LOC = "P40" ; +NET "adc_clk" LOC = "P46" ; +NET "adc_noe" LOC = "P47" ; +NET "ck_1356meg" LOC = "P91" ; +NET "ck_1356megb" LOC = "P93" ; +NET "cross_lo" LOC = "P87" ; +NET "dbg" LOC = "P22" ; +NET "mosi" LOC = "P43" ; +NET "ncs" LOC = "P44" ; +NET "pck0" LOC = "P36" ; +NET "pwr_hi" LOC = "P80" ; +NET "pwr_lo" LOC = "P81" ; +NET "pwr_oe1" LOC = "P82" ; +NET "pwr_oe2" LOC = "P83" ; +NET "pwr_oe3" LOC = "P84" ; +NET "pwr_oe4" LOC = "P86" ; +NET "spck" LOC = "P39" ; +NET "ssp_clk" LOC = "P71" ; +NET "ssp_din" LOC = "P32" ; +NET "ssp_dout" LOC = "P34" ; +NET "ssp_frame" LOC = "P31" ; + +# definition of Clock nets: +NET "ck_1356meg" TNM_NET = "clk_net_1356" ; +NET "ck_1356megb" TNM_NET = "clk_net_1356b"; +NET "pck0" TNM_NET = "clk_net_pck0" ; +NET "spck" TNM_NET = "clk_net_spck" ; + +# Timing specs of clock nets: +TIMEGRP "clk_net_1356_all" = "clk_net_1356" "clk_net_1356b" ; +TIMESPEC "TS_1356MHz" = PERIOD "clk_net_1356_all" 74 ns HIGH 37 ns ; +TIMESPEC "TS_24MHz" = PERIOD "clk_net_pck0" 42 ns HIGH 21 ns ; +TIMESPEC "TS_4MHz" = PERIOD "clk_net_spck" 250 ns HIGH 125 ns ; + diff --git a/fpga/xc3s100e-4-vq100.ucf b/fpga/xc3s100e-4-vq100.ucf new file mode 100644 index 0000000000..b259af2ed6 --- /dev/null +++ b/fpga/xc3s100e-4-vq100.ucf @@ -0,0 +1,48 @@ +# See the schematic for the pin assignment. + +NET "adc_d<0>" LOC = "P79" ; +NET "adc_d<1>" LOC = "P78" ; +NET "adc_d<2>" LOC = "P71" ; +NET "adc_d<3>" LOC = "P70" ; +NET "adc_d<4>" LOC = "P69" ; +NET "adc_d<5>" LOC = "P68" ; +NET "adc_d<6>" LOC = "P67" ; +NET "adc_d<7>" LOC = "P66" ; +#NET "cross_hi" LOC = "P88" ; +#NET "miso" LOC = "P40" ; +NET "adc_clk" LOC = "P65" ; +NET "adc_noe" LOC = "P62" ; +NET "ck_1356meg" LOC = "P88" ; +NET "ck_1356megb" LOC = "P89" ; +NET "cross_lo" LOC = "P90" ; +NET "dbg" LOC = "P22" ; +NET "mosi" LOC = "P43" ; +NET "ncs" LOC = "P40" ; +NET "pck0" LOC = "P36" ; +NET "pwr_hi" LOC = "P85" ; +NET "pwr_lo" LOC = "P83" ; +NET "pwr_oe1" LOC = "P84" ; +NET "pwr_oe2" LOC = "P91" ; +NET "pwr_oe3" LOC = "P92" ; +NET "pwr_oe4" LOC = "P86" ; +NET "spck" LOC = "P39" ; +NET "ssp_clk" LOC = "P33" ; +NET "ssp_din" LOC = "P32" ; +NET "ssp_dout" LOC = "P34" ; +NET "ssp_frame" LOC = "P27" ; +NET "FPGA_SWITCH" LOC = "P38" ; +NET "PWR_LO_EN" LOC = "P94" ; + +# definition of Clock nets: +NET "ck_1356meg" TNM_NET = "clk_net_1356" ; +NET "ck_1356megb" TNM_NET = "clk_net_1356b"; +NET "pck0" TNM_NET = "clk_net_pck0" ; +NET "spck" TNM_NET = "clk_net_spck" ; +NET "FPGA_SWITCH" CLOCK_DEDICATED_ROUTE = FALSE ; + +# Timing specs of clock nets: +TIMEGRP "clk_net_1356_all" = "clk_net_1356" "clk_net_1356b" ; +TIMESPEC "TS_1356MHz" = PERIOD "clk_net_1356_all" 74 ns HIGH 37 ns ; +TIMESPEC "TS_24MHz" = PERIOD "clk_net_pck0" 42 ns HIGH 21 ns ; +TIMESPEC "TS_4MHz" = PERIOD "clk_net_spck" 250 ns HIGH 125 ns ; + diff --git a/tools/fpga_compress/fpga_compress.c b/tools/fpga_compress/fpga_compress.c index 58b3a21626..0a66142ac8 100644 --- a/tools/fpga_compress/fpga_compress.c +++ b/tools/fpga_compress/fpga_compress.c @@ -282,7 +282,8 @@ static int bitparse_find_section(FILE *infile, char section_name, unsigned int * /* Four byte length field */ for (int i = 0; i < 4; i++) { tmp = fgetc(infile); - if (tmp < 0) { + /* image length sanity check, should be under 300KB */ + if ( (tmp < 0) || (tmp > 300*1024) ) { break; } current_length += tmp << (24 - (i * 8)); @@ -292,7 +293,8 @@ static int bitparse_find_section(FILE *infile, char section_name, unsigned int * default: /* Fall through, two byte length field */ for (int i = 0; i < 2; i++) { tmp = fgetc(infile); - if (tmp < 0) { + /* if name, date or time fields are too long, we probably shouldn't parse them */ + if ( (tmp < 0) || (tmp > 64) ){ break; } current_length += tmp << (8 - (i * 8)); @@ -334,14 +336,16 @@ static int FpgaGatherVersion(FILE *infile, char *infile_name, char *dst, int len } } - if (!memcmp("fpga_lf", basename(infile_name), 7)) - strncat(dst, "LF", len - strlen(dst) - 1); - else if (!memcmp("fpga_hf_15", basename(infile_name), 10)) - strncat(dst, "HF 15", len - strlen(dst) - 1); - else if (!memcmp("fpga_hf.", basename(infile_name), 8)) - strncat(dst, "HF", len - strlen(dst) - 1); - else if (!memcmp("fpga_felica", basename(infile_name), 7)) - strncat(dst, "HF FeliCa", len - strlen(dst) - 1); + if (bitparse_find_section(infile, 'a', &fpga_info_len)) { + for (uint32_t i = 0; i < fpga_info_len; i++) { + char c = (char)fgetc(infile); + if (i < sizeof(tempstr)) { + tempstr[i] = c; + } + } + + strncat(dst, tempstr, len - strlen(dst) - 1); + } strncat(dst, " image ", len - strlen(dst) - 1); if (bitparse_find_section(infile, 'b', &fpga_info_len)) {