X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/b811cc51f9a21324dc7589d1254e767374488a20..6658905f18a1eebc148836f26c731dea9c1377dc:/fpga/lo_read.v diff --git a/fpga/lo_read.v b/fpga/lo_read.v new file mode 100644 index 00000000..9c3edb22 --- /dev/null +++ b/fpga/lo_read.v @@ -0,0 +1,102 @@ +//----------------------------------------------------------------------------- +// 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. +// +// Jonathan Westhues, April 2006 +//----------------------------------------------------------------------------- + +module lo_read( + pck0, ck_1356meg, ck_1356megb, + pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4, + adc_d, adc_clk, + ssp_frame, ssp_din, ssp_dout, ssp_clk, + cross_hi, cross_lo, + dbg, + lo_is_125khz +); + 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; + +// 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; + +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; +end + +assign pwr_lo = carrier_divider_lo[2]; + +// 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) +begin + if(carrier_divider_lo == 3'b000) + to_arm_shiftreg <= adc_d; + else + to_arm_shiftreg[7:1] <= to_arm_shiftreg[6:0]; +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]; + +assign pwr_hi = 1'b0; + +assign dbg = adc_clk; + +endmodule