Unified fpga folders

This commit is contained in:
d18c7db 2023-05-30 19:47:27 +02:00
parent 1107c214c5
commit c59bdec4f2
114 changed files with 1852 additions and 4814 deletions

12
.gitignore vendored
View file

@ -80,17 +80,7 @@ tools/mfd_aes_brute/mfd_aes_brute
tools/mfd_aes_brute/mfd_multi_brute tools/mfd_aes_brute/mfd_multi_brute
tools/mfd_aes_brute/brute_key tools/mfd_aes_brute/brute_key
fpga/* fpga/__build*
!fpga/tests
!fpga/fpga_lf.bit
!fpga/fpga_hf.bit
!fpga/*.v
!fpga/Makefile
!fpga/fpga.ucf
!fpga/xst_lf.scr
!fpga/xst_hf.scr
!fpga/go.bat
!fpga/sim.tcl
# offcial dumps folder # offcial dumps folder
dumps/* dumps/*

View file

@ -103,9 +103,6 @@ endif
# Generic standalone Mode injection of source code # Generic standalone Mode injection of source code
include Standalone/Makefile.inc include Standalone/Makefile.inc
#the FPGA bitstream files. Note: order matters!
FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit fpga_felica.bit fpga_hf_15.bit
#the lz4 source files required for decompressing the fpga config at run time #the lz4 source files required for decompressing the fpga config at run time
SRC_LZ4 = lz4.c SRC_LZ4 = lz4.c
#additional defines required to compile lz4 #additional defines required to compile lz4

View file

@ -404,16 +404,22 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3
/* Four byte length field */ /* Four byte length field */
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16;
numbytes += 2; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
default: /* Fall through, two byte length field */ current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
numbytes += 4;
if (current_length > 300*1024) {
/* section e should never exceed about 300KB, if the length is too big limit it but still send the bitstream just in case */
current_length = 300*1024;
}
break;
default: /* Two byte length field */
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8;
current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0; current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0;
numbytes += 2; numbytes += 2;
} if (current_length > 64) {
/* if text field is too long, keep it but truncate it */
if (current_name != 'e' && current_length > 255) { current_length = 64;
/* Maybe a parse error */ }
break;
} }
if (current_name == section_name) { if (current_name == section_name) {

View file

@ -44,7 +44,7 @@ OBJDIR = obj
INCLUDE = -I../include -I../common_arm -I../common_fpga -I../common -I. INCLUDE = -I../include -I../common_arm -I../common_fpga -I../common -I.
# Also search prerequisites in the common directory (for usb.c), the fpga directory (for fpga.bit), and the lz4 directory # Also search prerequisites in the common directory (for usb.c), the fpga directory (for fpga.bit), and the lz4 directory
VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/lz4 ../fpga-$(PLATFORM_FPGA) ../armsrc/Standalone VPATH = . ../common_arm ../common ../common/crapto1 ../common/mbedtls ../common/lz4 ../fpga ../armsrc/Standalone
INCLUDES = ../include/proxmark3_arm.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/pm3_cmd.h INCLUDES = ../include/proxmark3_arm.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/pm3_cmd.h

View file

@ -92,18 +92,26 @@ PLTNAME = Unknown Platform
PLATFORM_FPGA = fpga-undefined PLATFORM_FPGA = fpga-undefined
ifeq ($(PLATFORM),PM3RDV4) ifeq ($(PLATFORM),PM3RDV4)
# FPGA bitstream files, the order matters!
FPGA_BITSTREAMS = fpga_pm3_lf.bit fpga_pm3_hf.bit fpga_pm3_felica.bit fpga_pm3_hf_15.bit
PLATFORM_DEFS = -DWITH_SMARTCARD -DWITH_FLASH -DRDV4 PLATFORM_DEFS = -DWITH_SMARTCARD -DWITH_FLASH -DRDV4
PLTNAME = Proxmark3 RDV4 PLTNAME = Proxmark3 RDV4
PLATFORM_FPGA = xc2s30 PLATFORM_FPGA = xc2s30
RDV4 = yes RDV4 = yes
else ifeq ($(PLATFORM),PM3OTHER) else ifeq ($(PLATFORM),PM3OTHER)
$(warning PLATFORM=PM3OTHER is deprecated, please use PLATFORM=PM3GENERIC) $(warning PLATFORM=PM3OTHER is deprecated, please use PLATFORM=PM3GENERIC)
# FPGA bitstream files, the order matters!
FPGA_BITSTREAMS = fpga_pm3_lf.bit fpga_pm3_hf.bit fpga_pm3_felica.bit fpga_pm3_hf_15.bit
PLTNAME = Proxmark3 generic target PLTNAME = Proxmark3 generic target
PLATFORM_FPGA = xc2s30 PLATFORM_FPGA = xc2s30
else ifeq ($(PLATFORM),PM3GENERIC) else ifeq ($(PLATFORM),PM3GENERIC)
# FPGA bitstream files, the order matters!
FPGA_BITSTREAMS = fpga_pm3_lf.bit fpga_pm3_hf.bit fpga_pm3_felica.bit fpga_pm3_hf_15.bit
PLTNAME = Proxmark3 generic target PLTNAME = Proxmark3 generic target
PLATFORM_FPGA = xc2s30 PLATFORM_FPGA = xc2s30
else ifeq ($(PLATFORM),PM3ICOPYX) else ifeq ($(PLATFORM),PM3ICOPYX)
# FPGA bitstream files, the order matters - only hf has a bitstream, the other 3 files are 0 bytes
FPGA_BITSTREAMS = fpga_icopyx_lf.bit fpga_icopyx_hf.bit fpga_icopyx_felica.bit fpga_icopyx_hf_15.bit
PLATFORM_DEFS = -DWITH_FLASH -DICOPYX -DXC3 PLATFORM_DEFS = -DWITH_FLASH -DICOPYX -DXC3
PLTNAME = iCopy-X with XC3S100E PLTNAME = iCopy-X with XC3S100E
PLATFORM_FPGA = xc3s100e PLATFORM_FPGA = xc3s100e
@ -246,6 +254,7 @@ export PLATFORM_DEFS
export PLATFORM_DEFS_INFO export PLATFORM_DEFS_INFO
export PLATFORM_DEFS_INFO_STANDALONE export PLATFORM_DEFS_INFO_STANDALONE
export PLATFORM_CHANGED export PLATFORM_CHANGED
export FPGA_BITSTREAMS
$(info ===================================================================) $(info ===================================================================)
$(info Version info: $(shell tools/mkversion.sh --short 2>/dev/null || ../tools/mkversion.sh --short 2>/dev/null)) $(info Version info: $(shell tools/mkversion.sh --short 2>/dev/null || ../tools/mkversion.sh --short 2>/dev/null))

View file

@ -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

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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/

View file

@ -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

View file

@ -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 .
)

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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."
}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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
View 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 "################################################################"

View file

