Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
17 years ago

Frequency Counter in Verilog?

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?

5 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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 :)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    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
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    --- 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 
    ...