X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/6658905f18a1eebc148836f26c731dea9c1377dc..709a8d3ff0f7991425dd2600f057acbd8019616a:/fpga/lo_read.v?ds=sidebyside diff --git a/fpga/lo_read.v b/fpga/lo_read.v index 9c3edb22..8dce4dda 100644 --- a/fpga/lo_read.v +++ b/fpga/lo_read.v @@ -1,8 +1,7 @@ //----------------------------------------------------------------------------- // The way that we connect things in low-frequency read mode. In this case -// we are generating the 134 kHz or 125 kHz carrier, and running the -// unmodulated carrier at that frequency. The A/D samples at that same rate, -// and the result is serialized. +// 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 //----------------------------------------------------------------------------- @@ -14,7 +13,7 @@ module lo_read( ssp_frame, ssp_din, ssp_dout, ssp_clk, cross_hi, cross_lo, dbg, - lo_is_125khz + lo_is_125khz, divisor ); input pck0, ck_1356meg, ck_1356megb; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; @@ -24,79 +23,81 @@ module lo_read( output ssp_frame, ssp_din, ssp_clk; input cross_hi, cross_lo; output dbg; - input lo_is_125khz; + input lo_is_125khz; // redundant signal, no longer used anywhere + input [7:0] divisor; -// The low-frequency RFID stuff. This is relatively simple, because most -// of the work happens on the ARM, and we just pass samples through. The -// PCK0 must be divided down to generate the A/D clock, and from there by -// a factor of 8 to generate the carrier (that we apply to the coil drivers). -// -// This is also where we decode the received synchronous serial port words, -// to determine how to drive the output enables. - -// PCK0 will run at (PLL clock) / 4, or 24 MHz. That means that we can do -// 125 kHz by dividing by a further factor of (8*12*2), or ~134 kHz by -// dividing by a factor of (8*11*2) (for 136 kHz, ~2% error, tolerable). - -reg [3:0] pck_divider; -reg clk_lo; +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(lo_is_125khz) - begin - if(pck_divider == 4'd11) - begin - pck_divider <= 4'd0; - clk_lo = !clk_lo; - end - else - pck_divider <= pck_divider + 1; - end - else - begin - if(pck_divider == 4'd10) - begin - pck_divider <= 4'd0; - clk_lo = !clk_lo; - end - else - pck_divider <= pck_divider + 1; - end -end - -reg [2:0] carrier_divider_lo; - -always @(posedge clk_lo) -begin - carrier_divider_lo <= carrier_divider_lo + 1; + 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 -assign pwr_lo = carrier_divider_lo[2]; +// this task also runs at pck0 frequency (24Mhz) and is used to serialize +// the ADC output which is then clocked into the ARM SSP. -// This serializes the values returned from the A/D, and sends them out -// over the SSP. - -reg [7:0] to_arm_shiftreg; - -always @(posedge clk_lo) +// because ant_lo always transitions when pck_divider = 0 we use the +// pck_divider 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 +always @(posedge pck0) begin - if(carrier_divider_lo == 3'b000) + if((pck_divider == 8'd7) && !ant_lo) to_arm_shiftreg <= adc_d; else + begin to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; + // simulation showed a glitch occuring 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 -assign ssp_clk = clk_lo; -assign ssp_frame = (carrier_divider_lo == 3'b001); -assign ssp_din = to_arm_shiftreg[7]; - -// The ADC converts on the falling edge, and our serializer loads when -// carrier_divider_lo == 3'b000. -assign adc_clk = ~carrier_divider_lo[2]; - +// 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] && !ant_lo; +// 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_divider[7:3] == 5'd1) && !ant_lo; +// 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 = ant_lo; +// ADC clock out of phase with antenna driver +assign adc_clk = ~ant_lo; +// ADC clock also routed to debug pin assign dbg = adc_clk; - endmodule