@ -14,7 +14,12 @@
// See LICENSE.txt for the text of the license. // See LICENSE.txt for the text of the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
module clk_divider(input clk, input [7:0] divisor, output [7:0] div_cnt, output div_clk); module clk_divider(
input clk,
input [7:0] divisor,
output [7:0] div_cnt,
output div_clk
);
reg [7:0] div_cnt_ = 0; reg [7:0] div_cnt_ = 0;
reg div_clk_; reg div_clk_;

155
fpga/define.v Normal file
View 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

Binary file not shown.

227
fpga/fpga_icopyx_hf.v Normal file
View 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
View file

218
fpga/fpga_icopyx_lf.v Normal file
View 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

View file

@ -1,37 +1,61 @@
////////////////////////////////////////////////////////////////////////////////// //-----------------------------------------------------------------------------
// Company: // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
// Engineer:
// //
// Create Date: 16:09:14 05/13/2020 // This program is free software: you can redistribute it and/or modify
// Design Name: // it under the terms of the GNU General Public License as published by
// Module Name: fpga_all_in_one // the Free Software Foundation, either version 3 of the License, or
// Project Name: // (at your option) any later version.
// Target Devices:
// Tool versions:
// Description:
// //
// Dependencies: // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// //
// Revision: // See LICENSE.txt for the text of the license.
// Revision 0.01 - File Created //-----------------------------------------------------------------------------
// Additional Comments:
// //
////////////////////////////////////////////////////////////////////////////////// // The FPGA is responsible for interfacing between the A/D, the coil drivers,
module fpga_hf( // and the ARM. In the low-frequency modes it passes the data straight
input spck, output miso, input mosi, input ncs, // through, so that the ARM gets raw A/D samples over the SSP. In the high-
input pck0, input ck_1356meg, input ck_1356megb, // frequency modes, the FPGA might perform some demodulation first, to
output pwr_lo, output pwr_hi, // reduce the amount of data that we must send to the ARM.
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, //-----------------------------------------------------------------------------
input [7:0] adc_d, output adc_clk, output adc_noe, //`include "fpga_lf.v"
output ssp_frame, output ssp_din, input ssp_dout, output ssp_clk, //`include "fpga_hf.v"
input cross_hi, input cross_lo, //`include "mux2_onein.v"
//`include "mux2_oneout.v"
//`include "util.v"
module fpga_top(
input spck,
output miso,
input mosi,
input ncs,
input pck0,
input ck_1356meg,
input ck_1356megb,
output pwr_lo,
output pwr_hi,
output pwr_oe1,
output pwr_oe2,
output pwr_oe3,
output pwr_oe4,
input [7:0] adc_d,
output adc_clk,
output adc_noe,
output ssp_frame,
output ssp_din,
input ssp_dout,
output ssp_clk,
input cross_hi,
input cross_lo,
output dbg, output dbg,
output PWR_LO_EN, output PWR_LO_EN,
input FPGA_SWITCH input FPGA_SWITCH
); );
fpga_hfmod hfmod( fpga_hf hfmod(
hfspck, hfmiso, hfmosi, hfncs, hfspck, hfmiso, hfmosi, hfncs,
hfpck0, hfck_1356meg, hfck_1356megb, hfpck0, hfck_1356meg, hfck_1356megb,
hfpwr_lo, hfpwr_hi, hfpwr_lo, hfpwr_hi,
@ -39,10 +63,10 @@ fpga_hfmod hfmod(
adc_d, hfadc_clk, hfadc_noe, adc_d, hfadc_clk, hfadc_noe,
hfssp_frame, hfssp_din, hfssp_dout, hfssp_clk, hfssp_frame, hfssp_din, hfssp_dout, hfssp_clk,
hfcross_hi, hfcross_lo, hfcross_hi, hfcross_lo,
hfdbg hfdebug
); );
fpga_lfmod lfmod( fpga_lf lfmod(
lfspck, lfmiso, lfmosi, lfncs, lfspck, lfmiso, lfmosi, lfncs,
lfpck0, lfck_1356meg, lfck_1356megb, lfpck0, lfck_1356meg, lfck_1356megb,
lfpwr_lo, lfpwr_hi, lfpwr_lo, lfpwr_hi,
@ -50,7 +74,7 @@ fpga_lfmod lfmod(
adc_d, lfadc_clk, lfadc_noe, adc_d, lfadc_clk, lfadc_noe,
lfssp_frame, lfssp_din, lfssp_dout, lfssp_clk, lfssp_frame, lfssp_din, lfssp_dout, lfssp_clk,
lfcross_hi, lfcross_lo, lfcross_hi, lfcross_lo,
lfdbg, lfdebug,
lfPWR_LO_EN lfPWR_LO_EN
); );
@ -75,7 +99,7 @@ mux2_oneout mux_ssp_dout_all (FPGA_SWITCH, ssp_dout, hfss
mux2_one mux_ssp_clk_all (FPGA_SWITCH, ssp_clk, hfssp_clk, lfssp_clk); mux2_one mux_ssp_clk_all (FPGA_SWITCH, ssp_clk, hfssp_clk, lfssp_clk);
mux2_oneout mux_cross_hi_all (FPGA_SWITCH, cross_hi, hfcross_hi, lfcross_hi); mux2_oneout mux_cross_hi_all (FPGA_SWITCH, cross_hi, hfcross_hi, lfcross_hi);
mux2_oneout mux_cross_lo_all (FPGA_SWITCH, cross_lo, hfcross_lo, lfcross_lo); mux2_oneout mux_cross_lo_all (FPGA_SWITCH, cross_lo, hfcross_lo, lfcross_lo);
mux2_one mux_dbg_all (FPGA_SWITCH, dbg, hfdbg, lfdbg); mux2_one mux_dbg_all (FPGA_SWITCH, dbg, hfdebug, lfdebug);
mux2_one mux_PWR_LO_EN_all (FPGA_SWITCH, PWR_LO_EN, 1'b0, lfPWR_LO_EN); mux2_one mux_PWR_LO_EN_all (FPGA_SWITCH, PWR_LO_EN, 1'b0, lfPWR_LO_EN);
endmodule endmodule

BIN
fpga/fpga_pm3_felica.bit Normal file

Binary file not shown.

BIN
fpga/fpga_pm3_hf.bit Normal file

Binary file not shown.

BIN
fpga/fpga_pm3_hf_15.bit Normal file

Binary file not shown.

BIN
fpga/fpga_pm3_lf.bit Normal file

Binary file not shown.

438
fpga/fpga_pm3_top.v Normal file
View 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

View file

@ -30,33 +30,30 @@
*/ */
module hi_flite( module hi_flite(
ck_1356meg, input ck_1356meg,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, input [7:0] adc_d,
adc_d, adc_clk, input [3:0] mod_type,
ssp_frame, ssp_din, ssp_dout, ssp_clk, input ssp_dout,
dbg,
mod_type output reg ssp_din,
output reg ssp_frame,
output reg ssp_clk,
output adc_clk,
output reg pwr_lo,
output reg pwr_hi,
output reg pwr_oe1,
output reg pwr_oe2,
output reg pwr_oe3,
output reg pwr_oe4,
output debug
); );
input ck_1356meg;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
input [7:0] adc_d;
output adc_clk;
input ssp_dout;
output ssp_frame, ssp_din, ssp_clk;
output dbg;
input [3:0] mod_type;
assign dbg = 0; assign debug = 0;
wire power = mod_type[2]; wire power = mod_type[2];
wire speed = mod_type[1]; wire speed = mod_type[1];
wire disabl = mod_type[0]; wire disabl = mod_type[0];
// Most off, oe4 for modulation;
// Trying reader emulation (would presumably just require switching power on, but I am not sure)
assign pwr_lo = 1'b0;
assign pwr_oe2 = 1'b0;
// 512x64/fc -wait before ts0, 32768 ticks // 512x64/fc -wait before ts0, 32768 ticks
// tslot: 256*64/fc // tslot: 256*64/fc
assign adc_clk = ck_1356meg; assign adc_clk = ck_1356meg;
@ -95,10 +92,6 @@ reg did_sync=0;
wire [7:0] bithalf = speed ? `bithalf_424 : `bithalf_212; wire [7:0] bithalf = speed ? `bithalf_424 : `bithalf_212;
wire [7:0] bitmlen = speed ? `bitmlen_424 : `bitmlen_212; wire [7:0] bitmlen = speed ? `bitmlen_424 : `bitmlen_212;
//ssp clock and current values
reg ssp_clk;
reg ssp_frame;
reg curbit = 1'b0; reg curbit = 1'b0;
reg [7:0] fccount = 8'd0; // in-bit tick counter. Counts carrier cycles from the first lower edge detected, reset on every manchester bit detected reg [7:0] fccount = 8'd0; // in-bit tick counter. Counts carrier cycles from the first lower edge detected, reset on every manchester bit detected
@ -107,6 +100,7 @@ reg [7:0] tsinceedge = 8'd0;// ticks from last edge, desync if the valye is too
reg zero = 1'b0; // Manchester first halfbit low second high corresponds to this value. It has been known to change. SYNC is used to set it reg zero = 1'b0; // Manchester first halfbit low second high corresponds to this value. It has been known to change. SYNC is used to set it
//ssp clock and current values
//ssp counter for transfer and framing //ssp counter for transfer and framing
reg [8:0] ssp_cnt = 9'd0; reg [8:0] ssp_cnt = 9'd0;
@ -122,6 +116,7 @@ begin
if( ((~speed) && (ssp_cnt[5:0] == 6'b000000)) || (speed && (ssp_cnt[4:0] == 5'b00000))) if( ((~speed) && (ssp_cnt[5:0] == 6'b000000)) || (speed && (ssp_cnt[4:0] == 5'b00000)))
begin begin
ssp_clk <= 1'b1; ssp_clk <= 1'b1;
//send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise)
ssp_din <= curbit; ssp_din <= curbit;
end end
if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000)) if( ( (~speed) && (ssp_cnt[5:0] == 6'b100000)) ||(speed && ssp_cnt[4:0] == 5'b10000))
@ -138,9 +133,6 @@ begin
end end
end end
//send current bit (detected in SNIFF mode or the one being modulated in MOD mode, 0 otherwise)
reg ssp_din;
//previous signal value, mostly to detect SYNC //previous signal value, mostly to detect SYNC
reg prv = 1'b1; reg prv = 1'b1;
@ -353,11 +345,8 @@ begin
end end
// sending <= 0; // sending <= 0;
end end
//put modulation here to maintain the correct clock. Seems that some readers are sensitive to that //put modulation here to maintain the correct clock. Seems that some readers are sensitive to that
reg pwr_hi;
reg pwr_oe1;
reg pwr_oe3;
reg pwr_oe4;
wire mod = ((fccount >= bithalf) ^ dlay) & (~disabl); wire mod = ((fccount >= bithalf) ^ dlay) & (~disabl);
@ -365,21 +354,22 @@ always @(ck_1356meg or ssp_dout or power or disabl or mod)
begin begin
if (power) if (power)
begin begin
pwr_hi <= ck_1356meg; pwr_hi <= ck_1356meg;
pwr_lo <= 1'b0;
pwr_oe1 <= 1'b0;//mod; pwr_oe1 <= 1'b0;//mod;
pwr_oe2 <= 1'b0;//mod;
pwr_oe3 <= 1'b0;//mod; pwr_oe3 <= 1'b0;//mod;
pwr_oe4 <= mod;//1'b0; pwr_oe4 <= mod;//1'b0;
end end
else else
begin begin
pwr_hi <= 1'b0; pwr_hi <= 1'b0;
pwr_lo <= 1'b0;
pwr_oe1 <= 1'b0; pwr_oe1 <= 1'b0;
pwr_oe2 <= 1'b0;
pwr_oe3 <= 1'b0; pwr_oe3 <= 1'b0;
pwr_oe4 <= mod; pwr_oe4 <= mod;
end end
end end
endmodule endmodule

View file

@ -13,17 +13,18 @@
// //
// See LICENSE.txt for the text of the license. // See LICENSE.txt for the text of the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//`include "define.v"
module hi_get_trace( module hi_get_trace(
ck_1356megb, input ck_1356megb,
adc_d, trace_enable, major_mode, input [7:0] adc_d,
ssp_frame, ssp_din, ssp_clk input trace_enable,
input [2:0] major_mode,
output ssp_din,
output reg ssp_frame,
output reg ssp_clk
); );
input ck_1356megb;
input [7:0] adc_d;
input trace_enable;
input [2:0] major_mode;
output ssp_frame, ssp_din, ssp_clk;
// clock divider // clock divider
reg [6:0] clock_cnt; reg [6:0] clock_cnt;
@ -88,9 +89,9 @@ begin
write_enable2 <= 1'b0; write_enable2 <= 1'b0;
end end
else else
begin begin
addr <= addr + 1; addr <= addr + 1;
end end
end end
end end
else else
@ -136,9 +137,6 @@ begin
end end
// SSC communication to ARM
reg ssp_clk;
reg ssp_frame;
reg [7:0] shift_out; reg [7:0] shift_out;
always @(negedge ck_1356megb) always @(negedge ck_1356megb)
@ -147,16 +145,16 @@ begin
begin begin
if (clock_cnt[6:4] == 3'd0) // either load new value if (clock_cnt[6:4] == 3'd0) // either load new value
begin begin
if (addr[11] == 1'b0) if (addr[11] == 1'b0)
shift_out <= D_out1; shift_out <= D_out1;
else else
shift_out <= D_out2; shift_out <= D_out2;
end end
else else
begin begin
// or shift left // or shift left
shift_out[7:1] <= shift_out[6:0]; shift_out[7:1] <= shift_out[6:0];
end end
end end
ssp_clk <= ~clock_cnt[3]; // ssp_clk frequency = 13,56MHz / 16 = 847,5 kHz ssp_clk <= ~clock_cnt[3]; // ssp_clk frequency = 13,56MHz / 16 = 847,5 kHz

View file

@ -14,29 +14,28 @@
// See LICENSE.txt for the text of the license. // See LICENSE.txt for the text of the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// ISO14443-A support for the Proxmark III // ISO14443-A support for the Proxmark III
// //`include "define.v"
module hi_iso14443a( module hi_iso14443a(
ck_1356meg, input ck_1356meg,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, input [7:0] adc_d,
adc_d, adc_clk, input [3:0] mod_type,
ssp_frame, ssp_din, ssp_dout, ssp_clk, input ssp_dout,
dbg,
mod_type output ssp_din,
output reg ssp_frame,
output reg ssp_clk,
output adc_clk,
output pwr_lo,
output pwr_hi,
output pwr_oe1,
output pwr_oe2,
output pwr_oe3,
output pwr_oe4,
output debug
); );
input ck_1356meg;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
input [7:0] adc_d;
output adc_clk;
input ssp_dout;
output ssp_frame, ssp_din, ssp_clk;
output dbg;
input [3:0] mod_type;
wire adc_clk = ck_1356meg;
assign adc_clk = ck_1356meg;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Reader -> PM3: // Reader -> PM3:
@ -76,8 +75,6 @@ begin
end end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Reader -> PM3 // Reader -> PM3
// detect when a reader is active (modulating). We assume that the reader is active, if we see the carrier off for at least 8 // detect when a reader is active (modulating). We assume that the reader is active, if we see the carrier off for at least 8
@ -137,7 +134,6 @@ wire [9:0] tmp2 = adc_d_times_2 + input_prev_1;
wire signed [10:0] adc_d_filtered = {1'b0, tmp1} - {1'b0, tmp2}; wire signed [10:0] adc_d_filtered = {1'b0, tmp1} - {1'b0, tmp2};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// internal FPGA timing. Maximum required period is 128 carrier clock cycles for a full 8 Bit transfer to ARM. (i.e. we need a // internal FPGA timing. Maximum required period is 128 carrier clock cycles for a full 8 Bit transfer to ARM. (i.e. we need a
// 7 bit counter). Adjust its frequency to external reader's clock when simulating a tag or sniffing. // 7 bit counter). Adjust its frequency to external reader's clock when simulating a tag or sniffing.
@ -222,7 +218,11 @@ reg signed [10:0] rx_mod_falling_edge_max;
reg signed [10:0] rx_mod_rising_edge_max; reg signed [10:0] rx_mod_rising_edge_max;
reg curbit; reg curbit;
`ifdef PM3ICOPYX
`define EDGE_DETECT_THRESHOLD 3
`else
`define EDGE_DETECT_THRESHOLD 5 `define EDGE_DETECT_THRESHOLD 5
`endif
`define EDGE_DETECT_THRESHOLDHIGH 20 `define EDGE_DETECT_THRESHOLDHIGH 20
always @(negedge adc_clk) always @(negedge adc_clk)
@ -266,7 +266,6 @@ begin
end end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Tag+Reader -> PM3 // Tag+Reader -> PM3
// sample 4 bits reader data and 4 bits tag data for sniffing // sample 4 bits reader data and 4 bits tag data for sniffing
@ -283,7 +282,6 @@ begin
end end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PM3 -> Reader: // PM3 -> Reader:
// a delay line to ensure that we send the (emulated) tag's answer at the correct time according to ISO14443-3 // a delay line to ensure that we send the (emulated) tag's answer at the correct time according to ISO14443-3
@ -307,7 +305,6 @@ begin
end end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PM3 -> Reader, internal timing: // PM3 -> Reader, internal timing:
// a timer for the 1172 cycles fdt (Frame Delay Time). Start the timer with a rising edge of the reader's signal. // a timer for the 1172 cycles fdt (Frame Delay Time). Start the timer with a rising edge of the reader's signal.
@ -400,7 +397,6 @@ begin
end end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PM3 -> Reader // PM3 -> Reader
// determine the required delay in the mod_sig_buf (set mod_sig_ptr). // determine the required delay in the mod_sig_buf (set mod_sig_ptr).
@ -444,7 +440,6 @@ begin
end end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FPGA -> ARM communication: // FPGA -> ARM communication:
// buffer 8 bits data to be sent to ARM. Shift them out bit by bit. // buffer 8 bits data to be sent to ARM. Shift them out bit by bit.
@ -495,8 +490,6 @@ end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FPGA <-> ARM communication: // FPGA <-> ARM communication:
// generate a ssp clock and ssp frame signal for the synchronous transfer from/to the ARM // generate a ssp clock and ssp frame signal for the synchronous transfer from/to the ARM
reg ssp_clk;
reg ssp_frame;
always @(negedge adc_clk) always @(negedge adc_clk)
begin begin
@ -529,7 +522,6 @@ begin
end end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// FPGA -> ARM communication: // FPGA -> ARM communication:
// select the data to be sent to ARM // select the data to be sent to ARM
@ -553,7 +545,6 @@ begin
sendbit = 1'b0; sendbit = 1'b0;
end end
if(mod_type == `FPGA_HF_ISO14443A_SNIFFER) if(mod_type == `FPGA_HF_ISO14443A_SNIFFER)
// send sampled reader and tag data: // send sampled reader and tag data:
bit_to_arm = to_arm[7]; bit_to_arm = to_arm[7];
@ -589,6 +580,6 @@ assign pwr_oe4 = mod_sig_coil & sub_carrier & (mod_type == `FPGA_HF_ISO14443A_TA
assign pwr_oe2 = 1'b0; assign pwr_oe2 = 1'b0;
assign pwr_lo = 1'b0; assign pwr_lo = 1'b0;
assign dbg = negedge_cnt[3]; assign debug = negedge_cnt[3];
endmodule endmodule

View file

@ -13,24 +13,27 @@
// //
// See LICENSE.txt for the text of the license. // See LICENSE.txt for the text of the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//`include "define.v"
module hi_reader( module hi_reader(
ck_1356meg, input ck_1356meg,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, input [7:0] adc_d,
adc_d, adc_clk, input [1:0] subcarrier_frequency,
ssp_frame, ssp_din, ssp_dout, ssp_clk, input [3:0] minor_mode,
dbg, input ssp_dout,
subcarrier_frequency, minor_mode
output ssp_din,
output reg ssp_frame,
output reg ssp_clk,
output adc_clk,
output pwr_lo,
output reg pwr_hi,
output pwr_oe1,
output pwr_oe2,
output pwr_oe3,
output reg pwr_oe4,
output debug
); );
input ck_1356meg;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
input [7:0] adc_d;
output adc_clk;
input ssp_dout;
output ssp_frame, ssp_din, ssp_clk;
output dbg;
input [1:0] subcarrier_frequency;
input [3:0] minor_mode;
assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz
@ -160,7 +163,6 @@ begin
end end
else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ) else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ)
begin begin
// Send 7 most significant bits of in phase tag signal (signed), plus 1 bit reader signal // Send 7 most significant bits of in phase tag signal (signed), plus 1 bit reader signal
if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111) if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111)
corr_i_out <= {corr_i_accum[11:5], after_hysteresis_prev_prev}; corr_i_out <= {corr_i_accum[11:5], after_hysteresis_prev_prev};
@ -261,9 +263,6 @@ end
// corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ... // corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ...
// //
reg ssp_clk;
reg ssp_frame;
always @(negedge adc_clk) always @(negedge adc_clk)
begin begin
if (corr_i_cnt[1:0] == 2'b00) if (corr_i_cnt[1:0] == 2'b00)
@ -298,9 +297,6 @@ begin
end end
end end
// Antenna drivers
reg pwr_hi, pwr_oe4;
always @(*) always @(*)
begin begin
if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD) if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD)
@ -341,6 +337,6 @@ assign pwr_lo = 1'b0;
assign pwr_oe2 = 1'b0; assign pwr_oe2 = 1'b0;
// Debug Output // Debug Output
assign dbg = corr_i_cnt[3]; assign debug = corr_i_cnt[3];
endmodule endmodule

