X-Git-Url: http://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/e17437f985b1c955b3a2e3cab4f9146db54631a1..3b2fee43ea7d9e08b7729d662d8d010ee0e2a2e3:/fpga/lf_edge_detect.v diff --git a/fpga/lf_edge_detect.v b/fpga/lf_edge_detect.v new file mode 100644 index 00000000..573adf7b --- /dev/null +++ b/fpga/lf_edge_detect.v @@ -0,0 +1,77 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2014 iZsh +// +// 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. +//----------------------------------------------------------------------------- +// input clk is 24Mhz +`include "min_max_tracker.v" + +module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold, + output [7:0] max, output [7:0] min, + output [7:0] high_threshold, output [7:0] highz_threshold, + output [7:0] lowz_threshold, output [7:0] low_threshold, + output edge_state, output edge_toggle); + + min_max_tracker tracker(clk, adc_d, lf_ed_threshold, min, max); + + // auto-tune + assign high_threshold = (max + min) / 2 + (max - min) / 4; + assign highz_threshold = (max + min) / 2 + (max - min) / 8; + assign lowz_threshold = (max + min) / 2 - (max - min) / 8; + assign low_threshold = (max + min) / 2 - (max - min) / 4; + + // heuristic to see if it makes sense to try to detect an edge + wire enabled = + (high_threshold > highz_threshold) + & (highz_threshold > lowz_threshold) + & (lowz_threshold > low_threshold) + & ((high_threshold - highz_threshold) > 8) + & ((highz_threshold - lowz_threshold) > 16) + & ((lowz_threshold - low_threshold) > 8); + + // Toggle the output with hysteresis + // Set to high if the ADC value is above the threshold + // Set to low if the ADC value is below the threshold + reg is_high = 0; + reg is_low = 0; + reg is_zero = 0; + reg trigger_enabled = 1; + reg output_edge = 0; + reg output_state; + + always @(posedge clk) + begin + is_high <= (adc_d >= high_threshold); + is_low <= (adc_d <= low_threshold); + is_zero <= ((adc_d > lowz_threshold) & (adc_d < highz_threshold)); + end + + // all edges detection + always @(posedge clk) + if (enabled) begin + // To enable detecting two consecutive peaks at the same level + // (low or high) we check whether or not we went back near 0 in-between. + // This extra check is necessary to prevent from noise artifacts + // around the threshold values. + if (trigger_enabled & (is_high | is_low)) begin + output_edge <= ~output_edge; + trigger_enabled <= 0; + end else + trigger_enabled <= trigger_enabled | is_zero; + end + + // edge states + always @(posedge clk) + if (enabled) begin + if (is_high) + output_state <= 1'd1; + else if (is_low) + output_state <= 1'd0; + end + + assign edge_state = output_state; + assign edge_toggle = output_edge; + +endmodule