VHDL coding
VHDL Training
On-line courses
-
Doulos VHDL Pacemaker- Unfortunately gone (08/2021)
Books
- VHDL for logic synthesis, Rushton (CERN Library, older edition)
- Formal Verification: An Essential Toolkit for Modern VLSI Design, Oreilly
- https://www.oreilly.com/library/view/formal-verification/9780128008157/
-
e-book for CERN only
Soon also a paper copy will be available in the CERN library (24/08/2021)
VHDL Coding Guidelines
OHWR Guidelines for VHDL coding
-
VHDL Coding Style
project on ohwr
- VHDL Coding Style guide
- VHDL Coding Style checker program
Many projects on OHWR use the Guidelines for VHDL Coding. Using similar coding styles will ease re-useability. It may be somewhat outdated.
-
- from the White Rabbit core collection project gives some exceptions and hints to make the above Guidelines for VHDL coding better usable for large complex modules.
Other
- OpenCores HDL modeling guidelines
- Design and Coding Style Guidelines for Synthesizable VHDL-FPGA Code (from C7T)
VHDL Review Checklist
Before the review of your project/module, check whether it follows the these simple tips/guidelines (these are the usual remarks that you would receive from reviewers)
- Use registers in IOB for in/out to get well-defined timing, independent of routing
- Check crossings of clock domains, use synchronizer stages when needed (e.g. gc_sync_ffs in modules/common of general-cores)
- Before using an asynchronous input signal (e.g. from DIO) in your synchronous design, first synchronise it with your clock domain and then deglitch the signal, preferably use gc_async_signals_input_stage in modules/common of general-cores
- Make sure that a synchronised signal is used only in processes that use the same clock as the one the signal is synchronised to.
- Use only real clocks as clocks for registers. Do not use a combinatorial or generated signal as a clock for a register
- Replace deep if-then statements by state machine
- Initialize in reset all signals for which you assign value in a process
- State machine recover from illegal states, i.e. always define the "others" state, preferably to go to IDLE state of your state machine, if happens.
- Follow the naming convention from the
guidelines, at minimum check
that
- the names of inputs/output signals of your module(s) finish with "_i"/"_o", bidirectional with "_b", asynchronous signals have "a" before "_i"/"_o"/"_b", and pulses have "pX" in their names (where X is the width of the pulse, e.g. single-cycle pulse should have _p1 in its name)
- the names of the signals inside your module(s) do not finish with "_i"/"_o"/"b" and do not begin with "s" (the optional naming convention from the guidelines that is not recommended)
- the names of clock signals, whenever it is known/fixed, indicate the frequency, e.g..: clk_125m_pllref, clk_80m_ADC, clk_20m_vcxo_i
- Make sure that only needed signals are in sensitivity list of a process (e.g. if you use process with synchronous reset, make sure reset is not in sensitivity list)
- Do not use "new" and "old" in the names (the new will become old very fast and the name will mean nothing)
- Check whether any module or function that you need in your design
and that is not specific to your project (say, it deals with
Endianness or calculates a CRC) exists already in
general-cores,
wr-cores, or opencores.org:
- if it does not exist, consider adding it there
- if it does exist already, consider reusing and extending/fixing if needed
- If your code is auto-generated (e.g. by wbgen2) do not modify it, unless you are really sure what you do (usually you need to do the modification because you don't know)
- If your code is auto-generated (e.g. by wbgen2) add a readme with how the commands for the auto-generation are invoked.
- State copyright and license in all files, see example
- Follow good practices when using git, in specific for HDL designs:
- git-ignore synthesis-generated and simulation-generated files
- don't commit the "*.xise" in syn/ folder unless it's in a release commit
- Remove unused signals/variables/inputs/outputs from the code
- Remove unused/ duplicated files from the .xise project.
- High-level files should highlight high-level structure and not include low-level processes/ modules.
- Avoid ambiguous code, e.g:
- Set a signal, use value on line afterwards (takes 'previous' value). Behavior would be different if it was a variable
- Provide minimum description in the header of each file, see example
- Follow, as closely as possible, the suggested file structure
Examples of VHDL design reviews
- VHDL design review of nanoFIP
Wishbone bus
Many Open designs use the Wishbone specification. You may want to generate the Wishbone slaves to be specified and automatically generated by the Wishbone Generator wbgen [2].
Usage of registers
The following are some hints that I received when I was a young fellow designing some interface and spoke with a clever guy with login 'tbl' who gave me some useful hints to make hardware that is easy to program. Although those ideas are from the same time the web was being invented at CERN, I think they are still valid and useful.
Control registers
- Make control registers all write-read. That way you can easily set a single bit if needed without needing a copy of the data. Also easy to check if everything works as you expect.
- Default value (everything working as normal) should be 0. Anything 'special' set should be written as a 1.
- Unused bits: define as: "reserved, write as 0.". This allows future upgrades of hardware that still will work with old software that doesn't know about added or hidden possibilities.
Status registers
- Default value (everything normal) should be 0. So you can easily see if a bit is set.
- Unused bits: define as: "reserved, ignore on read". This allows future upgrades of hardware that still will work with old software that doesn't know about added or hidden possibilities.
- Interrupt status register (showing the cause of an interrupt): actually the same as rule 1. But make the most significant bit an OR of all the other bits, likely combined with an interrupt mask register. With a single assembly instruction (check if negative) you can see if any of the bits is set. This would make software go faster if it has to scan many devices to check who has interrupted.
General
- Make that everything goes fast when things are OK (e.g with hint 6). To find out what was the cause of an error condition may take much more time.
- If possible, make that your hardware can continue without an interrupt being handled. E.g. one can have a counter that would show how many interrupts it would have given when continued (e.g. number of packets sent, so the software can just check off many items in a list in one interrupt service routine).
Erik van der Bij, Maciej Lipinski - 24 August 2021