]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - fpga/lf_edge_detect.v
New LF edge detection algorithm + lowpass filter
[proxmark3-svn] / fpga / lf_edge_detect.v
diff --git a/fpga/lf_edge_detect.v b/fpga/lf_edge_detect.v
new file mode 100644 (file)
index 0000000..573adf7
--- /dev/null
@@ -0,0 +1,77 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2014 iZsh <izsh at fail0verflow.com>
+//
+// 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
Impressum, Datenschutz