[SpiROSE] Testing systemverilog with SystemC, final round

Among the tasks I’ve been busy with these weeks, there is the making of integration tests for the FPGA’s SystemVerilog code.

SystemC is a very good asset to put in a CI environment. Basically, its advantages are:

  • It is quite light and free.
  • You only need tools to compile C++ code in your CI, instead of having modelsim or other full simulator.
  • You can customize the output to your needs, although formatting with SystemC with only 80 characters a line is quite awful.
  • You can use other library more instinctively.
  • You can even get VCD files back from the CI.
  • The compilation files are almost usual makefiles and testbenchs are C++ (sc_)main.

But eventually, we want to use this tool against the SystemVerilog code, so we need a bridge between them.

The situation

To put it clear, I will describe the situation for the driver_controller module. This module is the one generating control and data signal to the drivers. Amid these signals there are:

  • The GCLK and SCLK signals, both are clocks.
  • The LAT signal, which has strong timing requirements. It has different possible duration at the high state, each of these associated with a different command in the driver.
  • The SIN signal, which is the input of the driver itself

Before using the driver, it has to be configured and its the role of the driver_controller to do it too.

The inputs of the driver controller are first two clocks: clk_hse running at 66MHz and clk_lse running at 33MHz. This last one is generated thanks to the clk_hse clock in the clk_lse module, that we will need to include in the SystemC testbench too.

Then we have a framebuffer_sync signal, which should be generated each time we start a new frame. Finally there is a framebuffer_data signal of size 30bits, giving the SIN for each driver.

The tools

To achieve this, we will need to translate our SystemVerilog code into SystemC modules. It is time for the Verilator tool to enter the scene.

This tool was first included as a linter into our project, but revealed to be more useful than first thought. It is capable to translate SystemVerilog code into either special C++ to use with verilator, or SystemC modules which are a bit slower than the former but far easier to use.

Our little clock module becomes the following beautiful SC_MODULE:

SC_MODULE(Vclock_lse) {

    // PORTS
    // The application code writes and reads these signals to
    // propagate new values into/out from the Verilated model.
    sc_in<bool> clk_hse;
    sc_in<bool> nrst;
    sc_out<bool> clk_lse;

    // Internals; generally not touched by application code

    // Internals; generally not touched by application code

    // Internals; generally not touched by application code
    Vclock_lse__Syms* __VlSymsp; // Symbol table

    // ...


Verilator will generate its files in an obj_dir/ directory, which will be in the sim/ directory.

It will generate Vmodule_name.{h,cpp} file, containing the module itself and glue code to go with verilator library, Vmodule_name__Syms.{h,cpp} files making it available in the verilator library and some Vmodule_name__Trace.{h,cpp} files.

For the simulation, you only need to link against Vmodule_name.o and Vmodule_name__Syms.o. You can add the Vmodule_name__Trace.o file if you want to get the trace written into a VCD file, but you’ll need to have a deeper look into Verilated, the Verilator library, and especially the VerilatedVCD object to make it work.

The methodology


The first idea with testing module in SystemC is to put all the testing code in the sc_main function, where you are able to control the progress of the simulation :

sc_main(int argc, char**argv) {
    sc_time T(33, SC_NS);
    sc_clock clk(T);
    sc_signal<bool> nrst(“nrst”);
    // create the IN/OUT signal for the DUT
    Vmodule_name dut(“module_name”);
    // bind the IN/OUT signal of the DUT
    while(sc_time_stamp() < sc_time(10, SC_MS)) {
        // advance the simulation of T
        // do your tests


However it looks like software testing and it is usually a bad idea because you won’t be able to describe every interaction at the module scale you want. In our context within the driver_controller module, this drawback is visible and won’t allow us to do correct testing.


Instead, we write a Monitor SystemC module, which will interact with the DUT and run the tests as SystemC threads.

SC_MODULE(Monitor) {
    SC_CTOR(Monitor) {

    void run_test_1() {}
    void run_test_2() {}

    sc_in<bool> clk;
    sc_in<bool> nrst;
    // create sc_out for output signal to the DUT
    // create sc_in for input signal from the DUT

I will explain later how we benefit from this in the different tests.

The compilation


Now we have to compile the SystemC code into an executable simulation. We will want to recompile SystemVerilog into C++ each time there is a change and write makefile as small as possible for each testbench.


In the FPGA/ directory, we currently have the following structure:

  • src/ : containing the SystemVerilog code.
    • systemc/ : containing some SystemC modules, including the driver model we developed.
  • tb_src/ :
    • systemc/ : containing the SystemVerilog testbench we developed in SystemC.
  • sim/ : containing what’s needed to generate the simulation.
    • Makefile: will be the entrypoint to launch tests
    • base makefile from which will inherit the others
    • makefile for the module_name testbench


In Makefile, we will have a variable listing the different module we want to test. It will serve as generator to create FORCE-like tasks to generate and launch the simulation.


What we want for the is the following:

MODULE := driver_controller
DEPS := clock_lse

OBJS += $(ROOT)/main.o $(ROOT)/monitor.o driver.o driver_cmd.o


$(MODULE).simu: $(OBJS)
    $(LINK.o) $(OBJS) $(LOADLIBES) $(LIBS) $(TARGET_ARCH) -o $@

I’ve currently put the target to generate the simulation in this makefile but it could have been in the too. I just feel that it has more sense in the file.


MODULE is the device under test and DEPS is a list of SystemVerilog modules needed to build the testbench.


Then, the base_testbench will first define variables describing the environment:

export SYSTEMC_INCLUDE ?= /usr/include/
export SYSTEMC_LIBDIR ?= /usr/lib/


VERILATOR = verilator
VERILATOR_ROOT ?= /usr/share/verilator/include/
VERILATOR_FLAGS = --sc --trace
VERILATOR_BASE = verilated.o verilated_vcd_c.o verilated_vcd_sc.o

Then it will create objects list and dependency list:

    obj_dir/V$(MODULE).o obj_dir/V$(MODULE)__Syms.o \
    $(patsubst %,obj_dir/V%.o,$(DEPS)) $(patsubst %,obj_dir/V%__Syms.o,$(DEPS))
DEPSFILES = $(subst .o,.d,$(OBJS))

all: $(MODULE).simu

Then it defines the compilation options:

LIBS = -lsystemc
VPATH = ../src/ ../src/systemc ../tb_src/ ../tb_src/systemc ./obj_dir/ $(VERILATOR_ROOT) ../lib
CPPFLAGS = -I../src/systemc/ \
    -I./obj_dir/ \
    -I../lib/ \
    -I../tb_src/systemc/ \

And finally defines the compilation target to rebuild Verilator files or handle dependencies:

obj_dir/V%.cpp obj_dir/V%__Syms.cpp obj_dir/V%.h:

%.d: %.cpp

    rm -rf $(DEPSFILES) $(OBJS) $(MODULE).simu

-include $(DEPSFILES)



What has been done currently doesn’t fulfill our requirements yet. It seems that even if dependency files are correctly generated and included, the simulation won’t recompile if header files are modified. As we are prioritizing the development of the hardware at the moment, we’re not trying to debug it more. But this issue should be solved by the end of the year to make the development of the last testbench more enjoyable.


Except this task, I’ve been working on the improvement of the tests made by Adrien on the renderer, mainly by gathering code into sh functions so that tests and especially our use of Xvfb are more robust. I’ve also been working on the routing of the LED panel with Adrien, trying a slightly different version than Vincent’s one, but it seems that his one will be better. Finally I’ve written some tests for the column_mux module, a mux choosing the active columns on the LCD screen, but it doesn’t pass them.


I will continue to implement some tests as soon as the hardware is finished or if I get a window of time free.

[SpiROSE] no more EIM and we now have SystemC for testing

Hey, this week we read a lot of FPGA and SBC documentation. The goal was to be sure our project was feasible with the components we chose. We also validated many points on our design.

Choice of RGB versus EIM

It appears that we can’t use the “fast GPMC-like interface”, also known as the EIM on the board. Fortunately, as Tuetuopay explained it, the RGB is doing very well for what we ask it for.

The reason for not using the EIM are very simple : it doesn’t go on the MXM connector. Dot. So now we take a definitive stance on the choice of the communication bus from SBC to FPGA.

SystemC for testing

As written in our previous posts, we were trying to use Verilator as a compiler to SystemC. It is now an almost finished task. Each SystemVerilog file is built with a SystemC testbench and we are currently working on finishing a SystemC TLC5957 driver model and associated utils to produce test sequences and a way to test our driver and LED with C program directly, so as to validate everything. Tests will be done before the end of the week and we have a solid knowledge of the behaviour of the TLC5957.

Only one or two points are still beyond our understanding : the behaviour of XREFRESH also known as auto-refresh is part of them for instance, but we have good hopes to assert its behaviour with the previous library.

The Verilator makefile won’t produce correct dependency files too, but it will be fixed by replacing it by our own rules.

Next steps

There have still some issues with the SBC as it can’t do what we were expected at first.

Next week, we have to finish the tests quickly so as to integrate the FPGA parts into our project. After that we will fix the SBC issue by either finding a way to do what we want (openCL, CPU parts) or by replacing it by another CPU-only algorithm.

[SpiROSE] Continuous integration and the FPGA story

This week, we put a conscientious effort in making the project eventually start its journey in a more peaceful way. We were quite pressured by the choice of the FPGA and SBC as it was impeding the rest of the project and its existence. Now it has been fixed, we can really start to think about the next tasks: developing software and tests.

Even if it is still not perfect, we spent some time in configuring the continuous integration, designing the different steps for each piece of our software. As I spent most of the week doing code review (and FH work about happiness at work, which made me happy about ROSE), I highlighted some points where it failed, like some commits accepted by the tests although some files were missing, or incorrect style not failing the CI, or that the file organization in some subprojects weren’t practical for the integration of tests.

Two things are still missing. On the first hand, we have to save the artifacts so as to show demo easily, but we need more code so that it is useful and easy-to-follow manuals about how to use these artifact (flashing, running configuration, etc.) We expect to have this quickly for the LCD screen and renderer demos. On the other hand, we still don’t have very precise tests on our software, but things are to change quickly as we are writing simulation code in SystemC for the FPGA.

The idea, given by our teachers, is to use Verilator, a SystemVerilog-to-C++-library compiler, to put our FPGA controller into an environment with a simulated SBC input and simulated drivers so as to produce an output image. We will be able to cross-check the protocol used by the drivers in poker mode and check timing constraints. The SBC will generate sample image in the future and we will be able to check that it is correctly rendered by the FPGA.

To use Verilator, we have to:

  • compile each .sv file into a library (or only source/header files)
  • create a top file in SystemC which integrates each piece that we connect to the FPGA
  • monitor the input and output of the FPGA through SystemC stub modules

Eventually, we have to find a way to do the same on the real FPGA so as to have host integration tests.

We received the LED and the driver on Friday, so we didn’t try another experiment of the POV effect, but it will come quickly this week.

[Little Brosers] Finalize the Makefile and setup the CI

Hello there!


Guess what ? This week i’m writing my article from Madrid ! So let’s sum up what happened this week int the Little Brosers project, or at least, what I worked on.


This week was all about designing a compilation environment. First we started from the Nordic’s SDK examples. It gave us a functional Makefile compatible with the design we had in mind.

First idea was to put all make targets (devkit targets, c++ simulation target, custom Little Brosers PCB targets),  in one Makefile. However, it seemed simpler and cleaner to have a Makefile per platform. Thus we now have two Makefiles. One for building a .elf for the DevKit and another one for the C++ simulation.

Those two pick code from three folders:

  • hw : All code here is hardware dependent
  • core : All code here is hardware independent. It’s basically merging Merkle trees algorithms and cryptographic code. No main.c/.cpp should exist here.
  • sim : All code here is used to test the core folder C code. It allows us to get ride of BLE communication constraints to test algorithms.

The C++ simulation Makefile also comes with the linter related targets designed by me and Guillaume Lagrange.
Those are used by ourselves (programmers) before pushing our code and also by the CI to test the code style.

I worked a lot on the C++ Makefile to allow it manage automatically dependencies and put all the .o and .d files in a “build” sub folder. The objective was to never create any file in the src/ folder of the project. Indeed, we have to keep in mind that other Makefile will read files in the src/ folder.


Continuous Integration

This week was also about setting up the continuous integration using GitLab and Docker. This job has been shared between all group members. I took care of the CI artifacts and C/C++ compilation stages. Other group members took care of CI for python, linter and Android mobile app.

See you next week from home this time 🙂

Antony Lopez