Showing results for 
Show  only  | Search instead for 
Did you mean: 

MicroZed Chronicles: Vivado Simulator Interface – Using C Test Benches on HDL

Xilinx Employee
Xilinx Employee
0 0 827

Editor’s Note: This content is republished from the MicroZed Chronicles, with permission from the author and


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:

  • Set the location if the Simulation Kernel shared Variable in the Windows path. This is available under installation

 <install path>\ Vivado\2020.1\lib\win64.o directory.

  • We also need to set up the MinGW libraries in the Windows path. This is also included under the Vivado installation

<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 fileInitial BAT file


Modified BAT fileModified 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 ExampleOutput 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:

  • Adder.prj  -- This defines the list of VHDL files in the project and their associated libraries
  • Addr.vhd – The actual Unit Under Test
  • Run.bat – Window BAT file to execute simulation
  • Set_env.csh & run.csh – Linux scripts to execute simulation
  • Testbench.cpp – The test bench which stimulates and checks the UUT
  • Xsi_loader.ccp/h – API for working with the XSI to enable loading, running, and driving the simulation
  • Xsi_shared_lib.h  - header file for the shared libraries

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:

  • Load to simulation project shared library
  • Load in the design library and simulation engine
  • Get the entity port ID’s
  • Stimulate the design and capture the outputs

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:

  • Xsi_Instance.get_port_number – To get the entity port number for a specific port.
  • Xsi_Instance.num_ports – Get the port information, name, width, direction, and size.
  • Xsi_Instance.put_value – Apply a value std_logic value to a selected port.
  • – Run the simulator for a specific period of time.
  • Xsi_Instance.display_port_values – Display the port values.

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!