Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Advanced VHDL book recommendation

Status
Not open for further replies.

revkarol

Newbie level 1
Joined
Jul 11, 2019
Messages
1
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
29
Hi,

I'm looking for an advanced book on VHDL. I know the basics (async vs synchronous, signals, loop, generate, metastability, timing etc). I'm looking for something to help me improve my coding style - a list of good examples, pitfalls to avoid. Often, I'm writing something and I feel it's just clunky and there's a more elegant solution. I guess the C++ equivalent would be "Effective C++" by Scott Meyers, where he goes through a bunch of examples. Of course, it could be an online resource rather than a book if such a thing exists.

Advance thanks for any suggestions,
Karol.
 

the single most important thing you can do to improve your coding is to document it well
use comments liberally to describe the function, inputs and outputs of all modules, functions, and subroutines at the beginning of the module, function, or subroutine
use variable names that have meaning
bypass fancy and cute for clarity

for the question of how much documentation is enough -
do you want to write 10,000 lines of spaghetti logic (the Dilbert holy grail of programming) and never work on a new project,
or do you want to move on to a new project?

better coding is the same in every language - only the grammar and syntax change
so examine that book on C++ you mentioned and adopt the better practices it describes into VHDL
 

For a start, get a good reference guide. The Doulos ones are the ones Ive always used:
**broken link removed**

As for text books, Ive never used them but always seemed to be people's favorites:
https://www.amazon.co.uk/Designers-Guide-VHDL-Systems-Silicon/dp/0120887851

One point to note though is that a lot of guides/books are quite a few years old now. The styles in them may well be fine but most synth tools now work well with VHDL 2008 and can be very forgiving with infering elements (like ram) from code compared to the time the guides were written. Its always worth checking out the coding guidelines of the main vendors:
Xilinx: Xilinx Synthesis User Guide (UG901)
Intel: VHDL Coding Guidelines

Even these can be a rather basic version of what will actually work.

The main point to remember is to write code that another engineer will understand. Comments should be about "why" you're doing something - the "how" should be reasonably obvious from the code.
 

I don't think there are any really good coding style guides. The languages are overly sim based to the point the coding for synthesis is dangerously affected. Guides are often based on capricious tool quirks.

But you can get random wisdom. For myself, I prefer well-defined interfaces over ad-hoc interfaces. Exactly-aligned pipelines over ad-hoc pipelines. This makes it easier to understand modules in isolation and minimize issues with module interactions. But this can lead to less optimized designs.

Otherwise, don't write "overly-creative" code without comments. Retain whatever aesthetic style an existing file uses. etc...

also, make sandbox deisgns. sometimes the tools allow useful language features. knowing the tools is an advantage overall.
 

The main point to remember is to write code that another engineer will understand. Comments should be about "why" you're doing something - the "how" should be reasonably obvious from the code.

I find this to be one of the most important things to keep in mind.

I regularly see code written by senior people that have a counter with a comment similar to:
-- 32-bit counter that rolls over at the TERMINAL_COUNT value
and the counter is named cntr_reg or something equally vague.

Uh, okay, counting to a terminal count is apparent looking at the code...what is this counter for? After searching through the code you find out it's used as an index/timer/divider/etc.. Whatever it was used for should have been described in the comment not by searching through the rest of the code to see where that cntr_reg was used.

- - - Updated - - -

Otherwise, don't write "overly-creative" code without comments. Retain whatever aesthetic style an existing file uses. etc...
The overly-creative code is IMO some of the worst coding I've run across, namely because nobody bothers to explain why or what they are trying to do, which usually involves taking advantage of some tool or language quirk. If you do something like that then document it with detailed comments about how this works with XYZ tool and what is the expected result.

Occasionally these kinds of things can bite you in the rear when the language is changed or the tool changes to a new version which modifies the behavior of the "quirk".

I would say straight forward code is the best code, with no tricks being played to "optimize" the design. If nothing else it is understandable to the widest audience and is the most maintainable.
 

All designers will probably not agree with me, but avoid books (or at least the chapter) that discuss Moore and Mealy state machines and tell you to write them with two processes, one clocked and one asynchronous.
With FPGA's you normally get the registers "for free", and the Moore and Mealy stuff were invented to minimize the number of registers.
If you don't have a very good reason, make all outputs from your state machines registered, and write them as one clocked process.
Avoid variables, especially the ones with a "memory" from the previous clock cycle, until you really understand what they synthesize to.
 

