VHDL with gschem and gnetlist
Design a FPGA using open source
Click on the links to toggle the visability of the item.
- Introduction
VHDL or Verilog is a great way to design the internals of a FPGA or CLPD. You can use all your software skills to design hardware.
But there is a gotcha. The end result is not a software program but hardware. Although obvious it's often overlooked once the project is getting shape.
As with many good design work-flows there should be some VHDL coding guidelines to ensure a good working end result.
Here I will present you two VHDL coding guidelines that should be in every list:
- Design your architecture
- If you can't draw it you can't code it
Especially the last one is often #forgotten".
Using the vendor independent gEDA's gschem we can follow these coding guidelines perfectly.
Whether you design top-down or bottom-up you can use gEDA to keep your architecture consisted.
This tutorial uses the bottom-up approach, mainly because it will give us intermediate results we can check and verify.
Enjoy!
- First things first (setup)
We need to set-up some essential parameters.
Frst we create a new working directorycd /pathtowork
Add a text file gafrc into that directory.
mkdir work
cd work
Open the file gafrc and add:(source-library "/pathtowork/work")
In my installation the /pathtoVHDLlibrary is /usr/share/gEDA/sym/vhdl. Your system may be different.
(component-library "/pathtowork/work")
(component-library "/pathtoVHDLlibrary")
Thats all the setup needed. - Do not get confused
We will be using some symbols from the VHDL library of the gEDA 1.8.1 release. Some symbols have visual aspects that might confuse you.
For example:
the ipad-1.sym symbol has all the necessary attributes correctly defined, however it has also an unused attribute (pintype=OUT) with its visibility turned on. And this unused attribute will show-up in your schematics making you think it's an output pin instead of an input pin which it is.
How to fix this
Goto the directory where your VHDL library is located.
Open the file "ipad-1.sym" with gschem. Double click on "OUT" and deselect the visible option.
Save the file. Make sure you have write permission to the VHDL library location.
In my installation the VHDL library is located at /usr/share/gEDA/sym/vhdl your system may be different.
End of the fix. Lets continue!
- First schematic
In the directory /pathtowork/work create a file vlinder.sch.
Open vlinder.sch with gschem.
Now we can start adding components from the VHDL library.
Give each component a unique refdes.
Now for the connection to the outside world.
We need to add IO pins to our design in order to get these pins in the ENTITY section of our VHDL file.
The gnetlist VHDL back-end must be able to distinguish between pins used for interconnection within the schematics and a connection which will end-up in the ENTITY declaration of the VHDL file.
So for the top level exit or entry points in your schematic you need to use the ipad-1.sym, opad-1.sym or iopad-1.sym symbols.
More details
Actually the gnetlist VHDL back-end will look at any symbol that has the device=OPAD, device=IPAD or device=IOPAD attributes and treat them as top level exit or entry points.
Add the ipad and opad symbols.
I have used Ai, Bi and Qo as refdes for the PAD symbols.
Using number is optional as long as the refdes is unique.
I have also given some nets a netname.
Next we need to add an attribute module-name to the schematic to define the architecture (don't confuse module-name with model-name that's something different!).
Make sure you have nothing selected, then type A A or goto Add->Attribute in the menu.
For name type module-name
As value type the name to define the architecture.
Now we are ready to generate some VHDL code.
On the command line type:cd /pathtowork/work
Ready!
gnetlist -g vhdl -o vlinder.vhdl vlinder.sch
Check the VHDL code to see where all the attributes end-up - Make a symbol from the first schematic
In the directory /pathtowork/work create a file vlindersym.sym.
Open vlindersym.sym with gschem.
Add 3 pins to represent the three ports in the vlinder design.
Make sure you use correct pintypes (IN, OUT or INOUT).
The value you use for pinnumber will show-up in the COMPONENT declaration in the VHDL file.
The value used for the pinnumbers MUST be the same as the refdes of the IO pads (ipad, opad, iopad) used in vlinder.sch schematic!
The pinlabel must be the same as the pinnumber if you want to use the last trick mentioned in this tutorial.
Next add a refdes attribute, make sure you have nothing selected, then type A A or goto Add->Attribute in the menu.
Next add a device attribute, make sure you have nothing selected, then type A A or goto Add->Attribute in the menu.
The device attribute must be the same as the module-name used in the schematic.
Now you should have:
Finally you can add some decoration.
Last but not least. Do a symbol translate to realign the symbol correctly.
Make sure you have nothing selected and grid is set to 100, then type E T or goto Edit->Symbol Translate... in the menu.
Make sure it says 0 and press enter or click on OK.
Save the new symbol. - Second schematic
Steps in this section are more or less a repetition of the steps we took in creating our first schematic, so I will move a little faster.
In the directory /pathtowork/work create a new file bloem.sch. Open bloem.sch with gschem.
Add the necessary items as explained above.
Next we can add our vlindersym symbol. (Can't find the vlindersym.sym symbol?)
Did you save the vlindersym.sym file in your work directory?
If you can't find the vlindersym.sym symbol in your work library, you need to save bloem.sch and close gschem. Than open the gafrc file in your /pathtowork/work directory and add:(source-library "/pathtowork/work")
If you didn't do so already.
Save and close the rafrc file.
Reopen bloem.sch and try again.
Don't forget to add the module-name attribute!
Now we are ready to generate the second VHDL code.
On the command line type:gnetlist -g vhdl -o bloem.vhdl bloem.sch
- Supporting file
Now we should have 2 VHDL files (bloem.vhdl and vlinder.vhdl). Together these files will make the skeleton of our VHDL project.
To make it do anything we need 1 more file. That file must contain the entity for nand2
The device attribute in nand2-1.sym is set to nand2 (device=nand2) we must match that name exactly.
So we create a new file named zon.vhdl and insert:-- Context clause
Ready!
library IEEE;
use IEEE.Std_Logic_1164.all;
-- Entity declaration
ENTITY nand2 IS
PORT (
IN1 : in Std_Logic;
IN0 : in Std_Logic;
OUT0 : out Std_Logic);
END nand2;
-- Secondary unit
ARCHITECTURE nand2_arch OF nand2 IS
BEGIN
-- Signal assignment part
OUT0 <= IN1 NAND IN0;
END nand2_arch; - Check
Let's check if all works as expected. For this I use GHDL. If anyone can suggest alternatives, I will append them here.
First we analyse the files we created:ghdl -a bloem.vdhl vlinder.vhdl zon.vhdl
Next we can create an executable:ghdl -e bloem_entity
It should compile without errors.
You can run the bloem_entity executable but it will not do anything. - Last trick to explain
There is one more trick to explain. Until now we have three files each generated individually by gnetlist.
Personally that is my favourite way to implement VHDL code. Each sheet or schematic has it's own corresponding VHDL file.
However you can eliminate one step from the process.
First delete bloem.vhdl and vlinder.vhdl from your work directory.
Next open bloem.sch and select the vlindersym symbol.
Double click on the vlindersym symbol (BLOCK1).
In the attribute menu add a new attribute source=vlinder.sch
Save bloem.sch.
On the command line type:gnetlist -g vhdl -o bloem.vhdl bloem.sch
Now gnetlist has put everything in one VHDL file (except the nand2.vhdl deceleration).
Check your VHDL file to see the difference. - Check
Let's check if all works as expected.
First we analyse the files we created in step 7:ghdl -a bloem.vdhl zon.vhdl
Unfortunately we get an error.bloem.vhdl:26:18: ',' or ':' is expected after identifier in signal declaration
Looking at line 26 column 18 we see that gnetlist has used a / as a separator character when it uses the refdes of the vlindersym symbol as a prefix of the signals used in the vlinder.sch schematic.
ghdl: compilation error
In order to fix that we need to reconfigure gnetlist.
Add a text file gnetlistrc into your work directory.
Open the file gnetlistrc and add:(hierarchy-uref-separator "_")
More on how to configure gnetlist
(hierarchy-netname-separator "_")
Generate bloem.vhdl againgnetlist -g vhdl -o bloem.vhdl bloem.sch
Analyse againghdl -a bloem.vdhl zon.vhdl
No errors? Now we can create an executable:ghdl -e bloem_entity
It should compile without errors. - What's next
Next step is to create a test bench to get an actual output. But I will leave that to you.
Version used in this tutorial: gEDA 1.8.1
Comments are welcome.