View file

@ -14,25 +14,26 @@
// See LICENSE.txt for the text of the license. // See LICENSE.txt for the text of the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// modified to add support for iso15 2sc mode // modified to add support for iso15 2sc mode
//
module hi_15_reader( module hi_reader_15(
ck_1356meg, input ck_1356meg,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, input [7:0] adc_d,
adc_d, adc_clk, input [1:0] subcarrier_frequency,
ssp_frame, ssp_din, ssp_dout, ssp_clk, input [3:0] minor_mode,
dbg, input ssp_dout,
subcarrier_frequency, minor_mode
output ssp_din,
output reg ssp_frame,
output reg ssp_clk,
output adc_clk,
output pwr_lo,
output reg pwr_hi,
output pwr_oe1,
output pwr_oe2,
output pwr_oe3,
output reg pwr_oe4,
output debug
); );
input ck_1356meg;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
input [7:0] adc_d;
output adc_clk;
input ssp_dout;
output ssp_frame, ssp_din, ssp_clk;
output dbg;
input [1:0] subcarrier_frequency;
input [3:0] minor_mode;
assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz
@ -379,9 +380,6 @@ end
// corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ... // corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ...
// //
reg ssp_clk;
reg ssp_frame;
always @(negedge adc_clk) always @(negedge adc_clk)
begin begin
if (corr_i_cnt[1:0] == 2'b00) if (corr_i_cnt[1:0] == 2'b00)
@ -416,9 +414,6 @@ begin
end end
end end
// Antenna drivers
reg pwr_hi, pwr_oe4;
always @(*) always @(*)
begin begin
if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD) if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD)
@ -459,6 +454,6 @@ assign pwr_lo = 1'b0;
assign pwr_oe2 = 1'b0; assign pwr_oe2 = 1'b0;
// Debug Output // Debug Output
assign dbg = corr_i_cnt[3]; assign debug = corr_i_cnt[3];
endmodule endmodule

View file

@ -30,23 +30,26 @@
// //
// Jonathan Westhues, October 2006 // Jonathan Westhues, October 2006
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
//`include "define.v"
module hi_simulate( module hi_simulate(
ck_1356meg, input ck_1356meg,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, input [7:0] adc_d,
adc_d, adc_clk, input [3:0] mod_type,
ssp_frame, ssp_din, ssp_dout, ssp_clk, input ssp_dout,
dbg,
mod_type output reg ssp_din,
output reg ssp_frame,
output reg ssp_clk,
output adc_clk,
output pwr_lo,
output pwr_hi,
output pwr_oe1,
output pwr_oe2,
output pwr_oe3,
output pwr_oe4,
output debug
); );
input ck_1356meg;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
input [7:0] adc_d;
output adc_clk;
input ssp_dout;
output ssp_frame, ssp_din, ssp_clk;
output dbg;
input [3:0] mod_type;
// Power amp goes between LOW and tri-state, so pwr_hi (and pwr_lo) can // Power amp goes between LOW and tri-state, so pwr_hi (and pwr_lo) can
// always be low. // always be low.
@ -57,7 +60,7 @@ assign pwr_lo = 1'b0; // LF antenna connected to GND
assign pwr_oe2 = 1'b0; assign pwr_oe2 = 1'b0;
assign adc_clk = ck_1356meg; assign adc_clk = ck_1356meg;
assign dbg = ssp_frame; assign debug = ssp_frame;
// The comparator with hysteresis on the output from the peak detector. // The comparator with hysteresis on the output from the peak detector.
reg after_hysteresis; reg after_hysteresis;
@ -94,8 +97,6 @@ reg [8:0] ssp_clk_divider;
always @(negedge adc_clk) always @(negedge adc_clk)
ssp_clk_divider <= (ssp_clk_divider + 1); ssp_clk_divider <= (ssp_clk_divider + 1);
reg ssp_clk;
always @(negedge adc_clk) always @(negedge adc_clk)
begin begin
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT) if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT)
@ -112,7 +113,6 @@ end
// Produce the byte framing signal; the phase of this signal // Produce the byte framing signal; the phase of this signal
// is arbitrary, because it's just a bit stream in this module. // is arbitrary, because it's just a bit stream in this module.
reg ssp_frame;
always @(negedge adc_clk) always @(negedge adc_clk)
begin begin
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K) if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K)
@ -133,7 +133,6 @@ end
// Synchronize up the after-hysteresis signal, to produce DIN. // Synchronize up the after-hysteresis signal, to produce DIN.
reg ssp_din;
always @(posedge ssp_clk) always @(posedge ssp_clk)
ssp_din = after_hysteresis; ssp_din = after_hysteresis;

