Constants?

A

Alfonso Baz

I come from a C programming background where something like this can be done
#define MAX 32

at compile time the source code is parsed and any instants of MAX are
replaced with 32 before being passed to the compiler proper

I have been using constants thinking they were the same thing, but on closer
inspection I see we're having to give it a type also. This is leading me to
believe that a constant takes up hardware resources.

Does VHDL have some kind of pre-compiler/parser that can handle substitution
and math prior to compiling such as this in C
#define MAX 32
#define EXP 2
....
if( x == MAX^EXP)...
which gets changed to
if(x == 1024)

Thanks
 
K

KJ

Alfonso Baz said:
I come from a C programming background where something like this can be
done
#define MAX 32

at compile time the source code is parsed and any instants of MAX are
replaced with 32 before being passed to the compiler proper

I have been using constants thinking they were the same thing, but on
closer inspection I see we're having to give it a type also. This is
leading me to believe that a constant takes up hardware resources.

Constants do not use any hardware resources. The reason VHDL constants must
have a type is because the VHDL language is strongly typed whereas C with
#define is not. Whether you've hard coded value or defined a constant that
evaluates to the value doesn't matter. The synthesized result will be the
same.
Does VHDL have some kind of pre-compiler/parser that can handle
substitution and math prior to compiling such as this in C
#define MAX 32
#define EXP 2
...
if( x == MAX^EXP)...
which gets changed to
if(x == 1024)

You can generally use the language itself without any pre-compiler/parser.
Any place where you would generally type in some hard coded constant you can
use a function of arbitrary complexity instead. Some examples:

Assume you have some function called 'foo' that takes a couple of arguments
and returns a value of type integer
function foo(a: real; b:integer) return integer;

Then you can use foo to define constants like any of the following...

entity ent_foo is generic(
some_real_generic: real;
some_integer_generic: integer);
port(
-- foo is used to define the upper end of the range of a vector
xyz: in std_ulogic_vector(foo(some_real_generic, some_integer_generic)
downto 0));
end ent_foo;
architecture foofoo of ent_foo is
constant some_constant: integer := foo(1.0, 3);
....

Usually the only limitations you may run into with a synthesis tool is
whether or not they support the underlying data types. Quartus and Synplify
both support use of 'unsynthesizable' types such as 'time' and 'real' when
they are used to compute constants even though you can't create signals of
those types.

Functions of course can return any data types that you'd like, so you can
define vectors, arrays, custom types, etc. The hurdle for those used to C
programming is that in C the #define is a text substitution that doesn't
care about what it is being subbed into whereas VHDL, because of the strong
typing doesn't allow for such shenanigans. While it seems at first to be a
pain, the advantages of the type checking make it worth the effort. It's
not harder in VHDL, just different so that's the only hurdle.

Kevin Jennings
 
A

Alfonso Baz

Constants do not use any hardware resources. The reason VHDL constants
must have a type is because the VHDL language is strongly typed whereas C
with #define is not. Whether you've hard coded value or defined a
constant that evaluates to the value doesn't matter. The synthesized
result will be the same.

Good to hear.
You can generally use the language itself without any pre-compiler/parser.
Any place where you would generally type in some hard coded constant you
can use a function of arbitrary complexity instead. Some examples:

Assume you have some function called 'foo' that takes a couple of
arguments and returns a value of type integer
function foo(a: real; b:integer) return integer;

Then you can use foo to define constants like any of the following...

entity ent_foo is generic(
some_real_generic: real;
some_integer_generic: integer);
port(
-- foo is used to define the upper end of the range of a vector
xyz: in std_ulogic_vector(foo(some_real_generic, some_integer_generic)
downto 0));
end ent_foo;
architecture foofoo of ent_foo is
constant some_constant: integer := foo(1.0, 3);
...

Wow, you could almost call that a compile time macro
Usually the only limitations you may run into with a synthesis tool is
whether or not they support the underlying data types. Quartus and
Synplify both support use of 'unsynthesizable' types such as 'time' and
'real' when they are used to compute constants even though you can't
create signals of those types.

Functions of course can return any data types that you'd like, so you can
define vectors, arrays, custom types, etc. The hurdle for those used to C
programming is that in C the #define is a text substitution that doesn't
care about what it is being subbed into whereas VHDL, because of the
strong typing doesn't allow for such shenanigans. While it seems at first
to be a pain, the advantages of the type checking make it worth the
effort. It's not harder in VHDL, just different so that's the only
hurdle.

Kevin Jennings

Thanks very much for your in-depth reply Kevin, much appreciated and
enlightened

Alfonso
 
S

seth.mart

Good to hear.










Wow, you could almost call that a compile time macro








Thanks very much for your in-depth reply Kevin, much appreciated and
enlightened

Alfonso

excellent explaination of strong typing in vhdl.
 
A

Andy

To add a little to KJ's excellent explanation,

Constants sometimes do consume hardware, depending on how they are
used, which is no different from pre-processor macros. For example,
constant arrays which are indexed by dynamic signals are usually
implemented as logic or ROMs in hardware. Constant arrays indexed by
other constants are often completely optimized, just like scalar
constants. A constant array can also be initialized by a function
call.

Most tools also allow top-level generics to have their values set via
command line arguments.

Generics also allow default values to be specified, which makes
passing them down from above optional. For example, the size of a
graphic image to be processed could be controlled via a generic, and
defaulted to the size required in hardware, but made smaller when the
UUT is instantiated in the test bench to speed up simulations that are
merely attempting to proof out the image operations.

Andy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top