/*
 Fan speed monitor. Samples 2 inputs, counts signal frequencies

 Copyright (c) 2009 Dimtel, Inc., All Rights Reserved

 $Id: fanmon.v,v 1.3 2011/07/19 18:48:55 dim Exp $
 $Date: 2011/07/19 18:48:55 $
 $Author: dim $
 $Revision: 1.3 $
 $Log: fanmon.v,v $
 Revision 1.3  2011/07/19 18:48:55  dim
 Optimized initial state

 Revision 1.2  2010/10/05 16:13:49  dim
 Updates prior to iGp12 release

 Revision 1.1  2009/08/29 19:50:47  dim
 Initial import


*/

module fanmon(
  input clk,		// Bus clock (48 MHz)
  input addr,		// Register address
  output [31:0] dout,	// Read data
  
  input [1:0] fan	// Fan signals
);
  reg [1:0] fan1 = 2'b00, fan2 = 2'b00, cout = 2'b00;
  wire [1:0] pulse;
  reg [21:0] out[1:0];
  reg [21:0] cnt[1:0];
  
  debounce de0(.clk(clk), .in(fan2[0]), .out(pulse[0]));
  debounce de1(.clk(clk), .in(fan2[1]), .out(pulse[1]));
  
  always @(posedge clk) begin
    // Debouncing
    fan1 <= fan;
    fan2 <= fan1;
  
    if (pulse[0]) begin
      out[0] <= cnt[0];
      cnt[0] <= 22'b0;
    end
    else begin
      {cout[0], cnt[0]} <= cnt[0] + 22'b1;
      if (cout[0])
        out[0] <= 22'b0;
    end

    if (pulse[1]) begin
      out[1] <= cnt[1];
      cnt[1] <= 22'b0;
    end
    else begin
      {cout[1], cnt[1]} <= cnt[1] + 22'b1;
      if (cout[1])
        out[1] <= 22'b0;
    end

  end
  
  assign dout = addr ? out[1] : out[0];
  
endmodule // fanmon

module debounce(
  input clk,
  input in,
  output reg out
);
  reg [5:0] timer = 6'b0;
  reg state = 1'b0, noisy = 1'b0, cout = 1'b0;
  
  always @(posedge clk) begin
    if ((in ^ state) & ~noisy) begin
      noisy <= 1'b1;
      timer <= 6'b0;
    end
    else if ((in ^ state) & noisy) begin
      {cout, timer} <= timer + 6'b1;
      if (cout) begin
        state <= in; /* State transition */
        if (in) /* 0->1 */
          out <= 1'b1;
        noisy <= 1'b0;
      end
    end
    else if (~(in ^ state) & noisy)
      noisy <= 1'b0;
    if (out) out <= 1'b0;
  end
endmodule

