| 1 | //----------------------------------------------------------------------------- |
| 2 | // |
| 3 | // Jonathan Westhues, April 2006 |
| 4 | //----------------------------------------------------------------------------- |
| 5 | |
| 6 | module hi_reader( |
| 7 | ck_1356meg, |
| 8 | pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, |
| 9 | adc_d, adc_clk, |
| 10 | ssp_frame, ssp_din, ssp_dout, ssp_clk, |
| 11 | dbg, |
| 12 | subcarrier_frequency, minor_mode |
| 13 | ); |
| 14 | input ck_1356meg; |
| 15 | output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; |
| 16 | input [7:0] adc_d; |
| 17 | output adc_clk; |
| 18 | input ssp_dout; |
| 19 | output ssp_frame, ssp_din, ssp_clk; |
| 20 | output dbg; |
| 21 | input [1:0] subcarrier_frequency; |
| 22 | input [3:0] minor_mode; |
| 23 | |
| 24 | assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz |
| 25 | |
| 26 | // When we're a reader, we just need to do the BPSK demod; but when we're an |
| 27 | // eavesdropper, we also need to pick out the commands sent by the reader, |
| 28 | // using AM. Do this the same way that we do it for the simulated tag. |
| 29 | reg after_hysteresis, after_hysteresis_prev, after_hysteresis_prev_prev; |
| 30 | reg [11:0] has_been_low_for; |
| 31 | always @(negedge adc_clk) |
| 32 | begin |
| 33 | if (& adc_d[7:0]) after_hysteresis <= 1'b1; |
| 34 | else if (~(| adc_d[7:0])) after_hysteresis <= 1'b0; |
| 35 | |
| 36 | if (after_hysteresis) |
| 37 | begin |
| 38 | has_been_low_for <= 12'd0; |
| 39 | end |
| 40 | else |
| 41 | begin |
| 42 | if (has_been_low_for == 12'd4095) |
| 43 | begin |
| 44 | has_been_low_for <= 12'd0; |
| 45 | after_hysteresis <= 1'b1; |
| 46 | end |
| 47 | else |
| 48 | has_been_low_for <= has_been_low_for + 1; |
| 49 | end |
| 50 | end |
| 51 | |
| 52 | |
| 53 | // Let us report a correlation every 64 samples. I.e. |
| 54 | // one Q/I pair after 4 subcarrier cycles for the 848kHz subcarrier, |
| 55 | // one Q/I pair after 2 subcarrier cycles for the 424kHz subcarriers, |
| 56 | // one Q/I pair for each subcarrier cyle for the 212kHz subcarrier. |
| 57 | // We need a 6-bit counter for the timing. |
| 58 | reg [5:0] corr_i_cnt; |
| 59 | always @(negedge adc_clk) |
| 60 | begin |
| 61 | corr_i_cnt <= corr_i_cnt + 1; |
| 62 | end |
| 63 | |
| 64 | |
| 65 | // A couple of registers in which to accumulate the correlations. From the 64 samples |
| 66 | // we would add at most 32 times the difference between unmodulated and modulated signal. It should |
| 67 | // be safe to assume that a tag will not be able to modulate the carrier signal by more than 25%. |
| 68 | // 32 * 255 * 0,25 = 2040, which can be held in 11 bits. Add 1 bit for sign. |
| 69 | // Temporary we might need more bits. For the 212kHz subcarrier we could possible add 32 times the |
| 70 | // maximum signal value before a first subtraction would occur. 32 * 255 = 8160 can be held in 13 bits. |
| 71 | // Add one bit for sign -> need 14 bit registers but final result will fit into 12 bits. |
| 72 | reg signed [13:0] corr_i_accum; |
| 73 | reg signed [13:0] corr_q_accum; |
| 74 | // we will report maximum 8 significant bits |
| 75 | reg signed [7:0] corr_i_out; |
| 76 | reg signed [7:0] corr_q_out; |
| 77 | |
| 78 | |
| 79 | // the amplitude of the subcarrier is sqrt(ci^2 + cq^2). |
| 80 | // approximate by amplitude = max(|ci|,|cq|) + 1/2*min(|ci|,|cq|) |
| 81 | reg [13:0] corr_amplitude, abs_ci, abs_cq, max_ci_cq; |
| 82 | reg [12:0] min_ci_cq_2; // min_ci_cq / 2 |
| 83 | |
| 84 | always @(*) |
| 85 | begin |
| 86 | if (corr_i_accum[13] == 1'b0) |
| 87 | abs_ci <= corr_i_accum; |
| 88 | else |
| 89 | abs_ci <= -corr_i_accum; |
| 90 | |
| 91 | if (corr_q_accum[13] == 1'b0) |
| 92 | abs_cq <= corr_q_accum; |
| 93 | else |
| 94 | abs_cq <= -corr_q_accum; |
| 95 | |
| 96 | if (abs_ci > abs_cq) |
| 97 | begin |
| 98 | max_ci_cq <= abs_ci; |
| 99 | min_ci_cq_2 <= abs_cq / 2; |
| 100 | end |
| 101 | else |
| 102 | begin |
| 103 | max_ci_cq <= abs_cq; |
| 104 | min_ci_cq_2 <= abs_ci / 2; |
| 105 | end |
| 106 | |
| 107 | corr_amplitude <= max_ci_cq + min_ci_cq_2; |
| 108 | |
| 109 | end |
| 110 | |
| 111 | |
| 112 | // The subcarrier reference signals |
| 113 | reg subcarrier_I; |
| 114 | reg subcarrier_Q; |
| 115 | |
| 116 | always @(*) |
| 117 | begin |
| 118 | if (subcarrier_frequency == `FPGA_HF_READER_SUBCARRIER_848_KHZ) |
| 119 | begin |
| 120 | subcarrier_I = ~corr_i_cnt[3]; |
| 121 | subcarrier_Q = ~(corr_i_cnt[3] ^ corr_i_cnt[2]); |
| 122 | end |
| 123 | else if (subcarrier_frequency == `FPGA_HF_READER_SUBCARRIER_212_KHZ) |
| 124 | begin |
| 125 | subcarrier_I = ~corr_i_cnt[5]; |
| 126 | subcarrier_Q = ~(corr_i_cnt[5] ^ corr_i_cnt[4]); |
| 127 | end |
| 128 | else |
| 129 | begin // 424 kHz |
| 130 | subcarrier_I = ~corr_i_cnt[4]; |
| 131 | subcarrier_Q = ~(corr_i_cnt[4] ^ corr_i_cnt[3]); |
| 132 | end |
| 133 | end |
| 134 | |
| 135 | |
| 136 | // ADC data appears on the rising edge, so sample it on the falling edge |
| 137 | always @(negedge adc_clk) |
| 138 | begin |
| 139 | // These are the correlators: we correlate against in-phase and quadrature |
| 140 | // versions of our reference signal, and keep the (signed) results or the |
| 141 | // resulting amplitude to send out later over the SSP. |
| 142 | if (corr_i_cnt == 6'd0) |
| 143 | begin |
| 144 | if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_AMPLITUDE) |
| 145 | begin |
| 146 | // send amplitude plus 2 bits reader signal |
| 147 | corr_i_out <= corr_amplitude[13:6]; |
| 148 | corr_q_out <= {corr_amplitude[5:0], after_hysteresis_prev_prev, after_hysteresis_prev}; |
| 149 | end |
| 150 | else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ) |
| 151 | begin |
| 152 | // Send 7 most significant bits of in phase tag signal (signed), plus 1 bit reader signal |
| 153 | if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111) |
| 154 | corr_i_out <= {corr_i_accum[11:5], after_hysteresis_prev_prev}; |
| 155 | else // truncate to maximum value |
| 156 | if (corr_i_accum[13] == 1'b0) |
| 157 | corr_i_out <= {7'b0111111, after_hysteresis_prev_prev}; |
| 158 | else |
| 159 | corr_i_out <= {7'b1000000, after_hysteresis_prev_prev}; |
| 160 | // Send 7 most significant bits of quadrature phase tag signal (signed), plus 1 bit reader signal |
| 161 | if (corr_q_accum[13:11] == 3'b000 || corr_q_accum[13:11] == 3'b111) |
| 162 | corr_q_out <= {corr_q_accum[11:5], after_hysteresis_prev}; |
| 163 | else // truncate to maximum value |
| 164 | if (corr_q_accum[13] == 1'b0) |
| 165 | corr_q_out <= {7'b0111111, after_hysteresis_prev}; |
| 166 | else |
| 167 | corr_q_out <= {7'b1000000, after_hysteresis_prev}; |
| 168 | end |
| 169 | else if (minor_mode == `FPGA_HF_READER_MODE_RECEIVE_AMPLITUDE) |
| 170 | begin |
| 171 | // send amplitude |
| 172 | corr_i_out <= {2'b00, corr_amplitude[13:8]}; |
| 173 | corr_q_out <= corr_amplitude[7:0]; |
| 174 | end |
| 175 | else if (minor_mode == `FPGA_HF_READER_MODE_RECEIVE_IQ) |
| 176 | begin |
| 177 | // Send 8 bits of in phase tag signal |
| 178 | if (corr_i_accum[13:11] == 3'b000 || corr_i_accum[13:11] == 3'b111) |
| 179 | corr_i_out <= corr_i_accum[11:4]; |
| 180 | else // truncate to maximum value |
| 181 | if (corr_i_accum[13] == 1'b0) |
| 182 | corr_i_out <= 8'b01111111; |
| 183 | else |
| 184 | corr_i_out <= 8'b10000000; |
| 185 | // Send 8 bits of quadrature phase tag signal |
| 186 | if (corr_q_accum[13:11] == 3'b000 || corr_q_accum[13:11] == 3'b111) |
| 187 | corr_q_out <= corr_q_accum[11:4]; |
| 188 | else // truncate to maximum value |
| 189 | if (corr_q_accum[13] == 1'b0) |
| 190 | corr_q_out <= 8'b01111111; |
| 191 | else |
| 192 | corr_q_out <= 8'b10000000; |
| 193 | end |
| 194 | |
| 195 | // for each Q/I pair report two reader signal samples when sniffing. Store the 1st. |
| 196 | after_hysteresis_prev_prev <= after_hysteresis; |
| 197 | // Initialize next correlation. |
| 198 | // Both I and Q reference signals are high when corr_i_nct == 0. Therefore need to accumulate. |
| 199 | corr_i_accum <= $signed({1'b0,adc_d}); |
| 200 | corr_q_accum <= $signed({1'b0,adc_d}); |
| 201 | end |
| 202 | else |
| 203 | begin |
| 204 | if (subcarrier_I) |
| 205 | corr_i_accum <= corr_i_accum + $signed({1'b0,adc_d}); |
| 206 | else |
| 207 | corr_i_accum <= corr_i_accum - $signed({1'b0,adc_d}); |
| 208 | |
| 209 | if (subcarrier_Q) |
| 210 | corr_q_accum <= corr_q_accum + $signed({1'b0,adc_d}); |
| 211 | else |
| 212 | corr_q_accum <= corr_q_accum - $signed({1'b0,adc_d}); |
| 213 | end |
| 214 | |
| 215 | // for each Q/I pair report two reader signal samples when sniffing. Store the 2nd. |
| 216 | if (corr_i_cnt == 6'd32) |
| 217 | after_hysteresis_prev <= after_hysteresis; |
| 218 | |
| 219 | // Then the result from last time is serialized and send out to the ARM. |
| 220 | // We get one report each cycle, and each report is 16 bits, so the |
| 221 | // ssp_clk should be the adc_clk divided by 64/16 = 4. |
| 222 | // ssp_clk frequency = 13,56MHz / 4 = 3.39MHz |
| 223 | |
| 224 | if (corr_i_cnt[1:0] == 2'b00) |
| 225 | begin |
| 226 | // Don't shift if we just loaded new data, obviously. |
| 227 | if (corr_i_cnt != 6'd0) |
| 228 | begin |
| 229 | corr_i_out[7:0] <= {corr_i_out[6:0], corr_q_out[7]}; |
| 230 | corr_q_out[7:1] <= corr_q_out[6:0]; |
| 231 | end |
| 232 | end |
| 233 | |
| 234 | end |
| 235 | |
| 236 | |
| 237 | // ssp clock and frame signal for communication to and from ARM |
| 238 | // _____ _____ _____ _ |
| 239 | // ssp_clk | |_____| |_____| |_____| |
| 240 | // _____ |
| 241 | // ssp_frame ___| |____________________________ |
| 242 | // ___________ ___________ ___________ _ |
| 243 | // ssp_d_in X___________X___________X___________X_ |
| 244 | // |
| 245 | // corr_i_cnt 0 1 2 3 4 5 6 7 8 9 10 11 12 ... |
| 246 | // |
| 247 | |
| 248 | reg ssp_clk; |
| 249 | reg ssp_frame; |
| 250 | |
| 251 | always @(negedge adc_clk) |
| 252 | begin |
| 253 | if (corr_i_cnt[1:0] == 2'b00) |
| 254 | ssp_clk <= 1'b1; |
| 255 | if (corr_i_cnt[1:0] == 2'b10) |
| 256 | ssp_clk <= 1'b0; |
| 257 | |
| 258 | // set ssp_frame signal for corr_i_cnt = 1..3 |
| 259 | // (send one frame with 16 Bits) |
| 260 | if (corr_i_cnt == 6'd1) |
| 261 | ssp_frame <= 1'b1; |
| 262 | if (corr_i_cnt == 6'd3) |
| 263 | ssp_frame <= 1'b0; |
| 264 | end |
| 265 | |
| 266 | |
| 267 | assign ssp_din = corr_i_out[7]; |
| 268 | |
| 269 | |
| 270 | // a jamming signal |
| 271 | reg jam_signal; |
| 272 | reg [3:0] jam_counter; |
| 273 | |
| 274 | always @(negedge adc_clk) |
| 275 | begin |
| 276 | if (corr_i_cnt == 6'd0) |
| 277 | begin |
| 278 | jam_counter <= jam_counter + 1; |
| 279 | jam_signal <= jam_counter[1] ^ jam_counter[3]; |
| 280 | end |
| 281 | end |
| 282 | |
| 283 | // Antenna drivers |
| 284 | reg pwr_hi, pwr_oe4; |
| 285 | |
| 286 | always @(*) |
| 287 | begin |
| 288 | if (minor_mode == `FPGA_HF_READER_MODE_SEND_SHALLOW_MOD) |
| 289 | begin |
| 290 | pwr_hi = ck_1356meg; |
| 291 | pwr_oe4 = ssp_dout; |
| 292 | end |
| 293 | else if (minor_mode == `FPGA_HF_READER_MODE_SEND_FULL_MOD) |
| 294 | begin |
| 295 | pwr_hi = ck_1356meg & ~ssp_dout; |
| 296 | pwr_oe4 = 1'b0; |
| 297 | end |
| 298 | else if (minor_mode == `FPGA_HF_READER_MODE_SEND_JAM) |
| 299 | begin |
| 300 | pwr_hi = ck_1356meg & jam_signal; |
| 301 | pwr_oe4 = 1'b0; |
| 302 | end |
| 303 | else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ |
| 304 | || minor_mode == `FPGA_HF_READER_MODE_SNIFF_AMPLITUDE |
| 305 | || minor_mode == `FPGA_HF_READER_MODE_SNIFF_PHASE) |
| 306 | begin // all off |
| 307 | pwr_hi = 1'b0; |
| 308 | pwr_oe4 = 1'b0; |
| 309 | end |
| 310 | else // receiving from tag |
| 311 | begin |
| 312 | pwr_hi = ck_1356meg; |
| 313 | pwr_oe4 = 1'b0; |
| 314 | end |
| 315 | end |
| 316 | |
| 317 | // always on |
| 318 | assign pwr_oe1 = 1'b0; |
| 319 | assign pwr_oe3 = 1'b0; |
| 320 | |
| 321 | // Unused. |
| 322 | assign pwr_lo = 1'b0; |
| 323 | assign pwr_oe2 = 1'b0; |
| 324 | |
| 325 | // Debug Output |
| 326 | assign dbg = corr_i_cnt[3]; |
| 327 | |
| 328 | endmodule |