In this post I want to discuss an interesting naming convention that can be used to manage multiple firmware architectures. I will start off with a description of where the convention came from and how it works. After this I will show how Scineric Workspace can manage the process for you if you decide to use this approach.
What’s in a name?
(This section was contributed by one of my colleagues, Peter Lydall, who originally came up with the convention).
It was several years back and our VHDL team were faced with an interesting problem. We had been making use of the Mentor Graphics’ HDL Designer Series software tools to help us streamline and manage our code development. For the most part it really was a very effective tool. Where we came a bit unstuck though was in managing designs where multiple architectures were needed for an entity.
The reason one might want to have multiple architectures associated with an entity could be many, but in our case we found it a useful mechanism for handling hardware cores (eg FPGA block RAMs, PLLs etc), specifically where an instantiated core within a design contained a non-synthesisable simulation model, or in the very least a simulation code that differed from synthesis code.
In this case we would have two architectures: One for the synthesis code and one for simulation code. Depending on whether we were generating our VHDL for simulation or synthesis, we could simply select which architecture to use with the HDL Designer UI, and our design hierarchy would remain unchanged.
Incidentally this concept of having multiple architectures also proved very effective in creating device independent VHDL code. By isolating the device specific features into their own entities we could migrate from one device to another – either a different family of FPGA, or even from a different vendor (eg Altera to Xilinx) – by simply creating new cores and placing them in architectures associated with the existing entities. In so doing, our design hierarchy and all the VHDL we had written could remain completely unchanged, and could be used for either FPGA family simply by changing the default view of the affected blocks in HDL Designer’s UI. This is shown in the image below where the active architecture is currently set to simulation (SIM).
The issue was, however, that as designs became more complex, with more cores, it became a big hassle to manage the process of switching the default view for each block in HDL Designer, particularly during design testing when we would alternate between running simulations and then testing our code on the FPGA. Typically we would miss a block and the problem would only become apparent half an hour later (or more) when synthesis or translate failed.
So we devised a simple strategy to solve the issue.
Instead of switching the view in HDL Designer every time we wanted to switch between simulation and synthesis builds (or synthesis targeting a new FPGA) we realised we just needed to edit the tcl scripts generated by HDL Designer for use by the synthesis tool. In the HDL Designer environment we simply left the default view as that of the simulation model.
To facilitate doing this quickly and easily we came up with a file naming scheme. We started by splitting our VHDL files into entity files and architecture files. Entity files had names ending in the suffix _entity, while architecture files had different suffixes depending on their purpose. Simulation only architectures were labelled sim and the file names were suffixed _sim. Regular, platform independent VHDL architectures were labelled rtl and their file names were suffixed _rtl. For each new FPGA family we wanted to synthesise for we simply created a name [familyname], and attached that name to the generic name syn to get architecture labels syn_[familyname] and corresponding file name suffixes _syn_[familyname].
By managing our file naming convention it became a trivial matter to switch between different FPGA families, because we could do a quick search and replace (using any text editor, even as simple as Notepad) of affected files in the tcl script, replacing all instances of _sim with _syn_[familyname].
Interestingly this was one of the primary motivators for the Scineric tool – to enable us to manage that process even better, and avoid the possibility of human error during the process. Little did any of us know at the time how powerful the tool would eventually become and what other problems it would help us solve!
(A big thank you to Peter for contributing this section!)
What about VHDL configurations?
If you know VHDL well, you would have noticed that VHDL configurations can achieve the same outcome. Although we are probably no experts when it comes to VHDL configurations, there were some reasons why we did not use them to solve the problem. The main reason was lack of proper tool support for them back when we had to solve the problem. That said, I don’t know how many tools are out there today that does support configurations properly. Another reason is that this solution is simple to use, and it works very well in tools like HDL Author. We know that its probably not perfect, but it solves the problem in most cases.
How Scineric helps with this process
Scineric can help you manage this process. Firstly, it allows you to define all the architectures known to it, as shown below:
All Xilinx and Altera devices are there by default, and you can add any missing device that you are working on manually. This information is stored in the Scineric team settings file, ensuring that all members in a team use the same architecture list.
The firmware script preprocessor
The first place where you might actually notice this is when you import designs from firmware vendor scripts. For example, if you import a design from a Xilinx .prj script, it assists you in numerous. First, have a look at the screenshot below showing the .prj import wizard to give some context.
You might have noticed the following:
- Known architectures are highlighted for you.
- You can select your target device, and your script will automatically be updated to use files ending with the match string defined for your architecture.
- Once you’ve done the replacement you can verify the script and it will show you which files do not exist. This will normally happen when an entity somewhere in your design does not have an architecture for the selected device. Its very useful to realize this before starting your design’s implementation. If you do, synthesis tools (the ones that I’ve worked with at least) will treat the missing architecture as a black box and run through without problems. Translation will then search for the black box and fail because it can’t find it. Clearly this is a waste of time, and it happens quite frequently when you work on big designs where you are reusing other people’s blocks.
- You have the option to “Search for and add all available architectures”. When this is checked, it will actually search the directory where your entity file lies for all known architectures and add this to your design. This is needed (and very often overlooked) when you want to create a configuration package of your design. When someone books your design out of your configuration management system in 5 years time, they’d want all the architectures (including simulation architectures).
- You can perform case sensitive validation which is very useful when you are preparing builds for execution on Linux based machines where file names are treated as case sensitive.
When you create a design and you’ve selected that all architectures must be located and added, your design will look something like this:
Notice that all files for the architecture you’ve selected will be active, and all other architectures will be inactive.
How are you doing it?
I suspect most people out there who have run into these issues have their own solution which are probably one of the following:
- VHDL configurations
- Another custom type of naming scheme
- A solution based on generate statements
It will be interesting to hear what other solutions are out there. How are you doing it?