Written by Dan Kotylak and Adrian Chan
This term we had the opportunity to use VHDL as a tool in digital system design. Ideally, VHDL provides abstraction by isolating the behavioural description of a digital system from its hardware level implementation. Perhaps in the future this might improve, but have found that VHDL currently does not provide good abstraction. That is, you cannot successfully or efficiently design a digital system in VHDL without knowing the hardware implications of what you are describing. This is not a surprising statement considering that VHDL is a fully functioned language. There will always be some functionality in VHDL that has no hardware meaning (eg recursive functions, complex data structures, etc.).
The approach we took was to use VHDL as you would use schematic capture tools. This means planning out your design in terms of hardware blocks and describing them as a real peice of hardware would function. In our design this meant building our VHDL code in terms of registers, adders, flip-flops, etc. Designing with this method gives a higher probability of successful synthesis (as we all know, successful behavioural simulation does not mean that it will work).
However, even if you follow this design method, you can still end up writing un-synthesizable VHDL code. Synthesis is heavily dependant on the synthesis tools you are using. Support for VHDL functionality varies widely between vendors.
An example of this is our row scanner entity. This entity is used to scan the rows of a keypad for a key press. Asserting '0' on a row enables it; a key press on the row will cause a column to go low. Asserting a '1' disables the row and key presses will have no effect. Thus, we need the output of the scanner to be all '1's except for a single '0' which cycles through (similar to one-hot encoding)
-- row scanner library ieee; use ieee.std_logic_1164.all; -- entity declaration entity rowscan is port( clock,reset,enable : in std_logic; Q : inout std_logic_vector(3 downto 0) ); end rowscan; architecture bad of rowscan is begin scan : process(clock,reset) variable Qtemp : std_logic_vector(3 downto 0); begin if reset = '1' then Qtemp := "0111"; elsif falling_edge(clock) and (enable = '1') then if Qtemp = "0111" then Qtemp := "1011"; elsif Qtemp = "1011" then Qtemp := "1101"; elsif Q = "1101" then Qtemp := "1110"; elsif Qtemp = "1110" then Qtemp := "0111"; end if; end if; Q <= Qtemp; end process scan; end bad;
While this is implmentation of is not efficient (an extra variable is used to hold the value of the counter), it is perfectly valid and correct VHDL code. However, when we attempted to map it to Actel's technology by using Actmap to compile our code, the design did not work. Instead of cycling through the values 0111, 1011, 1101, 1110, the row scanner produced the values 0000, 0001, 0010, 0011.
By looking at Actmap's compilation output, we were able to determine that Actmap interpreted our code as a state machine. As a result, the complier optimized our "state encodings" The culprit turned out to be the temporary variable. Apparently, in Actmap VHDL, such a variable infers a state machine.
Here is an alternative solution. Without the extra variable, this VHDL code synthesizes correctly.
architecture good of rowscan is begin scan : process(clock,reset) begin if reset = '1' then Q <= "0111"; elsif falling_edge(clock) and (enable = '1') then if Q = "0111" then Q <= "1011"; elsif Q = "1011" then Q <= "1101"; elsif Q = "1101" then Q <= "1110"; elsif Q = "1110" then Q <= "0111"; end if; end if; end process scan; end good;
This is an inherent problem with using VHDL as a design tool; a VHDL design that maps correctly to one vendor's technology will not necessarily map to another vendor's product. While there are efforts to standardize VHDL synthesis (see VHDLSynth homepage for more info), this is something VHDL users will have to live with at the moment.
Despite its shortcomings, we have found VHDL to be a powerful tool in digital design. Changes are fairly easy to make. Also, simulation is simple and reproducible with the use of test benches. To effectively use VHDL, you need to know how to use it. From experience, the best approach seems to keep VHDL's limitations in mind from day one. There are several VHDL reference books that discuss synthesizable VHDL. Also, it is invaluable to read the vendor specific VHDL documentation. This generally tells you what features of VHDL that the vendor supports, and how it implements them. We have found that state machines are generally synthesizable. Also, many of the arithmethic operations are supported, although you may have to include vendor specific libraries (eg Actel substitues ieee.std_logic_arith with its own).