View file

@ -15,16 +15,20 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
module hi_sniffer( module hi_sniffer(
ck_1356meg, input ck_1356meg,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, input [7:0] adc_d,
adc_d, adc_clk,
ssp_frame, ssp_din, ssp_clk output ssp_din,
output reg ssp_frame,
output ssp_clk,
output adc_clk,
output pwr_lo,
output pwr_hi,
output pwr_oe1,
output pwr_oe2,
output pwr_oe3,
output pwr_oe4
); );
input ck_1356meg;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
input [7:0] adc_d;
output adc_clk;
output ssp_frame, ssp_din, ssp_clk;
// We are only snooping, all off. // We are only snooping, all off.
assign pwr_hi = 1'b0; assign pwr_hi = 1'b0;
@ -34,12 +38,13 @@ assign pwr_oe2 = 1'b0;
assign pwr_oe3 = 1'b0; assign pwr_oe3 = 1'b0;
assign pwr_oe4 = 1'b0; assign pwr_oe4 = 1'b0;
reg ssp_frame; //reg ssp_frame;
reg [7:0] adc_d_out = 8'd0; reg [7:0] adc_d_out = 8'd0;
reg [2:0] ssp_cnt = 3'd0; reg [2:0] ssp_cnt = 3'd0;
assign adc_clk = ck_1356meg; assign adc_clk = ck_1356meg;
assign ssp_clk = ~ck_1356meg; assign ssp_clk = ~ck_1356meg;
assign ssp_din = adc_d_out[0];
always @(posedge ssp_clk) always @(posedge ssp_clk)
begin begin
@ -49,18 +54,16 @@ begin
ssp_cnt <= ssp_cnt + 1; ssp_cnt <= ssp_cnt + 1;
if(ssp_cnt[2:0] == 3'b000) // set frame length if(ssp_cnt[2:0] == 3'b000) // set frame length
begin begin
adc_d_out[7:0] <= adc_d; adc_d_out[7:0] <= adc_d;
ssp_frame <= 1'b1; ssp_frame <= 1'b1;
end end
else else
begin begin
adc_d_out[7:0] <= {1'b0, adc_d_out[7:1]}; // shift value right one bit
ssp_frame <= 1'b0; adc_d_out[7:0] <= {1'b0, adc_d_out[7:1]};
end ssp_frame <= 1'b0;
end
end end
assign ssp_din = adc_d_out[0];
endmodule endmodule

