3
\$\begingroup\$

For the purposes of simplifying a test bench, I would like to set various delays by changing numerical values at the top of the file. I'd like to do something like:

input_frequency : integer := 1000000;
...
constant t_per : time := (1. / input_frequency * 1000000000.) ns;

... which does not compile.

Right now I'm hardcoding:

constant t_per : time := 1000 ns;

I have not been able to get the upper example to work using the variable keyword either.

Is there a way around hardcoding times in VHDL?

\$\endgroup\$
4
\$\begingroup\$

multiply (or operate otherwise) by the time unit

constant t_per : time := (1 / input_frequency * 1000000000) * 1ns; (or variations thereof)

\$\endgroup\$
  • 1
    \$\begingroup\$ Here is one reference that might help: aldec.com/en/support/resources/documentation/articles/1165 \$\endgroup\$ – CapnJJ Oct 3 '18 at 19:55
  • 2
    \$\begingroup\$ Actually, the 1 before ns is not needed, but recommended good style. To get his code running, just the multiplication operator would be needed. There should be a delimiter (whitespace) between the integer value and the secondary unit (ns). \$\endgroup\$ – Paebbels Oct 3 '18 at 20:05
  • 1
    \$\begingroup\$ @CapnJJ Worked like a charm. Thanks. I did not quite understand how the fs/ns/ms/etc. keywords worked. \$\endgroup\$ – schadjo Oct 3 '18 at 20:14
  • \$\begingroup\$ @Paebbels yep. I go back and forth between VHDL and Systemverilog, so syntax gets mashed for me at times :( (I'll leave my answer that way so your comment still applies, for posterity sake) \$\endgroup\$ – CapnJJ Oct 3 '18 at 20:14
  • 1
    \$\begingroup\$ @CapnJJ No complaints about your answer. I just wanted to add that fact :). Why use SV when you have VHDL? (but this question is of topic here ...) \$\endgroup\$ – Paebbels Oct 3 '18 at 20:19
4
\$\begingroup\$

You can convert integer values to type time values. Each time value is represented as a position number on the number scale. Therefore, VHDl offers the attributes 'val(...) and 'pos(...). Each integer unit represents one primary time unit. This primary unit is defined as femtosecond (fs). But many simulators like ModelSim chose a greater primary unit like picosecond (ps). You can set this minimum time resolution limit to femtoseconds with command line option -t 1fs.

Converting integers to time:

constant myInt  : integer := 10000;
constant myTime : time    := time'val(myInt);

This is equal to 10 ps, because it's 10,000 fs. You can convert back with attribute 'pos from a physical type value to a universal integer value.

The same can be achieved by multiplying time values with an integer, because package std.standard contains operator overloads for * to to allow time * integer and integer * time operations.

constant myInt  : integer := 5;
constant myTime : time    := 10 ns * myInt;

this results in 50 ns. Of cause there are more operators overloaded like division or modulo.


If you like to play more with type time or experience other physical type like frequency, have a look at the PoC Library and package PoC.physical.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the heads-up on PoC and answering the question in the general case. I look forward to checking out the PoC materials. \$\endgroup\$ – schadjo Oct 3 '18 at 20:08
-1
\$\begingroup\$

For people coming here from google, this answer is useful for convert frequency to time in test benches:

CONSTANT freq : positive := 50E6;
CONSTANT CLKPERIOD : time := (real(1E9)/real(freq)) * 1 ns;

The real() typecast allow more precise values.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.