vhdl for beginners

D

d_s_klein

VHDL tutorial site for beginners..many vhdl tips are explained in a
simpler way.http://vhdlguru.blogspot.com/

Why is it that as soon as someone manages to get a piece of VHDL code
through a simulator without encountering a "blue-screen-of-death" that
they think that they are some sort of 'guru' and need to blog it?

Sheesh.
 
A

Andy Peters

VHDL tutorial site for beginners..many vhdl tips are explained in a
simpler way.http://vhdlguru.blogspot.com/

A "guru" wouldn't use the deprecated std_logic_arith, and a guru
wouldn't use "if (clk'event and clk='1')" when "if rising_edge(clk)"
is available.
And a guru would figure out how to show code using a proper font.

-a
 
A

Andy

A "guru" wouldn't use the deprecated std_logic_arith, and a guru
wouldn't use "if (clk'event and clk='1')" when "if rising_edge(clk)"
is available.
And a guru would figure out how to show code using a proper font.

-a

That's giving Guru's too much credit...

I looked over some of the examples, and it is pathetic. This is one
beginner's site you DON'T want a beginner to be exposed to. The
problem is, a beginner won't know just how bad that site's advice
really is.

Andy
 
V

Vince

Andy Peters a écrit:
A "guru" wouldn't use the deprecated std_logic_arith, and a guru
wouldn't use "if (clk'event and clk='1')" when "if rising_edge(clk)"
is available.
And a guru would figure out how to show code using a proper font.

And a guru wouldn't say a program for a piece of VHDL code...
 
V

vipin lal

first of all,sorry for spamming this newsgroup.After sending the mail
only I realized that I have done something wrong.
Let me write what I think:
1)I dont think that I am VHDL guru.I am just a beginner.But the site
was named just for the sake of a good name.you can say a "SEO" method.

2)Its true that I have not encountered a "blue-screen-of-death" in
VHDL.But when I was learning VHDL I faced so many problems.I had to
research through many forums.When I had problems ,errors etc while
coding I tried googling for them.sometimes it worked.Some times
not.That is why I thought I will write what I have found out,when
learning VHDL , in a blog.

3)If I wait till I learn everything about VHDL,then probably this blog
will never come out...:)

4)I know that there are many mistakes in my codes.Such as the ones you
specified of not using rising_edge(clk),using libraries like
std_logic_arith etc.Thanks more mentioning them.I will keep them in
mind.

5)about highlighting the VHDL syntax I am looking for a VHDL syntax
highlighter which I can use with blogger.com.But havent got one yet.As
soon as I get one,I will put it.I know it is very difficult to read a
code without syntax highlighting.

6)Once again sorry for spamming.


Thanks for the suggestions...
vipin
 
Joined
Mar 16, 2010
Messages
1
Reaction score
0
You are right - all of you

vipin lal, you are right to blog, for so many reasons:

  • You may get constructive criticism like you got from your peers here. Now you can refine your posts.

  • There is so little good beginner level information on the Internet on VHDL development. Or is it just hard to find?

  • When you blog about something, you, yourself thinks more clearly about the topic.


However, it can be hard both to find constructive criticism and to go back and edit your posts into something better.

However people such as, d_s_klein, Andy Peters and Vince may not even bother to comment, if they discover they have to correct the same mistakes over and over again.

This is one reason I urge you to consider contributing your insights, comments and votes on a site like Overmapped.

Information there will not be lost in threads, and knowledgeable members get rewarded scores.
 
A

Andy

Vipin,

At least your heart is in the right place. I admire your initiative,
and have often wished I had the time to write a good tutorial/blog
myself.

It is just that, particularly on this site, there are a lot of us that
use design and coding techniques that many textbooks and college
courses have not (yet) adopted. Principles like single clocked
processs rather than two-process (combinatorial and clocked) methods.
Use of direct entity instantiation, rather than component
instantiation. Use of numeric_std or even the newer fixed_point
packages. Use of integer data types. Even use of variables.

Unfortunately, there is so much momentum behind some rather archaic
methods (after all, they are published in textbooks!), that it is very
frustrating for many of us to see yet another site dedicated to
beginners that just adds to that momentum.

