THIS REQUIRES A BOOTROM UPDATE!! To save FPGA area, split the LF and HF bitstreams and load them on-demand.

This commit is contained in:
iZsh 2014-06-20 01:02:59 +02:00
parent d51b2eda8f
commit 7cc204bff8
32 changed files with 771 additions and 661 deletions

6
.gitignore vendored
View file

@ -19,11 +19,13 @@ lua
luac luac
fpga/* fpga/*
!fpga/fpga.bit !fpga/fpga_lf.bit
!fpga/fpga_hf.bit
!fpga/*.v !fpga/*.v
!fpga/Makefile !fpga/Makefile
!fpga/fpga.ucf !fpga/fpga.ucf
!fpga/xst.scr !fpga/xst_lf.scr
!fpga/xst_hf.scr
!fpga/go.bat !fpga/go.bat
!fpga/sim.tcl !fpga/sim.tcl

View file

@ -52,10 +52,13 @@ OBJS = $(OBJDIR)/osimage.s19 $(OBJDIR)/fpgaimage.s19
all: $(OBJS) all: $(OBJS)
$(OBJDIR)/fpga.o: fpga.bit $(OBJDIR)/fpga_lf.o: fpga_lf.bit
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --redefine-sym _binary____fpga_fpga_bit_start=_binary_fpga_bit_start --redefine-sym _binary____fpga_fpga_bit_end=_binary_fpga_bit_end --prefix-sections=fpga_bit $^ $@ $(OBJCOPY) -O elf32-littlearm -I binary -B arm --redefine-sym _binary____fpga_fpga_lf_bit_start=_binary_fpga_lf_bit_start --redefine-sym _binary____fpga_fpga_lf_bit_end=_binary_fpga_lf_bit_end --prefix-sections=fpga_lf_bit $^ $@
$(OBJDIR)/fullimage.elf: $(VERSIONOBJ) $(OBJDIR)/fpga.o $(THUMBOBJ) $(ARMOBJ) $(OBJDIR)/fpga_hf.o: fpga_hf.bit
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --redefine-sym _binary____fpga_fpga_hf_bit_start=_binary_fpga_hf_bit_start --redefine-sym _binary____fpga_fpga_hf_bit_end=_binary_fpga_hf_bit_end --prefix-sections=fpga_hf_bit $^ $@
$(OBJDIR)/fullimage.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_lf.o $(OBJDIR)/fpga_hf.o $(THUMBOBJ) $(ARMOBJ)
$(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) $(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS)
$(OBJDIR)/fpgaimage.elf: $(OBJDIR)/fullimage.elf $(OBJDIR)/fpgaimage.elf: $(OBJDIR)/fullimage.elf

View file

@ -214,6 +214,7 @@ void MeasureAntennaTuning(void)
* ( hopefully around 95 if it is tuned to 125kHz!) * ( hopefully around 95 if it is tuned to 125kHz!)
*/ */
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
for (i=255; i>19; i--) { for (i=255; i>19; i--) {
WDT_HIT(); WDT_HIT();
@ -236,6 +237,7 @@ void MeasureAntennaTuning(void)
LED_A_ON(); LED_A_ON();
// Let the FPGA drive the high-frequency antenna around 13.56 MHz. // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
SpinDelay(20); SpinDelay(20);
// Vref = 3300mV, and an 10:1 voltage divider on the input // Vref = 3300mV, and an 10:1 voltage divider on the input
@ -264,6 +266,7 @@ void MeasureAntennaTuningHf(void)
for (;;) { for (;;) {
// Let the FPGA drive the high-frequency antenna around 13.56 MHz. // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
SpinDelay(20); SpinDelay(20);
// Vref = 3300mV, and an 10:1 voltage divider on the input // Vref = 3300mV, and an 10:1 voltage divider on the input
@ -286,6 +289,7 @@ void SimulateTagHfListen(void)
// We're using this mode just so that I can test it out; the simulated // We're using this mode just so that I can test it out; the simulated
// tag mode would work just as well and be simpler. // tag mode would work just as well and be simpler.
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
// We need to listen to the high-frequency, peak-detected path. // We need to listen to the high-frequency, peak-detected path.
@ -365,6 +369,7 @@ void SendVersion(void)
void SamyRun() void SamyRun()
{ {
DbpString("Stand-alone mode! No PC necessary."); DbpString("Stand-alone mode! No PC necessary.");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// 3 possible options? no just 2 for now // 3 possible options? no just 2 for now
#define OPTS 2 #define OPTS 2
@ -923,6 +928,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
break; break;
case CMD_SET_LF_DIVISOR: case CMD_SET_LF_DIVISOR:
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->arg[0]); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->arg[0]);
break; break;
@ -1017,7 +1023,8 @@ void __attribute__((noreturn)) AppMain(void)
AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
// Load the FPGA image, which we have stored in our flash. // Load the FPGA image, which we have stored in our flash.
FpgaDownloadAndGo(); // (the HF version by default)
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
StartTickCount(); StartTickCount();

View file

@ -67,7 +67,8 @@ extern uint32_t BigBuf[];
/// fpga.h /// fpga.h
void FpgaSendCommand(uint16_t cmd, uint16_t v); void FpgaSendCommand(uint16_t cmd, uint16_t v);
void FpgaWriteConfWord(uint8_t v); void FpgaWriteConfWord(uint8_t v);
void FpgaDownloadAndGo(void); void FpgaDownloadAndGo(int bitstream_version);
int FpgaGatherBitstreamVersion();
void FpgaGatherVersion(char *dst, int len); void FpgaGatherVersion(char *dst, int len);
void FpgaSetupSsc(void); void FpgaSetupSsc(void);
void SetupSpi(int mode); void SetupSpi(int mode);
@ -80,13 +81,16 @@ void SetAdcMuxFor(uint32_t whichGpio);
#define FPGA_CMD_SET_CONFREG (1<<12) #define FPGA_CMD_SET_CONFREG (1<<12)
#define FPGA_CMD_SET_DIVISOR (2<<12) #define FPGA_CMD_SET_DIVISOR (2<<12)
// Definitions for the FPGA configuration word. // Definitions for the FPGA configuration word.
// LF
#define FPGA_MAJOR_MODE_LF_READER (0<<5) #define FPGA_MAJOR_MODE_LF_READER (0<<5)
#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5) #define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5)
#define FPGA_MAJOR_MODE_HF_READER_TX (2<<5) #define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5)
#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (3<<5) // HF
#define FPGA_MAJOR_MODE_HF_SIMULATOR (4<<5) #define FPGA_MAJOR_MODE_HF_READER_TX (0<<5)
#define FPGA_MAJOR_MODE_HF_ISO14443A (5<<5) #define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5)
#define FPGA_MAJOR_MODE_LF_PASSTHRU (6<<5) #define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5)
#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5)
// BOTH
#define FPGA_MAJOR_MODE_OFF (7<<5) #define FPGA_MAJOR_MODE_OFF (7<<5)
// Options for LF_EDGE_DETECT // Options for LF_EDGE_DETECT
#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0) #define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0)

View file

@ -252,7 +252,7 @@ static void DownloadFPGA(const char *FpgaImage, int FpgaImageLen, int byterevers
static char *bitparse_headers_start; static char *bitparse_headers_start;
static char *bitparse_bitstream_end; static char *bitparse_bitstream_end;
static int bitparse_initialized; static int bitparse_initialized = 0;
/* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence /* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence
* 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01 * 00 09 0f f0 0f f0 0f f0 0f f0 00 00 01
* After that the format is 1 byte section type (ASCII character), 2 byte length * After that the format is 1 byte section type (ASCII character), 2 byte length
@ -322,12 +322,28 @@ int bitparse_find_section(char section_name, char **section_start, unsigned int
// Find out which FPGA image format is stored in flash, then call DownloadFPGA // Find out which FPGA image format is stored in flash, then call DownloadFPGA
// with the right parameters to download the image // with the right parameters to download the image
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
extern char _binary_fpga_bit_start, _binary_fpga_bit_end; extern char _binary_fpga_lf_bit_start, _binary_fpga_lf_bit_end;
void FpgaDownloadAndGo(void) extern char _binary_fpga_hf_bit_start, _binary_fpga_hf_bit_end;
void FpgaDownloadAndGo(int bitstream_version)
{ {
void *bit_start;
void *bit_end;
// check whether or not the bitstream is already loaded
if (FpgaGatherBitstreamVersion() == bitstream_version)
return;
if (bitstream_version == FPGA_BITSTREAM_LF) {
bit_start = &_binary_fpga_lf_bit_start;
bit_end = &_binary_fpga_lf_bit_end;
} else if (bitstream_version == FPGA_BITSTREAM_HF) {
bit_start = &_binary_fpga_hf_bit_start;
bit_end = &_binary_fpga_hf_bit_end;
} else
return;
/* Check for the new flash image format: Should have the .bit file at &_binary_fpga_bit_start /* Check for the new flash image format: Should have the .bit file at &_binary_fpga_bit_start
*/ */
if(bitparse_init(&_binary_fpga_bit_start, &_binary_fpga_bit_end)) { if(bitparse_init(bit_start, bit_end)) {
/* Successfully initialized the .bit parser. Find the 'e' section and /* Successfully initialized the .bit parser. Find the 'e' section and
* send its contents to the FPGA. * send its contents to the FPGA.
*/ */
@ -351,6 +367,17 @@ void FpgaDownloadAndGo(void)
DownloadFPGA((char*)0x102000, 10524*4, 1); DownloadFPGA((char*)0x102000, 10524*4, 1);
} }
int FpgaGatherBitstreamVersion()
{
char temp[256];
FpgaGatherVersion(temp, sizeof (temp));
if (!memcmp("LF", temp, 2))
return FPGA_BITSTREAM_LF;
else if (!memcmp("HF", temp, 2))
return FPGA_BITSTREAM_HF;
return FPGA_BITSTREAM_ERR;
}
void FpgaGatherVersion(char *dst, int len) void FpgaGatherVersion(char *dst, int len)
{ {
char *fpga_info; char *fpga_info;
@ -359,13 +386,15 @@ void FpgaGatherVersion(char *dst, int len)
if(!bitparse_find_section('e', &fpga_info, &fpga_info_len)) { if(!bitparse_find_section('e', &fpga_info, &fpga_info_len)) {
strncat(dst, "FPGA image: legacy image without version information", len-1); strncat(dst, "FPGA image: legacy image without version information", len-1);
} else { } else {
strncat(dst, "FPGA image built", len-1);
/* USB packets only have 48 bytes data payload, so be terse */ /* USB packets only have 48 bytes data payload, so be terse */
#if 0
if(bitparse_find_section('a', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) { if(bitparse_find_section('a', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {
strncat(dst, " from ", len-1); if (!memcmp("fpga_lf", fpga_info, 7))
strncat(dst, fpga_info, len-1); strncat(dst, "LF ", len-1);
else if (!memcmp("fpga_hf", fpga_info, 7))
strncat(dst, "HF ", len-1);
} }
strncat(dst, "FPGA image built", len-1);
#if 0
if(bitparse_find_section('b', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) { if(bitparse_find_section('b', &fpga_info, &fpga_info_len) && fpga_info[fpga_info_len-1] == 0 ) {
strncat(dst, " for ", len-1); strncat(dst, " for ", len-1);
strncat(dst, fpga_info, len-1); strncat(dst, fpga_info, len-1);

View file

@ -743,6 +743,7 @@ void SnoopHitag(uint32_t type) {
// Set up eavesdropping mode, frequency divisor which will drive the FPGA // Set up eavesdropping mode, frequency divisor which will drive the FPGA
// and analog mux selection. // and analog mux selection.
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD); SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
@ -966,6 +967,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
// Set up simulator mode, frequency divisor which will drive the FPGA // Set up simulator mode, frequency divisor which will drive the FPGA
// and analog mux selection. // and analog mux selection.
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD); SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
@ -1124,6 +1126,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
bool bStop; bool bStop;
bool bQuitTraceFull = false; bool bQuitTraceFull = false;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// Reset the return status // Reset the return status
bSuccessful = false; bSuccessful = false;

View file

@ -689,6 +689,8 @@ void RAMFUNC SnoopIClass(void)
// into trace, along with its length and other annotations. // into trace, along with its length and other annotations.
//uint8_t *trace = (uint8_t *)BigBuf; //uint8_t *trace = (uint8_t *)BigBuf;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// reset traceLen to 0 // reset traceLen to 0
iso14a_set_tracing(TRUE); iso14a_set_tracing(TRUE);
iso14a_clear_trace(); iso14a_clear_trace();
@ -995,6 +997,8 @@ void SimulateIClass(uint8_t arg0, uint8_t *datain)
{ {
uint8_t simType = arg0; uint8_t simType = arg0;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Enable and clear the trace // Enable and clear the trace
tracing = TRUE; tracing = TRUE;
traceLen = 0; traceLen = 0;
@ -1426,6 +1430,8 @@ void ReaderIClass(uint8_t arg0) {
uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes uint8_t* resp = (((uint8_t *)BigBuf) + 3560); // was 3560 - tied to other size changes
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Reset trace buffer // Reset trace buffer
memset(trace, 0x44, RECV_CMD_OFFSET); memset(trace, 0x44, RECV_CMD_OFFSET);
traceLen = 0; traceLen = 0;

View file

@ -350,6 +350,7 @@ void SimulateIso14443Tag(void)
int cmdsRecvd = 0; int cmdsRecvd = 0;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
memset(receivedCmd, 0x44, 400); memset(receivedCmd, 0x44, 400);
CodeIso14443bAsTag(response1, sizeof(response1)); CodeIso14443bAsTag(response1, sizeof(response1));
@ -867,6 +868,7 @@ void ReadSTMemoryIso14443(uint32_t dwLast)
{ {
uint8_t i = 0x00; uint8_t i = 0x00;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Make sure that we start from off, since the tags are stateful; // Make sure that we start from off, since the tags are stateful;
// confusing things will happen if we don't reset them between reads. // confusing things will happen if we don't reset them between reads.
LED_D_OFF(); LED_D_OFF();
@ -1011,6 +1013,7 @@ void RAMFUNC SnoopIso14443(void)
// response from the tag. // response from the tag.
int triggered = TRUE; int triggered = TRUE;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// The command (reader -> tag) that we're working on receiving. // The command (reader -> tag) that we're working on receiving.
uint8_t *receivedCmd = (uint8_t *)(BigBuf) + DEMOD_TRACE_SIZE; uint8_t *receivedCmd = (uint8_t *)(BigBuf) + DEMOD_TRACE_SIZE;
// The response (tag -> reader) that we're working on receiving. // The response (tag -> reader) that we're working on receiving.
@ -1196,6 +1199,7 @@ done:
void SendRawCommand14443B(uint32_t datalen, uint32_t recv,uint8_t powerfield, uint8_t data[]) void SendRawCommand14443B(uint32_t datalen, uint32_t recv,uint8_t powerfield, uint8_t data[])
{ {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
if(!powerfield) if(!powerfield)
{ {
// Make sure that we start from off, since the tags are stateful; // Make sure that we start from off, since the tags are stateful;

View file

@ -1763,6 +1763,7 @@ int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, u
} }
void iso14443a_setup(uint8_t fpga_minor_mode) { void iso14443a_setup(uint8_t fpga_minor_mode) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Set up the synchronous serial port // Set up the synchronous serial port
FpgaSetupSsc(); FpgaSetupSsc();
// connect Demodulated Signal to ADC: // connect Demodulated Signal to ADC:

View file

@ -606,6 +606,7 @@ void AcquireRawAdcSamplesIso15693(void)
int8_t prev = 0; int8_t prev = 0;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
BuildIdentifyRequest(); BuildIdentifyRequest();
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
@ -687,6 +688,7 @@ void RecordRawAdcSamplesIso15693(void)
int8_t prev = 0; int8_t prev = 0;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Setup SSC // Setup SSC
FpgaSetupSsc(); FpgaSetupSsc();
@ -753,6 +755,7 @@ void Iso15693InitReader() {
LED_C_OFF(); LED_C_OFF();
LED_D_OFF(); LED_D_OFF();
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Setup SSC // Setup SSC
// FpgaSetupSsc(); // FpgaSetupSsc();
@ -1015,6 +1018,7 @@ void ReaderIso15693(uint32_t parameter)
// Blank arrays // Blank arrays
memset(BigBuf + 3660, 0, 300); memset(BigBuf + 3660, 0, 300);
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Setup SSC // Setup SSC
FpgaSetupSsc(); FpgaSetupSsc();
@ -1165,6 +1169,7 @@ void SimTagIso15693(uint32_t parameter)
// Blank arrays // Blank arrays
memset(answer1, 0, 100); memset(answer1, 0, 100);
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// Setup SSC // Setup SSC
FpgaSetupSsc(); FpgaSetupSsc();

View file

@ -21,7 +21,8 @@ ENTRY(Vector)
SECTIONS SECTIONS
{ {
.fpgaimage : { .fpgaimage : {
*(fpga_bit.data) *(fpga_lf_bit.data)
*(fpga_hf_bit.data)
} >fpgaimage :fpgaimage } >fpgaimage :fpgaimage
.start : { .start : {

View file

@ -310,6 +310,7 @@ static uint32_t perform_setup_phase_rwd(int iv)
} }
static void LegicCommonInit(void) { static void LegicCommonInit(void) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
FpgaSetupSsc(); FpgaSetupSsc();
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
@ -687,6 +688,7 @@ void LegicRfSimulate(int phase, int frame, int reqresp)
legic_frame_drift = frame; legic_frame_drift = frame;
legic_reqresp_drift = reqresp; legic_reqresp_drift = reqresp;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
FpgaSetupSsc(); FpgaSetupSsc();
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_212K); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_212K);

View file

@ -17,6 +17,7 @@
void AcquireRawAdcSamples125k(int divisor) void AcquireRawAdcSamples125k(int divisor)
{ {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
if ( (divisor == 1) || (divisor < 0) || (divisor > 255) ) if ( (divisor == 1) || (divisor < 0) || (divisor > 255) )
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
else if (divisor == 0) else if (divisor == 0)
@ -69,6 +70,7 @@ void ModThenAcquireRawAdcSamples125k(int delay_off, int period_0, int period_1,
int at134khz; int at134khz;
/* Make sure the tag is reset */ /* Make sure the tag is reset */
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
SpinDelay(2500); SpinDelay(2500);
@ -158,6 +160,7 @@ void ReadTItag(void)
uint32_t threshold = (sampleslo - sampleshi + 1)>>1; uint32_t threshold = (sampleslo - sampleshi + 1)>>1;
// TI tags charge at 134.2Khz // TI tags charge at 134.2Khz
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
// Place FPGA in passthrough mode, in this mode the CROSS_LO line // Place FPGA in passthrough mode, in this mode the CROSS_LO line
@ -365,6 +368,7 @@ void AcquireTiType(void)
// if not provided a valid crc will be computed from the data and written. // if not provided a valid crc will be computed from the data and written.
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc) void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc)
{ {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
if(crc == 0) { if(crc == 0) {
crc = update_crc16(crc, (idlo)&0xff); crc = update_crc16(crc, (idlo)&0xff);
crc = update_crc16(crc, (idlo>>8)&0xff); crc = update_crc16(crc, (idlo>>8)&0xff);
@ -436,6 +440,7 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
int i; int i;
uint8_t *tab = (uint8_t *)BigBuf; uint8_t *tab = (uint8_t *)BigBuf;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
@ -602,6 +607,7 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
int m=0, n=0, i=0, idx=0, found=0, lastval=0; int m=0, n=0, i=0, idx=0, found=0, lastval=0;
uint32_t hi2=0, hi=0, lo=0; uint32_t hi2=0, hi=0, lo=0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
@ -815,6 +821,7 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
uint32_t code=0, code2=0; uint32_t code=0, code2=0;
//uint32_t hi2=0, hi=0, lo=0; //uint32_t hi2=0, hi=0, lo=0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
@ -1132,6 +1139,7 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
// Write one bit to card // Write one bit to card
void T55xxWriteBit(int bit) void T55xxWriteBit(int bit)
{ {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
if (bit == 0) if (bit == 0)
@ -1147,6 +1155,7 @@ void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMod
{ {
unsigned int i; unsigned int i;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
@ -1191,6 +1200,7 @@ void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
uint8_t *dest = (uint8_t *)BigBuf; uint8_t *dest = (uint8_t *)BigBuf;
int m=0, i=0; int m=0, i=0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
m = sizeof(BigBuf); m = sizeof(BigBuf);
// Clear destination buffer before sending the command // Clear destination buffer before sending the command
memset(dest, 128, m); memset(dest, 128, m);
@ -1255,6 +1265,7 @@ void T55xxReadTrace(void){
uint8_t *dest = (uint8_t *)BigBuf; uint8_t *dest = (uint8_t *)BigBuf;
int m=0, i=0; int m=0, i=0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
m = sizeof(BigBuf); m = sizeof(BigBuf);
// Clear destination buffer before sending the command // Clear destination buffer before sending the command
memset(dest, 128, m); memset(dest, 128, m);
@ -1970,6 +1981,7 @@ void SendForward(uint8_t fwd_bit_count) {
LED_D_ON(); LED_D_ON();
//Field on //Field on
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);

View file

@ -24,8 +24,10 @@ QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
MOC = $(QTDIR)/bin/moc MOC = $(QTDIR)/bin/moc
LUAPLATFORM = mingw LUAPLATFORM = mingw
else ifeq ($(platform),Darwin) else ifeq ($(platform),Darwin)
CXXFLAGS = -I/Library/Frameworks/QtGui.framework/Versions/Current/Headers -I/Library/Frameworks/QtCore.framework/Versions/Current/Headers #CXXFLAGS = -I/Library/Frameworks/QtGui.framework/Versions/Current/Headers -I/Library/Frameworks/QtCore.framework/Versions/Current/Headers
QTLDLIBS = -framework QtGui -framework QtCore #QTLDLIBS = -framework QtGui -framework QtCore
CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
QTLDLIBS = -F/opt/local/Library/Frameworks -framework QtGui -framework QtCore
MOC = moc MOC = moc
LUAPLATFORM = macosx LUAPLATFORM = macosx
else else

View file

@ -13,8 +13,8 @@ MEMORY
{ {
bootphase1 : ORIGIN = 0x00100000, LENGTH = 0x200 /* Phase 1 bootloader: Copies real bootloader to RAM */ bootphase1 : ORIGIN = 0x00100000, LENGTH = 0x200 /* Phase 1 bootloader: Copies real bootloader to RAM */
bootphase2 : ORIGIN = 0x00100200, LENGTH = 0x2000 - 0x200 /* Main bootloader code, stored in Flash, executed from RAM */ bootphase2 : ORIGIN = 0x00100200, LENGTH = 0x2000 - 0x200 /* Main bootloader code, stored in Flash, executed from RAM */
fpgaimage : ORIGIN = 0x00102000, LENGTH = 64k - 0x2000 /* Place where the FPGA image will end up */ fpgaimage : ORIGIN = 0x00102000, LENGTH = 96k - 0x2000 /* Place where the FPGA image will end up */
osimage : ORIGIN = 0x00110000, LENGTH = 256K - 64k /* Place where the main OS will end up */ osimage : ORIGIN = 0x00118000, LENGTH = 256K - 96k /* Place where the main OS will end up */
ram : ORIGIN = 0x00200000, LENGTH = 64K - 0x20 /* RAM, minus small common area */ ram : ORIGIN = 0x00200000, LENGTH = 64K - 0x20 /* RAM, minus small common area */
commonarea : ORIGIN = 0x00200000 + 64K - 0x20, LENGTH = 0x20 /* Communication between bootloader and main OS */ commonarea : ORIGIN = 0x00200000 + 64K - 0x20, LENGTH = 0x20 /* Communication between bootloader and main OS */
} }

View file

@ -1,31 +1,33 @@
include ../common/Makefile.common include ../common/Makefile.common
all: fpga.ngc fpga.ngd fpga.ncd fpga-placed.ncd fpga.bit all: fpga_lf.bit fpga_hf.bit
clean: clean:
$(DELETE) fpga.bgn fpga.drc fpga.ncd fpga.ngd fpga_par.xrpt fpga-placed.pad fpga-placed.par fpga-placed.xpi fpga_usage.xml xlnx_auto_0.ise xst.srp $(DELETE) *.bgn *.drc *.ncd *.ngd *_par.xrpt *-placed.* *-placed_pad.* *_usage.xml xst_hf.srp xst_lf.srp
$(DELETE) fpga.map fpga.ngc fpga_ngdbuild.xrpt fpga.pcf fpga-placed_pad.csv fpga-placed.ptwx fpga.rbt xlnx_auto_0_xdb $(DELETE) *.map *.ngc *.xrpt *.pcf *.rbt *_auto_* *.bld *.mrp *.ngm *.unroutes *_summary.xml netlist.lst xst
$(DELETE) fpga.bld fpga.mrp fpga.ngc_xst.xrpt fpga.ngm fpga-placed.ncd fpga-placed_pad.txt fpga-placed.unroutes fpga_summary.xml netlist.lst xst
fpga.ngc: fpga.v fpga.ucf xst.scr util.v lo_edge_detect.v lo_read.v lo_passthru.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v fpga_hf.ngc: fpga_hf.v fpga.ucf xst_hf.scr util.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v
$(DELETE) fpga.ngc $(DELETE) $@
$(XILINX_TOOLS_PREFIX)xst -ifn xst.scr $(XILINX_TOOLS_PREFIX)xst -ifn xst_hf.scr
fpga.ngd: fpga.ngc 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
$(DELETE) fpga.ngd $(DELETE) $@
$(XILINX_TOOLS_PREFIX)ngdbuild -aul -p xc2s30-5-vq100 -nt timestamp -uc fpga.ucf fpga.ngc fpga.ngd $(XILINX_TOOLS_PREFIX)xst -ifn xst_lf.scr
fpga.ncd: fpga.ngd %.ngd: %.ngc
$(DELETE) fpga.ncd $(DELETE) $@
$(XILINX_TOOLS_PREFIX)map -p xc2s30-5-vq100 fpga.ngd $(XILINX_TOOLS_PREFIX)ngdbuild -aul -p xc2s30-5-vq100 -nt timestamp -uc fpga.ucf $< $@
fpga-placed.ncd: fpga.ncd %.ncd: %.ngd
$(DELETE) fpga-placed.ncd $(DELETE) $@
$(XILINX_TOOLS_PREFIX)par fpga.ncd fpga-placed.ncd $(XILINX_TOOLS_PREFIX)map -p xc2s30-5-vq100 $<
fpga.bit: fpga-placed.ncd %-placed.ncd: %.ncd
$(DELETE) fpga.bit fpga.drc fpga.rbt $(DELETE) $@
$(XILINX_TOOLS_PREFIX)bitgen fpga-placed.ncd fpga.bit $(XILINX_TOOLS_PREFIX)par $< $@
%.bit: %-placed.ncd
$(DELETE) $@ $*.drc $*.rbt
$(XILINX_TOOLS_PREFIX)bitgen $< $@
.PHONY: all clean help .PHONY: all clean help
help: help:

25
fpga/clk_divider.v Normal file
View file

@ -0,0 +1,25 @@
//-----------------------------------------------------------------------------
// 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

Binary file not shown.

View file

@ -1,220 +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
//-----------------------------------------------------------------------------
`include "lo_read.v"
`include "lo_passthru.v"
`include "lo_edge_detect.v"
`include "hi_read_tx.v"
`include "hi_read_rx_xcorr.v"
`include "hi_simulate.v"
`include "hi_iso14443a.v"
`include "util.v"
module fpga(
spck, miso, mosi, ncs,
pck0, ck_1356meg, ck_1356megb,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
adc_d, adc_clk, adc_noe,
ssp_frame, ssp_din, ssp_dout, ssp_clk,
cross_hi, cross_lo,
dbg
);
input spck, mosi, ncs;
output miso;
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, adc_noe;
input ssp_dout;
output ssp_frame, ssp_din, ssp_clk;
input cross_hi, cross_lo;
output dbg;
//assign pck0 = pck0i;
// IBUFG #(.IOSTANDARD("DEFAULT") ) pck0b(
// .O(pck0),
// .I(pck0i)
// );
//assign spck = spcki;
// IBUFG #(.IOSTANDARD("DEFAULT") ) spckb(
// .O(spck),
// .I(spcki)
// );
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
reg [15:0] shift_reg;
reg [7:0] divisor;
reg [7:0] conf_word;
// 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])
4'b0001: conf_word <= shift_reg[7:0]; // FPGA_CMD_SET_CONFREG
4'b0010: divisor <= shift_reg[7:0]; // FPGA_CMD_SET_DIVISOR
endcase
end
always @(posedge spck)
begin
if(~ncs)
begin
shift_reg[15:1] <= shift_reg[14:0];
shift_reg[0] <= mosi;
end
end
wire [2:0] major_mode;
assign major_mode = conf_word[7:5];
// For the low-frequency configuration:
wire lo_is_125khz;
assign lo_is_125khz = conf_word[3];
// For the high-frequency transmit configuration: modulation depth, either
// 100% (just quite driving antenna, steady LOW), or shallower (tri-state
// some fraction of the buffers)
wire hi_read_tx_shallow_modulation;
assign hi_read_tx_shallow_modulation = conf_word[0];
// For the high-frequency receive correlator: frequency against which to
// correlate.
wire hi_read_rx_xcorr_848;
assign hi_read_rx_xcorr_848 = conf_word[0];
// and whether to drive the coil (reader) or just short it (snooper)
wire hi_read_rx_xcorr_snoop;
assign hi_read_rx_xcorr_snoop = conf_word[1];
// Divide the expected subcarrier frequency for hi_read_rx_xcorr by 4
wire hi_read_rx_xcorr_quarter;
assign hi_read_rx_xcorr_quarter = conf_word[2];
// For the high-frequency simulated tag: what kind of modulation to use.
wire [2:0] hi_simulate_mod_type;
assign hi_simulate_mod_type = conf_word[2:0];
// For the high-frequency simulated tag: what kind of modulation to use.
wire lf_field;
assign lf_field = conf_word[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.
//-----------------------------------------------------------------------------
lo_read lr(
pck0, ck_1356meg, ck_1356megb,
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, ssp_dout, lr_ssp_clk,
cross_hi, cross_lo,
lr_dbg,
lo_is_125khz, divisor
);
lo_passthru lp(
pck0, ck_1356meg, ck_1356megb,
lp_pwr_lo, lp_pwr_hi, lp_pwr_oe1, lp_pwr_oe2, lp_pwr_oe3, lp_pwr_oe4,
adc_d, lp_adc_clk,
lp_ssp_frame, lp_ssp_din, ssp_dout, lp_ssp_clk,
cross_hi, cross_lo,
lp_dbg, divisor
);
lo_edge_detect ls(
pck0, ck_1356meg, ck_1356megb,
ls_pwr_lo, ls_pwr_hi, ls_pwr_oe1, ls_pwr_oe2, ls_pwr_oe3, ls_pwr_oe4,
adc_d, ls_adc_clk,
ls_ssp_frame, ls_ssp_din, ssp_dout, ls_ssp_clk,
cross_hi, cross_lo,
ls_dbg, divisor,
lf_field
);
hi_read_tx ht(
pck0, ck_1356meg, ck_1356megb,
ht_pwr_lo, ht_pwr_hi, ht_pwr_oe1, ht_pwr_oe2, ht_pwr_oe3, ht_pwr_oe4,
adc_d, ht_adc_clk,
ht_ssp_frame, ht_ssp_din, ssp_dout, ht_ssp_clk,
cross_hi, cross_lo,
ht_dbg,
hi_read_tx_shallow_modulation
);
hi_read_rx_xcorr hrxc(
pck0, ck_1356meg, ck_1356megb,
hrxc_pwr_lo, hrxc_pwr_hi, hrxc_pwr_oe1, hrxc_pwr_oe2, hrxc_pwr_oe3, hrxc_pwr_oe4,
adc_d, hrxc_adc_clk,
hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk,
cross_hi, cross_lo,
hrxc_dbg,
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter
);
hi_simulate hs(
pck0, ck_1356meg, ck_1356megb,
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,
cross_hi, cross_lo,
hs_dbg,
hi_simulate_mod_type
);
hi_iso14443a hisn(
pck0, ck_1356meg, ck_1356megb,
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,
cross_hi, cross_lo,
hisn_dbg,
hi_simulate_mod_type
);
// Major modes:
// 000 -- LF reader (generic)
// 001 -- LF simulated tag (generic)
// 010 -- HF reader, transmitting to tag; modulation depth selectable
// 011 -- HF reader, receiving from tag, correlating as it goes; frequency selectable
// 100 -- HF simulated tag
// 101 -- HF ISO14443-A
// 110 -- LF passthrough
// 111 -- everything off
mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, ls_ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, lp_ssp_clk, 1'b0);
mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, ls_ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, lp_ssp_din, 1'b0);
mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, ls_ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, lp_ssp_frame, 1'b0);
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, ls_pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, lp_pwr_oe1, 1'b0);
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, ls_pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, lp_pwr_oe2, 1'b0);
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, ls_pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, lp_pwr_oe3, 1'b0);
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, ls_pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, lp_pwr_oe4, 1'b0);
mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, ls_pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, lp_pwr_lo, 1'b0);
mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, ls_pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, lp_pwr_hi, 1'b0);
mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, ls_adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, lp_adc_clk, 1'b0);
mux8 mux_dbg (major_mode, dbg, lr_dbg, ls_dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_dbg, lp_dbg, 1'b0);
// In all modes, let the ADC's outputs be enabled.
assign adc_noe = 1'b0;
endmodule

BIN
fpga/fpga_hf.bit Normal file

Binary file not shown.

150
fpga/fpga_hf.v Normal file
View file

@ -0,0 +1,150 @@
//-----------------------------------------------------------------------------
// 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
//-----------------------------------------------------------------------------
`include "hi_read_tx.v"
`include "hi_read_rx_xcorr.v"
`include "hi_simulate.v"
`include "hi_iso14443a.v"
`include "util.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.
//-----------------------------------------------------------------------------
reg [15:0] shift_reg;
reg [7:0] conf_word;
// 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])
4'b0001: conf_word <= shift_reg[7:0]; // FPGA_CMD_SET_CONFREG
endcase
end
always @(posedge spck)
begin
if(~ncs)
begin
shift_reg[15:1] <= shift_reg[14:0];
shift_reg[0] <= mosi;
end
end
wire [2:0] major_mode;
assign major_mode = conf_word[7:5];
// For the high-frequency transmit configuration: modulation depth, either
// 100% (just quite driving antenna, steady LOW), or shallower (tri-state
// some fraction of the buffers)
wire hi_read_tx_shallow_modulation = conf_word[0];
// For the high-frequency receive correlator: frequency against which to
// correlate.
wire hi_read_rx_xcorr_848 = conf_word[0];
// and whether to drive the coil (reader) or just short it (snooper)
wire hi_read_rx_xcorr_snoop = conf_word[1];
// Divide the expected subcarrier frequency for hi_read_rx_xcorr by 4
wire hi_read_rx_xcorr_quarter = conf_word[2];
// For the high-frequency simulated tag: what kind of modulation to use.
wire [2:0] hi_simulate_mod_type = conf_word[2: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.
//-----------------------------------------------------------------------------
hi_read_tx ht(
pck0, ck_1356meg, ck_1356megb,
ht_pwr_lo, ht_pwr_hi, ht_pwr_oe1, ht_pwr_oe2, ht_pwr_oe3, ht_pwr_oe4,
adc_d, ht_adc_clk,
ht_ssp_frame, ht_ssp_din, ssp_dout, ht_ssp_clk,
cross_hi, cross_lo,
ht_dbg,
hi_read_tx_shallow_modulation
);
hi_read_rx_xcorr hrxc(
pck0, ck_1356meg, ck_1356megb,
hrxc_pwr_lo, hrxc_pwr_hi, hrxc_pwr_oe1, hrxc_pwr_oe2, hrxc_pwr_oe3, hrxc_pwr_oe4,
adc_d, hrxc_adc_clk,
hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk,
cross_hi, cross_lo,
hrxc_dbg,
hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter
);
hi_simulate hs(
pck0, ck_1356meg, ck_1356megb,
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,
cross_hi, cross_lo,
hs_dbg,
hi_simulate_mod_type
);
hi_iso14443a hisn(
pck0, ck_1356meg, ck_1356megb,
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,
cross_hi, cross_lo,
hisn_dbg,
hi_simulate_mod_type
);
// Major modes:
// 000 -- HF reader, transmitting to tag; modulation depth selectable
// 001 -- HF reader, receiving from tag, correlating as it goes; frequency selectable
// 010 -- HF simulated tag
// 011 -- HF ISO14443-A
// 111 -- everything off
mux8 mux_ssp_clk (major_mode, ssp_clk, ht_ssp_clk, hrxc_ssp_clk, hs_ssp_clk, hisn_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_din (major_mode, ssp_din, ht_ssp_din, hrxc_ssp_din, hs_ssp_din, hisn_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_frame (major_mode, ssp_frame, ht_ssp_frame, hrxc_ssp_frame, hs_ssp_frame, hisn_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe1 (major_mode, pwr_oe1, ht_pwr_oe1, hrxc_pwr_oe1, hs_pwr_oe1, hisn_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe2 (major_mode, pwr_oe2, ht_pwr_oe2, hrxc_pwr_oe2, hs_pwr_oe2, hisn_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe3 (major_mode, pwr_oe3, ht_pwr_oe3, hrxc_pwr_oe3, hs_pwr_oe3, hisn_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_oe4 (major_mode, pwr_oe4, ht_pwr_oe4, hrxc_pwr_oe4, hs_pwr_oe4, hisn_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_lo (major_mode, pwr_lo, ht_pwr_lo, hrxc_pwr_lo, hs_pwr_lo, hisn_pwr_lo, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_hi (major_mode, pwr_hi, ht_pwr_hi, hrxc_pwr_hi, hs_pwr_hi, hisn_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_adc_clk (major_mode, adc_clk, ht_adc_clk, hrxc_adc_clk, hs_adc_clk, hisn_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_dbg (major_mode, dbg, ht_dbg, hrxc_dbg, hs_dbg, hisn_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

BIN
fpga/fpga_lf.bit Normal file

Binary file not shown.

125
fpga/fpga_lf.v Normal file
View file

@ -0,0 +1,125 @@
//-----------------------------------------------------------------------------
// 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
//-----------------------------------------------------------------------------
`include "lo_read.v"
`include "lo_passthru.v"
`include "lo_edge_detect.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.
//-----------------------------------------------------------------------------
reg [15:0] shift_reg;
reg [7:0] divisor;
reg [7:0] conf_word;
// 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])
4'b0001: conf_word <= shift_reg[7:0]; // FPGA_CMD_SET_CONFREG
4'b0010: divisor <= shift_reg[7:0]; // FPGA_CMD_SET_DIVISOR
endcase
end
always @(posedge spck)
begin
if(~ncs)
begin
shift_reg[15:1] <= shift_reg[14:0];
shift_reg[0] <= mosi;
end
end
wire [2:0] major_mode;
assign major_mode = conf_word[7:5];
// For the low-frequency configuration:
wire lf_field = conf_word[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.
//-----------------------------------------------------------------------------
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
);
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_cnt, 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
);
// Major modes:
// 000 -- LF reader (generic)
// 001 -- LF edge detect (generic)
// 010 -- LF passthrough
mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, le_ssp_frame, 1'b0, 1'b0, 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, 1'b0, 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, 1'b0, 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, 1'b0, 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, 1'b0, 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, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, le_pwr_hi, lp_pwr_hi, 1'b0, 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, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0);
mux8 mux_dbg (major_mode, dbg, lr_dbg, le_dbg, lp_dbg, 1'b0, 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

@ -2,37 +2,67 @@
rmdir/s/q xst rmdir/s/q xst
del fpga.ngc del fpga_lf.ngc
xst -ifn xst.scr xst -ifn xst_lf.scr
if errorlevel 0 goto ok1 if errorlevel 0 goto ok1
goto done goto done
:ok1 :ok1
del fpga.ngd del fpga_lf.ngd
ngdbuild -aul -p xc2s30-6vq100 -nt timestamp -uc fpga.ucf fpga.ngc fpga.ngd ngdbuild -aul -p xc2s30-6vq100 -nt timestamp -uc fpga.ucf fpga_lf.ngc fpga_lf.ngd
if errorlevel 0 goto ok2 if errorlevel 0 goto ok2
goto done goto done
:ok2 :ok2
del fpga.ncd del fpga_lf.ncd
map -p xc2s30-6vq100 fpga.ngd map -p xc2s30-6vq100 fpga_lf.ngd
if errorlevel 0 goto ok3 if errorlevel 0 goto ok3
goto done goto done
:ok3 :ok3
del fpga-placed.ncd del fpga_lf-placed.ncd
par fpga.ncd fpga-placed.ncd par fpga_lf.ncd fpga_lf-placed.ncd
if errorlevel 0 goto ok4 if errorlevel 0 goto ok4
goto done goto done
:ok4 :ok4
del fpga.bit fpga.drc fpga.rbt del fpga_lf.bit fpga_lf.drc fpga_lf.rbt
bitgen -b fpga-placed.ncd fpga.bit bitgen -b fpga_lf-placed.ncd fpga_lf.bit
if errorlevel 0 goto ok5 if errorlevel 0 goto ok5
goto done goto done
:ok5 :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 echo okay
perl ..\tools\rbt2c.pl fpga.rbt > ..\armsrc\fpgaimg.c perl ..\tools\rbt2c.pl fpga_lf.rbt > ..\armsrc\fpgaimg.c
:done :done

View file

@ -7,34 +7,18 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
module lo_edge_detect( module lo_edge_detect(
pck0, ck_1356meg, ck_1356megb, input pck0, input [7:0] pck_cnt, input pck_divclk,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, output pwr_lo, output pwr_hi,
adc_d, adc_clk, output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
ssp_frame, ssp_din, ssp_dout, ssp_clk, input [7:0] adc_d, output adc_clk,
cross_hi, cross_lo, output ssp_frame, input ssp_dout, output ssp_clk,
dbg, input cross_lo,
divisor, output dbg,
lf_field input lf_field
); );
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;
input lf_field;
// Divide the clock to be used for the ADC wire tag_modulation = ssp_dout & !lf_field;
reg [7:0] pck_divider; wire reader_modulation = !ssp_dout & lf_field & pck_divclk;
reg clk_state;
wire tag_modulation;
assign tag_modulation = ssp_dout & !lf_field;
wire reader_modulation;
assign reader_modulation = !ssp_dout & lf_field & clk_state;
// No logic, straight through. // No logic, straight through.
assign pwr_oe1 = 1'b0; // not used in LF mode assign pwr_oe1 = 1'b0; // not used in LF mode
@ -46,20 +30,7 @@ assign pwr_lo = reader_modulation;
assign pwr_hi = 1'b0; assign pwr_hi = 1'b0;
assign dbg = ssp_frame; assign dbg = ssp_frame;
always @(posedge pck0) assign adc_clk = ~pck_divclk;
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
assign adc_clk = ~clk_state;
// Toggle the output with hysteresis // Toggle the output with hysteresis
// Set to high if the ADC value is above 200 // Set to high if the ADC value is above 200
@ -70,7 +41,7 @@ reg output_state;
always @(posedge pck0) always @(posedge pck0)
begin begin
if((pck_divider == 8'd7) && !clk_state) begin if((pck_cnt == 8'd7) && !pck_divclk) begin
is_high = (adc_d >= 8'd190); is_high = (adc_d >= 8'd190);
is_low = (adc_d <= 8'd70); is_low = (adc_d <= 8'd70);
end end

View file

@ -4,42 +4,14 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
module lo_passthru( module lo_passthru(
pck0, ck_1356meg, ck_1356megb, input pck_divclk,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, output pwr_lo, output pwr_hi,
adc_d, adc_clk, output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
ssp_frame, ssp_din, ssp_dout, ssp_clk, output adc_clk,
cross_hi, cross_lo, output ssp_din, input ssp_dout,
dbg, divisor input cross_lo,
output dbg
); );
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;
reg [7:0] pck_divider;
reg ant_lo;
// this task runs on the rising egde of pck0 clock (24Mhz) and creates ant_lo
// which is high for (divisor+1) pck0 cycles and low for the same duration
// ant_lo is therefore a 50% duty cycle clock signal with a frequency of
// 12Mhz/(divisor+1) which drives the antenna as well as the ADC clock adc_clk
always @(posedge pck0)
begin
if(pck_divider == divisor[7:0])
begin
pck_divider <= 8'd0;
ant_lo = !ant_lo;
end
else
begin
pck_divider <= pck_divider + 1;
end
end
// 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
@ -47,7 +19,7 @@ assign pwr_oe3 = 1'b0;
assign pwr_oe1 = ssp_dout; 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 pwr_lo = ant_lo && ssp_dout; assign pwr_lo = pck_divclk && ssp_dout;
assign pwr_hi = 1'b0; assign pwr_hi = 1'b0;
assign adc_clk = 1'b0; assign adc_clk = 1'b0;
assign ssp_din = cross_lo; assign ssp_din = cross_lo;

View file

@ -7,58 +7,27 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
module lo_read( module lo_read(
pck0, ck_1356meg, ck_1356megb, input pck0, input [7:0] pck_cnt, input pck_divclk,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, output pwr_lo, output pwr_hi,
adc_d, adc_clk, output pwr_oe1, output pwr_oe2, output pwr_oe3, output pwr_oe4,
ssp_frame, ssp_din, ssp_dout, ssp_clk, input [7:0] adc_d, output adc_clk,
cross_hi, cross_lo, output ssp_frame, output ssp_din, output ssp_clk,
dbg, output dbg
lo_is_125khz, divisor
); );
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 lo_is_125khz; // redundant signal, no longer used anywhere
input [7:0] divisor;
reg [7:0] to_arm_shiftreg; reg [7:0] to_arm_shiftreg;
reg [7:0] pck_divider;
reg ant_lo;
// this task runs on the rising egde of pck0 clock (24Mhz) and creates ant_lo
// which is high for (divisor+1) pck0 cycles and low for the same duration
// ant_lo is therefore a 50% duty cycle clock signal with a frequency of
// 12Mhz/(divisor+1) which drives the antenna as well as the ADC clock adc_clk
always @(posedge pck0)
begin
if(pck_divider == divisor[7:0])
begin
pck_divider <= 8'd0;
ant_lo = !ant_lo;
end
else
begin
pck_divider <= pck_divider + 1;
end
end
// this task also runs at pck0 frequency (24Mhz) and is used to serialize // this task also runs at pck0 frequency (24Mhz) and is used to serialize
// the ADC output which is then clocked into the ARM SSP. // the ADC output which is then clocked into the ARM SSP.
// because ant_lo always transitions when pck_divider = 0 we use the // because pck_divclk always transitions when pck_cnt = 0 we use the
// pck_divider counter to sync our other signals off it // pck_div counter to sync our other signals off it
// we read the ADC value when pck_divider=7 and shift it out on counts 8..15 // we read the ADC value when pck_cnt=7 and shift it out on counts 8..15
always @(posedge pck0) always @(posedge pck0)
begin begin
if((pck_divider == 8'd7) && !ant_lo) if((pck_cnt == 8'd7) && !pck_divclk)
to_arm_shiftreg <= adc_d; to_arm_shiftreg <= adc_d;
else else begin
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 occuring due to the LSB of the shifter // simulation showed a glitch occuring due to the LSB of the shifter
// not being set as we shift bits out // not being set as we shift bits out
@ -83,11 +52,11 @@ end
// ssp_clk |_| |_| |_| |_| |_| |_| |_| |_| |_| |_ // ssp_clk |_| |_| |_| |_| |_| |_| |_| |_| |_| |_
// serialized SSP data is gated by ant_lo to suppress unwanted signal // serialized SSP data is gated by ant_lo to suppress unwanted signal
assign ssp_din = to_arm_shiftreg[7] && !ant_lo; assign ssp_din = to_arm_shiftreg[7] && !pck_divclk;
// SSP clock always runs at 24Mhz // SSP clock always runs at 24Mhz
assign ssp_clk = pck0; 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_divider[7:3] == 5'd1) && !ant_lo; 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;
@ -95,9 +64,9 @@ 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;
// this is the antenna driver signal // this is the antenna driver signal
assign pwr_lo = ant_lo; assign pwr_lo = pck_divclk;
// ADC clock out of phase with antenna driver // ADC clock out of phase with antenna driver
assign adc_clk = ~ant_lo; assign adc_clk = ~pck_divclk;
// ADC clock also routed to debug pin // ADC clock also routed to debug pin
assign dbg = adc_clk; assign dbg = adc_clk;
endmodule endmodule

View file

@ -1 +0,0 @@
run -ifn fpga.v -ifmt Verilog -ofn fpga.ngc -ofmt NGC -p xc2s30-5-vq100 -opt_mode Speed -opt_level 1 -ent fpga

1
fpga/xst_hf.scr Normal file
View file

@ -0,0 +1 @@
run -ifn fpga_hf.v -ifmt Verilog -ofn fpga_hf.ngc -ofmt NGC -p xc2s30-5-vq100 -top fpga_hf -opt_mode area -opt_level 2 -resource_sharing yes -fsm_style bram -fsm_encoding compact

1
fpga/xst_lf.scr Normal file
View file

@ -0,0 +1 @@
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

@ -60,6 +60,10 @@
#define SPI_FPGA_MODE 0 #define SPI_FPGA_MODE 0
#define SPI_LCD_MODE 1 #define SPI_LCD_MODE 1
#define FPGA_BITSTREAM_ERR 0
#define FPGA_BITSTREAM_LF 1
#define FPGA_BITSTREAM_HF 2
#define TRUE 1 #define TRUE 1
#define FALSE 0 #define FALSE 0