Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
21344 Discussions

Frequency Counter in Verilog?

Altera_Forum
Honored Contributor II
7,980 Views

Hi all, im trying to measure a squarewave frequency which is coming from a tacho. 

 

The first implementation i tried used a known frequency and between rising edges of this frequency the rising edge of the input was counted. Once the know frequency gave a rising edge again the count was recorded then reset.  

 

Im not sure why but it didnt work!?!? 

 

The i went on to use a much quicker reference frequency and counted how many rising edges of this occured between rising edges of the input. the reference frequency is 10KHz. 

 

My coded didnt seem to simulate correctly!?! 

 

module f_count(resetn,ref_clock,in_clock,f_measurment); input resetn,ref_clock,in_clock; output f_measurment; reg f_measurment; integer count; always@(posedge ref_clock) // on rising edge of the reference 10KHz begin if(resetn) // if reset line is high do the operation begin count=count+1; // increase the count end else // if reset line is low count=0; // then reset the count to zero end end always@(posedge in_clock) // on rising edge of the input begin frequency=10000/count; // calculate the frequency based on the count value count=0; // then reset the count to zero for the next measurment end endmodule  

 

The simulation in Quartus II just didnt work as I wanted, the count did seem to make sence it reduced in frequency!?!?!  

 

Am i going about doing this all wrong?
0 Kudos
5 Replies
Altera_Forum
Honored Contributor II
5,644 Views

You failed to mention whether this module will be synthesized or if it is only for simulation. If it is for synthesis, it will not compile as your are breaking a few rules. In either case, give this a try. I didn't compile this but you get the idea 

 

module f_count( input resetn, input ref_clock, input in_clock, output reg f_measurment ); reg in_clock_rsync; wire in_clock_rise; reg count; // Look for rising edge of in_clock assign in_clock_rise = ~in_clock_rsync & in_clock_rsync; // Resynchronize in_clock to ref_clock domain always @(posedge ref_clock) in_clock_rsync <= {in_clock_rsync,in_clock}; always @(posedge ref_clock or negedge resetn) if(!resetn) begin count <= 14'd0; // reset counter f_measurment <= 14'd0; // reset output end else begin count <= count + 14'd1; // increment counter by default if(in_clock_rise) begin count <= 14'd0; // reset counter f_measurment <= 10000 / count; // determine output end end endmodule  

 

Your 10khz reference clock obviously doesn't allow you to measure a wide range of frequencies. You can really only measure frequencies between 1Hz and 5kHz and of course at higher frequencies, you'll have more error. 

 

Jake
0 Kudos
Altera_Forum
Honored Contributor II
5,644 Views

Hi there, the design will hopefully be implemented fully into a Cyclone II ( I have one of the Cyclone II eval boards).  

 

The frequency range will be from a tacho mounted on a Yamaha R6 Motorbike engine which at maximum rev range will input 217 (approx) Hz square wave. Basically we want to monitor the revs remotely in the test chamber.  

 

Ill take a look at the example you posted and see how i get on...i only began using Verilog in September of last year so im still new to the syntax i guess :)
0 Kudos
Altera_Forum
Honored Contributor II
5,644 Views

Let me know if you have questions.

0 Kudos
Altera_Forum
Honored Contributor II
5,644 Views

If you monitor the frequency with an external system, maybe it is better to do the divide over there, and not in the fpga. Just send the counts over. 

 

Stefaan
0 Kudos
Altera_Forum
Honored Contributor II
5,644 Views

 

--- Quote Start ---  

 

// Resynchronize in_clock to ref_clock domain always @(posedge ref_clock) in_clock_rsync <= {in_clock_rsync,in_clock}; endmodule  

 

Jake 

--- Quote End ---  

 

 

the 3-bit wide in_clock_rsync is never used..  

 

did you mean  

 

always @(posedge in_clock_rsync or negedge reset_n) if(!reset_n) begin count <= 32'd0; // reset counter f_measurment <= 32'd0; // reset output end ...
0 Kudos
Reply