Reciprocal Counter

The favorite HDL language in North America

Reciprocal Counter

Postby crasic » Thu Jul 29, 2010 10:16 am

Hi all,

I'm trying to build a reciprocal frequency counter in an FPGA (A cyclone 2 on a DE2 board to be exact). I've been floundering the last 2 weeks with getting it working correctly

I'm interfacing it to a nios2 running uClinux (hardware driver is written and sending data via ethernet to my PC for saving and analysis).


The reciprocal counter consists of 3 individual counters. One is a simple 32 bit counter clocked by the input signal, this gives you the number of signal pulses over which to average the phase over. The other two are period counters, they count the duration of the input signal HIGH in numbers of fast clock pulses (100 Mhz system clock - 10Mhz Oven controlled external oscillator times 10 in a pll). The only difference is that one of the counters counts the negative pulse duration and the other counts the positive pulses - this takes allows you to count non-50% duty signals.

A global trigger (1, 10, 100hz selectable) is used to save the counters and to interrupt the cpu. The OS reads the values of the three counters and sends them off to the PC, synchronously with the trigger. The pc simply averages the positive and negative period counts and divides by the number of pulses in order to get an average period. One over which is the average frequency

Since the input signal is not synchronous with the trigger, it is quite possible that you get a trigger in the middle of a period count. This throws off the average because you are really measuring less full signal periods than the coarse counter would suggest. The average is thrown off enough that the frequency dances +-3 Hz, which with a counting time of 1second is about 3 times higher than it should be.

The sollution I came up with is a scheme where you count each period individually and then add it to the total count only if you see negative edge of the signal.

The problem is that it isn't working properly. The period count dances around as much as with the simple version of the counter. And Quartus is throwing me a clock hold violation - the timing constraints are not met.

In general I just need a second (third, fourth, etc.) pair of eyes to look over my code and tell me what I could do to improve it.

Code: Select all
module phase_counter_hw(
   input clock,
   input sig,
   input trigger,
   output reg[PHASE_RESOLUTION-1 : 0] phase
   );
   
   parameter PHASE_RESOLUTION = 32;
   
   
   reg [PHASE_RESOLUTION - 1 : 0] full_count;
   reg [PHASE_RESOLUTION - 1: 0] buffer;
   reg ready, ignore;
   
       always @(posedge(trigger)) begin
      phase <= full_count;
   end
   
   always @(posedge(clock) or posedge(trigger)) begin
      if (trigger) begin
         full_count<=0;
         buffer <= 0;
         ready <= 0;
         ignore <= 1;
      end
      else if (sig) begin
         ready <= 1;
         buffer <= buffer + 1;
      end
      /* if we triggered in the middle of a signal pulse
      we need to ignore that count, so after sig goes low
      we just drop that buffer*/
      else if (ignore) begin
         ready<=0;
         buffer<=0;
         ignore <=0;
      end
      else if (ready) begin
         ready <= 0;
         full_count <= full_count + buffer;
         buffer <= 0;
      end
   end
endmodule



And if anyone cares: BSD licensed, so copy at will.
crasic
 
Posts: 1
Joined: Thu Jul 29, 2010 9:51 am

Return to Verilog HDL