View file

@ -15,23 +15,37 @@
// See LICENSE.txt for the text of the license. // See LICENSE.txt for the text of the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// input clk is 24MHz // input clk is 24MHz
`include "min_max_tracker.v" //`include "min_max_tracker.v"
module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold, module lf_edge_detect(
output [7:0] max, output [7:0] min, input clk,
output [7:0] high_threshold, output [7:0] highz_threshold, input [7:0] adc_d,
output [7:0] lowz_threshold, output [7:0] low_threshold, input [7:0] lf_ed_threshold,
output edge_state, output edge_toggle);
min_max_tracker tracker(clk, adc_d, lf_ed_threshold, min, max); output [7:0] max,
output [7:0] min,
output [7:0] low_threshold,
output [7:0] high_threshold,
output [7:0] lowz_threshold,
output [7:0] highz_threshold,
output edge_state,
output edge_toggle
);
min_max_tracker tracker(
.clk (clk),
.adc_d (adc_d),
.threshold (lf_ed_threshold),
.min (min),
.max (max)
);
// auto-tune // auto-tune
assign high_threshold = (max + min) / 2 + (max - min) / 4; assign high_threshold = (max + min) / 2 + (max - min) / 4;
assign highz_threshold = (max + min) / 2 + (max - min) / 8; assign highz_threshold = (max + min) / 2 + (max - min) / 8;
assign lowz_threshold = (max + min) / 2 - (max - min) / 8; assign lowz_threshold = (max + min) / 2 - (max - min) / 8;
assign low_threshold = (max + min) / 2 - (max - min) / 4; assign low_threshold = (max + min) / 2 - (max - min) / 4;
// heuristic to see if it makes sense to try to detect an edge // heuristic to see if it makes sense to try to detect an edge
wire enabled = wire enabled =
@ -55,18 +69,20 @@ module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold,
always @(posedge clk) always @(posedge clk)
begin begin
is_high <= (adc_d >= high_threshold); is_high <= (adc_d >= high_threshold);
is_low <= (adc_d <= low_threshold); is_low <= (adc_d <= low_threshold);
is_zero <= ((adc_d > lowz_threshold) & (adc_d < highz_threshold)); is_zero <= ((adc_d > lowz_threshold) & (adc_d < highz_threshold));
end end
// all edges detection // all edges detection
always @(posedge clk) always @(posedge clk)
if (enabled) begin if (enabled)
begin
// To enable detecting two consecutive peaks at the same level // To enable detecting two consecutive peaks at the same level
// (low or high) we check whether or not we went back near 0 in-between. // (low or high) we check whether or not we went back near 0 in-between.
// This extra check is necessary to prevent from noise artifacts // This extra check is necessary to prevent from noise artifacts
// around the threshold values. // around the threshold values.
if (trigger_enabled & (is_high | is_low)) begin if (trigger_enabled & (is_high | is_low))
begin
output_edge <= ~output_edge; output_edge <= ~output_edge;
trigger_enabled <= 0; trigger_enabled <= 0;
end else end else
@ -75,14 +91,15 @@ module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold,
// edge states // edge states
always @(posedge clk) always @(posedge clk)
if (enabled) begin if (enabled)
begin
if (is_high) if (is_high)
output_state <= 1'd1; output_state <= 1'd1;
else if (is_low) else if (is_low)
output_state <= 1'd0; output_state <= 1'd0;
end end
assign edge_state = output_state; assign edge_state = output_state;
assign edge_toggle = output_edge; assign edge_toggle = output_edge;
endmodule endmodule

View file

@ -22,22 +22,24 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
module lo_adc( module lo_adc(
pck0, input pck0,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, input [7:0] adc_d,
adc_d, adc_clk, input [7:0] divisor,
ssp_frame, ssp_din, ssp_dout, ssp_clk, input lf_field,
dbg, divisor, input ssp_dout,
lf_field
output ssp_din,
output ssp_frame,
output ssp_clk,
output adc_clk,
output pwr_lo,
output pwr_hi,
output pwr_oe1,
output pwr_oe2,
output pwr_oe3,
output pwr_oe4,
output debug
); );
input pck0;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
input [7:0] adc_d;
output adc_clk;
input ssp_dout;
output ssp_frame, ssp_din, ssp_clk;
output dbg;
input [7:0] divisor;
input lf_field;
reg [7:0] to_arm_shiftreg; reg [7:0] to_arm_shiftreg;
reg [7:0] pck_divider; reg [7:0] pck_divider;
@ -49,16 +51,16 @@ wire reader_modulation = !ssp_dout & lf_field & clk_state;
// always on (High Frequency outputs, unused) // always on (High Frequency outputs, unused)
assign pwr_oe1 = 1'b0; assign pwr_oe1 = 1'b0;
assign pwr_hi = 1'b0; assign pwr_hi = 1'b0;
// low frequency outputs // low frequency outputs
assign pwr_lo = reader_modulation; assign pwr_lo = reader_modulation;
assign pwr_oe2 = 1'b0; // 33 Ohms assign pwr_oe2 = 1'b0; // 33 Ohms
assign pwr_oe3 = tag_modulation; // base antenna load = 33 Ohms assign pwr_oe3 = tag_modulation; // base antenna load = 33 Ohms
assign pwr_oe4 = 1'b0; // 10k Ohms assign pwr_oe4 = 1'b0; // 10k Ohms
// Debug Output ADC clock // Debug Output ADC clock
assign dbg = adc_clk; assign debug = adc_clk;
// ADC clock out of phase with antenna driver // ADC clock out of phase with antenna driver
assign adc_clk = ~clk_state; assign adc_clk = ~clk_state;
@ -76,10 +78,10 @@ assign ssp_frame = (pck_divider[7:3] == 5'd1) && !clk_state;
always @(posedge pck0) always @(posedge pck0)
begin begin
if (pck_divider == divisor[7:0]) if (pck_divider == divisor[7:0])
begin begin
pck_divider <= 8'd0; pck_divider <= 8'd0;
clk_state = !clk_state; clk_state = !clk_state;
end end
else else
begin begin
pck_divider <= pck_divider + 1; pck_divider <= pck_divider + 1;
@ -92,13 +94,9 @@ always @(posedge pck0)
begin begin
if ((pck_divider == 8'd7) && !clk_state) if ((pck_divider == 8'd7) && !clk_state)
to_arm_shiftreg <= adc_d; to_arm_shiftreg <= adc_d;
else begin else
begin
to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0];
// simulation showed a glitch occurring due to the LSB of the shifter
// not being set as we shift bits out
// this ensures the ssp_din remains low after a transfer and suppresses
// the glitch that would occur when the last data shifted out ended in
// a 1 bit and the next data shifted out started with a 0 bit
to_arm_shiftreg[0] <= 1'b0; to_arm_shiftreg[0] <= 1'b0;
end end
end end

View file

@ -25,19 +25,29 @@
// - ssp_frame (wired to TIOA1 on the arm) for the edge detection/state // - ssp_frame (wired to TIOA1 on the arm) for the edge detection/state
// - ssp_clk: cross_lo // - ssp_clk: cross_lo
`include "lp20khz_1MSa_iir_filter.v" //`include "lp20khz_1MSa_iir_filter.v"
`include "lf_edge_detect.v" //`include "lf_edge_detect.v"
module lo_edge_detect( module lo_edge_detect(
input pck0, input pck_divclk, input pck0,
output pwr_lo, output pwr_hi, input pck_divclk,
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, input [7:0] adc_d,
input [7:0] adc_d, output adc_clk,
output ssp_frame, input ssp_dout, output ssp_clk,
input cross_lo, input cross_lo,
output dbg,
input lf_field, input lf_field,
input lf_ed_toggle_mode, input [7:0] lf_ed_threshold input lf_ed_toggle_mode,
input [7:0] lf_ed_threshold,
input ssp_dout,
output ssp_frame,
output ssp_clk,
output adc_clk,
output pwr_lo,
output pwr_hi,
output pwr_oe1,
output pwr_oe2,
output pwr_oe3,
output pwr_oe4,
output debug
); );
wire tag_modulation = ssp_dout & !lf_field; wire tag_modulation = ssp_dout & !lf_field;
@ -58,18 +68,34 @@ assign pwr_hi = 1'b0;
wire data_rdy; wire data_rdy;
wire [7:0] adc_filtered; wire [7:0] adc_filtered;
assign adc_clk = pck0; assign adc_clk = pck0;
lp20khz_1MSa_iir_filter adc_filter(pck0, adc_d, data_rdy, adc_filtered);
lp20khz_1MSa_iir_filter adc_filter(
.clk (pck0),
.adc_d (adc_d),
.rdy (data_rdy),
.out (adc_filtered)
);
// detect edges // detect edges
wire [7:0] high_threshold, highz_threshold, lowz_threshold, low_threshold; wire [7:0] high_threshold, highz_threshold, lowz_threshold, low_threshold;
wire [7:0] max, min; wire [7:0] max, min;
wire edge_state, edge_toggle; wire edge_state, edge_toggle;
lf_edge_detect lf_ed(pck0, adc_filtered, lf_ed_threshold,
max, min,
high_threshold, highz_threshold, lowz_threshold, low_threshold,
edge_state, edge_toggle);
assign dbg = lf_ed_toggle_mode ? edge_toggle : edge_state; lf_edge_detect lf_ed(
.clk (pck0),
.adc_d (adc_filtered),
.lf_ed_threshold (lf_ed_threshold),
.max (max),
.min (min),
.high_threshold (high_threshold),
.highz_threshold (highz_threshold),
.lowz_threshold (lowz_threshold),
.low_threshold (low_threshold),
.edge_state (edge_state),
.edge_toggle (edge_toggle)
);
assign debug = lf_ed_toggle_mode ? edge_toggle : edge_state;
assign ssp_frame = lf_ed_toggle_mode ? edge_toggle : edge_state; assign ssp_frame = lf_ed_toggle_mode ? edge_toggle : edge_state;

View file

@ -17,27 +17,32 @@
// For reading TI tags, we need to place the FPGA in pass through mode // For reading TI tags, we need to place the FPGA in pass through mode
// and pass everything through to the ARM // and pass everything through to the ARM
module lo_passthru( module lo_passthru(
input pck_divclk, input pck_divclk,
output pwr_lo, output pwr_hi,
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
output adc_clk,
output ssp_din, input ssp_dout,
input cross_lo, input cross_lo,
output dbg input ssp_dout,
output ssp_din,
output adc_clk,
output pwr_lo,
output pwr_hi,
output pwr_oe1,
output pwr_oe2,
output pwr_oe3,
output pwr_oe4,
output debug
); );
// the antenna is modulated when ssp_dout = 1, when 0 the // the antenna is modulated when ssp_dout = 1, when 0 the
// antenna drivers stop modulating and go into listen mode // antenna drivers stop modulating and go into listen mode
assign pwr_oe3 = 1'b0; assign ssp_din = cross_lo;
assign adc_clk = 1'b0;
assign pwr_lo = pck_divclk && ssp_dout;
assign pwr_hi = 1'b0;
assign pwr_oe1 = ssp_dout; assign pwr_oe1 = ssp_dout;
assign pwr_oe2 = ssp_dout; assign pwr_oe2 = ssp_dout;
assign pwr_oe3 = 1'b0;
assign pwr_oe4 = ssp_dout; assign pwr_oe4 = ssp_dout;
assign pwr_lo = pck_divclk && ssp_dout; assign debug = cross_lo;
assign pwr_hi = 1'b0;
assign adc_clk = 1'b0;
assign ssp_din = cross_lo;
assign dbg = cross_lo;
endmodule endmodule

View file

