I want to calculate time period by using Verilog code. Is this the correct way to get time period of clock of a particular frequency? Please suggest to me some better Verilog code. The code is not working.
I have written this sample code:
module clk(reg gsclk, output reg time1,output time2,output gs_clk_period)
always@(posedge gsclk)time1=$current_time;
always@(negedge gsclk)time2=$current_time;
always@(posedge gsclk)gs_clk_period = (time2 - time1)*2;
$display("%clock %b",gs_clk_period);
endmodule
I have to use time period for synthesize and want to run in real device.
-
\$\begingroup\$ Could you explain more why you are doing this? Are you trying to determine how fast your simulation is running or do you want something you can synthesize and run in a real device? \$\endgroup\$The Photon– The Photon2013年01月26日 16:55:22 +00:00Commented Jan 26, 2013 at 16:55
-
\$\begingroup\$ I have to use time period for synthesize and want to run in real device.This will be use like for example , Vout(n) T = gsclk*2, Vout(n)=gsclk*3 like wise in my program. \$\endgroup\$Manzer– Manzer2013年01月26日 17:04:08 +00:00Commented Jan 26, 2013 at 17:04
3 Answers 3
Verilog offers three system tasks related to the simulation timestep:
$time
returns the current time as a 64-bit integer, in units of the timestep defined by the `timescale directive.
$stime
returns the same value as a 32-bit integer.
$realtime
returns the same value as a real number.
However none of these system directives are likely to be useful for synthesis. They would normally be implemented by special code in the simulator that accesses variables in the simulator program.
To keep track of time in a real circuit, you need to start with an input clock with a known frequency. For good accuracy you'd generate this with a crystal oscillator circuit, which would be entirely outside your device if you're working on an FPGA.
Then you simply build a counter to keep track of ticks of your clock (note code not tested):
module time_counter(input clk, input rst, output reg [31:0] ticks)
always @(posedge clk or posedge rst) begin
if (rst) begin
ticks <= 32'h00000000;
end
else begin
ticks <= ticks + 1;
end
end
endmodule
There is a limit to how fast a counter like this can operate, and various tricks to build faster counters if needed.
If you need to find the period of an input with an unknown period, you need to compare it to a clock with a known period. It's simplest conceptually to make the known clock much faster than the unknown clock and count ticks of the known clock for each period of the unknown clock. If that's not possible, you can divide the unknown clock by some factor (say 16 or 128 or 1024) and count ticks of the known clock for each cycle of the divider to work out the unknown period.
-
\$\begingroup\$ But my question is how to get time period of clock?I mean frequency calculation.If the frequency of clock is 10 mhz, i want to calculate in timeperiod in ns in verilog code?? \$\endgroup\$Manzer– Manzer2013年01月26日 18:11:23 +00:00Commented Jan 26, 2013 at 18:11
-
1\$\begingroup\$ You need to have another clock with known period. Count how many periods of the known clock make one (or 16 or 128 or 1024) period of the unknown clock. But the details of how to do it, beyond what I've already answered, depend on knowing more about your application --- what frequency range are you trying to measure? What technology are you using? etc. \$\endgroup\$The Photon– The Photon2013年01月26日 18:27:12 +00:00Commented Jan 26, 2013 at 18:27
-
\$\begingroup\$ @ThePhoton I also have the same question. I want to find the time period of some unknown incoming frequency having a maximum limit of 9khz. My internal clock is of 100mhz. Can you tell me how to calculate the time period in us. I am trying to write a synthesizable code which will be implemented using Nexys3 board. \$\endgroup\$Bojack Horseman– Bojack Horseman2022年10月31日 14:22:14 +00:00Commented Oct 31, 2022 at 14:22
For it to be synthesize you need a reference clock that you already know the real period (e.g. ref_clk
), then you can estimate the period of any other clock.
You'll need an counter (e.g. gs_cnt
) that is incremented by gsclk
. Let the counter run for ref_cnt
number of ref_clk
cycles. The period of gsclk
can be estimated as ref_period*ref_cnt/gs_cnt
.
It is a good idea to prevent the counter from rolling back to 0 while incrementing. This also lets you know that the gsclk
is to fast to be measured in the ref_cnt
window.
Your code assumes that the clock has 50% duty cycle. Instead you should sample twice in an always
block:
module clk(reg gsclk, output reg time1,output time2,output gs_clk_period)
time rising_edge;
always @(posedge gsclk)
begin
rising_edge = $time;
@(posedge gsclk)
gs_clk_period = $time - rising_edge;
end
endmodule