Integer - Time Conversion that actually works!

Hello,

I was recently looking at section 4.2.8 of the VHDL FAQ, which gives the

following example of Integer - Time Conversion

http://www.*-*-*.com/ #integer_time

architecture convert of x is

signal a,c : integer:=20;

signal b : time;

begin

process

begin

wait for 1 fs;

a <= a + 1;

b <= a * 1 fs;

wait for 1 fs;

c <= b / 1 fs;

end process;

end;

I was also recently writing a test bench that some time to real

conversion, and I came to the conclusion that the above example may be

correct from the point of view of the LRM, but it doesn't work so well

with the actual tools that we use.

For example, Modelsim uses a 64 bit signed integer to represent time (*

see footnote) but it only uses 32 bit signed integers to represent the

VHDL integer type.

This means that if in the above example, b had a value greater than

2.147 us, the integer c would not get the correct value, as 2.147 us / 1

fs overflows the 32 bit integer c.

2.147 us is not a very long time!

My fix was to divide not by 1 fs, which is the smallest time step

possible in VHDL, but to divide by the smallest time step possible in my

model, which was half the clock cycle. (Obviously if multiple clocks

are used, this wouldn't work quite so well.)

I felt this was much better than just guessing some fixed value in ps,

ns or us, which may not scale well with changes in clock rate.

Besides, I already had a constant that defined half the test clock

frequency.

The following code fragments are from my testbench, which I have tested

to be robust (in terms of accuracy) over widely varying simulation

periods, using two different simulators (Modelsim and Simili):

generic (

f_in : real; -- Hz, input frequency

);

...

constant clock_half_period : time := (0.5e15 / f_in) * 1 fs;

constant clock_period : time := 2 * clock_half_period;

-- Normally, we would say clock_half_period := clock_period / 2;

-- but that can lose accuracy, due to the implicit floor().

...

clock_generator : process

begin

clock <= '1';

wait for clock_half_period;

clock <= '0';

wait for clock_half_period;

end process clock_generator;

...

-- Here's where I needed the Time -> Real conversion

measured_frequency <= real(number_of_outputs) /

real((now - time_of_first_output) / clock_half_period) * f_in * 2.0;

(*) You can test this by putting Modelsim into fs resolution

(vsim -t fs) and noticing that time goes negative after about 2 hours

and 33 minutes. If you are doing any calculations involving time, these

calculations may overflow and produce rubbish answers much earlier.

I just thought I'd share my findings with you.

Regards,

Allan. "Nine parts water, one part sand."

--

Agilent Technologies Voice: +61 3 9210 5527

Advanced Networks Division Fax: +61 3 9210 5550

347 Burwood Highway Forest Hill 3131 Australia