I have a few constructive comments about some of your examples.

For instance, in your CRC example (what looks like almost a simple,
clocked process), you included data in the sensitivity list, and a
conditional based upon it ahead of the clocked clause (if
clk'event...). I'm not sure that most synthesis tools will handle that
the way you want to. I assume you want a synchronous enable function,
enabled only if data is non-zero. If so, remove data from the
sensitivity list, and then rearrange the order of the clocked
condition and the non-zero data condition. You can even combine them:

process (clk) is
begin
if rising_edge(clk) and (unsigned(data_in) /= 0) then...

or...

if rising_edge(clk) then
if unsigned(data_in) /= 0 then...

In clocked processes, conditionals before the clock condition are
usually assumed to be for asuynchronous set/reset, which does not
appear to be what you wanted.

Another area where your coding could use some help (and you mention it
in one of your other posts) is avoiding strings of zeroes or ones
(i.e. '00000000') when a numerical value or an others=> or
array'range => construct makes the code more writeable, readable and
maintainable (immune from data size changes). I hate counting digits,
and will do almost anything to allow the tool rather than me to do it.

Again in CRC, you have an internal counter. This is the perfect place
to do one of two things. Either declare the counter as unsigned in the
first place, or better yet, especially since it is only used to index
an array, declare it as an integer subtype in the first place. Beware,
integer counters will not silently roll over for you, instead you must
conditionally catch the roll-over and assign the next value, or you
can use the MOD operator.

You can use the range of an array as the range for the integer counter
subtype:

signal counter1: integer crc_temp'range;

Declaring things like this makes it clear the relationship between
sizes of different things. In another example, your internal signals
are declared with explicit data widths. Are those widths associated
with port widths, or are they just coincidentally the same? Use a
'range or 'length attribute to make it clear to you and the reader.

Back to integer counters, etc... You have to use mod, /, and *
operators with 2**n operands to shift or strip portions of an integer
counter, instead of using index ranges for SLV/unsigned.

Then your CRC computation lines might look something like:

crc_temp(2) <= data_in(31-(counter1 mod 32)) xor crc_temp(7) xor
crc_temp(1);

This is only my opinion, but I've often thought that the best, most
helpful way to present coding techniques in a tutorial or sequential
blog is to start with a single example, and then present successive
refinements of that example so that readers can follow the design/
coding changes, without also having to figure out what each new
example is trying to do. Sometimes you will have to switch to a
different example, simply because you will run out of things that can
be demonstrated within that context, but this should be infrequent
(i.e. the exception rather than the rule).

Hope this helps,

Andy
 
V

vipin lal

Hi Andy..
thanks a lot, for your reply.

For the CRC example as you said,I initially used just process(clk).But
when I synthesized it said "The following signals are missing in the
process sensitivity list".That is why I included the data_in in
sensitivity list.

I will keep in mind about the "declaring internal counter as
integer".That was one of the earlier programs I wrote.That time I used
only std_logic_vector for each and everything.I am trying to use sub
type integer nowadays.

I will keep all these points when I write my next code.

Is there any good site where you can get professional vhdl
codes.Different people code in different ways and I am confused about
them.
Also some one told you have to use "numeric_std" instead of
"std_arith" and "std_unsignd".What is the reason for this?
Is it possible to write any code,using only "numeric_std".

Regards
vipin
 
A

Andy

The reason you got the sensitivity list warning is that the process
code "looks at" the data_in input before it figures out whether the
clock has changed. This order is typically used for asyncrhonous set/
reset logic (in which case the set/reset input would be included in
the sensitivity list). The change that makes the warning go away is
not necessarily the fix for the problem.

You have described something along the lines of an asyncrhonous clock
enable, and I'm not aware of a reliable mechanism for implementing
that, other than a gated clock, in which case the gate input is
rightly included in the sensitivity list. I'm really surprised the
synthesis tool didn't cough a bit on that too, though maybe it figured
out what you really wanted was a synchronous clock enable. I would not
rely on many tools making the same assumption. Most synthesis tool
will not warn about additional signals in the sensitivity list, but
the simulation will be slower. (It has to do with typical
optimizations in simulators).

std_logic_arith, etc. were packages written by Synopsis and included
in their tools' version of the ieee library, without the approval of
the ieee standardization body. The LRM reserves the ieee libarary for
officially balloted and approved packages for the vhdl language.
However, since the whole world started using synopsys first, and
everyone had started writing code dependent upon std_logic_arith being
in ieee, Synopsys refused to take it out of their implementation. And
since other tools were usually forced to work seamlessly with code
that worked with Synopsys, they followed suit. However, different
vendors implemented the package slightly differently, with some
problems in compatibility. Since there is no standard governing it, it
is subject to change at any time.

So, the IEEE decided to write and approve a standard package for
numerical operations on SL and BIT based vectors. Those packages are
called numeric_std and numeric_bit. These are ieee standard packages,
located in the official version of the ieee library, and their
behavior is governed by the standard, so compatibility is assured.

Numeric_std does not attempt to imply a numerical interpretation on
SLV, but rather defines related types UNSIGNED and SIGNED which have
both numerical and bitwise interpretations (i.e. AND and OR are also
defined for them). This avoids any confusion when needing to use both
signed and unsigned arithmetic in the same body (std_logic_arith
simply assumes all arithmetic is unsigned). Numeric_std defines
arithmetic operations between various combinations of signed, unsigned
and integer operands. In all cases(?) the size of the result is the
same as the largest signed/unsigned operand. Over/underflows are
truncated (rolled over).

The latest version of the vhdl standard does include a package similar
in function to std_logic_arith, etc., named numeric_std_unsigned,
which does define unsigned arithmetic on std_logic_vector operands.
Unfortunately, I know of no tools that support it yet.

Generally, if you can, create your entity interfaces using unsigned or
signed (or even integer)if they are uniformly numerically
interpretted. (i.e. a generic memory device may be able to store any
kind of binary data, so SLV may make more sense there, but a digital
filter has a specific definition of its input data in mind, and that
can be coded by using the appropriate type on the port. Using the
appropriate types on the ports makes it much easier to avoid
conversions within the body.

For example, if you used an SLV input port, and you need to add one to
it and output that on an SLV output port, you must convert twice:

output <= std_logic_vector(unsigned(input) + 1);

This converts the SLV input to unsigned (so that + is defined for it),
adds (integer) one to it (the result is unsigned too), then converts
the result back to SLV for the output port.

It would have been much easier if input and output had been declared
unsigned (or signed) in the first place:

output <= input + 1;

Many users will caution you not to use anything but SL and SLV on top
level device (physical) ports, since most synthesis/P&R tools will
create the gate level model with SL and SLV ports regardless of the
types used for those ports in the RTL. This makes it more difficult to
swap out the RTL model in the testbench with the gate level model,
since the port types on the two models may differ. In practice, it is
not difficult to modify a testbench, or build a wrapper around the
gate level model such that it still interfaces to your RTL-ready
testbench.

Andy
 
V

vipin lal

hi andy.. that was some awesome information..I didn't find in any
sites these things.. I want to share this information in my blog.Hope
you don't mind.

I had little doubt about how successful I will be with writing codes
using only signed or unsigned data types.. but yesterday i wrote some
square root and division functions using numeric_std alone..it worked
well.. thanks..
I will try to avoid the use of SLV as much as possible..

Regards
vipin
 
M

M. Norton

I will try to avoid the use of SLV as much as possible..

I'm not sure that's the lesson to take from Andy's explanation. If I
may be allowed to interpret here, you should use the data type that
fits the data you are representing by that symbol. If you are
shipping around numbers, use unsigned or signed as appropriate. If
you are shipping around discrete logic, use std_logic and
std_logic_vector. The general thrust is that the language supports a
wide variety of data types and to the extent made possible by the EDA
tools, we should use those language features in an intelligent manner
to accurately represent the design we are building.
 
A

Andy

I'm not sure that's the lesson to take from Andy's explanation.  If I
may be allowed to interpret here, you should use the data type that
fits the data you are representing by that symbol.  If you are
shipping around numbers, use unsigned or signed as appropriate.  If
you are shipping around discrete logic, use std_logic and
std_logic_vector.  The general thrust is that the language supports a
wide variety of data types and to the extent made possible by the EDA
tools, we should use those language features in an intelligent manner
to accurately represent the design we are building.

Yes, M Norton has correctly interpreted what I wrote:


Generally, if you can, create your entity interfaces using unsigned
or
signed (or even integer)

!!!if they are uniformly numerically interpretted.!!!

(i.e. a generic memory device may be able to store any
kind of binary data, so SLV may make more sense there, but a digital
filter has a specific definition of its input data in mind, and that
can be coded by using the appropriate type on the port. Using the
appropriate types on the ports makes it much easier to avoid
conversions within the body.



There are many places where unsigned or signed should rightly be used
instead of SLV, but there are also many places where a single numeric
interpretation of the data is not supported, and the more general SLV
remains appropriate.

For example, an ALU that accepts signed or unsigned data (depending on
the operation control) may always have a numeric interpretation of the
data on its ports, but since we do not have a generic numeric signed
and unsigned representation, SLV would still be appropriate for those
ports.

Other examples, as Norton pointed out, include any collection of bits
that does not have a numeric meaning such as a vector of enable bits,
etc.

Andy
 
M

Mike Treseler

vipin said:
I will try to avoid the use of SLV as much as possible..

Since I agree with the others on this thread,
I will play the devils advocate.

What is the upside to a top entity with an SLV interface?

1. Everyone will understand the type and where bit 0 is.
2. Experts will provide conversions to their preferred types.
3. Journeymen will like it as is.
4. Very old synthesis tools will have a chance of working.

-- Mike Treseler
 
V

vipin lal

Hi...
Yeah..I misunderstood Andy in the beginning.Now I got it.
One more doubt.
IS there any math library in VHDL for operations such as square
root,floating point operations etc.Or you should make them your own
according to your own needs?
I am trying to write some functions of some basic operations.But if
any reliable standard library is there,then I can use them instead.

Thanks
vipin
 
R

rickman

Yes, M Norton has correctly interpreted what I wrote:

Generally, if you can, create your entity interfaces using unsigned
or
signed (or even integer)

  !!!if they are uniformly numerically interpretted.!!!

(i.e. a generic memory device may be able to store any
kind of binary data, so SLV may make more sense there, but a digital
filter has a specific definition of its input data in mind, and that
can be coded by using the appropriate type on the port. Using the
appropriate types on the ports makes it much easier to avoid
conversions within the body.

There are many places where unsigned or signed should rightly be used
instead of SLV, but there are also many places where a single numeric
interpretation of the data is not supported, and the more general SLV
remains appropriate.

For example, an ALU that accepts signed or unsigned data (depending on
the operation control) may always have a numeric interpretation of the
data on its ports, but since we do not have a generic numeric signed
and unsigned representation, SLV would still be appropriate for those
ports.

Other examples, as Norton pointed out, include any collection of bits
that does not have a numeric meaning such as a vector of enable bits,
etc.

Andy

Isn't that rather a philosophical approach? If I have a signal that
is sometimes signed and other times unsigned, there is nothing wrong
with declaring it unsigned and then converting to signed when I need
to use it that way. That beats converting to signed as well as
converting to unsigned anytime I need to use if for arithmetic. VHDL
is so verbose that I often code to avoid the verbosity rather than
worrying about philosophical issues.

Rick
 
T

Tricky

Hi...
Yeah..I misunderstood Andy in the beginning.Now I got it.
One more doubt.
IS there any math library in VHDL for operations such as square
root,floating point operations etc.Or you should make them your own
according to your own needs?
I am trying to write some functions of some basic operations.But if
any reliable standard library is there,then I can use them instead.

Thanks
vipin

in VHDL 2008 there are 2 new packages - one for fixed point operations
and one for floating point. The floating point one wont be very useful
until vendors start supporting it and are able to do decent register
re-timing to get the long pipelines required for floating point in
place. But the fixed point package makes code alot more readable when
theres fractional bits flying around. I dont think there is any you
cant already do with the numeric_std package, but it makes aligning
numerator and fractional parts so much easier and much easier to read.

Quick reference and version compatible with VHDL 93 are here:
http://www.vhdl.org/fphdl/
 
A

Andy

The fixed point packages can be used, by specifying zero fractional
(negative indexed) bits, to represent signed and unsigned integer
arithmetic. The fixed point packages assume a more integer-like tilt
toward numeric accuracy than numeric_std does, by expanding the sizes
of results to accurately handle the possible nnumeric range of those
results. So adding two n bit ufixed operands results in an n+1 bit
result. This means that intermediate results in expressions are
numerically accurate (not subject to truncation, except for division),
but due to the inability to override assignment operators in VHDL, the
results usually must be manually re-sized to store in a variable or
signal. Just like with integers, synthesis should be able to do a good
job of removing bits and logic associated with expanded intermediate
results if they do not contribute to those bits retained in storage.

So an up counter would look something like:
variable n : ufixed(nsize - 1 downto 0);
....
-- resize does the rollover
n := resize(n + 1, n);

My biggest disappointment with the fixed point package is that
subtraction of two ufixed operators does not expand the result to
sfixed (but it does expand the size of the results by one bit, which
will always be zero!) So while the ufixed + operator does not roll
over, the - operator for ufixed does, however by some perverse stroke
of luck, you still have to manually resize the result:

variable n : ufixed(nsize - 1 downto 0);
....
-- ufixed subtract does the rollover,
-- resize is still required :(
n := resize(n - 1, n);

Comparatively, with integers:

variable n : integer range 0 to 2**nsize - 1;
....
-- integer mod does the rollover
n := (n - 1) mod 2**nsize;

And with unsigned:

variable n : unsigned(nsize - 1 downto 0);
....
-- unsigned subtract does the rollover
n := n - 1;

Andy
 
V

vipin lal

The fixed point packages can be used, by specifying zero fractional
(negative indexed) bits, to represent signed and unsigned integer
arithmetic. The fixed point packages assume a more integer-like tilt
toward numeric accuracy than numeric_std does, by expanding the sizes
of results to accurately handle the possible nnumeric range of those
results. So adding two n bit ufixed operands results in an n+1 bit
result. This means that intermediate results in expressions are
numerically accurate (not subject to truncation, except for division),
but due to the inability to override assignment operators inVHDL, the
results usually must be manually re-sized to store in a variable or
signal. Just like with integers, synthesis should be able to do a good
job of removing bits and logic associated with expanded intermediate
results if they do not contribute to those bits retained in storage.

So an up counter would look something like:
variable n : ufixed(nsize - 1 downto 0);
...
-- resize does the rollover
n := resize(n + 1, n);

My biggest disappointment with the fixed point package is that
subtraction of two ufixed operators does not expand the result to
sfixed (but it does expand the size of the results by one bit, which
will always be zero!) So while the ufixed + operator does not roll
over, the - operator for ufixed does, however by some perverse stroke
of luck, you still have to manually resize the result:

variable n : ufixed(nsize - 1 downto 0);
...
-- ufixed subtract does the rollover,
-- resize is still required :(
n := resize(n - 1, n);

Comparatively, with integers:

variable n : integer range 0 to 2**nsize - 1;
...
-- integer mod does the rollover
n := (n - 1) mod 2**nsize;

And with unsigned:

variable n : unsigned(nsize - 1 downto 0);
...
-- unsigned subtract does the rollover
n := n - 1;

Andy

Thanks Andy..
I started using fixed_pkg and wrote some simple programs also.But when
I tried to synthesis the code it came "Library ieee_proposed cannot be
found."
I successfully simulated the same design.
Is Library ieee_proposed not synthesisable????????
pls help...
 
V

vipin lal

Thanks Andy..
I started using fixed_pkg and wrote some simple programs also.But when
I tried to synthesis the code it came "Library ieee_proposed cannot be
found."
I successfully simulated the same design.
Is Library ieee_proposed not synthesisable????????
pls help...
I am using Xilinx ISE 10.1
 

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

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top