| 1 | //----------------------------------------------------------------------------- |
| 2 | // Copyright (C) 2014 iZsh <izsh at fail0verflow.com> |
| 3 | // |
| 4 | // This code is licensed to you under the terms of the GNU GPL, version 2 or, |
| 5 | // at your option, any later version. See the LICENSE.txt file for the text of |
| 6 | // the license. |
| 7 | //----------------------------------------------------------------------------- |
| 8 | // input clk is 24Mhz |
| 9 | `include "min_max_tracker.v" |
| 10 | |
| 11 | module lf_edge_detect(input clk, input [7:0] adc_d, input [7:0] lf_ed_threshold, |
| 12 | output [7:0] max, output [7:0] min, |
| 13 | output [7:0] high_threshold, output [7:0] highz_threshold, |
| 14 | output [7:0] lowz_threshold, output [7:0] low_threshold, |
| 15 | output edge_state, output edge_toggle); |
| 16 | |
| 17 | min_max_tracker tracker(clk, adc_d, lf_ed_threshold, min, max); |
| 18 | |
| 19 | // auto-tune |
| 20 | assign high_threshold = (max + min) / 2 + (max - min) / 4; |
| 21 | assign highz_threshold = (max + min) / 2 + (max - min) / 8; |
| 22 | assign lowz_threshold = (max + min) / 2 - (max - min) / 8; |
| 23 | assign low_threshold = (max + min) / 2 - (max - min) / 4; |
| 24 | |
| 25 | // heuristic to see if it makes sense to try to detect an edge |
| 26 | wire enabled = |
| 27 | (high_threshold > highz_threshold) |
| 28 | & (highz_threshold > lowz_threshold) |
| 29 | & (lowz_threshold > low_threshold) |
| 30 | & ((high_threshold - highz_threshold) > 8) |
| 31 | & ((highz_threshold - lowz_threshold) > 16) |
| 32 | & ((lowz_threshold - low_threshold) > 8); |
| 33 | |
| 34 | // Toggle the output with hysteresis |
| 35 | // Set to high if the ADC value is above the threshold |
| 36 | // Set to low if the ADC value is below the threshold |
| 37 | reg is_high = 0; |
| 38 | reg is_low = 0; |
| 39 | reg is_zero = 0; |
| 40 | reg trigger_enabled = 1; |
| 41 | reg output_edge = 0; |
| 42 | reg output_state; |
| 43 | |
| 44 | always @(posedge clk) |
| 45 | begin |
| 46 | is_high <= (adc_d >= high_threshold); |
| 47 | is_low <= (adc_d <= low_threshold); |
| 48 | is_zero <= ((adc_d > lowz_threshold) & (adc_d < highz_threshold)); |
| 49 | end |
| 50 | |
| 51 | // all edges detection |
| 52 | always @(posedge clk) |
| 53 | if (enabled) begin |
| 54 | // To enable detecting two consecutive peaks at the same level |
| 55 | // (low or high) we check whether or not we went back near 0 in-between. |
| 56 | // This extra check is necessary to prevent from noise artifacts |
| 57 | // around the threshold values. |
| 58 | if (trigger_enabled & (is_high | is_low)) begin |
| 59 | output_edge <= ~output_edge; |
| 60 | trigger_enabled <= 0; |
| 61 | end else |
| 62 | trigger_enabled <= trigger_enabled | is_zero; |
| 63 | end |
| 64 | |
| 65 | // edge states |
| 66 | always @(posedge clk) |
| 67 | if (enabled) begin |
| 68 | if (is_high) |
| 69 | output_state <= 1'd1; |
| 70 | else if (is_low) |
| 71 | output_state <= 1'd0; |
| 72 | end |
| 73 | |
| 74 | assign edge_state = output_state; |
| 75 | assign edge_toggle = output_edge; |
| 76 | |
| 77 | endmodule |