Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
This gist contains the report for my Google Summer of Code 2020 Project

Automating Hardware And Bitstream Verification For PRGA With cocotb

The project aimed at automating the verification of custom FPGA defined using PRGA with the help of cocotb.


Link to Repositories:


PRGA (Princeton Reconfigurable Gate Array) is an open-source framework which provides a Python API for customizing FPGA architectures, for example (but is not limited to), customizing LUT sizes or number of LUTs per logic block; building DSP or BRAM blocks; optimizing routing channel composition and connectivity, etc.
cocotb (COroutine based COsimulation TestBench) is an environment for verifying VHDL and SystemVerilog RTL using Python. With cocotb, tests are used on the design itself, not the testbench.


Community Bonding

Once the selection for GSoC 2020 was confirmed, my mentor and I set up Slack(for communicating) and weekly meeting to discuss the progress. I started working on familiarising with the cocotb framework and experimented with a few designs. After getting know-how of writing test benches using cocotb, I started working on specific designs like LUTs(lookup tables), FLE6 and FFs(flip flops) which would be used in the primitive-module testing phase.

Primitive-Module Testing Phase

Primitive Modules are the building blocks of FPGA. Example- LUTs, FFs(flipflops), adders, muxes, etc.

PRGA employs a pass-based flow. Each pass may inspect and modify the core data structure, and generate files from the Jinja2 templates. Jinja2 is an open-source, template-based text rendering framework.

The primitive module tests check the logic implemented by them, including loading the configuration bits into the primitive through configuration ports, and testing if the configured primitives provide the intended functionality.

I worked on developing a pass whose function is to inspect the FPGA fabric and generate the appropriate cocotb tests for all primitive modules implemented in the design. Templates for primitive modules tests were developed alongside this.

FPGA Fabric Testing Phase

With the primitive-module testing in place, the next step was to create tests for logical modules like clusters, CLBs, subarray, etc.

Logical Modules use predefined configuration bits (transmitted as a bitstream) to choose one of the available configurations. The tests checked if the bitstream fragment successfully loaded correctly into the module and its submodules. This is followed by the verification of connections present in that particular configuration.

The pass developed in phase (b) was upgraded to operate on logical modules. The process required the development of a top-level test template, capable of generating tests for the Logical Modules.

Route Testing Phase

With Fabric Testing in place, the next step was to check the routing.

The first step was to create a graph representing the routing structure. Networkx, an open-source python framework for network analysis was inculcated for this purpose.

A route is selected along a predefined path. A corresponding bitstream is generated and written into the FPGA. This is followed by the verification of connections present along the route. A template was developed for generating tests to verify routing.


  • Creation of templates for unit-module Testing
  • Creation of a Pass for generating tests for each individual Module
  • A predefined route generator function


  • Using VPR to generate bitstream of a Target Verilog, loading it into the FPGA and testing the module.
  • Module Testing for packet chain configuration provided by PRGA


  • Context object which was used for descibing the FPGA Architecture
  • RTL and Translation passes must be executed along with the 'Tester' pass
    from prga import *
    from prga.core.context import Context
    from prga.passes.test import Tester
    ctx = Context.unpickle("ctx.pkl") # Unpickle the Context file

    flow = Flow(
            Tester('rtl','unit_tests') # 'rtl' is the name of the 
            # directory holding the Verilog source files 
            ), Scanchain.new_renderer())


PRGA repository contains a few examples of custom FPGAs. To check out unit testing, follow these commands

    cd prga/examples/fpga/tiny/k4_N2_8x8/
    make unit_test

This will create 2 directories 'rtl' and 'unit_tests' 'rtl' contains all the source Verilog files

    cbox_tile_clb_e0.v  clb.v               sbox_nw_w_ex_w.v    sw3.v
    cbox_tile_clb_w0.v  cluster.v           sbox_se_e_ex_es.v   sw48.v
    cbox_t_io_e_w0.v    flipflop.v          sbox_se_e_ex_e.v    sw4.v
    cbox_t_io_n_s0.v    include             sbox_se_W_ex_s.v    sw5.v
    cbox_t_io_s_n0.v    iob.v               sbox_se_W.v         sw6.v
    cbox_t_io_w_e0.v    lut4.v              sbox_se_Ww_ex_sw.v  sw7.v
    cfg_data_d16.v      sbox_ne_n_ex_ne.v   sbox_sw_N_ex_w.v    sw8.v
    cfg_data_d1.v       sbox_ne_n_ex_n.v    sbox_sw_Nn_ex_nw.v  sw9.v
    cfg_data_d2.v       sbox_ne_S_ex_e.v    sbox_sw_N.v         tile_clb.v
    cfg_data_d3.v       sbox_ne_Ss_ex_es.v  sbox_sw_s_ex_s.v    t_io_e.v
    cfg_data_d4.v       sbox_ne_S.v         sbox_sw_s_ex_sw.v   t_io_n.v
    cfg_data_d5.v       sbox_nw_Ee_ex_ne.v  subarray.v          t_io_s.v
    cfg_data_d6.v       sbox_nw_E_ex_n.v    sw10.v              t_io_w.v
    cfg_delim.v         sbox_nw_E.v         sw20.v              top.v
    cfg_e_reg.v         sbox_nw_w_ex_nw.v   sw2.v

'unit_tests' contains cocotb tests for individual modules

    test_cbox_tile_clb_e0  test_route_1           test_sbox_sw_s_ex_sw
    test_cbox_tile_clb_w0  test_sbox_ne_n_ex_n    test_subarray
    test_cbox_t_io_e_w0    test_sbox_ne_n_ex_ne   test_sw10
    test_cbox_t_io_n_s0    test_sbox_ne_S         test_sw2
    test_cbox_t_io_s_n0    test_sbox_ne_S_ex_e    test_sw20
    test_cbox_t_io_w_e0    test_sbox_ne_Ss_ex_es  test_sw3
    test_cfg_data_d1       test_sbox_nw_E         test_sw4
    test_cfg_data_d16      test_sbox_nw_Ee_ex_ne  test_sw48
    test_cfg_data_d2       test_sbox_nw_E_ex_n    test_sw5
    test_cfg_data_d3       test_sbox_nw_w_ex_nw   test_sw6
    test_cfg_data_d4       test_sbox_nw_w_ex_w    test_sw7
    test_cfg_data_d5       test_sbox_se_e_ex_e    test_sw8
    test_cfg_data_d6       test_sbox_se_e_ex_es   test_sw9
    test_cfg_delim         test_sbox_se_W         test_tile_clb
    test_cfg_e_reg         test_sbox_se_W_ex_s    test_t_io_e
    test_clb               test_sbox_se_Ww_ex_sw  test_t_io_n
    test_cluster           test_sbox_sw_N         test_t_io_s
    test_flipflop          test_sbox_sw_N_ex_w    test_t_io_w
    test_iob               test_sbox_sw_Nn_ex_nw  test_top
    test_lut4              test_sbox_sw_s_ex_s

To run the cocotb tests, cd into any directory and run make.

    cd unit_tests/test_cluster
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment