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/brute_key
|
||||
|
||||
fpga/*
|
||||
!fpga/tests
|
||||
!fpga/fpga_lf.bit
|
||||
!fpga/fpga_hf.bit
|
||||
!fpga/*.v
|
||||
!fpga/Makefile
|
||||
!fpga/fpga.ucf
|
||||
!fpga/xst_lf.scr
|
||||
!fpga/xst_hf.scr
|
||||
!fpga/go.bat
|
||||
!fpga/sim.tcl
|
||||
fpga/__build*
|
||||
|
||||
# offcial dumps folder
|
||||
dumps/*
|
||||
|
|
|
@ -103,9 +103,6 @@ endif
|
|||
# Generic standalone Mode injection of source code
|
||||
include Standalone/Makefile.inc
|
||||
|
||||
#the FPGA bitstream files. Note: order matters!
|
||||
FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit fpga_felica.bit fpga_hf_15.bit
|
||||
|
||||
#the lz4 source files required for decompressing the fpga config at run time
|
||||
SRC_LZ4 = lz4.c
|
||||
#additional defines required to compile lz4
|
||||
|
|
|
@ -404,16 +404,22 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
|
|||
/* Four byte length field */
|
||||
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24;
|
||||
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16;
|
||||
numbytes += 2;
|
||||
default: /* Fall through, two byte length field */
|
||||
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
|
||||
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
|
||||
numbytes += 4;
|
||||
if (current_length > 300*1024) {
|
||||
/* section e should never exceed about 300KB, if the length is too big limit it but still send the bitstream just in case */
|
||||
current_length = 300*1024;
|
||||
}
|
||||
break;
|
||||
default: /* Two byte length field */
|
||||
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
|
||||
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
|
||||
numbytes += 2;
|
||||
if (current_length > 64) {
|
||||
/* if text field is too long, keep it but truncate it */
|
||||
current_length = 64;
|
||||
}
|
||||
|
||||
if (current_name != 'e' && current_length > 255) {
|
||||
/* Maybe a parse error */
|
||||
break;
|
||||
}
|
||||
|
||||
if (current_name == section_name) {
|
||||
|
|
|
@ -44,7 +44,7 @@ OBJDIR = obj
|
|||
INCLUDE = -I../include -I../common_arm -I../common_fpga -I../common -I.
|
||||
|
||||
# Also search prerequisites in the common directory (for usb.c), the fpga directory (for fpga.bit), and the lz4 directory
|
||||
VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/lz4 ../fpga-$(PLATFORM_FPGA) ../armsrc/Standalone
|
||||
VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/lz4 ../fpga ../armsrc/Standalone
|
||||
|
||||
INCLUDES = ../include/proxmark3_arm.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/pm3_cmd.h
|
||||
|
||||
|
|
|
@ -92,18 +92,26 @@ PLTNAME = Unknown Platform
|
|||
PLATFORM_FPGA = fpga-undefined
|
||||
|
||||
ifeq ($(PLATFORM),PM3RDV4)
|
||||
# FPGA bitstream files, the order matters!
|
||||
FPGA_BITSTREAMS = fpga_pm3_lf.bit fpga_pm3_hf.bit fpga_pm3_felica.bit fpga_pm3_hf_15.bit
|
||||
PLATFORM_DEFS = -DWITH_SMARTCARD -DWITH_FLASH -DRDV4
|
||||
PLTNAME = Proxmark3 RDV4
|
||||
PLATFORM_FPGA = xc2s30
|
||||
RDV4 = yes
|
||||
else ifeq ($(PLATFORM),PM3OTHER)
|
||||
$(warning PLATFORM=PM3OTHER is deprecated, please use PLATFORM=PM3GENERIC)
|
||||
# FPGA bitstream files, the order matters!
|
||||
FPGA_BITSTREAMS = fpga_pm3_lf.bit fpga_pm3_hf.bit fpga_pm3_felica.bit fpga_pm3_hf_15.bit
|
||||
PLTNAME = Proxmark3 generic target
|
||||
PLATFORM_FPGA = xc2s30
|
||||
else ifeq ($(PLATFORM),PM3GENERIC)
|
||||
# FPGA bitstream files, the order matters!
|
||||
FPGA_BITSTREAMS = fpga_pm3_lf.bit fpga_pm3_hf.bit fpga_pm3_felica.bit fpga_pm3_hf_15.bit
|
||||
PLTNAME = Proxmark3 generic target
|
||||
PLATFORM_FPGA = xc2s30
|
||||
else ifeq ($(PLATFORM),PM3ICOPYX)
|
||||
# FPGA bitstream files, the order matters - only hf has a bitstream, the other 3 files are 0 bytes
|
||||
FPGA_BITSTREAMS = fpga_icopyx_lf.bit fpga_icopyx_hf.bit fpga_icopyx_felica.bit fpga_icopyx_hf_15.bit
|
||||
PLATFORM_DEFS = -DWITH_FLASH -DICOPYX -DXC3
|
||||
PLTNAME = iCopy-X with XC3S100E
|
||||
PLATFORM_FPGA = xc3s100e
|
||||
|
@ -246,6 +254,7 @@ export PLATFORM_DEFS
|
|||
export PLATFORM_DEFS_INFO
|
||||
export PLATFORM_DEFS_INFO_STANDALONE
|
||||
export PLATFORM_CHANGED
|
||||
export FPGA_BITSTREAMS
|
||||
|
||||
$(info ===================================================================)
|
||||
$(info Version info: $(shell tools/mkversion.sh --short 2>/dev/null || ../tools/mkversion.sh --short 2>/dev/null))
|
||||
|
|
|
@ -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.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module clk_divider(input clk, input [7:0] divisor, output [7:0] div_cnt, output div_clk);
|
||||
module clk_divider(
|
||||
input clk,
|
||||
input [7:0] divisor,
|
||||
output [7:0] div_cnt,
|
||||
output div_clk
|
||||
);
|
||||
|
||||
reg [7:0] div_cnt_ = 0;
|
||||
reg div_clk_;
|
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:
|
||||
// Engineer:
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
||||
//
|
||||
// Create Date: 16:09:14 05/13/2020
|
||||
// Design Name:
|
||||
// Module Name: fpga_all_in_one
|
||||
// Project Name:
|
||||
// Target Devices:
|
||||
// Tool versions:
|
||||
// Description:
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Dependencies:
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// Revision:
|
||||
// Revision 0.01 - File Created
|
||||
// Additional Comments:
|
||||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
module fpga_hf(
|
||||
input spck, output miso, input mosi, input ncs,
|
||||
input pck0, input ck_1356meg, input ck_1356megb,
|
||||
output pwr_lo, output pwr_hi,
|
||||
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
|
||||
input [7:0] adc_d, output adc_clk, output adc_noe,
|
||||
output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk,
|
||||
input cross_hi, input cross_lo,
|
||||
// The FPGA is responsible for interfacing between the A/D, the coil drivers,
|
||||
// and the ARM. In the low-frequency modes it passes the data straight
|
||||
// through, so that the ARM gets raw A/D samples over the SSP. In the high-
|
||||
// frequency modes, the FPGA might perform some demodulation first, to
|
||||
// reduce the amount of data that we must send to the ARM.
|
||||
//-----------------------------------------------------------------------------
|
||||
//`include "fpga_lf.v"
|
||||
//`include "fpga_hf.v"
|
||||
//`include "mux2_onein.v"
|
||||
//`include "mux2_oneout.v"
|
||||
//`include "util.v"
|
||||
|
||||
module fpga_top(
|
||||
input spck,
|
||||
output miso,
|
||||
input mosi,
|
||||
input ncs,
|
||||
input pck0,
|
||||
input ck_1356meg,
|
||||
input ck_1356megb,
|
||||
output pwr_lo,
|
||||
output pwr_hi,
|
||||
output pwr_oe1,
|
||||
output pwr_oe2,
|
||||
output pwr_oe3,
|
||||
output pwr_oe4,
|
||||
input [7:0] adc_d,
|
||||
output adc_clk,
|
||||
output adc_noe,
|
||||
output ssp_frame,
|
||||
output ssp_din,
|
||||
input ssp_dout,
|
||||
output ssp_clk,
|
||||
input cross_hi,
|
||||
input cross_lo,
|
||||
output dbg,
|
||||
output PWR_LO_EN,
|
||||
input FPGA_SWITCH
|
||||
);
|
||||
|
||||
|
||||
fpga_hfmod hfmod(
|
||||
fpga_hf hfmod(
|
||||
hfspck, hfmiso, hfmosi, hfncs,
|
||||
hfpck0, hfck_1356meg, hfck_1356megb,
|
||||
hfpwr_lo, hfpwr_hi,
|
||||
|
@ -39,10 +63,10 @@ fpga_hfmod hfmod(
|
|||
adc_d, hfadc_clk, hfadc_noe,
|
||||
hfssp_frame, hfssp_din, hfssp_dout, hfssp_clk,
|
||||
hfcross_hi, hfcross_lo,
|
||||
hfdbg
|
||||
hfdebug
|
||||
);
|
||||
|
||||
fpga_lfmod lfmod(
|
||||
fpga_lf lfmod(
|
||||
lfspck, lfmiso, lfmosi, lfncs,
|
||||
lfpck0, lfck_1356meg, lfck_1356megb,
|
||||
lfpwr_lo, lfpwr_hi,
|
||||
|
@ -50,7 +74,7 @@ fpga_lfmod lfmod(
|
|||
adc_d, lfadc_clk, lfadc_noe,
|
||||
lfssp_frame, lfssp_din, lfssp_dout, lfssp_clk,
|
||||
lfcross_hi, lfcross_lo,
|
||||
lfdbg,
|
||||
lfdebug,
|
||||
lfPWR_LO_EN
|
||||
);
|
||||
|
||||
|
@ -75,7 +99,7 @@ mux2_oneout mux_ssp_dout_all (FPGA_SWITCH, ssp_dout, hfss
|
|||
mux2_one mux_ssp_clk_all (FPGA_SWITCH, ssp_clk, hfssp_clk, lfssp_clk);
|
||||
mux2_oneout mux_cross_hi_all (FPGA_SWITCH, cross_hi, hfcross_hi, lfcross_hi);
|
||||
mux2_oneout mux_cross_lo_all (FPGA_SWITCH, cross_lo, hfcross_lo, lfcross_lo);
|
||||
mux2_one mux_dbg_all (FPGA_SWITCH, dbg, hfdbg, lfdbg);
|
||||
mux2_one mux_dbg_all (FPGA_SWITCH, dbg, hfdebug, lfdebug);
|
||||
mux2_one mux_PWR_LO_EN_all (FPGA_SWITCH, PWR_LO_EN, 1'b0, lfPWR_LO_EN);
|
||||
|
||||
endmodule
|
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(
|
||||
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;
|
||||
input ck_1356meg,
|
||||
input [7:0] adc_d,
|
||||
input [3:0] mod_type,
|
||||
input ssp_dout,
|
||||
|
||||
assign dbg = 0;
|
||||
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
|
||||
);
|
||||
|
||||
assign debug = 0;
|
||||
|
||||
wire power = mod_type[2];
|
||||
wire speed = mod_type[1];
|
||||
wire disabl = mod_type[0];
|
||||
|
||||
// Most off, oe4 for modulation;
|
||||
// Trying reader emulation (would presumably just require switching power on, but I am not sure)
|
||||
assign pwr_lo = 1'b0;
|
||||
assign pwr_oe2 = 1'b0;
|
||||
|
||||
// 512x64/fc -wait before ts0, 32768 ticks
|
||||
// tslot: 256*64/fc
|
||||
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] bitmlen = speed ? `bitmlen_424 : `bitmlen_212;
|
||||
|
||||
|
||||
//ssp clock and current values
|
||||
reg ssp_clk;
|
||||
reg ssp_frame;
|
||||
reg curbit = 1'b0;
|
||||
|
||||
reg [7:0] fccount = 8'd0; // in-bit tick counter. Counts carrier cycles from the first lower edge detected, reset on every manchester bit detected
|
||||
|
@ -107,6 +100,7 @@ reg [7:0] tsinceedge = 8'd0;// ticks from last edge, desync if the valye is too
|
|||
|
||||
reg zero = 1'b0; // Manchester first halfbit low second high corresponds to this value. It has been known to change. SYNC is used to set it
|
||||
|
||||
//ssp clock and current values
|
||||
//ssp counter for transfer and framing
|
||||
reg [8:0] ssp_cnt = 9'd0;
|
||||
|
||||
|
@ -122,6 +116,7 @@ begin
|
|||
if( ((~speed) && (ssp_cnt[5:0] == 6'b000000)) || (speed && (ssp_cnt[4:0] == 5'b00000)))
|
||||
begin
|
||||
ssp_clk <= 1'b1;
|
||||
//send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise)
|
||||
ssp_din <= curbit;
|
||||
end
|
||||
if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000))
|
||||
|
@ -138,9 +133,6 @@ begin
|
|||
end
|
||||
end
|
||||
|
||||
//send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise)
|
||||
reg ssp_din;
|
||||
|
||||
//previous signal value, mostly to detect SYNC
|
||||
reg prv = 1'b1;
|
||||
|
||||
|
@ -353,11 +345,8 @@ begin
|
|||
end
|
||||
// sending <= 0;
|
||||
end
|
||||
|
||||
//put modulation here to maintain the correct clock. Seems that some readers are sensitive to that
|
||||
reg pwr_hi;
|
||||
reg pwr_oe1;
|
||||
reg pwr_oe3;
|
||||
reg pwr_oe4;
|
||||
|
||||
wire mod = ((fccount >= bithalf) ^ dlay) & (~disabl);
|
||||
|
||||
|
@ -366,20 +355,21 @@ begin
|
|||
if (power)
|
||||
begin
|
||||
pwr_hi <= ck_1356meg;
|
||||
pwr_lo <= 1'b0;
|
||||
pwr_oe1 <= 1'b0;//mod;
|
||||
pwr_oe2 <= 1'b0;//mod;
|
||||
pwr_oe3 <= 1'b0;//mod;
|
||||
pwr_oe4 <= mod;//1'b0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
pwr_hi <= 1'b0;
|
||||
pwr_lo <= 1'b0;
|
||||
pwr_oe1 <= 1'b0;
|
||||
pwr_oe2 <= 1'b0;
|
||||
pwr_oe3 <= 1'b0;
|
||||
pwr_oe4 <= mod;
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
|
@ -13,17 +13,18 @@
|
|||
//
|
||||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
//`include "define.v"
|
||||
|
||||
module hi_get_trace(
|
||||
ck_1356megb,
|
||||
adc_d, trace_enable, major_mode,
|
||||
ssp_frame, ssp_din, ssp_clk
|
||||
input ck_1356megb,
|
||||
input [7:0] adc_d,
|
||||
input trace_enable,
|
||||
input [2:0] major_mode,
|
||||
|
||||
output ssp_din,
|
||||
output reg ssp_frame,
|
||||
output reg ssp_clk
|
||||
);
|
||||
input ck_1356megb;
|
||||
input [7:0] adc_d;
|
||||
input trace_enable;
|
||||
input [2:0] major_mode;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
|
||||
// clock divider
|
||||
reg [6:0] clock_cnt;
|
||||
|
@ -136,9 +137,6 @@ begin
|
|||
end
|
||||
|
||||
|
||||
// SSC communication to ARM
|
||||
reg ssp_clk;
|
||||
reg ssp_frame;
|
||||
reg [7:0] shift_out;
|
||||
|
||||
always @(negedge ck_1356megb)
|
|
@ -14,29 +14,28 @@
|
|||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// ISO14443-A support for the Proxmark III
|
||||
//
|
||||
//`include "define.v"
|
||||
|
||||
module hi_iso14443a(
|
||||
ck_1356meg,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
dbg,
|
||||
mod_type
|
||||
input ck_1356meg,
|
||||
input [7:0] adc_d,
|
||||
input [3:0] mod_type,
|
||||
input ssp_dout,
|
||||
|
||||
output ssp_din,
|
||||
output reg ssp_frame,
|
||||
output reg ssp_clk,
|
||||
output adc_clk,
|
||||
output pwr_lo,
|
||||
output pwr_hi,
|
||||
output pwr_oe1,
|
||||
output pwr_oe2,
|
||||
output pwr_oe3,
|
||||
output pwr_oe4,
|
||||
output debug
|
||||
);
|
||||
input ck_1356meg;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
output dbg;
|
||||
input [3:0] mod_type;
|
||||
|
||||
|
||||
wire adc_clk = ck_1356meg;
|
||||
|
||||
|
||||
assign adc_clk = ck_1356meg;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Reader -> PM3:
|
||||
|
@ -76,8 +75,6 @@ begin
|
|||
|
||||
end
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Reader -> PM3
|
||||
// detect when a reader is active (modulating). We assume that the reader is active, if we see the carrier off for at least 8
|
||||
|
@ -137,7 +134,6 @@ wire [9:0] tmp2 = adc_d_times_2 + input_prev_1;
|
|||
wire signed [10:0] adc_d_filtered = {1'b0, tmp1} - {1'b0, tmp2};
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// internal FPGA timing. Maximum required period is 128 carrier clock cycles for a full 8 Bit transfer to ARM. (i.e. we need a
|
||||
// 7 bit counter). Adjust its frequency to external reader's clock when simulating a tag or sniffing.
|
||||
|
@ -222,7 +218,11 @@ reg signed [10:0] rx_mod_falling_edge_max;
|
|||
reg signed [10:0] rx_mod_rising_edge_max;
|
||||
reg curbit;
|
||||
|
||||
`ifdef PM3ICOPYX
|
||||
`define EDGE_DETECT_THRESHOLD 3
|
||||
`else
|
||||
`define EDGE_DETECT_THRESHOLD 5
|
||||
`endif
|
||||
`define EDGE_DETECT_THRESHOLDHIGH 20
|
||||
|
||||
always @(negedge adc_clk)
|
||||
|
@ -266,7 +266,6 @@ begin
|
|||
end
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Tag+Reader -> PM3
|
||||
// sample 4 bits reader data and 4 bits tag data for sniffing
|
||||
|
@ -283,7 +282,6 @@ begin
|
|||
end
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PM3 -> Reader:
|
||||
// a delay line to ensure that we send the (emulated) tag's answer at the correct time according to ISO14443-3
|
||||
|
@ -307,7 +305,6 @@ begin
|
|||
end
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PM3 -> Reader, internal timing:
|
||||
// a timer for the 1172 cycles fdt (Frame Delay Time). Start the timer with a rising edge of the reader's signal.
|
||||
|
@ -400,7 +397,6 @@ begin
|
|||
end
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PM3 -> Reader
|
||||
// determine the required delay in the mod_sig_buf (set mod_sig_ptr).
|
||||
|
@ -444,7 +440,6 @@ begin
|
|||
end
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FPGA -> ARM communication:
|
||||
// buffer 8 bits data to be sent to ARM. Shift them out bit by bit.
|
||||
|
@ -495,8 +490,6 @@ end
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FPGA <-> ARM communication:
|
||||
// generate a ssp clock and ssp frame signal for the synchronous transfer from/to the ARM
|
||||
reg ssp_clk;
|
||||
reg ssp_frame;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
|
@ -529,7 +522,6 @@ begin
|
|||
end
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FPGA -> ARM communication:
|
||||
// select the data to be sent to ARM
|
||||
|
@ -553,7 +545,6 @@ begin
|
|||
sendbit = 1'b0;
|
||||
end
|
||||
|
||||
|
||||
if(mod_type == `FPGA_HF_ISO14443A_SNIFFER)
|
||||
// send sampled reader and tag data:
|
||||
bit_to_arm = to_arm[7];
|
||||
|
@ -589,6 +580,6 @@ assign pwr_oe4 = mod_sig_coil & sub_carrier & (mod_type == `FPGA_HF_ISO14443A_TA
|
|||
assign pwr_oe2 = 1'b0;
|
||||
assign pwr_lo = 1'b0;
|
||||
|
||||
assign dbg = negedge_cnt[3];
|
||||
assign debug = negedge_cnt[3];
|
||||
|
||||
endmodule
|
|
@ -13,24 +13,27 @@
|
|||
//
|
||||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
//`include "define.v"
|
||||
|
||||
module hi_reader(
|
||||
ck_1356meg,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
dbg,
|
||||
subcarrier_frequency, minor_mode
|
||||
input ck_1356meg,
|
||||
input [7:0] adc_d,
|
||||
input [1:0] subcarrier_frequency,
|
||||
input [3:0] minor_mode,
|
||||
input ssp_dout,
|
||||
|
||||
output ssp_din,
|
||||
output reg ssp_frame,
|
||||
output reg ssp_clk,
|
||||
output adc_clk,
|
||||
output pwr_lo,
|
||||
output reg pwr_hi,
|
||||
output pwr_oe1,
|
||||
output pwr_oe2,
|
||||
output pwr_oe3,
|
||||
output reg pwr_oe4,
|
||||
output debug
|
||||
);
|
||||
input ck_1356meg;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
output dbg;
|
||||
input [1:0] subcarrier_frequency;
|
||||
input [3:0] minor_mode;
|
||||
|
||||
assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz
|
||||
|
||||
|
@ -160,7 +163,6 @@ begin
|
|||
end
|
||||
else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ)
|
||||
begin
|
||||
|
||||
// Send 7 most significant bits of in phase tag signal (signed), plus 1 bit reader signal
|
||||
if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111)
|
||||
corr_i_out <= {corr_i_accum[11:5], after_hysteresis_prev_prev};
|
||||
|
@ -261,9 +263,6 @@ end
|
|||
// corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ...
|
||||
//
|
||||
|
||||
reg ssp_clk;
|
||||
reg ssp_frame;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if (corr_i_cnt[1:0] == 2'b00)
|
||||
|
@ -298,9 +297,6 @@ begin
|
|||
end
|
||||
end
|
||||
|
||||
// Antenna drivers
|
||||
reg pwr_hi, pwr_oe4;
|
||||
|
||||
always @(*)
|
||||
begin
|
||||
if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD)
|
||||
|
@ -341,6 +337,6 @@ assign pwr_lo = 1'b0;
|
|||
assign pwr_oe2 = 1'b0;
|
||||
|
||||
// Debug Output
|
||||
assign dbg = corr_i_cnt[3];
|
||||
assign debug = corr_i_cnt[3];
|
||||
|
||||
endmodule
|
|
@ -14,25 +14,26 @@
|
|||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// modified to add support for iso15 2sc mode
|
||||
//
|
||||
|
||||
module hi_15_reader(
|
||||
ck_1356meg,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
dbg,
|
||||
subcarrier_frequency, minor_mode
|
||||
module hi_reader_15(
|
||||
input ck_1356meg,
|
||||
input [7:0] adc_d,
|
||||
input [1:0] subcarrier_frequency,
|
||||
input [3:0] minor_mode,
|
||||
input ssp_dout,
|
||||
|
||||
output ssp_din,
|
||||
output reg ssp_frame,
|
||||
output reg ssp_clk,
|
||||
output adc_clk,
|
||||
output pwr_lo,
|
||||
output reg pwr_hi,
|
||||
output pwr_oe1,
|
||||
output pwr_oe2,
|
||||
output pwr_oe3,
|
||||
output reg pwr_oe4,
|
||||
output debug
|
||||
);
|
||||
input ck_1356meg;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
output dbg;
|
||||
input [1:0] subcarrier_frequency;
|
||||
input [3:0] minor_mode;
|
||||
|
||||
assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz
|
||||
|
||||
|
@ -379,9 +380,6 @@ end
|
|||
// corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ...
|
||||
//
|
||||
|
||||
reg ssp_clk;
|
||||
reg ssp_frame;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if (corr_i_cnt[1:0] == 2'b00)
|
||||
|
@ -416,9 +414,6 @@ begin
|
|||
end
|
||||
end
|
||||
|
||||
// Antenna drivers
|
||||
reg pwr_hi, pwr_oe4;
|
||||
|
||||
always @(*)
|
||||
begin
|
||||
if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD)
|
||||
|
@ -459,6 +454,6 @@ assign pwr_lo = 1'b0;
|
|||
assign pwr_oe2 = 1'b0;
|
||||
|
||||
// Debug Output
|
||||
assign dbg = corr_i_cnt[3];
|
||||
assign debug = corr_i_cnt[3];
|
||||
|
||||
endmodule
|
|
@ -30,23 +30,26 @@
|
|||
//
|
||||
// Jonathan Westhues, October 2006
|
||||
//-----------------------------------------------------------------------------
|
||||
//`include "define.v"
|
||||
|
||||
module hi_simulate(
|
||||
ck_1356meg,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
dbg,
|
||||
mod_type
|
||||
input ck_1356meg,
|
||||
input [7:0] adc_d,
|
||||
input [3:0] mod_type,
|
||||
input ssp_dout,
|
||||
|
||||
output reg ssp_din,
|
||||
output reg ssp_frame,
|
||||
output reg ssp_clk,
|
||||
output adc_clk,
|
||||
output pwr_lo,
|
||||
output pwr_hi,
|
||||
output pwr_oe1,
|
||||
output pwr_oe2,
|
||||
output pwr_oe3,
|
||||
output pwr_oe4,
|
||||
output debug
|
||||
);
|
||||
input ck_1356meg;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
output dbg;
|
||||
input [3:0] mod_type;
|
||||
|
||||
// Power amp goes between LOW and tri-state, so pwr_hi (and pwr_lo) can
|
||||
// always be low.
|
||||
|
@ -57,7 +60,7 @@ assign pwr_lo = 1'b0; // LF antenna connected to GND
|
|||
assign pwr_oe2 = 1'b0;
|
||||
|
||||
assign adc_clk = ck_1356meg;
|
||||
assign dbg = ssp_frame;
|
||||
assign debug = ssp_frame;
|
||||
|
||||
// The comparator with hysteresis on the output from the peak detector.
|
||||
reg after_hysteresis;
|
||||
|
@ -94,8 +97,6 @@ reg [8:0] ssp_clk_divider;
|
|||
always @(negedge adc_clk)
|
||||
ssp_clk_divider <= (ssp_clk_divider + 1);
|
||||
|
||||
reg ssp_clk;
|
||||
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT)
|
||||
|
@ -112,7 +113,6 @@ end
|
|||
|
||||
// Produce the byte framing signal; the phase of this signal
|
||||
// is arbitrary, because it's just a bit stream in this module.
|
||||
reg ssp_frame;
|
||||
always @(negedge adc_clk)
|
||||
begin
|
||||
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K)
|
||||
|
@ -133,7 +133,6 @@ end
|
|||
|
||||
|
||||
// Synchronize up the after-hysteresis signal, to produce DIN.
|
||||
reg ssp_din;
|
||||
always @(posedge ssp_clk)
|
||||
ssp_din = after_hysteresis;
|
||||
|
|
@ -15,16 +15,20 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
module hi_sniffer(
|
||||
ck_1356meg,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_clk
|
||||
input ck_1356meg,
|
||||
input [7:0] adc_d,
|
||||
|
||||
output ssp_din,
|
||||
output reg ssp_frame,
|
||||
output ssp_clk,
|
||||
output adc_clk,
|
||||
output pwr_lo,
|
||||
output pwr_hi,
|
||||
output pwr_oe1,
|
||||
output pwr_oe2,
|
||||
output pwr_oe3,
|
||||
output pwr_oe4
|
||||
);
|
||||
input ck_1356meg;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
|
||||
// We are only snooping, all off.
|
||||
assign pwr_hi = 1'b0;
|
||||
|
@ -34,12 +38,13 @@ assign pwr_oe2 = 1'b0;
|
|||
assign pwr_oe3 = 1'b0;
|
||||
assign pwr_oe4 = 1'b0;
|
||||
|
||||
reg ssp_frame;
|
||||
//reg ssp_frame;
|
||||
reg [7:0] adc_d_out = 8'd0;
|
||||
reg [2:0] ssp_cnt = 3'd0;
|
||||
|
||||
assign adc_clk = ck_1356meg;
|
||||
assign ssp_clk = ~ck_1356meg;
|
||||
assign ssp_din = adc_d_out[0];
|
||||
|
||||
always @(posedge ssp_clk)
|
||||
begin
|
||||
|
@ -55,12 +60,10 @@ begin
|
|||
end
|
||||
else
|
||||
begin
|
||||
// shift value right one bit
|
||||
adc_d_out[7:0] <= {1'b0, adc_d_out[7:1]};
|
||||
ssp_frame <= 1'b0;
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
assign ssp_din = adc_d_out[0];
|
||||
|
||||
endmodule
|
|
@ -15,17 +15,31 @@
|
|||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// input clk is 24MHz
|
||||
`include "min_max_tracker.v"
|
||||
//`include "min_max_tracker.v"
|
||||
|
||||
module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold,
|
||||
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);
|
||||
module lf_edge_detect(
|
||||
input clk,
|
||||
input [7:0] adc_d,
|
||||
input [7:0] lf_ed_threshold,
|
||||
|
||||
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
|
||||
assign high_threshold = (max + min) / 2 + (max - min) / 4;
|
||||
|
@ -61,12 +75,14 @@ module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold,
|
|||
|
||||
// all edges detection
|
||||
always @(posedge clk)
|
||||
if (enabled) begin
|
||||
if (enabled)
|
||||
begin
|
||||
// To enable detecting two consecutive peaks at the same level
|
||||
// (low or high) we check whether or not we went back near 0 in-between.
|
||||
// This extra check is necessary to prevent from noise artifacts
|
||||
// around the threshold values.
|
||||
if (trigger_enabled & (is_high | is_low)) begin
|
||||
if (trigger_enabled & (is_high | is_low))
|
||||
begin
|
||||
output_edge <= ~output_edge;
|
||||
trigger_enabled <= 0;
|
||||
end else
|
||||
|
@ -75,7 +91,8 @@ module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold,
|
|||
|
||||
// edge states
|
||||
always @(posedge clk)
|
||||
if (enabled) begin
|
||||
if (enabled)
|
||||
begin
|
||||
if (is_high)
|
||||
output_state <= 1'd1;
|
||||
else if (is_low)
|
|
@ -22,22 +22,24 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
module lo_adc(
|
||||
pck0,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
dbg, divisor,
|
||||
lf_field
|
||||
input pck0,
|
||||
input [7:0] adc_d,
|
||||
input [7:0] divisor,
|
||||
input lf_field,
|
||||
input ssp_dout,
|
||||
|
||||
output ssp_din,
|
||||
output ssp_frame,
|
||||
output ssp_clk,
|
||||
output adc_clk,
|
||||
output pwr_lo,
|
||||
output pwr_hi,
|
||||
output pwr_oe1,
|
||||
output pwr_oe2,
|
||||
output pwr_oe3,
|
||||
output pwr_oe4,
|
||||
output debug
|
||||
);
|
||||
input pck0;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
output dbg;
|
||||
input [7:0] divisor;
|
||||
input lf_field;
|
||||
|
||||
reg [7:0] to_arm_shiftreg;
|
||||
reg [7:0] pck_divider;
|
||||
|
@ -58,7 +60,7 @@ assign pwr_oe3 = tag_modulation; // base antenna load = 33 Ohms
|
|||
assign pwr_oe4 = 1'b0; // 10k Ohms
|
||||
|
||||
// Debug Output ADC clock
|
||||
assign dbg = adc_clk;
|
||||
assign debug = adc_clk;
|
||||
|
||||
// ADC clock out of phase with antenna driver
|
||||
assign adc_clk = ~clk_state;
|
||||
|
@ -92,13 +94,9 @@ always @(posedge pck0)
|
|||
begin
|
||||
if ((pck_divider == 8'd7) && !clk_state)
|
||||
to_arm_shiftreg <= adc_d;
|
||||
else begin
|
||||
else
|
||||
begin
|
||||
to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0];
|
||||
// simulation showed a glitch occurring due to the LSB of the shifter
|
||||
// not being set as we shift bits out
|
||||
// this ensures the ssp_din remains low after a transfer and suppresses
|
||||
// the glitch that would occur when the last data shifted out ended in
|
||||
// a 1 bit and the next data shifted out started with a 0 bit
|
||||
to_arm_shiftreg[0] <= 1'b0;
|
||||
end
|
||||
end
|
|
@ -25,19 +25,29 @@
|
|||
// - ssp_frame (wired to TIOA1 on the arm) for the edge detection/state
|
||||
// - ssp_clk: cross_lo
|
||||
|
||||
`include "lp20khz_1MSa_iir_filter.v"
|
||||
`include "lf_edge_detect.v"
|
||||
//`include "lp20khz_1MSa_iir_filter.v"
|
||||
//`include "lf_edge_detect.v"
|
||||
|
||||
module lo_edge_detect(
|
||||
input pck0, input pck_divclk,
|
||||
output pwr_lo, output pwr_hi,
|
||||
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
|
||||
input [7:0] adc_d, output adc_clk,
|
||||
output ssp_frame, input ssp_dout, output ssp_clk,
|
||||
input pck0,
|
||||
input pck_divclk,
|
||||
input [7:0] adc_d,
|
||||
input cross_lo,
|
||||
output dbg,
|
||||
input lf_field,
|
||||
input lf_ed_toggle_mode, input [7:0] lf_ed_threshold
|
||||
input lf_ed_toggle_mode,
|
||||
input [7:0] lf_ed_threshold,
|
||||
input ssp_dout,
|
||||
|
||||
output ssp_frame,
|
||||
output ssp_clk,
|
||||
output adc_clk,
|
||||
output pwr_lo,
|
||||
output pwr_hi,
|
||||
output pwr_oe1,
|
||||
output pwr_oe2,
|
||||
output pwr_oe3,
|
||||
output pwr_oe4,
|
||||
output debug
|
||||
);
|
||||
|
||||
wire tag_modulation = ssp_dout & !lf_field;
|
||||
|
@ -58,18 +68,34 @@ assign pwr_hi = 1'b0;
|
|||
wire data_rdy;
|
||||
wire [7:0] adc_filtered;
|
||||
assign adc_clk = pck0;
|
||||
lp20khz_1MSa_iir_filter adc_filter(pck0, adc_d, data_rdy, adc_filtered);
|
||||
|
||||
lp20khz_1MSa_iir_filter adc_filter(
|
||||
.clk (pck0),
|
||||
.adc_d (adc_d),
|
||||
.rdy (data_rdy),
|
||||
.out (adc_filtered)
|
||||
);
|
||||
|
||||
// detect edges
|
||||
wire [7:0] high_threshold, highz_threshold, lowz_threshold, low_threshold;
|
||||
wire [7:0] max, min;
|
||||
wire edge_state, edge_toggle;
|
||||
lf_edge_detect lf_ed(pck0, adc_filtered, lf_ed_threshold,
|
||||
max, min,
|
||||
high_threshold, highz_threshold, lowz_threshold, low_threshold,
|
||||
edge_state, edge_toggle);
|
||||
|
||||
assign dbg = lf_ed_toggle_mode ? edge_toggle : edge_state;
|
||||
lf_edge_detect lf_ed(
|
||||
.clk (pck0),
|
||||
.adc_d (adc_filtered),
|
||||
.lf_ed_threshold (lf_ed_threshold),
|
||||
.max (max),
|
||||
.min (min),
|
||||
.high_threshold (high_threshold),
|
||||
.highz_threshold (highz_threshold),
|
||||
.lowz_threshold (lowz_threshold),
|
||||
.low_threshold (low_threshold),
|
||||
.edge_state (edge_state),
|
||||
.edge_toggle (edge_toggle)
|
||||
);
|
||||
|
||||
assign debug = lf_ed_toggle_mode ? edge_toggle : edge_state;
|
||||
|
||||
assign ssp_frame = lf_ed_toggle_mode ? edge_toggle : edge_state;
|
||||
|
|
@ -17,27 +17,32 @@
|
|||
// For reading TI tags, we need to place the FPGA in pass through mode
|
||||
// and pass everything through to the ARM
|
||||
|
||||
|
||||
module lo_passthru(
|
||||
input pck_divclk,
|
||||
output pwr_lo, output pwr_hi,
|
||||
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
|
||||
output adc_clk,
|
||||
output ssp_din, input ssp_dout,
|
||||
input cross_lo,
|
||||
output dbg
|
||||
input ssp_dout,
|
||||
|
||||
output ssp_din,
|
||||
output adc_clk,
|
||||
output pwr_lo,
|
||||
output pwr_hi,
|
||||
output pwr_oe1,
|
||||
output pwr_oe2,
|
||||
output pwr_oe3,
|
||||
output pwr_oe4,
|
||||
output debug
|
||||
);
|
||||
|
||||
// the antenna is modulated when ssp_dout = 1, when 0 the
|
||||
// antenna drivers stop modulating and go into listen mode
|
||||
assign pwr_oe3 = 1'b0;
|
||||
assign pwr_oe1 = ssp_dout;
|
||||
assign pwr_oe2 = ssp_dout;
|
||||
assign pwr_oe4 = ssp_dout;
|
||||
assign ssp_din = cross_lo;
|
||||
assign adc_clk = 1'b0;
|
||||
assign pwr_lo = pck_divclk && ssp_dout;
|
||||
assign pwr_hi = 1'b0;
|
||||
assign adc_clk = 1'b0;
|
||||
assign ssp_din = cross_lo;
|
||||
assign dbg = cross_lo;
|
||||
assign pwr_oe1 = ssp_dout;
|
||||
assign pwr_oe2 = ssp_dout;
|
||||
assign pwr_oe3 = 1'b0;
|
||||
assign pwr_oe4 = ssp_dout;
|
||||
assign debug = cross_lo;
|
||||
|
||||
endmodule
|
|
@ -22,13 +22,23 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
module lo_read(
|
||||
input pck0, input [7:0] pck_cnt, input pck_divclk,
|
||||
output pwr_lo, output pwr_hi,
|
||||
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
|
||||
input [7:0] adc_d, output adc_clk,
|
||||
output ssp_frame, output ssp_din, output ssp_clk,
|
||||
output dbg,
|
||||
input lf_field
|
||||
input pck0,
|
||||
input pck_divclk,
|
||||
input [7:0] pck_cnt,
|
||||
input [7:0] adc_d,
|
||||
input lf_field,
|
||||
|
||||
output ssp_din,
|
||||
output ssp_frame,
|
||||
output ssp_clk,
|
||||
output adc_clk,
|
||||
output pwr_lo,
|
||||
output pwr_hi,
|
||||
output pwr_oe1,
|
||||
output pwr_oe2,
|
||||
output pwr_oe3,
|
||||
output pwr_oe4,
|
||||
output debug
|
||||
);
|
||||
|
||||
reg [7:0] to_arm_shiftreg;
|
||||
|
@ -43,13 +53,9 @@ always @(posedge pck0)
|
|||
begin
|
||||
if((pck_cnt == 8'd7) && !pck_divclk)
|
||||
to_arm_shiftreg <= adc_d;
|
||||
else begin
|
||||
else
|
||||
begin
|
||||
to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0];
|
||||
// simulation showed a glitch occurring due to the LSB of the shifter
|
||||
// not being set as we shift bits out
|
||||
// this ensures the ssp_din remains low after a transfer and suppresses
|
||||
// the glitch that would occur when the last data shifted out ended in
|
||||
// a 1 bit and the next data shifted out started with a 0 bit
|
||||
to_arm_shiftreg[0] <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
@ -84,5 +90,5 @@ assign pwr_lo = lf_field & pck_divclk;
|
|||
// ADC clock out of phase with antenna driver
|
||||
assign adc_clk = ~pck_divclk;
|
||||
// ADC clock also routed to debug pin
|
||||
assign dbg = adc_clk;
|
||||
assign debug = adc_clk;
|
||||
endmodule
|
|
@ -22,23 +22,27 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
module lo_simulate(
|
||||
pck0, ck_1356meg, ck_1356megb,
|
||||
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
|
||||
adc_d, adc_clk,
|
||||
ssp_frame, ssp_din, ssp_dout, ssp_clk,
|
||||
cross_hi, cross_lo,
|
||||
dbg,
|
||||
divisor
|
||||
input pck0,
|
||||
input ck_1356meg,
|
||||
input ck_1356megb,
|
||||
input [7:0] adc_d,
|
||||
input [7:0] divisor,
|
||||
input cross_hi,
|
||||
input cross_lo,
|
||||
input ssp_dout,
|
||||
|
||||
output ssp_din,
|
||||
output ssp_frame,
|
||||
output ssp_clk,
|
||||
output adc_clk,
|
||||
output pwr_lo,
|
||||
output pwr_hi,
|
||||
output pwr_oe1,
|
||||
output pwr_oe2,
|
||||
output pwr_oe3,
|
||||
output pwr_oe4,
|
||||
output debug
|
||||
);
|
||||
input pck0, ck_1356meg, ck_1356megb;
|
||||
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
|
||||
input [7:0] adc_d;
|
||||
output adc_clk;
|
||||
input ssp_dout;
|
||||
output ssp_frame, ssp_din, ssp_clk;
|
||||
input cross_hi, cross_lo;
|
||||
output dbg;
|
||||
input [7:0] divisor;
|
||||
|
||||
// No logic, straight through.
|
||||
assign pwr_oe3 = 1'b0;
|
||||
|
@ -48,7 +52,7 @@ assign pwr_oe4 = ssp_dout;
|
|||
assign ssp_clk = cross_lo;
|
||||
assign pwr_lo = 1'b0;
|
||||
assign pwr_hi = 1'b0;
|
||||
assign dbg = ssp_frame;
|
||||
assign debug = ssp_frame;
|
||||
|
||||
// Divide the clock to be used for the ADC
|
||||
reg [7:0] pck_divider;
|
|
@ -36,7 +36,12 @@
|
|||
// See details about its design see
|
||||
// https://fail0verflow.com/blog/2014/proxmark3-fpga-iir-filter.html
|
||||
|
||||
module lp20khz_1MSa_iir_filter(input clk, input [7:0] adc_d, output rdy, output [7:0] out);
|
||||
module lp20khz_1MSa_iir_filter(
|
||||
input clk,
|
||||
input [7:0] adc_d,
|
||||
output rdy,
|
||||
output [7:0] out
|
||||
);
|
||||
|
||||
// clk is 24MHz, the IIR filter is designed for 1MS/s
|
||||
// hence we need to divide it by 24
|
|
@ -23,8 +23,13 @@
|
|||
// This algorithm therefore can't be used directly for realtime peak detections,
|
||||
// but it can be used as a simple envelope follower.
|
||||
|
||||
module min_max_tracker(input clk, input [7:0] adc_d, input [7:0] threshold,
|
||||
output [7:0] min, output [7:0] max);
|
||||
module min_max_tracker(
|
||||
input clk,
|
||||
input [7:0] adc_d,
|
||||
input [7:0] threshold,
|
||||
output [7:0] min,
|
||||
output [7:0] max
|
||||
);
|
||||
|
||||
reg [7:0] min_val = 255;
|
||||
reg [7:0] max_val = 0;
|
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
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module mux2_one(sel, y, x0, x1);
|
||||
input [1:0] sel;
|
||||
input x0, x1;
|
||||
output y;
|
||||
reg y;
|
||||
module mux2_one(
|
||||
input [1:0] sel,
|
||||
output reg y,
|
||||
input x0,
|
||||
input x1
|
||||
);
|
||||
|
||||
always @(x0 or x1 or sel)
|
||||
always @(*)
|
||||
begin
|
||||
case (sel)
|
||||
1'b0: y = x1;
|
|
@ -4,13 +4,14 @@
|
|||
// kombi, 2020.05
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
module mux2_oneout(sel, y, x0, x1);
|
||||
input [1:0] sel;
|
||||
output x0, x1;
|
||||
input y;
|
||||
reg x0, x1;
|
||||
module mux2_oneout(
|
||||
input [1:0] sel,
|
||||
input y,
|
||||
output reg x0,
|
||||
output reg x1
|
||||
);
|
||||
|
||||
always @(x0 or x1 or sel)
|
||||
always @(*)
|
||||
begin
|
||||
case (sel)
|
||||
1'b0: x1 = y;
|
|
@ -17,23 +17,25 @@
|
|||
// General-purpose miscellany.
|
||||
//
|
||||
|
||||
module mux8(sel, y, x0, x1, x2, x3, x4, x5, x6, x7);
|
||||
input [2:0] sel;
|
||||
input x0, x1, x2, x3, x4, x5, x6, x7;
|
||||
output y;
|
||||
reg y;
|
||||
// 8 inputs to 1 output multiplexer
|
||||
module mux8(
|
||||
input [2:0] sel,
|
||||
output reg y,
|
||||
input x0, x1, x2, x3, x4, x5, x6, x7
|
||||
);
|
||||
|
||||
always @(x0 or x1 or x2 or x3 or x4 or x5 or x6 or x7 or sel)
|
||||
always @(*)
|
||||
begin
|
||||
// y = x[sel];
|
||||
case (sel)
|
||||
3'b000: y = x0;
|
||||
3'b001: y = x1;
|
||||
3'b010: y = x2;
|
||||
3'b011: y = x3;
|
||||
3'b100: y = x4;
|
||||
3'b101: y = x5;
|
||||
3'b110: y = x6;
|
||||
3'b111: y = x7;
|
||||
3'd0: y = x0;
|
||||
3'd1: y = x1;
|
||||
3'd2: y = x2;
|
||||
3'd3: y = x3;
|
||||
3'd4: y = x4;
|
||||
3'd5: y = x5;
|
||||
3'd6: y = x6;
|
||||
3'd7: y = x7;
|
||||
endcase
|
||||
end
|
||||
|
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