Best advice for FPGA/VHDL beginner?

K

KK6GM

As I've mentioned in another post, I'm a longtime software guy with
decent hardware experience (I've designed much of the hardware I've
programmed), but I've only dipped into the FPGA/VHDL waters in the
past few weeks. (And I must say, I'm fascinated by it all!)

So far, I've gotten advice on clocking at lower frequencies (generate
1-of-N clock enables) and I've read and understood (?) about unwanted
latches. I've gotten my Nexys2 counting, multiplexing the display,
debouncing buttons, simple stuff like that. So what I'm interested in
is something along the lines of the top N bits of advice for
beginners. These can be as simple as a single sentence ("Always
do..." or "If this than that"), I can probably take it from there. Or
pointers to good articles on the net. I'd really appreciate tapping
into the collective knowledge here. Thanks.

Mike
 
J

Jonathan Bromley

So far, I've gotten advice on clocking at lower frequencies (generate
1-of-N clock enables) and I've read and understood (?) about unwanted
latches. I've gotten my Nexys2 counting, multiplexing the display,
debouncing buttons, simple stuff like that. So what I'm interested in
is something along the lines of the top N bits of advice for
beginners. These can be as simple as a single sentence ("Always
do..." or "If this than that"), I can probably take it from there. Or
pointers to good articles on the net. I'd really appreciate tapping
into the collective knowledge here.

As for any knowledge transfer, it's unwise to seek one-size-fits-all
solutions. I am pretty certain that if you could put together a
two-page Top FPGA Desiderata sheet that was genuinely useful to a
wide audience, someone would have already done it; I'm not
aware of anything that fits the bill.

Your specific situation (s/w guy with good hardware experience
but little exposure to FPGAs and HDLs) is fairly unusual, but
we've had a few such popping up here in the past and, like you,
they generally seem to get the hang of things faster than most.

Many of the guidelines you'll find for HDL design are unduly
prescriptive and limiting, partly because there's a sense that
traditional digital designers aren't ready to exploit the
full power of HDLs that software people often try to use
instinctively. Other guidelines are aimed at dyed-in-the-wool
software people who wouldn't know a clock edge if you tried to
cut them with it. I would not wish to insult your intelligence
with either of these flavours of cookbook.

Every time I write any HDL code, I'm making use of a large
body of experience, wisdom, tricks and pitfall-avoidance
techniques that I've accumulated over half a lifetime of
real do-it-in-anger work. Much of that is stuff I've
learnt from others; some is stuff I've invented for myself
because of frustration with the standard solutions. Despite
having been a teacher and trainer for a large part of that
half-a-lifetime, I still don't know any good way to capture
that accumulated know-how in a short document.

So I'd instead urge you to go on using your own insight,
which is clearly pretty reliable, and keep coming back
here or to any other forum you trust. Treat textbooks
with the circumspection they mostly deserve, and be even
more cautious of web-based information which is often
motivated by vanity or commercial interests. A couple
of comments on your solution to your problem, from an
experienced reviewer, are likely to be more valuable to
you than any amount of staring at a cheat-sheet of
guidelines. You seem already to have bought in to
the really fundamental stuff (be synchronous; be
aware of the hardware your code implies; be aware
that you're writing code, so all the usual good
sense about software applies equally to HDL code).

My best shot at guidance that might be useful to you:
SIMULATE AND SYNTHESISE early and often. Review the
results of both processes and be sure you understand
how they relate to your original design intent. Be
on the lookout for synthesis results that look bloated
or wasteful of hardware - they probably indicate that
you wrote a software-like description without thinking
of the hardware consequences. Be on the lookout for
unexpected or flaky behaviour in simulation, and be
sure you understand the reasons before moving on -
errors are much easier and cheaper to fix if you
fix them early in the development cycle.

In other words, keep your brain engaged. That's all.

Good luck and happy designing,
 
J

Jonathan Ross

As someone who made the transition from software to hardware over a
year ago, but had little hardware experience, there are some things
that bit me that are still fresh. The numbers below are to delineate
ideas, they've nothing to do with priority:

1. As Jonathan Bromley said, simulate and synthesize often. As a
software developer I'd never written a test bench for a module of code
before, only for entire projects. Write a test bench for everything.
2. To go further, early on in your design allow speed of synthesis to
inform your design. That is, you could have a 20,000 line project that
altering a single line of VHDL affects a 20 minute or 3 hour synthesis
time, and may not offer any actual optimization benefit. If it's worth
keeping log that you went with the less optimal code-wise option and
save it for production releases...
3. Don't be too clever. In software if it's syntactically legal you
can do it, in VHDL it may simulate, but if your code isn't a common
idiom it may be rejected in synthesis, or may not be optimized.
Therefore every time you get an idea you think is clever, try it in a
sandbox first before you encorporate it in a project and heap other
code on it only to find out you've wasted 3 days because the code
simulates but won't synthesize.
4. Elaboration is your friend (I believe this is the name of the
stage, someone correct me if I'm wrong...) In many software languages,
besides some very simple expressions, most code makes it into the run
time. In VHDL any constant expression can be evaluated during
elaboration (again, correctme if wrong on the term), including user
defined functions.
5. In a process, signal assignment occurs at the next 'wait', which in
synthesizable code usually means at the end of the process. This means
that there's room for a concurrent process to pick up processing on a
synchronous process's results combinatorially IN THE SAME CLOCK CYCLE.
The information I read early on led menincorrectly to think that a
signal assignment always occurred in hardware at the end of the clock
cycle. Similarly, you make put combinatorially logic and processes
before your synchronous logic to move some setup burden to before a
clock cycle. I.E. If you have a block ram, which is synchronous, you
could do some combinatorially processing on data to be written to it
in the same entity it's instantiated in, but in the clock cycle of the
entity sending it data.
6. Wires are free. For example, if you have an enumerated type and an
instance of it, you may want to check it's value and make a decision
based on the result (I.e. If statement). This takes a minimum of 1 lut
or mux if it's binary, gray, of lfsr encoded, bit if it's one hot
encoded checking if it's equal or not equal to a value requires 0
logic! Similarly, perjuring values, shifting endianess, etc., is
always free.
7. Think more like a human. In Software development you try to keep
steps as simple as possible be wise the more complex your code, the
longer the sequences of instructions and the slower it is. In an FPGA
checking edge cases is almost free. The way humans tend to think of
tasks is they know bow to do the most general case, and handle the
edge cases differently, and since our minds work in parallel we can do
several approaches simultaneously and just pick the right result. An
example might be if you're trying to insert elements into a BRAM based
on some characteristic (I.e. values over x go in A, values under go in
B, and if x presents itself, put it in a register C) I'm sorry I can't
give a better example, I have 3-4 great cases in code I'm looking at
now, but it's all proprietary.
8. More of a warning than a suggestion: information is sparse. There
isn't a huge open source movement, and as a software developer you
won't be used to the idea that googling an error number from a
synthesis tool may have 0 results (more than half the time this is the
case). I also used to like to joke that software programming made a
lot more people athesists, since when you first start you presume a
lot ofthe errors you get must be the commoners fault, and very quickly
you learn to take responsibility for all errors, and assume there's a
rational reason for everything. FPGA development will make you believe
in God again, or a least the Devil, since a significant portion of the
time (5%+ in my case) I'll find an error in the synthesis or
simulation tools. Usually if it synthesis it's fine, I won't get an
erroneous result, it'll just bomb or not bomb, and it may not be your
fault! This is related to not being clever, hardware developers seem
to make bad beta testers or something.

I'll think of I can come up with more, bit that covers a bit of the
biggest time wasters. Sorry for misspellings, too, the device I'm on
lacks a spell checker - yeeesh.
 
J

Jonathan Ross

Now on better machine. In #6, "Perjuring" should read "permuting", #8
"commoners" should read "compilers."

I wanted to add a 9. Remember 5? Stick to synchronous logic as much as
possible, and save the combinatorial stuff for optimizations. When I
first started I was under the impression the time it took to travel
through a wire was trivial compared to logic expenses, but this is not
quite the case. Frequently you'll need to register your data.

10. Make sure you've correctly informed the tools of your timing
requirements. Don't assume anything. If you fail to correctly
constrain a clock in a multiclock design you may be under the
impression you're getting hardware errors because your logic was
wrong, when in fact it simply wasn't informing you that one of your
faster clock domains wasn't making timing (technically it was making
timing, just not the timing that relates to the clock you were passing
in).

11. Your main advantage over hardware developers is that you've seen
the higher level of abstraction and complexity possible in software
development than they're used to and will want to achieve the same
kind of designs in hardware. This is also your main disadvantage.
 
M

Mike Treseler

As I've mentioned in another post, I'm a longtime software guy with
decent hardware experience (I've designed much of the hardware I've
programmed), but I've only dipped into the FPGA/VHDL waters in the
past few weeks. (And I must say, I'm fascinated by it all!)


Longtime software guys sometimes like to use functions
instead of asynchronous processes and variables for registers.
This is how I do it:
http://mysite.ncnetwork.net/reszotzl/sync_template.vhd
http://mysite.ncnetwork.net/reszotzl/stack.vhd
http://mysite.ncnetwork.net/reszotzl/uart.vhd

Good luck.

-- Mike Treseler
 
J

jacko

Don't be afraid to apparently duplicate a lot of code. This refers to
say having 2 copies of a case statement with differing when clauses
based on some outer state of the machine being coded. It does not
consume many extra resources, and can lead to a better data flow.
 
P

Paul Uiterlinden

jacko said:
Don't be afraid to apparently duplicate a lot of code. This refers to
say having 2 copies of a case statement with differing when clauses
based on some outer state of the machine being coded. It does not
consume many extra resources, and can lead to a better data flow.

What do yo mean with "apparently duplicate a lot of code"? If it really
means copying and pasting a lot of code, I would object. It will result in
hard to mantain code. I thoroughly dislike copy-and-paste code.
 
J

jacko

What do yo mean with "apparently duplicate a lot of code"? If it really
means copying and pasting a lot of code, I would object. It will result in
hard to mantain code. I thoroughly dislike copy-and-paste code.

case A
when a => case B
when b => case B

In this example the case B structure is repeated/duplicated.

Although it may seem like a good idea to combine the case B into one
case and then test case A internally, often the process structure
suggest one way as better, case is better than if most of the time
because it will warn more than if. Real vs. apparent, copy case delete
assignments, put new in context assignments. best hardware performance
is often achieved with not with the most beautiful simple code, but
with the necessary code to dataflow the signals to pass through a
minimal of logic and placing all logic before the flip flop. Look up
'Moore State Machine' which is preferred to a Mealey machine in
synchronous design.

Cheers Jacko
 
M

Mike Treseler

case A
when a => case B
when b => case B

In this example the case B structure is repeated/duplicated.


I agree that duplicating a case expression is sometimes
easier to read than a long elsif.
Look up
'Moore State Machine' which is preferred to a Mealey machine in
synchronous design.

If you mean that a design with output registers
is usually preferred to one without, I agree.

Or if you mean that pipelining for timing closure
involves some trial and error, I agree.

-- Mike Treseler
 
M

Martin Thompson

Mike Treseler said:
I agree that duplicating a case expression is sometimes
easier to read than a long elsif.

But for ease of maintenance, I'd tend to move the duplicated content
to a subprogram and call it from both cases, rather than copy/paste.
Too easy to forget to update both sides when something changes.

Cheers,
Martin
 
M

Mike Treseler

But for ease of maintenance, I'd tend to move the duplicated content
to a subprogram and call it from both cases, rather than copy/paste.
Too easy to forget to update both sides when something changes.

Good point.

-- Mike Treseler
____________________________
case A_v is
when a => my_fn(B);
when b => my_fn(B);
when c => my_fn(Z);
end case;
 
J

jacko

I agree that duplicating a case expression is sometimes
easier to read than a long elsif.

Another example was duplicating a register for to separate uses of the
content. While increasing fan in, it can reduce fan out, which is
preferred for a low fan in signal set anyhow when it has a high fan
out. This fan balancing can be useful. Some tools can do this
balancing automatically, but sometimes the differing content of
register possibility can be used to good effect. Some tools
automatically throw logic to the other side of the flip flop to
balance logic complexity between flops.
If you mean that a design with output registers
is usually preferred to one without, I agree.

Yes, design with registered output. Registered input is also a good
idea... It does let full clock speed of device be used, but with
external memory say, it needs an extra clock state in the state
machine.
Or if you mean that pipelining for timing closure
involves some trial and error, I agree.

Yes this relates to the above, I had a case where some logic on the
inputs before the first register, and the delay cycle was not
acceptable, so the auto logic movement was used to good effect. In the
X3 I may explicitly do this adjustment by using a variable
combinational of register output instead of an if then selecting
register input. It's that annoying feeling of SRAM access delay PLUS
some logic delay, before the clock, and expressing this to the tool.
This is preferable to a 20% speed penalty as the critical path is
elsewhere. The splitting fan of the inputs, can cause a bit of a
headache as you decide on the fast input register meaning, as there is
likely to only be one per input....

Cheers Jacko

http://nibz.googlecode.com
 

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,989
Messages
2,570,207
Members
46,783
Latest member
RickeyDort

Latest Threads

Top