Here's an analogy which helps some people (especially those from a physical electronics background):
A component
tells the compiler "there's going to be something with these sorts of pins on it called this at some point, but don't worry for now". It sort of defines a "socket". You can go on to describe what "wires up" to that "socket" etc.
An entity
is something specific with a name and a set of pins, which the compiler can then "plug in" to that "socket" (and hence be connected to the "wires").
Note that you don't need a component
you can do "direct instantiation" which means the compiler already knows about an entity so the "socket" doesn't need to be defined separately. In fact, that would be my recommended approach, as otherwise the component
is an extra level to be kept in sync.
You need to use components if you are mixing Verilog and VHDL and need to use a Verilog block within the VHDL. Then the component
is the socket and not until much later on can the compiler/elaborator plug the Verilog into the socket.
This is where you can tell that VHDL was invented by a government committee. If VHDL was designed to be consistent then what you're referring to as "to" would be called "upto"-- as in the opposite of "downto". In this answer I will refer to "upto". Just understand that I'm using this term for clarity-- it still isn't an official VHDL keyword.
Vectors, or arrays, can have a range that is decending or assending. For example:
signal foo :std_logic_vector (7 downto 0);
signal bar :std_logic_vector (0 to 7);
This is strictly a numbering convention and has little to do with the resulting logic efficiency. Mostly, the correct one to use depends on what makes the most sense to the writer of the code.
That being said, never use "upto" unless you have to. What follows is my personal opinion, but it based on 20 years of writing VHDL professionally and 30 years of writing software:
Mixing downto and upto in the same code is always problematic. It can be done, but it requires careful planning and notation to get right. Even then, the code ends up to be difficult to read and modify later. It is very easy to confuse which signals are downto and which are upto.
Most busses are numbered using "N downto 0", where bit 0 is the least significant and N is the most significant. Because of this, downto is the most important of the two. And since we don't want to mix downto and upto, upto is given the boot. In every case where I've used upto, I have regretted it and usually ended up rewriting the code.
Understand that the use/misuse of upto mainly becomes an issue in large "programs". It makes it hard to share modules (a.k.a. code reuse), and hard to maintain and debug code. If you're just writing a page or two of VHDL then it might not matter. But if you're writing FPGA's with 30,000+ lines of VHDL then this will be a huge issue.
There are only a few downsides to only using downto. But the downsides are tiny compared to the problems I've encountered mixing downto and upto.
As a side note: The guy who decided to make the PowerPC busses reversed (with bit 0 being the most significant bit) should be tar'd and feathered. Or at least forced to watch Richard Simmons 24x7 while in solitary confinement. Just sayin.
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) orsleep()
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.
And finally
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 :
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 so7 + 7 = 6
or whatever is cheapest in hardware.So get the design right in simulation first...