////////////////////////////////////////////////////////////////////// //// //// //// Copyright (C) 2009 Authors and OPENCORES.ORG //// //// //// //// This source file may be used and distributed without //// //// restriction provided that this copyright statement is not //// //// removed from the file and that any derivative work contains //// //// the original copyright notice and the associated disclaimer. //// //// //// //// This source file is free software; you can redistribute it //// //// and/or modify it under the terms of the GNU Lesser General //// //// Public License as published by the Free Software Foundation; //// //// either version 2.1 of the License, or (at your option) any //// //// later version. //// //// //// //// This source is distributed in the hope that it will be //// //// useful, but WITHOUT ANY WARRANTY; without even the implied //// //// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// //// PURPOSE. See the GNU Lesser General Public License for more //// //// details. //// //// //// //// You should have received a copy of the GNU Lesser General //// //// Public License along with this source; if not, download it //// //// from http://www.opencores.org/lgpl.shtml //// //// //// ////////////////////////////////////////////////////////////////////// //// //// //// REV by Stephen Goadhouse //// //// -- changed in to din and out to dout so can use entity //// //// from VHDL //// //// //// //// -- fixed rise and fall by making output reg and using //// //// out_en. Before, there was the possibility to get //// //// rise or fall asserted when a glitch was on the input //// //// which would have prevented the output from rising or //// //// falling. //// //// //// //// -- added a reset state parameter for dout //// //// //// //// -- made SIZE to be number of bits compared for //// //// all_hi/all_lo instead of SIZE+1 being the number //// //// of bits. //// //// //// //// -- changed in_reg to sync_m with KEEP attribute so can //// //// easily make false paths for cross-clock domains like //// //// how Sync.vhd operates. //// //// //// //// -- changed rst to be active low rst_n //// //// //// ////////////////////////////////////////////////////////////////////// //`include "timescale.v" module glitch_filter #( parameter SIZE = 3, parameter DOUT_RST = 1'b0 // reset state of dout ) ( input din, output reg dout, output reg rise, output reg fall, input clk, input rst_n ); localparam BUFSIZE = SIZE-1; // Use the KEEP attribute on sync_m in an attempt to prevent XST & MAP from // using function RAM as a shift register in order to implement this // synchronation circuit. Although use of a shift register is efficient use // of FPGA resources, in the case of synchronizing between clock domains, it // may have a detrimental side-effect. Serious metastability issues have // been detected through ChipScope where it takes 50-100 clocks to resolve // the metastability. It is possible that the use of shift registers may be // causing the issue. There is also evidence found online that indicates // that the shift registers may be to blame. So eliminate them to create the // best possible defense against metastability. (* KEEP = "TRUE" *) reg sync_m; // -------------------------------------------------------------------- // in sync flop always @(posedge clk) sync_m <= din; // -------------------------------------------------------------------- // glitch filter reg [(BUFSIZE-1):0] buffer; always @(posedge clk) if (BUFSIZE > 1) buffer <= { buffer[(BUFSIZE-2):0], sync_m }; else buffer <= sync_m; wire all_hi = &{sync_m, buffer}; wire all_lo = ~|{sync_m, buffer}; wire out_en = (all_hi & sync_m) | (all_lo & ~sync_m); always @(posedge clk or negedge rst_n) if ( ~rst_n ) begin dout <= DOUT_RST; fall <= 1'b0; rise <= 1'b0; end else if( out_en ) begin dout <= buffer[(BUFSIZE-1)]; fall <= ~buffer[(BUFSIZE-1)] & dout; rise <= buffer[(BUFSIZE-1)] & ~dout; end else begin fall <= 1'b0; rise <= 1'b0; end endmodule