Editor’s Note: This content is republished from the MicroZed Chronicles, with permission from the author and Hackster.io.
Last week we examined Xilinx simulation and how we could create test benches for behavioural and post-layout simulation along with creating the switching activity file that is used to provide more accurate power estimate.
The test bench we created last week was self-checking because it checked the output value against expected values supplied from a text file. This works well for simple examples like the one presented, however, for more complex examples we may want to use a different structure.
For complex algorithms, it is often a good idea to first create a model which defines the behaviour. This algorithm could be developed in a high-level language such as C or Python. It is important for some projects to get the customer to sign off and agree to the models before further RTL development.
We can use these models within the test bench to verify the HDL implementation on a cycle-by-cycle basis. This ensures the implemented algorithm works exactly as the model intends it.
One of the best ways we can use C or even Python models to verify our HDL behaviour is to use the Interface. This enables us to interface with the using C++ which allows us to create the test bench in C that can leverage the capabilities provided by a higher-level language. We can also add Python bindings to the C, enabling it to be accessed from an even higher level. Graeme Smecher has a great example of this on his GitHub.
Using the XSI interface is straight forward. Indeed a Vivado installation provides all of the software, libraries, and even examples we need to get up and going.
All of the necessary information is contained within UG900 if we want to set up a XSI simulation using C.
Getting started is straightforward following these steps:
<install path>\ Vivado\2020.1\lib\win64.o directory.
<install path>\Vivado\2020.1\tps\mingw\6.2.0\win64.o\nt\x86_64-w64-mingw32\lib
Copy the adder directory to an area outside of the Vivado project directory to a working directory. This leaves the examples preserved, as we will be making a few changes.
With the adder example copied, open up the provided BAT file and add in the install location of the Vivado installation.
You might also want to add the command pause at the end of the file. This stops the BAT file from closing once completed.
Initial BAT file
Modified BAT file
Running the BAT should produce the output below where the C test bench file is applied. The results can be seen in the output.
Output from the XSI Example
But, what is really on here if we wish to start from scratch and create our own XSI test bench?
Let’s look at the files in the example directory:
If we want to start from scratch, a good starting point is one of the example directories. All we need to do then is update the example for our test bench. This will include updating the project file to include the files we want to simulate. It is of course a good idea to change the name to one which accurately reflects the project being simulated.
We will need to update the batch or Linux scripts to consider the new name for the project. However, the main file we will want to change is the test bench file. This file makes several calls to the shared library to set up and execute the simulation.
I thought it would be a good idea to try simulating the example code I created last week so I modified the files to support this, including the test bench.
The test bench file is pretty simple to follow. The biggest confusion could be how the test bench represents the nine values of std logic. It does this using a char array.
const char* std_logic_literal[]={"U", "X", "0", "1", "Z", "W", "L", "H", "-"};
Therefore, to set a logic one, we use the value 3 and a logic zero has the value 2. The best way to work with these is to declare constants to make the code more readable.
If we have input or output vectors on the entity, we again declare a C array of the same width as the number of bits.
We are then able to set elements of the array to a std logic value and they will be reflected in the std_logic_vector input on the UUT.
Setting up the test bench uses the following flow:
Running this through using last week’s example to check the first value out from the average function we created gives the following output in the terminal window, which is correct.
To stimulate this design, I used the following commands:
By using these and other calls to the XSI shared library as defined with UG900, we can create test benches which use C++ to stimulate the unit under test and allows for easy comparison with algorithm models.
The example project is available here on my GitHub if you want to examine it further!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.