In the series of learning FPGA project , here is simple little project to measure frequency with counter and few 7 segment display.
Measuring Maxim DS32Khz output absolute bang on |
Theory Of operation
there is nothing much to it actually , you need a counter (count) which increments with the rising edge of input signal (sigin) and you have to have a control (gate) through gate when counter counts when it does not. so if you keep gate open for 1sec flat , so after 1sec the value you have with the counter (count ) is your frequency.
lets look at this timing diagram , it has a signal input sigin, gate pulse gate, counter value count , frequency display freq,
the gate goes high (active ) for a fixed amount of time ,1 Second ,when gate is high(active) counter start increment on every rising edge of the sigin and keep on increment till gate is high , as soon as gate goes low , counter stop at the value how many rising edge was there in the sigin during the gate was high(active) . as gate time is 1 Second so what ever value is there in the count is your frequency ,
Now we need to update this value to frequency display . as soon as gate time expires it put the value of count to frequency display register.
for next sample gate pulse again go high and clear the count register also.
Verilog Model
first of all you need a counter , which increment on input and give a output , we have already implemented such counter in our last project but still here is the code
you will the another module to drive counter modules input , it will be the freq_meter module which will control this timer module by providing it gate (rst) , input signal (clk) and taking it's count value and putting it to a 7 segment display
freq_meter.v
after this you have a binary data in freq but to be displayed at 7 segment display you need to first covert it into BCD , which will be done by bin_to_bcd.v module, and then take that bcd and covert it to 7 segment code that is done by bcd_to_seg.v , all the source code is available at my github repo.
Hardware.
Test & Validation
Accuracy depended on the on board 25Mhz crystal and +/- 1 digit
first of all you need a counter , which increment on input and give a output , we have already implemented such counter in our last project but still here is the code
module timer(rst, clk, count);// a counter parameter size = 32; input rst; // These inputs/outputs represent input clk; // connections to the module. output [size-1:0] count; reg [size-1:0] count=0; // Signals assigned // within an always // (or initial)block // must be of type reg // The always statement below is a parallel // execution statement that // executes any time the signals // rst high to low or clk transition from low to high always @ (posedge clk or negedge rst ) begin if (!rst) // This causes reset of the cntr count = 0; else if(count<32'hFFFFFFFF) begin count = count + 1'b1; end end
endmodule
|
you will the another module to drive counter modules input , it will be the freq_meter module which will control this timer module by providing it gate (rst) , input signal (clk) and taking it's count value and putting it to a 7 segment display
freq_meter.v
module freq_meter( clk, segment, digit, sigin ); output [7:0]segment; output [7:0]digit; input clk; input sigin; reg [7:0]digit = 8'b01; reg [31:0]freq; wire [3:0]dispdata[7:0]; reg [2:0]digit_scan; reg [23:0]disp_scanner; reg [31:0]gatecounter; reg gate; wire [31:0]count; bcd_to_seg s1(dispdata[digit_scan],segment); bin_to_bcd b1(freq,dispdata[0],dispdata[1],dispdata[2],dispdata[3],dispdata[4],dispdata[5], dispdata[6],dispdata[7]); counter c1(gate,sigin,count); always @(posedge clk ) begin if(!gatecounter) begin gatecounter = 'd25000000; gate =0; freq = count; end // if !gatecounter end else begin gate =1; end gatecounter = gatecounter - 1'b1; disp_scanner = disp_scanner +1'b1; if(disp_scanner=='d50000) begin digit = {digit[6:0],digit[7]}; digit_scan=digit_scan+'d1; disp_scanner = 0; end end // always end endmodule |
after this you have a binary data in freq but to be displayed at 7 segment display you need to first covert it into BCD , which will be done by bin_to_bcd.v module, and then take that bcd and covert it to 7 segment code that is done by bcd_to_seg.v , all the source code is available at my github repo.
Hardware.
Test & Validation
Accuracy depended on the on board 25Mhz crystal and +/- 1 digit
Source Code and Design file
all the source code is available in the github repo
https://github.com/circuitvalley/WireFrame-FPGA/tree/master/VerilogHDL-Modules/Frequency_Meter/
What would be the maximum frequency this could detect? Would it work up to 125MHz?
ReplyDeletecertainly it can , but as it has only 8 digit , either you add one more digit or you have resolution of 10Hz instead 1Hz. in both case little modification to verilog code is required.
DeleteAre you using a 555 timer to generate the waveform and frequency for the FPGA board?
ReplyDeleteno, i used my home made Signal Generator
Deleteif you cant make a tachometer with FPGA cyclone IV
ReplyDeleteCould this work with a spartan 3e starter pack fpga? Thanks for the post.
ReplyDeleteit will work with any FPGA with enough cells to fit model.
DeleteHi Great Work,
ReplyDeleteI am new to FPGA. Pl let me know how to send freq [reg [7:0]freq;] value to serial monitor. In verilog I am using an array [ wire [7:0] BIT_ARRAY[7:0] ;] to assign value to array elemnts & sending it to Serial Monitor.