Simulation setup

FABulous provides a simulation environment to validate that the generated FPGA fabric works correctly. The simulation loads a test bitstream, built from the user design, into the simulated FABulous fabric RTL and verifies that configuration, routing, and primitive behavior function as intended.

        flowchart TB
    subgraph design ["User Design Flow"]
        A[User Design Verilog/VHDL] --> B[Yosys Synthesis]
        B --> C[nextpnr Place & Route]
        C --> D[Bitstream Generation]
    end

    subgraph fabric ["Fabric Generation"]
        F[FABulous] --> G[Fabric RTL]
    end

    subgraph sim ["Simulation"]
        direction LR
        E[Test Bitstream] --> H["Testbench (iverilog / GHDL)"]
        H --> I{Pass / Fail}
    end

    subgraph emu ["Emulation"]
        direction LR
        J[Hardwired Bitstream] --> K[Fabric RTL + Bitstream]
        K --> L[Commercial FPGA Board]
    end

    D --> E
    D --> J
    G --> H
    G --> K
    

Important

The purpose of FABulous simulation is to verify the generated fabric implementation, not to validate user designs mapped onto it. If you need to test your own design logic, use a standard HDL testbench for your design before mapping it to the fabric.

The following diagram illustrates the simulation flow and how the different components interact.

        flowchart LR
    A[User Design Verilog/VHDL] --> B[Yosys Synthesis]
    B --> C[nextpnr Place & Route]
    C --> D[Bitstream Generation]
    D --> E[Test Bitstream]

    F[FABulous] --> G[Fabric RTL]

    E --> H[Testbench Simulation]
    G --> H
    H --> I{Pass / Fail}
    

For simple use cases, there is the run_simulation command in the FABulous shell. For more complex use cases it can be useful to create your own flow using the Taskfile.yml provided in each project’s Test/ directory.

Prerequisites

Please make sure to use recent versions of Yosys, nextpnr-generic (not the old FABulous nextpnr fork) and GHDL with mcode backend or use the OSS-CAD-Suite which provides nightly builds of the necessary dependencies.

Note

The OSS-CAD-Suite is providing GHDL only with LLVM backend, which increases the simulation speed for FABulous projects significantly. We recommend using the latest GHDL with mcode backend for the best simulation performance.

Taskfile

FABulous uses Taskfile (a modern, YAML-based task runner) to manage the simulation build flow. Each project is created with a Taskfile.yml in the Test/ directory that defines all the steps needed to synthesize, place and route, generate bitstreams, and run simulations.

The task command is installed automatically as part of the FABulous package.

Running a simulation

From the project’s Test/ directory, run the full pipeline (build + simulate + clean) with a single command.

cd demo/Test
task

To run individual steps, use the task name directly.

task build-test-design    # synthesize, place & route, generate bitstream
task run-simulation       # run the simulation only
task clean                # remove the build directory

To see all available tasks, run task --list.

Customizing variables

All key parameters are defined as variables at the top of Taskfile.yml and can be overridden via the command line without editing the file.

task run-simulation DESIGN=my_design WAVEFORM_TYPE=vcd

The available variables are:

Variable

Default

Description

DESIGN

sequential_16bit_en

Name of the user design (without extension)

TOP_WRAPPER

top_wrapper

Top-level wrapper module name

WAVEFORM_TYPE

fst

Waveform output format (fst or vcd)

BUILD_DIR

build

Build output directory

FAB_PROJ_ROOT

..

Path to the project root

GHDL_FLAGS

--std=08 -O2

GHDL compilation flags (VHDL only)

BITSTREAM_BIN

build/<DESIGN>.bin

Path to the .bin bitstream file

EXTRA_IVERILOG_FLAGS

(empty)

Extra flags passed to iverilog (Verilog only)

EXTRA_GHDL_FLAGS

(empty)

Extra flags passed to GHDL (VHDL only)

MAX_BITBYTES

16384

Maximum bitstream size in bytes

Variables can also be set via environment variables or the project’s .FABulous/.env file (loaded automatically via dotenv).

Using the CLI

The run_simulation CLI command is a thin wrapper that invokes the Taskfile. It takes the path to a .bin bitstream file generated by run_FABulous_bitstream, converts it to the .hex format expected by the testbench, and then runs the simulation via the Taskfile. The design name is inferred from the bitstream filename unless overridden with -d.

# Basic usage (converts design.bin to hex and simulates)
FABulous> run_simulation fst path/to/design.bin

# Specify a different design name
FABulous> run_simulation fst path/to/design.bin -d my_design

# Pass extra simulator flags
FABulous> run_simulation fst path/to/design.bin --extra-iverilog-flag="-DDEBUG"
FABulous> run_simulation fst path/to/design.bin --extra-ghdl-flag="--warn-error"

# Combine options
FABulous> run_simulation vcd path/to/design.bin -d my_design -if "-DDEBUG -DTRACE"

Flag

Short

Description

--design

-d

Override the design name (default: inferred from bitstream filename)

--extra-iverilog-flag

-if

Extra flags for iverilog (Verilog projects)

--extra-ghdl-flag

-gf

Extra flags for GHDL (VHDL projects)

Verilog vs. VHDL

Each project language gets its own Taskfile.yml tailored to the appropriate toolchain.

  • Verilog projects use Icarus Verilog (iverilog / vvp) for simulation.

  • VHDL projects use GHDL for simulation. GHDL requires files to be compiled in dependency order, so the VHDL Taskfile compiles packages (models_pack) first, then tile files, then fabric infrastructure, and finally the user design and testbench.

Note

The Taskfile.yml is a regular YAML file that you can freely edit to add custom steps or adjust the flow for your project. See the Taskfile documentation for the full reference.

Deprecated since version next: release

The legacy Makefile in Test/ is deprecated and will be removed in the next release. Please migrate to Taskfile.yml. The FABulous CLI (run_simulation) will prefer Taskfile.yml when present and fall back to make with a deprecation warning.

FABulous comes with 3 different simulation methods:

  1. Serial (Mode 0)

    Send configuration in through UART

  2. Parallel (Mode 1) - default in the testbench

    Use parallel configuration port

  3. Bitbang configuration port (To be supported in the testbench)

    We have produced a quick asynchronous serial configuration port interface that is ideal for microcontroller configuration. It uses the original CPU interface that we have in our TSMC chip. The idea of the protocol is as follows:

    Bitbang description

    We drive s_clk and s_data. On each rising edge of s_clock, we sample data and on the falling edge, we sample control.

    Both values get shifted in a separate register. If the control register sees the bit-pattern x”FAB0” it samples the data shift register into a hold register and issues a one-cycle strobe output (active 1).

    The next figure shows the enable generation (and input sampling) for generating the enable signals for

    • the control shift register and

    • the data shift register.

    An illustration of the signals used in the custom bitbang protocol as well as the decoding of these signals.