Restrictions on VHDL subset
The VHDL subset, which Velab employs, is based on VHDL'93. This allows attributes to be
placed inside generate and block statements, as well as inside the entity declarations and
architecture declarative parts, alleviating problems we have had with workarounds for
Synopsys which uses VHDL'87.
Examples are to be found in the directory /examples.
In general, only entities, architectures, configurations, packages, signals,
components, labels and attributes are allowed. Procedures, functions, types, subtypes,
files, groups, units, variables and literals are precluded.
Behavioral VHDL
The VHDL subset precludes any of the behavioral statements, but this is not a problem
if you only want to describe hierarchical structures based on primitive gates. Synthesis,
in the true sense of the word, must be done using some other VHDL tool, such as Synopsys
or Metamor, and the structural VHDL produced can then be incorporated in the design using Velab.
Procedures and functions
VHDL procedures and functions are not allowed, since this would necessitate a much more
complex tool, which we really don't want.
However, from release 0.52, function calls may be included in the VHDL. The
mechanism for the use of functions is as follows:
1) Decide on the name of the function and declare this in the VHDL in a comment
thus:
-- FN : <function_name>
Any number of functions may be declared in this way. The function will be
visible according to the scoping rules on the VHDL file in which it is declared.
The "FN" is case-insensitive, but the function name will ALWAYS be made lower-case.
2) Write the function executable. This entails writing some code in C/C++ or
whatever language is desired, which processes integer arguments from the
command line and prints an integer result.
For example, the following code implements a function which adds the first two
input arguments:
#include <stdio.h>
#include <stdlib.h>
main(int argc, char *argv[])
{
printf("%d", atoi(argv[1])+atoi(argv[2]));
}
3) Compile this code to produce an executable with the correct function name,
remembering that the executable name MUST be in lower-case.
For example, given that the code above is in file sum2.c, and the desired
function name is "sum2", the following (Unix) command line compiles it
correctly:
gcc -o sum2 sum2.c
4) Now make sure that this executable is visible on the PATH, from wherever
Velab will be run.
5) It is then possible to include calls to this function from within the
VHDL code. For example, the following instanciation statement will result in a
5-bit adder being generated:
inst1 : adder generic map(n_bits => sum2(2,3))
port map(a=>a,
b=>b,
cout=>cout);
It is possible to nest these function calls and to mix function calls with VHDL
expressions. It is also possible to pass generic and generate loop variables to
the function call. For example, the following code results in 4, 8-bit adders
being generated:
-- z is a generic variable in scope, which is = 4
loop1 : for i in 0 to 3 generate
inst_i : adder generic map(n_bits => sum2(4,z))
port map(a=>a(((i+1)*sum2(4,z))-1 downto (i*sum2(4,z))),
b=>b(((i+1)*sum2(4,z))-1 downto (i*sum2(4,z))),
cout=>cout(i));
end generate;
and the following code results in 4 adders with widths 4, 6, 8 and 10 bits:
-- z = 4, again
loop1 : for i in 0 to 3 generate
inst_i : adder generic map(n_bits => sum2(sum2(i,i),z))
port map(a=>a(((i+1)*sum2(6,z))-1 downto (i*sum2(6,z))),
b=>b(((i+1)*sum2(6,z))-1 downto (i*sum2(6,z))),
cout=>cout(i));
end generate;
Where to use function calls
Function calls may be included in attribute value string expressions, generic
default settings, generic maps and in signal selection expressions in port maps.
Where very complex attribute value string expressions are required, the
following construct can be useful:
attribute blah of blob : label is "X" & integer'image(fn1(a, b, c)) & "Y" &
integer'image(fn2(d, e, f));
Restrictions on function calls
Arguments MUST be integers, generic or generate loop variables, or legal VHDL
expressions of those.
Only a single integer may be returned by a function call.
Further example
The following code can be compiled and used to read FIR filter coefficients from
a file. The function call from VHDL could be "getcoeff(<n>)", where <n> denotes
the coefficient number to read in.
#include
#include
#define coeffs_file "fir_coeffs.txt"
main(int argc, char* argv[])
{
FILE* cfile;
int count = 0;
int coeff_no = atoi(argv[1]);
int coeff_val = 0;
if(!(cfile=fopen(coeffs_file, "r")))
{
printf("Can't open coefficients file %s - Exiting!\n\n",coeffs_file);
exit(0);
}
while(count++ <= coeff_no)
fscanf(cfile, "%d", &coeff_val);
/* Output the coefficient value */
printf("%d", coeff_val);
}
Packages
Only package headers are allowed. No package bodies. Within the header, only component,
attribute and signal declarations, and attribute specifications are allowed.
The following are precluded from package headers:
- use_clause
- subprogram_declaration
- constant_declaration
- type_declaration
- subtype_declaration
- shared_variable_declaration
- alias_declaration disconnection_specification
- file_declaration
- group_template_declaration
- group_declaration
Entities
Only generic, port, attribute specifications and signal declarations are allowed in an
entity declaration.
The following are precluded:
- attribute_declaration
- subprogram_declaration
- subprogram_body
- type_declaration
- subtype_declaration
- constant_declaration shared_variable_declaration
- file_declaration
- alias_declaration
- disconnection_specification
- use_clause
- group_template_declaration
- group_declaration
Configurations
Only block configurations are allowed in a configuration declaration statement.
Configuration declarative items, such as attribute specifications, use clauses and group
declarations, are not allowed. Also, use clauses are not allowed in
a block configuration. Within a block configuration, only "USE ENTITY ..." is
allowed - not "USE CONFIGURATION" or "USE OPEN".
Configuration specifications, which go in the VHDL code beside the component
declarations, are not allowed.
Some of the warning messages produced by Velab are due to configurations:
Velab Warning : No configuration for top level entity found. Relying on
defaults
is caused by not having the top-level configuration named "toplevel".
IMPORTANT!
The configuration declaration for the top level entity MUST be named "toplevel".
The message:
Velab Warning : No architecture was selected by toplevel configuration for entity
'ent'...(line_no)
is caused by not having a "for arch_name...end for;"
directly inside the toplevel config.
The message:
Velab Warning : No elaboration template specified for instanciation 'inst_name'
using default
is caused by not having the lines:
for inst_name : comp_name use entity lib.ent;
end for;
Here are a few possible, valid config lines:
configuration toplevel of ent is
for struct
for AUnit : comp_name use entity work.comp_name(struct);
end for;
for others : comp_name use entity other_lib.other_comp(some_arch);
end for;
for all : blob generic map(smeee => smooo)
port map(bleee => blooo);
end for;
end for;
end configuration toplevel;
Nesting of this type of statement is allowed.
Data types
The only data types allowed are INTEGERs (for example in generic statements) and
bit(_vector) and std_logic(_vector) signal types. In fact, these are built into Velab, so
you do not need the usual...
library IEEE;
use IEEE.std_logic.all;
lines in your code. For compatibility reasons these lines may appear in your VHDL, but
will be ignored by Velab.
CONSTANTS are not (yet) allowed, and neither are TYPE definitions. So if you want a
multi-dimensional signal, you'll need to re-specify it as a vector, and split it up
using indexing in the VHDL code.
Also, the working library is by default always included for each entity and
architecture. If an architecture is defined in a file in a different directory to its
corresponding entity, then a library and use clause should be given explicitly.
Signal assignments, such as "a <= b", where a
is a vector and b a single wire, are not legal. Nor is "a(0 to
5) <= b". To assign a single signal to all bits of a vector, use a generate
loop.
The main thing to remember is that the two sides of such an assignment must have the
same width. Attributes for the supported data types, such as integer'range(), are not
allowed. Neither are qualified expressions such as type marks.
Aggregates to initialize arrays are not allowed (since arrays are also banned).
Libraries
Finally, it is NOT necessary to include the library and
use clauses for the 6200-specific attributes, since these are also built into Velab.
Portability of VHDL
For code-migration reasons, there are two special comments that
may be added to VHDL code: "-- voff" and "-- von". When the parser
sees a "-- voff" comment, parsing is suspended until a "-- von"
comment is found. This allows existing code that contains behavioral code, perhaps, to be
run through Velab as well as some other VHDL tools, without needing to change the code in
between.
Bug reporting
If you come across a problem with the code, then you can email me at gooby@xilinx.com for help. No support is actually
promised, but will be provided as I see fit.
Known bugs: Attributes which reference non-existant objects are silently ignored.
Changes and Improvements History
Changes v0.41->v0.5 :
The library "work" in the velab.ini file now denotes the location of VHDL
source files, and a second, standard line "files_out : <path>" can be
added to the .ini file to specify the location of VHDL and EDIF output files.
Improvements v0.41->v0.5 :
Many more bugs have been fixed. These include further problems with the order of
printing the EDIF cells, the stripping of signals in VHDL output, incorrect handling of
negative generic values, incorrect library/use behavior and various less obvious bugs.
There are also enhancements with this release: Attribute value strings can now be built
up in legal VHDL'93-style, using the '&' and integer'image()
constructs. For example, the string "X,i+3,Y,9-j," is equivalent to
"X" & integer'image(i+3) & "Y" & integer'image(9-j).
Further enhancements include a much less verbose text output (the
verbose output is available using command-line option "-i"). Finally, it is now
possible to rename the top-level design in VHDL output. Using the command-line options -v
-n <newname>, a VHDL file named <newname>.vhd will be written, with the
top-level entity appropriately named.
Acknowledgements
The author of this file, Douglas Grant, would like to thank Adam Donlin of the
University of Glasgow, and Behzad Safari Astari, formerly of Marie Curie in Paris, for
their coding efforts on this project. |