-
Notifications
You must be signed in to change notification settings - Fork 1
FPGA SPI And Register Map
The FPGA access for the S.U.R.F.E.R. FPGA is very similar to other SPI interfaces. However, there are a few quirks that were introduced to reduce FPGA resource consumption.
- In addition to W/R, Address [A], and Data [D] bits, there are Memory Type [T] bits (explained below) at the beginning of the SPI transfer.
- Writing is not permitted during memory reads. Memory reads follow writes almost immediately.
- The final bit sent over from the MCU to the FPGA is "0". That is because this interval is needed to prepare for data transfer from FPGA to MCU.
The FPGA access between the MCU and FPGA uses 4 different pins:
- NPS: Negated peripheral select. From the MCU (controller) to the FPGA (peripheral). Dictates which peripheral on the SPI bus is to be selected.
- PCLK: Peripheral clock. From the MCU (controller) to the FPGA (peripheral). Controls timing across the SPI bus.
- COPI: Controller Out Peripheral In: From the MCU (controller) to the FPGA (peripheral). Send data from MCU to FPGA.
- CIPO: Controller In Peripheral Out: From the FPGA (peripheral) to the MCU (controller). Send data from FPGA to MCU.
Addressing the different memories over the FPGA SPI Link is done with a modified one-hot scheme in which memories with larger address spaces are identified with higher-positioned one-hot values so as to be able to accommodate their addresses in the 3 bytes available for data transfer from the MCU to the FPGA. The memory spaces are:
- (1): Waveform Memory: This feature is currently disabled but when active it permits the MCU to access about 1ms of raw I/Q data capture from the SX1257. This feature was intended to use the fairly large amount of available SRAM on the 10M02 FPGA to capture raw waveforms for advanced tag localization techniques. Therefore, it has the largest address space of all of the memories on the S.U.R.F.E.R. FPGA.
- (01): Radio Memory: This memory is partitioned into TX and RX spaces. Setting bit A[9]=1 selects the RX RAM. Setting bit A[9]=0 selects the TX RAM.
- (001): TX Cancel Memory: This feature is currently removed, but when active it permits measured data from the tunable microwave network to guide the TX cancellation algorithm.
- (0001): User Memory: Used to effect various actions, change settings, and to access the SPI bridge to the SX1257 I/Q transceiver ASIC.
![FPGA SPI RX to TX Transition](https://github.com/surfer-rfid/surfer-rfid-wiki/raw/main/assets/images/FPGA_SPI_And_Register_Map/SPI_RXTX_Handover_091721.png)
The FPGA interface is designed to support 10MHz operation. However, the internal 27.5MHz clock of the FPGA runs as slow as 22MHz. In addition, transitioning between the TX and RX (COPI and CIPO) states takes a few clock cycles in the existing SPI architecture. In order to accommodate these constraints, the final bit of data from the MCU to the FPGA is ignored, as shown to the right. During this final bit on the COPI line, the data to be sent back to the FPGA is loaded into a shift register and then presented on the CIPO line. Is there a better way to do this? Maybe, but this technique worked for this project.
The FPGA SPI Radio Memory is an Intel (Altera) "altsyncram" SRAM block that lives on the FPGA. The top level of this block in the Verilog code is "radio_sram_with_mux.v". This SRAM block can be accessed by both the SPI and by the Data Recovery or TX GEN circuit, depending on whether the RX or TX section of the radio is active. In general, the TX GEN data is loaded over SPI at FPGA reset to the TX Radio Memory, and whenever TX command information has to change. The RFID tag response expected length data is usually written by SPI upon FPGA reset to the RX Radio Memory, and relevant data from the tag response is read over SPI from the RX Radio Memory after every successful tag data acquisition.
The TX Radio memory map shown below shows the start addresses for the data for each of the possible EPC Gen 2 TX commands. The data loaded into the TX Radio SRAM are the opcodes mentioned in the IEEE literature on this project; two opcodes per byte-wise address. The opcodes are, of course, loaded sequentially in the same order as described in the EPC Gen 2 specification.
Address | Name | Description |
---|---|---|
0000000000 | TXCW0 | TXCW0 command information start. |
0000010000 | QUERY | QUERY command information start. |
0000100000 | QRY_REP | QUERY_REP command information start. |
0000110000 | ACK_RN16 | ACK_RN16 command information start. |
0001000000 | ACK_HDL | ACK_HANDLE command information start. |
0001010000 | NAK | NAL command information start. |
0001100000 | REQHDL | Request Handle command information start. |
0001110000 | REQRN16 | Request RN16 command information start. |
0010000000 | LOCK | LOCK command information start. |
0010100000 | READ | READ command information start. |
0011010000 | WRITE0 | Write command information start. First 16b chunk. |
0011011000 | WRITE1 | Write command information start. Second 16b chunk. |
0011100000 | WRITE2 | Write command information start. Third 16b chunk. |
0011101000 | WRITE3 | Write command information start. Fourth 16b chunk. |
0011110000 | WRITE4 | Write command information start. Fifth 16b chunk. |
0011111000 | WRITE5 | Write command information start. Sixth 16b chunk. |
0101100000 | SELECT | First SELECT command information start. |
0110110000 | SEL_2 | Second SELECT command information start. |
The RX section of the SPI Radio Memory consists of 7 slots, one for each type of response that the tag can return to the reader. For each slot, the data stored after the slot head address is ordered as follows:
- Number of bits of expected data (1 byte, at the slot head address).
- This is the only part of the RX SPI Radio Memory that is intended to be written over SPI.
- Having the correct number of bits specified here is needed in this implementation for correctly timing the CRC check.
- Bits of valid data returned (varies, but up to 17 bytes).
- Exit code (1 byte).
- Received signal waveform "I" magnitude (4 bytes).
- Received signal waveform "Q" magnitude (4 bytes).
Note that the exact position of the data mentioned above depends on the number of bits of valid data returned. Therefore, the MCU firmware needs to know this value in order to compute the SRAM addresses of the other data in the tag response slot.
Address | Name | Description |
---|---|---|
100000000 | RN16 | Post-Initial RN16 Tag Response Information Slot Head and Expected Length of Response. |
100010000 | RN16_I | Initial RN16 Tag Response Information Slot Head and Expected Length of Response. |
100100000 | HANDLE | Handle Tag Response Information Slot Head and Expected Length of Response. |
100110000 | WRITE | Write Tag Response Information Slot Head and Expected Length of Response. |
101000000 | LOCK | Lock Tag Response Information Slot Head and Expected Length of Response. |
101010000 | READ | Read Tag Response Information Slot Head and Expected Length of Response. |
101110000 | PCEPC | PCEPC Tag Response Information Slot Head and Expected Length of Response. |
Below is the memory map for the User Memory. This memory is, in a sense, the control interface of the FPGA. Note that the write and read assignments for each register can be quite different! The user memory register map cap be modified in spi_prphrl.v.
Bit | Name | Description | Values |
---|---|---|---|
7:5 | N/A | N/A | N/A |
4 | use_i | Select use of I or Q Clock and Data Recovery Circuit. | 1: Use I. 0: Use Q. |
3:2 | radio_mode | Select sequence of EPC Gen 2 commands in Radio FSM for a macro UHF RFID operation. |
11: Program. 10: Undefined. 01: Inventory. 00: Search. |
1 | irq_ack | Acknowledge IRQ from FPGA to MCU. Required to transition RFIDR FSM to IDLE after a macro UHF RFID operation. |
1: Assert ACK. 0: No Assert. |
0 | go_radio | Execute macro UHF RFID operation, e.g. program a tag. | 1: Begin RFID operation. 0: Do nothing. |
Bit | Name | Description | Values |
---|---|---|---|
7 | N/A | N/A | 0 |
6:5 | radio_exit_code | Determine outcome of macro UHF RFID operation. | 3,2: Undefined. 1: Error. 0: No Error. |
4 | use_i | Select use of I or Q Clock and Data Recovery Circuit. | 1: Use I. 0: Use Q. |
3:2 | radio_mode | Select sequence of EPC Gen 2 commands in Radio FSM for a macro UHF RFID operation. |
11: Program. 10: Undefined. 01: Inventory. 00: Search. |
1 | clk_36_valid | Valid 36MHz clock from SX1257 detected. | 1: Valid. 0: Not valid. |
0 | clk_36_running | Same as clk_36_valid currently. | 1: Clock running. 0: Not running. |
Bit | Name | Description | Values |
---|---|---|---|
7 | clk_36_start | Does nothing anymore. CLK36 starts on its own. | N/A |
6 | use_select_packet | Use a EPC Gen 2 SELECT command at the beginning of the next macro UHF RFID operation. Bit self-clears after operation is over. |
1: Set bit. 0: Do nothing. |
5 | alt_radio_fsm_loop | During "Inventory" Mode, after returning control from MCU to FPGA, use "QUERY" command instead of "QUERY REP" command. (i.e. take an alternate state machine loop) Bit self-clears after operation is over. |
1: Set bit 0: Do nothing. |
4 | end_radio_fsm_loop | During "Inventory" Mode, after returning control from MCU to FPGA, exit "Inventory" mode loop. Bit self-clears after operation is over. |
1: Set bit. 0: Do nothing. |
3:0 | N/A | N/A | N/A |
Bit | Name | Description | Values |
---|---|---|---|
7 | N/A | N/A | 0 |
6 | use_select_packet | Use a EPC Gen 2 SELECT command at the beginning of the next macro UHF RFID operation. Bit self-clears after operation is over. |
1: Set bit. 0: Do nothing. |
5 | alt_radio_fsm_loop | During "Inventory" Mode, after returning control from MCU to FPGA, use "QUERY" command instead of "QUERY REP" command. (i.e. take an alternate state machine loop) Bit self-clears after operation is over. |
1: Set bit. 0: Do nothing. |
4 | end_radio_fsm_loop | During "Inventory" Mode, after returning control from MCU to FPGA, exit "Inventory" mode loop. Bit self-clears after operation is over. |
1: Set bit. 0: Do nothing. |
3 | wave_storage_running | Currently not used. | N/A |
2 | wave_storage_done | Currently not used. | N/A |
1 | radio_running | From rfidr_fsm.v. Shows whether FPGA is under control of the Radio FSM or User Memory Interface |
1: FPGA is operated by Radio FSM. 0: FPGA accepting command for new UHF RFID macro operation. |
0 | radio_done | From rfidr_fsm.v. Shows whether the FPGA has completed a UHF RFID macro operation. |
1: Radio operation is complete and awaiting an ACK from the MCU. 0: Radio operation is not complete. |
Bit | Name | Description | Values |
---|---|---|---|
7:2 | N/A | N/A | N/A |
1 | cntrlr_spi_rdy | Execute SPI Bridge Controller communication to SX1257 at next available interval. |
1: Ready communication. 0: Do nothing. |
0 | sw_reset | Software reset. | 1: Execute software reset. 0: Do nothing |
Bit | Name | Description | Values |
---|---|---|---|
7 | N/A | N/A | N/A |
6 | cntrlr_spi_pending | SPI Bridge Controller communication to SX1257 is pending. |
1: Is pending. 0: Not pending. |
5 | cntrlr_spi_done | SPI Bridge Controller communication to SX1257 is complete. |
1: Is done. 0: Not done. |
4 | N/A | N/A | N/A |
3 | tx_error | Error detected in TX Gen inputs. No longer used. | N/A |
2:0 | write_cntr | Current "Program" write counter value. Needed to recover from failure in the middle of tag programming. |
Counter value. |
Bit | Name | Description | Values |
---|---|---|---|
7:0 | wvfm_offset | Offset from start of the UHF RFID macro radio operation at which waveform recording begins. Currently disabled. |
Offset value in units of (2^16) CLK36 periods (about 1.8ms). |
Bit | Name | Description | Values |
---|---|---|---|
7:0 | cntrlr_addr_buf | Address for SPI Bridge data transfers to SX1257. |
Desired SX1257 SPI address. |
Bit | Name | Description | Values |
---|---|---|---|
7:0 | N/A | N/A | N/A |
Bit | Name | Description | Values |
---|---|---|---|
7:0 | cntrlr_data_buf | Data for SPI Bridge data transfers to SX1257. |
Desired SX1257 SPI data. |
Bit | Name | Description | Values |
---|---|---|---|
7:0 | cntrlr_rx_buf | Returned SPI Bridge data from SX1257. |
Returned SX1257 SPI data. |
Bit | Name | Description | Values |
---|---|---|---|
7:6 | N/A | N/A | N/A |
5 | kill_write_pkt | While executing "Program" radio mode to kill a tag, run the Radio FSM slightly differently. This bit is cleared after the radio operation. |
1: Set bit. 0: Do nothing. |
4 | N/A | N/A | N/A |
3 | dtc_test_mode | Enter special mode which permits direct control of digitally tunable capacitor (DTC) values for tunable microwave network (TMN) characterization. Currently disabled to save LUT resources. |
1: In DTC test mode. 0: In regular mode. |
2 | clear_cap_vals | In dtc_test_mode, clear DTC capacitor state variables. | 1: Clear DTC capacitor state variables. 0: Do nothing. |
1 | incr_cap_val_2 | In dtc_test_mode, increment DTC capacitor state variable 2. | 1: Increment DTC capacitor state variable 2. 0: Do nothing. |
0 | incr_cap_val_1 | In dtc_test_mode, increment DTC capacitor state variable 1. | 1: Increment DTC capacitor state variable 1. 0: Do nothing. |
Bit | Name | Description | Values |
---|---|---|---|
7:6 | N/A | N/A | N/A |
5 | kill_write_pkt | While executing "Program" radio mode to kill a tag, run the Radio FSM slightly differently. This bit is cleared after the radio operation. |
1: Bit is set. 0: Bit is not set. |
4 | N/A | N/A | N/A |
3 | dtc_test_mode | Enter special mode which permits direct control of digitally tunable capacitor (DTC) values for tunable microwave network (TMN) characterization. Currently disabled to save LUT resources. |
1: In DTC test mode. 0: In regular mode. |
2:0 | N/A | N/A | N/A |
Bit | Name | Description | Values |
---|---|---|---|
7:4 | sdm_offset | DC offset applied to TX Sigma Delta Modulator. This is the offset on the TX I channel. This is auto-set in software to maximize modulation depth. |
SDM DC Offset Value |
3:0 | zgn_offset | DC offset applied to TX Zero Generator. This is the offset on the TX Q channel. This is auto-set in software to maximize modulation depth. |
Zero-Gen DC Offset Value |
- Write SX1257 register address to cntrlr_addr_buf (see Address 004 above).
- Write SX1257 register data to cntrlr_data_buf (see Address 005 above).
- Write "1" to cntrlr_spi_rdy (see Address 002 above).
- Poll cntrlr_spi_pending and cntrlr_spi_done (see Address 002 above).
- Read result from SX1257 in cntrlr_rx_buf (see Address 005 above).