VHDL difference between component and subprogram

vhdl

I've read different article (and book chapter too) about "component" and "subprogram".
What i don't understand is what is the difference between the two…

I mean, i know that the component make easier the "hierarchical design" grouping "hardware pieces" somehow, while subprogram groups piece of code, but what i do not understand is how all this stuff behaves in synthesis. It is easy for me to understand how component behaves in synthesis (probably a compiler expand the component and just infers the logic embodied) but i don't figure out how a subprogram or function are synthetized.

Could you help me to understand?

Best Answer

First, look at subprograms. Subprograms are exactly as they are in a conventional programming language, C or Ada for example. Functions abstract over expressions, procedures (=void functions) abstract over statements. And they are normally called within sequential code, i.e. within a process ... and the process is key here..

(for completeness, functions can also be called outside a process, e.g. in a declaration to initialise an array or memory block)

Now a process resembles a complete C program (ignoring C's fork, join, pthread library etc which create multiple processes; ditto Ada's multitasking)

When you start it, it runs through to completion and stops - unless it contains a wait statement (VHDL) or sleep() call (C). And in VHDL for hardware, the normal form of process is started automatically when any signal in its sensitivity list (e.g. clock) is active.

(Think of clock or any other signal in VHDL as a communication channel from some other process - if you've used named pipes in C, you'll get the basic idea, but using signals is much easier)

Understand processes properly - including the fact that they can use variables exactly like your Ada or C program uses variables - and they can use signals differently, as communication to other processes, and we can move on to components.

Now you can view a VHDL design as composed of many processes, all communicating with each other using signals. Each process, internally, behaving like a simple C or Ada program. (Note that concurrent VHDL statements such as signal assignments are really a shorthand way of writing processes, so at the concurrent level, everything is a process. And at the sequential level, i.e. inside a process, everything is a statement or expression)

But what abstracts over processes, in the same way functions do over expressions?

First : entities/architectures.

  • An entity defines the interface to a process (or a group of processes) - i.e. its ports are the incoming and outgoing signals. Note the similarity to the argument list of a subprogram.
  • An architecture provides an implementation of the entity.

And finally

  • A component describes an entity you want to use in your design. It need not actually exist yet - but when you build the design (called "elaboration", a bit like linking) the libraries will be searched for an entity matching that component declaration. And then, failure to find an exact match (are you using the right libraries?) will be an error.

You can actually instantiate entities directly in a VHDL architecture and avoid dealing with components altogether : this involves specifying the precise library you want to find it in, and if you're doing this, the entity must already exist.

EDIT : what does synthesis do with a function? It implements it - or if you get too clever with older buggy synth tools, reports an error. Taking an integer addition as an example :

  • if both actual arguments are constants, it performs "constant folding" optimisation and generates no hardware for the addition
  • if both arguments are signals or variables, it will probably generate an adder of the correct size (inferred from the type of the arguments and result) i.e. if the arguments and result are all `natural range 0 to 7" it will generate a 3-bit unsigned adder.
  • NOTE that given this range restriction, adding 7+7 is erroneous behaviour. In simulation, assigning the result would report an error (unless you are using a broken simulator where range checks are off by default - like Xilinx ISIM). Synthesis, however, is allowed to assume you have verified correctness in simulation, so it has permission to do anything with broken code. In practice it'll probably wrap round so 7 + 7 = 6 or whatever is cheapest in hardware.
  • At a later stage it'll aggressively optimise : so if you add 1 to a variable, and an incrementer is cheaper than an adder, that's what you get.
  • Or if you neglect to use the result, it'll aggressively trim out the adder, and anything that led up to generating both arguments (if they aren't used anywhere else).

So get the design right in simulation first...