I like a compromise style where the fsm state transition logic is written as two process and outputs (and usually counters) are written as one clocked process. Having next_state is almost always worth the ~5 lines needed to get it.
 

If you want to learn VHDL then read something written by Peter Ashenden or a book named as such online.

If you want to write good structured code then read the following
https://gaisler.com/doc/vhdl2proc.pdf

If you want to know whats possible then look at the vhdl standard and play around. Normally this requires access to ieee, which requires an account.
 

If you want to write good structured code then read the following
https://gaisler.com/doc/vhdl2proc.pdf

I get to page three, and see this:

Code:
use ieee.std_logic_arith.all;

Then section 5.7 and see this:

Code:
cpu0 : cpu_sparc port map (rst, clk, ici, ico, dci, dco, fpui, fpuo);
fpu0 : fpu_core port map (clk, fpui, fpuo);
cache0 : cache port map (rst, clk, ici, ico, dci, dco, ahbi, ahbo, ahbsi, crami, cramo);
cmem0 : cachemem port map (clk, crami, cramo);


It instantly goes down in my estimation. Two styles that are generally recommended to avoid - non-standard libraries and positional association.
As for the overall style - I can see what he's trying to do - but big use of variables can add an extra layer of complexity to debugging.
I cant see a date for this paper. Given one of the goals is simulation speed then I suggest it's quite old.
I say there is no one "good" style, other than one others can easily understand. If a style is hardly used - I would suggest it is not "good" (at least, it's not "good" from an employability pov).
 

I cant see a date for this paper.

IIRC, it was from 1999. The style that it was trying to replace was the style where every signal is in its own process. Some of the arguments make way more sense if you compare them against common standards from 20 years ago.
 

IIRC, it was from 1999. The style that it was trying to replace was the style where every signal is in its own process. Some of the arguments make way more sense if you compare them against common standards from 20 years ago.

Well that makes more sense. Ive always understood that old synthesisors (in the 90s) couldnt deal with combinatorial and sync logic in the same process, hence the need for two processes for everything. Thankfully those days are long gone - Ive been mixing it all up for 15 years (since I started)
 


The article recommends the one-process state machine coding style, and I agree with it.

That is a good example of why one-process is dangerous. There is a comment "output is a function of the current state only". This is wrong -- there is an extra register stage. Is this an error? probably not. but there is a delay for no reason and the author doesn't seem to notice.
 

That is a good example of why one-process is dangerous. There is a comment "output is a function of the current state only". This is wrong -- there is an extra register stage. Is this an error? probably not. but there is a delay for no reason and the author doesn't seem to notice.

I would never count 1 process as "dangerous". Just needs a bit more thought if you want outputs based on current state - namely - another process/inline code that creates an output based on the current state.
I would argue that registering everything by default and explaining any exceptions would be preferable to having everything combinatorial and added registers later.
Registers are cheap and plentiful, latches are annoying and painful.
 
  • Like
Reactions: FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating
I agree that logic should be registered where possible and latches should be avoided. That is a different argument.
 

I agree that logic should be registered where possible and latches should be avoided. That is a different argument.

Are you decoding "next_state" in the clocked process to decide what should be assigned to the outputs?
Then I understand how you can create registered outputs without the delay you criticize in post #14.

I agree with the text in the article, but I think the code is a bad example.
The outputs can be assigned when the state changes, instead of inside the state.
Without changing the basic code structure in the article, I would probably do something like this:

Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
process(clk, reset)
begin
  if reset = '1' then
    current_state <= idle;
    op <= '0';
  elsif rising_edge(clk) then
    case current_state is
      when idle =>
        if start = '1' then
          op <= '1';
          current_state <= led_on;
        end if;
      when led_on =>
        if toggle = '1' then
          op <= '0';
          current_state <= led_off;
        end if;
      when led_off =>
        if toggle = '1' then
          op <= '1';
          current_state <= led_on;
        end if;
      when others =>
        op <= '0';
        current_state <= idle;
    end case;
  end if;
end process;

 

Having next_state does allow the register to be cleanly defined.

Your changes to the code sample do work. In some styles it can be confusing/annoying/verbose. The logic for a signal that matters in state X is written in state Y because Y has a transition to X. The code is also duplicated on multiple lines if there are multiple transitions to some state. This increases the chance that one will be missed by an update from a future maintainer. It also makes the one-process fsm more verbose, which was it's main benefit over a two-process fsm (not the straw-man two-process fsm that is latch-prone and verbose).
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top