Numbers in VHDL

A couple of times recently, I’ve found myself staring at VHDL code that starts thus:

library ieee;
use ieee.std_logic_arith.all;

and had to explain to the author that this is wrong. Yes, using an IEEE-library is wrong… how can this be?

When VHDL started out, its main logic type when used for creating chips was the “std_logic_vector” – a bag of bits with no intrinsic meaning numerically. There’s the integer types if you want numbers, but that was a bit iffy and inefficient with early synthesis tools. So Synopsys (big vendor of ASIC design tools) in their infinite wisdom came up with an extension library which they called std_logic_arith (and its compatriots std_logic_unsigned and std_logic_signed) which created some variations on the “bag-of-bits” theme which actually had numeric meaning.

This was popular – you could define how big your numbers were going to be by the size of the vector holding them, and you knew they would “wrap-around” like real hardware. VHDL’s integer types flagged errors in the simulation if they went out of range. In addition (sorry :), the synthesisers of the time tended to produce inefficient integers (always 32 bits), unless you constrained the range on them — that seemed unpopular with some. With Synopsys’ libraries, you could write code like this:

some_logic_vector <= some_logic_vector + 1; 

and have it increment your bag-of-bits by 1. Now, VHDL is a strongly typed language — this adding of an integer to a vector is just contrary to the whole design of the langauge. It makes it like Verilog (a popular alternative to VHDL). Briefly, Verilog is to C as VHDL is to Pascal or ADA.

  • Verilog: Give the programmer/hardware designer some sharp tools and let them get on with it
  • VHDL: give the programmer/designer some sharp tools and safety gear

Now, some think the safety gear gets in the way, but I quite like the fact that once my code has compiled, any errors are likely my own design errors, rather than wacky unexpected things the tool does…

Anyway, this would all have been fine if Synopsys had compiled their libraries by default into a synopsys library. But they didn’t – they put it into the IEEE library! So it gained false credibility, as well as being useful.

So when the IEEE come along with a proper standard library – numeric_std – it’s in direct “competition” (for want of a better word). So we had a generation of designers brought up on std_logic_arith. And they wrote some textbooks and example code. And the universities taught it. And other tool vendors (esp. the FPGA vendors, who have a large student audience) used it in their examples.

So now we have a third or fourth generation set of designers who are still using outdated, and non-standard libraries, in the mistaken belief that they are a standard. The company I work for was once bitten by this (fortunately at the FPGA prototyping stage, not in an ASIC). The behaviour of the simulator’s std_logic_arith library was different to the synthesiser’s when comparing vectors of different lengths! That was ten+ years ago, and I haven’t touched the Synopsys libraries since (and I wasn’t even working on that chip!)

The alternative is to use the standardised ieee.numeric_std library. It works the same in every package! The only downside is that you can’t “add 1 to your bag-of-bits”. But if they were going to represent a number, why not use the correct type (either signed or unsigned)? Or use an integer type – they simulate faster and tell you if they overflow (overflows are often a bad thing)! Once you’ve made the commitment to only using which std_logic_vectors when the bits truly have no numerical meaning and using unsigned or signed explicitly, there’s no penalty. Because you can add 1 to an (un)signed vector, and you can do all the other expected numerical operations. And they wrap around like “real hardware” if that’s the behaviour you want. So there it is — there’s no reason to use std_logic_arith — use numeric_std!


  1. Thanks! When I write
    some_logic_vector <= some_logic_vector + 1;
    I always fear the signed, usigned and overflows. Now I will not use signed and unsigned explicitly and use numeric_std!

Leave a comment

Your email address will not be published. Required fields are marked *