mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-07-06 04:51:36 -07:00
Unified fpga folders
This commit is contained in:
parent
1107c214c5
commit
c59bdec4f2
114 changed files with 1852 additions and 4814 deletions
12
.gitignore
vendored
12
.gitignore
vendored
|
@ -80,17 +80,7 @@ tools/mfd_aes_brute/mfd_aes_brute
|
||||||
tools/mfd_aes_brute/mfd_multi_brute
|
tools/mfd_aes_brute/mfd_multi_brute
|
||||||
tools/mfd_aes_brute/brute_key
|
tools/mfd_aes_brute/brute_key
|
||||||
|
|
||||||
fpga/*
|
fpga/__build*
|
||||||
!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
|
|
||||||
|
|
||||||
# offcial dumps folder
|
# offcial dumps folder
|
||||||
dumps/*
|
dumps/*
|
||||||
|
|
|
@ -103,9 +103,6 @@ endif
|
||||||
# Generic standalone Mode injection of source code
|
# Generic standalone Mode injection of source code
|
||||||
include Standalone/Makefile.inc
|
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
|
#the lz4 source files required for decompressing the fpga config at run time
|
||||||
SRC_LZ4 = lz4.c
|
SRC_LZ4 = lz4.c
|
||||||
#additional defines required to compile lz4
|
#additional defines required to compile lz4
|
||||||
|
|
|
@ -404,16 +404,22 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
|
||||||
/* Four byte length field */
|
/* 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) << 24;
|
||||||
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16;
|
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16;
|
||||||
numbytes += 2;
|
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
|
||||||
default: /* Fall through, two byte length field */
|
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) << 8;
|
||||||
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
|
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
|
||||||
numbytes += 2;
|
numbytes += 2;
|
||||||
}
|
if (current_length > 64) {
|
||||||
|
/* if text field is too long, keep it but truncate it */
|
||||||
if (current_name != 'e' && current_length > 255) {
|
current_length = 64;
|
||||||
/* Maybe a parse error */
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_name == section_name) {
|
if (current_name == section_name) {
|
||||||
|
|
|
@ -44,7 +44,7 @@ OBJDIR = obj
|
||||||
INCLUDE = -I../include -I../common_arm -I../common_fpga -I../common -I.
|
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
|
# 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
|
INCLUDES = ../include/proxmark3_arm.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/pm3_cmd.h
|
||||||
|
|
||||||
|
|
|
@ -92,18 +92,26 @@ PLTNAME = Unknown Platform
|
||||||
PLATFORM_FPGA = fpga-undefined
|
PLATFORM_FPGA = fpga-undefined
|
||||||
|
|
||||||
ifeq ($(PLATFORM),PM3RDV4)
|
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
|
PLATFORM_DEFS = -DWITH_SMARTCARD -DWITH_FLASH -DRDV4
|
||||||
PLTNAME = Proxmark3 RDV4
|
PLTNAME = Proxmark3 RDV4
|
||||||
PLATFORM_FPGA = xc2s30
|
PLATFORM_FPGA = xc2s30
|
||||||
RDV4 = yes
|
RDV4 = yes
|
||||||
else ifeq ($(PLATFORM),PM3OTHER)
|
else ifeq ($(PLATFORM),PM3OTHER)
|
||||||
$(warning PLATFORM=PM3OTHER is deprecated, please use PLATFORM=PM3GENERIC)
|
$(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
|
PLTNAME = Proxmark3 generic target
|
||||||
PLATFORM_FPGA = xc2s30
|
PLATFORM_FPGA = xc2s30
|
||||||
else ifeq ($(PLATFORM),PM3GENERIC)
|
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
|
PLTNAME = Proxmark3 generic target
|
||||||
PLATFORM_FPGA = xc2s30
|
PLATFORM_FPGA = xc2s30
|
||||||
else ifeq ($(PLATFORM),PM3ICOPYX)
|
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
|
PLATFORM_DEFS = -DWITH_FLASH -DICOPYX -DXC3
|
||||||
PLTNAME = iCopy-X with XC3S100E
|
PLTNAME = iCopy-X with XC3S100E
|
||||||
PLATFORM_FPGA = xc3s100e
|
PLATFORM_FPGA = xc3s100e
|
||||||
|
@ -246,6 +254,7 @@ export PLATFORM_DEFS
|
||||||
export PLATFORM_DEFS_INFO
|
export PLATFORM_DEFS_INFO
|
||||||
export PLATFORM_DEFS_INFO_STANDALONE
|
export PLATFORM_DEFS_INFO_STANDALONE
|
||||||
export PLATFORM_CHANGED
|
export PLATFORM_CHANGED
|
||||||
|
export FPGA_BITSTREAMS
|
||||||
|
|
||||||
$(info ===================================================================)
|
$(info ===================================================================)
|
||||||
$(info Version info: $(shell tools/mkversion.sh --short 2>/dev/null || ../tools/mkversion.sh --short 2>/dev/null))
|
$(info Version info: $(shell tools/mkversion.sh --short 2>/dev/null || ../tools/mkversion.sh --short 2>/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
|
|
||||||
|
|
|
@ -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 ;
|
|
||||||
|
|
Binary file not shown.
|
@ -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
|
|
Binary file not shown.
|
@ -1,255 +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_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 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 x
|
|
||||||
sub | 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
|
|
Binary file not shown.
|
@ -1,233 +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.
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// 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_HF_FSK_READER 6
|
|
||||||
`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
|
|
||||||
`define FPGA_HF_READER_2SUBCARRIERS_424_484_KHZ 3
|
|
||||||
|
|
||||||
`define FPGA_HF_FSK_READER_OUTPUT_1695_KHZ 0
|
|
||||||
`define FPGA_HF_FSK_READER_OUTPUT_848_KHZ 1
|
|
||||||
`define FPGA_HF_FSK_READER_OUTPUT_424_KHZ 2
|
|
||||||
`define FPGA_HF_FSK_READER_OUTPUT_212_KHZ 3
|
|
||||||
|
|
||||||
`define FPGA_HF_FSK_READER_NOPOWER 0
|
|
||||||
`define FPGA_HF_FSK_READER_WITHPOWER 1
|
|
||||||
|
|
||||||
// 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_15.v"
|
|
||||||
`include "hi_simulate.v"
|
|
||||||
`include "hi_sniffer.v"
|
|
||||||
`include "util.v"
|
|
||||||
`include "hi_get_trace.v"
|
|
||||||
|
|
||||||
module fpga_hf_15(
|
|
||||||
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 x
|
|
||||||
sub | 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 15 reader
|
|
||||||
hi_15_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
|
|
||||||
);
|
|
||||||
|
|
||||||
// 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 15 reader; subcarrier frequency and modulation depth selectable
|
|
||||||
// 001 -- HF simulated tag
|
|
||||||
// 010 --
|
|
||||||
// 011 -- HF sniff
|
|
||||||
// 100 --
|
|
||||||
// 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, 1'b0, 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, 1'b0, 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, 1'b0, 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, 1'b0, 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, 1'b0, 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, 1'b0, 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, 1'b0, 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, 1'b0, 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, 1'b0, 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, 1'b0, 1'b0, 1'b0, 1'b0);
|
|
||||||
mux8 mux_dbg (major_mode, dbg, hr_dbg, hs_dbg, 1'b0, he_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
|
|
Binary file not shown.
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
68
fpga-xc3s100e/.gitignore
vendored
68
fpga-xc3s100e/.gitignore
vendored
|
@ -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/
|
|
|
@ -1,25 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2014 iZsh <izsh at fail0verflow.com>
|
|
||||||
//
|
|
||||||
// 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
|
|
||||||
|
|
|
@ -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 .
|
|
||||||
)
|
|
|
@ -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
|
|
|
@ -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
|
|
Binary file not shown.
|
@ -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 <izsh at fail0verflow.com>, 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
|
|
|
@ -1,236 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Jonathan Westhues, March 2006
|
|
||||||
// iZsh <izsh at fail0verflow.com>, 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
|
|
|
@ -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<curminthres) //falling edge
|
|
||||||
begin
|
|
||||||
case (state)
|
|
||||||
0: begin
|
|
||||||
curmin <= adc_d<`imin? adc_d :`imin;
|
|
||||||
state <= 1;
|
|
||||||
end
|
|
||||||
1: begin
|
|
||||||
if (adc_d<curmin)
|
|
||||||
curmin <= adc_d;
|
|
||||||
end
|
|
||||||
2: begin
|
|
||||||
curminthres <= ( (curmin >> 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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
|
@ -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
|
|
Binary file not shown.
|
@ -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 <options>"
|
|
||||||
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/<language>/<simulator>"
|
|
||||||
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."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,77 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2014 iZsh <izsh at fail0verflow.com>
|
|
||||||
//
|
|
||||||
// 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
|
|
|
@ -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
|
|
|
@ -1,70 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2014 iZsh <izsh at fail0verflow.com>
|
|
||||||
//
|
|
||||||
// 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
|
|
||||||
|
|
|
@ -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 <izsh at fail0verflow.com>, 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
|
|
|
@ -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 <izsh at fail0verflow.com>, 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
|
|
|
@ -1,81 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2014 iZsh <izsh at fail0verflow.com>
|
|
||||||
//
|
|
||||||
// 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
|
|
|
@ -1,65 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Copyright (C) 2014 iZsh <izsh at fail0verflow.com>
|
|
||||||
//
|
|
||||||
// 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
|
|
|
@ -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
|
|
221
fpga/Makefile
Normal file
221
fpga/Makefile
Normal file
|
@ -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 "# <target> - 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 "################################################################"
|
||||||
|
|
|
@ -14,7 +14,12 @@
|
||||||
// See LICENSE.txt for the text of the license.
|
// 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 [7:0] div_cnt_ = 0;
|
||||||
reg div_clk_;
|
reg div_clk_;
|
155
fpga/define.v
Normal file
155
fpga/define.v
Normal file
|
@ -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
|
BIN
fpga/fpga_icopyx_hf.bit
Normal file
BIN
fpga/fpga_icopyx_hf.bit
Normal file
Binary file not shown.
227
fpga/fpga_icopyx_hf.v
Normal file
227
fpga/fpga_icopyx_hf.v
Normal file
|
@ -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
|
0
fpga/fpga_icopyx_lf.bit
Normal file
0
fpga/fpga_icopyx_lf.bit
Normal file
218
fpga/fpga_icopyx_lf.v
Normal file
218
fpga/fpga_icopyx_lf.v
Normal file
|
@ -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
|
|
@ -1,37 +1,61 @@
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
//-----------------------------------------------------------------------------
|
||||||
// Company:
|
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
||||||
// Engineer:
|
|
||||||
//
|
//
|
||||||
// Create Date: 16:09:14 05/13/2020
|
// This program is free software: you can redistribute it and/or modify
|
||||||
// Design Name:
|
// it under the terms of the GNU General Public License as published by
|
||||||
// Module Name: fpga_all_in_one
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
// Project Name:
|
// (at your option) any later version.
|
||||||
// Target Devices:
|
|
||||||
// Tool versions:
|
|
||||||
// Description:
|
|
||||||
//
|
//
|
||||||
// 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:
|
// See LICENSE.txt for the text of the license.
|
||||||
// Revision 0.01 - File Created
|
//-----------------------------------------------------------------------------
|
||||||
// Additional Comments:
|
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////////////////////////
|
// The FPGA is responsible for interfacing between the A/D, the coil drivers,
|
||||||
module fpga_hf(
|
// and the ARM. In the low-frequency modes it passes the data straight
|
||||||
input spck, output miso, input mosi, input ncs,
|
// through, so that the ARM gets raw A/D samples over the SSP. In the high-
|
||||||
input pck0, input ck_1356meg, input ck_1356megb,
|
// frequency modes, the FPGA might perform some demodulation first, to
|
||||||
output pwr_lo, output pwr_hi,
|
// reduce the amount of data that we must send to the ARM.
|
||||||
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
|
//-----------------------------------------------------------------------------
|
||||||
input [7:0] adc_d, output adc_clk, output adc_noe,
|
//`include "fpga_lf.v"
|
||||||
output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk,
|
//`include "fpga_hf.v"
|
||||||
input cross_hi, input cross_lo,
|
//`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 dbg,
|
||||||
output PWR_LO_EN,
|
output PWR_LO_EN,
|
||||||
input FPGA_SWITCH
|
input FPGA_SWITCH
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
fpga_hfmod hfmod(
|
fpga_hf hfmod(
|
||||||
hfspck, hfmiso, hfmosi, hfncs,
|
hfspck, hfmiso, hfmosi, hfncs,
|
||||||
hfpck0, hfck_1356meg, hfck_1356megb,
|
hfpck0, hfck_1356meg, hfck_1356megb,
|
||||||
hfpwr_lo, hfpwr_hi,
|
hfpwr_lo, hfpwr_hi,
|
||||||
|
@ -39,10 +63,10 @@ fpga_hfmod hfmod(
|
||||||
adc_d, hfadc_clk, hfadc_noe,
|
adc_d, hfadc_clk, hfadc_noe,
|
||||||
hfssp_frame, hfssp_din, hfssp_dout, hfssp_clk,
|
hfssp_frame, hfssp_din, hfssp_dout, hfssp_clk,
|
||||||
hfcross_hi, hfcross_lo,
|
hfcross_hi, hfcross_lo,
|
||||||
hfdbg
|
hfdebug
|
||||||
);
|
);
|
||||||
|
|
||||||
fpga_lfmod lfmod(
|
fpga_lf lfmod(
|
||||||
lfspck, lfmiso, lfmosi, lfncs,
|
lfspck, lfmiso, lfmosi, lfncs,
|
||||||
lfpck0, lfck_1356meg, lfck_1356megb,
|
lfpck0, lfck_1356meg, lfck_1356megb,
|
||||||
lfpwr_lo, lfpwr_hi,
|
lfpwr_lo, lfpwr_hi,
|
||||||
|
@ -50,7 +74,7 @@ fpga_lfmod lfmod(
|
||||||
adc_d, lfadc_clk, lfadc_noe,
|
adc_d, lfadc_clk, lfadc_noe,
|
||||||
lfssp_frame, lfssp_din, lfssp_dout, lfssp_clk,
|
lfssp_frame, lfssp_din, lfssp_dout, lfssp_clk,
|
||||||
lfcross_hi, lfcross_lo,
|
lfcross_hi, lfcross_lo,
|
||||||
lfdbg,
|
lfdebug,
|
||||||
lfPWR_LO_EN
|
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_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_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_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);
|
mux2_one mux_PWR_LO_EN_all (FPGA_SWITCH, PWR_LO_EN, 1'b0, lfPWR_LO_EN);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
BIN
fpga/fpga_pm3_felica.bit
Normal file
BIN
fpga/fpga_pm3_felica.bit
Normal file
Binary file not shown.
BIN
fpga/fpga_pm3_hf.bit
Normal file
BIN
fpga/fpga_pm3_hf.bit
Normal file
Binary file not shown.
BIN
fpga/fpga_pm3_hf_15.bit
Normal file
BIN
fpga/fpga_pm3_hf_15.bit
Normal file
Binary file not shown.
BIN
fpga/fpga_pm3_lf.bit
Normal file
BIN
fpga/fpga_pm3_lf.bit
Normal file
Binary file not shown.
438
fpga/fpga_pm3_top.v
Normal file
438
fpga/fpga_pm3_top.v
Normal file
|
@ -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
|
|
@ -30,33 +30,30 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module hi_flite(
|
module hi_flite(
|
||||||
ck_1356meg,
|
input ck_1356meg,
|
||||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
input [7:0] adc_d,
|
||||||
adc_d, adc_clk,
|
input [3:0] mod_type,
|
||||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
input ssp_dout,
|
||||||
dbg,
|
|
||||||
mod_type
|
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;
|
assign debug = 0;
|
||||||
|
|
||||||
wire power = mod_type[2];
|
wire power = mod_type[2];
|
||||||
wire speed = mod_type[1];
|
wire speed = mod_type[1];
|
||||||
wire disabl = mod_type[0];
|
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;
|
|
||||||
|
|
||||||
// 512x64/fc -wait before ts0, 32768 ticks
|
// 512x64/fc -wait before ts0, 32768 ticks
|
||||||
// tslot: 256*64/fc
|
// tslot: 256*64/fc
|
||||||
assign adc_clk = ck_1356meg;
|
assign adc_clk = ck_1356meg;
|
||||||
|
@ -95,10 +92,6 @@ reg did_sync=0;
|
||||||
wire [7:0] bithalf = speed ? `bithalf_424 : `bithalf_212;
|
wire [7:0] bithalf = speed ? `bithalf_424 : `bithalf_212;
|
||||||
wire [7:0] bitmlen = speed ? `bitmlen_424 : `bitmlen_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 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] 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
|
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
|
//ssp counter for transfer and framing
|
||||||
reg [8:0] ssp_cnt = 9'd0;
|
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)))
|
if( ((~speed) && (ssp_cnt[5:0] == 6'b000000)) || (speed && (ssp_cnt[4:0] == 5'b00000)))
|
||||||
begin
|
begin
|
||||||
ssp_clk <= 1'b1;
|
ssp_clk <= 1'b1;
|
||||||
|
//send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise)
|
||||||
ssp_din <= curbit;
|
ssp_din <= curbit;
|
||||||
end
|
end
|
||||||
if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000))
|
if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000))
|
||||||
|
@ -138,9 +133,6 @@ begin
|
||||||
end
|
end
|
||||||
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
|
//previous signal value, mostly to detect SYNC
|
||||||
reg prv = 1'b1;
|
reg prv = 1'b1;
|
||||||
|
|
||||||
|
@ -353,11 +345,8 @@ begin
|
||||||
end
|
end
|
||||||
// sending <= 0;
|
// sending <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
//put modulation here to maintain the correct clock. Seems that some readers are sensitive to that
|
//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);
|
wire mod = ((fccount >= bithalf) ^ dlay) & (~disabl);
|
||||||
|
|
||||||
|
@ -365,21 +354,22 @@ always @(ck_1356meg or ssp_dout or power or disabl or mod)
|
||||||
begin
|
begin
|
||||||
if (power)
|
if (power)
|
||||||
begin
|
begin
|
||||||
pwr_hi <= ck_1356meg;
|
pwr_hi <= ck_1356meg;
|
||||||
|
pwr_lo <= 1'b0;
|
||||||
pwr_oe1 <= 1'b0;//mod;
|
pwr_oe1 <= 1'b0;//mod;
|
||||||
|
pwr_oe2 <= 1'b0;//mod;
|
||||||
pwr_oe3 <= 1'b0;//mod;
|
pwr_oe3 <= 1'b0;//mod;
|
||||||
pwr_oe4 <= mod;//1'b0;
|
pwr_oe4 <= mod;//1'b0;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
pwr_hi <= 1'b0;
|
pwr_hi <= 1'b0;
|
||||||
|
pwr_lo <= 1'b0;
|
||||||
pwr_oe1 <= 1'b0;
|
pwr_oe1 <= 1'b0;
|
||||||
|
pwr_oe2 <= 1'b0;
|
||||||
pwr_oe3 <= 1'b0;
|
pwr_oe3 <= 1'b0;
|
||||||
pwr_oe4 <= mod;
|
pwr_oe4 <= mod;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
|
@ -13,17 +13,18 @@
|
||||||
//
|
//
|
||||||
// See LICENSE.txt for the text of the license.
|
// See LICENSE.txt for the text of the license.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
//`include "define.v"
|
||||||
|
|
||||||
module hi_get_trace(
|
module hi_get_trace(
|
||||||
ck_1356megb,
|
input ck_1356megb,
|
||||||
adc_d, trace_enable, major_mode,
|
input [7:0] adc_d,
|
||||||
ssp_frame, ssp_din, ssp_clk
|
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
|
// clock divider
|
||||||
reg [6:0] clock_cnt;
|
reg [6:0] clock_cnt;
|
||||||
|
@ -88,9 +89,9 @@ begin
|
||||||
write_enable2 <= 1'b0;
|
write_enable2 <= 1'b0;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
addr <= addr + 1;
|
addr <= addr + 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -136,9 +137,6 @@ begin
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// SSC communication to ARM
|
|
||||||
reg ssp_clk;
|
|
||||||
reg ssp_frame;
|
|
||||||
reg [7:0] shift_out;
|
reg [7:0] shift_out;
|
||||||
|
|
||||||
always @(negedge ck_1356megb)
|
always @(negedge ck_1356megb)
|
||||||
|
@ -147,16 +145,16 @@ begin
|
||||||
begin
|
begin
|
||||||
if (clock_cnt[6:4] == 3'd0) // either load new value
|
if (clock_cnt[6:4] == 3'd0) // either load new value
|
||||||
begin
|
begin
|
||||||
if (addr[11] == 1'b0)
|
if (addr[11] == 1'b0)
|
||||||
shift_out <= D_out1;
|
shift_out <= D_out1;
|
||||||
else
|
else
|
||||||
shift_out <= D_out2;
|
shift_out <= D_out2;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
// or shift left
|
// or shift left
|
||||||
shift_out[7:1] <= shift_out[6:0];
|
shift_out[7:1] <= shift_out[6:0];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
ssp_clk <= ~clock_cnt[3]; // ssp_clk frequency = 13,56MHz / 16 = 847,5 kHz
|
ssp_clk <= ~clock_cnt[3]; // ssp_clk frequency = 13,56MHz / 16 = 847,5 kHz
|
|
@ -14,29 +14,28 @@
|
||||||
// See LICENSE.txt for the text of the license.
|
// See LICENSE.txt for the text of the license.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// ISO14443-A support for the Proxmark III
|
// ISO14443-A support for the Proxmark III
|
||||||
//
|
//`include "define.v"
|
||||||
|
|
||||||
module hi_iso14443a(
|
module hi_iso14443a(
|
||||||
ck_1356meg,
|
input ck_1356meg,
|
||||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
input [7:0] adc_d,
|
||||||
adc_d, adc_clk,
|
input [3:0] mod_type,
|
||||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
input ssp_dout,
|
||||||
dbg,
|
|
||||||
mod_type
|
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:
|
// Reader -> PM3:
|
||||||
|
@ -76,8 +75,6 @@ begin
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Reader -> PM3
|
// 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
|
// 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};
|
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
|
// 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.
|
// 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 signed [10:0] rx_mod_rising_edge_max;
|
||||||
reg curbit;
|
reg curbit;
|
||||||
|
|
||||||
|
`ifdef PM3ICOPYX
|
||||||
|
`define EDGE_DETECT_THRESHOLD 3
|
||||||
|
`else
|
||||||
`define EDGE_DETECT_THRESHOLD 5
|
`define EDGE_DETECT_THRESHOLD 5
|
||||||
|
`endif
|
||||||
`define EDGE_DETECT_THRESHOLDHIGH 20
|
`define EDGE_DETECT_THRESHOLDHIGH 20
|
||||||
|
|
||||||
always @(negedge adc_clk)
|
always @(negedge adc_clk)
|
||||||
|
@ -266,7 +266,6 @@ begin
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Tag+Reader -> PM3
|
// Tag+Reader -> PM3
|
||||||
// sample 4 bits reader data and 4 bits tag data for sniffing
|
// sample 4 bits reader data and 4 bits tag data for sniffing
|
||||||
|
@ -283,7 +282,6 @@ begin
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// PM3 -> Reader:
|
// PM3 -> Reader:
|
||||||
// a delay line to ensure that we send the (emulated) tag's answer at the correct time according to ISO14443-3
|
// 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
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// PM3 -> Reader, internal timing:
|
// 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.
|
// 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
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// PM3 -> Reader
|
// PM3 -> Reader
|
||||||
// determine the required delay in the mod_sig_buf (set mod_sig_ptr).
|
// determine the required delay in the mod_sig_buf (set mod_sig_ptr).
|
||||||
|
@ -444,7 +440,6 @@ begin
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// FPGA -> ARM communication:
|
// FPGA -> ARM communication:
|
||||||
// buffer 8 bits data to be sent to ARM. Shift them out bit by bit.
|
// buffer 8 bits data to be sent to ARM. Shift them out bit by bit.
|
||||||
|
@ -495,8 +490,6 @@ end
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// FPGA <-> ARM communication:
|
// FPGA <-> ARM communication:
|
||||||
// generate a ssp clock and ssp frame signal for the synchronous transfer from/to the ARM
|
// 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)
|
always @(negedge adc_clk)
|
||||||
begin
|
begin
|
||||||
|
@ -529,7 +522,6 @@ begin
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// FPGA -> ARM communication:
|
// FPGA -> ARM communication:
|
||||||
// select the data to be sent to ARM
|
// select the data to be sent to ARM
|
||||||
|
@ -553,7 +545,6 @@ begin
|
||||||
sendbit = 1'b0;
|
sendbit = 1'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
if(mod_type == `FPGA_HF_ISO14443A_SNIFFER)
|
if(mod_type == `FPGA_HF_ISO14443A_SNIFFER)
|
||||||
// send sampled reader and tag data:
|
// send sampled reader and tag data:
|
||||||
bit_to_arm = to_arm[7];
|
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_oe2 = 1'b0;
|
||||||
assign pwr_lo = 1'b0;
|
assign pwr_lo = 1'b0;
|
||||||
|
|
||||||
assign dbg = negedge_cnt[3];
|
assign debug = negedge_cnt[3];
|
||||||
|
|
||||||
endmodule
|
endmodule
|
|
@ -13,24 +13,27 @@
|
||||||
//
|
//
|
||||||
// See LICENSE.txt for the text of the license.
|
// See LICENSE.txt for the text of the license.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
//`include "define.v"
|
||||||
|
|
||||||
module hi_reader(
|
module hi_reader(
|
||||||
ck_1356meg,
|
input ck_1356meg,
|
||||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
input [7:0] adc_d,
|
||||||
adc_d, adc_clk,
|
input [1:0] subcarrier_frequency,
|
||||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
input [3:0] minor_mode,
|
||||||
dbg,
|
input ssp_dout,
|
||||||
subcarrier_frequency, minor_mode
|
|
||||||
|
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
|
assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz
|
||||||
|
|
||||||
|
@ -160,7 +163,6 @@ begin
|
||||||
end
|
end
|
||||||
else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ)
|
else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ)
|
||||||
begin
|
begin
|
||||||
|
|
||||||
// Send 7 most significant bits of in phase tag signal (signed), plus 1 bit reader signal
|
// 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)
|
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};
|
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 ...
|
// 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)
|
always @(negedge adc_clk)
|
||||||
begin
|
begin
|
||||||
if (corr_i_cnt[1:0] == 2'b00)
|
if (corr_i_cnt[1:0] == 2'b00)
|
||||||
|
@ -298,9 +297,6 @@ begin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// Antenna drivers
|
|
||||||
reg pwr_hi, pwr_oe4;
|
|
||||||
|
|
||||||
always @(*)
|
always @(*)
|
||||||
begin
|
begin
|
||||||
if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD)
|
if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD)
|
||||||
|
@ -341,6 +337,6 @@ assign pwr_lo = 1'b0;
|
||||||
assign pwr_oe2 = 1'b0;
|
assign pwr_oe2 = 1'b0;
|
||||||
|
|
||||||
// Debug Output
|
// Debug Output
|
||||||
assign dbg = corr_i_cnt[3];
|
assign debug = corr_i_cnt[3];
|
||||||
|
|
||||||
endmodule
|
endmodule
|
|
@ -14,25 +14,26 @@
|
||||||
// See LICENSE.txt for the text of the license.
|
// See LICENSE.txt for the text of the license.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// modified to add support for iso15 2sc mode
|
// modified to add support for iso15 2sc mode
|
||||||
//
|
|
||||||
|
|
||||||
module hi_15_reader(
|
module hi_reader_15(
|
||||||
ck_1356meg,
|
input ck_1356meg,
|
||||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
input [7:0] adc_d,
|
||||||
adc_d, adc_clk,
|
input [1:0] subcarrier_frequency,
|
||||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
input [3:0] minor_mode,
|
||||||
dbg,
|
input ssp_dout,
|
||||||
subcarrier_frequency, minor_mode
|
|
||||||
|
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
|
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 ...
|
// 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)
|
always @(negedge adc_clk)
|
||||||
begin
|
begin
|
||||||
if (corr_i_cnt[1:0] == 2'b00)
|
if (corr_i_cnt[1:0] == 2'b00)
|
||||||
|
@ -416,9 +414,6 @@ begin
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// Antenna drivers
|
|
||||||
reg pwr_hi, pwr_oe4;
|
|
||||||
|
|
||||||
always @(*)
|
always @(*)
|
||||||
begin
|
begin
|
||||||
if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD)
|
if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD)
|
||||||
|
@ -459,6 +454,6 @@ assign pwr_lo = 1'b0;
|
||||||
assign pwr_oe2 = 1'b0;
|
assign pwr_oe2 = 1'b0;
|
||||||
|
|
||||||
// Debug Output
|
// Debug Output
|
||||||
assign dbg = corr_i_cnt[3];
|
assign debug = corr_i_cnt[3];
|
||||||
|
|
||||||
endmodule
|
endmodule
|
|
@ -30,23 +30,26 @@
|
||||||
//
|
//
|
||||||
// Jonathan Westhues, October 2006
|
// Jonathan Westhues, October 2006
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
//`include "define.v"
|
||||||
|
|
||||||
module hi_simulate(
|
module hi_simulate(
|
||||||
ck_1356meg,
|
input ck_1356meg,
|
||||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
input [7:0] adc_d,
|
||||||
adc_d, adc_clk,
|
input [3:0] mod_type,
|
||||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
input ssp_dout,
|
||||||
dbg,
|
|
||||||
mod_type
|
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
|
// Power amp goes between LOW and tri-state, so pwr_hi (and pwr_lo) can
|
||||||
// always be low.
|
// always be low.
|
||||||
|
@ -57,7 +60,7 @@ assign pwr_lo = 1'b0; // LF antenna connected to GND
|
||||||
assign pwr_oe2 = 1'b0;
|
assign pwr_oe2 = 1'b0;
|
||||||
|
|
||||||
assign adc_clk = ck_1356meg;
|
assign adc_clk = ck_1356meg;
|
||||||
assign dbg = ssp_frame;
|
assign debug = ssp_frame;
|
||||||
|
|
||||||
// The comparator with hysteresis on the output from the peak detector.
|
// The comparator with hysteresis on the output from the peak detector.
|
||||||
reg after_hysteresis;
|
reg after_hysteresis;
|
||||||
|
@ -94,8 +97,6 @@ reg [8:0] ssp_clk_divider;
|
||||||
always @(negedge adc_clk)
|
always @(negedge adc_clk)
|
||||||
ssp_clk_divider <= (ssp_clk_divider + 1);
|
ssp_clk_divider <= (ssp_clk_divider + 1);
|
||||||
|
|
||||||
reg ssp_clk;
|
|
||||||
|
|
||||||
always @(negedge adc_clk)
|
always @(negedge adc_clk)
|
||||||
begin
|
begin
|
||||||
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT)
|
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT)
|
||||||
|
@ -112,7 +113,6 @@ end
|
||||||
|
|
||||||
// Produce the byte framing signal; the phase of this signal
|
// Produce the byte framing signal; the phase of this signal
|
||||||
// is arbitrary, because it's just a bit stream in this module.
|
// is arbitrary, because it's just a bit stream in this module.
|
||||||
reg ssp_frame;
|
|
||||||
always @(negedge adc_clk)
|
always @(negedge adc_clk)
|
||||||
begin
|
begin
|
||||||
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K)
|
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K)
|
||||||
|
@ -133,7 +133,6 @@ end
|
||||||
|
|
||||||
|
|
||||||
// Synchronize up the after-hysteresis signal, to produce DIN.
|
// Synchronize up the after-hysteresis signal, to produce DIN.
|
||||||
reg ssp_din;
|
|
||||||
always @(posedge ssp_clk)
|
always @(posedge ssp_clk)
|
||||||
ssp_din = after_hysteresis;
|
ssp_din = after_hysteresis;
|
||||||
|
|
|
@ -15,16 +15,20 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
module hi_sniffer(
|
module hi_sniffer(
|
||||||
ck_1356meg,
|
input ck_1356meg,
|
||||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
input [7:0] adc_d,
|
||||||
adc_d, adc_clk,
|
|
||||||
ssp_frame, ssp_din, ssp_clk
|
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.
|
// We are only snooping, all off.
|
||||||
assign pwr_hi = 1'b0;
|
assign pwr_hi = 1'b0;
|
||||||
|
@ -34,12 +38,13 @@ assign pwr_oe2 = 1'b0;
|
||||||
assign pwr_oe3 = 1'b0;
|
assign pwr_oe3 = 1'b0;
|
||||||
assign pwr_oe4 = 1'b0;
|
assign pwr_oe4 = 1'b0;
|
||||||
|
|
||||||
reg ssp_frame;
|
//reg ssp_frame;
|
||||||
reg [7:0] adc_d_out = 8'd0;
|
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_clk = ~ck_1356meg;
|
||||||
|
assign ssp_din = adc_d_out[0];
|
||||||
|
|
||||||
always @(posedge ssp_clk)
|
always @(posedge ssp_clk)
|
||||||
begin
|
begin
|
||||||
|
@ -49,18 +54,16 @@ begin
|
||||||
ssp_cnt <= ssp_cnt + 1;
|
ssp_cnt <= ssp_cnt + 1;
|
||||||
|
|
||||||
if(ssp_cnt[2:0] == 3'b000) // set frame length
|
if(ssp_cnt[2:0] == 3'b000) // set frame length
|
||||||
begin
|
begin
|
||||||
adc_d_out[7:0] <= adc_d;
|
adc_d_out[7:0] <= adc_d;
|
||||||
ssp_frame <= 1'b1;
|
ssp_frame <= 1'b1;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
adc_d_out[7:0] <= {1'b0, adc_d_out[7:1]};
|
// shift value right one bit
|
||||||
ssp_frame <= 1'b0;
|
adc_d_out[7:0] <= {1'b0, adc_d_out[7:1]};
|
||||||
end
|
ssp_frame <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
assign ssp_din = adc_d_out[0];
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
|
@ -15,23 +15,37 @@
|
||||||
// See LICENSE.txt for the text of the license.
|
// See LICENSE.txt for the text of the license.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
// input clk is 24MHz
|
// 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(
|
||||||
output [7:0] max, output [7:0] min,
|
input clk,
|
||||||
output [7:0] high_threshold, output [7:0] highz_threshold,
|
input [7:0] adc_d,
|
||||||
output [7:0] lowz_threshold, output [7:0] low_threshold,
|
input [7:0] lf_ed_threshold,
|
||||||
output edge_state, output edge_toggle);
|
|
||||||
|
|
||||||
min_max_tracker tracker(clk, adc_d, lf_ed_threshold, min, max);
|
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 (clk),
|
||||||
|
.adc_d (adc_d),
|
||||||
|
.threshold (lf_ed_threshold),
|
||||||
|
.min (min),
|
||||||
|
.max (max)
|
||||||
|
);
|
||||||
|
|
||||||
// auto-tune
|
// 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 highz_threshold = (max + min) / 2 + (max - min) / 8;
|
||||||
assign lowz_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 low_threshold = (max + min) / 2 - (max - min) / 4;
|
||||||
|
|
||||||
// heuristic to see if it makes sense to try to detect an edge
|
// heuristic to see if it makes sense to try to detect an edge
|
||||||
wire enabled =
|
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)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
is_high <= (adc_d >= high_threshold);
|
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));
|
is_zero <= ((adc_d > lowz_threshold) & (adc_d < highz_threshold));
|
||||||
end
|
end
|
||||||
|
|
||||||
// all edges detection
|
// all edges detection
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if (enabled) begin
|
if (enabled)
|
||||||
|
begin
|
||||||
// To enable detecting two consecutive peaks at the same level
|
// 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.
|
// (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
|
// This extra check is necessary to prevent from noise artifacts
|
||||||
// around the threshold values.
|
// around the threshold values.
|
||||||
if (trigger_enabled & (is_high | is_low)) begin
|
if (trigger_enabled & (is_high | is_low))
|
||||||
|
begin
|
||||||
output_edge <= ~output_edge;
|
output_edge <= ~output_edge;
|
||||||
trigger_enabled <= 0;
|
trigger_enabled <= 0;
|
||||||
end else
|
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
|
// edge states
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
if (enabled) begin
|
if (enabled)
|
||||||
|
begin
|
||||||
if (is_high)
|
if (is_high)
|
||||||
output_state <= 1'd1;
|
output_state <= 1'd1;
|
||||||
else if (is_low)
|
else if (is_low)
|
||||||
output_state <= 1'd0;
|
output_state <= 1'd0;
|
||||||
end
|
end
|
||||||
|
|
||||||
assign edge_state = output_state;
|
assign edge_state = output_state;
|
||||||
assign edge_toggle = output_edge;
|
assign edge_toggle = output_edge;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
|
@ -22,22 +22,24 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
module lo_adc(
|
module lo_adc(
|
||||||
pck0,
|
input pck0,
|
||||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
input [7:0] adc_d,
|
||||||
adc_d, adc_clk,
|
input [7:0] divisor,
|
||||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
input lf_field,
|
||||||
dbg, divisor,
|
input ssp_dout,
|
||||||
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
|
||||||
);
|
);
|
||||||
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] to_arm_shiftreg;
|
||||||
reg [7:0] pck_divider;
|
reg [7:0] pck_divider;
|
||||||
|
@ -49,16 +51,16 @@ wire reader_modulation = !ssp_dout & lf_field & clk_state;
|
||||||
|
|
||||||
// always on (High Frequency outputs, unused)
|
// always on (High Frequency outputs, unused)
|
||||||
assign pwr_oe1 = 1'b0;
|
assign pwr_oe1 = 1'b0;
|
||||||
assign pwr_hi = 1'b0;
|
assign pwr_hi = 1'b0;
|
||||||
|
|
||||||
// low frequency outputs
|
// low frequency outputs
|
||||||
assign pwr_lo = reader_modulation;
|
assign pwr_lo = reader_modulation;
|
||||||
assign pwr_oe2 = 1'b0; // 33 Ohms
|
assign pwr_oe2 = 1'b0; // 33 Ohms
|
||||||
assign pwr_oe3 = tag_modulation; // base antenna load = 33 Ohms
|
assign pwr_oe3 = tag_modulation; // base antenna load = 33 Ohms
|
||||||
assign pwr_oe4 = 1'b0; // 10k Ohms
|
assign pwr_oe4 = 1'b0; // 10k Ohms
|
||||||
|
|
||||||
// Debug Output ADC clock
|
// Debug Output ADC clock
|
||||||
assign dbg = adc_clk;
|
assign debug = adc_clk;
|
||||||
|
|
||||||
// ADC clock out of phase with antenna driver
|
// ADC clock out of phase with antenna driver
|
||||||
assign adc_clk = ~clk_state;
|
assign adc_clk = ~clk_state;
|
||||||
|
@ -76,10 +78,10 @@ assign ssp_frame = (pck_divider[7:3] == 5'd1) && !clk_state;
|
||||||
always @(posedge pck0)
|
always @(posedge pck0)
|
||||||
begin
|
begin
|
||||||
if (pck_divider == divisor[7:0])
|
if (pck_divider == divisor[7:0])
|
||||||
begin
|
begin
|
||||||
pck_divider <= 8'd0;
|
pck_divider <= 8'd0;
|
||||||
clk_state = !clk_state;
|
clk_state = !clk_state;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
pck_divider <= pck_divider + 1;
|
pck_divider <= pck_divider + 1;
|
||||||
|
@ -92,13 +94,9 @@ always @(posedge pck0)
|
||||||
begin
|
begin
|
||||||
if ((pck_divider == 8'd7) && !clk_state)
|
if ((pck_divider == 8'd7) && !clk_state)
|
||||||
to_arm_shiftreg <= adc_d;
|
to_arm_shiftreg <= adc_d;
|
||||||
else begin
|
else
|
||||||
|
begin
|
||||||
to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0];
|
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;
|
to_arm_shiftreg[0] <= 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -25,19 +25,29 @@
|
||||||
// - ssp_frame (wired to TIOA1 on the arm) for the edge detection/state
|
// - ssp_frame (wired to TIOA1 on the arm) for the edge detection/state
|
||||||
// - ssp_clk: cross_lo
|
// - ssp_clk: cross_lo
|
||||||
|
|
||||||
`include "lp20khz_1MSa_iir_filter.v"
|
//`include "lp20khz_1MSa_iir_filter.v"
|
||||||
`include "lf_edge_detect.v"
|
//`include "lf_edge_detect.v"
|
||||||
|
|
||||||
module lo_edge_detect(
|
module lo_edge_detect(
|
||||||
input pck0, input pck_divclk,
|
input pck0,
|
||||||
output pwr_lo, output pwr_hi,
|
input pck_divclk,
|
||||||
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
|
input [7:0] adc_d,
|
||||||
input [7:0] adc_d, output adc_clk,
|
|
||||||
output ssp_frame, input ssp_dout, output ssp_clk,
|
|
||||||
input cross_lo,
|
input cross_lo,
|
||||||
output dbg,
|
|
||||||
input lf_field,
|
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;
|
wire tag_modulation = ssp_dout & !lf_field;
|
||||||
|
@ -58,18 +68,34 @@ assign pwr_hi = 1'b0;
|
||||||
wire data_rdy;
|
wire data_rdy;
|
||||||
wire [7:0] adc_filtered;
|
wire [7:0] adc_filtered;
|
||||||
assign adc_clk = pck0;
|
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
|
// detect edges
|
||||||
wire [7:0] high_threshold, highz_threshold, lowz_threshold, low_threshold;
|
wire [7:0] high_threshold, highz_threshold, lowz_threshold, low_threshold;
|
||||||
wire [7:0] max, min;
|
wire [7:0] max, min;
|
||||||
wire edge_state, edge_toggle;
|
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;
|
assign ssp_frame = lf_ed_toggle_mode ? edge_toggle : edge_state;
|
||||||
|
|
|
@ -17,27 +17,32 @@
|
||||||
// For reading TI tags, we need to place the FPGA in pass through mode
|
// For reading TI tags, we need to place the FPGA in pass through mode
|
||||||
// and pass everything through to the ARM
|
// and pass everything through to the ARM
|
||||||
|
|
||||||
|
|
||||||
module lo_passthru(
|
module lo_passthru(
|
||||||
input pck_divclk,
|
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,
|
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
|
// the antenna is modulated when ssp_dout = 1, when 0 the
|
||||||
// antenna drivers stop modulating and go into listen mode
|
// 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_oe1 = ssp_dout;
|
||||||
assign pwr_oe2 = ssp_dout;
|
assign pwr_oe2 = ssp_dout;
|
||||||
|
assign pwr_oe3 = 1'b0;
|
||||||
assign pwr_oe4 = ssp_dout;
|
assign pwr_oe4 = ssp_dout;
|
||||||
assign pwr_lo = pck_divclk && ssp_dout;
|
assign debug = cross_lo;
|
||||||
assign pwr_hi = 1'b0;
|
|
||||||
assign adc_clk = 1'b0;
|
|
||||||
assign ssp_din = cross_lo;
|
|
||||||
assign dbg = cross_lo;
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
|
@ -22,13 +22,23 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
module lo_read(
|
module lo_read(
|
||||||
input pck0, input [7:0] pck_cnt, input pck_divclk,
|
input pck0,
|
||||||
output pwr_lo, output pwr_hi,
|
input pck_divclk,
|
||||||
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
|
input [7:0] pck_cnt,
|
||||||
input [7:0] adc_d, output adc_clk,
|
input [7:0] adc_d,
|
||||||
output ssp_frame, output ssp_din, output ssp_clk,
|
input lf_field,
|
||||||
output dbg,
|
|
||||||
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;
|
reg [7:0] to_arm_shiftreg;
|
||||||
|
@ -43,13 +53,9 @@ always @(posedge pck0)
|
||||||
begin
|
begin
|
||||||
if((pck_cnt == 8'd7) && !pck_divclk)
|
if((pck_cnt == 8'd7) && !pck_divclk)
|
||||||
to_arm_shiftreg <= adc_d;
|
to_arm_shiftreg <= adc_d;
|
||||||
else begin
|
else
|
||||||
|
begin
|
||||||
to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0];
|
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;
|
to_arm_shiftreg[0] <= 1'b0;
|
||||||
end
|
end
|
||||||
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
|
// 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;
|
assign ssp_frame = (pck_cnt[7:3] == 5'd1) && !pck_divclk;
|
||||||
// unused signals tied low
|
// unused signals tied low
|
||||||
assign pwr_hi = 1'b0;
|
assign pwr_hi = 1'b0;
|
||||||
assign pwr_oe1 = 1'b0;
|
assign pwr_oe1 = 1'b0;
|
||||||
assign pwr_oe2 = 1'b0;
|
assign pwr_oe2 = 1'b0;
|
||||||
assign pwr_oe3 = 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
|
// ADC clock out of phase with antenna driver
|
||||||
assign adc_clk = ~pck_divclk;
|
assign adc_clk = ~pck_divclk;
|
||||||
// ADC clock also routed to debug pin
|
// ADC clock also routed to debug pin
|
||||||
assign dbg = adc_clk;
|
assign debug = adc_clk;
|
||||||
endmodule
|
endmodule
|
|
@ -22,23 +22,27 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
module lo_simulate(
|
module lo_simulate(
|
||||||
pck0, ck_1356meg, ck_1356megb,
|
input pck0,
|
||||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
input ck_1356meg,
|
||||||
adc_d, adc_clk,
|
input ck_1356megb,
|
||||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
input [7:0] adc_d,
|
||||||
cross_hi, cross_lo,
|
input [7:0] divisor,
|
||||||
dbg,
|
input cross_hi,
|
||||||
divisor
|
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.
|
// No logic, straight through.
|
||||||
assign pwr_oe3 = 1'b0;
|
assign pwr_oe3 = 1'b0;
|
||||||
|
@ -46,9 +50,9 @@ assign pwr_oe1 = ssp_dout;
|
||||||
assign pwr_oe2 = ssp_dout;
|
assign pwr_oe2 = ssp_dout;
|
||||||
assign pwr_oe4 = ssp_dout;
|
assign pwr_oe4 = ssp_dout;
|
||||||
assign ssp_clk = cross_lo;
|
assign ssp_clk = cross_lo;
|
||||||
assign pwr_lo = 1'b0;
|
assign pwr_lo = 1'b0;
|
||||||
assign pwr_hi = 1'b0;
|
assign pwr_hi = 1'b0;
|
||||||
assign dbg = ssp_frame;
|
assign debug = ssp_frame;
|
||||||
|
|
||||||
// Divide the clock to be used for the ADC
|
// Divide the clock to be used for the ADC
|
||||||
reg [7:0] pck_divider;
|
reg [7:0] pck_divider;
|
|
@ -36,7 +36,12 @@
|
||||||
// See details about its design see
|
// See details about its design see
|
||||||
// https://fail0verflow.com/blog/2014/proxmark3-fpga-iir-filter.html
|
// 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
|
// clk is 24MHz, the IIR filter is designed for 1MS/s
|
||||||
// hence we need to divide it by 24
|
// hence we need to divide it by 24
|
|
@ -23,8 +23,13 @@
|
||||||
// This algorithm therefore can't be used directly for realtime peak detections,
|
// This algorithm therefore can't be used directly for realtime peak detections,
|
||||||
// but it can be used as a simple envelope follower.
|
// 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,
|
module min_max_tracker(
|
||||||
output [7:0] min, output [7:0] max);
|
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] min_val = 255;
|
||||||
reg [7:0] max_val = 0;
|
reg [7:0] max_val = 0;
|
50
fpga/mux16.v
Normal file
50
fpga/mux16.v
Normal file
|
@ -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
|
|
@ -4,13 +4,14 @@
|
||||||
// kombi, 2020.05
|
// kombi, 2020.05
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
module mux2_one(sel, y, x0, x1);
|
module mux2_one(
|
||||||
input [1:0] sel;
|
input [1:0] sel,
|
||||||
input x0, x1;
|
output reg y,
|
||||||
output y;
|
input x0,
|
||||||
reg y;
|
input x1
|
||||||
|
);
|
||||||
|
|
||||||
always @(x0 or x1 or sel)
|
always @(*)
|
||||||
begin
|
begin
|
||||||
case (sel)
|
case (sel)
|
||||||
1'b0: y = x1;
|
1'b0: y = x1;
|
|
@ -4,13 +4,14 @@
|
||||||
// kombi, 2020.05
|
// kombi, 2020.05
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
module mux2_oneout(sel, y, x0, x1);
|
module mux2_oneout(
|
||||||
input [1:0] sel;
|
input [1:0] sel,
|
||||||
output x0, x1;
|
input y,
|
||||||
input y;
|
output reg x0,
|
||||||
reg x0, x1;
|
output reg x1
|
||||||
|
);
|
||||||
|
|
||||||
always @(x0 or x1 or sel)
|
always @(*)
|
||||||
begin
|
begin
|
||||||
case (sel)
|
case (sel)
|
||||||
1'b0: x1 = y;
|
1'b0: x1 = y;
|
|
@ -17,23 +17,25 @@
|
||||||
// General-purpose miscellany.
|
// General-purpose miscellany.
|
||||||
//
|
//
|
||||||
|
|
||||||
module mux8(sel, y, x0, x1, x2, x3, x4, x5, x6, x7);
|
// 8 inputs to 1 output multiplexer
|
||||||
input [2:0] sel;
|
module mux8(
|
||||||
input x0, x1, x2, x3, x4, x5, x6, x7;
|
input [2:0] sel,
|
||||||
output y;
|
output reg y,
|
||||||
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
|
begin
|
||||||
|
// y = x[sel];
|
||||||
case (sel)
|
case (sel)
|
||||||
3'b000: y = x0;
|
3'd0: y = x0;
|
||||||
3'b001: y = x1;
|
3'd1: y = x1;
|
||||||
3'b010: y = x2;
|
3'd2: y = x2;
|
||||||
3'b011: y = x3;
|
3'd3: y = x3;
|
||||||
3'b100: y = x4;
|
3'd4: y = x4;
|
||||||
3'b101: y = x5;
|
3'd5: y = x5;
|
||||||
3'b110: y = x6;
|
3'd6: y = x6;
|
||||||
3'b111: y = x7;
|
3'd7: y = x7;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
0
fpga-xc2s30/tests/plot_edgedetect.py → fpga/tests/plot_edgedetect.py
Executable file → Normal file
0
fpga-xc2s30/tests/plot_edgedetect.py → fpga/tests/plot_edgedetect.py
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue