t27.aiРусский

Everything in one bench

You will learn

What an integration bench checks when every bus of the design is driven at once.

An integration bench drives every bus at once and asks the design to hold together: test_reset_all_modules, test_module_count, test_mac_uart_pipeline, test_spi_memory_pipeline, test_full_pipeline, seven tests. The recording lowers the integration testbench spec to Verilog: every bus of the design in one bench.

Try it

In the recording, find the five pipeline tests; then in the spec frame say which two buses the integration bench joins.

Open the interactive lesson →

t27c gen-verilog on integration_tb.t27 -- the integration bench
t27c gen-verilog on integration_tb.t27 -- the integration bench ↗

The integration testbench spec lowered to Verilog: every bus of the design in one bench.

specs/fpga/testbench/integration_tb.t27

// SPDX-License-Identifier: Apache-2.0
// t27/specs/fpga/testbench/integration_tb.t27
// Full FPGA Integration Testbench
// Tests top-level connectivity: MAC + UART + SPI + Memory + Bridge
// phi^2 + 1/phi^2 = 3 | TRINITY

module Integration_Testbench {
    const CLK_PERIOD : u32 = 20;
    const SIM_TIMEOUT : u32 = 20_000_000;
    const NUM_MODULES : u32 = 5;

    var clk : bool = false;
    var rst_n : bool = false;
    var mac_busy : bool = false;
    var uart_tx_ready : bool = false;
    var spi_done : bool = false;
    var mem_ready : bool = false;
    var bridge_busy : bool = false;
    var all_modules_idle : bool = false;
    var integration_passed : bool = false;

    var test_passed : u32 = 0;
    var test_failed : u32 = 0;

    fn tick() {
        clk = false;
        clk = true;
    }

    fn reset() {
        rst_n = false;
        tick();
        tick();
        rst_n = true;
        tick();
    }

    fn check_all_idle() -> bool {
        return !mac_busy && uart_tx_ready && spi_done && mem_ready && !bridge_busy;
    }

    test test_reset_all_modules {
        reset();
        all_modules_idle = check_all_idle();
        invariant all_modules_idle == true;
    }

    test test_module_count {
        invariant NUM_MODULES == 5;
    }

    test test_mac_uart_pipeline {
        reset();
        mac_busy = true;
        tick();
        tick();
        mac_busy = false;
        uart_tx_ready = true;
        tick();
        invariant uart_tx_ready == true;
    }

    test test_spi_memory_pipeline {
        reset();
        spi_done = false;
        tick();
        tick();
        spi_done = true;
        mem_ready = true;
        tick();
        invariant mem_ready == true;
    }

    test test_full_pipeline {
        reset();
        mac_busy = true;
        tick();
        mac_busy = false;
        uart_tx_ready = true;
        tick();
        spi_done = true;
        mem_ready = true;
        bridge_busy = true;
        tick();
        bridge_busy = false;
        all_modules_idle = check_all_idle();
        invariant all_modules_idle == true;
        integration_passed = true;
    }

    test test_stress_pipeline {
        reset();
        var i : u32 = 0;
        while i < 10 {
            mac_busy = true;
            tick();
            mac_busy = false;
            uart_tx_ready = true;
            tick();
            spi_done = true;
            mem_ready = true;
            bridge_busy = true;
            tick();
            bridge_busy = false;
            i = i + 1;
        }
        all_modules_idle = check_all_idle();
        invariant all_modules_idle == true;
    }

    invariant num_modules_positive : NUM_MODULES > 0;

    test test_tick_function {
        reset();
        var initial_clk : bool = clk;
        tick();
        invariant clk == !initial_clk;
    }

    bench bench_integration_throughput {
        reset();
        var i : u32 = 0;
        while i < 50 {
            mac_busy = true;
            tick();
            mac_busy = false;
            uart_tx_ready = true;
            tick();
            i = i + 1;
        }
    }
}

Open the lesson's spec in the player ↗

All lessons