@ -22,13 +22,23 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
module lo_read( module lo_read(
input pck0, input [7:0] pck_cnt, input pck_divclk, input pck0,
output pwr_lo, output pwr_hi, input pck_divclk,
output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4, input [7:0] pck_cnt,
input [7:0] adc_d, output adc_clk, input [7:0] adc_d,
output ssp_frame, output ssp_din, output ssp_clk, input lf_field,
output dbg,
input lf_field output ssp_din,
output ssp_frame,
output ssp_clk,
output adc_clk,
output pwr_lo,
output pwr_hi,
output pwr_oe1,
output pwr_oe2,
output pwr_oe3,
output pwr_oe4,
output debug
); );
reg [7:0] to_arm_shiftreg; reg [7:0] to_arm_shiftreg;
@ -43,13 +53,9 @@ always @(posedge pck0)
begin begin
if((pck_cnt == 8'd7) && !pck_divclk) if((pck_cnt == 8'd7) && !pck_divclk)
to_arm_shiftreg <= adc_d; to_arm_shiftreg <= adc_d;
else begin else
begin
to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0];
// simulation showed a glitch occurring due to the LSB of the shifter
// not being set as we shift bits out
// this ensures the ssp_din remains low after a transfer and suppresses
// the glitch that would occur when the last data shifted out ended in
// a 1 bit and the next data shifted out started with a 0 bit
to_arm_shiftreg[0] <= 1'b0; to_arm_shiftreg[0] <= 1'b0;
end end
end end
@ -74,7 +80,7 @@ assign ssp_clk = pck0;
// SSP frame is gated by ant_lo and goes high when pck_divider=8..15 // SSP frame is gated by ant_lo and goes high when pck_divider=8..15
assign ssp_frame = (pck_cnt[7:3] == 5'd1) && !pck_divclk; assign ssp_frame = (pck_cnt[7:3] == 5'd1) && !pck_divclk;
// unused signals tied low // unused signals tied low
assign pwr_hi = 1'b0; assign pwr_hi = 1'b0;
assign pwr_oe1 = 1'b0; assign pwr_oe1 = 1'b0;
assign pwr_oe2 = 1'b0; assign pwr_oe2 = 1'b0;
assign pwr_oe3 = 1'b0; assign pwr_oe3 = 1'b0;
@ -84,5 +90,5 @@ assign pwr_lo = lf_field & pck_divclk;
// ADC clock out of phase with antenna driver // ADC clock out of phase with antenna driver
assign adc_clk = ~pck_divclk; assign adc_clk = ~pck_divclk;
// ADC clock also routed to debug pin // ADC clock also routed to debug pin
assign dbg = adc_clk; assign debug = adc_clk;
endmodule endmodule

View file

@ -22,23 +22,27 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
module lo_simulate( module lo_simulate(
pck0, ck_1356meg, ck_1356megb, input pck0,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, input ck_1356meg,
adc_d, adc_clk, input ck_1356megb,
ssp_frame, ssp_din, ssp_dout, ssp_clk, input [7:0] adc_d,
cross_hi, cross_lo, input [7:0] divisor,
dbg, input cross_hi,
divisor input cross_lo,
input ssp_dout,
output ssp_din,
output ssp_frame,
output ssp_clk,
output adc_clk,
output pwr_lo,
output pwr_hi,
output pwr_oe1,
output pwr_oe2,
output pwr_oe3,
output pwr_oe4,
output debug
); );
input pck0, ck_1356meg, ck_1356megb;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
input [7:0] adc_d;
output adc_clk;
input ssp_dout;
output ssp_frame, ssp_din, ssp_clk;
input cross_hi, cross_lo;
output dbg;
input [7:0] divisor;
// No logic, straight through. // No logic, straight through.
assign pwr_oe3 = 1'b0; assign pwr_oe3 = 1'b0;
@ -46,9 +50,9 @@ assign pwr_oe1 = ssp_dout;
assign pwr_oe2 = ssp_dout; assign pwr_oe2 = ssp_dout;
assign pwr_oe4 = ssp_dout; assign pwr_oe4 = ssp_dout;
assign ssp_clk = cross_lo; assign ssp_clk = cross_lo;
assign pwr_lo = 1'b0; assign pwr_lo = 1'b0;
assign pwr_hi = 1'b0; assign pwr_hi = 1'b0;
assign dbg = ssp_frame; assign debug = ssp_frame;
// Divide the clock to be used for the ADC // Divide the clock to be used for the ADC
reg [7:0] pck_divider; reg [7:0] pck_divider;

View file

@ -36,7 +36,12 @@
// See details about its design see // See details about its design see
// https://fail0verflow.com/blog/2014/proxmark3-fpga-iir-filter.html // https://fail0verflow.com/blog/2014/proxmark3-fpga-iir-filter.html
module lp20khz_1MSa_iir_filter(input clk, input [7:0] adc_d, output rdy, output [7:0] out); module lp20khz_1MSa_iir_filter(
input clk,
input [7:0] adc_d,
output rdy,
output [7:0] out
);
// clk is 24MHz, the IIR filter is designed for 1MS/s // clk is 24MHz, the IIR filter is designed for 1MS/s
// hence we need to divide it by 24 // hence we need to divide it by 24

View file

@ -23,8 +23,13 @@
// This algorithm therefore can't be used directly for realtime peak detections, // This algorithm therefore can't be used directly for realtime peak detections,
// but it can be used as a simple envelope follower. // but it can be used as a simple envelope follower.
module min_max_tracker(input clk, input [7:0] adc_d, input [7:0] threshold, module min_max_tracker(
output [7:0] min, output [7:0] max); input clk,
input [7:0] adc_d,
input [7:0] threshold,
output [7:0] min,
output [7:0] max
);
reg [7:0] min_val = 255; reg [7:0] min_val = 255;
reg [7:0] max_val = 0; reg [7:0] max_val = 0;

50
fpga/mux16.v Normal file
View 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

View file

@ -4,13 +4,14 @@
// kombi, 2020.05 // kombi, 2020.05
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
module mux2_one(sel, y, x0, x1); module mux2_one(
input [1:0] sel; input [1:0] sel,
input x0, x1; output reg y,
output y; input x0,
reg y; input x1
);
always @(x0 or x1 or sel) always @(*)
begin begin
case (sel) case (sel)
1'b0: y = x1; 1'b0: y = x1;

View file

@ -4,13 +4,14 @@
// kombi, 2020.05 // kombi, 2020.05
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
module mux2_oneout(sel, y, x0, x1); module mux2_oneout(
input [1:0] sel; input [1:0] sel,
output x0, x1; input y,
input y; output reg x0,
reg x0, x1; output reg x1
);
always @(x0 or x1 or sel) always @(*)
begin begin
case (sel) case (sel)
1'b0: x1 = y; 1'b0: x1 = y;

View file

@ -17,23 +17,25 @@
// General-purpose miscellany. // General-purpose miscellany.
// //
module mux8(sel, y, x0, x1, x2, x3, x4, x5, x6, x7); // 8 inputs to 1 output multiplexer
input [2:0] sel; module mux8(
input x0, x1, x2, x3, x4, x5, x6, x7; input [2:0] sel,
output y; output reg y,
reg y; input x0, x1, x2, x3, x4, x5, x6, x7
);
always @(x0 or x1 or x2 or x3 or x4 or x5 or x6 or x7 or sel) always @(*)
begin begin
// y = x[sel];
case (sel) case (sel)
3'b000: y = x0; 3'd0: y = x0;
3'b001: y = x1; 3'd1: y = x1;
3'b010: y = x2; 3'd2: y = x2;
3'b011: y = x3; 3'd3: y = x3;
3'b100: y = x4; 3'd4: y = x4;
3'b101: y = x5; 3'd5: y = x5;
3'b110: y = x6; 3'd6: y = x6;
3'b111: y = x7; 3'd7: y = x7;
endcase endcase
end end

View file

Some files were not shown because too many files have changed in this diff Show more